Binary: slmcode. Every command has --help; slmcode --help groups them.
slmcode --help
slmcode <command> --helpEvery command is safe to call from a script, a CI job or another agent.
- Colour. ANSI escapes are emitted only when stdout is a terminal,
TERMis notdumb, andNO_COLORis unset.slmcode status | catis plain text. Override with--color=auto|always|neverorFORCE_COLOR=1. - JSON.
--jsonis available onstatus,doctor,readiness,board,version,apply,compose,task show,blocks list,hooks list,auth list,auth get, everyconfigsubcommand exceptconfig set, and everymemory/evolve/metricssubcommand. It writes a single JSON document to stdout with colour forced off; diagnostics go to stderr. - Prompts. Nothing prompts without a TTY.
slmcode applyrefuses interactive review (exit 2) and points at--all/--list/--json;slmcodewith no workspace refuses to scaffold (exit 3);slmcode updateneeds--yes. - HITL gates. With a TTY on stdin and stdout they render inline and block until
answered — they never expire into an automatic decision. Without a TTY the decision is taken at
run start, before the first model call, and logged: with
--on-gate-timeoutunset the plan / clarify / continue / escalate gates answer themselves with "yes"; an explicit--on-gate-timeout=stop|rejectrefuses the run at the door (exit 6) rather than planning for minutes and discarding the result.shell_permission=askis a safety gate and never auto-approves — headless it refuses up front. - Errors. A failure is reported exactly once, on stderr, prefixed with
✖.
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | generic failure |
| 2 | usage error / invalid argument / a TTY was required |
| 3 | workspace not initialized |
| 4 | provider check failed — run pre-flight found nothing listening, or doctor found an unreachable endpoint, a rejected key or a missing model |
| 5 | the run completed but tasks failed |
| 6 | a human-in-the-loop gate could not be answered |
| 130 | interrupted (SIGINT/SIGTERM); a second interrupt force-quits |
| Flag | Notes |
|---|---|
--root |
Project root (default: cwd) |
--provider |
SLMCODE_PROVIDER. Never clobbers an endpoint set by flag, env, or an explicit non-default config value |
--model |
SLMCODE_MODEL |
--endpoint |
SLMCODE_ENDPOINT |
--api-key |
SLMCODE_API_KEY / provider-specific |
--backend |
slmcode (default) or claude-code |
-v / --verbose |
same as --log-level=info |
--vv |
same as --log-level=debug |
--log-level |
error|warn|info|debug — what the CLI renders |
--color |
auto (default) | always | never |
--dry-run |
do not write code files |
--parallel |
max parallel workers |
--retries |
review/correct retries |
--think-passes |
multi-pass think loops |
--on-gate-timeout |
approve|reject|stop — what a HITL gate does with no TTY. Unset + no TTY: convenience gates auto-approve and say so. An explicit stop/reject refuses the run before any model call |
--no-explore |
greedy bandit, no exploration — reproducible runs (config: deterministic) |
--evolve / --no-evolve |
force the self-improvement engine on/off for this run |
--max-task-calls |
per-task LLM call budget (config: max_task_calls) |
--architect-editor |
enable the describer→editor role pair (config: architect_editor) |
--structured-decoding |
auto|off — constrained decoding policy |
--no-banner |
hide the ASCII banner — help, studio, the TUI and version |
--version |
print the version and exit; slmcode version is the detailed form (--check queries GitHub) |
Lowest precedence first: built-in defaults → user file → project file (.slmcode/config.yaml) →
SLMCODE_* environment → command-line flags. slmcode config show --origin attributes each
effective value to default | user | project | env SLMCODE_X | flag --x.
The user file is discovered by pkg/config, so the layer applies to Studio, the TUI and any
embedder as well as the CLI. Candidates, most specific first: $SLMCODE_USER_CONFIG,
$XDG_CONFIG_HOME/slmcode/config.yaml, ~/.slmcode/config.yaml,
~/.config/slmcode/config.yaml. Write to it with slmcode config set --user <key> <value>.
A saved config.yaml records intent: only the keys that differ from what the project would
otherwise inherit, plus a config_version stamp. So config show --origin can tell a choice from
an inherited default, a new release's improved default reaches existing projects, and no absolute
path is embedded in a file that may be committed. Older files are migrated forward on load, and
config show says when that happened.
| Command | Purpose |
|---|---|
slmcode / tui |
Interactive TUI (default with no subcommand) |
init |
Create .slmcode/ memory, board, config, and a .slmcode/.gitignore |
run [query…] |
Full pipeline, or a single specialist |
chat |
Classic REPL |
studio |
Studio web UI + SSE API |
watch |
Live-refreshing kanban |
| Command | Purpose |
|---|---|
apply [path…] |
Review and apply pending agent writes (permission: review) |
reject [path…] |
Discard pending proposals |
diff [path…] |
Working-tree diff |
commit |
git add -A + commit helper |
| Command | Purpose |
|---|---|
configure |
Find a model server and write a working config — start here |
config |
show · get · set · unset · schema · path |
stack |
list · show · apply · edit · new — provider/model presets |
agent |
list · show · edit · clear-llm — per-agent LLM pins |
blocks |
list · show · new · edit · delete · apply · validate |
skills |
list · show · new · edit · path |
hooks |
list · trust · untrust — inspect and approve .slmcode/hooks.json |
update |
Refresh the binary release or rebuild from source |
| Command | Purpose |
|---|---|
status |
Query, provider, board counts, plan gate, connection probe, pending count |
board |
Kanban snapshot; flags tasks that need a human and names the one to inspect |
task show <id> |
Why a task stopped — scope, acceptance, last output, review verdict and issues, the gate that blocked it, and the diff of its focus files (--json, --no-diff) |
compose [query…] |
Preview the dynamic pipeline — no LLM call, no writes |
readiness / ready |
Score local-SLM readiness; --fix applies safe defaults |
task |
add · show · edit · move · delegate · check · uncheck · promote · rm |
context |
Show / append to CONTEXT.md |
docs |
List / show / edit markdown memory |
plan |
Show PLAN.md |
session |
list · show · resume |
doctor |
Provider / model / endpoint / workspace health |
eval |
Evaluation harness |
memory |
show · episodes · facts · forget |
evolve |
rules · why · regressions · reset |
metrics |
show · compare |
version |
Version metadata (--check queries GitHub) |
completion |
bash|zsh|fish|powershell |
slmcode run -v "add JWT auth"
slmcode run --agent explorer "Where is auth handled?"
slmcode run --mode specialist --agent worker "…"
slmcode run --skill atomic-coding "Refactor helpers"
slmcode run --dynamic "add JWT auth" # force task-specific composition
slmcode run --no-dynamic "tiny typo fix" # force the static pipeline
slmcode run --think-passes 2 --parallel 2 --retries 2 "…"
slmcode run "…" # headless: gates auto-approve, logged
slmcode run --on-gate-timeout=stop "…" # headless: refuse up front instead
slmcode run --issue 42 # take the query from a GitHub issue
slmcode run --isolate worktree "…" # work in a throwaway git worktree
slmcode run --issue 42 --deliver pr --draft # …and open a draft PR when it passes| Flag | Meaning |
|---|---|
--mode |
full | specialist (overrides config) |
--agent |
run a single specialist |
--skill |
pin/load a skill by name (repeatable); @skill:name in the query also works |
--dynamic / --no-dynamic |
override dynamic_pipeline for this run |
dynamic_pipeline defaults on: the composer selects a task-specific subset of phases, agents,
slots and execute-loop roles before workers run. It also assigns a budget class — see
Budget classes below.
While you type, Studio shows a provisional pipeline: a deterministic guess assembled from the query text alone, without reading the repository. The composer agent decides the real one when the run starts, so expect it to change. The guess picks language specialists from the repository's detected language, and only lets a language named in the query override that when the workspace actually contains files of that language — otherwise a Go project could be handed Python workers because the sentence happened to mention Python.
--issue takes the query from a GitHub issue instead of the command line. It accepts an issue
URL, owner/repo#123, or a bare number, and needs the gh CLI
authenticated. Extra words on the command line refine the issue rather than replacing it:
slmcode run --issue 42 "focus on the parser only"The issue body is untrusted text. It is framed as a report rather than pasted as instructions, harness markers inside it are defused so it cannot forge gate evidence, and it is truncated so a long issue cannot evict the repo map and file excerpts from the context pack.
--isolate worktree runs against a throwaway git worktree instead of your checkout. Your
working tree is never written to while the run is in flight; on success the branch is merged back,
on failure the whole worktree is deleted in one operation.
| Flag | Meaning |
|---|---|
--isolate |
worktree | none (default: none, in-place) |
--branch |
branch to work on (default: generated) |
--keep-worktree |
keep the branch when an isolated run fails, to inspect it |
Harness state stays in your checkout's .slmcode/ while the work happens in the worktree, so
memory, the board and the learned policy keep accumulating where they belong. Isolation needs a
git repository with at least one commit; it refuses up front, before the run starts, when it
cannot be used.
--deliver pr opens a pull request when the run succeeds. It always asks first, printing the
branch, title and the exact file list — with no TTY it refuses unless --yes is given.
| Flag | Meaning |
|---|---|
--deliver |
pr opens a pull request (asks first) |
--base |
pull request base branch |
--draft |
open the pull request as a draft |
--yes |
skip the confirmation (required with no TTY) |
Only the files the run's completed tasks named are staged — never git add -A — so unrelated work
in your tree is left alone. The PR body carries the task list and the acceptance criteria that were
verified. With --isolate worktree, a delivered PR is the delivery: the branch is left for review
rather than also being merged locally.
The composer classifies each request on two axes — complexity (trivial, simple, standard,
critical) and kind (inquiry, task, debug) — and the pair decides how much of the run's
budget it is worth: which optional phases run, how many corrective waves, how many think passes and
QA rounds, and whether the strict reviewer engages.
slmcode compose "fix the typo in README.md" # → trivial:task · 5 phases · 1 wave
slmcode compose "rotate the production API key" # → critical:task · 12 phases · 4 wavesA class may lower cost below your configuration but never re-enables a gate you switched off. The
only gate a class turns off is the smoke requirement for a read-only inquiry, which writes
nothing and so could never satisfy it.
The last block of every run — successful or not — answers "what changed and what do I do now".
When files changed:
duration 41.2s
tasks 2/3 done · 1 awaiting a human
board .slmcode/board.json
Changes
3 files · +47 −12
pkg/auth/jwt.go +31 -2 ++++++++++++++++
pkg/auth/jwt_test.go +14 -0 +++++++
README.md +2 -10 ++--------
Next
slmcode diff the full patch, file by file
slmcode commit -m "…" keep it
slmcode task show T3 why T3 stopped: verdict, gate and diff
When nothing changed — the most common outcome of a small local model, and the one the CLI used to be silent about:
Changes
⚠ no files changed — nothing was created, modified or deleted on disk
the model's edits were refused before they reached the tree (usually: an edit was claimed but never made)
Next
slmcode task show T1 why T1 stopped: verdict, gate and diff
slmcode run --vv "…" re-run with the full agent transcript
Details worth knowing:
- The change set is what this run did. Files that were already dirty when the run started and
that the run did not touch are excluded, and
.slmcode/harness state never counts. permission: reviewstages edits instead of writing them, so the block saysN proposed edit(s) are held for review and have NOT been written yetand offersslmcode applyfirst.tasksseparates verified done from human overrides: answering[d]oneat the escalate gate closes a task the evidence gate refused, and the summary says1 human override — you answered [d]one at the escalate gaterather than folding it into the done count.slmcode boardmarks the same task⚑ forced done.errors .slmcode/errors/errors.mdappears only when that file actually holds something.- The same block prints when a run fails, dies at a gate or is interrupted — "did my files change?" is a more urgent question after a failure than after a success.
The first command to run, and the one to run when nothing works.
slmcode configure # look around, then ask before writing
slmcode configure --yes # accept the best candidate
slmcode configure --dry-run # show what it would write and stop
slmcode configure --json # machine-readable
slmcode configure --endpoint http://127.0.0.1:1234/v1
slmcode configure --model Qwen3-Coder-30B-A3B-Instruct
slmcode configure --user # write to the user config, not this projectIt probes the configured endpoint first, then the addresses local model servers listen on (oMLX, Ollama, LM Studio, vLLM), then any hosted provider whose API key is already in the environment. Candidates are probed at once, so a machine with nothing running answers in a couple of seconds rather than waiting out each address in turn.
Looking for a model server…
✗ omlx http://127.0.0.1:8000/v1 — nothing is listening
✗ ollama http://127.0.0.1:11434 — nothing is listening
✓ lmstudio http://127.0.0.1:1234/v1 — 3 model(s) in 3ms (default lmstudio address)
provider lmstudio
endpoint http://127.0.0.1:1234/v1
model Qwen3-Coder-30B-A3B-Instruct-MLX-4bit
tuned for code (coder), instruction-tuned, 30B, 3B active
also available: Qwen2.5-1.5B-Instruct
A model server serves whatever it was given, and the list is rarely all chat models — embedding models, rerankers, speech, vision and safety classifiers sit next to the one you want. Picking one of those produces a failure that is baffling rather than obvious: the harness runs, the model answers, and nothing it says is JSON.
So the ranking rules those out first, then prefers coder-tuned over
instruction-tuned over larger. A mixture-of-experts name is read correctly, so
30B-A3B is a 30B model with 3B active rather than a 3B one. Matching is on
whole name segments rather than substrings — codestral contains tts and
instruct contains stt.
- Replace a working configuration. The endpoint you set is probed first and kept if it answers. Re-detecting around a working setup is how a tool moves somebody's configuration out from under them.
- Send your API key to a local port. A key travels only to the endpoint you
configured, or to a hosted provider offered because that provider's own key is
present — never to
127.0.0.1:1234because LM Studio might be there. - Second-guess
--endpoint. That flag is an instruction: a dead address you named fails rather than falling through to whatever else is running.
The three real problems have different fixes, so they are reported differently: nothing listening, a server with no models loaded, and a server whose models cannot write code. Collapsing them into "no endpoint found" is what sends somebody to restart a server that is already running.
slmcode configure is also the remedy named when a run refuses to start
because the endpoint is down or the configured model is not served. In the
Studio it is the Find my model server panel in Settings, with the same two
steps: Look around changes nothing, Configure for me writes.
slmcode init used to end with "no model server answered" and a pointer at
slmcode doctor — two more commands for somebody who has just scaffolded a
workspace, when a server is often running on a port that is simply not the
default. It now looks around and adopts what it finds:
⚠ no model server answered at http://127.0.0.1:8000/v1
looking for one elsewhere…
✔ found lmstudio at http://127.0.0.1:1234/v1
model Qwen3-Coder-30B-A3B-Instruct-MLX-4bit
why tuned for code (coder), instruction-tuned, 30B, 3B active
Only when the configured endpoint did not answer, so it can never move a
working setup, and never when you pinned --endpoint or SLMCODE_ENDPOINT —
that is a statement about where the server is, and configuring something else
would be the tool arguing with you.
slmcode compose "add JWT auth"
slmcode compose --json "add JWT auth"Deterministic inspection only — it does not call the LLM and does not write code. Shows the phases, the team, the execute loop and the SLM-fit assessment the run would use.
slmcode readiness # scores provider/model reachability + safe SLM defaults
slmcode readiness --fix # apply the safe config patch it recommends
slmcode readiness --no-probe # skip the endpoint/model availability check
slmcode readiness --jsonExits non-zero when required checks fail.
slmcode apply is interactive by default: each pending change is rendered as a coloured
unified diff and you choose what happens to it.
| Key | Action |
|---|---|
a (or y) |
apply this file |
s (or n, or Enter) |
skip — stays pending |
r |
reject — discard the proposal |
e |
open the proposal in $EDITOR, re-diff, ask again |
v |
view the full diff (no line cap) |
A |
apply this and everything after it |
q |
stop and summarise |
File modes are preserved when a proposal is written.
slmcode apply --list # summary of what is waiting
slmcode apply --json # machine-readable pending set (implies no prompts)
slmcode apply --all # apply everything without prompting
slmcode apply pkg/x.go # only files matching a path prefix
slmcode reject pkg/x.go
slmcode reject --allWithout a TTY, slmcode apply exits 2 and names the three non-interactive options.
The answer to "why did T1 stop?". T1 needs human review is the most common terminal state of a
local-SLM run, and this is where it stops being a dead end.
slmcode task show T1 # scope, verdict, gate, and the diff of its focus files
slmcode task show T1 --no-diff # skip the diff
slmcode task show T1 --json # task, verdict, gate, gate reason, answerIt renders, in the order a human needs them:
| Section | What it answers |
|---|---|
| header | the column, the role, retry count, focus files — and ← forced done by a human when someone overrode the evidence gate |
| Scope | what the task was asked to do |
| Acceptance criteria | how it was going to be judged |
| Last output | the agent's final JSON, with files_changed labeled as a claim |
| Review verdict | approved/rejected, score, summary, and each issue |
| Gate | which gate refused it, how many times, the escalate question and how it was answered |
| Diff of focus files | what those files actually look like now — or an explicit "no change on disk" |
| Next | the commands that move it forward from this terminal |
Repeated engine notes are collapsed (… ×200), and Studio-only advice in engine-authored text is
rewritten into a command this binary has.
slmcode board flags the tasks worth opening (⚑ needs you, ⚑ blocked, ⚑ forced done) and
names one in its tip.
slmcode studio # default port 7420, auto-picks a free one if busy
slmcode studio --listen :9000
slmcode studio --no-port-auto # fail instead of moving to a free port
slmcode studio --kill # terminate an existing slmcode on that port first
slmcode studio --dev-cors # allow the Vite dev server (npm run dev in web/)
slmcode studio --no-auth # drop the session token (loopback enforcement stays)Studio mints a per-run session token and prints it in the URL (http://127.0.0.1:7420/?t=…) —
open that URL, or /api/* returns 401. --kill only ever signals a process whose executable
is exactly slmcode. Ctrl+C shuts down gracefully. See Studio.
.slmcode/hooks.json runs shell commands around tool calls, and it lives inside the project — so
the harness fails closed on it. Nothing runs until both hooks_enabled: true and an explicit
per-content approval from you.
slmcode hooks list # every command the file would run, and whether it is trusted
slmcode hooks list --json
slmcode hooks trust # prints the commands, then asks; -y skips the prompt
slmcode hooks untrust # withdraw approvalThe listing always prints the commands before asking, and never executes them. Approvals are
keyed on (absolute path, SHA-256 of the file) and stored in your OS config directory, never in
the repository — so a repo cannot ship its own approval, and editing hooks.json revokes it.
SLMCODE_TRUST_HOOKS=1 force-trusts every hooks file on the machine (for CI images that generate
their own). hooks list says so when it is set. Details → Permissions §10.
| Exit | Meaning |
|---|---|
| 0 | listed / trusted / untrusted |
| 1 | the hooks file does not parse, or declares no commands |
| 3 | there is no hooks file to trust |
| 6 | you answered "no" at the approval prompt |
slmcode stack list
slmcode stack show deepseek
slmcode stack apply omlx-local
slmcode stack apply deepseek --clear-agent-llm # agents inherit the stack LLM
slmcode stack apply openai --agents # also write optional role pins
slmcode stack apply openai --agents --force-agents
slmcode agent list # agents with their effective LLM
slmcode agent show worker
slmcode agent edit worker model=… provider=… # pin; empty = inherit the stack
slmcode agent clear-llm workerShipped stacks (13, stacks/*.yaml): omlx-local, mlx-qwen-coder, ollama-local,
ollama-qwen-coder, ollama-qwen3-coder, lmstudio-local, vllm-local, openai,
openrouter, deepseek, groq, google, qwen. slmcode stack list prints the live set.
Details → Providers.
slmcode blocks list
slmcode blocks list --json
slmcode blocks show pipeline go
slmcode blocks apply go
slmcode blocks apply python --materialize-agents
slmcode blocks apply react --force
slmcode blocks new agent my-worker --file ./my-worker.yaml
slmcode blocks validateDetails → Blocks.
slmcode config show
slmcode config show --origin # where each effective value came from
slmcode config show --json
slmcode config get max_parallel
slmcode config set max_parallel 6
slmcode config unset fast_model
slmcode config set --user model qwen2.5-coder:14b # write the user-level layer
slmcode config schema # machine-readable field schema
slmcode config pathBare slmcode config prints help — use config show. Full field list →
Config reference.
Keys belong in .slmcode/auth.json or the environment, not in committed YAML.
Measures what the configured (model, endpoint) pair can actually do —
concurrency knee, latency baseline, decode rate, context window — instead of
guessing it from the provider name.
slmcode calibrate # measure (or reuse) the active pair
slmcode calibrate --force # re-measure regardless of the cache
slmcode calibrate --show # print stored profiles, probe nothing
slmcode calibrate --json
slmcode calibrate --model Qwen3.5-9B-MLX-4bitIt runs automatically, once, when a run meets an unseen pair. The full level
table is printed so the chosen max_parallel is checkable rather than magic,
and values you have set explicitly are never overridden. Details →
Calibration.
slmcode memory show --role worker # the memory block a role actually receives
slmcode memory episodes 20 # recent runs the harness remembers
slmcode memory facts --kind command # distilled semantic facts
slmcode memory forget episodic --yes
slmcode evolve rules # repair rules with confidence + hit counts
slmcode evolve rules --all # include seeded-but-unused and retired rules
slmcode evolve why edit_format # the posterior table behind a learned choice
slmcode evolve regressions --run # replay the offline regression checks
slmcode evolve reset --yes
slmcode metrics show --last 10
slmcode metrics compare 12 # newest 12 runs vs the 12 before themAll take --json. Details → Self-improvement & memory.
Tunes the harness's own agent prompts and a whitelist of safe config knobs against the eval suite, keeping a change only when the primary metric improves and no guarded metric (tokens, wall clock, tool errors, edit-format apply rate) regresses.
slmcode autoresearch --surface # what is mutable, and in what range
slmcode autoresearch # DRY RUN: what it would try — no model, no writes
slmcode autoresearch --apply --seed 7 --max-experiments 6 --budget 20m
slmcode autoresearch --restore # undo the last applied runIt writes nothing unless asked twice: --apply and autoresearch: true in
.slmcode/config.yaml. Everything it does is reversible from the snapshot it takes
first, and everything it records lives under .slmcode/autoresearch/.
Details → Autoresearch.
Reports the active provider / model / endpoint, reachability with latency, the embedding mode,
and workspace / board / skills sanity. --json for scripts. Exit code 4 means the provider check
failed — an unreachable endpoint, a rejected or missing API key, or a model the endpoint does not
serve; the message names which.
slmcode completion zsh > "$(brew --prefix)/share/zsh/site-functions/_slmcode"
slmcode completion bash
slmcode completion fish
slmcode completion powershell| Variable | Effect |
|---|---|
SLMCODE_<KEY> |
every config key has one, mechanically: SLMCODE_MAX_PARALLEL, SLMCODE_QA_BOOTSTRAP, SLMCODE_ESCALATE_ASK_TIMEOUT, … slmcode config schema lists them all with types and defaults |
SLMCODE_PROVIDER SLMCODE_MODEL SLMCODE_ENDPOINT SLMCODE_API_KEY |
provider selection |
SLMCODE_BACKEND |
slmcode | claude-code |
SLMCODE_USER_CONFIG, XDG_CONFIG_HOME |
user-level config layer location |
SLMCODE_BASH_ALLOW |
extra shell allowlist prefixes (comma-separated) |
SLMCODE_BLOCKS, SLMCODE_STACKS |
extra block / stack search paths |
SLMCODE_TRUST_HOOKS=1 |
force-trust every .slmcode/hooks.json (CI images that write their own; see slmcode hooks) |
SLMCODE_TRUST_PROJECT_MCP=1 |
honour mcp_servers from a project config file — normally a user-layer-only key, because each entry is spawned as a child process at startup |
SLMCODE_TUI=0, CI=true |
force the non-interactive path |
SLMCODE_NO_QUIET=1 |
do not filter dependency stderr during engine construction |
SLMCODE_SKIP_UPDATE_CHECK=1 |
never contact GitHub |
SLMCODE_EMBEDDING_* |
embedding backend overrides |
SLMCODE_STUDIO_TOKEN, SLMCODE_STUDIO_NO_AUTH, SLMCODE_STUDIO_DEV_CORS |
Studio security profile |
SLMCODE_SRC, SLMCODE_UPDATE_REPO |
slmcode update source resolution |
NO_COLOR, FORCE_COLOR, TERM |
colour resolution |
Bare slmcode opens the interactive TUI: a non-blocking REPL with an append-only transcript and
a sticky status footer (it does not clear the screen on repaint).
| Key | Action |
|---|---|
Esc |
interrupt the running phase and redirect it mid-run |
↑ / ↓ |
prompt history |
Ctrl-R |
reverse history search |
Tab |
complete a slash command |
/ |
fuzzy command picker |
Ctrl-A/E/K/U/W |
line editing |
Ctrl-C |
cancel; twice to quit |
Slash commands: /help /run /stop /resume /plan /board /status /diff
/apply /reject /rewind /compact /agents /agent /model /models /provider
/permission /auth /schema /mcp /skills /blocks /pack /sessions /history
/stats /errors /feedback /escalate /doctor /studio /refresh /clear /q
(aliases /quit, /exit).