Skip to content
xiv

How It Works

The architecture: the xiv CLI launches Smithers workflows, which run agents against your repo, Linear, and GitHub.

The four layers

  1. The xiv CLI — runs from this repo's source via bun link. It parses your command, resolves SMITHERS_HOME, and either installs the pack (init/update) or launches a workflow.
  2. The managed pack — a copy of this repo's pack/ (workflows, agent definitions, prompts, and its own dependencies) installed into SMITHERS_HOME. This is what actually executes; the repo copy is only the source.
  3. The Smithers enginesmithers-orchestrator, installed as a dependency of the pack. Every workflow command boils down to running smithers up workflows/<name>.tsx --input '{…}' inside SMITHERS_HOME, using the pack's own node_modules/.bin/smithers. Smithers executes the workflow graph durably: steps, retries, resumability, run state.
  4. Agent tasks — workflow steps that drive the claude and codex CLIs. Those agents do the actual work against the target repo (the directory you invoked xiv from, passed as SMITHERS_TARGET_CWD), Linear (over MCP), and GitHub (via gh).
Loading diagram...

Two consequences of this shape:

  • The CLI is always live; the pack is versioned by install. Command and flag changes take effect the moment you pull, because xiv runs from source. Workflow behavior only changes when you run xiv update, because the engine reads the copy in SMITHERS_HOME — never the repo's pack/ directly (except under xiv dev — see below).
  • The engine runs in SMITHERS_HOME but operates on your repo. The working directory of the smithers process is SMITHERS_HOME; the repo being changed is whatever SMITHERS_TARGET_CWD points at. That's why you run xiv commands from inside the target repo.

Jujutsu under the stack

The stacked-PR machinery is built on Jujutsu (jj) rather than scripted git rebase — a core design choice, and most of what makes stacks cheap to operate:

  • xiv stack init runs jj git init --colocate once per repo: .jj/ lives next to .git/, git stays the interface GitHub and CI see, and jj is purely local machinery. It's reversible — delete .jj/ to undo.
  • Rebasing is jj's native model, not a scripted loop: when stack amend edits an entry or stack review fixes a finding in the branch that owns it, every descendant branch re-flows automatically, and the stack pushes the rewritten branches back out.

This is why fixing a review comment at the bottom of a ten-PR stack is a one-command operation instead of nine manual rebases. Details in Stack map & triage.

The managed pack

init/update treat the pack as a set of managed files: every file under pack/ is hashed (sha256), copied into SMITHERS_HOME, and recorded in SMITHERS_HOME/.xiv/manifest.json. On the next install, any managed file whose on-disk hash no longer matches the manifest — i.e. something you hand-edited in SMITHERS_HOME — is backed up to .xiv/backups/<timestamp>/ before being overwritten.

The point: SMITHERS_HOME is a deployment target, not a workspace. Local edits there don't survive an update (though they're never lost), which keeps every machine's installed workflows identical to some state of the repo. Full details in Managed files.

Engine-owned files are explicitly excluded from management and never touched by an install: smithers.db (and its -shm/-wal companions), accounts.json, and the executions/, runs/, and logs/ directories.

Where state lives

Everything lives under SMITHERS_HOME (default ~/.smithers; override with the env var):

PathWhat it isWritten by
workflows/, agents.ts, prompts/, …The managed pack (mirrors this repo's pack/)xiv init / xiv update
.xiv/manifest.jsonHash manifest of the managed filesxiv init / xiv update
.xiv/backups/<timestamp>/Drifted files saved before overwritexiv update
smithers.db (+ -shm, -wal)The engine's durable run databaseSmithers
executions/, runs/, logs/Per-run output and logsSmithers
stacks/<feature>.jsonStack maps — one per feature, keyed by feature alone so every xiv stack command finds it from any directoryxiv stack plan and later stack commands
review/xiv pr review state: clones/ (auto-cloned repos), worktrees/ (per-PR checkouts), and per-PR scratch dirs (findings, draft review body)xiv pr review

Nothing xiv-specific is written into the target repo itself, with one exception: xiv stack init creates a colocated .jj/ directory next to .git/ (reversible — delete it to undo).

xiv dev — the authoring loop

Editing a workflow would be painful if every change needed an xiv update round-trip into SMITHERS_HOME. So two commands bypass the managed copy and run straight from the repo's pack/:

cd pack && bun install    # one-time: the pack's own deps
cd /path/to/target-repo   # the repo the workflow should operate on
 
xiv check linear-implement --input '{"issueId":"ENG-123"}'   # render the graph, no agents (fast, free)
xiv dev   linear-implement --input '{"issueId":"ENG-123"}'   # run it live against this repo

check maps to smithers graph (build and print the workflow graph without executing it); dev maps to smithers up, exactly like a normal run, but with the in-repo pack/ as the pack root. Both accept a bare workflow name or a path to a .tsx file, and default --cwd to the current directory. Edit pack/workflows/<name>.tsx, re-run, repeat — then xiv update when it's ready to become the installed behavior. See xiv dev & check.

Observing runs

The operational commands (xiv ps, logs, ui, inspect, cancel, down/panic) forward directly to the corresponding smithers command in SMITHERS_HOME, so they see every run regardless of which repo you launched it from. See Operations.