Skip to main content
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:
  1. 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 opus or --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.
  2. 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.
  3. 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.
Size does not pick the route; shape does. A task with one finish line belongs in oneshot no matter how much work it implies. Real asks that fit a single oneshot run, each historically completed by one strong agent in under 300k tokens:
  • “Go through the entire codebase and make sure every feature is documented.”
  • “Run pnpm up --latest on 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.”
Authoring a workflow for asks like these is overengineering: it pays authoring latency and review overhead for durability the task does not need. Escalate to tier 3 only when the task requires a workflow-only feature (an approval gate, phases needing different models, parallel lanes, reuse). Neither “it feels big” nor the existence of a seeded workflow with a matching name (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:
For a built-in oneshot, this opens the dedicated oneshot monitor. It includes the live implement and review transcripts, diff, durable event log, pause and cancel controls, plus:
  • 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. Use bunx smthrs hijack RUN_ID for interactive takeover.
  • Restart: after confirmation, cancel the active attempt if needed and launch a fresh run from the durable builtinResume argv 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.
The oneshot UI, the 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