Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Four words carry the whole tool:

- [Getting started](getting-started.md) — the end-to-end flow
- [The `Spinloop` file](spinloop-file.md) — syntax and examples
- [The `fleet.yaml` file](fleet-file.md) — the file a fleet is built from:
its nodes, its token references, and what it refuses
- [Running on a cloud GPU](commands/remote.md) — the same Spinloop, on a
machine that stops when you do
- [The HTTP control API](http-api.md) — driving a supervised engine over
Expand Down Expand Up @@ -84,7 +86,7 @@ including the `SPINLOOP_REMOTE_*` overrides:
| `SPINLOOP_BASE_URL` | Overrides any provider's API base URL (`--base-url`/`-u` beats it) |
| `SPINLOOP_API_TOKEN` | Bearer token for the daemon [control API](http-api.md) |
| `SPINLOOP_LOG_LEVEL` | How much `spinloop daemon`/`spinloop serve` record — `debug`, `info` (default), `warn`, `error` (`--log-level` beats it) |
| *(named by `tokenEnv`)* | A [fleet](commands/fleet.md) node's bearer token — `fleet.yaml` names the variable, never the value |
| *(named by `tokenEnv`)* | A fleet node's bearer token — the [fleet file](fleet-file.md#tokens) names the variable, never the value |
| `DEEPSEEK_API_KEY`, `OPENAI_API_KEY`, … | Provider API keys — `spinloop provider list` shows which each provider reads |
| `OLLAMA_BASE_URL`, `LLAMACPP_BASE_URL`, `OMLX_BASE_URL`, `VLLM_BASE_URL`, `MTPLX_BASE_URL`, `OPENAI_BASE_URL` | Per-provider endpoint overrides |
| `AWS_REGION` | Region for AWS Bedrock |
Expand Down
2 changes: 1 addition & 1 deletion docs/commands/alias.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ spinloop harness apply team-default
```

It is stored and resolved just like a local one — see
[Fetching a Spinloop from a URL](../spinloop-file.md#fetching-an-spinloop-from-a-url).
[Fetching a Spinloop from a URL](../spinloop-file.md#fetching-a-spinloop-from-a-url).

## Naming one for the whole shell

Expand Down
2 changes: 1 addition & 1 deletion docs/commands/code.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ spinloop code --fleet ./fleet.yaml # route through a fleet, or its gateway

`code` is the only way to launch an agent against a fleet: `spinloop fleet
harness` was removed, and typing it names this command instead. A fleet file
that names a [gateway](fleet.md#gateway) needs no Spinloop at all — the gateway
that names a [gateway](../fleet-file.md#gateway) needs no Spinloop at all — the gateway
resolves the model per request — so `spinloop code --fleet ./fleet.yaml` is a
complete launch on a machine holding nothing but the fleet file.

Expand Down
320 changes: 17 additions & 303 deletions docs/commands/fleet.md

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions docs/commands/gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ side.

## Pointing an agent at it

A [`gateway` section](fleet.md#gateway) in the fleet file names the address and
A [`gateway` section](../fleet-file.md#gateway) in the fleet file names the address and
the variable holding the token. A launch routed through that file — `spinloop
harness open -f` or `spinloop code -f` — is pointed at the gateway rather than
a node: the section's address is the agent's base URL (with the OpenAI-
Expand Down Expand Up @@ -93,7 +93,7 @@ once in a short window, so a poll of the models list is cheap.
A completion request is answered by the fleet's own selection: a node already
running the model wins, ranked by the fleet file's `prefer` with fleet-file
order breaking ties. A node whose engine is bound to loopback without an
[`engine` override](fleet.md#where-a-nodes-engine-answers) is never selected,
[`engine` override](../fleet-file.md#where-a-nodes-engine-answers) is never selected,
and when it is the only match the failure says so rather than holding the
request until the wake timeout.

Expand All @@ -111,12 +111,12 @@ the node.
`GET /v1/fleet` answers with the fleet as it is now: the same cached fan-out
the model listing reads, joined with the file's claims about each node and its
fleet-level settings. Each node's entry carries its name, kind,
[tags](fleet.md#tags), state, what it serves (the served name where a running
[tags](../fleet-file.md#tags), state, what it serves (the served name where a running
engine reports one, else the model id), whether it has answered its own health
check, when it last did work — and, for a node that is not running, the model
a request would start it with, where its own source describes one and the
file's [wake policy](fleet.md#waking) allows it. The file's `wake` and
`prefer` settings and its [concurrency](fleet.md#concurrency) limits ride
file's [wake policy](../fleet-file.md#waking) allows it. The file's `wake` and
`prefer` settings and its [concurrency](../fleet-file.md#concurrency) limits ride
along, each absent where the file declares none. A node that does not answer
is reported in its place — the way the fleet's own views report it — rather
than failing the whole reply.
Expand All @@ -128,7 +128,7 @@ of the fleet: the orchestrator takes no fleet file of its own.
### Waking a node

When no running node serves the model and the fleet file's
[`wake`](fleet.md#waking) setting allows it, the gateway starts a node with
[`wake`](../fleet-file.md#waking) setting allows it, the gateway starts a node with
the config that node's own Spinloop source resolves to — only nodes whose
source describes the requested model are candidates, and a node whose stored
config already matches is tried first — and holds the request until the engine
Expand Down
6 changes: 3 additions & 3 deletions docs/commands/harness.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,11 @@ using it — so a fleet with every machine busy on other models fails rather tha
displacing anyone. `--no-wake` turns starting off entirely.

Which node wins among several that could all serve you is a
[`prefer` setting](fleet.md#spreading-or-consolidating): `idle` (the default)
[`prefer` setting](../fleet-file.md#spreading-or-consolidating): `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](fleet.md#gateway) points the agent there,
A fleet file that names a [gateway](../fleet-file.md#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.
Expand Down Expand Up @@ -314,7 +314,7 @@ Notes:
that a file named `Spinloop` in the current directory — see
[`spinloop alias`](alias.md#naming-one-for-the-whole-shell).
- A URL ending in `/` is treated like a directory — `Spinloop` is appended. See
[Fetching a Spinloop from a URL](../spinloop-file.md#fetching-an-spinloop-from-a-url).
[Fetching a Spinloop from a URL](../spinloop-file.md#fetching-a-spinloop-from-a-url).
- A Spinloop's `PRESET` line is for [`spinloop serve`](serve.md); `apply`
ignores it — never fetched, even when it's a URL.
- With `--env <name>`, the Spinloop points at a registered
Expand Down
8 changes: 4 additions & 4 deletions docs/commands/orchestrator.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Work a backlog of items against a [fleet](fleet.md) at a pace the fleet can
absorb. The orchestrator holds the backlog, reads the fleet's topology from
the fleet's [gateway](gateway.md), admits an item while the fleet's declared
[concurrency](fleet.md#concurrency) limits allow, and runs each admitted item
[concurrency](../fleet-file.md#concurrency) limits allow, and runs each admitted item
as a one-shot agent of the [active harness](harness.md) in the item's own
directory — the agent's inference going through that same gateway.

Expand Down Expand Up @@ -59,7 +59,7 @@ directory the agent works in:
`--create-item-dirs`, the orchestrator creates a missing directory instead.
- **`priority`** — an integer, higher first; items of one rank go in file
order.
- **`tags`** — `key=value` pairs naming the [tags](fleet.md#tags) of the nodes
- **`tags`** — `key=value` pairs naming the [tags](../fleet-file.md#tags) of the nodes
the item may run on. Every pair must be a tag the node carries; an item with
no tags may run anywhere. An item nothing matches waits — the fleet may
change — rather than failing.
Expand Down Expand Up @@ -164,7 +164,7 @@ an item matches a node only where every tag it names is one the node carries;
a node already running and answering is offered before a node the run would
have to start, and among a tier the fleet file's `prefer` ranks them. A
stopped node is an option only where the fleet file
[wakes](fleet.md#waking).
[wakes](../fleet-file.md#waking).

## What it does not do

Expand All @@ -180,7 +180,7 @@ stopped node is an option only where the fleet file
- It never re-runs an ended item. `done` stands, and a `failed` one —
including the ones a crash left in flight — stands.
- It is not the fleet's scheduler. The limits it works to are the fleet
file's declared [concurrency](fleet.md#concurrency); it measures nothing and
file's declared [concurrency](../fleet-file.md#concurrency); it measures nothing and
estimates no load.

## Flags
Expand Down
2 changes: 1 addition & 1 deletion docs/commands/serve.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ against its URL, when the Spinloop itself was fetched from one — so the pair
can travel together either way. `PRESET` may also be an absolute URL of its
own, fetched only when `serve` builds the command, never merely because the
Spinloop was read. See [Fetching a Spinloop from a
URL](../spinloop-file.md#fetching-an-spinloop-from-a-url).
URL](../spinloop-file.md#fetching-a-spinloop-from-a-url).

## oMLX

Expand Down
6 changes: 3 additions & 3 deletions docs/env-vars.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ from the environment or a `.env` beside the Spinloop — never written into an
| `SPINLOOP_API_TOKEN` | `spinloop daemon`, `spinloop serve --api`, `spinloop gateway` | Bearer token for the daemon control API — and the token a [gateway](commands/gateway.md)'s callers must present. One of three peer sources, alongside `--api-token-file` and `--api-token`; two at once is an error. From a service manager prefer the file form — see [serve](commands/serve.md). A non-loopback listen without any of them refuses to start. |
| `SPINLOOP_REMOTE_KEYSTORE` | `spinloop remote auth` | Set to `file` to keep the stored control-plane credential in the owner-only file under the config directory, even where an OS keystore is reachable — the opt-out for a machine whose keystore is locked or unreachable. Unset, the OS keystore is used where available. See [credentials](commands/remote.md#credentials). |
| `SPINLOOP_LOG_LEVEL` | `spinloop daemon`, `spinloop serve` | How much spinloop records about the control API and the supervised engine: `debug`, `info` (default), `warn` or `error`. Precedence: `--log-level` flag > `SPINLOOP_LOG_LEVEL` > `info`. An unrecognised value refuses to start rather than falling back to the default. Under `spinloop serve` the `.env` beside the Spinloop can set it; the daemon reads no Spinloop, so there it comes from the environment its service manager gives it. Records go to stderr; see [what gets logged](commands/serve.md#what-gets-logged). |
| *(per-node, named by `tokenEnv`)* | `spinloop fleet` | A fleet node's bearer token. `fleet.yaml` names the variable rather than holding the value; it resolves from the environment, then the `.env` beside the fleet file. See [fleet](commands/fleet.md). |
| *(per-node, named by `engineTokenEnv`)* | `spinloop fleet`, `spinloop harness open` | The key a fleet node's **engine** is gated with. Resolved the same way, and supplied by the client when it starts that engine — so the node holds no key of its own and the two ends cannot disagree. See [fleet](commands/fleet.md). |
| *(fleet-wide, named by `apiKeyEnv`)* | `spinloop fleet`, `spinloop harness open` | The default key for a `kind: remote` environment's engine, for every remote node that does not name its own `engineTokenEnv`. Resolved the same way. See [fleet](commands/fleet.md). |
| *(per-node, named by `tokenEnv`)* | `spinloop fleet` | A fleet node's bearer token. `fleet.yaml` names the variable rather than holding the value; it resolves from the environment, then the `.env` beside the fleet file. See [the fleet file](fleet-file.md#tokens). |
| *(per-node, named by `engineTokenEnv`)* | `spinloop fleet`, `spinloop harness open` | The key a fleet node's **engine** is gated with. Resolved the same way, and supplied by the client when it starts that engine — so the node holds no key of its own and the two ends cannot disagree. See [the fleet file](fleet-file.md#tokens). |
| *(fleet-wide, named by `apiKeyEnv`)* | `spinloop fleet`, `spinloop harness open` | The default key for a `kind: remote` environment's engine, for every remote node that does not name its own `engineTokenEnv`. Resolved the same way. See [the fleet file](fleet-file.md#tokens). |

## Remote (`spinloop remote`)

Expand Down
Loading