Smelt ideas, skim the bugs, forge the product.
Task orchestrator for AI-powered development. Breaks requirements into S-expression ingots and forges them with its own agentic engine speaking straight to the OpenRouter API: tool loop, retries, re-smelt recovery, proof-gated commits. One binary, one key, no vendor CLI to install first.
curl -sSf https://slag.dev/install.sh | sh
slag key
slag "Build a REST API with auth and rate limiting"
slag --tui "Build a REST API with auth and rate limiting"
One OpenRouter key is the whole setup. No Claude CLI, no vendor login, no model to pick: every role runs on openrouter/auto until you override it. The key is verified before it is saved, and lives in ~/.config/slag/config.toml at mode 0600. Already have OPENROUTER_API_KEY exported? Skip step two.
slag runs shell commands and edits files in the directory you start it in. Point it at a fresh directory or a repo you can revert.
The published build is macOS on Apple Silicon. Elsewhere, clone the repo and run cargo install --path slag-rs.
High-grade ingots get cast twice in separate git worktrees. A judge model assays both casts and merges the winner; a split verdict discards both and re-casts with the critique. Fires when cast B (SLAG_MODEL_ALT) differs from the worker model, or per ingot via :duel t.
--tui opens a full-screen dashboard: crucible state, live event feed, token totals. Type a message and press Enter to steer the smith mid-forge without stopping the run.
A lightweight interpreter turns raw tool calls into one-line narration on the feed, so you read "wiring the auth routes" instead of a wall of diffs and greps.
Drop recipes/<name>/RECIPE.md files (frontmatter + markdown) in your repo or ~/.config/slag/recipes/. slag indexes them into every ingot prompt and the smith loads them by name.
Dollar ceilings per ingot session (SLAG_MAX_COST_INGOT) and per run (SLAG_MAX_COST_RUN), or max_cost_per_ingot / max_cost_per_run in the config file. Default is uncapped.
Every ingot carries a :proof shell command. Exit 0 forges the ingot and commits; anything else feeds the error back and retries. No commit lands without its proof passing.
All four model roles (work, plan, duel, judge) route through openrouter/auto until you pin one. A fresh key forges with zero model configuration.
PRD.md PROGRESS.md (ore) (ledger) | ^ v | +-----------+ +--------------+ +--------+ +-------+ | SURVEYOR |--->| FOUNDER |--->| FORGE |--->| ASSAY | | analyze | | cast ingots | | strike | | report| +-----------+ +--------------+ +--------+ +-------+ | | | v v v BLUEPRINT.md PLAN.md git commits (analysis) (s-expr ingots) (per ingot)
PICK ORE PARALLEL ANVILS | +---------+---------+ v | | | :solo t? ----yes-----> ANVIL 1 ANVIL 2 ANVIL 3 | | | | no v v v | (each anvil runs its own smith session) v SELECT SMITH by :grade | | grade >= 3 --> plan model | default --> work model | both --> openrouter/auto v STRIKE (agent session over OpenRouter) | v TOOLS (read, write, edit, grep, bash) | v PROOF (run :proof shell command) | +----- pass ----> :forged + git commit | +----- fail ----> :heat++ retry with slag feedback | +----- max -----> :cracked + on to the next ingot (the run keeps going; ASSAY reports the cracks and the run exits 1 once nothing is pending)
Deep analysis on the plan model. Reads PRD.md (ore), produces BLUEPRINT.md with architecture, dependency graph, risk assessment, and forging sequence. Self-iterates to resolve any ambiguity.
Casts S-expression ingots from the blueprint. Each ingot has an ID, complexity grade, skill tag, proof command, and work description. Outputs PLAN.md as the crucible.
Strikes each ingot with an agent session over OpenRouter. Solo ingots run on parallel anvils (up to 3). Grade picks the model. Retries with slag feedback on failure. Commits on success.
Final quality report. Shows forged/cracked counts, temperature bar, and identifies any cracked ingots. It prints on failed runs too, not only clean ones. Exits 0 on full forge, 1 if any ingot cracked.
slag speaks to OpenRouter and nothing else. That is one credential to paste, one bill to read, and every model on the router reachable by id. The four roles (work, plan, duel, judge) all default to openrouter/auto, so a fresh key forges without you choosing a model. Override any role when you have an opinion: a flag, an environment variable, or a line in ~/.config/slag/config.toml. The file wants the lowercase key; the uppercase name is the environment variable and is ignored inside the file.
| Role | Env var | config.toml key | Flag |
|---|---|---|---|
| work | SLAG_MODEL_BASE |
model_base |
--model |
| plan | SLAG_MODEL_PLAN |
model_plan |
--plan-model |
| duel | SLAG_MODEL_ALT |
model_alt |
|
| judge | SLAG_MODEL_JUDGE |
model_judge |
--judge-model |
The key itself, the duel knobs, and the spend caps follow the same rule: openrouter_api_key, duel, duel_rounds, screenshot_cmd, max_cost_per_ingot, max_cost_per_run in the file; OPENROUTER_API_KEY, SLAG_DUEL, SLAG_DUEL_ROUNDS, SLAG_SCREENSHOT_CMD, SLAG_MAX_COST_INGOT, SLAG_MAX_COST_RUN in the environment.
S-expressions are single-line and grep-parseable, so PLAN.md stays readable by you and by a one-line shell command. Every ingot is one line. Fields are keyword-prefixed (:id, :status), which makes them unambiguous to extract with pattern matching and cheap for a model to emit correctly.
Independent ingots (:solo t) run concurrently, up to MAX_ANVILS=3. This gives 3x throughput for foundation tasks that have no dependencies. Each anvil gets its own smith session. Sequential ingots (:solo nil) run one at a time after parallel work completes.
Every ingot carries a :proof field containing a shell command. Exit code 0 means pass, anything else means fail. No human review needed. Proofs are concrete: "test -f file", "npm test", "grep -q pattern file". This enables fully autonomous forging with machine-verifiable quality gates.
When a surveyor or founder output contains questions, slag detects them and feeds the output back with instructions to resolve autonomously. Up to 3 rounds. This prevents the forge from stalling on ambiguity. The AI is instructed to make expert decisions rather than ask for clarification.
Unambiguous vocabulary that maps naturally to the pipeline. Ore (raw input) is surveyed, cast into ingots, heated in a forge, and either becomes forged steel or cracked waste. Every term has exactly one meaning. The temperature gradient (cold → hot → pure) maps to progress from unstarted to complete.
| Field | Values | Meaning |
|---|---|---|
:id |
"i1", "i2", ... | Unique ingot identifier |
:status |
ore | molten | forged | cracked | Lifecycle state |
:solo |
t | nil | Can run in parallel (t) or must be sequential (nil) |
:grade |
1-5 | Complexity level; grade ≥ 3 uses the plan model |
:skill |
web | api | cli | default | Work-type tag. Today only web changes anything: Playwright note in the prompt, duel screenshots |
:heat |
0-N | Current retry attempt |
:max |
5-8+ | Max retries before cracking |
:smelt |
0 | 1 | Re-smelt count. A cracked ingot gets one rewrite; at 1 it cracks for good |
:proof |
shell command | Acceptance test (exit 0 = pass) |
:work |
string | Task description for the smith |
:duel |
t | nil | Twin-cast override: t forces a duel, nil blocks one, absent follows SLAG_DUEL |
Those eleven are every field the parser reads. Any other :key value pair survives a rewrite untouched.
| Command | Role |
|---|---|
slag "commission" | Write PRD.md from the commission and run the full pipeline |
slag | Forge the PRD.md already in this directory |
slag key [KEY] | Show setup, or verify and store an OpenRouter key |
slag status | Show crucible state |
slag resume | Resume an existing forge |
slag update | Self-update to the latest release |
| Flag | Effect |
|---|---|
--tui | Full-screen dashboard: crucible, live feed, steering input |
--anvils N | Max parallel anvil workers (default 3) |
--auto | Force openrouter/auto on all four roles, ignoring pinned models |
--model MODEL | Worker model, any OpenRouter id |
--plan-model MODEL | Planner model for grade ≥ 3 ingots |
--judge-model MODEL | Duel judge model |
--worktree | Branch-per-ingot isolation. Not implemented yet: warns and runs in the shared checkout |
| Environment variable | Effect |
|---|---|
OPENROUTER_API_KEY | The key. Overrides the stored one |
SLAG_MODEL_BASE / _PLAN / _ALT / _JUDGE | Per-role model ids |
SLAG_DUEL | auto (default) / on / off |
SLAG_DUEL_ROUNDS | Override the duel round cap |
SLAG_MAX_COST_INGOT | Dollar ceiling for a single ingot session |
SLAG_MAX_COST_RUN | Dollar ceiling for the whole run |
SLAG_REASONING_EFFORT | low / medium / high for models that take it |
SLAG_SCREENSHOT_CMD | Shell command producing a screenshot for visual assay of web ingots |
SLAG_CHAR_BUDGET | Transcript char budget before an agent session compacts |
SLAG_CONFIG_DIR | Move the config directory off ~/.config/slag |
SLAG_OPENROUTER_BASE | Point slag at a proxy instead of OpenRouter |
NO_COLOR / COLORTERM | Drop color entirely / enable truecolor |