Pular para o conteúdo principal
O checkpointing de arquivo rastreia modificações de arquivo feitas através das ferramentas Write, Edit e NotebookEdit durante uma sessão de agente, permitindo que você reverta arquivos para qualquer estado anterior. Quer experimentar? Vá para o exemplo interativo. Com checkpointing, você pode:
  • Desfazer alterações indesejadas restaurando arquivos para um estado conhecido e bom
  • Explorar alternativas restaurando para um checkpoint e tentando uma abordagem diferente
  • Recuperar de erros quando o agente faz modificações incorretas
Apenas as alterações feitas através das ferramentas Write, Edit e NotebookEdit são rastreadas. As alterações feitas através de comandos Bash (como echo > file.txt ou sed -i) não são capturadas pelo sistema de checkpoint.

Como o checkpointing funciona

Quando você ativa o checkpointing de arquivo, o SDK cria backups de arquivos antes de modificá-los através das ferramentas Write, Edit ou NotebookEdit. As mensagens do usuário no fluxo de resposta incluem um UUID de checkpoint que você pode usar como ponto de restauração. O checkpoint funciona com essas ferramentas integradas que o agente usa para modificar arquivos:
FerramentaDescrição
WriteCria um novo arquivo ou sobrescreve um arquivo existente com novo conteúdo
EditFaz edições direcionadas em partes específicas de um arquivo existente
NotebookEditModifica células em notebooks Jupyter (arquivos .ipynb)
A reversão de arquivo restaura arquivos no disco para um estado anterior. Ela não reverte a conversa em si. O histórico de conversa e o contexto permanecem intactos após chamar rewindFiles() (TypeScript) ou rewind_files() (Python).
O sistema de checkpoint rastreia:
  • Arquivos criados durante a sessão
  • Arquivos modificados durante a sessão
  • O conteúdo original de arquivos modificados
Quando você reverte para um checkpoint, os arquivos criados são deletados e os arquivos modificados são restaurados para seu conteúdo naquele ponto.

Implementar checkpointing

Para usar checkpointing de arquivo, ative-o em suas opções, capture UUIDs de checkpoint do fluxo de resposta e, em seguida, chame rewindFiles() (TypeScript) ou rewind_files() (Python) quando precisar restaurar. O exemplo a seguir mostra o fluxo completo: ativar checkpointing, capturar o UUID de checkpoint e ID de sessão do fluxo de resposta e, em seguida, retomar a sessão mais tarde para reverter arquivos. Cada etapa é explicada em detalhes abaixo.
import asyncio
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
    )

    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())
1

Ativar checkpointing

Configure suas opções de SDK para ativar checkpointing e receber UUIDs de checkpoint:
OpçãoPythonTypeScriptDescrição
Ativar checkpointingenable_file_checkpointing=TrueenableFileCheckpointing: trueRastreia alterações de arquivo para reversão
Receber UUIDs de checkpointextra_args={"replay-user-messages": None}extraArgs: { 'replay-user-messages': null }Necessário para obter UUIDs de mensagem do usuário no fluxo
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")
2

Capturar UUID de checkpoint e ID de sessão

Com a opção replay-user-messages definida (mostrada acima), cada mensagem do usuário no fluxo de resposta tem um UUID que serve como um checkpoint.Para a maioria dos casos de uso, capture o UUID da primeira mensagem do usuário (message.uuid); reverter para ele restaura todos os arquivos para seu estado original. Para armazenar múltiplos checkpoints e reverter para estados intermediários, veja Múltiplos pontos de restauração.Capturar o ID de sessão (message.session_id) é opcional; você só precisa dele se quiser reverter mais tarde, após o fluxo ser concluído. Se você estiver chamando rewindFiles() imediatamente enquanto ainda processa mensagens (como o exemplo em Checkpoint antes de operações arriscadas faz), você pode pular a captura do ID de sessão.
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
3

Reverter arquivos

Para reverter após o fluxo ser concluído, retome a sessão com um prompt vazio e chame rewind_files() (Python) ou rewindFiles() (TypeScript) com seu UUID de checkpoint. Você também pode reverter durante o fluxo; veja Checkpoint antes de operações arriscadas para esse padrão.
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
Se você capturar o ID de sessão e o ID de checkpoint, você também pode reverter a partir da CLI:
claude -p --resume <session-id> --rewind-files <checkpoint-uuid>

Padrões comuns

Esses padrões mostram diferentes maneiras de capturar e usar UUIDs de checkpoint dependendo do seu caso de uso.

Checkpoint antes de operações arriscadas

Este padrão mantém apenas o UUID de checkpoint mais recente, atualizando-o antes de cada turno do agente. Se algo der errado durante o processamento, você pode reverter imediatamente para o último estado seguro e sair do loop.
import asyncio
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},
    )

    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())

Múltiplos pontos de restauração

Se Claude fizer alterações em múltiplos turnos, você pode querer reverter para um ponto específico em vez de voltar completamente. Por exemplo, se Claude refatorar um arquivo no turno um e adicionar testes no turno dois, você pode querer manter a refatoração mas desfazer os testes. Este padrão armazena todos os UUIDs de checkpoint em um array com metadados. Após a sessão ser concluída, você pode reverter para qualquer checkpoint anterior:
import asyncio
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},
    )

    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())

Experimente

Este exemplo completo cria um pequeno arquivo utilitário, faz o agente adicionar comentários de documentação, mostra as alterações e pergunta se você quer reverter. Antes de começar, certifique-se de que você tem o Claude Agent SDK instalado.
1

Criar um arquivo de teste

Crie um novo arquivo chamado utils.py (Python) ou utils.ts (TypeScript) e cole o seguinte código:
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
2

Executar o exemplo interativo

Crie um novo arquivo chamado try_checkpointing.py (Python) ou try_checkpointing.ts (TypeScript) no mesmo diretório que seu arquivo utilitário e cole o seguinte código.Este script pede ao Claude para adicionar comentários de documentação ao seu arquivo utilitário e, em seguida, oferece a opção de reverter e restaurar o original.
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())
Este exemplo demonstra o fluxo de trabalho completo de checkpointing:
  1. Ativar checkpointing: configure o SDK com enable_file_checkpointing=True e permission_mode="acceptEdits" para aprovar automaticamente edições de arquivo
  2. Capturar dados de checkpoint: conforme o agente é executado, armazene o UUID da primeira mensagem do usuário (seu ponto de restauração) e o ID de sessão
  3. Solicitar reversão: após o agente terminar, verifique seu arquivo utilitário para ver os comentários de documentação e decida se deseja desfazer as alterações
  4. Retomar e reverter: se sim, retome a sessão com um prompt vazio e chame rewind_files() para restaurar o arquivo original
3

Executar o exemplo

Execute o script do mesmo diretório que seu arquivo utilitário.
Abra seu arquivo utilitário (utils.py ou utils.ts) em seu IDE ou editor antes de executar o script. Você verá o arquivo ser atualizado em tempo real conforme o agente adiciona comentários de documentação e, em seguida, reverter para o original quando você escolher reverter.
python try_checkpointing.py
Você verá o agente adicionar comentários de documentação e, em seguida, um prompt perguntando se você quer reverter. Se você escolher sim, o arquivo é restaurado para seu estado original.

Limitações

O checkpointing de arquivo tem as seguintes limitações:
LimitaçãoDescrição
Apenas ferramentas Write/Edit/NotebookEditAs alterações feitas através de comandos Bash não são rastreadas
Mesma sessãoOs checkpoints estão vinculados à sessão que os criou
Apenas conteúdo de arquivoCriar, mover ou deletar diretórios não é desfeito pela reversão
Arquivos locaisArquivos remotos ou de rede não são rastreados

Troubleshooting

Opções de checkpointing não reconhecidas

Se enableFileCheckpointing ou rewindFiles() não estiver disponível, você pode estar em uma versão mais antiga do SDK. Solução: Atualize para a versão mais recente do SDK:
  • Python: pip install --upgrade claude-agent-sdk
  • TypeScript: npm install @anthropic-ai/claude-agent-sdk@latest

Mensagens do usuário não têm UUIDs

Se message.uuid for undefined ou estiver faltando, você não está recebendo UUIDs de checkpoint. Causa: A opção replay-user-messages não está definida. Solução: Adicione extra_args={"replay-user-messages": None} (Python) ou extraArgs: { 'replay-user-messages': null } (TypeScript) às suas opções.

Erro “No file checkpoint found for message”

Este erro ocorre quando os dados de checkpoint não existem para o UUID de mensagem do usuário especificado. Causas comuns:
  • O checkpointing de arquivo não foi ativado na sessão original (enable_file_checkpointing ou enableFileCheckpointing não foi definido como true)
  • A sessão não foi concluída adequadamente antes de tentar retomar e reverter
Solução: Certifique-se de que enable_file_checkpointing=True (Python) ou enableFileCheckpointing: true (TypeScript) foi definido na sessão original, depois use o padrão mostrado nos exemplos: capture o UUID da primeira mensagem do usuário, conclua a sessão completamente e, em seguida, retome com um prompt vazio e chame rewindFiles() uma vez.

Erro “ProcessTransport is not ready for writing”

Este erro ocorre quando você chama rewindFiles() ou rewind_files() após ter terminado de iterar através da resposta. A conexão com o processo CLI fecha quando o loop é concluído. Solução: Retome a sessão com um prompt vazio e, em seguida, chame rewind na nova query:
# 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)
        break

Próximos passos

  • Sessions: aprenda como retomar sessões, o que é necessário para reverter após o fluxo ser concluído. Cobre IDs de sessão, retomada de conversas e bifurcação de sessão.
  • Permissions: configure quais ferramentas Claude pode usar e como as modificações de arquivo são aprovadas. Útil se você quiser mais controle sobre quando as edições acontecem.
  • TypeScript SDK reference: referência completa da API incluindo todas as opções para query() e o método rewindFiles().
  • Python SDK reference: referência completa da API incluindo todas as opções para ClaudeAgentOptions e o método rewind_files().