/clear Doesn't Reset Claude Code the Way You Think
I /clear between tasks the way other people crack their knuckles. Finish a thing, clear, start the next thing. I assumed it handed Claude a clean slate every time.
It does. That's the problem.
"Reset" means two different things inside Claude Code, and most setups only do one of them. You get the cost of the reset without the benefit — which is worse than not clearing at all.
What people think /clear does
The mental model is "new session." Wipe everything, reload everything, start fresh like I just launched the tool.
Half right. /clear is not a new process. It's the same running CLI. Everything at the process level survives:
- The working directory, environment variables, and loaded
settings.json - Your MCP server connections
- The CLI's uptime and PID
What /clear actually throws away is one thing: the conversation. The message history goes to zero tokens. Your files, your commits, your work — all untouched. Only the chat transcript is gone. (m.academy has a clean explainer of this if you want the official version.)
So far, fine. That's what I wanted.
The part nobody documents
After a reset, something is supposed to flow back in to replace the conversation you just deleted: your re-grounding context. In my setup that's a SessionStart hook that injects who I am, my live business metrics, which internal APIs exist, and my standing rules.
SessionStart hooks fire on four events, and each hook entry has a matcher that decides which ones it responds to:
| Event | Trigger |
|---|---|
startup |
Fresh claude launch |
resume |
claude --resume / --continue
|
clear |
You typed /clear
|
compact |
Context got auto-summarized |
My hook was registered on startup and resume. Not clear. Not compact.
So every /clear deleted my conversation and skipped the re-grounding. The agent was left with the static scaffolding (CLAUDE.md, a memory file) but none of the live, high-signal context. It looked equipped. It wasn't. It would re-derive systems it had used a hundred times as if it had never seen them — scrape a site instead of SSHing in, recite a metric from memory instead of pulling it live, ignore an internal tool and propose building a new one.
That's the "why does it act like it's never met me" feeling. After a /clear, it genuinely hadn't.
You didn't misconfigure this
I assumed I'd broken something in my own setup. Then I read the issue tracker.
-
anthropics/claude-code #34072: "SessionStart hooks configured in project
.claude/settings.jsonexecute correctly on startup... but never execute when triggered by/clear." Status: closed as won't-fix. -
#15174: even when you do register a
compactmatcher, "the hook stdout is NOT injected into Claude's context after compaction." Closed as duplicate. -
#26794: in the VSCode extension,
/clearreportssource: "startup"instead of"clear", so aclearmatcher never fires.
Read those together and the takeaway is blunt: on several builds, hooks are not a reliable way to re-ground a session after /clear or compaction. Depending on your version and whether you're in the CLI or VSCode, the hook either doesn't fire, fires under the wrong name, or fires but gets ignored.
The fix that actually holds
Two layers. The first is the obvious one; the second is the one that matters.
Layer 1 — widen the matcher. Collapse your separate hook blocks into one:
{ "matcher": "startup|resume|clear|compact",
"hooks": [{ "type": "command", "command": "your-context-loader", "timeout": 25 }] }
This is correct and harmless. On builds where clear/compact fire, it works. On the buggy builds, it does nothing — which is why you need:
Layer 2 — put the instruction in CLAUDE.md. This is the maintainer-suggested workaround from #34072, and it's the dependable path: CLAUDE.md reliably reloads on /clear. So the re-grounding instruction lives in CLAUDE.md itself rather than inside a hook.
I added one block to the top of my global CLAUDE.md:
At the start of any session, if you do NOT see a
# Brain Contextblock above, your context did not load. Before substantive work, read the cached snapshot at~/.claude/brain-context.cache.json.
The hook keeps that cache file fresh on every successful launch. The CLAUDE.md directive guarantees the agent uses it even when the hook silently no-ops. Hook for speed, CLAUDE.md for reliability.
How to check yours in 30 seconds
- Start a session, run
/clear. - Watch the reload. Does your re-grounding context (identity, project state, rules) come back?
- If you only see your static
CLAUDE.mdand no live context — your hook isn't firing onclear, and you're running blind every time you reset.
The reframe
/clear between tasks is still the right move. It beats letting one marathon thread run until auto-compaction, because compaction is lossy and silent (more on that here) while /clear plus proper re-grounding stays clean. Keep clearing. Just make the re-grounding that's supposed to follow the clear actually fire.
You weren't wrong that /clear resets the session. You were wrong about what "reset" includes. Close the gap, and the agent stops treating you like a stranger after every command.
Top comments (1)
The
startup|resume|clear|compactmatcher plus aCLAUDE.mdfallback is the right shape - but the part I'd underline hardest is your "hook for speed,CLAUDE.mdfor reliability" split. That's the real lesson: any re-grounding path that can silently no-op needs a second path that the agent can self-check.One addition: put a freshness stamp inside the cache and make the directive check it, not just its existence. Otherwise a hook that fails after the first successful write leaves a stale
brain-context.cache.jsonthat reads as healthy forever.Then the
CLAUDE.mdblock becomes: read the cache, comparegenerated_atto now, and say out loud if it's past TTL rather than proceeding on stale metrics. Silent staleness is the same failure class as the silent hook - you just moved it downstream.Same reasoning applies to anything the agent re-derives from a snapshot: MCP tool lists, API surfaces, internal endpoints. A stale inventory is how you get "let's build a new tool for this" for something that already exists.
Have you hit the stale-cache case yet, or has the hook been failing loudly enough to catch?