Session Chains

Create, resume, continue, and fork conversations

Sessions are persistent conversation contexts. Every claude -p call creates a session with a unique ID. You can resume it later with --resume, continue the most recent one with --continue, or disable persistence with --no-session-persistence. This is what makes multi-step workflows possible — a plan-review-execute chain, a staged migration, or a CI pipeline that picks up where a previous run left off.

Session lifecycle: create, resume, fork, expireCreateResumeForkExpireBranch

Create and Capture

The first step in any session workflow is capturing the session ID from the initial call. Pass --output-format json so you can extract the session_id field with jq.

Create & Capture a Session
$

The JSON response from that initial call contains everything you need. Here is the full payload:

create_sessionclaude -p --output-format json
1{
2 "type": "result",
3 "subtype": "success",
4 "is_error": false,
5 "duration_ms": 3071,
6 "num_turns": 1,
7 "result": "session test 1",A
8 "session_id": "d25a595e-22f0-4206-87d8-20cce15c6355",B
9 "total_cost_usd": 0.015954
10}
AStore this UUID to resume later
BCost for this turn only

—resume vs —continue

These two flags both resume a session, but they find it in very different ways. Choosing the wrong one is one of the most common mistakes in session-based workflows.

Session Resumption Flags

FlagBehaviorScope
—resume SESSION_IDResumes a specific session by UUIDWorks from any directory
—continueResumes the most recent sessionCurrent directory only
—resume (no args)Opens interactive session pickerInteractive mode only

For automation, always use --resume SESSION_ID. The --continue flag is convenient for interactive use, but in scripts it introduces ambiguity: another process could create a newer session in the same directory, and --continue would pick that one instead of yours.

Ephemeral Sessions

Add --no-session-persistence when you do not want the session saved to disk:

Terminal window
claude -p "Quick question" --no-session-persistence --output-format json

The response still includes a session_id field, but the session is not saved to disk. Attempting to --resume it later will fail. This is the right choice for:

  • CI/CD pipelines — do not pollute the session store with one-off runs
  • Batch processing — thousands of independent queries do not need persistence
  • Privacy — sensitive prompts are not stored on disk

The JSON response looks identical to a normal session. You cannot tell from the payload alone whether the session was persisted. This is by design — the calling code decides persistence, not the response format.

Session-Aware Workflows

The real power of sessions is chaining multiple calls into a single coherent workflow. The classic pattern is plan-review-execute: Claude plans in a restricted mode, a human reviews, and then Claude executes with full permissions in the same conversational context.

Terminal window
# Step 1: Plan
PLAN=$(claude -p "Plan a refactoring of auth.py" \
--permission-mode plan --output-format json)
SESSION=$(echo "$PLAN" | jq -r '.session_id')
# Step 2: Review
echo "$PLAN" | jq -r '.result'
# Step 3: Execute (same session, full context)
claude -p "yes, proceed" --resume "$SESSION" --permission-mode bypassPermissions

Step 3 resumes the exact session from Step 1. Claude has the full plan in context and does not need to re-analyze the codebase. The --permission-mode flag changes between steps, letting you enforce a review gate before granting write access.

Branching with —fork-session

The --fork-session flag creates a new session with a copy of the conversation history. The original session is left untouched:

Terminal window
claude -p "Try approach B instead" \
--resume "$SESSION" --fork-session --output-format json

This gives you a clean branch point. The forked session has its own UUID and its own future, while the original remains available for --resume. Use cases include:

  • A/B testing approaches — fork at the same decision point and compare results
  • Exploring alternatives — try a risky refactor without losing the main thread
Gotcha

—continue is directory-scoped. If you created a session in /project-a/ and run —continue from /project-b/, it will not find it. Use —resume SESSION_ID for cross-directory resumption.

Tip

Sessions share the 200K context window. Long sessions hit auto-compaction, which summarizes earlier turns to free space. Plan for this in long workflows — critical instructions should live in CLAUDE.md so they survive compaction.

Resume Payload

When you resume a session, the payload confirms continuity. Here is the response after asking “What was my previous message?” in a resumed session:

resume_sessionclaude -p --resume SESSION_ID --output-format json
1{
2 "type": "result",
3 "subtype": "success",
4 "is_error": false,
5 "duration_ms": 3523,
6 "num_turns": 1,
7 "result": "Your previous message was:\n\n> Say: session test 1",A
8 "session_id": "d25a595e-22f0-4206-87d8-20cce15c6355",B
9 "total_cost_usd": 0.01628525
10}
AClaude correctly recalled the previous turn
BSame session ID -- conversation continuity confirmed

The result field shows Claude recalling the exact content from the previous turn. The session_id matches the original, confirming this is the same conversation context — not a new session that happened to receive similar instructions.

Concurrent Sessions

Multiple claude -p calls can run in parallel in the same directory without conflicts. Each gets a unique session ID and independent context:

Terminal window
# Both run simultaneously, no locking
claude -p "Review auth module" --output-format json > review_auth.json &
claude -p "Review database module" --output-format json > review_db.json &
wait

There is no session locking mechanism. Parallel calls do not interfere with each other.

Which Session Does —continue Pick?

When multiple sessions exist in a directory, --continue picks the most recently created one. It does not pick the most recently modified or the one that ran longest.

--continue Resolution Rules

ScenarioResult
One session in directoryPicks that session
Multiple sessions in directoryPicks the most recently created
Sessions in parent and subfolderOnly sees sessions from current directory
No sessions in current directoryError: no session to continue

Sessions are stored in ~/.claude/projects/<encoded-dir-path>/, which is why --continue is directory-scoped. Use --resume SESSION_ID when you need to target a specific session regardless of directory.

Tip

For parallel workflows where you need to continue specific sessions later, capture the session_id from each JSON response and use —resume instead of —continue. This eliminates ambiguity about which session gets continued.