How tracking works

Whenever the agent calls a write tool (`write_file`, `edit_file`, `apply_patch`, or any custom MCP tool that reports a modification), the CLI emits a `file_modified` event over JSON-RPC. The CLI also stores a record of the change under `~/.autohand/runs/<run-id>/` so the change can be inspected after the fact.

The SDK's job is to surface those events to your app; the CLI's job is to persist them.

Observe file modifications in real time

Match `file_modified` events while you stream a prompt. Use them to invalidate caches, refresh editor buffers, or track what the agent changed for an audit log.

TypeScript

const modified = new Set();

for await (const event of sdk.streamPrompt({ message: prompt })) {
  if (event.type === 'file_modified') {
    modified.add(event.path);
    editor.refresh(event.path);
  }
  if (event.type === 'agent_end') {
    console.log('Files touched:', [...modified]);
  }
}

Python

modified = set()

async for event in sdk.stream_prompt(prompt):
    if event["type"] == "file_modified":
        modified.add(event.get("path"))
        editor.refresh(event.get("path"))
    if event["type"] == "agent_end":
        print("Files touched:", sorted(modified))

Go

modified := map[string]struct{}{}

for event := range events {
    switch e := event.(type) {
    case autohand.FileModifiedEvent:
        modified[e.Path] = struct{}{}
        editor.Refresh(e.Path)
    case autohand.AgentEndEvent:
        fmt.Println("Files touched:", modified)
    }
}

Java

Set<String> modified = new HashSet<>();

sdk.streamPrompt(new PromptParams(prompt), event -> {
    if (event instanceof Events.FileModifiedEvent fme) {
        modified.add(fme.path());
        editor.refresh(fme.path());
    } else if (event instanceof Events.AgentEndEvent) {
        System.out.println("Files touched: " + modified);
    }
});

Revert with git

The simplest, safest revert path is git. Run inside a clean working tree (or commit before each agent run) so you can `git restore`, `git stash`, or `git reset --hard` if the agent goes off the rails.

bash

# Snapshot before the agent runs
git add -A && git commit -m "pre-agent snapshot"

# Run the agent
bun run my-agent.ts

# If unhappy, revert
git reset --hard HEAD@{1}

If you let the agent commit on your behalf, restrict it to its own branch:

bash

git switch -c agent/$(date +%s)
bun run my-agent.ts
# Review the diff before merging back to main
git diff main...HEAD

Inspect run history with the CLI

The CLI keeps a per-run history under `~/.autohand/runs/`. Use it when you need to inspect what an agent did across multiple sessions, including ones that did not commit to git.

bash

# List recent runs
autohand runs list

# Show every file the run wrote
autohand runs show <run-id> --files

# Restore a single file from a run
autohand runs restore <run-id> src/auth.ts

The exact subcommands depend on your CLI version. Run `autohand runs --help` to see what is available locally.

Best practices

  • Run agents inside a clean git working tree so revert is one command away.
  • Stream `file_modified` into your editor / IDE integration so users see changes the moment they happen.
  • For unattended runs, write `file_modified` paths to an audit log alongside the run ID. That pair lets you tie back any change to the agent and prompt that produced it.
  • Do not rely on CLI run history for compliance. Treat it as a developer convenience; treat git (or your VCS of choice) as the source of truth.