How the Checkpoint and Rewind System Works Without Git in DeepSeek-Reasonix
DeepSeek-Reasonix implements a snapshot-based checkpoint system that captures file states and conversation boundaries in JSON files before each edit, enabling full restoration of code and chat history without Git commands or repository initialization.
The DeepSeek-Reasonix agent provides a git-free checkpoint and rewind system that persists session state using minimal JSON snapshots rather than repository commits. This allows users to roll back both code files and conversation history to any previous turn, even in directories that have never been initialized with Git. The system operates through three coordinated components: a snapshot store for file content, turn-boundary tracking for conversation state, and an orchestration layer that handles restoration logic.
Core Architecture of the Snapshot System
The checkpoint system rests on three pillars that work together to provide atomic rollback capabilities without version control dependencies.
The Checkpoint Store
At internal/checkpoint/checkpoint.go, the Store struct manages persistence of file snapshots. Each turn generates a new JSON file (turn-<n>.json) in a *.ckpt/ directory adjacent to the session file. The Store.Snapshot method (lines 29–55) captures the pre-edit content of every file before modifications occur, storing data in a FileSnap struct that preserves the original encoding and content.
Turn Boundaries for Conversation Rewind
The system tracks conversation state through message indices stored in checkpoint metadata. When a turn begins, Controller.beginCheckpoint in control/controller.go records the current message count (MsgIndex) in the checkpoint. This boundary marker allows the system to truncate the in-memory message log to the exact length it had at the start of any historical turn.
Rewind Orchestration
The Controller.Rewind method in control/controller.go (lines 1560–1595) coordinates the restoration process. It accepts a target turn number and a RewindScope (RewindCode, RewindConversation, or RewindBoth), then executes the appropriate restoration logic without invoking external version control commands.
How Checkpoints Are Created
Checkpoints are generated automatically through a pre-edit hook mechanism that intercepts file changes before they reach the filesystem.
The Pre-Edit Hook
When the controller initializes, it installs a hook via c.executor.SetPreEditHook in control/controller.go:
c.executor.SetPreEditHook(func(ch diff.Change) {
c.checkpoints.snapshot(ch)
})
This hook fires for every file modification, forwarding a diff.Change struct containing the file path, change kind, and original content to the checkpoint manager.
Snapshot Deduplication and Persistence
The checkpointManager delegates to Store.Snapshot, which performs several critical operations under a mutex lock:
- Path validation: Ignores empty paths
- Encoding detection: Preserves the original file encoding (unless the file is new)
- Deduplication: Uses a
seenmap to ensure only the first change to a file in a given turn is recorded - Content capture: Stores the old content (or
nilfor new files) in aFileSnap
The resulting checkpoint persists to disk as atomic JSON, ensuring that corruption of one checkpoint never affects others.
The Rewind Process
Rewinding involves three coordinated steps that restore the workspace to a previous state while maintaining session integrity.
Parsing Rewind Requests
User commands flow through parseRewind in control/controller.go (lines 3066–3100), which converts string arguments or HTTP JSON payloads into structured targets:
func parseRewind(args string, cps []checkpoint.Meta) (int, RewindScope, error) {
// Defaults to latest checkpoint with RewindBoth scope
// Validates turn numbers and scope strings
}
Restoring Code Snapshots
When RewindCode or RewindBoth is requested, Store.RestoreCode walks the checkpoint history to find the earliest snapshot for each modified path at or after the target turn. The restoration logic handles two cases:
- Existing files: Writes back the captured content using the original encoding
- New files: Removes files that did not exist at the target turn (indicated by
nilcontent in the snapshot)
Truncating Conversation History
For conversation rewinds, the system retrieves the stored MsgIndex from the checkpoint manager's boundary map. The Controller.truncateHistory method then slices the session's message array to this index, effectively removing all messages from subsequent turns. Finally, checkpointManager.truncateFrom renumbers future turn counters and cleans up stale boundaries.
Using the Checkpoint System
DeepSeek-Reasonix exposes checkpoint functionality through multiple interfaces: CLI commands, HTTP endpoints, and direct Go API calls.
CLI Usage
The desktop and terminal interfaces accept rewind commands:
# Restore both code and conversation to turn 2
reasonix /rewind 2
# Restore only code state, keep conversation history
reasonix /rewind 3 code
# Restore only conversation, keep current files
reasonix /rewind 5 conversation
# Shortcut to latest checkpoint with both scopes
reasonix /rewind
HTTP API
The server implementation in internal/serve/serve.go (lines 610–632) exposes a REST endpoint:
curl -X POST http://localhost:8080/rewind \
-H "Content-Type: application/json" \
-d '{"turn":4,"scope":"both"}'
The handler unmarshals the request and forwards it to Controller.Rewind:
func (s *Server) rewind(w http.ResponseWriter, r *http.Request) {
var body struct { Turn int; Scope string }
json.NewDecoder(r.Body).Decode(&body)
// Scope parsing logic...
if err := s.ctl().Rewind(body.Turn, scope); err != nil {
// Error handling...
}
}
Programmatic Go API
For integration with custom tools or automated testing:
c, _ := control.New(opts)
// ... execute several turns ...
err := c.Rewind(3, control.RewindBoth)
if err != nil {
log.Fatal(err)
}
Inspecting Checkpoint Metadata
The frontend retrieves checkpoint listings via Controller.Checkpoints(), which returns metadata including turn numbers, prompt excerpts, and file counts:
cps := c.Checkpoints()
for _, cp := range cps {
fmt.Printf("Turn %d – %s (%d files)\n",
cp.Turn, cp.Prompt, len(cp.Paths))
}
Summary
- DeepSeek-Reasonix implements git-free checkpoints using JSON snapshot files stored in
*.ckpt/directories rather than Git commits. - The pre-edit hook in
control/controller.gocaptures file states before modifications occur, storing them ininternal/checkpoint/checkpoint.go. - Turn boundaries track conversation length via
MsgIndex, enabling message log truncation without file system changes. - The rewind orchestrator supports three scopes (
RewindCode,RewindConversation,RewindBoth) and handles both file restoration and conversation trimming. - Multiple interfaces expose the functionality: CLI commands (
/rewind), HTTP POST requests to/rewind, and direct Go API calls toController.Rewind. - Each checkpoint is stored in an isolated JSON file (
turn-<n>.json), ensuring that corruption of one checkpoint does not affect the ability to rewind to others.
Frequently Asked Questions
Where are checkpoint files stored?
Checkpoint files are stored in a directory named <session>.ckpt/ adjacent to the session file, with each turn represented by a separate JSON file (turn-1.json, turn-2.json, etc.). This location is intentionally separate from the workspace root to avoid polluting the user's project directory, and it requires no Git initialization or .git directory.
What happens to files that were created after the target turn?
During a rewind operation, Store.RestoreCode checks the snapshot content for each file. If a file was created after the target turn, its earliest snapshot will contain nil content, signaling the system to delete the file entirely. If the file existed before the target turn, the system overwrites it with the captured pre-edit content.
Can I rewind only the conversation without changing files?
Yes. By specifying RewindConversation as the scope (or using reasonix /rewind <turn> conversation), the system truncates the message log to the stored MsgIndex boundary while leaving the current filesystem state untouched. This allows you to retry prompts against your current code without losing recent edits.
How does this system differ from using Git for version control?
Unlike Git, which requires repository initialization and creates .git directories, DeepSeek-Reasonix's system works immediately in any directory without setup. It captures pre-edit snapshots rather than post-commit diffs, stores only the files touched in a specific turn (not the entire repository), and maintains conversation state alongside code state. Additionally, checkpoints are stored as simple JSON files that can be manually inspected or deleted without risking repository corruption.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →