bigred-sh
v0.1.0
Published
The big red button for your agent fleet. go / throttle / pause / stop, one URL, curl -f is the integration.
Maintainers
Readme
The one-liner
# agent side — the entire integration:
curl -fs https://bigred.legible.sh/ok/my-fleet || exit 1
# human side — the emergency stop:
curl -d "runaway refactor" https://bigred.legible.sh/my-fleet/stop/ok/{topic} answers 200 with go (or throttle rate=0.5) when running is allowed, and 409 with stop or pause when it is not. curl -f turns the 409 into a non-zero exit — and if the switch server is unreachable, curl fails too. The agent stops unless it can prove it's allowed to continue. That's the whole design.
The hosted API at bigred.legible.sh is in soft launch. To run the identical API yourself:
npx bigred-sh servestarts it onhttp://127.0.0.1:4181. Every example below works with that in place ofhttps://bigred.legible.sh.
Why
You kicked off six agents and went to dinner. One of them is now on hour three of a refactor nobody asked for, burning tokens at API prices. The feature-flag platforms solve this with an org, a project, an environment, an SDK key, and a sales call. You need the opposite: a switch that exists the moment you name it, that any process can check with one line of shell, and that you can slam from a phone browser.
bigred is that switch. Four states — go, throttle, pause, stop — one topic per fleet (or per agent, or per job; topics are free and created by first use). Opening /{topic} in a browser gives you a phone-sized page dominated by one giant red STOP button.
The whole API
| Route | What it does |
|---|---|
| GET /ok/{topic} | The fail-safe check: 200 + go or throttle rate=R when running is allowed; 409 + stop or pause when not |
| GET /{topic} | Browser: the big red button page. curl: state JSON |
| GET /{topic}/state?wait=30&since=R | State JSON {topic, state, rate?, reason?, since, rev}; with wait, long-polls until rev > R (or times out to current state) |
| POST /{topic}/stop | Flip to stop. Plain-text body (or ?reason=) = reason. Returns new state JSON |
| POST /{topic}/pause | Flip to pause (same semantics as stop: agents get 409) |
| POST /{topic}/go | Resume. Requires the token if the server has one |
| POST /{topic}/throttle?rate=0.5 | Advisory slow-down, rate 0.0–1.0 (default 0.5). Requires the token if the server has one |
| GET /{topic}/sse | SSE stream of transitions (named state events, JSON data, heartbeat comments every 25s) |
| GET /{topic}/log | Recent transitions, newest first, with timestamps and reasons |
| GET /README.md · /llms.txt | These docs, as text, for agents (GET / with Accept: text/markdown works too) |
Topics match [a-zA-Z0-9_-]{1,64} (ok is reserved — it's the check route). Errors are JSON {"error": "...", "code": "...", "hint": "..."} with correct status codes — hint spells out the correct next request. JSON bodies ({"reason": "...", "rate": 0.5}) work anywhere plain text does. Limits live in src/limits.mjs: 4 KB bodies, 200 log entries per topic, 60 s max long-poll, 10,000 topics.
The fail-safe asymmetry: stop and pause never require a token. If the server runs with --token, it is enforced only on go and throttle. A leaked topic name should at worst let a stranger stop your fleet — never restart it. Anyone can pull a fire alarm; resetting one takes the key.
Teach your agent
Paste this into your CLAUDE.md / AGENTS.md (swap in your topic and server):
## Kill switch (bigred)
Before each task, work unit, or expensive call, check the kill switch:
curl -fs https://bigred.legible.sh/ok/$TOPIC || exit 1
200 body "go" = proceed. 200 body "throttle rate=0.5" = proceed at that
fraction of normal pace (longer sleeps, smaller batches). Non-zero exit
(409 stop/pause, or server unreachable) = stop working NOW, finish nothing.
Watch for changes: curl "https://bigred.legible.sh/$TOPIC/state?wait=30&since=$REV"
(JSON: {state, rate?, reason?, since, rev})
Flip the switch: curl -d "why" https://bigred.legible.sh/$TOPIC/stop (or /pause)
Never POST /go or /throttle yourself — resuming is the human's call.Wrap what you can't instrument
Some processes won't ever check a URL — a runaway Claude Code session, a vendor script, a scraper you didn't write. bigred run is the moat for those:
bigred run my-fleet -- claude -p "migrate the database"It spawns the command, watches the topic (SSE, long-poll fallback), and translates transitions into signals:
- stop →
SIGTERMto the whole process tree,SIGKILLafter 5 s (--grace Nto change) - pause →
SIGSTOP(frozen mid-instruction, zero tokens burn while you think) - go →
SIGCONT - throttle → nothing; it's advisory, and a wrapped process can't be slowed by signal. It keeps running at full speed — documented, not pretended away.
If the topic is already stopped, or the switch server is unreachable, bigred run refuses to start the command at all. If the connection drops mid-run, the child keeps running and the watcher reconnects — a flaky network shouldn't kill your job; the pending stop lands on reconnect.
Self-hosting
npx bigred-sh serve # http://0.0.0.0:4181, in-memory
bigred serve --data-dir /var/lib/bigred # survive restarts (JSONL, replayed on boot)
bigred serve --token s3cret # lock go/throttle (stop/pause stay open)
bigred serve --port 4181 --host 0.0.0.0 --base-url https://red.example.comOr clone and run: git clone … && cd bigred && npm start. There is no build step, no config file, and zero dependencies — node:http and the standard library.
CLI
The CLI is a thin client over the same HTTP API — curl remains the contract. Base URL: --url flag, then $BIGRED_URL, then https://bigred.legible.sh.
bigred state my-fleet # current state (--json for machines)
bigred stop my-fleet --reason "enough" # flip it
bigred pause my-fleet
bigred go my-fleet # needs --token / $BIGRED_TOKEN if the server has one
bigred throttle my-fleet --rate 0.5
bigred watch my-fleet # stream transitions to stdout
bigred run my-fleet -- <command...> # the process wrapper (above)
bigred serve # run the serverRunnable walkthroughs live in examples/: loop-guard.sh (the curl -f pattern inside an agent loop), fleet-demo.sh (every endpoint), run-wrapper.sh (kill-switching an uninstrumented process).
Pro (planned for the hosted instance)
The core verbs are free forever, hosted and self-hosted alike. The hosted instance will charge for capacity and guarantees, never the verbs:
- Reserved topics — own
acme-prodwith per-topic tokens, instead of capability-by-obscurity - Fleet dashboard — every switch you operate on one page, one master button above them all
- Audit retention — transition history that outlives the 200-entry ring buffer, exportable
- Escalation policies — auto-stop a topic when a linked meter budget 429s
- Teams — shared ownership, per-member resume rights
See CONCEPT.md for the full reasoning.
Straight talk
- This is a cooperative stop for anything you don't wrap. An agent that never checks
/okwill never notice the switch. That's physics, not a bug — no HTTP service can kill a process it doesn't own. Put the check in the loop (one line), or usebigred run, which enforces with real signals. - Topic names are capability-by-obscurity. Anyone who learns the name can stop your fleet — by design, that direction is safe — and, without
--token, restart it too. If restart matters, set the token. Unguessable names (fleet-x7Kp2m…) are the zero-ceremony default, not real auth. - Throttle is advisory everywhere. Compliant loops slow down; wrapped processes don't. If you need hard budget enforcement, that's meter's job.
- In-memory by default. No
--data-dir, no memory: a restart resets every switch togo. Persistent deployments should always set--data-dir. SIGSTOPfreezes, it doesn't checkpoint. A paused process still holds its terminal, sockets, and locks; peers may time out on it. Pause is for minutes, not days.- No WebSocket. SSE + long-poll cover shells, browsers, and sandboxes with plain HTTP egress; WebSocket is omitted deliberately under the zero-dependency constraint.
License
MIT. © 2026 Myles Krecny.
bigred is one of the legible primitives — ntfy.sh-shaped tools for people who run agent fleets:
| | | |---|---| | gate (4180) | ntfy tells you things. gate asks you things. | | bigred (4181) | The big red button for your agent fleet. | | trail (4182) | The flight recorder for agent runs. | | slate (4183) | The blackboard from the multi-agent papers, as a URL. | | relay (4184) | The work queue your agents can provision themselves. | | mutex (4185) | flock(1) for agents that live on different machines. | | quorum (4186) | Coordination for agents that do not share a parent process. | | meter (4187) | The kill-brake for agent spend. 429-as-a-service. | | stash (4188) | ntfy moves signals. stash moves bytes. | | tally (4189) | StatHat reborn as ntfy. Three months too late — or right on time. |
