Skip to content

Session resume and transcripts

This page reverse-engineers the local session and transcript paths that explain how Claude Code resumes conversations and persists state.

Source anchors

Semantic aliasString or symbolMeaning
LocalJsonlTranscriptSourcetranscriptSource:"local-jsonl"Default local transcript source classification.
ProjectStateRootprojectsConfig/project root helper under the Claude config directory.
SessionJsonlLookup${H}.jsonlJSONL transcript filename lookup helper.
CurrentSessionJsonlPath${v$()}.jsonlCurrent session JSONL transcript path.
SessionDiscoveryasync function loadConversationForResume(H,$)Latest/resume session discovery helper.
SessionRestoreasync function OG8(H,$,q)Session restore path.
ContinueFlag-c, --continueContinue most recent conversation.
ResumeFlag-r, --resume [value]Resume by ID or picker/search term.
ForkSessionFlag--fork-sessionResume into a new session ID.
NoSessionPersistenceFlag--no-session-persistenceDisables transcript writes and resume.
ResumeSessionAtGuard--resume-session-at requires --resumeHeadless resume validation.
RewindFilesResumeGuard--rewind-files requires --resumeRewind validation.

Bundle module in cli.renamed.js

Semantic aliasLoader lineRepresentative renamed exportsAtlas entry
TranscriptAgentMetadataStore623491writeRemoteAgentMetadata, writeAgentMetadata, readAgentMetadata, getMaterializedSessionFile, getTranscriptPathForSession, transcriptCursorEnd, trackSessionWrite, subscribeSessionTitleChanged, subscribeSessionAgentNameChanged, setInternalEventWriter, setInternalEventReader, worktreeStateSignal, sessionIdExistsBundle module map — session, transcript, agent metadata, and teammate IPC

Local transcript flow

flowchart TD
Start[Start mode] --> Choice{resume input?}
Choice -->|none| Fresh[Fresh session id]
Choice -->|--continue| Latest[Latest-session discovery]
Choice -->|--resume| Resolve[Discovery / picker / exact id]
Latest --> Restore[Session restore]
Resolve --> Restore
Fresh --> Loop[Runtime loop]
Restore --> Loop
Loop --> Jsonl[session-id.jsonl]
Jsonl --> Future[future --continue / --resume]

Session flags

SurfaceRuntime role
--continue / -cLoads the most recent conversation in the current directory.
--resume [value] / -rResumes by explicit ID or opens a search/picker path when ambiguous.
--from-prClassified as a resume-like start in Uzq.
--session-id <uuid>Uses a specific session ID, with validation and incompatibility checks in SDK/bridge paths.
--fork-sessionResumes into a new session ID rather than mutating the original.
--no-session-persistenceDisables transcript writes and therefore future resume.
--resume-session-at <message id>Truncates resumed context to an assistant message in print mode.
--rewind-files <user-message-id>Restores files to the state at a user message and exits.

Persistence interpretation

The local-jsonl and ${sessionId}.jsonl anchors show that local sessions are durable JSONL transcript files. SessionDiscovery and SessionRestore then form the semantic pair for session discovery and restore. The root action routes --continue, --resume, PR resume, remote/teleport branches, and picker fallback into these restoration surfaces before entering InteractiveSessionLoop or HeadlessRunner.

Edge cases

  • --resume-session-at and --rewind-files require --resume.
  • --rewind-files is a standalone operation and cannot be used with a prompt.
  • --no-session-persistence explicitly prevents saving and resuming.
  • Resuming may warn when permission mode differs from the saved session.

Restore internals

This section reconstructs how resume/continue state is loaded and transformed before re-entering the runtime loop. The core pair is SessionDiscovery (find/load a resumable session) and SessionRestore (apply restored state into the current runtime envelope).

Additional anchors

Semantic aliasString or symbolMeaning
LiveSessionFilterlistAllLiveSessionsUsed to filter out live non-interactive sessions during latest-session lookup.
TranscriptPathLoadBranchkI7($)Transcript-path based load branch.
SessionIdLoadBranchJJ$(H)Session-ID/string based load branch.
ResumeHookMessageRm("resume"Resume hook/system messages are appended to restored messages.
DeferredToolResumeStateturnInterruptionState, deferredToolUseResume returns interruption and deferred-tool metadata.
ForkSessionRestoreforkSessionForking changes which session/bridge/worktree fields are reused.
PermissionModeTransitiontransitionPermissionModeRestored permission mode is transitioned into current permission context.
InterruptedTurnResumeGateCLAUDE_CODE_RESUME_INTERRUPTED_TURNOptional interrupted-turn auto-resume gate.
TranscriptGoalRestorerestoreGoalFromTranscriptRestores goal-like state from transcript messages.
WorktreeSessionPersistenceactiveWorktreeSessionWorktree session state is persisted in current project config.
ExistingWorktreeEntryenterExistingWorktreeForSession, is not a registered worktreeExisting-worktree attach validates canonical git root and registered worktrees.

Session discovery: finding and normalizing a session

SessionDiscovery supports several inputs:

Input shapeBranchMeaning
H === undefinedlatest-session lookupLoads candidate sessions and filters out live non-interactive session IDs from listAllLiveSessions.
transcript path suppliedTranscriptPathLoadBranchLoads messages/session ID from an explicit transcript path.
string valueSessionIdLoadBranchResolves a session by ID/string.
object Hdirect object branchUses an already-loaded session-like object.

After loading, SessionDiscovery normalizes and enriches the result by resolving the session ID, mapping/validating the transcript path, loading messages and marking them as resume input, looking for deferred tool state, calling a resume hook, and returning a large state object.

Session discovery return state families

State familyReturned fields
Conversationmessages, turnInterruptionState, deferredToolUse, sessionId, fullPath
File/historyfileHistorySnapshots, attributionSnapshots, contentReplacements
Context collapsecontextCollapseCommits, contextCollapseSnapshot
Agent identityagentName, agentColor, agentSetting, customTitle, aiTitle, tag, mode
Permission/isolationpermissionMode, isolationLatch
Worktree/PRworktreeSession, prNumber, prUrl, prRepository
Bridge/remotebridgeSessionId, bridgeLastSeq

Resume is not simply replaying chat messages — it rehydrates a broad runtime envelope.

Session restore: applying restored state

flowchart TD
Loaded[SessionDiscovery loaded state] --> Fork{forkSession?}
Fork -->|no| Reuse[reuse session id / transcript dir / bridge/worktree]
Fork -->|yes| Strip[strip worktree and bridge session fields]
Reuse --> ResolveAgent[resolve agent definition]
Strip --> ResolveAgent
ResolveAgent --> Permission[transition restored permission mode]
Permission --> Model[restore main-loop model]
Model --> Attribution[restore attribution and standalone agent context]
Attribution --> Interrupted[optional interrupted-turn auto-resume]
Interrupted --> Goal[restoreGoalFromTranscript]
Goal --> InitialState[return restored initialState]

Key mechanics:

  • Session reuse versus fork. Non-fork restores set the active session ID and transcript directory; forked restores intentionally clear worktreeSession, bridgeSessionId, and bridgeLastSeq before applying state.
  • Content replacement handling. Forked sessions with contentReplacements apply those replacements separately.
  • Agent resolution. xyH(...) resolves restored agent settings against current main-thread and available agent definitions.
  • Permission transition. If a restored permission mode exists, transitionPermissionMode merges it into the current toolPermissionContext; failures are logged with [sessionRestore].
  • Model restore. Sa5(...) can restore the main-loop model; IG(...) applies it when present.
  • Bridge restore. Non-fork sessions with bridge metadata can re-enable the REPL bridge unless the current initial state is outbound-only.
  • Interrupted turn. With CLAUDE_CODE_RESUME_INTERRUPTED_TURN set and an interrupted_prompt turn-interruption kind, the runtime re-injects the interrupted user message as the initial message.
  • Goal restore. restoreGoalFromTranscript rebuilds goal-like state from transcript messages before returning.

Worktree session state

Worktree state is persisted separately from the JSONL transcript through activeWorktreeSession in current project config. The decoded worktree helper stores the original cwd, worktree path/name/branch, session ID, and cleanup flags, then later restores or clears that state through restoreWorktreeSession, keepWorktree, and cleanup helpers.

Attaching to an existing worktree is stricter than checking whether a path exists. enterExistingWorktreeForSession resolves the current canonical git root, rejects paths that are the main worktree or current cwd, runs git -C <root> worktree list --porcelain, and only persists enteredExisting: true after the real path matches a registered worktree. This keeps resume/worktree continuity tied to git’s registered worktree set.

Failure behavior

SessionDiscovery records session_resume feature markers. If no session is found it marks not_found and returns null. If loading fails it marks load_failed, reports the error, and rethrows.

Implementation takeaways

  1. Resume is a state rehydration pipeline, not just JSONL replay.
  2. Forking is explicit and strips bridge/worktree continuity to avoid mutating the original session lineage.
  3. Permission mode and model state are restored through transition helpers, not blindly copied.
  4. Remote/bridge continuity is preserved only when compatible with the current runtime initial state.

Created and maintained by Yingting Huang.