> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Checkpoints

> File-level undo and restore using shadow git snapshots before agent edits

Save and rewind workspace snapshots before agents change files — powered by a shadow git repository.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(name="coder", instructions="Edit project files safely.")
agent.start("Refactor the auth module.")
```

The user runs an agent that edits files; checkpoints snapshot the workspace so you can diff or restore before bad changes land.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Agent[🤖 Agent run] --> Save[📸 Auto checkpoint]
    Save --> Work[📝 File edits]
    Work --> Restore[⏪ Restore / diff]
    Restore --> Agent

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef tool fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff
    classDef agent fill:#8B0000,color:#fff
    classDef tool fill:#189AB4,color:#fff
    class Agent agent
    class Save,Work tool
    class Restore ok
```

## Quick Start

<Steps>
  <Step title="Attach checkpoints to an agent">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent
    from praisonaiagents.checkpoints import CheckpointService

    checkpoints = CheckpointService(workspace_dir="./my_project")
    agent = Agent(
        name="RefactorBot",
        instructions="You are a code refactoring assistant.",
        checkpoints=checkpoints,
    )
    agent.start("Refactor the codebase to improve readability")
    ```
  </Step>

  <Step title="Save and restore from CLI">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai checkpoint save "Before major changes"
    praisonai checkpoint list
    praisonai checkpoint restore last
    ```
  </Step>

  <Step title="One-liner undo after a run">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai run agents.yaml
    praisonai run --restore last
    ```
  </Step>
</Steps>

## Overview

Checkpoints allow you to:

* **Save** snapshots of your workspace before changes
* **Restore** files to any previous checkpoint
* **Diff** between checkpoints to see what changed
* **Track** all file modifications made by agents

## In-session `/undo` and `/revert`

When `praisonai code --checkpoints` is active, the coding REPL gains turn-aware undo and revert commands.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant REPL as code REPL
    participant CP as Checkpoint Manager
    participant Store as Session Store

    User->>REPL: [starts session with --checkpoints]
    REPL->>CP: baseline checkpoint
    User->>REPL: prompt → edits files
    REPL->>CP: checkpoint_turn(message_count=N)
    User->>REPL: /undo
    REPL->>CP: preview(1)
    CP-->>REPL: diff + dropped_message_count
    REPL->>CP: revert(1)
    CP-->>REPL: workspace restored
    CP->>Store: revert_to_message(N)
    Store-->>CP: chat_history truncated
    CP-->>REPL: ready

    classDef user fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef repl fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef cp fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef store fill:#6366F1,stroke:#7C90A0,color:#fff

    class User user
    class REPL repl
    class CP cp
    class Store store
```

**`/undo` mode comparison:**

| Mode                                                                        | What `/undo` does                                                                                                                                                                    |
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Checkpointing **off** (default)                                             | Removes the last assistant + user message pair from history only. Workspace files are untouched.                                                                                     |
| Checkpointing **on**, session store **not wired**                           | Restores workspace files to the previous turn's snapshot. Conversation history is left intact. (Legacy / file-only fallback.)                                                        |
| Checkpointing **on**, session store **wired** (default in `praisonai code`) | Restores workspace files **and** rewinds `chat_history` to the message count captured at `checkpoint_turn()`, so the agent's memory matches the workspace. Diff preview shown first. |

<Note>
  Revert is best-effort. A file restore failure skips the conversation rewind. A conversation-revert failure leaves the already-restored files intact — you can retry from a clean workspace state.
</Note>

**Preview reports dropped-message count.** `preview(n)` now returns `dropped_message_count` alongside the file diff, so the CLI can show how many chat turns would be discarded before you confirm. If the session store is not wired in, `dropped_message_count` is `None`.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
preview = manager.preview(1)
print(preview.dropped_message_count)   # 3 → messages that would be truncated
```

**`/revert [n]`** rolls back `n` turns (default 1). After revert, the timeline drops the restored turns so the next `/undo` walks further back.

**Project config:**

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# agents.yaml
checkpoints:
  auto: true
  storage_dir: ./.praisonai/checkpoints   # optional
```

**Env override:** `PRAISONAI_CHECKPOINTS=on` (or `off`).

**Precedence:** `PRAISONAI_CHECKPOINTS` (env) > `checkpoints.auto` (config) > default (off).

***

## CLI Commands

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Save a checkpoint (--allow-empty to snapshot even with no changes)
praisonai checkpoint save "Before major changes"
praisonai checkpoint save "Before major changes" --allow-empty

# List checkpoints (newest first; -n to limit)
praisonai checkpoint list
praisonai checkpoint list -n 10

# Show diff — accepts last/latest, full id, short id, or unique prefix
praisonai checkpoint diff
praisonai checkpoint diff last
praisonai checkpoint diff abc12345 def67890

# Restore to a checkpoint
praisonai checkpoint restore last
praisonai checkpoint restore abc12345

# Delete all checkpoints (-y to skip confirm prompt)
praisonai checkpoint delete
praisonai checkpoint delete --yes

# All subcommands accept -w to target a specific workspace directory
praisonai checkpoint list -w /path/to/project
praisonai checkpoint restore last -w /path/to/project
```

<Note>
  One-liner undo after a bad `praisonai run`: `praisonai run --restore last`. See [Run — Checkpoint & Rewind](/docs/cli/run) for details.
</Note>

## Automatic Checkpoints with `praisonai run`

`praisonai run` snapshots your workspace automatically before every YAML-file run.

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Project config — opt out per project
checkpoints:
  auto: false
```

* **Default:** `true` — automatic checkpoints are on for all YAML-file runs.
* **Scoped to YAML runs:** plain-prompt runs (`praisonai run "…"`) are skipped.
* **Workspace:** the directory of the target YAML file, not the cwd.
* **Label:** `run:<run_id>` (or `"auto checkpoint before run"` as a fallback).
* **Best-effort:** failures are swallowed and never block the run.
* **Per-run override:** `praisonai run agents.yaml --no-checkpoint`.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai run agents.yaml            # auto-checkpoint, then run
praisonai run --restore last         # rewind workspace, exit
praisonai run agents.yaml --no-checkpoint   # skip auto-checkpoint
```

## Configuration

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.checkpoints import CheckpointService

service = CheckpointService(
    workspace_dir="/path/to/project",
    storage_dir="~/.praisonai/checkpoints",
    enabled=True,
    auto_checkpoint=True,
    max_checkpoints=100
)
```

**Parameters:**

* `workspace_dir`: Directory to track
* `storage_dir`: Where to store checkpoint data (default: `~/.praisonai/checkpoints`)
* `enabled`: Enable/disable checkpoints
* `auto_checkpoint`: Auto-checkpoint before file modifications
* `max_checkpoints`: Maximum checkpoints to keep

## Data Types

### Checkpoint

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
@dataclass
class Checkpoint:
    id: str           # Full commit hash
    short_id: str     # Short hash (8 chars)
    message: str      # Checkpoint message
    timestamp: datetime
    files_changed: int
    insertions: int
    deletions: int
```

### CheckpointDiff

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
@dataclass
class CheckpointDiff:
    from_checkpoint: str
    to_checkpoint: Optional[str]  # None = working directory
    files: List[FileDiff]
    total_additions: int
    total_deletions: int
```

## Best Practices

<AccordionGroup>
  <Accordion title="Checkpoint before major refactors">
    Save with a descriptive message before large edits so restore targets are obvious in `checkpoint list`.
  </Accordion>

  <Accordion title="Diff before restore">
    Run `praisonai checkpoint diff last` to confirm you are rewinding to the right snapshot.
  </Accordion>

  <Accordion title="Cap stored checkpoints">
    Set `max_checkpoints` on `CheckpointService` to avoid unbounded shadow-git growth.
  </Accordion>

  <Accordion title="Use --no-checkpoint for throwaway runs">
    Skip auto-checkpoints on YAML runs when you know the workspace is disposable.
  </Accordion>

  <Accordion title="Prefer /undo over /clear after a bad edit">
    With the session store wired in, `/undo` rewinds files **and** chat history to the same turn boundary, so the agent's memory stays consistent with the workspace. `/clear` only truncates history and leaves reverted edits invisible to the agent.
  </Accordion>
</AccordionGroup>

***

## Low-level API Reference

### CheckpointService Direct Usage

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.checkpoints import CheckpointService

# Create checkpoint service
service = CheckpointService(
    workspace_dir="/path/to/project",
    storage_dir="~/.praisonai/checkpoints"
)

# Initialize
await service.initialize()

# Save a checkpoint
result = await service.save("Before refactoring")
print(f"Saved: {result.checkpoint.short_id}")

# Make changes...

# Restore if needed
await service.restore(result.checkpoint.id)

# View diff
diff = await service.diff()
```

### Methods

#### initialize()

Initialize the checkpoint service:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
success = await service.initialize()
```

#### save(message, allow\_empty=False, quiet=False)

Save a checkpoint:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
result = await service.save("Checkpoint message")

if result.success:
    print(f"Saved: {result.checkpoint.short_id}")
else:
    print(f"Error: {result.error}")
```

| Parameter     | Type   | Default | Description                                          |
| ------------- | ------ | ------- | ---------------------------------------------------- |
| `message`     | `str`  | —       | Checkpoint message                                   |
| `allow_empty` | `bool` | `False` | Allow saving even when no files changed              |
| `quiet`       | `bool` | `False` | Suppress output (used by machine-readable run modes) |

#### restore(checkpoint\_id)

Restore to a checkpoint:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
result = await service.restore("abc123")

if result.success:
    print("Restored successfully")
```

#### diff(from\_id=None, to\_id=None)

Get diff between checkpoints:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Diff from last checkpoint to current
diff = await service.diff()

# Diff between specific checkpoints
diff = await service.diff("abc123", "def456")

for file in diff.files:
    print(f"{file.status}: {file.path} (+{file.additions}/-{file.deletions})")
```

#### list\_checkpoints(limit=50)

List all checkpoints:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
checkpoints = await service.list_checkpoints(limit=20)

for cp in checkpoints:
    print(f"{cp.short_id} - {cp.message} ({cp.timestamp})")
```

### Event Handlers

Subscribe to checkpoint events:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.checkpoints import CheckpointEvent

def on_checkpoint(checkpoint):
    print(f"Checkpoint created: {checkpoint.short_id}")

service.on(CheckpointEvent.CHECKPOINT_CREATED, on_checkpoint)
service.on(CheckpointEvent.CHECKPOINT_RESTORED, lambda cp: print(f"Restored: {cp.short_id}"))
service.on(CheckpointEvent.ERROR, lambda e: print(f"Error: {e['error']}"))
```

## Zero Performance Impact

The checkpoint system is designed for minimal overhead:

* **Lazy loading**: All imports via `__getattr__`
* **Async operations**: Non-blocking git operations
* **Incremental commits**: Only changed files are tracked
* **Configurable limits**: Control max checkpoints to manage storage

***

## Related

<CardGroup cols={2}>
  <Card icon="terminal" href="/features/cli" title="CLI">
    `praisonai checkpoint` and `praisonai run --restore` commands.
  </Card>

  <Card icon="play" href="/features/code" title="Code Execution">
    Agents that edit files benefit most from automatic checkpoints.
  </Card>

  <Card icon="folder" href="/features/context-files" title="Context Files">
    Pair workspace snapshots with project context files.
  </Card>

  <Card icon="rotate" href="/features/selfreflection" title="Self-Reflection">
    Rewind bad reflection loops with a saved checkpoint.
  </Card>
</CardGroup>
