obsidian/wiki/agent-sdk/file-checkpointing.md
2026-04-17 13:07:55 +01:00

5.2 KiB

title aliases tags sources created updated
File Checkpointing — Rewind File Changes
checkpointing
rewind-files
file-rewind
agent-sdk
checkpointing
sessions
file-management
python
typescript
raw/Rewind file changes with checkpointing.md
2026-04-17 2026-04-17

File Checkpointing — Rewind File Changes

File checkpointing tracks modifications made through the Write, Edit, and NotebookEdit tools during an agent session, allowing you to restore files to any prior state.

What Gets Tracked

Tool Tracked?
Write Yes
Edit Yes
NotebookEdit Yes
Bash (echo >, sed -i, etc.) No

The checkpoint system records:

  • Files created during the session (deleted on rewind)
  • Files modified during the session (content restored on rewind)
  • The original content of each modified file

Rewinding restores files on disk only — conversation history and context remain intact.

Setup

Enable checkpointing in options and add replay-user-messages to receive checkpoint UUIDs in the stream:

options = ClaudeAgentOptions(
    enable_file_checkpointing=True,
    permission_mode="acceptEdits",
    extra_args={"replay-user-messages": None},  # Required for UUIDs
)

TypeScript equivalent:

const options = {
  enableFileCheckpointing: true,
  permissionMode: "acceptEdits",
  extraArgs: { "replay-user-messages": null },
}

How It Works

  1. Run a session — each UserMessage in the stream carries a uuid (checkpoint ID)
  2. Capture the UUID(s) and the session's session_id from ResultMessage
  3. To rewind: resume the session with an empty prompt, call rewind_files() / rewindFiles() inside the loop, then break
# Resume and rewind
async with ClaudeSDKClient(
    ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)
) as client:
    await client.query("")           # Empty prompt opens the connection
    async for message in client.receive_response():
        await client.rewind_files(checkpoint_id)
        break

Common Patterns

Keep Only the Latest Checkpoint (Safe Rollback)

safe_checkpoint = None

async for message in client.receive_response():
    if isinstance(message, UserMessage) and message.uuid:
        safe_checkpoint = message.uuid   # Overwrite — keep latest only

    if your_revert_condition and safe_checkpoint:
        await client.rewind_files(safe_checkpoint)
        break

Multiple Restore Points (Turn-Granular Undo)

Store every UUID with metadata; rewind to any specific turn after the session ends.

@dataclass
class Checkpoint:
    id: str
    description: str
    timestamp: datetime

checkpoints = []
async for message in client.receive_response():
    if isinstance(message, UserMessage) and message.uuid:
        checkpoints.append(Checkpoint(
            id=message.uuid,
            description=f"After turn {len(checkpoints) + 1}",
            timestamp=datetime.now(),
        ))

Limitations

Limitation Detail
Bash not tracked Only Write/Edit/NotebookEdit are checkpointed
Session-scoped Checkpoints tied to the session that created them
Files only Directory create/move/delete is not undone
Local only Remote/network files are not tracked

Troubleshooting

Error Cause Fix
rewindFiles() not available Old SDK version pip install --upgrade claude-agent-sdk
message.uuid is undefined replay-user-messages not set Add extra_args={"replay-user-messages": None}
"No file checkpoint found for message" Checkpointing not enabled on original session, or session not completed Set enable_file_checkpointing=True on original session; fully complete before resuming
"ProcessTransport is not ready for writing" Called rewind_files() after loop ended Resume session with empty prompt, call rewind inside the new loop

Key Takeaways

  • Enable with enable_file_checkpointing=True + extra_args={"replay-user-messages": None}
  • Checkpoint UUIDs come from UserMessage.uuid in the response stream; session ID from ResultMessage.session_id
  • Rewinding requires resuming the session — you can't rewind in a closed connection
  • Only Write/Edit/NotebookEdit changes are tracked; Bash file changes bypass the system entirely
  • Conversation context is not rewound — only files on disk
  • Two main patterns: single rolling checkpoint (last safe state) vs. array of checkpoints (granular undo)

Sources