檔案檢查點追蹤在代理程式工作階段期間透過 Write、Edit 和 NotebookEdit 工具進行的檔案修改,允許您將檔案還原到任何先前的狀態。想要試試看嗎?跳到互動範例。
使用檢查點,您可以:
只有透過 Write、Edit 和 NotebookEdit 工具進行的變更才會被追蹤。透過 Bash 命令進行的變更(如 echo > file.txt 或 sed -i)不會被檢查點系統捕獲。
當您啟用檔案檢查點時,SDK 會在透過 Write、Edit 或 NotebookEdit 工具修改檔案之前建立檔案備份。回應串流中的使用者訊息包含一個檢查點 UUID,您可以將其用作還原點。
檢查點適用於代理程式用來修改檔案的這些內建工具:
| 工具 | 描述 |
|---|---|
| Write | 建立新檔案或用新內容覆寫現有檔案 |
| Edit | 對現有檔案的特定部分進行有針對性的編輯 |
| NotebookEdit | 修改 Jupyter 筆記本(.ipynb 檔案)中的儲存格 |
檔案回退將磁碟上的檔案還原到先前的狀態。它不會回退對話本身。呼叫 rewindFiles()(TypeScript)或 rewind_files()(Python)後,對話歷史記錄和上下文保持不變。
檢查點系統追蹤:
當您還原到檢查點時,建立的檔案會被刪除,修改的檔案會還原到該時間點的內容。
要使用檔案檢查點,請在您的選項中啟用它,從回應串流中捕獲檢查點 UUID,然後在需要還原時呼叫 rewindFiles()(TypeScript)或 rewind_files()(Python)。
以下範例顯示完整流程:啟用檢查點、從回應串流中捕獲檢查點 UUID 和工作階段 ID,然後稍後恢復工作階段以回退檔案。下面詳細說明每個步驟。
這些模式顯示根據您的使用情況捕獲和使用檢查點 UUID 的不同方式。
此模式僅保留最新的檢查點 UUID,在每個代理程式轉向之前更新它。如果在處理過程中出現問題,您可以立即回退到最後的安全狀態並跳出迴圈。
如果 Claude 在多個轉向中進行變更,您可能想要還原到特定點而不是一直回到最開始。例如,如果 Claude 在第一個轉向中重構檔案,在第二個轉向中新增測試,您可能想要保留重構但撤銷測試。
此模式將所有檢查點 UUID 與中繼資料一起儲存在陣列中。工作階段完成後,您可以還原到任何先前的檢查點:
此完整範例建立一個小型公用程式檔案,讓代理程式新增文件註解,向您顯示變更,然後詢問您是否要回退。
在開始之前,請確保您已安裝 Claude Agent SDK。
檔案檢查點有以下限制:
| 限制 | 描述 |
|---|---|
| 僅限 Write/Edit/NotebookEdit 工具 | 透過 Bash 命令進行的變更不會被追蹤 |
| 相同工作階段 | 檢查點與建立它們的工作階段相關聯 |
| 僅限檔案內容 | 建立、移動或刪除目錄不會透過回退來撤銷 |
| 本機檔案 | 遠端或網路檔案不會被追蹤 |
如果 enableFileCheckpointing 或 rewindFiles() 不可用,您可能使用的是較舊的 SDK 版本。
解決方案:更新到最新的 SDK 版本:
pip install --upgrade claude-agent-sdknpm install @anthropic-ai/claude-agent-sdk@latest如果 message.uuid 是 undefined 或遺失,您沒有接收檢查點 UUID。
原因:未設定 replay-user-messages 選項。
解決方案:將 extra_args={"replay-user-messages": None}(Python)或 extraArgs: { 'replay-user-messages': null }(TypeScript)新增到您的選項。
當指定的使用者訊息 UUID 的檢查點資料不存在時,會發生此錯誤。
常見原因:
CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING 環境變數解決方案:確保您已設定環境變數(請參閱設定環境變數),然後使用範例中顯示的模式:捕獲第一個使用者訊息 UUID,完全完成工作階段,然後使用空提示恢復並呼叫 rewindFiles() 一次。
當您在完成回應迭代後呼叫 rewindFiles() 或 rewind_files() 時,會發生此錯誤。當迴圈完成時,與 CLI 程序的連線會關閉。
解決方案:使用空提示恢復工作階段,然後在新查詢上呼叫回退:
# Resume session with empty prompt, then rewind
async with ClaudeSDKClient(ClaudeAgentOptions(
enable_file_checkpointing=True,
resume=session_id
)) as client:
await client.query("")
async for message in client.receive_response():
await client.rewind_files(checkpoint_id)
breakquery() 的所有選項和 rewindFiles() 方法。ClaudeAgentOptions 的所有選項和 rewind_files() 方法。import asyncio
import os
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, UserMessage, ResultMessage
async def main():
# Step 1: Enable checkpointing
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
permission_mode="acceptEdits", # Auto-accept file edits without prompting
extra_args={"replay-user-messages": None}, # Required to receive checkpoint UUIDs in the response stream
env={**os.environ, "CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING": "1"}
)
checkpoint_id = None
session_id = None
# Run the query and capture checkpoint UUID and session ID
async with ClaudeSDKClient(options) as client:
await client.query("Refactor the authentication module")
# Step 2: Capture checkpoint UUID from the first user message
async for message in client.receive_response():
if isinstance(message, UserMessage) and message.uuid and not checkpoint_id:
checkpoint_id = message.uuid
if isinstance(message, ResultMessage) and not session_id:
session_id = message.session_id
# Step 3: Later, rewind by resuming the session with an empty prompt
if checkpoint_id and session_id:
async with ClaudeSDKClient(ClaudeAgentOptions(
enable_file_checkpointing=True,
resume=session_id
)) as client:
await client.query("") # Empty prompt to open the connection
async for message in client.receive_response():
await client.rewind_files(checkpoint_id)
break
print(f"Rewound to checkpoint: {checkpoint_id}")
asyncio.run(main())設定環境變數
檔案檢查點需要 CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING 環境變數。您可以在執行指令碼之前透過命令列設定它,或直接在 SDK 選項中設定。
選項 1:透過命令列設定
export CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=1選項 2:在 SDK 選項中設定
在設定 SDK 時透過 env 選項傳遞環境變數:
import os
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
env={**os.environ, "CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING": "1"}
)啟用檢查點
設定您的 SDK 選項以啟用檢查點並接收檢查點 UUID:
| 選項 | Python | TypeScript | 描述 |
|---|---|---|---|
| 啟用檢查點 | enable_file_checkpointing=True | enableFileCheckpointing: true | 追蹤檔案變更以便回退 |
| 接收檢查點 UUID | extra_args={"replay-user-messages": None} | extraArgs: { 'replay-user-messages': null } | 需要在串流中取得使用者訊息 UUID |
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
permission_mode="acceptEdits",
extra_args={"replay-user-messages": None}
)
async with ClaudeSDKClient(options) as client:
await client.query("Refactor the authentication module")捕獲檢查點 UUID 和工作階段 ID
設定 replay-user-messages 選項後(如上所示),回應串流中的每個使用者訊息都有一個 UUID,用作檢查點。
對於大多數使用情況,捕獲第一個使用者訊息 UUID(message.uuid);還原到它會將所有檔案還原到其原始狀態。要儲存多個檢查點並還原到中間狀態,請參閱多個還原點。
捕獲工作階段 ID(message.session_id)是可選的;只有在您想在串流完成後稍後回退時才需要它。如果您在仍在處理訊息時立即呼叫 rewindFiles()(如檢查點在風險操作之前中的範例所做的那樣),您可以跳過捕獲工作階段 ID。
checkpoint_id = None
session_id = None
async for message in client.receive_response():
# Update checkpoint on each user message (keeps the latest)
if isinstance(message, UserMessage) and message.uuid:
checkpoint_id = message.uuid
# Capture session ID from the result message
if isinstance(message, ResultMessage):
session_id = message.session_id回退檔案
要在串流完成後回退,請使用空提示恢復工作階段,並使用您的檢查點 UUID 呼叫 rewind_files()(Python)或 rewindFiles()(TypeScript)。您也可以在串流期間回退;請參閱檢查點在風險操作之前以了解該模式。
async with ClaudeSDKClient(ClaudeAgentOptions(
enable_file_checkpointing=True,
resume=session_id
)) as client:
await client.query("") # Empty prompt to open the connection
async for message in client.receive_response():
await client.rewind_files(checkpoint_id)
break如果您捕獲了工作階段 ID 和檢查點 ID,您也可以從 CLI 回退:
claude --resume <session-id> --rewind-files <checkpoint-uuid>import asyncio
import os
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, UserMessage
async def main():
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
permission_mode="acceptEdits",
extra_args={"replay-user-messages": None},
env={**os.environ, "CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING": "1"}
)
safe_checkpoint = None
async with ClaudeSDKClient(options) as client:
await client.query("Refactor the authentication module")
async for message in client.receive_response():
# Update checkpoint before each agent turn starts
# This overwrites the previous checkpoint. Only keep the latest
if isinstance(message, UserMessage) and message.uuid:
safe_checkpoint = message.uuid
# Decide when to revert based on your own logic
# For example: error detection, validation failure, or user input
if your_revert_condition and safe_checkpoint:
await client.rewind_files(safe_checkpoint)
# Exit the loop after rewinding, files are restored
break
asyncio.run(main())import asyncio
import os
from dataclasses import dataclass
from datetime import datetime
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, UserMessage, ResultMessage
# Store checkpoint metadata for better tracking
@dataclass
class Checkpoint:
id: str
description: str
timestamp: datetime
async def main():
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
permission_mode="acceptEdits",
extra_args={"replay-user-messages": None},
env={**os.environ, "CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING": "1"}
)
checkpoints = []
session_id = None
async with ClaudeSDKClient(options) as client:
await client.query("Refactor the authentication module")
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()
))
if isinstance(message, ResultMessage) and not session_id:
session_id = message.session_id
# Later: rewind to any checkpoint by resuming the session
if checkpoints and session_id:
target = checkpoints[0] # Pick any checkpoint
async with ClaudeSDKClient(ClaudeAgentOptions(
enable_file_checkpointing=True,
resume=session_id
)) as client:
await client.query("") # Empty prompt to open the connection
async for message in client.receive_response():
await client.rewind_files(target.id)
break
print(f"Rewound to: {target.description}")
asyncio.run(main())建立測試檔案
建立一個名為 utils.py(Python)或 utils.ts(TypeScript)的新檔案,並貼上以下程式碼:
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b執行互動範例
在與您的公用程式檔案相同的目錄中建立一個名為 try_checkpointing.py(Python)或 try_checkpointing.ts(TypeScript)的新檔案,並貼上以下程式碼。
此指令碼要求 Claude 將文件註解新增到您的公用程式檔案,然後給您選擇回退並還原原始檔案的選項。
import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, UserMessage, ResultMessage
async def main():
# Configure the SDK with checkpointing enabled
# - enable_file_checkpointing: Track file changes for rewinding
# - permission_mode: Auto-accept file edits without prompting
# - extra_args: Required to receive user message UUIDs in the stream
options = ClaudeAgentOptions(
enable_file_checkpointing=True,
permission_mode="acceptEdits",
extra_args={"replay-user-messages": None}
)
checkpoint_id = None # Store the user message UUID for rewinding
session_id = None # Store the session ID for resuming
print("Running agent to add doc comments to utils.py...\n")
# Run the agent and capture checkpoint data from the response stream
async with ClaudeSDKClient(options) as client:
await client.query("Add doc comments to utils.py")
async for message in client.receive_response():
# Capture the first user message UUID - this is our restore point
if isinstance(message, UserMessage) and message.uuid and not checkpoint_id:
checkpoint_id = message.uuid
# Capture the session ID so we can resume later
if isinstance(message, ResultMessage):
session_id = message.session_id
print("Done! Open utils.py to see the added doc comments.\n")
# Ask the user if they want to rewind the changes
if checkpoint_id and session_id:
response = input("Rewind to remove the doc comments? (y/n): ")
if response.lower() == "y":
# Resume the session with an empty prompt, then 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) # Restore files
break
print("\n✓ File restored! Open utils.py to verify the doc comments are gone.")
else:
print("\nKept the modified file.")
asyncio.run(main())此範例演示完整的檢查點工作流程:
enable_file_checkpointing=True 和 permission_mode="acceptEdits" 設定 SDK 以自動批准檔案編輯rewind_files() 以還原原始檔案執行範例
設定環境變數並從與您的公用程式檔案相同的目錄執行指令碼。
在執行指令碼之前,在您的 IDE 或編輯器中開啟您的公用程式檔案(utils.py 或 utils.ts)。當代理程式新增文件註解時,您會看到檔案實時更新,然後當您選擇回退時還原到原始檔案。
export CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING=1
python try_checkpointing.py您會看到代理程式新增文件註解,然後出現一個提示,詢問您是否要回退。如果您選擇是,檔案會還原到其原始狀態。