Most developers never need these patterns. But if you’re building CI integrations or managing concurrent Claude instances, these patterns prevent subtle session corruption bugs.
Your multi-step pipeline works in sequence but takes 20 minutes. You try to parallelize by forking the session — and discover that forked sessions share the initial context but not subsequent updates from sibling forks. Advanced session patterns require understanding what state transfers and what doesn’t.
This chapter covers advanced session patterns. For session basics (create, resume, continue), see Working with Sessions.
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:
claude -p "Try approach B instead" \ --resume "$SESSION" --fork-session --output-format jsonThis 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
- Chain forks — fork a fork to create tree-shaped exploration (each fork gets a fresh UUID)
Here is a real fork response showing the new session ID:
The original session (4b8101c6-...) still returns “BASE_MESSAGE” when resumed — forking is completely non-destructive.
Fork a session and test context isolation:
SID=$(claude -p “Remember: the code is 42” —output-format json | jq -r ‘.session_id’)
claude -p “What is the code?” —resume “$SID” —output-format json | jq ‘.result’
claude -p “Change the code to 99. What is the code now?” —resume “$SID” —output-format json | jq ‘.result’
Does the second resume see the change from the first resume, or does each fork get the original state?
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:
# Both run simultaneously, no lockingclaude -p "Review auth module" --output-format json > review_auth.json &claude -p "Review database module" --output-format json > review_db.json &waitThere 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
| Scenario | Result |
|---|---|
| One session in directory | Picks that session |
| Multiple sessions in directory | Picks the most recently created |
| Sessions in parent and subfolder | Only sees sessions from current directory |
| No sessions in current directory | Error: 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.
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.
Deterministic Session IDs
The --session-id flag assigns a specific UUID to a new session, enabling deterministic naming for CI correlation.
Use case: CI traceability. The same PR number always produces the same session ID, making logs searchable across pipeline runs:
# Assign a deterministic session ID for CI traceabilityPR_UUID=$(echo "pr-$PR_NUMBER" | uuidgen --sha1 --namespace @url)claude -p "Run linting" \ --session-id "$PR_UUID" \ --output-format jsonKey behaviors:
- The returned
session_idis exactly the UUID you provide — no prefix or suffix added - The value must be a valid UUID (8-4-4-4-12 hex format). Non-conforming strings silently produce empty output
- Reusing an already-active session ID produces:
Error: Session ID <uuid> is already in use --session-idis for assignment only — it does NOT resume. Use--resumefor that- Combining
--resumewith--session-idrequires--fork-session(fork-to-new-ID semantics)
# Fork a session to a new deterministic IDclaude -p "Continue with approach B" \ --resume "$OLD_SESSION" \ --session-id "$NEW_UUID" \ --fork-sessionInteractive mode sessions have NO file locking. Two terminal windows modifying the same session WILL corrupt it. We’ve lost entire conversation histories this way.
While concurrent claude -p sessions are safe (each gets a unique session ID and independent context), interactive sessions can corrupt .claude.json state files when multiple instances modify them simultaneously.
What corruption looks like: Parse errors, missing turns, or claude failing to resume. No recovery mechanism exists—delete the file and start fresh.
Safe patterns: Headless (-p) mode stores sessions in ~/.claude/projects/ with per-session isolation. For interactive sessions, avoid running multiple instances in the same project directory.
See how —resume + —fork-session powers a real discussion system with three branching strategies in Build an MR Reviewer, Part 4: Fork Sessions for Discussions.
Fork a session: capture a session ID, then resume it twice with different prompts. Verify that each fork gets the original context but doesn’t see the other fork’s changes. This is the pattern for parallel task execution — branch from a common plan, execute independently.