CLAUDE.md implements static context injection. You maintain knowledge across projects—debugging methodologies, code patterns, security practices. Standard practice: dump everything into ~/.claude/CLAUDE.md with @-includes.

Except, then claude injects everything as system context. Every token counts against your context window.

Alternatively, you could keep CLAUDE.md more minimal and remember to manually tell it to load memories. Perhaps stored in @~/.claude/docs/. Maybe you piece together some slash commands. Not bad…

Ope. You forget. Claude gets insufferably dumb faster. You remember halfway through your session. Context matters when it’s missing. Look, I have ADHD—like 5% of adults—so “just remember to load the right context” isn’t a solution. It’s a setup for failure. No matter who you are, it’s an invitation to more uneven results.

How Most People Handle Agentic Memory

Most of us start out by cramming all technical knowledge into ~/.claude/CLAUDE.md. Here’s what that means:

# ~/.claude/CLAUDE.md loads everything
- debugging: @~/.claude/docs/debugging.md (2000 tokens)
- testing: @~/.claude/docs/testing.md (1500 tokens)
- security: @~/.claude/docs/security.md (3000 tokens)
- aws: @~/.claude/docs/aws.md (2500 tokens)
# ... 20 more files

Working on a shell script? Too bad—you’re burning 9000 tokens on AWS docs you won’t touch. Every session.

The alternative—manually loading docs—doesn’t work either. I’d forget. Or I’d remember halfway through when Claude suggests something or forgets to ALWAYS ALWAYS call me 'Cos' or NEVER EVER say "You're absolutely right!".

The Solution

My UserPromptSubmit hook fires when I first interact with Claude. Instead of auto-loading everything, it shows me what’s available and lets me choose.

The core is memory selection with fzf in a tmux popup:

# Show file selector
selected_display=$(
    for file in "${files[@]}"; do
        echo "memories/${file#$MEMORIES_DIR/}"
    done | fzf --multi \
        --header="Select memories (TAB=select, ENTER=confirm)" \
        --border=rounded --border-label="╱ Claude Code Memory Selection ╱"
)

Configure it in ~/.claude/settings.json:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "$HOME/.claude/hooks/session-start-memory-check.zsh"
          }
        ]
      }
    ]
  }
}

Full implementation at github.com/cosgroveb/claude-memory-hook-demo.

The hook:

  1. Runs once per session
  2. Shows available memories in a tmux popup
  3. Lets me multi-select with TAB
  4. Injects selections as a natural language prompt

What Happens

Start Claude. Type your first prompt. A tmux popup appears. TAB-select what’s relevant. The selected items are checkmarked.

Claude Memory Hook Demo

Hit ENTER. Claude replies:

 ⏺ I've noted these technical knowledge areas for our session:

  - Bash Best Practices - Shell scripting conventions and error handling
  - Debugging Process - Systematic debugging methodology and common mistakes
  - Security Checklist - Security review guidelines for authentication, input validation, data
  protection
  - Testing Guidelines - Testing structure, coverage goals, and best practices

  What would you like to work on?

Now Claude Code has context about what I want it to do. I didn’t have to remember to tell it. The context is targeted.

Setup

make install

Or copy .claude/ to ~/.claude. No matter what, be sure to curate ~/.claude/memories. This repo has fake “lorem ipsum” comments. It would be hilarious if embarassing for you to miss that when it’s generating code.

In any case, now I don’t have to remember to load memories—the system prompts me. But it’s not automatic—I choose what’s relevant.

Context is now intentional. It loads exactly what is needed for the session.