# How the Checkpoint Navigation System in Roo Code Works: Task History and Resumption

> Explore Roo Code's checkpoint navigation system to save, navigate, and restore task states using lightweight Git checkpoints. Rewind your workspace and message history without altering your main Git repo.

- Repository: [Roo Code/Roo-Code](https://github.com/RooCodeInc/Roo-Code)
- Tags: internals
- Published: 2026-04-26

---

**Roo Code’s checkpoint navigation system creates lightweight Git checkpoints in a hidden shadow repository, allowing you to save, navigate, and restore task states by rewinding both the workspace and message history without affecting your actual Git repository.**

The checkpoint navigation system in Roo Code enables safe experimentation by capturing task states as recoverable snapshots. Implemented in the RooCodeInc/Roo-Code repository, this feature uses an isolated Git-based architecture defined in [`src/services/checkpoints/ShadowCheckpointService.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/services/checkpoints/ShadowCheckpointService.ts) to track changes without polluting your project's version control history, making task resumption reliable and transparent.

## Architecture Overview

The system centers on the **`ShadowCheckpointService`** class, an abstract service that manages a per-task shadow Git repository. Concrete implementations like **`RepoPerTaskCheckpointService`** handle lifecycle instantiation through a static `create` method that accepts `CheckpointServiceOptions` (task ID, workspace path, and global storage location).

Key components include:

- **`getCheckpointService`** in [`src/core/checkpoints/index.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/checkpoints/index.ts): Lazily initializes the service, handles Git availability checks, and manages UI warnings during initialization timeouts.
- **`checkpointSave`**, **`checkpointRestore`**, and **`checkpointDiff`**: Public API functions in [`src/core/checkpoints/index.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/checkpoints/index.ts) that coordinate between the UI and shadow repository, automatically handling logging and telemetry.
- **Event-driven updates**: The service emits `"initialize"`, `"checkpoint"`, and `"restore"` events. Listeners registered in [`index.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/index.ts) (around lines 65-90) update the webview and emit `checkpoint_saved` chat messages.

## Shadow Repository Creation

Each task receives an isolated shadow repository stored in global storage at `<globalStorage>/checkpoints/<hash>`. The initialization process in [`ShadowCheckpointService.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/ShadowCheckpointService.ts) configures your workspace as a Git worktree while keeping metadata completely separate:

```typescript
await fs.mkdir(this.checkpointsDir, { recursive: true })
const git = createSanitizedGit(this.checkpointsDir)
await git.init({ "--template": "" })
await git.addConfig("core.worktree", this.workspaceDir)
await this.stageAll(git)
const { commit } = await git.commit("initial commit", { "--allow-empty": null })
this.baseHash = commit

```

The service writes an exclusion file to `.git/info/exclude` (via `writeExcludeFile`) to keep Roo Code-specific files like `.rooignore` out of snapshots. This setup ensures all file operations occur on your actual workspace while Git data remains isolated in the shadow directory.

## Saving Checkpoints

When you invoke `checkpointSave()` or when the system auto-saves, the service stages all workspace changes—including untracked files—and commits them to the shadow repository. The implementation maintains an internal ordered array **`_checkpoints`** to track commit hashes:

```typescript
await this.stageAll(this.git)
const result = await this.git.commit(message, options?.allowEmpty ? { "--allow-empty": null } : undefined)
const fromHash = this._checkpoints.at(-1) ?? this.baseHash!
const toHash = result.commit ?? fromHash
this._checkpoints.push(toHash)
this.emit("checkpoint", { fromHash, toHash, duration, suppressMessage })

```

The `allowEmpty` option (exposed as the `force` argument in `checkpointSave`) permits creating checkpoints even when no files have changed, ensuring you can mark specific moments in the conversation history.

## Restoring Checkpoints and Task Resumption

Restoration involves more than file reversion. The **`checkpointRestore`** function in [`src/core/checkpoints/index.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/checkpoints/index.ts) coordinates three critical actions:

1. **Workspace reset**: Forces the working tree back to the target commit using `git reset --hard` and `git clean -f -d`, removing any new files created since the checkpoint.
2. **History truncation**: Removes checkpoint entries newer than the restoration point from the internal `_checkpoints` array.
3. **Message rewinding**: Discards assistant messages generated after the checkpoint by manipulating `task.clineMessages`.

```typescript
await this.git.clean("f", ["-d", "-f"])
await this.git.reset(["--hard", commitHash])
const idx = this._checkpoints.indexOf(commitHash)
if (idx !== -1) this._checkpoints = this._checkpoints.slice(0, idx + 1)
this.emit("restore", { commitHash, duration })

```

This ensures that restoring a checkpoint rewinds both your files and the conversation context to that exact moment.

## Navigating Task History

The checkpoint navigation system derives its history list from task chat messages rather than querying Git logs directly. Each successful save inserts a message with `say: "checkpoint_saved"` and `text: <commitHash>` into `task.clineMessages`.

To enumerate available checkpoints for the UI:

```typescript
const checkpoints = task.clineMessages
    .filter(m => m.say === "checkpoint_saved")
    .map(m => m.text!);   // each text is a commit hash

```

This design ensures the checkpoint history remains synchronized with the conversation timeline visible in the UI, using the message history as the single source of truth for navigation.

## Diffing Checkpoints

The **`checkpointDiff`** function generates comparisons between any two checkpoints or between a checkpoint and the current workspace. `ShadowCheckpointService.getDiff` stages current changes temporarily to compute the diff using `git.diffSummary` and `git.show`, then presents results using VS Code's native diff view via `vscode.changes`, showing files side-by-side.

## Error Handling and Safety Measures

The system includes several safeguards:

- **Git availability**: If Git isn't installed, checkpoints are disabled and the UI displays a warning via the webview.
- **Nested repository detection**: The `getNestedGitRepository` check disables checkpoints when nested Git repositories are detected to prevent corruption.
- **Initialization timeouts**: Slow shadow repository creation triggers a `checkpointInitWarning` message to the webview while the operation continues asynchronously.

## Implementation Example

Here is a complete workflow demonstrating the checkpoint navigation system API:

```typescript
import { checkpointSave, checkpointRestore, checkpointDiff } from "./core/checkpoints";

// Save a checkpoint (force empty commit if you want)
await checkpointSave(task, /*force=*/false, /*suppressMessage=*/false);

// List saved checkpoints (hashes) – UI typically does this:
const savedHashes = task.clineMessages
  .filter(m => m.say === "checkpoint_saved")
  .map(m => m.text!);

// Restore a previous checkpoint (e.g., the first one)
await checkpointRestore(task, {
  ts: task.clineMessages[0].ts,   // timestamp of the checkpoint_saved message
  commitHash: savedHashes[0],
  mode: "restore",                // actually revert workspace & task state
});

// Show a diff between two checkpoints
await checkpointDiff(task, {
  commitHash: savedHashes[1],
  previousCommitHash: savedHashes[0],
  mode: "checkpoint",   // diff current → next checkpoint
});

```

All three functions are thin wrappers around the shadow-repo service; they handle service creation, logging, telemetry, and UI notifications automatically.

## Summary

- Roo Code's checkpoint navigation system uses **isolated shadow Git repositories** to snapshot task states without affecting project history, stored under global storage at `<globalStorage>/checkpoints/<hash>`.
- The **`ShadowCheckpointService`** class in [`src/services/checkpoints/ShadowCheckpointService.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/services/checkpoints/ShadowCheckpointService.ts) manages repository initialization, commits, and restorations using `core.worktree` to target your actual workspace.
- High-level APIs in **[`src/core/checkpoints/index.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/checkpoints/index.ts)** provide `checkpointSave`, `checkpointRestore`, and `checkpointDiff` functions that handle UI integration and message history synchronization.
- Checkpoint history is tracked via **`checkpoint_saved`** messages in `task.clineMessages`, enabling the UI to navigate the task timeline reliably.
- Restoration rewinds both the file system (via Git hard reset and clean operations) and conversation history (via message truncation), ensuring complete state resumption.

## Frequently Asked Questions

### How does Roo Code's checkpoint system avoid modifying my project's Git history?

The system creates a separate shadow repository in VS Code's global storage and configures Git's `core.worktree` setting to point at your actual workspace directory. This ensures all commits, branches, and Git metadata live in the isolated shadow directory, leaving your project's `.git` directory and history completely untouched.

### What happens to my conversation history when I restore a checkpoint?

The `checkpointRestore` function automatically truncates `task.clineMessages` to remove any assistant messages generated after the checkpoint's timestamp. This synchronizes the conversation view with the restored workspace state, effectively undoing any AI outputs and file modifications that occurred after the saved point.

### Can I create a checkpoint when there are no file changes?

Yes. The `checkpointSave` function accepts a `force` parameter that maps to Git's `--allow-empty` flag. When enabled, the system creates a checkpoint commit even with no file modifications, allowing you to mark specific decision points or conversational milestones in the task history.

### Where are the shadow repositories physically stored?

Shadow repositories are stored in your VS Code global storage directory under `checkpoints/<hash>/`, as defined in the `CheckpointServiceOptions` passed to the service factory. Each task receives its own isolated directory containing the full Git history for that specific session, completely separate from your workspace file system.