Rewind file changes with checkpointing changedagent-sdk/file-checkpointing
Nearest release: v2.1.285, published an hour before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 29 Sep 2026 19:08 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 29 Sep 2026 19:37 UTC.
Upstream edited
Recorded here
Lines+7added
Lines−126removed
From line
2
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits9to this page, all time
The whole hunk
from line 2, old and new numbered
/
from line 2
22
33> Track file changes during agent sessions and restore files to any previous state
44
5File 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. Want to try it out? Jump to the [interactive example](#try-it-out).
5File checkpointing tracks file modifications made through the [Write](/docs/en/tools-reference#write-tool-behavior), [Edit](/docs/en/tools-reference#edit-tool-behavior), and [NotebookEdit](/docs/en/tools-reference#notebookedit-tool-behavior) tools during an agent session, allowing you to rewind files to any previous state. To watch a rewind restore a file, jump to the [interactive example](#try-it-out).
66
7With checkpointing, you can:
8
9* **Undo unwanted changes** by restoring files to a known good state
10* **Explore alternatives** by restoring to a checkpoint and trying a different approach
11* **Recover from errors** when the agent makes incorrect modifications
12
137<Warning>
148 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, and neither are edits a [subagent](/docs/en/agent-sdk/subagents) applies, except a [skill with `context: fork`](/docs/en/skills#run-skills-in-a-subagent) that runs in the foreground.
159</Warning>
from line 22
2822
2923To use file checkpointing, enable it in your options, capture checkpoint UUIDs from the response stream, then call `rewindFiles()` (TypeScript) or `rewind_files()` (Python) when you need to restore.
3024
31The following example shows the complete flow: enable checkpointing, capture the checkpoint UUID and session ID from the response stream, then resume the session later to rewind files. Each step is explained in detail below. The examples in this section use the prompt "Refactor the authentication module". Run them in a project that contains an authentication module, or change the prompt to name files that exist in your project, so you can watch files change and see the rewind restore them.
25The examples in this section use the prompt "Refactor the authentication module". Run them in a project that contains an authentication module, or change the prompt to name files that exist in your project, so you can watch files change and see the rewind restore them.
3226
27This example enables checkpointing, captures the checkpoint UUID and session ID from the response stream, then resumes the session later to rewind files. The example's numbered comments match the steps that follow.
28
3329<CodeGroup>
3430 ```python Python theme={null}
3531 import asyncio
from line 141
145141 | Enable checkpointing | `enable_file_checkpointing=True` | `enableFileCheckpointing: true` | Tracks file changes for rewinding |
146142 | Receive checkpoint UUIDs | `extra_args={"replay-user-messages": None}` | `extraArgs: { 'replay-user-messages': null }` | Required to get user message UUIDs in the stream |
147143
148 <CodeGroup>
149 ```python Python theme={null}
150 options = ClaudeAgentOptions(
151 enable_file_checkpointing=True,
152 permission_mode="acceptEdits",
153 extra_args={"replay-user-messages": None},
154 )
155
156 async with ClaudeSDKClient(options) as client:
157 await client.query("Refactor the authentication module")
158 ```
159
160 ```typescript TypeScript theme={null}
161 const response = query({
162 prompt: "Refactor the authentication module",
163 options: {
164 enableFileCheckpointing: true,
165 permissionMode: "acceptEdits" as const,
166 extraArgs: { "replay-user-messages": null }
167 }
168 });
169 ```
170 </CodeGroup>
144 The lead example under [Implement checkpointing](#implement-checkpointing) also sets the permission mode to `acceptEdits`, which approves the agent's file edits without a prompt. For more information, see [Permission modes](/docs/en/agent-sdk/permissions#permission-modes).
171145 </Step>
172146
173147 <Step title="Capture checkpoint UUID and session ID">
from line 150
176150 For most use cases, capture the first user message UUID (`message.uuid`); rewinding to it restores the tracked files to their original state. To store multiple checkpoints and rewind to intermediate states, see [Multiple restore points](#multiple-restore-points).
177151
178152 Capturing the session ID (`message.session_id`) is optional; you only need it if you want to rewind later, after the stream completes. If you're calling `rewindFiles()` immediately while still processing messages (as the example in [Checkpoint before risky operations](#checkpoint-before-risky-operations) does), you can skip capturing the session ID.
179
180 <CodeGroup>
181 ```python Python theme={null}
182 checkpoint_id = None
183 session_id = None
184
185 async for message in client.receive_response():
186 # Capture the first user message UUID as the checkpoint
187 if isinstance(message, UserMessage) and message.uuid and checkpoint_id is None:
188 checkpoint_id = message.uuid
189 # Capture session ID from the result message
190 if isinstance(message, ResultMessage):
191 session_id = message.session_id
192 ```
193
194 ```typescript TypeScript theme={null}
195 let checkpointId: string | undefined;
196 let sessionId: string | undefined;
197
198 for await (const message of response) {
199 // Capture the first user message UUID as the checkpoint
200 if (message.type === "user" && message.uuid && !checkpointId) {
201 checkpointId = message.uuid;
202 }
203 // Capture session ID from any message that has it
204 if ("session_id" in message) {
205 sessionId = message.session_id;
206 }
207 }
208 ```
209 </CodeGroup>
210153 </Step>
211154
212155 <Step title="Rewind files">
213 To rewind after the stream completes, resume the session with an empty prompt and call `rewind_files()` (Python) or `rewindFiles()` (TypeScript) with your checkpoint UUID. You can also rewind during the stream; see [Checkpoint before risky operations](#checkpoint-before-risky-operations) for that pattern.
156 To rewind after the stream completes, resume the session with an empty prompt and call `rewind_files()` (Python) or `rewindFiles()` (TypeScript) with your checkpoint UUID. Enable checkpointing on the resumed session's options too, and call rewind from inside the response loop. You can also rewind during the stream. See [Checkpoint before risky operations](#checkpoint-before-risky-operations) for that pattern.
214157
215 <CodeGroup>
216 ```python Python theme={null}
217 async with ClaudeSDKClient(
218 ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)
219 ) as client:
220 await client.query("") # Empty prompt to open the connection
221 async for message in client.receive_response():
222 if checkpoint_id:
223 await client.rewind_files(checkpoint_id)
224 break
225 ```
226
227 ```typescript TypeScript theme={null}
228 const rewindQuery = query({
229 prompt: "", // Empty prompt to open the connection
230 options: { ...opts, resume: sessionId }
231 });
232
233 for await (const msg of rewindQuery) {
234 if (checkpointId) {
235 await rewindQuery.rewindFiles(checkpointId);
236 }
237 break;
238 }
239 ```
240 </CodeGroup>
241
242158 If you capture the session ID and checkpoint ID, you can also rewind from the CLI. This command requires the `claude` executable, which comes from [installing Claude Code](/docs/en/setup). The SDK enables checkpointing for you, but when you run `claude -p` directly you must set the `CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING` environment variable:
243159
244160 ```bash theme={null}
from line 669
753669
754670This error occurs when you call `rewindFiles()` or `rewind_files()` after you've finished iterating through the response. The connection to the CLI process closes when the loop completes.
755671
756**Solution**: Resume the session with an empty prompt, then call rewind on the new query:
757
758<CodeGroup>
759 ```python Python theme={null}
760 # Resume session with empty prompt, then rewind
761 async with ClaudeSDKClient(
762 ClaudeAgentOptions(enable_file_checkpointing=True, resume=session_id)
763 ) as client:
764 await client.query("")
765 async for message in client.receive_response():
766 if checkpoint_id:
767 await client.rewind_files(checkpoint_id)
768 break
769 ```
770
771 ```typescript TypeScript theme={null}
772 // Resume session with empty prompt, then rewind
773 const rewindQuery = query({
774 prompt: "",
775 options: { ...opts, resume: sessionId }
776 });
777
778 try {
779 for await (const msg of rewindQuery) {
780 if (checkpointId) {
781 await rewindQuery.rewindFiles(checkpointId);
782 }
783 break;
784 }
785 } catch (error) {
786 // An error here means the rewind didn't complete, for example the checkpoint
787 // wasn't found or the session couldn't be resumed.
788 console.error(`Rewind session ended with an error: ${error}`);
789 }
790 ```
791</CodeGroup>
672**Solution**: Resume the session with an empty prompt, then call rewind on the new query. The lead example under [Implement checkpointing](#implement-checkpointing) shows the resume-and-rewind call in both languages, at the comment marked Step 3.
792673
793674## Next steps
794675
No line in this hunk matches that.