stella tools
List every tool the agent can use this session, including built-in tools and custom tools from .stella/tools/, plus a --validate check for both.
Lists every tool the agent can use in the current session: built-in tools, custom tools you've added, tools the foundry built on its own, and a check for any problems with them.
Synopsis
stella tools [--validate [DIR]] [--draft GAP_ID] [--adopt NAME] [--enable NAME [--yes]]
[--disable NAME] [--rollback NAME [--to N]] [--foundry] [--status]
[global flags]What it does
stella tools prints the tools the agent can call this session.
- Built-in tools — always-available tools, plus a few that only show up in certain conditions. See the full Built-in Tools catalog for names and whether each one is read-only or can make changes.
- Custom tools you've added — loaded from
<name>.tomlmanifest files. - Tools the foundry built — tools stella wrote itself from shell commands you kept repeating, then proved, adopted, and enabled at the end of a turn. See The autonomous foundry below.
Custom tools come from a <name>.toml manifest placed in <workspace>/.stella/tools/ (just for this project) or ~/.stella/tools/ (for all your projects). If a project tool and a global tool share a name, the project one wins.
stella tools does not list MCP tools. It just notes that any servers set up in .stella/mcp.toml add more tools when a session starts. Use stella mcp list to see your configured MCP servers.
Flags
--validate [DIR]Checks your custom-tool manifests instead of listing tools. Reads every <name>.toml
file in .stella/tools/ and ~/.stella/tools/, or in the folder you give it, and
reports errors, warnings, and other notes for each one. Exits with an error code if any
manifest has a real error.
--adopt NAMEMoves a staged tool into .stella/tools/ and runs its capability witness: a test
that must fail using the tools you already had, and succeed once the new tool is used,
producing a real result. The test result is saved. This is the manual verb: run by
hand, it leaves the tool turned off until --enable. Under the default
autonomy = "auto", the end-of-turn pipeline runs this same adopt step itself and
enables the tool right after, so you never type it.
--enable NAMETurns on an adopted tool so the model can use it. The manual path: it shows what the
tool would run and asks you to confirm. Refuses to enable it if the manifest or script
changed since the test ran. Under the default auto mode the pipeline enables tools
without this flag; you need it only under draft-only, or for a tool you staged and
adopted by hand.
--yesAccept an --enable without the confirmation question. For provisioning scripts that
have no terminal. Only valid together with --enable.
--disable NAMETurns off an adopted tool. Its saved test result is kept. Never asks.
--foundryLists every tool the foundry built: whether its test passed, whether it's turned on, and how many times it has been used since it was adopted, including ones never used at all.
--draft GAP_IDAuthor a staged manifest+script pair from one ledgered tool gap
(.stella/private/tool_gaps.jsonl) and stop — the manual escape hatch that runs the
autonomy pipeline's author+validate steps without adopting anything. The pair lands
under .stella/tools/proposed/, invisible to discovery.
--rollback NAMERestore a prior recorded version of an adopted foundry tool — exact bytes from the
append-only version history — re-digest it, and re-enable it, which is also how a
tripped circuit breaker is reset. Defaults to the version before the current one;
--to N targets an explicit one.
--to NThe version --rollback restores.
--statusPer-tool foundry health: enablement (with the circuit breaker's recorded reason when it spoke), version history, and the recent launch record — plus how many gaps sit in the ledger waiting for a draft.
stella tools also accepts the global flags. Which model you're using rarely matters for this command, since it's just a diagnostic.
Examples
List the tools available this session:
stella toolsCheck your custom-tool manifests in CI, and fail if any have errors:
stella tools --validateCheck one folder of manifests before you install them:
stella tools --validate ./contrib/stella-toolsWatch the foundry work on its own (the default). There is nothing to type to make a tool appear: at the end of each turn, stella looks for shell commands you kept repeating, writes a manifest and script for each one, proves it with the witness, adopts it, and turns it on. It prints a notice naming what it did. These commands let you see and steer the result:
stella tools --status # per-tool health, versions, recent launches, gaps waiting
stella tools --foundry # every foundry tool, its witness, and how much it's used
stella tools --disable jq # turn one tool off; its proof stays on file
stella tools --rollback jq # go back one version and re-enable; resets a tripped breakerCarry a tool through by hand. This is the path under autonomy = "draft-only", or on a
platform where the network denial cannot be enforced, or for a tool you wrote yourself:
stella tools --draft GAP_ID # author + validate one ledgered gap; lands in proposed/
# Or place your own jq.toml (with a [foundry] table) + jq.sh under
# .stella/tools/proposed/, where stella won't see them yet.
stella tools --validate .stella/tools/proposed
stella tools --adopt jq # run the test; saves the result, tool stays off
stella tools --enable jq # shows what it grants, then asks
stella tools --enable jq --yes # same, for a provisioning script with no terminalOn the manual path, --enable asks, and refuses if nobody can answer. It shows the
script the model would run, the saved test result, and what that test does not prove,
then waits for you to type y. If there's no terminal attached, it refuses instead of
going ahead. Pass --yes when you're running it from a provisioning script. None of
this applies to the default auto mode, where the pipeline enables what it proves and
the standing controls below do the guarding.
--disable never asks. Turning a tool off must never be blocked just because there's no
terminal available.
The autonomous foundry
The foundry is the part of stella that builds tools for itself. It runs at the end of every turn, next to skill mining, and by default it needs nobody's help. The pipeline is:
- Detect — look at this session's shell calls for a command shape you keep reusing:
the same basic call with different arguments, used more than once with each set. The
shape is written to the gap ledger at
.stella/private/tool_gaps.jsonl. - Author — write a
<name>.tomlmanifest and<name>.shscript for the gap, staged under.stella/tools/proposed/where discovery cannot see it. - Validate — re-parse the manifest, lint the script, and run the capability witness twice with the network denied. Those two runs are the sandboxed dry run.
- Adopt — record the manifest and script digests in the foundry ledger, using the same
writer the manual
--adoptverb uses. Every adoption also appends the exact bytes to the version history. - Enable — turn the tool on. From the next turn, the model can call it.
- Execute — every launch goes through the foundry gate, which re-digests the files on each call. A tool whose bytes changed since its witness ran is held back, not launched.
One turn carries at most two new gaps through the pipeline, because the witness runs each
candidate twice. Any extra gaps stay in the ledger, and the end-of-turn notice tells you how
many are waiting for stella tools --draft GAP_ID. A failed witness leaves the draft
staged for you to look at; authored work is never thrown away, and nothing unproven
registers.
Autonomy modes
foundry.autonomy in stella.toml picks how far the pipeline goes. It is the kill switch.
| Mode | What happens at the end of a turn |
|---|---|
auto (default) | Detect → author → validate → adopt → enable, network denied at spawn. |
draft-only | Detect, author, and validate. The pair lands in .stella/tools/proposed/ and nothing is adopted; you take it from there with --adopt and --enable. |
off | Detect and write the gap to the ledger. Nothing is authored. |
auto also drops down to draft-only on a platform that has no working network
isolation, and prints a notice saying so. A control that cannot be enforced is never
claimed, so on such a machine files are staged and nothing is adopted.
stella tools --disable NAME turns off one tool without changing the mode.
The [foundry] keys
All of these live in the [foundry] block of stella.toml. The block is one policy: the
last scope to set it wins as a whole. See the
[foundry] reference for the full description of
each key.
| Key | Default | What it does |
|---|---|---|
min_occurrences | 3 | Matching calls before a shape is worth proposing. 0 or 1 turn detection off. |
min_distinct_arguments | 2 | Different argument sets required. One set is an exact repeat, which is loop detection's job. |
min_reuse_ratio | 3.0 | Uses per argument set required. At or below 1.0 turns this gate off. |
require_success | true | Whether at least one of the repeated calls must have succeeded. |
max_examples | 3 | Example command lines per proposal and example values per parameter. At least 1, because the witness input is built from them. |
autonomy | "auto" | "auto", "draft-only", or "off", as above. |
breaker_consecutive_failures | 3 | Failures in a row that trip a tool's circuit breaker. At least 1. |
breaker_window | 10 | Recent launches the failure-rate check looks at. At least 1. |
breaker_failure_rate | 0.5 | Share of that window that trips the breaker. Above 0, at most 1. |
network_allowlist | [] | Foundry tools allowed to reach the network, by name. Names must match ^[a-z][a-z0-9_]{1,63}$. |
Lowering a detection threshold changes what gets proposed. What executes is still gated by the ledger, the per-call re-digest, and the network denial.
The standing controls
Nobody approves a foundry tool. What guards the loop instead is a set of controls that run on every tool, every time, in places the pipeline cannot skip:
- Network denied by default. Every foundry-built tool starts with its network cut off
by the operating system at spawn:
sandbox-execon macOS,unshare -rnon Linux. The witness's two runs go through the same path. To let one tool reach the network, add its name tofoundry.network_allowlist, a line in a settings file a reviewer can find. - Versioned rollback. Every adoption appends the exact manifest and script bytes to an
append-only version history in the store.
stella tools --rollback NAME [--to N]restores a version, re-digests it, and re-enables the tool. History is never rewritten. - A telemetry ledger. Every launch writes an invocation row: the tool, its script
digest, the gap it came from, duration, exit status, whether it timed out, and output
bytes.
stella tools --statusshows the recent launch record. - A circuit breaker. A tool that fails 3 times in a row, or fails more than half of a
full 10-launch window, is turned off on its own. The reason is recorded, and both the
foundry gate and
stella tools --statusshow it. A new version re-enables the tool, whether it comes from a re-author or from--rollback. The counts are thebreaker_*keys above. - The kill switch.
foundry.autonomy = "draft-only"or"off"stops the pipeline at the step you choose, in either settings scope, andstella tools --disable NAMEstops one tool.
When a foundry tool registers
A tool with a [foundry] table in its manifest only registers once all three of these
are true:
- it was adopted — its witness passed;
- it is enabled — by the pipeline under
auto, or by you with--enableunderdraft-onlyand for tools you staged by hand; - the manifest and script still have the exact same bytes the witness ran against. Editing an adopted tool's script cancels its adoption instead of carrying it over.
So copying a staged manifest into .stella/tools/ by hand does not grant anything on its
own. Every tool that gets held back is listed by name and reason in stella tools, so a
missing tool is never a mystery.
The test is a fail-then-pass check, not a smoke test. The same call must fail using the tools you already had, succeed with the new tool, and check a real result the tool produced. A tool that works either way is just a different name for something you already had. A tool that prints nothing, or only repeats its own input back, proves nothing and is rejected.
Staging a tool yourself
You can also write a manifest and script by hand and place them under
.stella/tools/proposed/, then carry them through --adopt and --enable as in the
examples above. Write the script so every parameter is a quoted "$STELLA_INPUT_*"
reference. That keeps each value treated as plain data, not as shell code.
A useful custom tool covers a command shape you actually reuse: the same basic call with
different arguments, used at least a couple of times with each set of arguments. A command
where the arguments are different every single time, like running sed with a one-off
expression across a thousand different files, isn't really a reusable tool. It's just you
using the shell.
None of this affects manifests you write by hand. Dropping your own <name>.toml straight
into .stella/tools/ still works exactly like it always has.