Sessions & Checkpoints
Every conversation you have with Command Code is a session: a durable transcript on disk that you can resume, rename, fork, clone, rewind, share, and export. Close your terminal mid-task, come back tomorrow, and pick up exactly where you left off.
A session is a single append-only JSONL file — one JSON record per line. The first line is a header (session id, creation time, working directory); every line after it is an entry: your messages, the model's replies (with token usage and cost), model and effort changes, compaction summaries, and more.
Entries form a tree, not just a list. Each entry points at its parent, so a session can hold multiple branches of the same conversation — this is what powers /rewind, /tree, and forking. The file itself is never rewritten in place: navigating history just moves a pointer, and new entries are appended.
Where session files live
Sessions are stored per project, keyed by a slug of the working directory:
Because the catalog is project-scoped, /resume and --continue only ever see sessions from the directory you launched Command Code in.
Alongside the transcript, a session can have sidecar files:
| File | Contents |
|---|---|
<id>.jsonl | The transcript itself (header + entries) |
<id>.meta.json | Title, model, lineage, trace ids, compaction stats |
<id>.share.json | Share link state, if the session was shared |
<id>.checkpoints.jsonl | Checkpoint snapshots for /rewind |
<id>.prompts.jsonl | Prompt history |
Finding the current session file
/session-file prints the current session id and the absolute path of its transcript. In terminals that support hyperlinks the path is clickable. If you haven't sent a message yet you'll see a (not created yet) note — the transcript is created on the first save.
Sessions are designed so you never lose committed work:
- Per-turn commit: Every completed turn is appended to the transcript as it commits — not on exit. Kill the process mid-run and everything up to the last committed turn is on disk.
- A turn either commits or is lost: There is no torn state: an interrupted turn simply doesn't make it into the file, and the session resumes cleanly from the previous commit.
- User messages survive failed turns: If a turn dies on a model/API error, your message that opened it is still written to disk — so a session that errored on its very first turn still shows up in
/resume. - Empty sessions leave no file: A brand-new session buffers in memory until the first assistant reply, so opening Command Code and quitting without a real exchange doesn't litter your session catalog.
- Torn files never block startup: If a transcript is damaged, corrupted lines are skipped and the session still loads.
In a session: /clear
/clear starts a new session with empty context. The previous session stays on disk, fully resumable with /resume. /new is an alias — same command, same menu row.
At launch
| Flag | What it does |
|---|---|
-n, --name <name> | Set the new session's display name at startup |
--no-session | Don't persist the session to disk at all (in-memory only) |
The resume picker
/resume (alias /sessions) opens the session picker — the same picker you get from cmd -r with no argument. It supports search, renaming (without leaving the picker), deleting sessions, and filtering by the git branch a session was started on. Forked sessions show their provenance (fork of <parent>), and the session you're currently in is highlighted and can't be deleted.
Two kinds of sessions are hidden from the picker:
- Headless (
cmd -p) sessions — they carry no title and stay out of the picker and--continue, but an exact session id still resumes them. - In-memory (
--no-session) sessions — they were never written to disk.
At launch
| Flag | What it does |
|---|---|
-r, --resume [name] | Resume a session by id or name; with no argument, open the picker |
--sessions [name] | Alias of --resume |
-c, --continue | Continue the most recent session in the current directory |
--session <path|id> | Resume by transcript path (.jsonl) or a unique session-id prefix |
--fork-session | With --resume/--continue/--session: fork the resolved session into a new one, leaving the original untouched |
A --session path inside the current project resumes like -r; a path outside it keeps appending to that file where it is.
Model restored on resume
The model a session was using is stored in its meta and adopted when you resume. An in-session /resume always adopts the resumed session's model (clearing any --model launch override so the resumed model wins); a cold cmd -r adopts it unless you explicitly passed --model for that launch.
Three commands let one conversation become many. They differ in what comes with you:
/fork [name] — copy everything
/fork copies the entire session — the full tree with every branch, plus checkpoints and file backup history, so /rewind keeps working in the fork — into a new session and switches to it. The original is left untouched and resumable.
Lineage is recorded on the fork's meta: parentSessionId (the source session) and branchPoint (the stable message id of the last source message at the fork point), so the picker can render fork of <parent> provenance. Names are optional (up to 200 characters) and must be unique.
/clone — copy the current branch only
/clone duplicates just the active branch of the conversation (from the current point back to the root) into a brand-new session file and switches into it. Unlike /fork, checkpoints and file history are deliberately not copied — a clone is "duplicate the conversation", and /rewind in the clone legitimately starts empty. The new file's header records the source transcript as its parentSession.
/tree — browse the whole tree
/tree opens the session-tree navigator: every branch of the session, not just the active one. From there you can jump to any point in the tree, fold segments, search, attach labels to entries, and cycle display filters (default, no-tools, user-only, labeled-only). When you navigate away from a branch, Command Code can generate a branch summary so the work you're leaving behind stays findable — you can confirm, customize, or skip the summary (and set a default in /config).
| Command | What it does |
|---|---|
/rename <name> | Rename the current session; bare /rename auto-generates a title with the model |
/name | Alias of /rename; bare /name shows the current name |
/session-file | Show the current session id and transcript path |
/status | Show comprehensive environment status |
/trace | Copy the current OpenTelemetry trace id (for support); works mid-turn, and persisted trace ids survive resume |
Names must be unique within a project — renaming to a taken name is rejected. The name also becomes your terminal tab title, and it's what -r <name> resolves.
Every prompt you send opens a checkpoint: a snapshot of the conversation plus a backup of every file Command Code goes on to edit. If something goes off track, rewind to any earlier checkpoint and continue from there.
Opening the rewind UI
Press Esc twice within 500ms, or run:
Each row in the selector shows when the checkpoint was taken, a preview of the message that opened it, and how many files that checkpoint changed (or No code changes).
Restore modes
| Mode | What it restores |
|---|---|
| Both | Restores conversation and code together (recommended). |
| Conversation only | Removes messages after the checkpoint. Files are untouched. |
| Code only | Restores files to their state at the checkpoint. Conversation is untouched. |
Checkpoints with no file changes only offer Conversation only.
What a file rewind does to your working tree
A Code only or Both rewind doesn't just undo edits — it puts the tree back the way it was:
| If a file was… | After the rewind |
|---|---|
| Modified after the checkpoint | Restored to its contents at the checkpoint |
| Created after the checkpoint | Deleted — it didn't exist at the checkpoint |
| Deleted after the checkpoint | Restored |
Backups are taken before each write_file or edit_file call and replayed newest-first, so a run of edits to the same file lands back on its oldest state. Backups are byte-faithful, so binary files (images, compiled artifacts) survive a backup–restore round-trip unchanged — no special handling needed.
Restores are verified before they run
Command Code checks every backup in the set can actually be restored before writing anything, so a rewind either applies in full or not at all — it won't leave you half-restored. If a file can't be restored, you're told which one and why.
Limits and pausing
Checkpoints are kept for 30 days, capped at 200 backups per session. Backups live in ~/.commandcode/file-history/<session-id>/, and identical content is stored once no matter how many checkpoints reference it.
Each session gets a scratchpad: a per-session temporary workspace for intermediate files — analysis notes, throwaway scripts, generated data — that don't belong in your project.
- Silent access: Reads and writes inside the scratchpad need no permission prompts (explicit deny/ask rules still take precedence). The path is advertised in the system prompt and exported to shell commands as
$COMMANDCODE_SCRATCHPAD. - Shared with sub-agents: Every sub-agent in the session sees the same directory, so agents can hand intermediate results to each other by file name.
- Survives compaction: After history compaction, a bounded metadata-only manifest of the scratchpad is re-injected, so the model remembers which working files still exist on disk without re-reading them.
- Follows launch-time forks: Forking at launch with
--fork-sessioncopies the source session's scratchpad into the fork, so the branched conversation keeps its working files. - Cleaned up with retention: Scratchpads older than 30 days are swept, and deleting a session deletes its scratchpad. It's temp space — keep durable deliverables in the project itself.
The whole tree can be relocated with the COMMANDCODE_SCRATCHPAD_BASE environment variable. Provisioning is fail-open: if the scratchpad can't be created safely, the feature silently disables and the session runs normally without it.
Disable it entirely in settings.json:
/share — live share link
/share uploads the conversation, copies a share URL to your clipboard, and — this is the key part — keeps the shared page live: every turn committed after sharing is streamed to the link automatically. Resuming a previously shared session re-arms the live updates. Run /share again to re-copy the existing link.
/unshare deletes the share and stops the live updates.
/share gist — GitHub gist
/share gist [html|jsonl|md] renders the session and posts it as a secret GitHub gist via the gh CLI, then copies the gist URL. The default format comes from /config's "Default share gist format" setting.
/export — write a file
With no path, the file is written as command-code-session-<first 8 chars of id>.<format> using /config's "Default export format" (html when unset). jsonl exports the raw transcript.
/copy — clipboard
/copy copies the last assistant reply to the clipboard. Best-effort: in headless/SSH terminals without clipboard access, the feed line tells you it couldn't.
When the conversation approaches the context limit, Command Code compacts history (automatically, or on /compact). Two guarantees matter for sessions:
- The on-disk log is never rewritten: Compaction appends a compaction entry (the summary plus a pointer to the first entry kept verbatim) to the transcript tree. Your full history stays in the file — context building just reads through the compaction entry, and
/treecan still reach everything. - Savings persist across resumes: Cumulative compaction stats (event count, total tokens saved, last event) are written to the session's meta on every compaction, so the "total this session" figure
/compactreports survives--resume.
What compaction does to the transcript, the tiers and their thresholds,
/compact and /compact-mode, and how to keep context lean.
- One picker, not two.
/resumeand/sessionsopen the same unified picker rather than separate interactive/print views, so there's one mental model for "where are my sessions." - Rewind is destructive on purpose, but reversible. Restoring is instant and irreversible in the moment, but because it's just moving between checkpoints, you can rewind forward again if you change your mind.
- Print sessions are real sessions. They're saved and resumable, just hidden from the picker by default — automation output doesn't have to mean throwaway state.
Checkpoints not appearing
- Ensure you've sent at least one message in the session
- Check if checkpointing is paused (you'll have seen a disk-space notice)
- Verify the session has file modifications — a checkpoint with no file changes only offers a conversation restore
Restore failed
- Check the error message for which file failed
- Ensure backup files haven't been manually deleted from
~/.commandcode/file-history/ - Verify you have write permissions to the target files
Double-Esc not working
- Press Esc twice within 500ms
- Ensure focus is on the Command Code input
- Use
/rewindinstead
- Name sessions you'll come back to:
/rename auth-refactor(or launch with-n) makescmd -r auth-refactora one-liner later — and a bare/renamewill generate a decent title for you. - Fork before risky experiments:
cmd -c --fork-sessionor/forkgives you a full copy — checkpoints included — while the original stays pristine. - Use
/cloneto tidy up: After heavy rewinding,/cloneextracts just the branch you kept into a clean new session. - Label important points in
/tree: Labels survive forks and make long trees navigable. - Let the scratchpad absorb clutter: Ask for throwaway scripts and intermediate outputs in the scratchpad — no permission prompts, no files polluting your repo, and it's cleaned up automatically.
/sharebefore pairing: The link updates live as the session continues, so a teammate can follow along in real time.- Grab
/tracewhen something breaks: The trace id is what support needs, it's copyable mid-turn, and past ids survive a resume.
- Headless Mode — resuming and naming sessions from scripts and CI.
- Interactive Mode — the full session experience.
- Context & Compaction — how history is summarized as it grows.
- Permissions — how permission decisions apply as you resume or fork a session.