Skip to main content

Shadow Git Checkpointing

The Checkpoints feature provides file-level undo/restore capabilities using a shadow git repository. This enables automatic checkpointing before file modifications, allowing you to rewind to any previous state.

Quick Start

Agent-Centric Usage

from praisonaiagents import Agent
from praisonaiagents.checkpoints import CheckpointService

# Create checkpoint service
checkpoints = CheckpointService(workspace_dir="./my_project")

# Agent with checkpoints - auto-saves before file modifications
agent = Agent(
    name="RefactorBot",
    instructions="You are a code refactoring assistant.",
    checkpoints=checkpoints
)

# Checkpoints are saved automatically during agent operations
agent.start("Refactor the codebase to improve readability")

# Access checkpoints via agent
# await agent.checkpoints.restore(checkpoint_id)
# diff = await agent.checkpoints.diff()

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

CLI Commands

# Save a checkpoint
praisonai checkpoint save "Before major changes"

# List all checkpoints
praisonai checkpoint list

# Show diff from last checkpoint
praisonai checkpoint diff

# Show diff between specific checkpoints
praisonai checkpoint diff abc123 def456

# Restore to a checkpoint
praisonai checkpoint restore abc123

# Delete all checkpoints
praisonai checkpoint delete

Configuration

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

@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

@dataclass
class CheckpointDiff:
    from_checkpoint: str
    to_checkpoint: Optional[str]  # None = working directory
    files: List[FileDiff]
    total_additions: int
    total_deletions: int

Best Practices

  1. Checkpoint before major changes - Save before refactoring or large edits
  2. Use descriptive messages - Makes it easier to find the right checkpoint
  3. Don’t checkpoint too frequently - Balance between safety and storage
  4. Clean up old checkpoints - Use delete when no longer needed
  5. Check diff before restore - Verify you’re restoring to the right state

Low-level API Reference

CheckpointService Direct Usage

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:
success = await service.initialize()

save(message, allow_empty=False)

Save a checkpoint:
result = await service.save("Checkpoint message")

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

restore(checkpoint_id)

Restore to a checkpoint:
result = await service.restore("abc123")

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

diff(from_id=None, to_id=None)

Get diff between checkpoints:
# 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:
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:
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