Global options
These ride every subcommand.
| Option | Value | Default | Description |
|---|---|---|---|
--hermetic |
— | false | Benchmark-legal mode: for the life of this process sirloop opens no network of its own — no relay dial or attach, no depot, no peer dispatch, no introductions, no update fetch — starts no listener, and latches inbound dispatch shut as if `pause remote --hard` (in-process; nothing is written to pause.json). Receipts are stamped `hermetic`. NOTE THE BOUNDARY: the harness CLI sirloop drives (claude, codex, …) is a separate process and keeps its own network — sirloop guarantees only its own surface. Env twin: SIRLOOP_HERMETIC=1 (exported to children, so --detach inherits it) |
--forbid-path |
GLOB (repeatable) | — | No-test-peeking guard: a glob a benchmark's gold tests live behind (repeatable; pass the task's FAIL_TO_PASS paths). If the verify command names one, or the run modifies one, the receipt is stamped `tainted: <reason>` — the run still finishes, and the bench exporter drops the row. File *reads* are not detectable this way and are not claimed. Env twin: SIRLOOP_FORBID_PATH (comma-separated) |
sirloop id
Show this node's identity (label, public key, fingerprint)
Usage: sirloop id [OPTIONS]
sirloop rename
Rename a node — this one, or ask a paired peer to rename itself. Either way the renamed node tells its own paired peers, so the pins they hold follow the new name instead of stranding on the old one (labels are how verbs address a peer). A renamed daemon serves under its old in-memory label until it restarts; --restart asks the peer for the update hand-off so the new name serves immediately
Usage: sirloop rename [OPTIONS] <LABEL>
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | The new label Required. |
--peer |
PEER | — | Ask this paired peer to rename itself, instead of renaming this node |
--restart |
— | false | With --peer: the peer hands off to a replacement daemon so the new name serves immediately (interrupted daemon-owned jobs resume on its boot) |
--addr |
ADDR | — | Override the peer's stored address (host:port) |
sirloop introduce
Heal the relay mesh: re-run introductions between every pair of pinned peers that share a relay AND a named room, so a hub-and-spoke (pre-introductions) becomes the full mesh a fresh pairing now gets. Idempotent — an edge that already stands is re-pinned by key, which also refreshes the labels the two sides hold for each other. The daemon runs this same sweep on its own slow cadence by default
Usage: sirloop introduce [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--relay |
RELAY | — | Heal only rooms on this relay (host:port); default: every relay that appears among the pins |
sirloop room
Group pins into named rooms (ADR 0019). Mesh management — introductions, heals, the daemon's periodic sweep — stays within a room, so one machine can sit in several isolated meshes on the same relay. Grouping is this node's own policy; the pairing boundary stays the only security boundary. With no subcommand: list rooms and members
Usage: sirloop room [OPTIONS] [COMMAND]
sirloop room set
Move a pinned peer into a named room ("default" moves it back to the open room). Local policy: it changes which mesh THIS node grows around that pin, not what the peer may do
Usage: sirloop room set [OPTIONS] <PEER> <ROOM>
| Option | Value | Default | Description |
|---|---|---|---|
peer |
positional | — | Peer label (as `sirloop peers` prints it) Required. |
room |
positional | — | Room name (≤64 bytes, printable) Required. |
sirloop room heal
Heal one named room now instead of waiting for the daemon's sweep
Usage: sirloop room heal [OPTIONS] [ROOM]
| Option | Value | Default | Description |
|---|---|---|---|
room |
positional | — | Room name; default: the default room |
sirloop serve
Run the daemon: listen for verbs from paired peers
Usage: sirloop serve [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--bind |
BIND | 127.0.0.1:4520 | Bind address. Default is loopback-only |
--lan |
— | false | Accept paired peers from other machines (shorthand for --bind 0.0.0.0:4520). Only paired keys get past the handshake |
sirloop supervise
Keep the daemon alive across crashes (P1's restart supervisor): spawn `sirloop serve` on --bind and bring a fresh one back with bounded exponential backoff whenever it dies. `sirloop stop` stops both — the supervisor honours the stop latch at every decision and stands down instead of restarting. The daemon is its own detached process: killing (or Ctrl-C-ing) this supervisor leaves the daemon serving, exactly as unsupervised
Usage: sirloop supervise [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--bind |
BIND | 127.0.0.1:4520 | Bind address the supervised daemon serves. Default matches `serve` |
sirloop connect
Attach to a hosted relay with a signed attach token — the whole onboarding a stranger needs (issue #358): validate and store the token, prove the relay takes this node's attach, then serve with the token riding every room park
Usage: sirloop connect [OPTIONS] <TOKEN>
| Option | Value | Default | Description |
|---|---|---|---|
token |
positional | — | The attach token from sirloop.com (or `sirloop relay mint`) Required. |
sirloop pair
Pair with another node
Usage: sirloop pair [OPTIONS] [ADDR]
| Option | Value | Default | Description |
|---|---|---|---|
addr |
positional | — | Address of the listening node (host:port). Omit with --listen or --relay |
--listen |
— | false | Listen for an incoming pairing instead of initiating one |
--bind |
BIND | 0.0.0.0:4521 | Bind address for --listen (LAN pairing) |
--code |
CODE | — | The 6-digit code shown by the listening node |
--relay |
RELAY | — | Rendezvous relay (host:port) — pair across networks: both sides dial the relay outbound, like a WhatsApp/Zoom call setup |
--room |
ROOM | — | Room id printed by the relay-listening node |
--relay-key |
RELAY_KEY | — | The relay's public key as printed by the listening node — pins the relay identity so a DNS-spoofed impostor fails the handshake |
--serve-port |
SERVE_PORT | 4520 | Port this node's own daemon serves on — advertised to the peer during pairing so it knows where to reach us afterwards |
sirloop relay
Run a rendezvous relay (deploy on any small VM with a public address; it forwards opaque Noise ciphertext and can read nothing)
Usage: sirloop relay [OPTIONS] [COMMAND]
| Option | Value | Default | Description |
|---|---|---|---|
--bind |
BIND | 0.0.0.0:8443 | — |
sirloop relay mint
Mint a signed attach token with $SIRLOOP_RELAY_TOKEN_KEY — how the operator mints free-tier tokens (and how tests mint any of them). Paid tiers are the website's checkout doing exactly this, with its own copy of the key
Usage: sirloop relay mint [OPTIONS] --relay <RELAY>
| Option | Value | Default | Description |
|---|---|---|---|
--relay |
RELAY | — | The relay address the token opens, as clients dial it (host:port) Required. |
--cap |
CAP | 3 | Distinct rooms the fleet may park at once (the tier's cap) |
--days |
DAYS | 30 | Days the token stays valid |
--fleet |
FLEET | — | Fleet id (32 hex chars); default: a fresh random one |
sirloop peers
List pinned peers, kick one out of the fleet, or disband it all
Usage: sirloop peers [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--unpair |
UNPAIR | — | Kick this peer out of the fleet: best-effort tell it to forget this node too, then drop its pin here regardless |
--disband |
— | false | Disband the whole fleet: kick every paired peer, one by one |
--caps |
— | false | Include each peer's last-known capabilities (from the cache) |
--p2p |
PEER (repeatable) | — | Direct P2P for one pin: `--p2p <peer> on|off` (default off = relay-only, no IP disclosure; ADR 0020). Takes effect once the WebRTC transport is built in; the relay stays the fallback |
sirloop caps
Show capabilities — this node's (probed + declared), or a peer's
Usage: sirloop caps [OPTIONS] [LABEL]
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | Peer label to query live (omitted = this node) |
--declare |
DECLARE (repeatable) | — | Declare a fact about this node: --declare azure=prod-access |
--undeclare |
UNDECLARE (repeatable) | — | Remove a declared fact by key |
--refresh |
— | false | Force a fresh probe instead of the cache |
--verify-auth |
— | false | Prove harness auth with a real turn: harnesses with no `status` command of their own get ONE bounded hello run each ("Reply with the single word: ok"), cached in harness-auth.json until the next --verify-auth. Costs real spend — never part of a routine sweep |
--addr |
ADDR | — | Override the peer's stored address (host:port) |
sirloop gates
Verify-gate coverage: which nodes and landing points are judged by a deterministic gate, and which only ever report their own success
Usage: sirloop gates [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--from |
FROM | — | Read one paired peer's gate table instead of this node's |
--all |
— | false | The whole fleet: this node plus every paired peer (an offline peer answers from its last-known manifest) |
--strict |
— | false | Exit 1 when any listed landing point has no verify gate (a trivial one that cannot fail counts as none) — or a node could not be asked at all: a CI check on fleet honesty |
--history |
— | false | Read the same table for trend: per landing point, the current green/red streak under the gate configured now, the last green, the last red, and the gate's fingerprint — folded from each node's own receipts, no separate history kept |
--addr |
ADDR | — | Override the peer's stored address (host:port) |
sirloop quota
Subscription & quota state per harness account (issue #404): the plan, the renewal timer, the usage windows each provider exposes — codex's from its own rollout logs, claude's from the vendor's usage endpoint — this node's read live, or a paired peer's from its manifest. Read-only; unknown is the honest answer for a cell the provider does not expose
Usage: sirloop quota [OPTIONS] [LABEL]
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | Peer label to read instead (asked live; its manifest carries the same probe's rows) |
--json |
— | false | Print the raw JSON rows instead of the table |
--addr |
ADDR | — | Override the peer's stored address (host:port) |
--live |
— | false | Dial the claude usage endpoint once before reading (local only): the ONLY code path that spends that endpoint's strictly-budgeted requests. Everything else — including a peer's rows — serves the 15-minute cache this writes |
sirloop setup
Install a harness CLI bare-metal (npm/pip, no containers) and verify it
Usage: sirloop setup [OPTIONS] <FRAMEWORK>
| Option | Value | Default | Description |
|---|---|---|---|
framework |
positional | — | The harness to install: claude | codex | opencode | qwen | zcode | gemini | copilot | cursor-agent | aider | crush Required. |
--as-entry |
— | false | After a successful install, also make it this node's entry harness |
sirloop entry
Show or set this node's entry harness — the landing point for instructions from paired peers/controllers
Usage: sirloop entry [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--framework |
FRAMEWORK | — | Known framework: claude | codex | opencode | qwen | zcode | gemini | copilot | cursor-agent | aider | crush |
--cmd |
CMD (repeatable) | — | Custom argv template instead (repeat per arg; {goal} lands the instruction): --cmd mytool --cmd --flag --cmd {goal} |
--access |
ACCESS | — | What the harness may do here: full (default — write files, run commands; the verify gate is the safety) or ro (read-only analysis; a verify gate that needs edits cannot pass) |
--cwd |
CWD | — | Working directory for the harness and verify command |
--model |
MODEL | — | Model injected via the framework's native flag |
--verify |
VERIFY | — | Verify command (local shell) — its exit code is the verdict |
--timeout-secs |
TIMEOUT_SECS | — | Kill the harness past this many seconds |
--stdin |
— | false | Deliver the goal on the harness's stdin instead of argv — required for npm/batch-shim CLIs on Windows (claude, etc.), which mangle multi-line argv arguments |
--clear |
— | false | Remove the entry configuration |
sirloop project
Manage this node's named projects — each is its own landing point (cwd, harness, verify gate) on the one shared daemon
Usage: sirloop project [OPTIONS] [NAME]
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Project name; omit to list all projects |
--framework |
FRAMEWORK | — | Known framework: claude | codex | opencode | qwen | zcode | gemini | copilot | cursor-agent | aider | crush |
--cmd |
CMD (repeatable) | — | Custom argv template (repeat per arg; {goal} lands the goal). Hyphen-leading values are taken literally, so a real harness invocation types as-is: --cmd claude --cmd -p --cmd {goal} |
--access |
ACCESS | — | What the harness may do here: full (default) or ro (read-only) |
--cwd |
CWD | — | Working directory for the harness and verify command |
--model |
MODEL | — | Model injected via the framework's native flag |
--verify |
VERIFY | — | Verify command (local shell) — its exit code is the verdict |
--timeout-secs |
TIMEOUT_SECS | — | Kill the harness past this many seconds |
--stdin |
— | false | Deliver the goal via stdin (needed for npm-shim CLIs on Windows) |
--repo |
REPO | — | Git repo this project provisions from — makes it portable to any paired node via `sirloop provision` |
--branch |
BRANCH | — | Branch to provision |
--root |
ROOT | — | Set where provisioned projects are placed on this node (default C:\git on Windows, ~/git elsewhere) |
--remove |
— | false | Remove this project |
sirloop providers
Show or edit the model provider registry: named endpoints (anthropic-compat | openai-compat | omniroute) and the ordered `model_classes` that cascade over them. A task then asks for a model by requirement — `provider/model`, `class:<name>`, `omniroute:<route>`, or a bare model id — and the resolver binds the first reachable survivor into the harness's own model flag plus an environment overlay for that child alone. Nothing here is ever written into a harness's own config
Usage: sirloop providers [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--preset |
PRESET | — | Write a built-in endpoint profile (rows + a class) for a vendor with a public compatible API but no CLI of its own — `deepseek` adds its OpenAI- and Anthropic-dialect endpoints so installed harnesses can front DeepSeek models (--model class:deepseek) |
--set |
SET | — | Add or replace a provider row (with --kind/--base-url/--auth-env) |
--kind |
KIND | — | anthropic-compat | openai-compat | omniroute |
--base-url |
BASE_URL | — | Endpoint base url (e.g. localhost:20128) |
--auth-env |
AUTH_ENV | — | NAME of the environment variable holding this endpoint's key — never the key itself |
--models |
MODELS | — | Comma-separated model ids: the declared list for --set, or the cascade order for --class |
--hermetic |
— | false | Ask an omniroute row for hermetic traffic (memory injection and compression off) |
--remove |
REMOVE | — | Remove a provider row |
--class |
CLASS | — | Add or replace a model class (with --models a,b,c) |
--remove-class |
REMOVE_CLASS | — | Remove a model class |
--no-probe |
— | false | Skip the reachability probe when listing |
--probe |
FRAMEWORK | — | Conformance-probe one harness: stand up a fake local endpoint, redirect the CLI at it, and prove the base-url mechanism this node's adapter table claims for it actually reaches the wire. Spawns the real CLI (no key, no spend); records the verdict in frameworks.json |
--probe-timeout |
PROBE_TIMEOUT | 120 | Seconds the probed harness may run before it is killed |
sirloop browser
Pull a newer sirloop binary from a paired peer (no compiling) and install it in place — restart `serve` afterwards. A different- platform peer falls back to its release channel: the sha comes over the authenticated channel, the bytes from the relay depot, verified. `--push` inverts the direction: the peer is told to run this same pull against this node's daemon, so a fleet member can be updated without a shell on it — the same rails apply on its side. `--push-channel` (optionally with `--all`) configures the peer's release channel remotely instead of moving a build. Drive a browser — locally, or on a paired peer over the authenticated channel. Remote sessions persist per caller (open, then act); local runs are one-shot. The answering node's rails apply everywhere: http/https only, a throwaway headless profile, no wire-supplied JavaScript
Usage: sirloop browser [OPTIONS] [PEER] <COMMAND>
| Option | Value | Default | Description |
|---|---|---|---|
peer |
positional | — | Paired peer to drive; omit for this node (one-shot, local) |
--addr |
ADDR | — | — |
sirloop browser open
Open a URL (http/https only)
Usage: sirloop browser open [OPTIONS] <URL>
| Option | Value | Default | Description |
|---|---|---|---|
url |
positional | — | Required. |
sirloop browser snapshot
Where is the page now — url, title, text snippet
Usage: sirloop browser snapshot [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--url |
URL | — | Local one-shot: open this page first |
sirloop browser shot
A PNG of the viewport (1024x768); --out writes the file
Usage: sirloop browser shot [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--out |
OUT | — | — |
--url |
URL | — | Local one-shot: open this page first |
sirloop browser click
Click the element a CSS selector matches
Usage: sirloop browser click [OPTIONS] <SELECTOR>
| Option | Value | Default | Description |
|---|---|---|---|
selector |
positional | — | Required. |
--url |
URL | — | Local one-shot: open this page first |
sirloop browser type
Type text into the element a CSS selector matches
Usage: sirloop browser type [OPTIONS] <SELECTOR> <TEXT>
| Option | Value | Default | Description |
|---|---|---|---|
selector |
positional | — | Required. |
text |
positional | — | Required. |
--url |
URL | — | Local one-shot: open this page first |
sirloop browser scroll
Scroll the page (positive is down)
Usage: sirloop browser scroll [OPTIONS] <DY>
| Option | Value | Default | Description |
|---|---|---|---|
dy |
positional | — | Required. |
--url |
URL | — | Local one-shot: open this page first |
sirloop browser close
End the session on the peer (kills its throwaway engine)
Usage: sirloop browser close [OPTIONS]
sirloop update
Usage: sirloop update [OPTIONS] [PEER]
| Option | Value | Default | Description |
|---|---|---|---|
peer |
positional | — | Paired peer to pull from; omit to use the release channel |
--force |
— | false | Install even if the peer's build is not newer |
--channel |
CHANNEL | — | Set the release channel: the peer this node updates from when no peer is named — and, with --auto on, unprompted by the daemon |
--auto |
AUTO | — | Let the daemon install newer channel builds by itself and hand off to them (on|off) One of: on, off. |
--every |
EVERY | — | Seconds between the daemon's unprompted checks (floor 300) |
--show |
— | false | Print the release channel and the last unprompted check |
--forget-channel |
— | false | Forget the release channel (the daemon stops checking) |
--restart |
— | false | Restart onto the new build. With --push the peer performs the hand-off itself (the new image spawns as the replacement daemon, the old process exits, interrupted daemon-owned jobs resume on its boot); on a local pull the daemon running here is restarted |
--push |
— | false | Push instead of pull: tell the peer to update itself from this node's daemon (the same rails apply on its side — platform match, newer build unless --force; it restarts `serve` on its own schedule, never mid-connection) |
--relay |
RELAY | — | Relay hosting the depot (default: the peer's stored relay) |
--addr |
ADDR | — | Override the peer's stored address (host:port) |
--push-channel |
— | false | Configure the PEER's release channel remotely instead of pulling/pushing a build — the wire side of --channel, so a node can be pointed without a shell on it. Combined with --channel <label>, that label is who the peer should follow (must already be paired on the peer's side); with --channel omitted, the peer follows THIS node ("follow me"). --auto, --every and --forget-channel apply on the peer exactly as they would locally |
--all |
— | false | With --push-channel, apply to every paired peer instead of the one named — drop the peer name when using this |
sirloop outbox
The standing outbox: fleet commands addressed to an offline peer that STAND — parked durably and delivered by this node's daemon when the peer returns. Only verbs that mean the same thing whenever the machine comes back stand (an update push, a rename, a channel setting); a task (`run`/`ask`/`shell`) never parks — it fails to your face immediately so you reassign it to a machine that is on. With no flag: list what stands
Usage: sirloop outbox [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--drop |
DROP | — | Cancel one standing command by id (a unique prefix is enough) |
--flush |
— | false | Try to deliver everything standing right now, ignoring backoff |
sirloop ops
The ops ledger: control-plane instructions — update pulls and pushes, the daemon's unprompted channel checks, outbox deliveries — each recorded when it fires and settled with what actually happened. In-flight instructions print first; that is the question this ledger exists to answer. (Runs have their own audit surface: `sirloop results` and `sirloop trail`.)
Usage: sirloop ops [OPTIONS]
sirloop publish
Publish a sirloop build to the relay depot and record it in this node's release catalog, so different-platform peers can update from it. With no file, publishes this running binary
Usage: sirloop publish [OPTIONS] [FILE]
| Option | Value | Default | Description |
|---|---|---|---|
file |
positional | — | Path to a (cross-)built sirloop binary; omit for self |
--os |
OS | — | Target platform of the file (defaults to this machine's) |
--arch |
ARCH | — | — |
--epoch |
EPOCH | — | Build epoch of the file (unix secs). Must equal the SIRLOOP_BUILD_EPOCH the file was compiled with, or a peer that installs it sees the catalog as forever newer and reinstalls on every `update`. Default: now (only right for a build you just made without pinning the epoch) |
--relay |
RELAY | — | Relay hosting the depot (default: first pinned relay) |
sirloop docs-gen
Generate the CLI reference for the docs site: walk this binary's own command tree and write `sirloop-cli-reference.json` into --out. The release pipeline feeds that JSON to sirloop.com's renderer, so the published docs are the tree as shipped — the build stamp rides inside as provenance. Output is deterministic (no timestamps)
Usage: sirloop docs-gen [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--out |
OUT | . | Directory to write sirloop-cli-reference.json into (created if missing) |
sirloop provision
Materialize one of this node's projects on a paired peer: the peer clones/refreshes the repo under its own projects root and registers the project, ready for `run --project`
Usage: sirloop provision [OPTIONS] [PEER] [NAME]
| Option | Value | Default | Description |
|---|---|---|---|
peer |
positional | — | — |
name |
positional | — | Name of a local project that has a --repo configured |
--addr |
ADDR | — | Override the peer's stored address (host:port) |
--cloud |
CLOUD | — | A disposable cloud node (issue #364, provider v1 = SSH): ssh://user@host — you bring the instance, sirloop installs its own image (platform match, sha verified), pairs it over the relay, stamps its cost hint and starts the daemon |
--relay |
RELAY | — | The rendezvous relay the cloud node pairs through (host:port) — the only road a cloud node has to this machine |
--size |
SIZE | small | The instance's size NAME, for cost attribution on every receipt it settles (declared, never measured) |
--destroy |
— | false | Tear a cloud node down: pause → drain (zero lanes, empty outbox) → stop → unpair → remove sirloop from the instance. Any failing step leaves it paused and paired |
sirloop orchestrate
Self-orchestrate a goal: loop harness→verify→feedback locally, cascade across installed harnesses, or route to the fleet when requirements (or a missing local entry) demand it
Usage: sirloop orchestrate [OPTIONS] [GOAL]...
Self-orchestrate a goal: loop harness→verify→feedback locally, cascade across installed harnesses, or route to the fleet when requirements (or a missing local entry) demand it.
EXIT CODES: 0 = settled ACCEPTED. 1 = settled REJECTED (the gate ran and the work failed — a real verdict, not an error). 2 = hard error: nothing settled, because the lane, the repo, the config or the harness stopped the run before it could produce a verdict. A caller scoring runs wants 0/1 as the score and 2 as "this trial did not happen".
WHERE THE WORK HAPPENS: when the entry/project cwd is inside a git repo, the run gets its own throwaway worktree lane, and an ACCEPTED run's lane is deleted with nothing merged back — the cwd never sees the edits (this is deliberate: it is what keeps two runs on one project from racing, and what makes `--deliver patch` the way to collect the diff). Pass --in-place to work in the cwd itself instead
| Option | Value | Default | Description |
|---|---|---|---|
goal |
positional | — | The goal (free text) |
--attempts |
ATTEMPTS | — | Total attempt budget for the primary harness (default 3, or the workflow's own when --workflow names one) |
--workflow |
WORKFLOW | — | Run a saved workflow instead of a typed goal: its template is expanded with --param values and its harness/model/gate/project bindings fill in whatever this command line leaves unsaid (`sirloop workflow list`). The receipt records the workflow's name, file digest and the parameter values |
--param |
NAME=VALUE (repeatable) | — | name=value for a placeholder in --workflow's template (repeatable) |
--require |
REQUIRE (repeatable) | — | Capability requirements: docker | key=value | os:linux | device:android (also android-emulator | android-physical | ios-simulator | ios) (repeatable; routes to whichever node satisfies) |
--peer |
PEER | — | Force execution on a specific peer |
--scatter |
— | false | Fan the same goal out to every eligible node (self + peers with entry harnesses, filtered by --require) and report all verdicts |
--project |
PROJECT | — | Named project to land on (here or on the chosen peer) |
--model |
MODEL | — | Model requirement for this dispatch, overriding the project's: provider/model | class:<name> | omniroute:<route> | a bare model id passed to the harness untouched (see `sirloop providers`) |
--require-model |
— | false | Refuse the run (exit 2, before attempt 1) if --model names a provider this node's registry does not have, instead of passing the string to the harness verbatim — which a CLI that does not recognize it answers by silently using its own default model. Implied by --hermetic, where a number attributed to a model that never ran is worse than no number at all |
--in-place |
— | false | Run the harness in the entry/project cwd itself instead of this run's own throwaway git worktree lane, so accepted edits stay where you pointed sirloop. Still exclusive: a second run on the same directory is refused rather than raced |
--addr |
ADDR | — | Override the peer's stored address (host:port) |
--detach |
— | false | Start the loop in a background process and return immediately with its run id — close the terminal, collect the result later with `sirloop results <id>` |
--kind |
KIND | — | Pin the task-deliverable kind the report contract asks the harness for: code | brainstorm | research | ops | generic, or patch (sirloop extracts the run's own diff — needs a git workspace). Unset lets the harness choose from the registry |
--parent |
RUN_ID | — | Link this run as a child of <RUN_ID> in the run tree; defaults to $SIRLOOP_JOB when invoked from inside a harness run, so a driver's breakdown stays visible as a tree in `sirloop runs` |
--repo |
REPO | — | Run in a workspace of this repository (git url or local path) instead of a project's tree: sirloop materializes it here, at --at, in this run's own lane. Clones are cached as one bare mirror per repo, so a batch of runs against one repo clones once |
--at |
AT | — | The exact commit --repo is checked out at — the base a `patch` deliverable diffs against, and the base an evaluation harness replays that patch onto |
--needs-approval |
— | false | Park this run at the door before attempt 1: nothing runs until `sirloop approve <id>` — here, from a paired peer, or the dashboard. Silence past the deadline (30 min; settings.json `approval_timeout_secs`) denies it, charging no attempt |
sirloop notify
Show, set, or test the settle notification hook — a command of your own that sirloop fires (out of process, outbound only) whenever a run settles here. The run is described in the environment: SIRLOOP_RESULT_ID, SIRLOOP_VERDICT, SIRLOOP_GOAL, SIRLOOP_TARGET, SIRLOOP_ATTEMPTS, and SIRLOOP_PROJECT (present only when the run targeted a named project)
Usage: sirloop notify [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--cmd |
CMD (repeatable) | — | Command argv to fire on settle (repeat per arg): --cmd curl --cmd -s --cmd api.telegram.org/… |
--test |
— | false | Fire the configured hook now with placeholder values |
--clear |
— | false | Remove the hook |
sirloop plugin
Out-of-process plugins (ADR 0022): programs this node's owner registers, the daemon spawns and supervises, and sirloop talks to over the child's stdin/stdout — a chat channel (Microsoft Teams first, in its own repository) that polls for messages and posts replies. What a message may DO is decided here, not in the plugin: allowlist by default, expiring pairing code, constrained verbs (/ask, /run, /status), never raw passthrough. No subcommand: list
Usage: sirloop plugin [OPTIONS] [COMMAND]
sirloop plugin list
List registered plugins and what the daemon last knew about them
Usage: sirloop plugin list [OPTIONS]
sirloop plugin add
Register a plugin directory (the one holding plugin.json)
Usage: sirloop plugin add [OPTIONS] <PATH>
| Option | Value | Default | Description |
|---|---|---|---|
path |
positional | — | Path to the plugin's directory Required. |
--name |
NAME | — | Register under this name instead of the manifest's |
--disabled |
— | false | Register but do not start it |
sirloop plugin remove
Forget a plugin (its state under ~/.sirloop/plugins/<name>/ stays)
Usage: sirloop plugin remove [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sirloop plugin enable
Let the daemon start it (takes effect on the daemon's next start)
Usage: sirloop plugin enable [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sirloop plugin disable
Stop starting it; a running one is not restarted after it exits
Usage: sirloop plugin disable [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sirloop plugin set
Host options (project=, framework=, model=) or the plugin's own config (key=value; JSON values are kept typed; an empty value clears the key)
Usage: sirloop plugin set [OPTIONS] <NAME> <PAIRS>...
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
pairs |
positional | — | Required. |
sirloop plugin pair
Mint a pairing code: a sender types `/pair <code>` in the channel within 15 minutes to be allowlisted
Usage: sirloop plugin pair [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sirloop plugin allow
Allowlist a sender id directly, without a code
Usage: sirloop plugin allow [OPTIONS] <NAME> <SENDER>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sender |
positional | — | The channel's own id for the sender (what the plugin reports) Required. |
--label |
LABEL | — | A display name to remember it by |
sirloop plugin deny
Remove a sender from the allowlist
Usage: sirloop plugin deny [OPTIONS] <NAME> <SENDER>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sender |
positional | — | Required. |
sirloop plugin senders
List allowlisted senders
Usage: sirloop plugin senders [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sirloop plugin run
Run one plugin in the foreground on this console — no daemon needed — until it exits or Ctrl-C
Usage: sirloop plugin run [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sirloop plugin log
Show the tail of the plugin's stderr log
Usage: sirloop plugin log [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
--lines |
LINES | 40 | — |
sirloop mcp
Serve this node and its paired fleet as MCP tools over stdin/stdout (newline-delimited JSON-RPC 2.0) to any MCP-capable agent — Claude Code, codex, opencode. Runs with the authority of this terminal's CLI. The read-only tools (status, peers, caps, gates, results, runs, lanes, schedules) are always on; tools that start, stop or redirect work exist only for the verbs named in --allow, and a call to one that was not named is refused by name. No port, no token: the pipe is the boundary. Serves until stdin closes
Usage: sirloop mcp [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--allow |
VERBS | — | Action verbs to grant this session, comma-separated: run | ask | cancel | swap (default: none — read-only) |
sirloop remote
Open the browser seat: a temporary, token-guarded web surface for controlling this sirloop from a browser — the live session feed, a goal input, slash palette, results/trail views, and the browser verbs with inline screenshots. Opt-in and ephemeral: one random token per run (printed once as a URL, never written down), loopback by default, gone when the process dies. `--bind` beyond loopback is an explicit operator choice; the token is the only boundary there
Usage: sirloop remote [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--bind |
BIND | — | Bind address [default: 127.0.0.1:8791] |
--token-from |
TOKEN_FROM | — | Read the seat token from this environment variable instead of generating one (secrets come from the environment, not argv) |
sirloop dashboard
Open the local dashboard: a token-guarded web control room for this sirloop — fleet, projects, models, results, audit trail, node health, and a tiered surface from plain-language buttons (simple) down to the executable's raw verb set (RAW). First visit opens a tutorial wizard. Same security posture as `remote`: one random token per run, loopback by default, gone when the process dies
Usage: sirloop dashboard [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--bind |
BIND | — | Bind address for THIS run (overrides any saved default) |
--default-bind |
HOST:PORT|loopback | — | Make a bind the persistent default so every start — including the login launcher — serves it without flags. `host:port`, or `loopback` to reset to 127.0.0.1:8792. Beyond-loopback defaults are said loudly on every start: the token is the only boundary |
--token-from |
TOKEN_FROM | — | Read the token from this environment variable instead of the one this machine keeps (secrets come from the environment, not argv) |
--url |
— | false | Print the URL this machine's dashboard serves — token and all — and exit. What to run when a page has gone stale, or when the login launcher started the dashboard and printed its URL to a stdout nobody sees. Add --open to open it |
--new-token |
— | false | Mint a fresh token before serving. Every URL handed out so far stops working — for a link that leaked, or a shared screen |
--open |
— | false | Open the default browser on the dashboard once it is listening |
--startup |
STARTUP | — | Manage the login-time launcher: install | remove | status. `install` makes the dashboard start (and open a browser) when you log in; the launcher stores no token — the machine's kept token makes the URL the same one every login. The dashboard brings the mesh daemon up with it, so this is the whole node autostarting — also controllable from the page |
--no-serve |
— | false | Do not start (or supervise) the mesh daemon from this dashboard — for a machine that runs `sirloop serve` its own way |
sirloop run
Land an instruction on a paired peer's entry harness
Usage: sirloop run [OPTIONS] <LABEL> [GOAL]...
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | Required. |
goal |
positional | — | The instruction (free text) |
--project |
PROJECT | — | Named project on the peer to land on |
--addr |
ADDR | — | Override the stored address (host:port) |
--kind |
KIND | — | Pin the task-deliverable kind the peer's report contract asks the harness for: code | brainstorm | research | ops | generic. Unset lets the harness choose |
--framework |
FRAMEWORK | — | Override the peer's entry framework for this job: claude | codex | opencode | qwen | zcode. The peer refuses one it does not have installed; if the chosen (or configured) harness fails, the peer cascades to its other installed harnesses before settling REJECTED |
--model |
MODEL | — | Model requirement for this job, overriding the peer entry's: provider/model | class:<name> | omniroute:<route> | a bare model id passed to the harness untouched. Resolved against the peer's own registry (its `sirloop providers`), and refused by it when the harness that would run could not carry the model at all |
--parent |
RUN_ID | — | Link this job as a child of <RUN_ID> in the run tree; defaults to $SIRLOOP_JOB when invoked from inside a harness run |
sirloop ask
Ask an ephemeral peer agent: spawn a fresh harness session on a paired peer (or here, with --local) for exactly one prompt, print the answer, and the agent is gone — no project, no verify gate, no queue, nothing durable. It thinks in a throwaway scratch directory, read-only by default (--full lets a scratch experiment write and run commands, under the same pairing-is-the-boundary trust as `run`). Built for borrowing judgement rather than landing work: brainstorming, a second opinion from another harness or model, or the same question fanned across several nodes at once — name comma-separated peers (or --all) and every answer comes back under its node's own header. Where `run` is goal → gate → durable receipt, `ask` is prompt → answer → gone
Usage: sirloop ask [OPTIONS] [LABEL] [PROMPT]...
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | Peer label — or comma-separated labels to fan the same prompt across several nodes. Omit with --local or --all |
prompt |
positional | — | The prompt (free text) |
--all |
— | false | Ask every paired peer at once (the brainstorm sweep) |
--local |
— | false | Ask this node itself — no peer, the agent spawns right here |
--framework |
FRAMEWORK | — | Harness for the agent: claude | codex | opencode | qwen | zcode (or a frameworks.json row). The answering node vets it; unset uses its configured entry harness |
--model |
MODEL | — | Model for the harness's native flag, verbatim (a literal id) |
--full |
— | false | Let the agent write files and run commands in its scratch (default: read-only — an opinion needs no write access) |
--timeout-secs |
TIMEOUT_SECS | — | Harness wall-clock seconds; the answering node caps it at its own ceiling (900) |
--keep |
— | false | Keep the exchange in the answering node's receipts ledger — prompt as goal, answer as transcript, shown in `sirloop results` and the dashboard (as a self-report: no gate ran). Default: nothing durable anywhere |
--brief |
— | false | Ask for a structured brief instead of prose: the agent ends with a marked JSON line and only that summary comes back (kind, summary, items with their critical line, refs). The long answer stays on the answering node — pair with --keep to keep it auditable there. Built for a caller that pays by the token |
--reduce |
— | false | Fan out, then reduce: one local agent reads every answer and returns a single brief — the consensus, the real disagreements, a recommendation — instead of N transcripts. Needs at least two answers. Each node's harness/model/exit is still printed verbatim beneath it; the rollup never restates a verdict. Add --brief to compress the leaves on their own nodes too |
--addr |
ADDR | — | Override the stored address (host:port) — single peer only |
--parent |
RUN_ID | — | Link this ask as a child of <RUN_ID> in the run tree; defaults to $SIRLOOP_JOB when invoked from inside a harness run |
sirloop shell
Run a command in a persistent shell session on a paired peer — the direct way to set a node up (clone a repo, register a project, install a tool) so the first sirloop can create what a node needs instead of only landing goals on projects that must already exist. A named session keeps its working directory across commands; open several names for several terminals. Paired-only, like every verb
Usage: sirloop shell [OPTIONS] <LABEL> [COMMAND]...
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | Required. |
command |
positional | — | The command line to run (free text). Omit to just open the session at --cwd, or with --list / --close |
--shell |
SHELL | default | Named session on the peer — each keeps its own cwd. Reuse a name to send another command to the same terminal |
--cwd |
CWD | — | Working directory to open the session in (its starting cwd) |
--list |
— | false | List the shell sessions open on the peer for this node |
--close |
— | false | Close the named session on the peer |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop term
Open an interactive terminal — the project's coding CLI in its own TUI, or the platform shell — here or on a paired peer. The twin of `sirloop run` for the times a human wants to drive the harness personally: same project, same resolved argv, same provider and endpoint environment a headless run of that entry would get, minus the goal. Nothing durable is created and no lane is taken. The terminal lives exactly as long as this command does — leave it and the program on the far node dies with the connection
Usage: sirloop term [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--peer |
PEER | — | Paired peer to open the terminal on. Omit for this machine |
--project |
PROJECT | — | Project whose entry (harness, directory, model) to open. Omit for the node's default entry |
--framework |
FRAMEWORK | — | Harness to open instead of the project's own — or `shell` for the platform shell in the project's directory |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop harness
Harness fleet lifecycle (issue #372): install, configure, verify — and open a harness's own login on a paired node. `--all` fans the action out to every paired peer
Usage: sirloop harness [OPTIONS] [PEER] <COMMAND>
| Option | Value | Default | Description |
|---|---|---|---|
peer |
positional | — | Paired peer to act on (omit with --all) |
--all |
— | false | Every paired peer, one line each |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop harness setup
Install a harness CLI on the node(s) with the bare-metal recipe (npm/pip), then re-probe it
Usage: sirloop harness setup [OPTIONS] <FRAMEWORK>
| Option | Value | Default | Description |
|---|---|---|---|
framework |
positional | — | Harness to install (claude, codex, opencode, …) Required. |
sirloop harness config
Push adapter and provider rows to the node(s) — the same JSON a hand-edited file takes, vetted the same way; an invalid row refuses the whole push
Usage: sirloop harness config [OPTIONS] <FILE>
| Option | Value | Default | Description |
|---|---|---|---|
file |
positional | — | Path to a JSON file: {"frameworks": […], "providers": {"name": …}} Required. |
sirloop harness login
Open the harness's own login in a terminal on the peer — the vendor's flow, driven by sirloop launching it (never implemented by sirloop); the credential stays in the CLI's own store there
Usage: sirloop harness login [OPTIONS] <FRAMEWORK>
| Option | Value | Default | Description |
|---|---|---|---|
framework |
positional | — | Harness whose login to run Required. |
sirloop harness verify
Run the auth-state probe on the node(s): the harness's own status command where it has one, else the cached verdict — `--hello` spends one real turn
Usage: sirloop harness verify [OPTIONS] <FRAMEWORK>
| Option | Value | Default | Description |
|---|---|---|---|
framework |
positional | — | Harness to verify Required. |
--hello |
— | false | Spend one real turn when the harness has no status command |
sirloop harness status
The replication matrix: every harness this controller pushed to a peer, and where each cell stands — pushed, node-verified, or user-confirmed (the green check is BOTH sides, never a probe or a click alone)
Usage: sirloop harness status [OPTIONS]
sirloop harness confirm
The human half of the two-way gate: confirm, from THIS controller, that a peer's verified verdict is truly the access you meant
Usage: sirloop harness confirm [OPTIONS] <FRAMEWORK>
| Option | Value | Default | Description |
|---|---|---|---|
framework |
positional | — | Harness whose verdict is confirmed Required. |
sirloop results
Read run receipts — the durable results of past runs. With no id, the most recent runs; with one, that run in full plus its transcript. Own node by default; `--from <peer>` collects a paired peer's instead; `--fleet` merges what every reachable node is running and queueing
Usage: sirloop results [OPTIONS] [ID]
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Receipt id (a prefix is enough) |
--tail |
TAIL | 80 | Transcript lines to show with an id |
--from |
FROM | — | Read a paired peer's results over the wire instead of this node's |
--addr |
ADDR | — | Override the stored address (host:port) of --from |
--fleet |
— | false | Every node at once: this node plus every paired peer, asked in parallel, merged into one table of what is running and queued and, below it, the newest settled receipts across the fleet (--limit per node). Unreachable peers are named as unreachable, never omitted |
--limit |
LIMIT | 0 | How many settled receipts to list (per node with --fleet). 0 = the default page |
--patch |
— | false | With an id: print that run's patch deliverable and nothing else, so it can be piped straight into `git apply` (or a benchmark's model_patch field). Reads the full patch file when the receipt holds only a truncated prefix |
--json |
— | false | Print receipts as JSON instead of tables — one object with an id, the page as an array without. The receipt is the whole durable record (verdict, deliverable, segments, git evidence); the transcript stays in its own file, transcripts/<id>.log |
sirloop feed
Follow the controller feed — what the fleet is doing, live. Every paired node's feed at once by default (one connection each), folded into a single view: runs in flight, gate verdicts, refusals, and attempts spent. Read-only; nothing here can change a node
Usage: sirloop feed [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--from |
FROM (repeatable) | — | Follow only these peers (repeatable). Default: every pin |
--once |
— | false | Print one page and exit instead of following |
--json |
— | false | Emit the fleet view as JSON — one object per change while following, one object with --once |
--since |
SINCE | 0 | Resume from a cursor instead of asking for a fresh snapshot (only meaningful with --once and a single --from) |
sirloop offer
Offer a task to another node: park a sealed manifest on its board for it — or anyone paired with it — to claim. The unit of handoff is a **pushed branch**: commit and push first, because nothing uncommitted ever crosses this wire
Usage: sirloop offer [OPTIONS] --project <PROJECT> --repo <REPO> --branch <BRANCH> <PEER> <GOAL>
| Option | Value | Default | Description |
|---|---|---|---|
peer |
positional | — | The peer whose board to park it on Required. |
goal |
positional | — | What the claiming node should accomplish Required. |
--project |
PROJECT | — | Project name the claimant registers it under Required. |
--repo |
REPO | — | Clonable repo url Required. |
--branch |
BRANCH | — | The pushed branch holding the work Required. |
--attempts |
ATTEMPTS | 3 | Attempts the claimant may spend |
--verify |
VERIFY | — | The gate that decides it; omitted, the claimant's own |
--framework |
FRAMEWORK | — | Preferred harness — a preference the claimant may override |
--ttl |
TTL | 86400 | Seconds the offer stays claimable |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop offers
Read an offer shelf — what work is parked on it, and who holds what
Usage: sirloop offers [OPTIONS] [PEER]
| Option | Value | Default | Description |
|---|---|---|---|
peer |
positional | — | The peer whose board to read; omit for this node's own |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop claim
Claim an offer and land it here: the board grants it to exactly one node, then this node clones the manifest's branch under its own projects root and runs the goal through its own loop and its own gate. A landing that fails releases the claim
Usage: sirloop claim [OPTIONS] <PEER> <ID>
| Option | Value | Default | Description |
|---|---|---|---|
peer |
positional | — | The peer whose board holds it Required. |
id |
positional | — | Offer id (16 hex characters, as `sirloop offers` prints it) Required. |
--no-adopt |
— | false | Take it without landing it — the claim is then a lease that expires unless an adopt is confirmed before it does |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop swap
Take a running task away from its driver and hand it to another harness: the current one is stopped where it stands, the next gets a deterministic handoff brief (goal, gate, git evidence, what has been tried), and the run keeps its attempt budget. With no id, lists the runs in flight here so you can pick one
Usage: sirloop swap [OPTIONS] [ID]
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Run id (a prefix is enough); omit to list what is running |
--to |
TO | — | Harness to hand it to: claude | codex | opencode | qwen. Omitted = the next installed one in the cascade |
--from |
FROM | — | Redirect a run executing on a paired peer instead of here: the request is parked on that node (the same file its own CLI writes) for the loop driving the run to honour. The peer vets the target against what is installed there, fail-closed |
--addr |
ADDR | — | Override the stored address (host:port) of --from |
sirloop cancel
Stop a live run: park a stop beside its intent for the loop driving it to honour at its next poll (the same file a peer's `cancel` verb writes). The gate still answers first — a run that goes green before the stop lands settles green — and a stopped run's receipt reads STOPPED, never `rejected`, because no gate ruled on it
Usage: sirloop cancel [OPTIONS] [ID]
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Run id (a prefix is enough); omit to list what is running |
--reason |
REASON | — | Why, in one line — it rides into the receipt and the ledger |
--from |
FROM | — | Stop a run executing on a paired peer instead of here |
--addr |
ADDR | — | Override the stored address (host:port) of --from |
sirloop approve
Let a run waiting at the door start: one dispatched with --needs-approval, or landing on a project that requires approval. The decision is a file parked beside the run's intent (like `cancel`), honoured by whichever loop is waiting at its next poll. With no id, lists the runs waiting here and the landing points whose policy parks every dispatch
Usage: sirloop approve [OPTIONS] [ID]
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Run id (a prefix is enough); omit to list what is waiting |
--from |
FROM | — | Decide for a run waiting on a paired peer instead of here |
--addr |
ADDR | — | Override the stored address (host:port) of --from |
--require |
LANDING | — | Policy: make every dispatch landing on this project (or `default`, the default entry) wait at the door — whoever sent it: a peer, a plugin's /run, a schedule fire. Kept in settings.json (`approval_required`) |
--release |
LANDING | — | Lift that policy from a landing point |
sirloop deny
Refuse a run waiting at the door: it settles DENIED with no attempt charged — nothing ran and no gate ruled, so the receipt says neither `rejected` nor STOPPED
Usage: sirloop deny [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Run id (a prefix is enough) Required. |
--reason |
REASON | — | Why, in one line — it rides into the receipt and the ledger |
--from |
FROM | — | Decide for a run waiting on a paired peer instead of here |
--addr |
ADDR | — | Override the stored address (host:port) of --from |
sirloop stop
Stop this node's daemon (`sirloop serve`) from any shell — or a paired peer's with --from (P1's missing verb). The daemon writes its disarm latch and exits: no launcher, dashboard auto-start or restart brings it back until `sirloop serve` (or the dashboard's Start button) arms it again. Detached runs are their own processes and keep going to their receipts; daemon-owned jobs resume on the next boot
Usage: sirloop stop [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--from |
FROM | — | Stop a paired peer's daemon instead of this node's |
--addr |
ADDR | — | Override the stored address (host:port) of --from |
--drain |
— | false | Let what is running there settle first; start nothing new meanwhile |
sirloop lanes
Workspace lanes (M6.4): a landed job or local run gets its own git worktree rather than sharing a project's cwd, so two runs landed on the same project never race. With no flag, lists lanes still kept around for inspection (a rejected run's worktree, left exactly as its harness left it until reclaimed)
Usage: sirloop lanes [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--fleet |
— | false | The whole fleet's lane picture, one line per node (queue depth included — the number that says "add capacity": a cron'd `provision --cloud` reads exactly this, issue #364 ruling 2) |
--reap |
— | false | Reclaim every kept lane now (normally left for a human to inspect first) |
--slots |
SLOTS | — | How many runs this node may execute at once (M6.9). A run that lands with every slot busy is queued, not refused, and starts when one frees. Omit to see the cap in force |
--default-slots |
— | false | Back to the built-in default cap (this machine's parallelism, bounded) |
sirloop job
Poll a job started with `run`
Usage: sirloop job [OPTIONS] <LABEL> <ID>
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | Required. |
id |
positional | — | Required. |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop tui
Open the fleet TUI: rooms as tabs, nodes with live presence, capability details, and a command bar that dispatches to the selected node
Usage: sirloop tui [OPTIONS]
sirloop recover
Sweep for interrupted runs (crash/reboot) and resume them now. With `--reassign`/`--orphan`: act on a delegated job whose peer went MIA mid-work (`sirloop runs` lists them) — reassignment is always manual, never automatic, and both refuse a record whose peer still answers
Usage: sirloop recover [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--reassign |
ID | — | Close a MIA delegated job by re-dispatching its goal to the peer named with --peer (new job id; the old record is ledgered as reassigned in jobs.jsonl) |
--peer |
PEER | — | Where --reassign lands the goal |
--orphan |
ID | — | Give up on a MIA delegated job: drop its record and ledger it |
sirloop runs
List every durable intent this node is holding in `pending/` — runs still in flight (same rows `sirloop swap` lists), plus any record that crashed into a corrupted, unparseable state (a torn write, or a reboot that zeroed a file's content while its length survived). `sweep` already ages the corrupt ones out on its own tick, but this is the only way to actually see them before that, and `--clear-stale` forces the same cleanup immediately, with no daemon required
Usage: sirloop runs [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--clear-stale |
— | false | Remove corrupt intent records old enough that no writer could still be touching them (same tolerance the heartbeat staleness check uses). Never touches a valid, resumable run — that stays `sirloop recover`'s job |
--deadlock |
— | false | Sweep the whole fleet for cross-node wait cycles: node A holding a lane on a run it dispatched to B while B's work queues behind A. Prints cycles and stuck lanes, ledgers each finding to jobs.jsonl, and exits 1 iff a cycle exists (warnings alone exit 0). Detection only — it never breaks a cycle |
sirloop ping
Round-trip a ping to a paired peer
Usage: sirloop ping [OPTIONS] <LABEL>
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | Required. |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop status
Ask a paired peer for its status — hostname, user, free disk, version, uptime. With no label: this node plus every paired peer, one line each (the fleet validation sweep); exit 1 if any peer failed to answer
Usage: sirloop status [OPTIONS] [LABEL]
| Option | Value | Default | Description |
|---|---|---|---|
label |
positional | — | — |
--addr |
ADDR | — | Override the stored address (host:port) |
sirloop bench
Benchmark artifacts: turn what this node recorded into what a leaderboard wants to read
Usage: sirloop bench [OPTIONS] <COMMAND>
sirloop bench swe
Run a SWE-bench-shaped dataset headlessly and write the predictions JSONL an evaluation harness eats
Usage: sirloop bench swe [OPTIONS] --dataset <DATASET> --out <OUT>
Run a SWE-bench-shaped dataset headlessly and write the predictions JSONL an evaluation harness eats.
Each instance is one orchestrated run in its own workspace-at-commit lane (`--repo`/`--at` from the dataset), delivering that run's own diff as `model_patch`. `model_name_or_path` is the model the receipt says actually bound — never the `--model` request.
Resumable: an instance already in the predictions or in `<out>.skipped.jsonl` is not re-run, and every settled instance is fsynced before the next starts. Tainted, patch-less and errored instances write NO prediction but ARE logged in the skip sidecar with the reason — a silent gap is how a benchmark gets mis-scored.
Local only: there is no `--scatter`, because a workspace-at-commit run is materialized on this node and cannot be routed to a peer that holds nothing to run in. Concurrency is this node's own lane cap.
| Option | Value | Default | Description |
|---|---|---|---|
--dataset |
DATASET | — | Dataset: JSONL, one instance per line, with at least instance_id, repo, base_commit and problem_statement (unknown fields are ignored; the gold `patch`/`test_patch` are never read) Required. |
--out |
OUT | — | Predictions file to write/append (JSONL). Its siblings `<out>.skipped.jsonl` and `<out>.meta.json` are written beside it Required. |
--model |
MODEL | — | Model requirement for every instance: provider/model | class:<name> | omniroute:<route> | a bare model id |
--limit |
LIMIT | — | Run at most N instances (after --instances filtering) |
--instances |
INSTANCES (repeatable) | — | Run only these instance ids (comma-separated, repeatable). An id the dataset does not have is an error, not a shorter benchmark |
--attempts |
ATTEMPTS | 1 | Attempt budget per instance |
--jobs |
JOBS | — | Run at most N instances at a time. Clamped to this node's lane cap (`sirloop lanes --slots`) — never above it |
sirloop bench export
Export a predictions file plus this node's own record into the swe-bench/experiments submission layout: `all_preds.jsonl`, `trajs/<instance>.md`, `logs/<instance>.log`, `metadata.yaml` and `README.md`
Usage: sirloop bench export [OPTIONS] --preds <PREDS> --dest <DEST>
Export a predictions file plus this node's own record into the swe-bench/experiments submission layout: `all_preds.jsonl`, `trajs/<instance>.md`, `logs/<instance>.log`, `metadata.yaml` and `README.md`.
Trajectories are assembled from receipts, the job ledger and transcripts, and every one says so in its own header: they are SUPERVISION-level (attempts, harness and routed model per attempt, driver swaps and their handoff briefs, gate outcomes, captured output), never the supervised CLI's own token stream — sirloop drives a separate process and does not intercept its reasoning.
Any instance whose receipt is stamped `tainted` (the no-test-peeking guard saw the run touch or grade itself on the benchmark's gold tests) is EXCLUDED from `all_preds.jsonl`, named on stderr. An instance with a prediction but no local receipt still exports, with a stub trajectory stating the gap — one hole never costs the run.
| Option | Value | Default | Description |
|---|---|---|---|
--preds |
PREDS | — | The predictions file (`sirloop bench swe`'s output, or any JSONL with an `instance_id` per row) Required. |
--dest |
DEST | — | Where to write the submission directory (created if absent) Required. |
--meta |
META | — | The run-metadata sidecar. Default: `<preds>.meta.json` beside the predictions file, if it is there |
--model-name |
MODEL_NAME | — | The submission's name in `metadata.yaml`/`README.md`. Wins over the sidecar — this is what makes the exporter usable standalone on a hand-built predictions file |
--tail-lines |
TAIL_LINES | 400 | Transcript lines each trajectory carries (`logs/` gets the whole thing regardless) |
sirloop doctor
Diagnose this node: state files parse, identity loads, relays answer, projects can run. One line per check; exit 1 if any failed. --relay additionally proves this node can ATTACH to its hosted relay (entitlement, not just reachability)
Usage: sirloop doctor [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--relay |
— | false | — |
sirloop proxy
Show or set the outbound proxy relay traffic tunnels through (HTTP CONNECT — the path git and curl use on corporate networks that allow no direct outbound TCP). The setting lives with the node in network.json, so doctor, the dashboard and the daemon all dial the same way; SIRLOOP_PROXY in the environment still outranks it for a one-off. `--set direct` pins "no proxy" even when the shell exports HTTPS_PROXY. `--test` dials every pinned relay through a candidate (or the current route) without saving it
Usage: sirloop proxy [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--set |
SET | — | host:port or host:port, or "direct" |
--clear |
— | false | Forget the setting — back to the environment |
--test |
TEST | — | Dial every pinned relay through this candidate (or, with no value, the route in effect) and report — nothing is saved |
sirloop introductions
Show or set whether this node accepts introductions (ADR 0018): the one pairing path with no ceremony at this keyboard — a peer this node already trusts hands it a one-time secret and it pairs with a third machine on its own, which is how a room self-meshes. `off` refuses inbound introductions in both roles (the refusal is ledgered naming the sender's pin, and the introducer sees that edge decline, never the pairing fail), restoring ADR 0017's "a compromised node cannot enroll new nodes" on this node. Default `on`. With no argument (or `show`), prints the current setting
Usage: sirloop introductions [OPTIONS] [on|off|show]
| Option | Value | Default | Description |
|---|---|---|---|
state |
positional | — | `on`, `off`, or `show` (the default) |
sirloop pause
Stop this node taking work, without killing it (ADR 0017 D7). `remote` refuses every inbound work verb from paired peers — run, shell, provision, update, browser, swap — each refusal ledgered naming the pause, while status, caps and results keep answering, so the fleet sees this node as *paused*, not *dead*; local runs, schedules and the recovery sweep continue. `all` additionally freezes new local starts and the queue pump — queued work stays queued and running sessions finish, because a pause never kills work. The latch lives in pause.json and survives a restart. With no argument (or `show`), prints the current state
Usage: sirloop pause [OPTIONS] [remote|all|show]
| Option | Value | Default | Description |
|---|---|---|---|
scope |
positional | — | `remote`, `all`, or `show` (the default) |
--hard |
— | false | Make the latch local-only: a paired peer's `resume` is refused too, and lifting it takes `sirloop resume --hard-clear` at this keyboard. Use when the machine must stay yours |
--drain |
DRAIN | — | Drain to a stop: with `all`, refuse new starts and let what is running settle, bounded by this many seconds (0 uses the default window). `sirloop pause show` reports when the node has drained and is safe to stop |
sirloop resume
Lift this node's pause and take work again. Also reachable over the wire from a paired peer — the one work verb a paused node still accepts, so pausing a node remotely is not a one-way door — unless the latch was set `--hard`, which lifts only here
Usage: sirloop resume [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--hard-clear |
— | false | Clear a `--hard` (local-only) latch too. Without it, a hard latch is left in force and the command says so |
sirloop schedule
Cron-style scheduled fleet runs: a saved goal, a five-field expression (or @hourly/@daily/@weekly/@monthly) saying when it fires, and a target — this node or a paired peer. `sirloop serve` fires them; every surface that manages a node (this CLI, the dashboard, the phone app) reads and edits the same rows. With no subcommand: list
Usage: sirloop schedule [OPTIONS] [COMMAND]
sirloop schedule add
Save a schedule. The expression is parsed and gated NOW — a spec that can never match a real date is refused here, never stored as a schedule that would silently never run
Usage: sirloop schedule add [OPTIONS] --id <ID> --spec <SPEC>
| Option | Value | Default | Description |
|---|---|---|---|
--id |
ID | — | Schedule id: [a-z0-9_-], 1..40 chars Required. |
--spec |
SPEC | — | When it fires: five fields "m h dom mon dow" or @hourly, @daily, @weekly, @monthly — in this machine's local time Required. |
--goal |
GOAL | — | What the fired run is asked to do (or --workflow) |
--workflow |
WORKFLOW | — | Fire a saved workflow instead of a literal goal: the REFERENCE is stored, so editing the workflow file changes future fires. It must exist and expand with --param values now, or the row is refused |
--param |
NAME=VALUE (repeatable) | — | name=value for a placeholder in --workflow's template (repeatable) |
--target |
TARGET | — | Fire at this paired peer instead of this node (its label) |
--project |
PROJECT | — | Named project on the target the goal runs in (None = its default) |
--model |
MODEL | — | Model (or routing requirement, e.g. class:frontier) the fired run is pinned to |
--grace-minutes |
GRACE_MINUTES | 60 | How late (minutes) a missed occurrence may be and still fire when the machine wakes |
--disabled |
— | false | Save it switched off — it never fires until `enable` |
sirloop schedule list
Every schedule on this node, with its next fire time and last outcome
Usage: sirloop schedule list [OPTIONS]
sirloop schedule enable
Switch one back on. Enabling is a fresh start: it does not fire for occurrences that passed while it was off
Usage: sirloop schedule enable [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop schedule disable
Switch one off. Its cursor stands still; nothing is deleted
Usage: sirloop schedule disable [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop schedule run-now
Fire one right now, ignoring its expression — a manual run through the same orchestrate path a foreground goal takes (so the exit code is the run's own verdict: 0 accepted, 1 rejected, 2 nothing ran). Does not move the cursor: a manual run never cancels the next occurrence
Usage: sirloop schedule run-now [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop schedule remove
Delete one schedule by id (its ledger lines stay)
Usage: sirloop schedule remove [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop schedule next
Show the next few fire times for an expression — or for a saved schedule's id — so a spec can be checked before it is trusted
Usage: sirloop schedule next [OPTIONS] <SPEC_OR_ID>
| Option | Value | Default | Description |
|---|---|---|---|
spec_or_id |
positional | — | An expression ("0 9 * * 1-5") or a saved schedule's id Required. |
sirloop schedule log
What happened to the schedules, in order: every fire and skip (the ledger) interleaved with every config change and who made it (the audit trail) — one schedule's when an id is given
Usage: sirloop schedule log [OPTIONS] [ID]
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | A saved schedule's id (all schedules when omitted) |
--lines |
LINES | 20 | How many of the newest lines to print |
sirloop github
The GitHub issue trigger: watched repositories whose labelled open issues become verify-gated runs here or at a paired peer, the verdict posted back as a comment. `sirloop serve` polls them (`gh` on PATH, or curl + SIRLOOP_GITHUB_TOKEN); the first poll baselines and fires nothing; an issue is dispatched once, ever. With no subcommand: list
Usage: sirloop github [OPTIONS] [COMMAND]
sirloop github add
Watch a repository. The first poll baselines and fires nothing (unless --backlog); after that a labelled issue updated later is dispatched once
Usage: sirloop github add [OPTIONS] <REPO>
| Option | Value | Default | Description |
|---|---|---|---|
repo |
positional | — | owner/name Required. |
--label |
LABEL | — | Only issues carrying this label are work (default: every open issue — think twice) |
--project |
PROJECT | — | Named project on the target the run lands in |
--target |
TARGET | — | Dispatch at this paired peer instead of this node (its label) |
--workflow |
WORKFLOW | — | Expand a saved workflow instead of the default goal; the template receives --param values plus the issue params it declares (repo, number, title, body, url) |
--param |
NAME=VALUE (repeatable) | — | name=value for a placeholder in --workflow's template (repeatable) |
--model |
MODEL | — | Model (or routing requirement, e.g. class:frontier) the run is pinned to |
--backlog |
— | false | Process the issues that are already open at the first poll |
--no-comment |
— | false | Do not post the pickup and the verdict back to the issue |
--max-in-flight |
MAX_IN_FLIGHT | 1 | At most this many unsettled runs per repository at once |
--disabled |
— | false | Save it switched off — nothing is polled until `enable` |
--no-board |
— | false | Do not open a board thread per dispatched issue (default: each dispatch opens one — `sirloop board`) |
--mirror |
MIRROR | qa | What the thread mirrors to the issue as comments: `qa` (the default — questions, answers and the verdict) or `all` (every agent post too: status, links, text) |
sirloop github list
Every watched repository with its poll state
Usage: sirloop github list [OPTIONS]
sirloop github enable
Switch one back on
Usage: sirloop github enable [OPTIONS] <REPO>
| Option | Value | Default | Description |
|---|---|---|---|
repo |
positional | — | Required. |
sirloop github disable
Switch one off (its state stays: nothing is re-dispatched later)
Usage: sirloop github disable [OPTIONS] <REPO>
| Option | Value | Default | Description |
|---|---|---|---|
repo |
positional | — | Required. |
sirloop github remove
Stop watching one repository (state and ledger lines stay)
Usage: sirloop github remove [OPTIONS] <REPO>
| Option | Value | Default | Description |
|---|---|---|---|
repo |
positional | — | Required. |
sirloop github status
The poll state and the recent ledger lines, for one repo or all
Usage: sirloop github status [OPTIONS] [REPO]
| Option | Value | Default | Description |
|---|---|---|---|
repo |
positional | — | — |
--lines |
LINES | 20 | How many ledger lines |
sirloop github poll
One poll now, from this console: dispatches via `orchestrate --detach` into this home. The daemon's tick is the same pass
Usage: sirloop github poll [OPTIONS]
sirloop github run-now
Dispatch one issue by hand, ignoring the baseline and whether it was handled before — foreground, through the same orchestrate path a goal takes (exit 0 accepted, 1 rejected, 2 nothing ran)
Usage: sirloop github run-now [OPTIONS] <REPO> <NUMBER>
| Option | Value | Default | Description |
|---|---|---|---|
repo |
positional | — | Required. |
number |
positional | — | Required. |
sirloop github reset
Forget one issue so the next poll may dispatch it again
Usage: sirloop github reset [OPTIONS] <REPO> <NUMBER>
| Option | Value | Default | Description |
|---|---|---|---|
repo |
positional | — | Required. |
number |
positional | — | Required. |
sirloop board
The board (ADR 0024): one thread per subject, the repositories it concerns, the agents on it and every post — progress, questions, verdicts, replies — in one place. A watched GitHub issue opens a thread per dispatch; a run on a thread posts with `board post` / `ask` / `link` (it knows its thread from SIRLOOP_BOARD); a person replies with `board reply`. With no subcommand: list
Usage: sirloop board [OPTIONS] [COMMAND]
sirloop board list
Every thread here, phpBB-style: repository › subject · state · posts · origin. `--all` sweeps the paired fleet (a dark home is listed from the replica cache, marked stale); `--peer` one peer
Usage: sirloop board list [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--all |
— | false | — |
--peer |
PEER | — | — |
sirloop board open
Open a thread by hand
Usage: sirloop board open [OPTIONS] <SUBJECT>
| Option | Value | Default | Description |
|---|---|---|---|
subject |
positional | — | The subject (one per thread) Required. |
--repo |
REPO (repeatable) | — | owner/name it concerns (repeatable; the first is where it files) |
sirloop board show
The thread: header, members, then the posts — newest first (the latest reply on top); `--oldest` reads it as a story. The summary is inline; a post's detail collapses to one line unless `--full`. `--peer` reads it from the peer that holds it (the replica cache when the peer is dark, marked stale)
Usage: sirloop board show [OPTIONS] [ID]
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Thread id or prefix; inside a run: defaults to its own thread |
--peer |
PEER | — | — |
--since |
SINCE | 0 | Only posts after this seq |
--lines |
LINES | 50 | At most this many posts (the newest) |
--oldest |
— | false | Oldest post first — the thread as a story |
--full |
— | false | Expand every post's detail inline |
sirloop board post
Post on the thread. Inside a run: as its member, on its thread. Outside: as a person, --thread required (a `text` post — see `reply` for an answer that resumes the agent). The text is what a person reads; --detail is the full technical record an agent resuming digests; --attach pins links to the post
Usage: sirloop board post [OPTIONS] <TEXT>
| Option | Value | Default | Description |
|---|---|---|---|
text |
positional | — | Required. |
--kind |
KIND | text | text | status | link (a run's kinds; a person posts text) |
--thread |
THREAD | — | — |
--detail |
DETAIL | — | The full technical record under the summary: commands, output, diffs — collapsed for a person, whole in a digest |
--attach |
ATTACH (repeatable) | — | A link to pin to the post (repeatable): a GitHub pull/commit/issue URL, any URL, or a run id |
sirloop board ask
Ask a person something and let the thread wait (a run's verb)
Usage: sirloop board ask [OPTIONS] <QUESTION>
| Option | Value | Default | Description |
|---|---|---|---|
question |
positional | — | Required. |
--detail |
DETAIL | — | The technical record under the question, for whoever resumes |
--attach |
ATTACH (repeatable) | — | A link to pin to the question (repeatable) |
sirloop board link
Link a PR or a commit (a run's verb)
Usage: sirloop board link [OPTIONS] <URL>
| Option | Value | Default | Description |
|---|---|---|---|
url |
positional | — | Required. |
--detail |
DETAIL | — | What the link is about, for whoever resumes |
sirloop board reply
Reply as a person: an `answer` — from WAITING, PARKED or REVIEW it asks the board to bring the agent back
Usage: sirloop board reply [OPTIONS] <ID> <TEXT>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
text |
positional | — | Required. |
--to |
TO | — | The post seq this answers |
--detail |
DETAIL | — | The technical record under the answer (rarely needed from a person; it is the agent-facing half) |
--attach |
ATTACH (repeatable) | — | A link to pin to the reply (repeatable) |
sirloop board dispatch
Put a harness on this thread and queue its first real run: binds the member and queues it in one step, for the daemon's board sweep to dispatch through the same gated path a watched issue takes — the project's own verify command decides the verdict, which settles back here. Free: it does not spend the thread's automatic resume budget. Serial per thread and fail-closed — a WAITING, CLOSED or LOCKED thread, a thread with a run already queued, or a framework already on the thread is refused by name, never overwritten
Usage: sirloop board dispatch [OPTIONS] --project <PROJECT> --framework <FRAMEWORK> --goal <GOAL> <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Thread id or prefix Required. |
--project |
PROJECT | — | The named project the run happens in (`sirloop project` lists them) Required. |
--framework |
FRAMEWORK | — | The harness that drives it: an installed framework (claude, codex, zcode, …) or `entry` for whatever the project is already configured with Required. |
--model |
MODEL | — | Model (or routing requirement, e.g. class:frontier) to pin |
--goal |
GOAL | — | What the member is asked to do. Kept on the member, so every later resume is briefed with the thread above *this* goal Required. |
--peer |
PEER | — | Not supported: a dispatch lands on the node whose board this is |
sirloop board resume
Bring a member back by hand (free — it does not spend the thread's automatic budget): queued for the daemon's board sweep, which dispatches it with the thread digest as its brief
Usage: sirloop board resume [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
--member |
MEMBER | — | Which member (default: the one that ran last) |
sirloop board close
Close a thread (running members are told to stop)
Usage: sirloop board close [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop board reopen
Reopen a closed thread (its resume budget resets)
Usage: sirloop board reopen [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop board lock
Lock a closed thread: read-only, for good
Usage: sirloop board lock [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop board log
The transition ledger, for one thread or all
Usage: sirloop board log [OPTIONS] [ID]
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | — |
--lines |
LINES | 20 | — |
sirloop lessons
Fleet lessons: per-project memory distilled from this node's settled receipts — never from a run's self-report, never by a model — and injected into every brief a driver is handed here (goal, handoff, `$SIRLOOP_LESSONS_FILE`). Every entry names the runs that prove it. With no subcommand: list. `docs/lessons.md` has the rules
Usage: sirloop lessons [OPTIONS] [COMMAND]
| Option | Value | Default | Description |
|---|---|---|---|
--project |
PROJECT | — | Only this project (`default` is the default entry) |
sirloop lessons distill
Re-derive the distilled lessons from the ledger now. This runs on every settle anyway; here it is for a ledger edited or imported by hand. Idempotent: human entries untouched, contradicted ones stale
Usage: sirloop lessons distill [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--project |
PROJECT | — | One project (`default` is the default entry); omit for --all |
--all |
— | false | Every landing point that has receipts |
sirloop lessons add
Write a lesson yourself. Pinned from the start: a distill never rewrites or retires what a human wrote
Usage: sirloop lessons add [OPTIONS] [TEXT]...
| Option | Value | Default | Description |
|---|---|---|---|
--project |
PROJECT | — | The project it belongs to (`default` is the default entry) |
text |
positional | — | The lesson, one line |
sirloop lessons mute
Stop injecting a lesson. Kept on disk with its evidence, marked muted; a distill never un-mutes it
Usage: sirloop lessons mute [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop lessons pin
Keep injecting a lesson whatever the ledger says next
Usage: sirloop lessons pin [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop lessons unpin
Back to the ledger's judgement (active now; stale if contradicted)
Usage: sirloop lessons unpin [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop lessons remove
Delete a lesson outright
Usage: sirloop lessons remove [OPTIONS] <ID>
| Option | Value | Default | Description |
|---|---|---|---|
id |
positional | — | Required. |
sirloop workflow
Saved workflows: a goal template plus harness/model/gate/project bindings and declared `{param}`s, kept as one JSON file — this node's under ~/.sirloop/workflows/, a project's under its .sirloop/workflows/ (which shadows). Runnable from here, from `orchestrate --workflow`, and from a schedule. With no subcommand: list
Usage: sirloop workflow [OPTIONS] [COMMAND]
sirloop workflow add
Save a workflow: from a JSON file, or from flags. Validated NOW — a template with an undeclared or unused placeholder is refused here, never stored to fail at run time
Usage: sirloop workflow add [OPTIONS] [FILE]
| Option | Value | Default | Description |
|---|---|---|---|
file |
positional | — | A workflow JSON file (its own `name` names it). Exclusive with the field flags below |
--name |
NAME | — | Workflow name: [a-z0-9][a-z0-9_-]{0,63} |
--goal |
GOAL | — | The goal template — `{name}` placeholders, `{{` for a literal brace |
--param |
NAME[=DEFAULT] (repeatable) | — | Declare a placeholder: `name` (required) or `name=default` (repeatable) |
--framework |
FRAMEWORK | — | Harness binding (a known framework name) |
--model |
MODEL | — | Model binding: provider/model | class:<name> | omniroute:<route> |
--verify |
VERIFY | — | Verify gate binding (applies where the run lands here) |
--project |
PROJECT | — | Named project the run lands on unless the dispatch names one |
--attempts |
ATTEMPTS | — | Attempt budget |
--deliver |
DELIVER | — | Deliverable kind: code | brainstorm | research | ops | generic | patch |
--into-project |
PROJECT | — | Save into this project's .sirloop/workflows/ (versioned with the repository) instead of this node's ~/.sirloop/workflows/ |
sirloop workflow list
Every workflow visible from here: the addressed project's (or the default entry's), then this node's own, shadowing marked
Usage: sirloop workflow list [OPTIONS]
| Option | Value | Default | Description |
|---|---|---|---|
--project |
PROJECT | — | Look in this project's .sirloop/workflows/ too |
sirloop workflow show
One workflow in full — the file, where it was found, its digest
Usage: sirloop workflow show [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
--project |
PROJECT | — | — |
sirloop workflow remove
Delete this node's copy (a project's file is edited in its repository)
Usage: sirloop workflow remove [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
sirloop workflow run
Expand and run one: rides the same orchestrate path a typed goal takes, so the exit code is the run's own verdict (0 accepted, 1 rejected, 2 nothing ran) and the receipt carries the stamp
Usage: sirloop workflow run [OPTIONS] <NAME>
| Option | Value | Default | Description |
|---|---|---|---|
name |
positional | — | Required. |
--param |
NAME=VALUE (repeatable) | — | name=value for a placeholder (repeatable) |
--target |
TARGET | — | Run it at this paired peer (its label) instead of here |
--project |
PROJECT | — | Named project to land on (wins over the workflow's own) |
--model |
MODEL | — | Model requirement (wins over the workflow's own) |
--attempts |
ATTEMPTS | — | Attempt budget (wins over the workflow's own; default 3) |
--detach |
— | false | Start the loop in a background process and return its run id |