# Can Conversations Branch and Rewind Like Code?

Git gives code the power to branch, rewind, and merge—but conversations are usually one-off and linear. Claude Code uses JSONL persistence and a full suite of conversation management commands to let you treat dialogue like source code: branch to explore different directions, rewind to any point, or fire off a quick side question without interrupting the main thread. This chapter dissects the implementations behind `/branch`, `/rewind`, and `/btw`.

> 💡 **Plain English**: It's like save states in a video game—you can save your progress, load an old save, and start over from any point.

---

### 🌍 Industry Context

Conversation branching and rewinding aren't unique to Claude Code—they're a general problem the AI coding-assistant space is actively exploring. **ChatGPT**'s web interface has supported conversation branching since 2023 (you can "Edit" any message to spawn a new branch), but it's purely UI-level with no persistent file storage. **Cursor**'s Composer mode offers a "checkpoint" feature that automatically creates a Git snapshot after every AI operation, letting users one-click rollback to any checkpoint—but this rolls back the *code state*, not the *conversation history*. **Aider** uses Git commits as rollback units—automatically committing after every AI code change so users can `git revert`—but the conversation itself remains linear and unforkable. **Windsurf (Codeium)**'s Cascade mode lets you browse conversation history but doesn't support true forking.

Claude Code's unique angle is that it treats the **conversation itself** (rather than the code state) as a first-class branchable object, using JSONL files to implement Git-like fork/rewind semantics. This design hews closer to academic modeling of "dialogue trees," but in terms of engineering implementation, the industry has yet to converge on a single best practice.

---

## The Problem

Git lets code branch, backtrack, and merge. But what about conversations? If Claude is in the middle of helping you with something and you suddenly wonder, "What if I had taken a different direction back then?"—is there a way to go back?

---

## Here's How It Actually Works

Claude Code implements a full **conversation history management system** that supports three operation modes: branching, rewinding, and quick side questions. A conversation isn't disposable—it's a persistent object that can be copied, jumped to, and forked.

---

## Operation 1: `/branch` — The Git Fork of Conversation

```
/branch [optional name]
```

Execution flow (`commands/branch/branch.ts`):

1. Read the current session's JSONL transcript file
2. Filter out sidechains (sub-agent internal messages), keeping only the main conversation
3. Generate a new session UUID
4. Write each message to the new file, preserving original metadata but appending a `forkedFrom` field:

```typescript
forkedFrom: {
  sessionId: originalSessionId,
  messageUuid: entry.uuid,
}
```

5. Handle `content-replacement` records—this is a crucial detail: without copying these records, the branched version would reconstruct state thinking all replaced tool results are "complete content," triggering massive prompt cache misses

6. Handle branch name collisions: "Branch" → "Branch 2" → "Branch 3"…

After execution, you are **inside the branched version**. The original conversation continues to exist, and the two are completely independent.

---

## Operation 2: `/rewind` — Rewind to Any Message

```
/rewind
```

This opens the `MessageSelector`—a UI component that lets you pick a message from the list. Once selected, the conversation history is truncated to just before that message, and you can restart from there.

This solves a common scenario: the AI goes down the wrong path, makes a series of incorrect operations, and rather than undoing them one by one, you simply jump back to the fork point.

---

## Operation 3: `/btw` — A Side Question That Doesn't Interrupt the Main Conversation

```
/btw <question>
```

This is a cleverly designed feature. Implementation principle (`commands/btw/btw.tsx`):

> 📚 **Course Connection**: `/btw`'s cache reuse mechanism is analogous to the Copy-on-Write (CoW) concept from **operating systems** courses—the side question shares the parent request's cached context (like sharing page tables), and only the genuinely different part (the new question) requires additional resources.

1. Call `getLastCacheSafeParams()` to get a snapshot of the last API request's parameters
2. Launch `runSideQuestion()` with those exact same parameters
3. The question is handled by an independent AI instance, **completely isolated from the main conversation**
4. The main conversation's message history is left untouched

Why does this work? Because `/btw` reuses the parent request's prompt cache (keeping cache parameters identical via `CacheSafeParams`), so the side question itself is extremely cheap—it doesn't need to reprocess the entire main conversation context, only the new question.

Use cases:
- You're in the middle of a refactor and suddenly want to confirm how an API works, but don't want that question appearing in the conversation history
- You want to quickly look up something unrelated without breaking your current workflow

---

## Under the Hood: Conversations Are JSONL Files

All of these features are possible for one fundamental reason: **every conversation is serialized to a JSONL file on disk**.

```
~/.claude/projects/{project-hash}/{session-uuid}.jsonl
```

Each message is one line of JSON containing:
- `uuid` — unique message ID
- `parentUuid` — forms a linked list
- `sessionId` — owning session
- `isSidechain` — whether this is a sub-agent internal message
- `forkedFrom` — if forked, records the original source

The choice of JSONL isn't arbitrary: each message is an independent line, enabling append-only writes (no need to read the whole file), line-by-line streaming reads, and a disk layout that naturally supports append-only semantics.

> 📚 **Course Connection**: This append-only log design is highly consistent with the WAL (Write-Ahead Logging) principle from **database systems** courses—guaranteeing crash recovery and write performance through append-only writes. The linked list formed by `parentUuid` resembles the singly linked list from **data structures** courses, while the `forkedFrom` field lets that list branch into a tree structure—essentially a directed acyclic graph (DAG), strikingly similar to Git's commit graph data model.

```typescript
// Content replacement records are also stored in the same file
type ContentReplacementEntry = {
  type: 'content-replacement'
  sessionId: UUID
  replacements: ContentReplacementRecord[]
}
```

---

## An Underrated Small Design: `thinkback`

```typescript
// commands/thinkback/index.ts
description: 'Your 2025 Claude Code Year in Review'
```

Because every conversation is persisted, the system can produce a "year in review"—counting how many times you used AI, what types of work you did, which conversation was the longest. This feature is a direct byproduct of JSONL persistence.

---

## The Full Conversation Management Toolkit

| Command | Function |
|---------|----------|
| `/branch` | Fork the current conversation and enter the branched version |
| `/rewind` | Rewind to any message point |
| `/btw` | Quick side question without polluting the main conversation |
| `/resume` | Resume any previous conversation |
| `/rename` | Give a conversation a name |
| `/clear` | Clear conversation history and start a new session |

---

## Limitations and Critique

- **No branch merging**: Unlike Git, conversation branches can only be forked, never merged—you cannot combine the results of two branches into one
- **JSONL file bloat**: Long conversations and frequent branching produce large numbers of JSONL files, and there is currently no automatic cleanup mechanism for expired sessions
- **Hidden costs of `/btw`**: While side questions don't pollute the main conversation, they still consume API calls and token budget, which users may underestimate (especially under complex contexts)

---

## Code Landmarks

- `src/utils/sessionBranching.ts` — core session branching utility functions
- `src/components/BranchSelector.tsx` — branch selection UI component
- `src/commands/branch/branch.ts`, line 61: `createFork()` function (complete fork logic)
- `src/commands/branch/branch.ts`, lines 97-107: copying of content-replacement records (prevents cache misses)
- `src/commands/rewind/rewind.ts`: `openMessageSelector()` call (minimalist implementation)
- `src/commands/btw/btw.tsx`, line 22: `getLastCacheSafeParams` import (cache reuse mechanism)
- `src/utils/sessionStorage.ts`: JSONL persistence system
