---
title: "File Checkpointing — Rewind File Changes"
aliases: [checkpointing, rewind-files, file-rewind]
tags: [agent-sdk, checkpointing, sessions, file-management, python, typescript]
sources: [raw/Rewind file changes with checkpointing.md]
created: 2026-04-17
updated: 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:

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

TypeScript equivalent:
```typescript
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

```python
# 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)
```python
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.

```python
@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)

## Related

- [[wiki/agent-sdk/agent-loop|Agent Loop]] — how turns, sessions, and context management work
- [[wiki/agent-sdk/configure-permissions|Configure Permissions]] — control which tools fire and how edits are approved
- [[wiki/agent-sdk/python-api-reference|Python API Reference]] — full `ClaudeAgentOptions` and `rewind_files()` docs
- [[wiki/agent-sdk/typescript-api-reference|TypeScript API Reference]] — full `query()` and `rewindFiles()` docs
- [[wiki/agent-sdk/sdk-hooks|SDK Hooks]] — intercept tool use before/after file writes

## Sources

- `raw/Rewind file changes with checkpointing.md`
- Original: https://code.claude.com/docs/en/agent-sdk/file-checkpointing
