You’re 45 minutes into a Claude Code session. Earlier you decided “we’re not using GraphQL, stick with REST.” Suddenly Claude proposes a GraphQL resolver. Or it re-reads CLAUDE.md and package.json for the fourth time as if it’s never seen them. Or its plan now contradicts the plan it agreed to at minute 10.
The conversation got long enough that auto-summarization kicked in — your earlier context was compressed, and the specific constraints (no GraphQL, use vitest, edit in apps/web/) dropped out of the summary. The agent is now working from a lossy memory of what you said. The fix: re-anchor with explicit state, or — usually faster — start a fresh session with a tight handoff.
Common causes
Ordered by hit rate, highest first.
1. Conversation hit the context limit; auto-summarization compressed earlier turns
Once context fills, older turns get summarized. Summaries preserve the gist but lose specifics — “discussed approach” instead of “agreed no GraphQL, use vitest, no inline styles.” The agent then makes decisions inconsistent with what got summarized away.
How to spot it: Watch for “compacting context” / “summarizing earlier conversation” indicators. After they appear, expect lossy memory.
2. Long tool-call traces ate context faster than expected
Every Read, Grep, Bash adds to context. Five `Read’s of large files can be 20K tokens. The auto-summary triggers earlier than the conversation length suggests.
How to spot it: Session feels short but tool calls are dense. Check the visible context-usage indicator; high % comes from tools, not your messages.
3. The summary kept the high-level goal but lost the specific constraints
Auto-summary preserves “user wants to add a billing feature” but drops “user said: do NOT use GraphQL, ONLY edit apps/web/, tests in vitest.” Now the agent proceeds with the goal but free of the specific guardrails.
How to spot it: Output is on-task but violates constraints you set earlier. Constraints were what got dropped, not the task.
4. CLAUDE.md is too vague to substitute for in-session context
When summarization happens, Claude falls back on persistent context (CLAUDE.md). If CLAUDE.md doesn’t capture the constraint, it’s gone. CLAUDE.md gaps become summarization gaps.
How to spot it: The dropped constraint was a per-session decision (not durable). Future-proof it by promoting to CLAUDE.md.
5. Tool errors ate context without producing useful info
A Bash command failed 5 times in a row; each error trace went to context. Claude can’t think because half its window is identical permission-denied messages.
How to spot it: Many repeated tool errors in the session. Each adds noise but no signal.
6. Plan mode produced a long plan that filled context before code started
A 100-line plan + your modifications + tool reads to validate the plan = context already half-full before any real work. The first code generation triggers summarization, dropping the plan.
How to spot it: Session opened with extensive plan work; bug starts when code generation begins.
Shortest path to fix
Ordered by ROI. Step 1 is the fast restart; steps 2-3 are the durable hardening.
Step 1: Stop, snapshot, restart
When the session has clearly lost the thread, don’t try to recover — start fresh with a tight handoff:
- Write a 5-line “where we are” block:
## Status (2026-05-22 15:30)
Task: Add billing feature to apps/web/
Decisions:
- No GraphQL — REST only
- Tests in vitest, alongside source
- Follow `apps/web/src/features/auth/` for structure
Progress:
- Done: created `apps/web/src/features/billing/index.ts`, `types.ts`
- Next: implement `billing.service.ts`
Blockers: none
- Open a new session.
- Paste the status block as the first message. Add “continue from here.”
A fresh session has full context for the snapshot — no fading memory.
Step 2: Promote per-session decisions to CLAUDE.md
Every constraint that got dropped is a CLAUDE.md gap. After the session, update:
## Architectural decisions
- API style: REST only (not GraphQL — past attempt was abandoned 2025-Q4)
- Test framework: vitest only (not jest — see `apps/web/AGENTS.md`)
- Working directory for new web features: `apps/web/src/features/`
Next session reads this on startup; the constraint survives summarization.
Step 3: Snapshot progress every 30 min into a file
For long tasks, write progress to disk so it survives context resets:
# At session start, claude creates this file
echo "## Progress log" > .agent-progress.md
echo "Started: $(date -Iminutes)" >> .agent-progress.md
Prompt:
Every time you complete a meaningful step, append to `.agent-progress.md`:
- Timestamp
- What was done
- Files touched
- What's next
If we lose context, this file is the authoritative status.
Step 4: Minimize context-eating tool calls
Reduce noise that triggers earlier summarization:
- Prefer `Grep` over `Read` for finding things — much smaller output
- When `Read`-ing, use line ranges, not whole files
- Don't `Read` the same file twice; remember its content
- Cache long outputs by writing to `/tmp/<name>.txt` and referring to them
- If a `Bash` command keeps failing, stop and ask — don't retry 5x
Step 5: Use sub-agents for orthogonal sub-tasks
Long tasks with multiple concerns benefit from delegating to sub-agents (Task tool / sub-conversations). Each sub-agent has its own context window:
For the database migration step, spawn a sub-agent with just that task.
Return: the migration file path and applied migration name.
Main session doesn't see the sub-agent's tool calls; it sees only the return value.
Step 6: Recognize when summarization is imminent
Claude Code shows context usage. When it crosses ~60%, expect summarization soon. Before that:
- Save any in-flight decisions to CLAUDE.md or
.agent-progress.md - Wrap up the current sub-task
- Plan a restart at a clean boundary, not mid-task
Restarting at 60% is cheaper than recovering from a broken 95%.
Prevention
- Treat per-session decisions as documentation gaps; promote to CLAUDE.md so they survive
- Keep a
.agent-progress.mdfor tasks longer than 20 minutes; it’s the fallback when context resets - Restart sessions at clean boundaries (after a step completes) instead of trying to push through past summarization
- Minimize tool-call noise — Grep > Read, line ranges > full files, no re-reading
- Delegate orthogonal sub-tasks to sub-agents so each has its own context
- Treat ~60% context usage as a wrap-up signal; ~80% as a “save and restart” trigger