Never lose your context again. A complete end-to-end guide to Claude Code session management — what sessions are, why they matter, every command, and real-world workflows.
May 2026 ~15 min read Claude Code · CLI
In this tutorial
- What is a Claude Code session?
- Why session persistence matters
- The
--continueflag in depth - The
--resumeflag in depth - Side-by-side comparison
- All session commands & flags
- How sessions are stored
- Naming sessions with
--name - Forking sessions
- Context management with
/compact - Automation & scripting
- Real-world workflows
- Troubleshooting
- Pro tips & best practices
01 · Foundations
What is a Claude Code session?
A session is the complete conversation history that Claude Code accumulates while working on your code. It is not just the text you typed — it is everything:
- Every prompt you sent
- Every tool call Claude made (file reads, edits, bash commands)
- Every tool result returned
- Every response Claude produced
The SDK writes this record to disk automatically as a .jsonl file. Each line is an event — an append-only stream of everything that happened. Because it is persisted to disk, you can close your terminal, shut down your laptop, come back tomorrow, and load the entire history back in as if you never left.
ℹ
Important distinction: Sessions persist the conversation, not the filesystem. If Claude edited a file during a session, that file change is already on disk — resuming the session gives Claude memory of having made that change, but does not undo or redo it. For snapshot-and-revert of file changes, use file checkpointing.
When you resume a session, Claude has full context from before: files it already read, analysis it already performed, decisions it already made. You can ask a follow-up question, recover from an interruption, or branch off to try a different approach — all without re-explaining your codebase from scratch.
02 · Motivation
Why session persistence matters
Without session management, every time you invoke claude you start with a blank slate. Claude has no idea what you worked on yesterday. You re-explain the architecture, re-describe the bug, re-establish the constraints. This is not just annoying — it is costly in time and tokens.
Without sessions
- Re-explain architecture every morning
- Re-describe the bug context each time
- Lose decisions made mid-refactor
- Start fresh after a terminal crash
- Cannot hand off work to a teammate
- No audit trail of what Claude changed
With sessions
- Step away for lunch, continue seamlessly
- Recover from IDE/terminal crashes
- Multi-day features stay in context
- Juggle multiple tasks with separate threads
- Audit every tool call that was made
- Branch off to try alternative approaches
03 · The first flag
The --continue flag in depth
What it does
--continue (short form: -c) automatically finds the most recent session for the current working directory and resumes it. You do not need to know any session ID. Zero configuration required.
bash
# Resume the last session in this directory claude --continue # Short form claude -c # Resume AND immediately send a prompt (no interactive mode needed) claude -c "check if the tests pass now" # Resume in non-interactive / script mode claude -c -p "Check for type errors"
When to use --continue
1
You stepped away mid-task
You were refactoring an auth module, went to lunch, came back. Just run claude -c and ask “where were we?” — Claude will summarize the last few actions and pick up exactly where it stopped.
2
Your terminal was killed
Session state is written to disk on every event, not on exit. A crash loses nothing. Run claude -c to restore the full conversation.
3
Daily continuation on a single project
If you work on one project at a time and want to just keep going each morning, --continue is the zero-friction way to do it. No IDs, no lists — just continuity.
⚠
Non-interactive mode caveat: When using --continue with -p in scripts, it may sometimes create a new session instead of resuming. For reliable automation with a specific thread, use --resume with an explicit session ID or name instead.
04 · The second flag
The --resume flag in depth
What it does
--resume (short form: -r) resumes a specific session. You either pass a session ID, a session name, or nothing (to get an interactive picker of all recent sessions).
bash
# Open interactive picker — browse all recent sessions claude --resume # Resume a session by its ID claude --resume abc123def456 # Short form with ID claude -r abc123def456 # Resume a named session claude --resume "feature-auth-system" # Resume a named session + immediately send a prompt claude -r "payment-integration" "Finalize the Stripe webhook handler" # Resume a specific model version alongside claude --resume abc123def456 --model opus
The interactive picker
Running claude --resume with no arguments opens a rich interactive list. The picker shows session summaries, message counts, git branch names, and timestamps. You can:
- Press
Ato toggle between current directory and all projects - Press
Bto filter by your current git branch - Search by session name
When to use --resume
1
Multiple concurrent tasks
You have a “bugfix-payment” session and a “feature-new-dashboard” session running in parallel. --continue only gets you the most recent one. --resume lets you switch between them precisely.
2
Returning to a session that is not the most recent
You started a multi-week feature branch. You have done other sessions since. --resume "feature-user-auth" takes you straight back to that thread without hunting through history.
3
Cross-directory session access
By passing an explicit session ID, you can resume a session originally created in a different project directory. This is called “session archaeology” — recovering valuable older conversations.
4
Reliable automation & CI/CD
Scripts that capture a session ID can pass it back to --resume on subsequent runs for guaranteed continuity, unlike --continue which may create a new session in non-interactive mode.
Using /resume inside a running session
You do not have to exit Claude Code to switch sessions. Type /resume during any conversation and the same interactive picker appears. Perfect when you are bouncing between tasks and realize you need context from a different thread.
05 · Side by side
–continue vs –resume: the definitive comparison
–continue / -c
Zero-config continuation
Finds the most recent session in the current directory automatically.
- No session ID required
- Best for single-task workflows
- Ideal for daily resumption
- Minimal cognitive overhead
- Caution in non-interactive scripts
–resume / -r
Precise session targeting
Loads any session by ID, name, or interactive picker.
- Requires ID or name
- Required for multi-session apps
- Works across directories
- Reliable in automation
- Full session archaeology
| Aspect | –continue | –resume |
|---|---|---|
| –continue / -r | Most recent in CWD | Any, by ID or name |
| ID tracking needed? | No | Yes (or use picker) |
| Interactive picker? | No | Yes (claude –resume with no args) |
| Works cross-directory? | No | Yes |
| Safe in scripts? | Sometimes unreliable | Reliable with explicit ID |
| Multi-user apps? | Not suitable | Required |
06 · Reference
All session commands & flags
| Command / Flag | Short | What it does | Type |
|---|---|---|---|
| –continue | -c | Resume most recent session in current directory | CLI flag |
| –resume [id|name] | -r | Resume a specific session or open the interactive picker | CLI flag |
| –name <name> | -n | Assign a human-readable name when starting a new session | CLI flag |
| –list | — | List all sessions with IDs, names, and timestamps | CLI flag |
| –no-session-persistence | — | Disable session saving for a one-shot query | CLI flag |
| –output-format json | — | Output includes session_id field for capturing IDs in scripts | CLI flag |
| /resume | — | Open the session picker from inside a running session | REPL cmd |
| /compact | — | Summarize conversation history to free context window | REPL cmd |
| /rename <name> | — | Give the current session a human-readable name | REPL cmd |
| /status | — | Show current model, context usage, and session info | REPL cmd |
| continue: true | — | SDK option (TypeScript/Python) — continue most recent session | SDK option |
| resume: sessionId | — | SDK option — resume a specific session by ID | SDK option |
| fork: sessionId | — | SDK option — create a new session branched from an existing one | SDK option |
07 · Under the hood
How sessions are stored on disk
Every session is stored locally as a .jsonl file (JSON Lines — one event per line). The file lives inside ~/.claude/projects/, in a subdirectory keyed by a hash of the project’s absolute path. This keeps sessions from different projects completely isolated from one another.
~/.claude/ ├── projects/ │ ├── -Users-you-project-alpha/← hash of /Users/you/project-alpha │ │ ├── a1b2c3d4-e5f6-7890-abcd-ef1234567890.jsonl │ │ ├── b2c3d4e5-f6a7-8901-bcde-f12345678901.jsonl │ │ └── settings.json │ └── -Users-you-project-beta/← hash of /Users/you/project-beta │ └── c3d4e5f6-a7b8-9012-cdef-123456789012.jsonl ├── history.jsonl← global session index └── CLAUDE.md← global memory file
The encoded directory name is the project path with every non-alphanumeric character replaced by a dash. So /Users/me/proj becomes -Users-me-proj. This is why resuming from the wrong directory fails — Claude Code looks in the wrong subdirectory.
What each session file contains
Each .jsonl file is an append-only stream of events. A typical entry looks like:
jsonl
{
"sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"startTime": "2026-05-08T10:00:00Z",
"lastActive": "2026-05-08T11:27:00Z",
"messages": [...],
"fileContext": {
"read": ["src/auth.ts", "src/middleware.ts"],
"modified": ["src/auth.ts"],
"created": ["tests/auth.test.ts"]
},
"permissions": {
"approvedTools": ["Bash(git:*)", "Edit"]
}
}
✦
Sessions do not expire. You can resume any saved session regardless of when it was created. The picker shows them sorted by last activity, with the ability to search by name. The global history is in ~/.claude/history.jsonl — each entry includes a sessionId and the project path it came from.
08 · Organization
Naming sessions with –name
The --name flag (short: -n), introduced in Claude Code v2.1.76, lets you assign a human-readable name at session start. A good name transforms “abc123def” into “feature-auth-system” — instantly scannable in the picker.
bash
# Start a new named session claude -n "feature-user-auth" # Long form claude --name "bugfix-stripe-webhook" # Good naming patterns ✓ claude -n "feature-user-auth" # feature work claude -n "bugfix-stripe-webhook" # bug fix claude -n "refactor-api-routes" # refactoring claude -n "docs-api-reference" # documentation claude -n "review-pr-142" # PR review # Bad names to avoid ✗ claude -n "work" # too vague claude -n "2026-05-08" # date alone says nothing claude -n "misc" # meaningless # Rename an existing session from inside it > /rename payment-refactor-v2 # Resume later by name claude --resume "feature-user-auth"
✦
The single most impactful habit you can build: name sessions immediately with -n when you start them. “payment-integration” is findable in three months. “explain this function” is not.
09 · Branching
Forking sessions
Sometimes you want to try a different approach without losing the thread you are on. The fork operation creates a new session that starts with a copy of the original’s history — but the original stays completely unchanged. You end up with two independent sessions you can resume separately.
Session A
original thread
→
fork(session_A_id)
→
Session B
new forked thread
Both sessions share the same history up to the fork point, then diverge independently.
typescript (SDK)
// You analyzed an auth module in session_id.
// Fork to explore OAuth2 without losing the JWT thread.
const forkResult = await query({
prompt: "Explore an OAuth2 implementation instead",
options: { fork: session_id }
});
const forked_id = forkResult.session_id;
// Now you have two threads:
// session_id → JWT-focused original
// forked_id → OAuth2 exploration
// Resume the original at any time:
await query({
prompt: "Continue down the JWT path",
options: { resume: session_id }
});
⚠
Forking branches conversation history, not the filesystem. If a forked agent edits files, those changes are real and affect the same working directory. To branch and revert file changes together, pair forking with file checkpointing.
10 · Context management
Managing context with /compact
Long sessions fill up the context window. Claude Code has a 1 million token context window, but long refactors, extensive trial-and-error, and days of continuous work can push you toward the limit. The /compact command summarizes the conversation history into a concise briefing and starts a fresh context window with that summary preloaded.
repl commands
# Check how much context you have used > /status # → Model: claude-opus-4-6 # → Context: 245,000 / 1,000,000 tokens (24.5%) # → Session: feature-auth-system # Compact — standard summary > /compact # Compact with custom instructions > /compact Keep the database design decisions but summarize the rest # Compact before switching topics to clear irrelevant history > /compact Summarize the auth work so far, I'm switching to the payments module
With Session Memory enabled (available on Anthropic’s native API for Pro/Max subscribers), /compact is instantaneous. Background summarization keeps the summary pre-written — no waiting while Claude re-reads the whole conversation.
Auto-compaction triggers automatically when you hit 95% context capacity. You can toggle this via /config.
ℹ
Good time to compact: token usage exceeds 50%, you switch to a different feature, or after extensive failed attempts that can be summarized away. Compact freely — it is designed to be used often.
11 · Scripting
Automation & scripting with sessions
Capturing a session ID for later
Use --output-format json to get the session ID in structured output. The session_id field is present on every result.
bash
# Start a session and capture its ID sid=$(claude -p "Start a refactor session: list the risk points" \ --output-format json | jq -r '.session_id') echo "Session ID: $sid" # Later, resume that exact session claude --resume "$sid" -p "Continue with step 2 of the refactor"
CI/CD pipeline integration
bash
# Create a named session per build (pipeline usage) claude -p "Analyze test results and generate a bug report" \ -n "ci-test-analysis-$(date +%Y%m%d)" # Script: run tests and check status claude -c -p "Run the tests and tell me if they pass" \ --output-format json > test-results.json # One-shot query with no session saved claude -p --no-session-persistence "Explain this function briefly"
Shell alias for quick resumption
bash (add to ~/.zshrc or ~/.bashrc)
# Resume the most recent session for the current directory
claude-resume() {
local prev_session=$(jq -r 'select(.project == env.PWD) | .sessionId' \
~/.claude/history.jsonl | uniq | tail -2 | head -1)
if [[ -z "$prev_session" ]]; then
echo "claude-resume: no previous session found for $PWD"
return 1
fi
echo "Resuming session: $prev_session"
claude --resume "$prev_session"
}
Parallel sessions with Git worktrees
For truly isolated parallel work — a bugfix and a new feature simultaneously — use Git worktrees to create separate working directories, then run Claude Code independently in each.
bash
# Create isolated worktrees git worktree add ../project-bugfix bugfix/stripe-webhook git worktree add ../project-feature feature/new-dashboard # Launch separate Claude Code sessions in each cd ../project-bugfix && claude -n "bugfix-stripe" cd ../project-feature && claude -n "feature-dashboard" # Sessions, context, and file state are fully isolated
12 · Recipes
Real-world workflows
Daily developer workflow
bash — a full dev day
# Morning: list sessions and resume yesterday's work claude --list claude --resume "feature-auth-system" > Summarize where we left off yesterday # Late morning: focused implementation > Implement the backend login endpoint # Before lunch: compact to prepare for afternoon > /compact Keep the implementation details and remaining tasks # Afternoon: switch to a different task claude -n "code-review-pr-142" > Review PR #142 for security issues # Evening: return to the original task claude --resume "feature-auth-system" > Continue from this morning — build the frontend login form
Multi-day feature branch
bash — multi-day work
# Day 1: design the data model claude -n "migration-v2" > Create a migration plan for the new database schema # Day 2: continue the work claude --resume "migration-v2" > Let's continue from Step 2 of the migration plan # Day 3: implementation complete, wrap up claude --resume "migration-v2" > Generate the final migration scripts and test plan
Exploring alternatives without losing your place
typescript (SDK) — fork pattern
// You're deep in a JWT auth implementation.
// Want to explore Redis session storage without losing the JWT thread.
const jwtSessionId = currentSession.session_id;
// Fork to explore the alternative
const { session_id: redisSessionId } = await query({
prompt: "Let's try Redis session storage instead of JWT",
options: { fork: jwtSessionId }
});
// ... explore Redis approach ...
// Not happy? Resume the original JWT thread
await query({
prompt: "Let's stick with JWT. Continue from the token refresh logic.",
options: { resume: jwtSessionId }
});
13 · Debugging
Troubleshooting
–resume returns a fresh session instead of the expected history
!
Root cause: Mismatched working directory. Sessions are stored under ~/.claude/projects/<encoded-cwd>/, where the encoded name is your absolute project path. If you run the resume command from a different directory (even a parent or child), Claude looks in the wrong folder and creates a new session.
Fix: Make sure you are in the exact same directory the session was created from before running --resume. If you need to resume across machines or directories, capture the session ID from --output-format json and store it explicitly.
–continue creates a new session in a script
In non-interactive mode with -p, --continue may occasionally create a new session instead of resuming. This is a known limitation. For reliable automation, always use --resume with an explicit session ID captured from the first run.
Cannot find an old session
Use claude --list to see all sessions. You can also inspect the global history log:
bash
# List all sessions
claude --list
# Search history for sessions in a specific project
jq -r 'select(.project | contains("my-app")) | .sessionId + " " + .project' \
~/.claude/history.jsonl | sort -u
# Find sessions from a specific date
jq -r 'select(.startTime | startswith("2026-05")) | .sessionId' \
~/.claude/history.jsonl
Session memory not available
Session Memory (which powers instant /compact) is gated behind a feature flag and requires Anthropic’s native API. It is not available on Bedrock, Vertex, or Foundry. If you are on a Pro or Max subscription and don’t see “Recalled/Wrote memories” messages, your account may be in a gradual rollout queue.
Permissions asking for re-approval after resume
Tool permissions can expire for security reasons. Simply re-approve when prompted. For development environments where you want to skip approvals entirely, you can use --dangerously-skip-permissions — but only in well-controlled environments like Docker containers or CI pipelines.
14 · Best practices
Pro tips & best practices
🏷
Name every session
Always start with claude -n "descriptive-name". It’s the single highest-ROI habit in session management.
🔀
Use -c daily, -r for switching
For single-task daily work use --continue. Switch to --resume only when juggling multiple active threads.
⚡
Compact proactively
Don’t wait for 95% capacity. Run /compact when switching topics or after extensive exploration.
🔀
Fork to explore
Before trying a risky alternative approach, fork. It costs nothing and preserves your current thread.
🤖
Capture IDs in scripts
For automation, always use --output-format json | jq -r '.session_id' to capture IDs. Don’t rely on --continue in CI.
🌲
Git worktrees for parallel work
Isolate concurrent tasks with git worktree + separate Claude sessions. Context and file state stay fully separated.
📋
Use /resume inside sessions
You don’t have to exit to switch sessions. Type /resume mid-conversation and pick a different thread on the spot.
📖
CLAUDE.md for persistent memory
Sessions hold conversation history. For persistent project knowledge (architecture, conventions), use CLAUDE.md. It loads automatically every session.
Naming convention reference
bash — recommended naming patterns
# Use a consistent prefix that describes the type of work # Feature development claude -n "feature-user-auth" claude -n "feature-payments-v2" # Bug fixes claude -n "bugfix-stripe-webhook" claude -n "bugfix-race-condition" # Refactoring claude -n "refactor-api-routes" claude -n "refactor-db-layer" # Documentation claude -n "docs-api-reference" claude -n "docs-onboarding-guide" # Code review claude -n "review-pr-142" claude -n "review-security-audit" # CI / automation claude -n "ci-test-analysis-$(date +%Y%m%d)"
Quick reference card
Everything in one place
bash — complete cheat sheet
════════════════════════════════════════════════ CLAUDE CODE SESSION MANAGEMENT — CHEAT SHEET ════════════════════════════════════════════════ ## STARTING SESSIONS claude # new session (no name) claude -n "feature-auth" # new named session claude -p --no-session-persistence # one-shot, no save ## RESUMING SESSIONS claude -c # continue most recent claude -c "run tests" # continue + prompt claude --resume # interactive picker claude -r abc123def # resume by ID claude -r "feature-auth" # resume by name ## LISTING / FINDING claude --list # list all sessions ## INSIDE A SESSION (REPL commands) /resume # switch session mid-conversation /rename feature-auth-v2 # rename current session /compact # summarize to free context /compact Keep the auth decisions # compact with instruction /status # model + token usage info ## AUTOMATION claude -p "prompt" --output-format json | jq -r '.session_id' claude -r "$sid" -p "continue here" ## STORAGE LOCATIONS # Sessions: ~/.claude/projects/<path-hash>/<uuid>.jsonl # History: ~/.claude/history.jsonl # Memory: ~/.claude/CLAUDE.md (global) # Memory: ./CLAUDE.md (project, auto-loaded)
Based on official Claude Code documentation at docs.claude.com · Claude Code · May 2026