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:

ToolDescription
WriteCreates a new file or overwrites an existing file with new content
EditMakes targeted edits to specific parts of an existing file
NotebookEditModifies 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.

checkpointing-example.ts
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

1

Set the environment variable

File checkpointing requires the CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING environment variable.

export CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=1
2

Enable checkpointing in options

OptionDescription
enableFileCheckpointing: trueTracks file changes for rewinding
extraArgs: { 'replay-user-messages': null }Required to receive checkpoint UUIDs
3

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.

4

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.

risky-operations.ts
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.

multiple-checkpoints.ts
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

LimitationDescription
Write/Edit/NotebookEdit tools onlyChanges made through Bash commands are not tracked
Same sessionCheckpoints are tied to the session that created them
File content onlyCreating, moving, or deleting directories is not undone by rewinding
Local filesRemote 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