Agent orchestration · Go CLI · MIT

Orchestrate every model your agent runs on.

One CLI for the whole supply line. Point opencode, Pi or lucinate at a hosted or local model, serve it yourself, watch every engine you run from one board — and wake a cloud GPU only for as long as you use it.

brew install spinloop-ai/tap/spinloop
Read the docs
spinloop fleet dashboard
╭──────────────────────────────────────────╮
│ studio  running  (up 1h 2m 5s)          │
│llamacpp  Qwen3.6-35B-A3B-GGUF            │
│  last active 12s ago                     │
│  CPU       ██████████░░░░░░░░░░░░░░░ 41% │
│  RAM       ████████████░░░░░░░░░░░░░ 48% │
│  GPU util  ███████████████░░░░░░░░░░ 61% │
│  GPU mem   ████████████░░░░░░░░░░░░░ 50% │
│                                          │
│  running:          1                     │
│  prompt tokens:    184320                │
│  generation tokens: 20481                │
│  requests:         37                    │
╰──────────────────────────────────────────╯
╭──────────────────────────────────────────╮
│ gpu-box  running  (up 22m 41s)          │
│vllm  Qwen3.8-27B-Instruct                │
│  last active 3s ago                      │
│  CPU       ████████████████░░░░░░░░░ 66% │
│  RAM       ████████████████████░░░░░ 83% │
│  GPU util  ██████████████████████░░░ 91% │
│  GPU mem   █████████████████████░░░░ 87% │
│                                          │
│  running:          3                     │
│  prompt tokens:    902144                │
│  generation tokens: 118307               │
│  requests:         214                   │
╰──────────────────────────────────────────╯
╭──────────────────────────────────────────╮
│ aws-h100  starting                      │
│instance starting; retrying in 42s        │
│stopped                                   │
│vllm  Qwen3.8-27B-Instruct                │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
╰──────────────────────────────────────────╯
╭──────────────────────────────────────────╮
│ mac-studio  unreachable                 │
│dial tcp 10.0.0.9:4242: connect: connectio│
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
│                                          │
╰──────────────────────────────────────────╯
↑↓←→ move   s start   x stop   r refresh   q quit
A node that is down is a row, not a failure — the rest of the fleet still renders.

Nine providers built in — name one, spinloop fills in the rest

  • OpenRouter
  • AWS Bedrock
  • Google Vertex · Gemini
  • Google Vertex · Claude
  • Ollama
  • llama.cpp
  • oMLX
  • vLLM
  • Any OpenAI-compatible endpoint

Adding one that isn't here is a data change, not code.

The problem

Changing model is never just changing the model.

Every agent keeps its config somewhere different, in a shape of its own. Pointing one at a new provider means getting the base URL, the model id, the package it loads and the name of the environment variable holding your key all correct at once. One stray brace and the agent won't start.

And the model you want changes by the day — a frontier model on OpenRouter for the hard problems, a local Qwen when you're offline or cost-conscious, Claude on Bedrock for work.

  • Local models are the worst of it

    Each runtime has its own ports, model refs and quirks — llama.cpp, vLLM, oMLX, Ollama — and none of it is written down where you need it.

  • Then there's the box it runs on

    A workstation under the desk, a GPU box on the LAN, a cloud instance you'd rather not leave running. Three machines, three ways to start, stop and check them.

  • Switching should take a second

    It usually doesn't. Which is the whole reason spinloop exists.

How it works

It scales with what you're actually running.

Start at the first command and stop there if that's all you need. Each step up reuses the file you already wrote.

  1. 01

    Point

    spinloop add -p ollama -m qwen3.6

    Configures the agent and points it at the model. Everything else in the config stays exactly where you left it.

  2. 02

    Serve

    spinloop serve

    The same file that configures the agent launches the engine behind it — llama-server, vLLM or oMLX, flags and all.

  3. 03

    Fleet

    spinloop fleet dashboard

    Every machine runs a daemon behind one small control API. One board watches them all, and starts or stops any of them.

  4. 04

    Cloud

    spinloop remote start

    A GPU instance that only exists while you're using it, boots to a stable address, and stops itself once you've stopped.

The Spinloop file

Like a Dockerfile, but for your coding agent.

One flat, line-oriented file describing one provider selection. Commit it beside the project, give it a short name with spinloop alias, or publish it at a URL and let your team fetch it by name.

  • The same file applies the config, serves the model, and names the fleet or cloud endpoint behind it.
  • The agent is never named in it — pick your harness when you run the command, not when you write the file.
  • No secrets in it. Keys are read from an adjacent .env, written 0600, so it stays committable.
Full syntax
Spinloop
PROVIDER  llamacpp
MODEL     unsloth/Qwen3.6-35B-A3B-GGUF:UD-Q4_K_XL
ALIAS     qwen3.6
CONTEXT   128k          # context window
OUTPUT    32k           # max output tokens
PARALLEL  2             # concurrent slots
PRESET    preset.ini    # llama.cpp flags this can't model
FLEET     fleet.yaml    # route the launch to a node
$ spinloop apply              # configure the agent
$ spinloop serve              # run the engine it names
$ spinloop harness -O         # apply, then launch the agent
$ spinloop export > Spinloop  # capture what you already have

What you get

Careful with your config, your keys and your machines.

A Go binary with no runtime dependencies. Nothing to run in the background until you ask for it.

  • Your config survives

    Settings are merged into what you already have. Other providers, your theme, even your comments stay exactly where you left them.

  • Keys stay where they belong

    Read from a local .env, written owner-only, or kept as an environment reference — never hard-coded somewhere they'll leak.

  • Model ids from the source

    spinloop list --models asks the provider's own endpoint for what it currently serves. Nothing to memorise, nothing to look up.

  • Routing picks the machine

    prefer: idle spreads work across the fleet; active consolidates it. A launch that names a fleet needs no address of its own.

  • Logs that outlive the box

    Engine and boot output ship off the instance, so you can still read what a cloud machine said after it's gone — which is when you want it most.

  • A published contract

    The daemon's control API ships an OpenAPI description with every release, so anything you build against it works from the spec, not guesswork.

Harnesses

Late-bound by design: the file picks the model, the command picks the agent.

  • opencode

    Default

    An in-place JSONC merge that keeps your comments. add also sets the chosen model as the default.

  • Pi

    Registers the provider in Pi's own model catalogue and tells you which model to pick with /model.

  • lucinate

    Writes one managed connection and points the startup default at it, so it opens straight onto the model you chose.

$ spinloop add -p ollama -m llama3.2 --harness pi   # this command only

See it first

Run a three-node fleet without owning three machines.

The dockerised example brings up real daemons with real auth and a stand-in engine, so you can drive the whole thing before setting up a single machine. No GPU, no cloud account, about a minute.

Read the fleet guide
$ cd examples/fleet-docker && cp .env.example .env
$ docker compose up -d --build
$ set -a && . ./.env && set +a
$ spinloop fleet status --fleet ./fleet.yaml

NODE     STATE         SERVING
studio   running       llamacpp  org/fake-model  (up 1m 4s)
gpu-box  idle
laptop   idle

Point your agent at anything. Then run what's behind it.

One Go binary, no runtime dependencies, MIT licensed.

brew install spinloop-ai/tap/spinloop
Star on GitHub

or build from source — go build -o spinloop ./cmd/spinloop