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