Claude Code Context Management
Prerequisites: @smith-ctx/SKILL.md
Companion (Layer 3, read on demand): smith-ctx-claude/REFERENCE.md — hooks, linting hooks, permission modes, agent features + dispatch, /goal, model routing, tool search, plugin discovery, session analytics, moved trigger table + skill catalog. Read only when configuring those surfaces.
CRITICAL: Context Commands
Agent prompts for context status, then recommends action.
Thresholds and actions (graduated):
- 40-50%: Consider "Summarize from here" (targeted compression)
- 50%: Warning - recommend action (summarize or /clear)
- 60%: Critical - /clear mandatory (stop hook enforced)
"Summarize from here" preserves context before a checkpoint and compresses
everything after into a summary; pass focus instructions to steer it (access
via /rewind; full path in ACTION below).
"/clear" (full reset, save state first): stop hook enforced at 60% via
smith-mode-plan-claude using stop_hook_active (official best practice).
Check for uncommitted work before running /clear.
/compact — When to Avoid
/compact summarizes the entire conversation in-place; auto-compact fires
near the limit unless disabled (PreCompact hook runs first — persist state).
Prefer "Summarize from here" or /clear: /compact is lossy and non-deterministic
(you cannot pick the checkpoint; file:line refs / decisions can silently drop).
If it does run, pass focus instructions where allowed and re-verify file:line
refs + open decisions against the repo afterward.
Tool-Output Hygiene
Every byte a tool returns persists in context for the rest of the session and is itself re-summarized on compaction. Large spills (full file reads, verbose command output, subagent transcripts) are the main avoidable context cost.
Automated reminder (PostToolUse hook):
tool-output-hygiene.mjsfires when output >5K tokens- Reminds to summarize findings and use file:line refs
- Register in
~/.claude/settings.json(see REFERENCE.md)
Manual discipline:
- Process, don't dump: filter/aggregate noisy output in a sandbox
(context-mode
ctx_execute/ctx_batch_execute) so only the derived answer enters context. - Delegate noisy investigation (grep sweeps, log trawls) to a subagent; keep only its findings.
- Reference artifacts by
file:line/ path, not pasted content. - Read targeted ranges, not whole files, when a section suffices.
/clear - Full Context Reset
Before /clear:
- Update plan file with current progress (if active)
- Commit current work if the user has authorized commits, showing the detailed commit message for an explicit yes first (
@smith-guidanceExternal writes); otherwise list uncommitted files in the Reload block - Run
/smith-checkpoint(@smith-checkpoint/SKILL.md) - AFTER all tool calls complete, output the Reload block it printed, unchanged
Preserved: Project files, CLAUDE.md, plan files. Lost: conversation history.
After /clear:
- Plan auto-reloads with todo reconstruction ONLY if a flag file exists (from enforce-clear or on-plan-exit); state file alone = informational, not auto-resume
- Follow the memory-restore directive the SessionStart:clear hook injects; without one, restore the checkpoint the Reload block names from one backend
- Re-read relevant files as needed
- No memory saved? Recover intent from the JSONL transcript — see
smith-ctx-claude/REFERENCE.md"JSONL State Recall"
Commit-Early Pattern
- Do not batch commits to end of session — context resets lose uncommitted work
- When uncommitted changes accumulate, say so and offer a
#WIPcommit; commit only on the user's yes - Before destructive operations (rebase,
/clear), commit (message shown for an explicit yes) or stash current work
Context Hooks
Warning Hook (50%)
UserPromptSubmit hook context-warning.sh injects warnings at 50%+ context:
- 50-59%: "Warning — consider /compact or prepare for /clear"
- 60%+: "Critical — checkpoint work, then /clear"
Uses lib-context.sh for token-based percentage (DRY).
Stop Hook (60%)
Stop hook enforce-clear.sh blocks at 60% context. Uses real token counts from transcript JSONL (same data as Claude Code statusline). A single unified hook covers both plan-active and non-plan contexts:
- Real percentage: Blocks at 60% context (from transcript token usage, not byte count)
- Three branches: Plan+pending, plan+completed, no-plan (plan filepath shown first, Serena optional)
- Loop prevention: Uses
stop_hook_activefield (official best practice)
Config: Both hooks in smith-ctx-claude/scripts/.
When stop hook triggers:
- Mark completed tasks in plan (if plan active)
- Commit uncommitted work only if the user has authorized commits, showing the commit message for an explicit yes first (
@smith-guidanceExternal writes); otherwise list uncommitted files in the Reload block - Write the session's durable facts to a body file (format:
@smith-checkpoint) - Invoke /smith-checkpoint with the label, plan path and
body=«path»from the hook's invoke directive - smith-checkpoint outputs Reload block with actual memory names
Flag File and Injection Points
Flag-based auto-reload mechanism for plan and state restoration after /clear:
Injection points (all in smith-ctx-claude/scripts/):
on-session-clear.sh(SessionStart:clear) — Reliable plan injection post-/clearinject-plan.sh(UserPromptSubmit) — Flag-based reload or trigger wordenforce-clear.sh(Stop) — Creates flag at 60%, outputs reload directiveon-plan-exit.sh(PostToolUse:ExitPlanMode) — Creates flag for later/clear
Flag file location: ~/.claude/plans/.pending-reload-«session-hash»
Known upstream bugs (mitigated by preemptive flag creation; issue links in
references/SOURCES.md):
- Plan mode "clear context and auto-accept" may not fire PostToolUse:ExitPlanMode
- Plan mode "clear context" may not fire SessionStart:clear
System Reminders (Auto-Injected Context)
Claude Code auto-injects system-reminder blocks in response to events. They look like user messages but are NOT user input — don't treat them as acknowledgements or replies. Respond to the underlying event only when action is required.
Events: task-tools idle nudge, file-modification notice, skills-available list,
plan-mode transitions, background-task completion, date
change, auto-mode active, bg-isolation guard refusal. Full descriptions (with
the relevant skill cross-refs) in smith-ctx-claude/REFERENCE.md
"System-Reminder Event Taxonomy".
Active Plugin Side-Effects
Some plugins inject SessionStart hooks that alter behavior for the whole session. Account for them; do not mistake their output for a user instruction or an error.
- caveman — terse PROSE only; commits, PR/issue bodies, code, Slack drafts stay full prose (
@smith-slack); its SessionStart hook restates the detail. - ponytail — biases to the laziest working solution; build the full version when the user asks; its SessionStart hook restates the detail.
- context-mode — sandboxed analysis tools (
ctx_*). Subprocess/ctx_executewrites do NOT persist to the host FS — use Write/Edit for real file changes. The recurring "vX outdated → /ctx-upgrade" banner is noise, not a failure.
These are output/behavioral contracts, not memory; they persist until the user says "stop caveman" / "stop ponytail" / "normal mode".
AskUserQuestion — Body Prose Is Hidden
The AskUserQuestion UI surfaces only the question text and each option's label and description; surrounding message prose may be hidden. Put every decision-critical fact (trade-offs, recommendation, what each choice commits to) INSIDE the question and option fields, never only in the body. Recommendation goes as the first option labelled "… (Recommended)".
One scope decision per turn. Ask ONE scope/approach decision at a time; do not bundle several unrelated decisions into one AskUserQuestion call. A single multiSelect for ONE coherent choice (e.g. which sources to sweep) is fine; batching distinct decisions is not. (Implementation-phase confirmations that follow logically from an approved plan need no re-ask.)
External Writes — Preview, Then the User's Reply
Permissions and confirmation are separate: allow rules decide whether a
tool may run, and external-write-guard never reads or overrides them.
For every write it matches, the guard reads the transcript and lets the
call through only when every text field and target identifier (page,
issue, parent) was shown verbatim and the user replied after it, by a
typed message or an AskUserQuestion answer; notifications do not count.
Preview one smaller part per turn and wait for the reply to each; save
long text to a durable file the user can open in an editor and give its
absolute path on a line that says "preview"; a file changed after the
reply no longer counts. Pass gh bodies in single quotes, a quoted
heredoc (<<'EOF') or --body-file in a command of its own. Name the
target in the same message as content written to it. The guard does not
notice a repost: a yes covers one write, so posting the same payload
again needs a new preview and reply. Otherwise
the guard denies the call: show the missing part, wait for the reply,
and call again only on a yes. A subagent's
write is denied; return the draft to the main thread. A "fixed in «SHA»"
reply passes as mechanics only after the user typed /smith-ship or
/smith-review in this session, when the SHA
exists locally and GitHub reports every comment in that thread as written
by a bot. The guard raises a permission prompt only when it cannot check:
no readable transcript, a body from stdin, --input or shell expansion,
or a write with no text. A write the guard
does not match still needs its payload shown and a yes in chat first if
it publishes words; one that publishes none needs only the user's
instruction for that action, and a mechanic inside an approved
transaction needs neither (@smith-guidance).
Slash Command Invocation
When the user names a slash command (e.g. /insights, /commit, /foo), invoke it directly via the Skill tool. The user naming the command IS the confirmation it exists. A failed Skill call costs one round-trip; an exhaustive existence audit costs dozens of tool calls plus a confidently wrong conclusion.
Treat the user naming a slash command as sufficient grounds to try it — invoke Skill(skill="«name»") first rather than:
- Searching
~/.claude/plugins/, marketplace catalogs, or plugin cache to "prove" the command exists before invoking it - Grepping transcript JSONL files for prior invocations as existence proof
- Concluding a slash command "doesn't exist on this system" without trying
Skill(skill="«name»")first
If the Skill call fails with "skill not found": surface the error, ask the user to confirm the name or install the plugin. Do not escalate to filesystem search.
CLAUDE.md Persistence
Location: $WORKSPACE_ROOT/.claude/CLAUDE.md or $HOME/.claude/CLAUDE.md
Put in CLAUDE.md (always active): critical guardrails stated plainly with their reasons, reference to @AGENTS.md, project-specific preferences.
Put in skill files (context-triggered): detailed technical guidelines, platform-specific patterns.
Related
smith-ctx-claude/REFERENCE.md- Hooks, permission modes, agent features, model routing, moved trigger table + skill catalog (Layer-3 dumps)- @smith-ctx/SKILL.md - Universal context strategies
@smith-ctx-claude-mode-auto/SKILL.md- Auto-mode classifier denial recovery@smith-worktree/SKILL.md- EnterWorktree/ExitWorktree, bgIsolation guard
Before You Finish
Proactive context management:
- At 40-50%: Try "Summarize from here" first
- Esc+Esc -> select checkpoint -> Summarize
- Guide: "Focus on «task», «decisions», «file:line refs»"
- At 50%: Warn, prepare retention criteria
- At 60%: if the user has authorized commits, commit on a yes to the shown message (else list uncommitted files), update plan, save to Serena, "/clear"
- After /clear: Plan auto-reloads; check Serena memories; recall from JSONL if no memory saved
Throughout: keep tool-output spill out of context (sandbox-process, delegate, reference by path).
Agent RECOMMENDS - user executes the command.