Chapter 14
Rewind File Changes with Checkpointing
Track file changes during agent sessions and restore files to any previous state.
File checkpointing tracks file modifications made through the Write, Edit, and NotebookEdit tools during an agent session, allowing you to rewind files to any previous state.
With checkpointing, you can:
- -Undo unwanted changes by restoring files to a known good state
- -Explore alternatives by restoring to a checkpoint and trying a different approach
- -Recover from errors when the agent makes incorrect modifications
Warning
Only changes made through the Write, Edit, and NotebookEdit tools are tracked. Changes made through Bash commands (like echo > file.txt or sed -i) are not captured by the checkpoint system.
How checkpointing works
When you enable file checkpointing, the SDK creates backups of files before modifying them through the Write, Edit, or NotebookEdit tools. User messages in the response stream include a checkpoint UUID that you can use as a restore point.
Checkpoint works with these built-in tools:
| Tool | Description |
|---|---|
Write | Creates a new file or overwrites an existing file with new content |
Edit | Makes targeted edits to specific parts of an existing file |
NotebookEdit | Modifies cells in Jupyter notebooks (.ipynb files) |
Note: File rewinding restores files on disk to a previous state. It does not rewind the conversation itself. The conversation history and context remain intact after calling rewindFiles().
The checkpoint system tracks:
- -Files created during the session
- -Files modified during the session
- -The original content of modified files
When you rewind to a checkpoint, created files are deleted and modified files are restored to their content at that point.
Implement checkpointing
To use file checkpointing, enable it in your options, capture checkpoint UUIDs from the response stream, then call rewindFiles() when you need to restore.
import { query } from "@anthropic-ai/claude-agent-sdk";
async function main() {
// Step 1: Enable checkpointing
const opts = {
enableFileCheckpointing: true,
permissionMode: "acceptEdits" as const,
extraArgs: { 'replay-user-messages': null },
env: { ...process.env, CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING: '1' }
});
const response = query({
prompt: "Refactor the authentication module",
options: opts
});
let checkpointId: string | undefined;
let sessionId: string | undefined;
// Step 2: Capture checkpoint UUID from user messages
for await (const message of response) {
if (message.type === 'user' && message.uuid && !checkpointId) {
checkpointId = message.uuid;
}
if ('session_id' in message && !sessionId) {
sessionId = message.session_id;
}
}
// Step 3: Rewind by resuming the session
if (checkpointId && sessionId) {
const rewindQuery = query({
prompt: "", // Empty prompt to open connection
options: { ...opts, resume: sessionId }
});
for await (const msg of rewindQuery) {
await rewindQuery.rewindFiles(checkpointId);
break;
}
console.log(`Rewound to checkpoint: ${checkpointId}`);
}
}
main();Implementation steps
Set the environment variable
File checkpointing requires the CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING environment variable.
export CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=1
Enable checkpointing in options
| Option | Description |
|---|---|
enableFileCheckpointing: true | Tracks file changes for rewinding |
extraArgs: { 'replay-user-messages': null } | Required to receive checkpoint UUIDs |
Capture checkpoint UUID and session ID
Each user message has a UUID that serves as a checkpoint. Capture the first one to restore all files to their original state.
Rewind files
Resume the session with an empty prompt and call rewindFiles() with your checkpoint UUID.
You can also rewind from the CLI: claude --resume <session-id> --rewind-files <checkpoint-uuid>
Common patterns
Checkpoint before risky operations
Keep only the most recent checkpoint UUID, updating it before each agent turn. If something goes wrong, immediately rewind to the last safe state.
let safeCheckpoint: string | undefined;
for await (const message of response) {
// Update checkpoint before each turn (overwrites previous)
if (message.type === 'user' && message.uuid) {
safeCheckpoint = message.uuid;
}
// Revert based on your own logic
if (yourRevertCondition && safeCheckpoint) {
await response.rewindFiles(safeCheckpoint);
break;
}
}Multiple restore points
Store all checkpoint UUIDs in an array with metadata. After the session completes, you can rewind to any previous checkpoint.
interface Checkpoint {
id: string;
description: string;
timestamp: Date;
}
const checkpoints: Checkpoint[] = [];
for await (const message of response) {
if (message.type === 'user' && message.uuid) {
checkpoints.push({
id: message.uuid,
description: `After turn ${checkpoints.length + 1}`,
timestamp: new Date()
});
}
}
// Later: rewind to any checkpoint
const target = checkpoints[0]; // Pick any checkpoint
await rewindQuery.rewindFiles(target.id);Limitations
| Limitation | Description |
|---|---|
| Write/Edit/NotebookEdit tools only | Changes made through Bash commands are not tracked |
| Same session | Checkpoints are tied to the session that created them |
| File content only | Creating, moving, or deleting directories is not undone by rewinding |
| Local files | Remote or network files are not tracked |
Troubleshooting
Checkpointing options not recognized
If enableFileCheckpointing or rewindFiles() isn't available, update to the latest SDK version.
npm install @anthropic-ai/claude-agent-sdk@latest
User messages don't have UUIDs
The replay-user-messages option isn't set.
extraArgs: { 'replay-user-messages': null }"No file checkpoint found for message" error
The environment variable CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING isn't set, or the session wasn't properly completed before attempting to resume and rewind.
"ProcessTransport is not ready for writing" error
You called rewindFiles() after iterating through the response. Resume the session with an empty prompt, then call rewind on the new query.
Next steps
- -Sessions: learn how to resume sessions, which is required for rewinding after the stream completes
- -Permissions: configure which tools Claude can use and how file modifications are approved