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

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. 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 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 provides the rewind fork <turn> command, which parses arguments and invokes the controller's forking logic. The 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):

$ 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:

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:

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

Programmatic Forking in 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 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, 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), HTTP API (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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →