Sessions persist the conversation, not the filesystem. To snapshot and revert file changes the agent made, use file checkpointing.
resume and fork manually, and what to know about resuming sessions across hosts.
Choose an approach
How much session handling you need depends on your application’s shape. Session management comes into play when you send multiple prompts that should share context. Within a singlequery() call, the agent already takes as many turns as it needs, and permission prompts and AskUserQuestion are handled in-loop (they don’t end the call).
| What you’re building | What to use |
|---|---|
| One-shot task: single prompt, no follow-up | Nothing extra. One query() call handles it. |
| Multi-turn chat in one process | ClaudeSDKClient (Python) or continue: true (TypeScript). The SDK tracks the session for you with no ID handling. |
| Pick up where you left off after a process restart | continue_conversation=True (Python) / continue: true (TypeScript). Resumes the most recent session in the directory, no ID needed. |
| Resume a specific past session (not the most recent) | Capture the session ID and pass it to resume. |
| Try an alternative approach without losing the original | Fork the session. |
| Stateless task, don’t want anything written to disk (TypeScript only) | Set persistSession: false. The session exists only in memory for the duration of the call. Python always persists to disk. |
Continue, resume, and fork
Continue, resume, and fork are option fields you set onquery() (ClaudeAgentOptions in Python, Options in TypeScript).
Continue and resume both pick up an existing session and add to it. The difference is how they find that session:
- Continue finds the most recent session in the current directory. You don’t track anything. Works well when your app runs one conversation at a time.
- Resume takes a specific session ID. You track the ID. Required when you have multiple sessions (for example, one per user in a multi-user app) or want to return to one that isn’t the most recent.
Automatic session management
Both SDKs offer an interface that tracks session state for you across calls, so you don’t pass IDs around manually. Use these for multi-turn conversations within a single process.Python: ClaudeSDKClient
ClaudeSDKClient handles session IDs internally. Each call to client.query() automatically continues the same session. Call client.receive_response() to iterate over the messages for the current query. The client must be used as an async context manager.
This example runs two queries against the same client. The first asks the agent to analyze a module; the second asks it to refactor that module. Because both calls go through the same client instance, the second query has full context from the first without any explicit resume or session ID:
Python
ClaudeSDKClient vs the standalone query() function.
TypeScript: continue: true
The stable TypeScript SDK (the query() function used throughout these docs, sometimes called V1) doesn’t have a session-holding client object like Python’s ClaudeSDKClient. Instead, pass continue: true on each subsequent query() call and the SDK picks up the most recent session in the current directory. No ID tracking required.
This example makes two separate query() calls. The first creates a fresh session; the second sets continue: true, which tells the SDK to find and resume the most recent session on disk. The agent has full context from the first call:
TypeScript
There’s also a V2 preview of the TypeScript SDK that provides
createSession() with a send / stream pattern, closer to Python’s ClaudeSDKClient in feel. V2 is unstable and its APIs may change; the rest of this documentation uses the stable V1 query() function.Use session options with query()
Capture the session ID
Resume and fork require a session ID. Read it from thesession_id field on the result message (ResultMessage in Python, SDKResultMessage in TypeScript), which is present on every result regardless of success or error. In TypeScript the ID is also available earlier as a direct field on the init SystemMessage; in Python it’s nested inside SystemMessage.data.
Resume by ID
Pass a session ID toresume to return to that specific session. The agent picks up with full context from wherever the session left off. Common reasons to resume:
- Follow up on a completed task. The agent already analyzed something; now you want it to act on that analysis without re-reading files.
- Recover from a limit. The first run ended with
error_max_turnsorerror_max_budget_usd(see Handle the result); resume with a higher limit. - Restart your process. You captured the ID before shutdown and want to restore the conversation.
Fork to explore alternatives
Forking creates a new session that starts with a copy of the original’s history but diverges from that point. The fork gets its own session ID; the original’s ID and history stay unchanged. You end up with two independent sessions you can resume separately.Forking branches the conversation history, not the filesystem. If a forked agent edits files, those changes are real and visible to any session working in the same directory. To branch and revert file changes, use file checkpointing.
session_id and want to explore OAuth2 without losing the JWT-focused thread. The first block forks the session and captures the fork’s ID (forked_id); the second block resumes the original session_id to continue down the JWT path. You now have two session IDs pointing at two separate histories:
Resume across hosts
Session files are local to the machine that created them. To resume a session on a different host (CI workers, ephemeral containers, serverless), you have two options:- Move the session file. Persist
~/.claude/projects/<encoded-cwd>/<session-id>.jsonlfrom the first run and restore it to the same path on the new host before callingresume. Thecwdmust match. - Don’t rely on session resume. Capture the results you need (analysis output, decisions, file diffs) as application state and pass them into a fresh session’s prompt. This is often more robust than shipping transcript files around.
listSessions() and getSessionMessages() in TypeScript, list_sessions() and get_session_messages() in Python. Use them to build custom session pickers, cleanup logic, or transcript viewers.
Both SDKs also expose functions for looking up and mutating individual sessions: get_session_info(), rename_session(), and tag_session() in Python, and getSessionInfo(), renameSession(), and tagSession() in TypeScript. Use them to organize sessions by tag or give them human-readable titles.
Related resources
- How the agent loop works: Understand turns, messages, and context accumulation within a session
- File checkpointing: Track and revert file changes across sessions
- Python
ClaudeAgentOptions: Full session option reference for Python - TypeScript
Options: Full session option reference for TypeScript