# How Conversation Branches Work with Checkpointing and Forking in DeepSeek-Reasonix

> Explore how DeepSeek-Reasonix conversation branches use checkpointing and forking. Rewind or create new sessions from any prior turn with file snapshots before edits.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: internals
- Published: 2026-06-22

---

**DeepSeek-Reasonix implements conversation branches through a turn-based checkpoint system that captures file snapshots before any edits, enabling users to rewind to previous states or fork new independent sessions from any earlier turn.**

DeepSeek-Reasonix provides sophisticated conversation branching capabilities built on a robust checkpoint architecture. The system creates immutable snapshots at the start of every user turn, recording both the conversation state and file system contents. This design enables precise rewinding and forking operations that preserve the integrity of the original session while allowing parallel exploration of alternative coding paths.

## Checkpoint Architecture and Data Structure

The foundation of conversation branching lies in the checkpoint system defined in [`internal/checkpoint/checkpoint.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/checkpoint/checkpoint.go). Every user turn automatically triggers the creation of a checkpoint that records the complete state of the workspace **before** any edit tools modify files.

### What Each Checkpoint Captures

When the `Begin` function executes at `checkpoint.go#L86-L100`, it constructs a checkpoint containing five critical fields:

- **Turn**: The numeric turn identifier starting at 0
- **Time**: The timestamp when the turn initiated
- **Prompt**: The user prompt that triggered the turn
- **MsgIndex**: The boundary index in the session's message list where the turn begins, serving as the *conversation-rewind boundary*
- **Files**: A slice of `FileSnap` objects (defined at `checkpoint.go#L35-L45`) storing file paths and their pre-edit contents, or `nil` for non-existent files

The checkpoint store persists these snapshots as individual JSON files (`turn-<n>.json`) within a dedicated checkpoint directory (`*.ckpt`). The implementation at `checkpoint.go#L186-L204` ensures turn counter consistency across system restarts, enabling reliable session recovery.

## Rewinding to Previous Conversation States

Rewinding restores both the workspace and conversation history to a specific earlier turn. When the controller receives a rewind request, it retrieves the target checkpoint's `MsgIndex` and executes two synchronized operations.

First, the system invokes `RestoreCode` (implemented at `checkpoint.go#L335-L352`) to revert the workspace. This function writes back the recorded file contents from the earliest snapshot, deleting files that were recorded as `nil`. Second, the controller truncates the session's message list to the saved `MsgIndex`, permanently discarding all subsequent messages. This dual restoration ensures that both the code and conversation return to the exact state captured at the beginning of the chosen turn.

## Forking and Branching Mechanisms

Forking creates a **new, independent session** that diverges from the original conversation without modifying it. The `forkNamed` method in [`internal/control/controller.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/control/controller.go) orchestrates this process through five distinct steps:

1. **Validation**: The controller verifies that no turn is currently running and that the session has a persistent checkpoint directory (forking is impossible for in-memory-only sessions)
2. **Boundary lookup**: Using checkpoint metadata returned by `Store.List()`, the system locates the `MsgIndex` for the requested turn
3. **Transcript copy**: The controller copies the message slice up to that `MsgIndex` into a brand-new `Session` object
4. **New checkpoint store**: A fresh `Store` instance is constructed for the new session, seeded with the same checkpoint directory where it will write new `turn-<n>.json` files alongside the original ones
5. **Controller swap**: A new `Controller` instance wraps the forked session, and the server swaps its active controller while preserving the original

The HTTP server exposes this functionality through the **POST `/fork`** endpoint registered at `serve.go#L208-L215`. The CLI implementation in [`internal/cli/rewind.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/cli/rewind.go) provides the `rewind fork <turn>` command, which parses arguments and invokes the controller's forking logic. The [`internal/agent/branch.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/agent/branch.go) file defines branch-specific metadata fields including `ForkTurn` and `ForkMessageIndex` that track the branching origin.

## Practical Usage Examples

### Rewinding from the CLI

To restore the workspace and conversation to turn 2 (the third turn, zero-indexed):

```bash
$ reasonix rewind 2

```

The CLI parses the argument and calls `Controller.Rewind(turn)`, which internally uses `Store.RestoreCode` and truncates the message list.

### Forking via the HTTP API

To create a new branch from turn 3:

```http
POST /fork HTTP/1.1
Content-Type: application/json

{
  "turn": 3
}

```

The server handler forwards the request to `Controller.Fork(turn)` and returns the new session identifier:

```json
{
  "branchId": "branch-20240622-01"
}

```

### Programmatic Forking in Go

```go
// Assume ctrl is a *control.Controller already constructed
branchID, err := ctrl.Fork(4)  // Fork from turn 4
if err != nil {
    log.Fatalf("fork failed: %v", err)
}
fmt.Println("Created branch:", branchID)

```

Internally, this calls `ctrl.forkNamed(4, "", true)` which performs the validation, boundary lookup, and session duplication steps.

## Summary

- **Turn-based snapshots**: Every user turn creates a checkpoint in [`internal/checkpoint/checkpoint.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/checkpoint/checkpoint.go) that captures file states and conversation boundaries before any edits occur
- **Complete state restoration**: Rewinding uses `RestoreCode` and message list truncation to revert both code and conversation history to any previous turn
- **Session isolation**: Forking creates independent sessions via `forkNamed` in [`internal/control/controller.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/control/controller.go), copying transcript history to a new checkpoint store without affecting the original
- **Persistent storage**: Checkpoints write to `*.ckpt` directories as JSON files (`turn-<n>.json`), enabling crash recovery and branch persistence
- **Multiple interfaces**: The branching system is accessible via CLI ([`rewind.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/rewind.go)), HTTP API ([`serve.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/serve.go)), and direct Go API calls

## Frequently Asked Questions

### What data is stored in each checkpoint file?

Each checkpoint file contains the turn number, start time, user prompt, message index boundary, and a complete snapshot of all files in their pre-edit state. These are serialized as `FileSnap` structures in [`checkpoint.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/checkpoint.go) and persisted as JSON files within the session's checkpoint directory.

### Can I fork a conversation from an in-memory session?

No. The `forkNamed` implementation explicitly validates that the session must have a persistent checkpoint directory on disk. In-memory-only sessions lack the stored state required to initialize a new branch, making forking impossible for ephemeral sessions.

### How does forking differ from rewinding?

Rewinding modifies the current session by restoring file contents and truncating the message history to a previous point, effectively erasing subsequent turns. Forking creates a completely new session that starts from a previous turn's state while preserving the original session intact, allowing both timelines to diverge independently.

### Where are checkpoint files physically stored?

Checkpoint files reside in a directory named `<session>.ckpt/` within the configured storage path. Each turn generates a separate JSON file (`turn-<n>.json`), making it trivial to reload session history after crashes or to inspect the evolution of file states across the conversation.