Skip to main content
Smithers records a JJ (Jujutsu) change ID at the end of each successful task attempt. You can use the revert feature to restore the workspace to the exact filesystem state that existed when a specific attempt completed. This is useful for debugging, undoing agent changes, or replaying a task from a known-good state.

Prerequisites

  • JJ must be installed and available in your PATH. Install it with brew install jj, cargo install jj-cli, or see the JJ installation docs.
  • The workspace must be a JJ repository (run jj git init or jj init in your project root).
  • The attempt you want to revert to must have a recorded JJ pointer. Pointers are only recorded when JJ is available at the time the attempt finishes.

How It Works

  1. When a task attempt finishes successfully, Smithers runs jj log -r @ --no-graph --template change_id to capture the current JJ change ID.
  2. This change ID is stored in the _smithers_attempts table in the jj_pointer column.
  3. When you invoke smithers revert, Smithers looks up the stored change ID and runs jj restore --from <change_id> to restore the workspace to that state.
The revert operation restores file contents but does not alter the JJ history. It creates a new change on top of the current working copy with the restored content.

CLI Usage

smithers revert <workflow.tsx> \
  --run-id <run-id> \
  --node-id <node-id> \
  [--attempt N] \
  [--iteration N]

Required Flags

FlagDescription
--run-id IDThe run containing the attempt to revert to.
--node-id IDThe task node whose attempt you want to revert to.

Optional Flags

FlagDefaultDescription
--attempt N1The attempt number to revert to (1-indexed).
--iteration N0The Ralph iteration number.

Examples

Revert to the first attempt of task “analyze” in a specific run:
smithers revert workflow.tsx --run-id abc123 --node-id analyze
Revert to the second attempt (after a retry):
smithers revert workflow.tsx --run-id abc123 --node-id analyze --attempt 2
Revert to a specific Ralph iteration:
smithers revert workflow.tsx --run-id abc123 --node-id fix --attempt 1 --iteration 2

Exit Codes

CodeMeaning
0Revert succeeded.
1Revert failed (attempt not found, no JJ pointer, or JJ command failed).

Output

The command prints a JSON result to stdout:
{
  "success": true,
  "jjPointer": "zxkqmrstvwxy"
}
On failure:
{
  "success": false,
  "error": "Attempt has no jjPointer recorded",
  "jjPointer": null
}
During execution, RevertStarted and RevertFinished events are printed as JSON lines to stdout.

Programmatic Usage

You can also revert programmatically using the revertToAttempt function:
import { SmithersDb } from "smithers-orchestrator/db/adapter";
import { ensureSmithersTables } from "smithers-orchestrator/db/ensure";
import { revertToAttempt } from "smithers-orchestrator/revert";

const adapter = new SmithersDb(db);

const result = await revertToAttempt(adapter, {
  runId: "abc123",
  nodeId: "analyze",
  iteration: 0,
  attempt: 1,
  onProgress: (event) => console.log(event.type),
});

if (result.success) {
  console.log("Reverted to", result.jjPointer);
} else {
  console.error("Revert failed:", result.error);
}

RevertOptions

type RevertOptions = {
  runId: string;
  nodeId: string;
  iteration: number;
  attempt: number;
  onProgress?: (event: SmithersEvent) => void;
};

RevertResult

type RevertResult = {
  success: boolean;
  error?: string;
  jjPointer?: string;
};

Events

Revert operations emit two events:
  • RevertStarted — Fired before the jj restore command runs. Includes the jjPointer being restored to.
  • RevertFinished — Fired after the restore completes. Includes success (boolean) and error (string, if failed).
See Events for the full type definitions.

Troubleshooting

“Attempt has no jjPointer recorded” The attempt finished before JJ was installed, or JJ was not available in PATH when the attempt completed. JJ pointers are only captured opportunistically — if jj log fails, the pointer is silently set to null. “jj exited with code 1” The JJ restore command failed. Common causes:
  • The change ID no longer exists in the JJ repository (pruned or garbage-collected).
  • The workspace is in a conflicted state.
  • JJ is not properly configured for the repository.
Revert does not undo database changes Revert only restores the filesystem via JJ. It does not modify the SQLite database. Task outputs, attempt records, and run state remain unchanged. To re-run a task, resume the workflow — Smithers will detect that the output is now invalid and re-execute.
  • Events — RevertStarted and RevertFinished event types.
  • VCS Integration — How Smithers integrates with version control.
  • CLI — Full CLI reference including the revert command.