smithers oneshot is the built-in minimal workflow: one agent, one goal, no
authoring. It launches in the background by default and serves a live
dashboard with chat, diff, hijack, pause, and cancel controls.
Its long-running implement and optional review tasks use the existing
per-task heartbeatTimeoutMs override with a 10-minute inactivity window. Live
tool execution, output streaming, and owned CLI subprocesses refresh that
window; an agent with no activity still fails. This does not raise the global
heartbeat default.
When to use it
Route work in three tiers:- Trivial asks (a typo, a rename, an edit under about 10 agent turns): do
them directly. If the stored trivial preference is
oneshot, launch oneshot with--model opusor--model terra: those are the only two slots allowed for trivial oneshot (never sol, luna, kimi, or any other tier), and no other model belongs in a trivial routing explanation. Trivial means one tiny change in one place: an ask that bundles multiple coordinated edits (a flag plus its help text plus a test, code plus docs) is tier 2 oneshot work, not trivial, no matter how fast it would be. - Clear single-goal asks, small or repo-wide:
smithers oneshot. One strong agent routinely finishes hours-long goals in a single oneshot run of up to roughly 300k tokens, so a large goal is not a reason to leave this tier. The worker manages its own context across the run, so “it will not fit in one context window” is not a reason either. When explaining a routing decision, name the task shape and the seat it routes to (UI goals lead with kimi: opencode, then pi, then the kimi CLI, backed by claude opus or fable; every other goal leads with claude opus) and which seat you picked. - Genuinely multi-goal work (human approval gates, staged phases that need different agents or models, parallel fan-out, durable loops, or a reusable procedure): build and run a real workflow.
- “Go through the entire codebase and make sure every feature is documented.”
- “Run
pnpm up --lateston every package and make sure all builds still pass.” - “Make CI green on this branch: rebase on main, fix failures, push until green.”
- “Replace every use of library X with library Y and get all tests passing.”
- “Read review.md, address every review comment, delete the artifacts when done.”
audit,
review, upgrade) qualifies: shape decides, not the catalog. Pick exactly
one route and commit to it; never answer with a menu of alternative routes or
a hybrid of oneshot plus a workflow.
Explicit overrides win over inference: “oneshot” forces oneshot, “oneshot with
review” adds --review on, “oneshot without review” adds --review off.
Ambiguous goals deserve clarifying questions to the user before anything
launches; wait for the answers rather than substituting assumptions or an
exploratory plan for them. “Make the settings page better” gets a reply that
is ONLY clarifying questions, covering both the target (which settings page?)
and the goal (what is wrong today? what does better mean? what counts as
done?). The entire reply is the questions: never a plan whose first step is to
find out, and never a provisional plan under an assumed answer.
Agents and models
With no--model or --agent, oneshot classifies the goal and routes by task
shape (registry v8). A UI-flavored goal (interface, page, component, styling,
layout, responsive, animation, theme, dashboard, and similar keywords) leads
with Kimi K3: OpenCode’s kimi-for-coding/k3 seat first, then kimi through
the Pi CLI (pi --provider kimi-coding --model k3), then the Kimi CLI’s
kimi-code/k3. When no kimi seat is usable, the UI chain falls back to Claude
Opus 5, then Fable 5; Codex Sol is only ever the last-resort UI rung. Every
other goal, including tedious backend work (migrations, backfills, renames,
test burndowns), runs the default chain: Claude Opus 5 first (the default
implementer), then Codex Sol, then Kimi K3, then Fable, with pi’s kimi-coding
seat closing the chain.
Every rung is availability-gated: oneshot selects only from the agents
detected usable on the machine, the claude seats fall back to opencode when
the Claude CLI is unavailable, and the kimi seats all run Kimi K3 (1M-token
context). An explicit --model (a slot: sol, terra, luna, kimi,
fable, opus, sonnet; or a canonical model id) or --agent (codex,
kimi, claude-code, opencode, pi) always overrides classification; the
default auto follows the task shape, with review on Sol at high reasoning
effort.
Run bunx smthrs oneshot --status "<goal>" before first use.
It prints the usable agents, the goal’s classified taskType, the resolved
model chain, and the stored preferences as JSON; when no usable agent is
detected, oneshot is unavailable and work should go through the direct or
workflow route instead. Oneshot being unavailable never means the
orchestrating agent is unavailable: a simple task still gets done directly, a
multi-goal one still gets a workflow, and “no routing path exists” is never
the answer.
Review and trivial preferences
Two stored preferences shape routing, kept in the global Smithers config:- Review (
--set-review on|off): add one review-and-polish round after the implement pass. Higher quality, slower. Recommended on. - Trivial (
--set-trivial direct|oneshot): whether the most-trivial asks run directly or still launch oneshot. Recommended direct.
--review on|off overrides the stored review preference for one run.
Dirty working copies
Oneshot runs directly in--cwd, so a stale detached lineage, foreign WIP, or
.jjconflict* tree can be swept into a goal commit and make landing unsafe.
The default --preflight auto warns and prepends agent-judged triage
instructions; use warn to warn without injection or off to skip assessment.
Sharing a directory with another run
Preflight treats dirty paths as pre-existing work the agent may snapshot into its own commit. That is only true when nothing else is producing them. Launch therefore asks the workspace store which runs are still working in--cwd,
using the same PID-verified liveness bunx smthrs ps reports. A run whose engine
is dead does not count.
When another run is live there, preflight names it, and the injected
instructions flip: the agent commits only the paths its own goal work touches,
by explicit pathspec, and leaves every other path alone. It does not snapshot,
stash, revert, or gitignore anything, because those changes belong to a run
that is still editing them.
The two clean fixes are to wait for that run, or to relaunch with --cwd
pointing at an isolated worktree. --preflight force-commit keeps the old
behavior for the case where you know the tree is yours.
Two launches that race inside the scan window can still each see an empty
store and proceed. Sequential launches, the common case, are covered.
Watching and steering a oneshot
Every launch CTA tells the operator to offer the monitor to the user. Open it directly with:- Steer: send a message from the chat composer. Delivery is shown as
queued,delivered,agent-acked, or an explicit failure. Claude Code is currently supported by interrupting at the next recorded agent-event boundary, resuming the same Claude session with the appended message, then resuming the Smithers run. If delivery fails after handoff, the monitor clears the hijack request and returns control to Smithers so the run is not stranded. Codex, Kimi, and OpenCode are shown as unsupported because their current headless sessions do not provide an equally reliable live message boundary. Usebunx smthrs hijack RUN_IDfor interactive takeover. - Restart: after confirmation, cancel the active attempt if needed and
launch a fresh run from the durable
builtinResumeargv recorded at the original launch. The UI follows the new run id. - Cheap narrator: while the monitor remains attached, the Luna/trivial model tier tails recorded agent activity and emits short status lines. It stops after the attachment lease expires, so an unattended oneshot does not pay narration cost. Lines are persisted as run events and reappear after a monitor reattaches.
chat-create run UI, and the Monitor’s node-row hijack
view are all the same shared OneshotSurface component from
smthrs/gateway-ui: goal and status cards, chat, diff, events,
and an embedded PTY terminal for hijack and reopen. The Monitor hosts it in a
dialog that can maximize to the viewport and restore.
Steering and restart requests and outcomes are durable run events shown by
bunx smthrs status RUN_ID, events RUN_ID, and
timeline RUN_ID. Narrator lines are durable NodeOutput events shown by
events RUN_ID --raw and by a later monitor attachment.
On an interactive TTY, --interactive opens the full-screen TUI monitor
instead of the detached default. --detach false runs in the foreground.
Overriding the built-in workflow
A workspace can replace the built-in pipeline with.smithers/workflows/oneshot.tsx; the CLI passes goal, review, and
model input fields to it, and uses .smithers/ui/oneshot.tsx as the
dashboard when present. See Custom workflow UIs.
See also
- CLI catalog → oneshot for the full flag list
- Agent operating playbook for routing doctrine