Feature: CLI-invocable session branch (claude branch <id> --name <n>) / make --fork-session safe for live sessions
Use case
I run long-lived orchestration sessions in my homelab, one tmux window per Claude Code session. A recurring need: take a LIVE session that has accumulated a lot of useful context and branch it into a new terminal — carry the full context into a sub-project session, guide that branch independently, and eventually merge a summary back into the parent (the workflow sketched in #32631 and #69712).
/branch has exactly the right semantics for this — it snapshots the current conversation into a new session and leaves the original untouched. But it is only invocable from inside the running session's UI. There is no way to trigger it from a script or another terminal, which is where orchestration tooling lives.
Current behavior
claude --resume <id> --fork-sessionworks fine when<id>is not open anywhere. But when the session is currently open in another terminal, the new process exits almost immediately — in my repro the tmux window closes in under 4 seconds (interactive mode, v2026.x). No error I can capture, just gone.- There is no lock or coordination between processes: #19364 (session lock file) was closed not-planned, and #48270 documents that concurrently resuming the same id fragments the transcript. #69364 notes the live-session registry (
~/.claude/sessions/<pid>.json) now exists but resume doesn't consult it. - Even when the fork doesn't die, #44684 showed
--fork-sessionreads the last-flushed JSONL rather than the live in-memory conversation, so forking a live session from outside is unreliable by design today.
My workaround is cp of the transcript .jsonl to a new uuid and claude --resume <new-uuid>. It works, but it depends on the internal file layout that the docs explicitly warn changes between releases — not something I want load-bearing in my orchestration scripts.
Proposed behavior
Either of these would solve it:
- A
claude branch <session-id> [--name <name>]subcommand that snapshots the target session's transcript to a new session id and prints it (or opens it). This is what/branchalready does internally; done as copy-on-branch it is inherently safe against a live holder because nothing writes to the original. - Make
claude --resume <live-id> --fork-sessiondetect the live holder (the~/.claude/sessions/registry already has pid + sessionId) and fork from its current state — ideally asking the live process to flush first — instead of silently exiting.
Option 1 also composes nicely with the SessionStart source:"branch" hook I filed separately (#73053), giving scripted branches the same observability as interactive ones.
Related issues
- #32631 — conversation branching spec (
/merge,/tree); this is the CLI entry point for that model - #69712 — branches in agent view + merge-back path
- #19364 — session lock file (closed not-planned)
- #48270 — concurrent resume of one session id fragments the transcript
- #69364 — resume doesn't check the live-session registry
- #44684 —
--fork-sessionforks last-flushed JSONL, not live state - #67870 — fork-as-new-session from a checkpoint (in-session ask; this issue is the from-outside counterpart)
Environment
Claude Code CLI on Linux, interactive tmux-based workflow, v2.x current.