spinloop harness¶
Manage the harness — your coding agent — through its subcommands: six
configure which providers and models the agent uses, open launches it, and
config reports or stores which harness is the default. A bare spinloop
harness shows this list. opencode is the default; Pi and lucinate are also
supported. The harness is chosen at runtime, never baked into a Spinloop
file, so the same selection works for any of them.
spinloop harness # show the subcommands
spinloop harness open # launch the active harness (forwards trailing args)
spinloop harness add # configure a provider and a model
spinloop harness remove # take a provider, or some of its models, out
spinloop harness apply # apply a Spinloop file
spinloop harness unapply # remove what a Spinloop selects
spinloop harness show # what the harness has configured
spinloop harness export # print the config as a Spinloop file
spinloop harness config # report or store the default harness
Which harness wins¶
Every spinloop command resolves the harness the same way:
--harness/-HflagSPINLOOP_HARNESSenvironment variable- Your stored default (
spinloop harness config --set) - opencode
spinloop harness open¶
Launch the active harness's executable, forwarding stdio and any trailing arguments to it. The harness's exit code is yours.
spinloop code is a one-word shortcut for this same launch — the same flags,
Spinloop application, and forwarding. See spinloop code.
Configure, then launch¶
--spinloop/-O applies an Spinloop on the way in —
the same work spinloop harness apply does — so one
command configures the agent and launches it:
spinloop harness open -O # apply ./Spinloop, then launch
spinloop harness open --spinloop=path/to/Spinloop # ...or a specific one
spinloop harness open --spinloop=path/to/dir # ...or a directory holding a Spinloop
spinloop harness open --spinloop=https://example.com/Spinloop # ...or a URL, fetched instead of read
Given bare, --spinloop defaults to ./Spinloop like apply does; when you name
a path, attach it to the flag, because anything positional is forwarded to the
agent (spinloop harness open -O run --model x passes run --model x on). The one
exception is an argument that names a Spinloop — a path, a directory holding
one, or a registered alias — which is applied rather than
forwarded. It can sit anywhere among the command's own flags (--env, -H,
--fleet, ...), in any order; the first argument that is neither one of those
flags nor a Spinloop name starts the agent's own arguments:
spinloop harness open qwen3.6-27b # apply the aliased Spinloop, launch
spinloop harness open qwen3.6-27b --env prod # the alias and --env in either order
spinloop harness open --env prod qwen3.6-27b # ...parse the same way
spinloop harness open qwen3.6-27b -- --agent-arg # ...forwarding --agent-arg
spinloop harness open -- qwen3.6-27b # leading -- opts out: forward it
Put -- before the agent's own arguments if one of them would otherwise be
mistaken for a Spinloop name.
SPINLOOP_ALIAS decides what "the default Spinloop" means, so spinloop harness open -O
applies the alias it names. A bare spinloop harness open still applies nothing: the
variable chooses which Spinloop, never whether you are configured. See
spinloop alias.
Launching with no Spinloop at all¶
--env <name> on its own — no leading alias or path, no --spinloop/-O —
configures the harness from what is actually deployed to that
environment, rather than doing nothing with the flag:
spinloop harness open --env dev-3 --prompt "..." # configured from dev-3's deployment, then launched
The environment's runner becomes the provider, its served model name becomes
the model, and its context size (when set) becomes the context window — the
same result a Spinloop stating the matching PROVIDER/ALIAS/CONTEXT with
--env dev-3 would produce, without writing one. This is what makes the
two-machine flow work: deploy from one machine
(spinloop remote deploy <spinloop> --env dev-3), then on any machine that
can reach the same environment — one that has its remote.json in the
registry, however it got there — run spinloop harness open --env dev-3 with no
Spinloop and get the same configuration, live, so a later redeploy is picked
up automatically rather than requiring anyone to re-copy anything.
Applying a Spinloop alongside --env (a leading alias/path, or -O) is
unaffected: the Spinloop's own PROVIDER, ALIAS, MODEL and CONTEXT win,
exactly as a hand-written BASEURL already wins over the environment's
registered address.
A bare --env against an environment with nothing deployed — or a control
plane too old to report what is deployed — fails before launching, naming the
environment and how to fix it: spinloop remote deploy <spinloop> --env
<name> to deploy something, or spinloop remote bootstrap to update the
control plane.
Flags¶
| Flag | Meaning |
|---|---|
-H, --harness |
Which harness to launch (or set SPINLOOP_HARNESS) |
-O, --spinloop |
Apply this Spinloop before launching (bare: ./Spinloop) |
-e, --env |
The registered environment to launch against; with no Spinloop applied, configures the harness from what is deployed there — mutually exclusive with fleet routing, since each names where the model is served from |
--providers |
Path to a custom catalogue, for the applied Spinloop |
-f, --fleet |
Route through this fleet file (default: ./fleet.yaml, when the Spinloop is not named) |
--node |
Pin the launch to one fleet node |
--prefer |
Rank fleet nodes by idle or active (overrides the fleet file) |
--no-wake |
Fail rather than starting an engine on an idle fleet node |
--wake-timeout |
How long to wait for a woken node's engine (default 5m) |
Launching against your fleet¶
A fleet file sends the agent to a machine on your network instead of a local
engine. Which one a launch routes through is a launch concern, not a Spinloop
field: --fleet <path> names it explicitly, and without the flag a Spinloop you
did not name — the default ./Spinloop, worn by a valueless -O — takes the
fleet.yaml in the working directory. A Spinloop you did name — a path, a -O
value, or the alias SPINLOOP_ALIAS names — routes only by flag. See
fleet files.
spinloop harness open -O -f fleet.yaml # valueless -O wears ./Spinloop; routes through fleet.yaml
spinloop harness open --node gpu-box -f fleet.yaml
spinloop harness open --prefer active -f fleet.yaml
spinloop queries the fleet, prefers a node already serving the Spinloop's model, and points the launched agent at that node's engine — the same injection that carries a remote environment's endpoint address and key, with a selection step in front. It reports which node it chose, and why, before the agent starts.
When nothing is serving that model, spinloop picks a node that is not running,
tells it what to serve, starts it, and waits for its engine to answer. A node
that is already running is never stopped to make room — someone else may be
using it — so a fleet with every machine busy on other models fails rather than
displacing anyone. --no-wake turns starting off entirely.
Which node wins among several that could all serve you is a
prefer setting: idle (the default)
takes the machine that has been quiet longest, keeping a second agent off an
engine that is mid-request; active consolidates onto the busy one instead.
A fleet file that names a gateway points the agent there,
so the address lives in the file rather than in every Spinloop — and because a
gateway resolves the model per request, a launch through one needs no Spinloop
at all: spinloop code --fleet ./fleet.yaml is enough.
spinloop harness config¶
Report or store which harness is the default. With no flag — or --get — it
prints the active harness and where that choice came from; --set <name>
stores the default and exits.
spinloop harness config # report the active harness
spinloop harness config --get # ...explicitly
spinloop harness config --set pi # store pi as the default and exit
| Flag | Meaning |
|---|---|
--get |
Print the active harness and where that choice came from (the default) |
--set |
Store this harness as the default and exit |
-H, --harness |
Which harness to report with --get |
The stored default is what Which harness wins resolves to when no flag or environment is set.
spinloop harness add¶
Point your coding agent at a provider and model. Settings are deep-merged into the agent's config — other providers, your theme, even your comments stay exactly where you left them.
spinloop harness add --provider <name> [--model <id>] [--alias <name>]
[--context <size>] [--output <size>] [--base-url <url>]
# A model from OpenRouter (key from .env or the environment)
spinloop harness add -p openrouter -m deepseek/deepseek-v4-flash
# A local Ollama model (no key required)
spinloop harness add -p ollama -m llama3.2
# Claude on AWS Bedrock (uses your AWS credentials)
spinloop harness add -p amazon-bedrock -m anthropic.claude-3-5-sonnet
# Claude on GCP Vertex AI (uses your Google credentials; set the project)
GOOGLE_VERTEX_PROJECT=my-gcp-project \
spinloop harness add -p google-vertex-anthropic -m claude-3-5-sonnet-v2@20241022
# Gemini on GCP Vertex AI
GOOGLE_VERTEX_PROJECT=my-gcp-project \
spinloop harness add -p google-vertex -m gemini-2.0-flash
# Any OpenAI-compatible endpoint
OPENAI_API_KEY=sk-... \
spinloop harness add -p openai-compatible -m my-model --base-url https://my-endpoint/v1
# Pin a specific default model
spinloop harness add -p openrouter -m deepseek/deepseek-v4-pro
# Record the context window and cap the output tokens
spinloop harness add -p llamacpp -m my-model -c 128k -o 32k
| Flag | Meaning |
|---|---|
-p, --provider |
Provider name — see spinloop provider list. Required. |
-m, --model |
The provider-native model id to add or pin as the default |
-a, --alias |
Friendly name for the model — the key your agent shows |
-c, --context |
Context window; 128k, 1m, 200000, even 128 K tokens all work |
-o, --output |
Max output tokens, same format; defaults to a quarter of the context |
-u, --base-url |
Override the provider's API base URL (or set SPINLOOP_BASE_URL) |
-H, --harness |
Which harness to configure (or set SPINLOOP_HARNESS) |
--providers |
Path to a custom catalogue — see spinloop provider init |
Notes:
- You need at least one of
--modelor--aliasalongside the provider. - API keys are read from a
.envbeside theSpinloop— or, forspinloop harness add, which has no Spinloop, from a.envin the current directory — then your environment, and never written anywhere they'll leak. A provider that requires a key tells you which variable to set. - Some cloud providers authenticate with ambient credentials instead of an API
key:
amazon-bedrockvia your AWS credentials, andgoogle-vertex/google-vertex-anthropicvia Google Application Default Credentials (rungcloud auth application-default login, or setGOOGLE_APPLICATION_CREDENTIALSto a service-account key file). The Vertex providers need a project — setGOOGLE_VERTEX_PROJECT(and optionallyGOOGLE_VERTEX_LOCATION, which defaults toglobal). These providers are opencode-only. - On opencode,
addsets the chosen model as the default. Pi has no default-model setting, soaddtells you which model to pick with/model. --outputneeds--context, and cannot exceed it.
spinloop harness remove¶
Take a provider back out of your agent's config — or just some of its models.
The inverse of add; everything else in the config
stays put.
# Remove a provider entirely
spinloop harness remove -p ollama
# Drop one model, keep the provider's others
spinloop harness remove -p openrouter -m deepseek/deepseek-v4-flash
| Flag | Meaning |
|---|---|
-p, --provider |
Provider to remove from. Required. |
-m, --model |
Remove this model |
-a, --alias |
Remove the model stored under this alias |
-H, --harness |
Which harness to configure (or set SPINLOOP_HARNESS) |
--providers |
Path to a custom catalogue |
Notes:
- With no model or alias, the whole provider goes.
- If the agent's default model pointed at something you removed, it is cleared too.
- Removing something that isn't there is not an error —
spinloopjust tells you there was nothing to remove.
spinloop harness apply¶
Apply an Spinloop file — a declarative description of
one provider selection — exactly as if you had run the equivalent
spinloop harness add. Everything else in your
agent's config is preserved.
spinloop harness apply # reads ./Spinloop in the current directory
spinloop harness apply path/to/Spinloop # a full path to the file
spinloop harness apply path/to/dir # a directory holding a Spinloop
spinloop harness apply qwen3.6-27b # a name registered with `spinloop alias`
spinloop harness apply https://example.com/Spinloop # a URL, fetched instead of read from disk
Add --harness pi (or set SPINLOOP_HARNESS) to apply it to Pi instead of
opencode. After applying, just launch your agent — or do both at once with
spinloop harness open -O.
| Flag | Meaning |
|---|---|
-e, --env |
The registered environment the Spinloop points at: names the harness provider and, with no BASEURL, supplies the endpoint's address |
-o, --output |
Max output tokens — overrides the Spinloop's OUTPUT |
-H, --harness |
Which harness to configure (or set SPINLOOP_HARNESS) |
--providers |
Path to a custom catalogue (a Spinloop never names one) |
Notes:
- With no argument,
applyuses the aliasSPINLOOP_ALIASnames, and failing that a file namedSpinloopin the current directory — seespinloop alias. - A URL ending in
/is treated like a directory —Spinloopis appended. See Fetching a Spinloop from a URL. - A Spinloop's
PRESETline is forspinloop serve;applyignores it — never fetched, even when it's a URL. - With
--env <name>, the Spinloop points at a registered environment: the harness provider is keyed on the environment name (so several environments built from the same engine keep their own entries), and a Spinloop with noBASEURLtakes the endpoint's address from the environment'sremote.jsonbase_url, which its deployment writes. ABASEURLin the Spinloop wins over it. An unregistered name fails, naming thespinloop remote deploy --env <name>that would create it. Without--env, apply reads no remote config at all.
spinloop harness unapply¶
Remove what an Spinloop file selects from your agent's
config — the inverse of apply, just as
remove is to add.
spinloop harness unapply # reads ./Spinloop in the current directory
spinloop harness unapply path/to/Spinloop # a full path to the file
spinloop harness unapply path/to/dir # a directory holding a Spinloop
spinloop harness unapply qwen3.6-27b # a name registered with `spinloop alias`
spinloop harness unapply https://example.com/Spinloop # a URL, fetched instead of read from disk
| Flag | Meaning |
|---|---|
-H, --harness |
Which harness to configure (or set SPINLOOP_HARNESS) |
--providers |
Path to a custom catalogue |
Notes:
- It honours
--harness/-HandSPINLOOP_HARNESSlike everything else, so unapply from whichever harness you applied to. - With no argument it resolves the same way
applydoes:SPINLOOP_ALIAS, then./Spinloop— seespinloop alias. - If the agent's default model pointed at something the Spinloop selected, it is cleared too.
spinloop harness show¶
Show what a harness currently has configured: its providers, each provider's models with their context/output limits, the default model, and your registered aliases.
spinloop harness show # the active harness
spinloop harness show --harness pi # a specific one, without changing your default
Where spinloop provider list shows the catalogue of
providers you could configure, show reports what the harness actually has
right now — and which config file that lives in.
| Flag | Meaning |
|---|---|
-H, --harness |
Which harness to inspect (or set SPINLOOP_HARNESS) |
Notes:
- The output names the active harness and where that choice came from (flag, environment, stored preference, or the default).
- Inspecting another harness with
--harnessnever touches your stored default.
spinloop harness export¶
Print the active harness's configuration as an Spinloop
file, so you can save a setup you built by hand:
spinloop harness export > Spinloop
spinloop harness export --harness pi > Spinloop # read Pi's config instead
By default it exports the provider behind your default model (or the only
configured provider). If you have several, choose one with -p:
| Flag | Meaning |
|---|---|
-p, --provider |
Which configured provider to export |
-H, --harness |
Which harness to read (or set SPINLOOP_HARNESS) |
--providers |
Path to a custom catalogue |
Notes:
- Export names the configured
MODELdirectly. - It writes canonical UPPERCASE keywords, and records
CONTEXT/OUTPUTonly when the exported models agree on a value — it never guesses. - Secrets are never exported; keys stay in your
.envor environment.
Notes¶
openpasses trailing arguments and stdio to the agent untouched, and its exit code is yours.- Not every provider maps to every harness —
spinloop provider listshows which harnesses each supports.
See also¶
spinloop code— this launch, as a one-word top-level shortcutspinloop provider list— what the harness could be configured withspinloop fleet route— which node a launch would pickexamples/fleet-local/— routing at a single local node, end to end