Skip to content

Sessions

Resume, name, branch, find and export Claude Code conversations from the CLI, and understand what a resumed session restores and where transcripts live.

A session is a saved conversation tied to a project directory. Claude Code writes it to disk as you go, which means you can quit, come back tomorrow and carry on, branch off to try a different idea, or juggle several tasks without losing any of them.

This page is about the terminal CLI. The desktop app, Claude Code on the web and the VS Code extension each keep their own session lists (the desktop app can also pick up CLI sessions).

Getting back into a session

CommandEffect
claude --continue (or -c)Reopen the latest conversation in this directory
claude --resume (or -r)Open the session picker
claude --resume <name>Jump straight to a named session
claude --resume <session-id>Resume by ID
claude --resume /abs/path/to/session.jsonlResume from a specific transcript file
claude --from-pr <number>Open the picker filtered to sessions linked to that pull request
/resumeSwitch conversation from inside a running session

My daily pattern: claude -c first thing to pick up where I stopped, and named sessions for anything that will span several days.

Sessions that are hidden by default

Runs started with claude -p or the Agent SDK are kept out of the picker and out of --continue, as are sessions whose first prompt was /loop. You can still resume any of them by ID. claude -p --continue does include -p, SDK and /loop sessions.

Resuming by ID from anywhere

claude --resume <session-id> works from any directory. It looks first in the current project and its git worktrees, then in every other project on the machine. The cross-project search only succeeds when exactly one other project has a transcript with messages for that ID, so a hand-copied duplicate gives you No conversation found with session ID: <id> rather than a guess. (Before v2.1.223, you had to resume from the directory the session last used.)

Background sessions

claude --continue will open a finished background session (v2.1.257 or later) but not one still running. If your latest conversation is running in the background, it exits with Your most recent conversation is running in the background and the session's ID; attach from claude agents or pick another with claude --resume.

Resuming a background session that is still running opens that live session rather than loading a copy (from v2.1.285; earlier versions told you to use claude attach <id> or stop it first). With --bg on the command line, the resume becomes a background dispatch instead.

From the shell, claude --resume <session> attaches this terminal to the running session. A prompt on the command line, as in claude --resume nightly-audit "include the admin routes too", is sent as its next turn first, and you see Sent your prompt to the background session (<id>); opening it…. Typing claude -p --resume <session> "..." at a terminal does the same.

It will not attach, and instead exits with status 1 and prints the claude attach <id> command (or points you to claude agents), if the command line includes:

  • piped or redirected input or output,
  • session-configuring flags such as --permission-mode, --model or --settings,
  • output-reading flags such as --output-format json or --json-schema,
  • run-limiting flags such as --max-turns or --max-budget-usd,

or if agent view is turned off. Add --fork-session to resume a copy instead, or run claude stop <id> and repeat the command to take the conversation over with your flags. Prompts starting with / or !, and any prompt while the session is waiting on your answer to a question, are not sent; the message explains why with Your prompt was not sent to it.

From inside a session, /resume on a running background session moves your current conversation to the background and attaches you, printing Opening "<title>", running in the background (<id>). Press the left arrow on an empty prompt to return to agent view. If your current conversation cannot move to the background (you are already attached to one, or persistence is off), /resume prints the claude attach command instead.

What resuming brings back

Loading a session from its transcript restores:

  • The conversation, including every tool call and result. A tool that was mid-run when the previous process died (say, in a crash) is not re-run. Claude sees it marked as cut off and is told to check whether it took effect before trying again, unless CLAUDE_CODE_RESUME_INTERRUPTED_TURN is set. (Before v2.1.281, such calls were dropped or shown as interrupted by you.)
  • The model, with a few exceptions covered in model configuration.
  • The agent, if the session started with --agent or the agent setting: same tool restrictions and model. Pass --agent to choose another. Claude Code looks for the agent definition in the original directory (if you trusted that workspace) and then in your current one; if neither has it, you get default tools and a warning naming the missing agent.
  • The permission mode, in many cases (details below).
  • An active goal, with its turn count, timer and token baseline reset.
  • Scheduled tasks that have not expired. Background Bash and monitor tasks are not restored.
  • Notes about unfinished background work. Background subagents, background Bash commands and workflows that died with the old process appear as notes in the transcript. Claude reads them with your next prompt; they do not trigger a turn by themselves.

Not every launch flag is remembered. If the session relied on --mcp-config, --settings, --plugin-dir, --fallback-model or --add-dir, pass them again. Directories added mid-session with /add-dir are not restored either (though the picker still uses them to find the session). Normal settings files are re-read at launch, so anything configured there is fine. For --system-prompt and --append-system-prompt, see the CLI reference.

Permission mode after resuming

It depends how you resume. (Attaching to a running background session keeps whatever mode it is in.)

  • Terminal, direct: claude --continue, claude --resume <id>, or claude --resume <name> matching exactly one session, without -p. The previous mode is restored subject to the table below. --permission-mode or --dangerously-skip-permissions overrides it.
  • Non-interactive: claude -p --resume or claude -p --continue start in whatever mode a fresh claude -p would, except plan mode can be restored under the conditions listed below.
  • Session picker at launch (plain claude --resume, --from-pr, or an ambiguous name): starts in the mode a new session would, except a session that ended in plan mode returns to plan mode unless you pass --permission-mode, --dangerously-skip-permissions or --fork-session.
  • /resume inside a session: the conversation continues in your current mode, except one that ended in plan mode goes back to plan mode, even if you launched with --permission-mode or --dangerously-skip-permissions. A conversation already opened earlier in this process continues in your current mode.
  • VS Code: see VS Code.
Ended inResumed viaStarts in
bypassPermissionsTerminalWhatever a new session would. Re-enable bypass with its launch flag or permissions.defaultMode: "bypassPermissions" in user, --settings or managed settings
planTerminalPlan mode (or the new-session default with --fork-session)
autoTerminalauto, if your account still qualifies for auto mode
ManualTerminalManual when a new session would otherwise start in auto by built-in default; if a settings defaultMode applies, that mode instead
planNon-interactive, conditions metPlan mode
AnythingNon-interactive, otherwiseWhatever a new claude -p run would
planVS CodePlan mode, with exceptions described on the VS Code page

Restoring plan mode via -p or VS Code needs v2.1.246 or later. For -p, all of these must hold: you pass --permission-prompt-tool and not --permission-prompts none; you do not pass --permission-mode or --dangerously-skip-permissions; you do not pass --fork-session; and the run was not started through channels. See permission modes.

Resuming from a summary

On Pro and Max, if you resume a session that has been idle for more than about an hour and holds over 100,000 tokens, a dialog appears before your first message. The prompt cache has expired by then, so the next request processes the full history once whichever option you pick.

OptionWhat happensTrade-off
Resume from summaryRuns /compact straight away: one summarisation request, then history becomes the summary, your latest exchanges and up to five recently read filesCheaper on every later request; anything the summary omits is gone
Resume full session as-isLoads everything unchanged and re-caches it after your first messageEvery detail kept; each request costs in proportion to the full history
Don't ask me againResumes in full and never shows the dialog againAs above

Costs explains why per-request usage grows with session length.

The session picker

/resume with no argument, or claude --resume on its own, opens the picker.

What it shows

By default, sessions from the current worktree (including background sessions, marked bg) and sessions from elsewhere that added this directory with /add-dir. Each row shows the name (or generated title, summary or first prompt), time since last activity, git branch and file size.

Sessions whose first prompt was /loop are hidden (running /loop later in a conversation does not hide it; before v2.1.211, an early /loop hid it permanently). A session moved with /cd lives in the new directory's storage and, from v2.1.196, stays out of the old directory's list even after a crash.

Forks from /branch or --fork-session have their own IDs and appear as separate rows. Multiple entries for one session are grouped; press the right arrow to expand.

Shortcuts

KeyAction
Up/Down or k/jMove through the list
Right/LeftExpand or collapse a group
EnterResume the highlighted session
1 to 9Resume the session at that position
SpacePreview (Ctrl+V also works on terminals that do not treat it as paste)
Ctrl+RRename the highlighted session
/ or any other printable keySearch. Paste a GitHub, GitHub Enterprise, GitLab or Bitbucket pull or merge request URL to find the session that created it
Ctrl+WToggle all worktrees of this repository (only in multi-worktree repos)
Ctrl+AToggle every project on the machine (also shows project paths)
Ctrl+BToggle filtering to the current git branch
EscLeave search, or close the picker

Picking a session from somewhere else

A session from another worktree of the same repo resumes in place; if that worktree no longer exists, it resumes in your current directory (see worktrees). A session from an unrelated project puts a cd plus resume command on your clipboard, unless that project's directory is gone, in which case it resumes where you are.

If a session selected from the claude --resume picker fails to load, you get Failed to resume the conversation with a retry command and exit code 1. From /resume, the error is reported and your current conversation keeps going.

Resuming by name

Name lookup covers the current repository and all its worktrees:

CommandExact matchAmbiguous
claude --resume <name>Resumes directlyOpens the picker with the name as a search
/resume <name>Resumes directlyReports an error; use /resume alone to pick

Naming sessions

Names make sessions easy to find and resume. They pay off most when several tasks run in parallel.

WhenHow
At launchclaude -n stripe-webhooks
Mid-session/rename stripe-webhooks (also shown on the prompt bar)
In the pickerHighlight and press Ctrl+R
Accepting a planPlan mode gives an unnamed session a title based on the plan
From claude.ai or the Claude appRenaming a Remote Control session applies in the CLI too (v2.1.221 or later)
In the desktop appRename it there; it then resumes in the desktop app

If you choose a name already used by another live session on the machine, the existing session keeps it and yours gets a two-word suffix, such as stripe-webhooks-quiet-otter, with a notice (from v2.1.232). This check skips AI-generated titles and default display names, the --name of background or -p sessions at startup, and sessions on older versions.

Unnamed sessions still get two automatic labels:

  • Default display name (v2.1.196 or later): the directory name plus a two-character suffix, such as api-7k. It identifies the session in running-session lists like agent view and claude agents --json, but is not a resume handle.
  • Generated title: a short summary of your first prompt, written in the background by the small fast model (usually Haiku class). Plain claude -p runs from a script do not get one. Accepting a plan replaces it with a plan-based title, which also replaces the default display name in running-session lists. Both kinds of title work with --resume and /resume.

Branching

Branching copies the conversation so far into a new session and switches you into it, leaving the original untouched. It is ideal when you want to try a riskier approach without losing a good line of work.

/branch try-websocket-transport

Without a name, the branch is named after the conversation's first prompt (from v2.1.198 this works after compaction too, rather than falling back to Branched conversation). From the shell:

claude --continue --fork-session

/branch prints both IDs; return to the original with /resume and its name or ID.

WhatAfter /branch
Conversation historyCopied up to the moment you branched
"Allow for this session" grantsKept, because the same process continues. --fork-session starts a new process and you re-approve
Running background subagents and Bash commandsKeep running, reporting into the new branch
Remote ControlStays connected and follows you into the branch

Resuming the same session in two terminals without forking interleaves both into one transcript, which is rarely what you want. For rewinding within one session, see checkpointing.

Managing context without leaving

  • /clear starts a fresh, empty conversation. The old one is saved; get it back with /resume or, in the same process, from the rewind menu's previous-session entry. With no argument, the new conversation keeps a name set with --name or /rename (but not a generated title). Pass a name, as in /clear invoice-bugfix, to name the conversation you are leaving; the new one starts unnamed.
  • /compact [instructions] swaps history for a summary, optionally focused.
  • /context shows what is using space.

See context window and best practices for when to clear versus compact.

Exporting and scripting

/export copies the conversation to your clipboard or saves it as readable plain text; give it a filename to skip the menu.

For scripts, use the structured interfaces rather than parsing transcripts:

You want toUse
Run once and capture the outcomeclaude -p with --output-format json or stream-json (result, session ID, usage, cost)
Ask an existing session somethingclaude -p --resume <id>
React to session eventsThe transcript_path field given to hooks and status line commands, for example archiving in a SessionEnd hook
Embed Claude in an appThe Agent SDK

For example, to get a quick changelog out of yesterday's session:

claude -p --resume 3f9c2a1e-... --output-format json \
  "list every file we changed and why, as bullet points" | jq -r '.result'

See headless mode.

Where transcripts live

Transcripts are JSONL files at ~/.claude/projects/<project>/<session-id>.jsonl, where <project> is the working directory path with every non-alphanumeric character replaced by -. If that name would exceed 200 characters it is truncated and a hash of the full path appended.

Each line is a JSON object for a message, tool call or metadata. The format is internal and changes between releases, so do not build scripts on it.

ToSet
Store everything outside ~/.claudeCLAUDE_CONFIG_DIR environment variable
Choose the <project> folder nameCLAUDE_CODE_PROJECT_DIR_NAME environment variable
Change the 30-day retentioncleanupPeriodDays in settings.json
Limit desktop and Cowork transcript agedesktopSessionCleanupPeriodDays in user, managed or --settings settings
Cap how large a -p or SDK transcript growsCLAUDE_CODE_TRANSCRIPT_LOCAL_GC environment variable
Stop writing transcripts in every modeCLAUDE_CODE_SKIP_PROMPT_HISTORY environment variable
Skip writing for one -p run--no-session-persistence

Transcripts are swept automatically after the retention period; claude purge removes a project's data immediately. Both are covered in the .claude directory. Deleting a background session with claude rm <id> leaves its transcript on disk, still resumable.

Naming the project folder yourself

Useful when a host application embeds Claude Code and gives each user or tenant its own config directory. Set CLAUDE_CODE_PROJECT_DIR_NAME together with CLAUDE_CONFIG_DIR (v2.1.234 or later):

CLAUDE_CONFIG_DIR=/var/lib/agents/acme CLAUDE_CODE_PROJECT_DIR_NAME=main claude

Transcripts then go to /var/lib/agents/acme/projects/main/ and auto memory to /var/lib/agents/acme/projects/main/memory/, regardless of working directory.

  • It is ignored without CLAUDE_CONFIG_DIR, because under the default ~/.claude it would merge every project into one folder.
  • Use 1 to 64 letters, digits, hyphens or underscores, and avoid Windows device names like con. Anything else is ignored.
  • Set it in the shell that launches claude; it is read once at startup, so a settings env block cannot set it.

If you later launch with the same config directory but without the variable, Claude Code goes back to the derived folder. Your named sessions are still there: Ctrl+A in the picker lists both, and claude --resume <id> finds either.