Skip to main content
Smithers integrates with JJ (Jujutsu), a Git-compatible version control system, to record filesystem snapshots at each task completion. This enables reverting the workspace to the exact state it was in after any specific attempt.

How JJ Pointers Work

When JJ is installed and the workspace is a JJ repository, Smithers captures a JJ pointer (the current change ID or operation ID) at the end of each task attempt. This pointer is stored in the _smithers_attempts table alongside the attempt’s other metadata. The flow:
  1. A task executes and makes filesystem changes (via agent tools like edit, write, bash).
  2. The task completes (successfully or with failure).
  3. Smithers captures the current JJ state and stores it in _smithers_attempts.jj_pointer.
  4. On the next attempt or task, JJ continues tracking changes from this point.
Each attempt gets its own pointer, so you can revert to any point in the workflow’s execution history.

What Gets Recorded

Each row in _smithers_attempts includes a jj_pointer column:
ColumnTypeDescription
jj_pointertext (nullable)The JJ change/operation ID captured after this attempt completed. null if JJ is not installed or the workspace is not a JJ repository.
You can inspect the recorded pointers directly:
sqlite3 smithers.db "SELECT run_id, node_id, iteration, attempt, jj_pointer FROM _smithers_attempts WHERE run_id = '<id>';"
Example output:
smth_a1b2|analyze|0|1|zqkopwvn
smth_a1b2|fix|0|1|xrlmqkts
smth_a1b2|fix|0|2|ynpwzrmv
smth_a1b2|report|0|1|kutswxqp
Here, the fix task had two attempts (perhaps the first failed and was retried). Each attempt has a distinct JJ pointer.

Revert CLI Command

Use the revert command to restore the workspace to the state captured at a specific attempt:
smithers revert workflow.tsx \
  --run-id <run-id> \
  --node-id <node-id> \
  --attempt <attempt-number> \
  --iteration <iteration-number>
For example, to revert to the state after the first attempt of the fix task:
smithers revert workflow.tsx --run-id smth_a1b2 --node-id fix --attempt 1 --iteration 0
This restores the filesystem to the exact state it was in after that attempt completed. Smithers emits RevertStarted and RevertFinished events during the operation.

Revert use cases

  • Undo a bad fix: The agent made changes that broke something. Revert to before the fix and try a different approach.
  • Compare attempts: Revert to attempt 1, inspect the state, then revert to attempt 2 to compare.
  • Debug failures: Revert to the state just before a failure to inspect the workspace.

When JJ Is Not Installed

If JJ is not installed or the workspace is not a JJ repository:
  • jj_pointer is recorded as null for all attempts.
  • The revert command fails with an error explaining that no JJ pointer was found.
  • All other Smithers functionality works normally. Execution, persistence, resume, and caching are unaffected.
JJ is entirely optional. You only need it if you want revert support.

Setting Up JJ

Install JJ:
brew install jj
Initialize a JJ repository in your workspace (or use an existing one):
cd /path/to/my-project
jj git init
If your project already uses Git, JJ can colocate with your Git repository:
cd /path/to/my-project
jj git init --colocate
Once JJ is initialized, Smithers will automatically detect it and start recording pointers.

Cache Key Integration

JJ pointers are also used as part of the cache key when caching is enabled (<Workflow cache> or { cache: true }). The cache key includes:
  • Workflow name + nodeId
  • Prompt text or static payload
  • Model ID and parameters
  • Tool allowlist and versions
  • Output schema signature
  • JJ pointer (change or operation ID)
This means that if the workspace changes (tracked by JJ), cached results for affected tasks are automatically invalidated. If the workspace returns to a previous state (same JJ pointer), the cached result is reused.

Next Steps

  • Resumability — How Smithers persists state for crash recovery.
  • Caching — How cache keys work and when to enable caching.
  • CLI Reference — All CLI commands including revert.