Point slag at an issue. It writes a regression test, fixes the code, and proves the fix with your own tests. You review one commit on a branch, or a draft PR with --pr. One flag picks the provider. Hand it a sentence instead and it forges a whole project in proof-gated ingots.
curl -sSf https://slag.dev/install.sh | sh
slag fix "export drops the last day of the range"
slag fix 123 --provider cerebras --pr
slag "Build a REST API with auth and rate limiting"
slag --tui "Build a REST API with auth and rate limiting"
slag needs one key from one provider. Choose the provider with --provider NAME, SLAG_PROVIDER, or provider = "NAME" in ~/.config/slag/config.toml: openrouter (the default), openai, anthropic, gemini, groq, cerebras, xai, mistral, deepseek, together, fireworks, ollama, lmstudio, or custom. Each preset brings its base URL and a default model. slag reads the provider's key variable, such as CEREBRAS_API_KEY, or the key that slag key --provider NAME stores. ollama and lmstudio need no key.
slag fix takes free text, an issue number, a GitHub issue URL, or --issue-file. It runs your tests before any edit, writes a regression test, fixes the code, and reruns the tests itself. Then it reverts the fix to show the new test fails without it. The fix lands as one commit on a slag/fix-<slug> branch (slag/fix-<n>-<slug> for a GitHub issue). --pr pushes it and opens a draft PR; --no-commit leaves it in the working tree.
slag runs shell commands and edits files in the directory you start it in. Its sandbox keeps shell writes inside that directory and temp space, while reads and the network stay open. Point it at a fresh directory or a repo you can revert.
Releases ship for macOS (Apple Silicon and Intel) and Linux (x86_64 and aarch64, glibc 2.17 or newer). Elsewhere, clone the repo and run cargo install --path slag-rs.
A solo ingot can forge as two or three casts in separate git worktrees, each steered by its own direction prompt, so even one model explores different solutions. A judge model assays the casts and merges the winner. SLAG_DUEL=auto (the default) picks 1 to 3 casts by grade and work; on, off, or :duel t per ingot override it.
--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.
Spend lines show the cost OpenRouter reports, or an estimate from a dated price list (≈ $0.0031 est.). An unknown price shows token counts, and a [pricing] table overrides any rate. Dollar ceilings per ingot session (SLAG_MAX_COST_INGOT) and per run (SLAG_MAX_COST_RUN) are uncapped by default.
The smith's shell commands write only inside the workspace and temp directories: Seatbelt on macOS, bubblewrap or Landlock on Linux. Package caches and the repo's git hooks and config stay read-only. Proofs and slag fix test runs use the same sandbox. --no-sandbox or SLAG_SANDBOX=off turns it off.
Every forge records a tape in .slag/logs/, and slag replay plays it through the same renderers, in the stream view or the dashboard, at any speed, and can hold a frame at a named moment. It needs no key and no network.
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.
--provider picks one of 14 presets, from openrouter and openai to cerebras, groq, and a local ollama. Each brings its base URL and a default model, so a fresh key forges with no model to choose. Write provider::model to run one role elsewhere: --provider cerebras --plan-model openai::gpt-4.1-mini.
slag fix skips the survey and the plan. One agent session adds a regression test and fixes the bug. slag reruns your tests itself and reverts the fix once to prove the new test catches the bug. The verdict comes from exit codes, not from the model's summary.
PRD.md PROGRESS.md (ore) (ledger) | ^ v | +-----------+ +--------------+ +--------+ +-------+ | SURVEYOR |--->| FOUNDER |--->| FORGE |--->| ASSAY | | analyze | | cast ingots | | strike | | report| +-----------+ +--------------+ +--------+ +-------+ | | ^ | v v | v --temper N BLUEPRINT.md PLAN.md | +---------+ (analysis) (s-expr ingots) | | TEMPER | +-- gap --| warden | +---------+ New commissions keep these files in .slag/.
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 | unset --> the provider's default v STRIKE (agent session over your provider) | 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 .slag/PRD.md (ore), produces .slag/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 .slag/PLAN.md as the crucible.
Strikes each ingot with an agent session over your provider. Solo ingots run on parallel anvils (up to 3). Grade picks the model. Retries with slag feedback on failure. Commits on success.
Opt in with --temper N. A warden on the plan model, a critic that built nothing, writes the acceptance bar to .slag/BAR.md and checks the blueprint and the plan against it first. After the forge it opens the built project, runs its checks in a read-only sandbox, and compares the result with the bar. On a loss, the gap it names becomes new ingots and the forge runs again, up to N rounds.
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 the OpenAI-compatible chat-completions API, so any provider that serves it works, local ones included. OpenAI GPT-5.4 and later go through the Responses API instead. A preset brings the base URL and a default model for every role, so a fresh key forges without you choosing a model. OpenRouter stays the default. Override any role when you have an opinion: a flag, an environment variable, or a line in ~/.config/slag/config.toml. Write provider::model to send one role to another provider; the :: keeps OpenRouter ids such as openai/gpt-5 working. 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 |
| editor | SLAG_MODEL_ |
model_ |
--editor- |
The editor role writes harness edits for slag fix --evolve and defaults to the plan model. The provider, its key, the duel knobs, and the spend caps follow the same rule: provider, <provider>_api_key (such as openai_api_key), duel, duel_rounds, screenshot_cmd, max_cost_per_ingot, max_cost_per_run in the file; SLAG_PROVIDER, the provider's key variable (such as OPENAI_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) |
:bar |
string | The ingot's acceptance bar. With --temper, the warden judges it after the proof passes; empty means the proof alone decides |
:work |
string | Task description for the smith |
:duel |
t | nil | Twin-cast override: t forces a duel, nil blocks one, absent follows SLAG_DUEL |
:casts |
1 | 2 | 3 | Cast-count override; absent follows SLAG_DUEL and the grade |
Those thirteen are every field the parser reads. Any other :key value pair survives a rewrite untouched.
| Command | Role |
|---|---|
slag fix ISSUE | Fix one issue in this repository and commit it on a new branch. Takes free text, an issue number, or a GitHub issue URL. --pr opens a draft PR. --tries N, --test CMD, --temper, --tui, --model and --plan-model tune the run |
slag fix --evolve K | Experimental. Evolve the harness on this issue first (Harness², arXiv 2610.14224). It costs several fix attempts, capped at $2 by default. On slag's own bench it has not beaten plain --tries 4. --harness library reuses past lessons with no probing |
slag "commission" | Write .slag/PRD.md from the commission and run the full pipeline |
slag | Forge the .slag/PRD.md already in this directory |
slag key [KEY] [--provider NAME] | Show provider setup or store its key |
slag cost | Show session spend, and the provider balance when available |
slag status [--json] | Show crucible state; --json prints one object for scripts |
slag resume | Resume an existing forge |
slag replay FILE | Play a recorded tape through the renderers. --speed, --tui, --at, --points |
slag runs | List past runs from the event logs |
slag insights | Offline analytics over the logs: forged and cracked ingots, heats, spend, tool errors |
slag ps | List live forges on this machine |
slag rewind | Restore the workspace from an attempt checkpoint |
slag hooks list | Print the hook events and the exit-code contract |
slag update | Self-update to the latest release |
| Flag | Effect |
|---|---|
--provider NAME | Provider preset (overrides SLAG_PROVIDER) |
--tui | Full-screen dashboard: crucible, live feed, steering input |
--temper N | Judge the result against the goal with the warden, up to N rounds (default 0, off) |
--anvils N | Max parallel anvil workers (default 3) |
--auto | Reset all roles to the selected provider's default model, ignoring environment and config model settings |
--model MODEL | Worker model ID or provider::model |
--plan-model MODEL | Planner model ID or provider::model, also for grade ≥ 3 ingots |
--judge-model MODEL | Duel judge model ID or provider::model |
--duel | Give every solo ingot at least two casts (same as SLAG_DUEL=on) |
--trace FILE | Write a Chrome trace-event file, one lane per anvil |
--force | Accept a one-word commission instead of reading it as a mistyped subcommand |
--no-sandbox | Let shell commands write outside the workspace (same as SLAG_SANDBOX=off) |
--worktree | Branch-per-ingot isolation. Not implemented yet: warns and runs in the shared checkout |
| Environment variable | Effect |
|---|---|
OPENROUTER_API_KEY, OPENAI_API_KEY, CEREBRAS_API_KEY, … | The provider's key. Overrides that provider's stored key |
SLAG_PROVIDER | Default provider; --provider takes precedence |
SLAG_BASE_URL | Override the selected provider's API root |
SLAG_<PROVIDER> | Override one provider's API root in a mixed run |
SLAG_MODEL_BASE / _PLAN / _ALT / _JUDGE / _EDITOR | Per-role model ids |
SLAG_SANDBOX | auto (default) / off for the shell sandbox |
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_EVOLVE_BUDGET / SLAG_EVOLVE_TOKENS | Dollar and token caps for --evolve (defaults 2 and 4000000) |
SLAG_HARNESS_LIBRARY | Harness library directory for --evolve and --harness |
SLAG_DISABLE_HOOKS | Turn off every [hooks] entry for this 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 | Legacy OpenRouter-only base URL override |
NO_COLOR / COLORTERM | Drop color entirely / enable truecolor |