Manage session state, resumption, and forking
Long-running agentic work rarely fits in one sitting: engineers pause an investigation and pick it up the next day, or want to try two competing approaches from the same starting analysis. Claude Code and the Agent SDK persist conversations as resumable sessions and let you branch them with fork_session. Choosing correctly between resuming, forking, and starting fresh with a summary is what keeps an agent working from accurate state instead of stale tool results.
What a session is and how resumption works
A session is the persisted transcript of a conversation: the full message history plus every tool call and tool result the agent accumulated. Claude Code stores sessions locally so you can leave and return to the same line of work later. Each session has a stable identifier, and you continue a specific one with claude --resume <session-name>. Running --resume with no name opens an interactive picker of recent sessions, and --continue (-c) jumps straight back into the most recent session without naming it.
In the Agent SDK the same idea is exposed through query() options. You pass resume: '<session-id>' to reload a prior conversation, or continue (TypeScript) / continue_conversation (Python) to resume the latest one. When you resume, the entire prior context, including old tool results, is replayed into the model. That is powerful when the context is still accurate and expensive to rebuild, but it is exactly why resuming a session whose underlying files have since changed is risky.
# Continue a specific named investigation across work sessions
claude --resume payments-audit
# Or jump back into the most recent session
claude -c
fork_session: branching from a shared baseline
Sometimes you want to explore two divergent approaches, say a Jest migration versus a Vitest migration, without redoing the expensive codebase analysis that both share, and without letting the two explorations contaminate each other. That is what forking is for. Setting forkSession: true (TypeScript) / fork_session=True (Python) when you resume tells the SDK to spin up a new session that branches from the resumed point rather than appending to the original.
The shared analysis becomes a baseline. You fork it once per approach, and each fork gets its own independent session ID and its own future history. The original baseline session stays untouched, so you can always fork it again. This is the clean way to run parallel exploration branches and then compare their outputs side by side.
// Fork the same analyzed baseline into two independent branches
const jest = query({ prompt: 'Plan a Jest migration',
options: { resume: baselineId, forkSession: true } });
const vitest = query({ prompt: 'Plan a Vitest migration',
options: { resume: baselineId, forkSession: true } });
Forks are independent, not collaborative: nothing merges them automatically. You read both results and decide, or combine the winning pieces yourself. Contrast this with subagents (task 1.2), where a coordinator actively routes information between agents. A fork is just a parallel timeline of one conversation.
Resume vs. fork vs. fresh start
These three operations answer different questions. Resume means "keep going on this exact line of work" and mutates the original session in place. Fork means "start from here, but along a new independent path" and preserves the original. Starting fresh means "discard the accumulated transcript and begin a new session," usually seeded with a hand-written or agent-written summary of what mattered.
The decision hinges on how valid the prior context still is. If the prior context is mostly valid, resume (and, if you need alternatives, fork). If the prior tool results are stale, because files were rewritten, a migration ran, or a lot changed since, resuming drags outdated Read and Grep results back into the model, and the agent will reason about code that no longer exists. In that case a fresh session seeded with a structured summary is more reliable than resuming, because the summary carries forward only the durable conclusions, not the outdated raw tool output.
Think of it as a spectrum of staleness: fully valid context favors resume, a few changed files favors resume-plus-notification, and heavily changed state favors a clean restart with an injected summary.
Informing a resumed session about file changes
When you resume after some code changed, but the bulk of the prior analysis is still good, you do not have to choose between blindly trusting stale results and throwing everything away. The middle path is to explicitly tell the resumed agent which files changed and ask for targeted re-analysis of just those, rather than a full re-exploration.
The agent still holds the map of the codebase it built earlier, so a prompt like "Since we last worked, refund_service.py and order_repository.py were refactored to use the new async client. Re-read those two files and update your understanding; the rest of your analysis still holds" is far cheaper and more accurate than making it rediscover the whole module. This keeps the durable structural knowledge and refreshes only the parts that went stale.
Omitting this step is a common failure: the agent silently relies on cached reads and produces edits against code that has moved, so always name the changed files on resume.
Naming and organizing sessions for real work
Named sessions are what make resumption practical across days. claude --resume <session-name> only helps if you can identify the session you want, so give long-running investigations meaningful names (for example payments-audit or legacy-test-coverage) instead of relying on the anonymous most-recent session. --continue is convenient for a quick return but ambiguous once you have several parallel threads going.
A useful pattern for open-ended investigation is: build one well-named baseline session, resume it by name whenever you return, notify it of any file changes, and fork it whenever you want to try a divergent approach without disturbing the baseline. This gives you a stable trunk plus disposable branches.
Note the vocabulary difference between the CLI and the SDK. The CLI leans on --resume and --continue for interactive use; the SDK exposes resume, continue / continue_conversation, and forkSession / fork_session as programmatic options. They are the same underlying capability surfaced for two different workflows.
Anti-patterns to avoid
Why it fails: Resuming replays the old transcript, including stale Read and Grep output, so the agent reasons about and edits code that has since been rewritten, producing broken or irrelevant changes.
instead If a lot changed, start a fresh session seeded with a structured summary of the durable conclusions. If only a few files changed, resume but explicitly name those files and request targeted re-analysis.
Why it fails: Running both explorations in one session pollutes each with the other's reasoning and makes clean comparison impossible; manual transcript copying is error-prone and does not preserve real session state.
instead Fork the shared baseline with fork_session (once per approach). Each branch gets an independent session ID and history, leaving the baseline intact for further forks.
Why it fails: Forks are independent timelines with no automatic merge, and resume mutates the original session rather than copying it; flags such as --branch or --clone do not exist and are typical exam distractors alongside fakes like a --batch flag or a CLAUDE_HEADLESS variable.
instead Use fork_session to branch, resume to continue, and combine fork outputs yourself. Rely only on the real options: --resume, --continue, resume, continue/continue_conversation, and forkSession/fork_session.
Worked example: Resuming and forking a legacy-module investigation (Developer Productivity scenario)
You are building developer-productivity tooling on the Agent SDK, and an engineer is using it to understand a legacy payments module before migrating its tests.
Day 1, build the baseline. The engineer runs claude --resume payments-audit (creating and naming the session) and has Claude map the module: it uses Grep and Read to trace refund_service, order_repository, and the existing test coverage. This analysis is expensive, so the named session becomes the reusable baseline.
Day 2, resume with a change notification. Overnight, two files were refactored to an async client. Instead of starting over, the engineer resumes by name and tells the agent exactly what moved:
Since last session, refund_service.py and order_repository.py were
refactored to the new async client. Re-read just those two files and
update your model; the rest of your prior analysis is still valid.
The agent refreshes only the stale parts and keeps the rest of its map, a targeted re-analysis rather than a full re-exploration.
Evaluating two migration strategies via forking. Now the engineer wants to compare a Jest-based and a Vitest-based migration from the same analyzed baseline, without the two exploring branches interfering:
const jest = query({ prompt: 'Design a Jest migration for the payments tests',
options: { resume: baselineId, forkSession: true } });
const vitest = query({ prompt: 'Design a Vitest migration for the payments tests',
options: { resume: baselineId, forkSession: true } });
Each fork inherits the baseline analysis but evolves independently; the engineer reviews both proposals and picks one. The payments-audit baseline is untouched and can be forked again.
When to abandon resumption instead. Suppose that between sessions the whole module had been rewritten. Now the baseline's tool results describe code that no longer exists. Here resuming would inject misleading stale context, so the better move is a fresh session seeded with a structured summary of what the earlier analysis concluded, letting the durable findings carry forward while the outdated raw reads are dropped.
Exam tips
- ✓`claude --resume <session-name>` continues a specific named prior conversation; `--continue` (`-c`) resumes only the most recent session without naming it.
- ✓`forkSession: true` (TypeScript) / `fork_session=True` (Python) branches a resumed session into a NEW session ID; the original baseline stays intact and can be forked again.
- ✓Without forking, resuming appends to and mutates the original session in place; forks are independent and are never merged automatically.
- ✓Prior context mostly valid -> resume. Prior tool results stale (files rewritten) -> start fresh with a structured summary. A few files changed -> resume and name the changed files for targeted re-analysis.
- ✓Forking is the right way to compare divergent approaches (e.g., two testing or refactoring strategies) from one shared codebase analysis without cross-contamination.
- ✓Distractor watch: `--branch`, `--clone`, `--batch`, and a `CLAUDE_HEADLESS` variable are not real; the only session tools are --resume, --continue, resume, continue/continue_conversation, and forkSession/fork_session.
Official exam objectives for 1.7
- Named session resumption using --resume <session-name> to continue a specific prior conversation
- fork_session for creating independent branches from a shared analysis baseline to explore divergent approaches
- The importance of informing the agent about changes to previously analyzed files when resuming sessions after code modifications
- Why starting a new session with a structured summary is more reliable than resuming with stale tool results
- Using --resume with session names to continue named investigation sessions across work sessions
- Using fork_session to create parallel exploration branches (e.g., comparing two testing strategies or refactoring approaches from a shared codebase analysis)
- Choosing between session resumption (when prior context is mostly valid) and starting fresh with injected summaries (when prior tool results are stale)
- Informing a resumed session about specific file changes for targeted re-analysis rather than requiring full re-exploration
Flashcards from this lesson
Which CLI flag continues a specific named prior conversation, and which resumes the most recent one?
--resume <session-name> continues a specific named session; --continue (-c) resumes the most recent session.
What does fork_session (forkSession: true) do when you resume?
It branches the resumed conversation into a new independent session ID from that point, leaving the original baseline session untouched.
How do you evaluate two divergent approaches from the same expensive codebase analysis?
Fork the shared baseline session twice with fork_session, one branch per approach, then compare the independent outputs.
When should you start a fresh session with a structured summary instead of resuming?
When the prior tool results are stale (files were rewritten or a lot changed), so replaying old Read/Grep output would mislead the agent.
You resume a session but two files were refactored since. What must you do?
Explicitly tell the agent which files changed and request targeted re-analysis of just those, rather than a full re-exploration.
Does forking merge branches automatically, and does resume copy the session?
No. Forks are independent timelines with no automatic merge; resume mutates the original session rather than copying it.
Which session-management flags/options are fake exam distractors?
--branch, --clone, --batch, and a CLAUDE_HEADLESS variable are not real; the real ones are --resume, --continue, resume, continue/continue_conversation, and forkSession/fork_session.