[FEATURE] Conversation Branching — full spec for fork, merge, and tree navigation
Preflight Checklist
- [x] I have searched existing issues — this consolidates ideas from #10370 (locked), #12629, #150 (locked), #16276 (locked)
- [x] This is a single feature request
Summary
Claude Code already has /fork and --fork-session. These create independent sessions from a shared history point. What's missing is the return path — bringing conclusions back, navigating the tree, and managing branches as first-class objects. This would make Claude Code dramatically more useful for exploratory work where you need to try multiple approaches before committing to one.
Business Case
Agentic coding sessions are expensive in time, tokens, and cognitive load. When a user reaches message 40 and wants to try two different approaches, they currently must either:
- Pick one and hope — risk wasting a long session if the approach fails
- Fork and abandon —
/forkworks, but conclusions from the winning fork can't flow back; the losing fork's lessons are lost - Start over — discard accumulated context entirely
Branching with merge-back solves all three. It turns Claude Code from a linear tool into a tree-structured one, matching how real engineering decisions actually work: explore, evaluate, commit. The closest analogy is git branch + git merge — proven UX that every developer already understands.
What Exists Today
| Capability | Status | Gap |
|-----------|--------|-----|
| Fork from current point | ✅ /fork [name] | Works well |
| Fork on resume | ✅ --fork-session | Works well |
| Rewind current session | ✅ /rewind | Modifies in-place, no branch |
| List/navigate branches | ❌ | /resume shows flat list, no tree |
| Merge conclusions back | ❌ | Must manually copy-paste findings |
| Compare branches | ❌ | No diff between session states |
| Name/tag checkpoints | ❌ | Sessions have IDs, not meaningful names |
Proposed Features (incremental)
Tier 1: Branch awareness (low effort, high value)
/branches or /tree — show the fork tree of the current session lineage.
main (current)
├─ msg 12: fork "try-redis" (15 messages, idle 2h)
│ └─ msg 8: fork "redis-cluster" (3 messages, idle 1h)
├─ msg 28: fork "try-postgres" (22 messages, active)
└─ msg 35: (you are here)
/fork <name> — already exists, but names should be visible in /resume and /branches.
/switch <name|id> — jump to a sibling/child branch. Current session suspends; target session resumes. Equivalent to git checkout <branch>.
Tier 2: Merge-back (medium effort, transformative)
/merge <name|id> — in the current session, inject a summary of another branch's work.
The merge is not replaying tool calls. It's an LLM-generated summary of what the branch accomplished, inserted as a system message. Equivalent to reading a colleague's findings.
/merge try-redis
Inserts into current context:
[Branch "try-redis" merged — 15 messages, 3 file edits]
Summary: Redis approach works for caching but requires sentinel
for HA. Implemented in src/cache.rs. Key finding: latency drops
from 12ms to 0.3ms for repeated queries. Abandoned because
operational complexity too high for single-node deployment.
Merge strategies:
- summary (default): LLM-generated digest of the branch, injected as context
- custom:
/merge try-redis "Redis works but too complex, use SQLite instead"— user-written summary - silent:
/merge try-redis --silent— mark as merged for bookkeeping, don't inject anything
Tier 3: Checkpoints and tags (low effort, quality of life)
/checkpoint [name] — bookmark the current conversation state with an optional name. Like a git tag on the message timeline.
/rewind <checkpoint> — rewind to a named checkpoint (currently rewind only goes to auto-created restore points).
This gives users explicit save points before risky operations, without creating a full fork.
Tier 4: Branch comparison (aspirational)
/diff <branch-a> <branch-b> — LLM-generated comparison of two branches' approaches and outcomes.
/diff try-redis try-postgres
Both branches solved the caching problem:
- try-redis: 0.3ms latency, requires sentinel, 3 new dependencies
- try-postgres: 1.2ms latency, uses existing infra, materialized views
Recommendation: try-postgres — simpler operations, acceptable perf.
Implementation Notes
Data model
The JSONL session format already has parentUuid linking messages and isSidechain for subagents. Fork metadata could extend this:
// In session metadata (or a sibling .meta.json)
{
"sessionId": "abc123",
"forkOf": "parent456", // null for root sessions
"forkAtMessage": "msg789", // message UUID where fork occurred
"forkName": "try-redis", // user-provided name
"mergedInto": ["parent456"], // sessions this was merged back into
"checkpoints": [
{"name": "before-refactor", "messageId": "msg012", "created": "..."}
]
}
Context budget
Merge summaries should be treated like compacted context — they compress a branch's work into a few hundred tokens. This is strictly cheaper than the alternative (user manually copy-pasting findings, which wastes context on formatting and repetition).
Git integration (optional, not required)
Branches could optionally map to git branches (as #150 proposed), but this is not required for the core feature. Conversation branching is useful even when not writing code — for research, planning, debugging. Tying it to git would limit the feature unnecessarily.
Prior Art
- #10370: Comprehensive proposal for chat branching with selective merge-back (18 👍, detailed UX mockups, storage format spec). Locked.
- #12629: Request for in-session
/forkUI (15 👍). Open. - #150: Conversation forks as git branches (locked).
- #16276: Fork from specific message (closed as duplicate).
- ChatGPT: Has conversation branching in the web UI (edit a message → creates a branch), but no merge-back.
- Cursor: Has checkpoint/restore but no branching.
- agent-deck (community): Wraps
--fork-sessionin tmux for parallel sessions.
Summary
The primitives exist (/fork, --fork-session, session JSONL with parent links). The missing pieces are branch awareness (see the tree), merge-back (bring conclusions home), and naming (human-meaningful labels). Tiers 1-2 would make Claude Code meaningfully better for any session longer than 20 messages. Tier 1 alone would be a significant improvement with relatively low implementation cost.
---
Addendum: Cross-session context sharing (the git remote analogy)
The branching model above covers forks within a single session lineage. But there's an equally important use case: sending context between unrelated concurrent sessions.
Real workflow
I'm working on two related projects simultaneously:
- Session A:
valdivia-analysis/— computational geometry, GPU kernels, benchmarking - Session B:
vga-paper/— the academic paper describing Session A's algorithm
Session A discovers that p=10 HLL precision gives R²=0.996 at 3.6x less memory than p=12. Session B needs this finding for the results section. Today I copy-paste between terminals. What I want:
# In Session A (valdivia-analysis)
/push vga-paper "p=10 is the sweet spot: R²=0.996 IHH, R²=0.982 MD, median err 1.25%/0.44%, 4.1s BFS. 3.6x less memory than p=12."
# In Session B (vga-paper) — receives it as injected context
[From session "valdivia-analysis"]: p=10 is the sweet spot: R²=0.996 IHH...
This is git remote for conversations
| Git | Conversation equivalent |
|-----|------------------------|
| git remote add | Register another session as a peer |
| git push | Send a finding/conclusion to a peer session |
| git pull | Request a summary of a peer session's recent work |
| git fetch | Check what's new in a peer without injecting it |
Why this matters beyond single-user workflows
The same primitive enables multi-user agent collaboration:
- My Claude session pushes a question to a colleague's Claude session
- A CI/CD agent pushes test results to a developer's active session
- A research agent pushes findings to a coding agent working on implementation
This connects to #32504 and #24798 but frames it differently: those issues focus on orchestration (coordinator directing workers). The git-remote model is peer-to-peer — any session can push to any other, no coordinator required. It's the difference between a CI pipeline and distributed version control.
Proposed commands
/push <session-name|id> "message"— send context to another session/pull <session-name|id>— request an LLM-generated summary of another session's recent work/peers— list sessions that have been registered as peers (or auto-discover by project proximity)/inbox— view messages pushed to this session from peers
Messages arrive asynchronously. The receiving session sees them on next user interaction (like checking email), not as interrupts. This keeps sessions autonomous while enabling information flow.
10 Comments
This issue consolidates ideas from several related proposals that were auto-closed and locked:
Also builds on work by @asheshgoplani (agent-deck fork implementation) and @smconner (search-term consolidation on #10370).
If this captures what you were after, a 👍 on the issue would help signal demand. Feedback welcome — especially on the merge-back semantics (Tier 2) and cross-session push/pull (the git-remote addendum).
cc @NickNick @tbrebant @wxtry @kyryl-lebedin @marcindulak
Great consolidation, @stiege — especially the Addendum section with the
git remoteanalogy.We're running a multi-team coordinator workflow that maps directly to your cross-session push/pull proposal:
Today the coordinator manually transfers files between teams via shared directories and updates memory files. The pain points:
Your proposed
/push+/inboxwould eliminate our entire manual relay workflow. Specifically:The peer-to-peer model (vs. coordinator-directed) is key — sometimes the dev team needs to push findings directly to research without going through the coordinator.
+1 on the full proposal. Tiers 1-2 are valuable, but the Addendum is what would be transformative for multi-agent workflows.
Use case: retroactive fork with selective compaction
Related: #28716 (summarize before here)
There's a variant that sits between Tier 1 and Tier 2: retroactive branch-and-compact. The scenario:
You're 60 messages in and realize messages 35–60 went down a tangent. You want to:
The result is a clean, focused session for the tangent — with enough compressed context to remain coherent, but without dragging along the full weight of the earlier conversation.
This differs from
/forktoday (which copies everything up to the fork point verbatim) and from/compact(which compresses the whole session indiscriminately). It's the combination: fork + selective compaction at the branch point.The git analogy would be
git checkout -b tangent && git rebase --squash main~34— take the recent commits as-is, squash the old history.A hook-based approach can implement basic conversation branching via checkpoints:
This gives you basic /branch, /branch restore, and /branch list commands via hooks.
Prefix cache reuse makes fork/merge nearly free - here's why
Building on the discussion here and in related issues (#10370, #18840, #28415, #12790), I want to add an
The three-way dilemma today
As emernic noted in #12790, the current options are all unsatisfying:
| Mode | Sees parent context? | Prefix cache hit? | Intermediates pollute parent? |
|---|---|---|---|
| Inline (default) | Yes | Yes | Yes (permanent) |
| Agent /
context: fork| No | No (fresh prompt) | No || Workarounds (log replay, etc.) | Partial | No | Varies |
Why branching is cheaper than you'd expect
The Anthropic API caches KV states for matching prompt prefixes. A branched execution that copies the parent's message array as its prefix would hit the cache automatically - cached tokens are ~90% cheaper and near-instant. The branch diverges only at the append point (the scoped task + tool calls), so the entire shared prefix is served from cache.
This means fork/merge isn't just a convenience - it's cheaper than the current subagent approach, which rebuilds its entire prompt from scratch every turn with zero cache benefit.
For a session at 100k tokens with a skill producing 20k tokens of intermediate output:
For N parallel branches from the same point (the scenario in #28415), all N share the same cached prefix - the redundant ~50k x (N-1) token cost disappears entirely.
Implementation: harness-level only, no API changes
The harness already manages the message array:
This could surface as:
context: branchin skill frontmatter (a third option alongside inline and fork, as Crazytieguy suggested the parent should control)branch_from_current: trueon the Agent tool/forkcommand (completing the gap identified in this issue)Relation to the tier structure
This supports the tiered approach proposed here. Prefix cache reuse makes Tier 1/2 forks cheap enough to be casual - you wouldn't need to think twice about branching for a quick investigation, because the cost is essentially "only pay for the new work, not for re-reading the conversation."
Great spec. One thing I'd add to Tier 1 that would cover a very common workflow:
/branch "name" --from N — Create a named branch from N prompts ago, without leaving the current session.
Use case: You're deep in a technical architecture discussion and it naturally forks into business/legal implications. You realize 3 prompts later that you want both threads. Today this
requires: /branch (only from current point) → exit → picker → rename → re-enter → /rewind. By then you've lost your flow.
The proposed command would:
Related: there's currently no way to see the current session ID from inside a session (/session-info or similar), which makes managing parallel branches very hard.
[dictated to me by my claude code after we discussed it, Pietro]
Hi Alex,
Your #32631 spec stuck with me — modeling conversation branching as git branch + fork → evaluate → merge-back, with a tree to navigate the rest. Cleaner than how Claude Code thinks about it today.
I noticed swarm-mcp too — you're already running parallel Claude agents in Docker. So you've probably hit the thing I'm chasing: when several branches finish overnight, deciding which one is actually safe to merge back is its own job, separate from getting the work done.
One genuine question, no pitch: when you've got multiple parallel agent outputs to merge, do you enjoy going through each one yourself — reading the diff, working out why it changed what it did — or would you rather just have a fast, trustworthy read on which branch is merge-safe and skip the deep-dive?
I'm async-only and a few timezones off, so no call — a one-line reply is plenty.
For context on why I'm asking: I'm building the thing that sits after the agent finishes. The agent does the work overnight; in the morning you get a short report that tells you in a few minutes whether it's safe to merge, instead of reading all of it line by line.
Best,
Shiyu
the thing I keep hitting with fork/merge proposals like this: the blocker isn't the merge command, it's that the parent session keeps auto-compacting underneath you. you fork at message 40, explore a branch or two deep, and by the time you want to merge findings back the parent's context already got summarized out from under you, so there's nothing faithful left to merge into. tree-structured work only holds if every node keeps its full context independently and survives a restart. the parentUuid plumbing handles lineage fine, but lineage isn't the same as preserved context per node. separate those two and merge-back gets a lot more tractable.
For Tier 1/3 (branch from a past message + checkpoint navigation), there's something working today: hit Ctrl-B in ccfind (claude-grep) on any session row to fork that session at any past user message — creates a new session file in Claude Code's native /btw-compatible format. No merge-back yet (Tier 2), but the branch-from-checkpoint UX is functional.
— happy for this to be superseded by a native impl, just sharing as existence proof.
I just created this simple tool: branch-graph, as a workaround for the following gap mentioned in this issue until it's implemented natively.
| Capability | Status | Gap |
|------------|--------|-----|
| List/navigate branches | ❌ |
/resumeshows a flat list instead of a branch tree |The
branch-graphUI looks like the following, making it much easier to navigate between branches.