Hosted Andon: the board from anywhere
Andon is local-first and free to self-host forever — that stays the default and shares nothing. This guide is the optional, opt-in hosted mode: see your board (and get phone alerts) from anywhere, through a relay that routes ciphertext only and can’t read your agents’ content.
Deploying a relay for others to share? See deploy-relay.md.
What it is (in one minute)
Section titled “What it is (in one minute)”- Every status event is end-to-end encrypted on your machine before it leaves.
- A relay stores + forwards that ciphertext and never has the key — it sees only coarse routing (which board, a hashed session id, working/waiting/done/error/idle, timing).
- You open the same board as self-host; it decrypts in your browser with a key carried in the
link’s
#fragment(never sent to the server). The service worker decrypts phone pushes the same way. - No local
andon serveneeded — the hook’s normal post path also forwards a sealed copy.
There are two ways to use it:
| Who runs the relay | Who can use it | |
|---|---|---|
| A. Your own relay | you (andon relay on a box you control) | just you |
| B. A shared relay | an operator, at one public HTTPS URL | many people — each gets their own isolated board under the same URL |
Both are the same code; B is just A exposed publicly. See Multi-tenant.
Quick start
Section titled “Quick start”# 1) Run a relay (yours), or skip this and use a shared relay URL someone gives youandon relay # listens on :8788 (see deploy-relay.md for HTTPS/public use)
# 2) Opt in — generates a key that NEVER leaves your machine, prints your board linkandon hosted setup http://127.0.0.1:8788# → prints: http://127.0.0.1:8788/b/<board-id>#k=<key>
# 3) Open that link in a browser. Done — your agents now show up there.andon hosted setup first shows you exactly what the relay can and can’t see, and asks [y/N]
(default No). After it’s on, every Claude Code / Codex status also forwards (sealed) to the relay.
Treat the board link like a password — the #k=… part is your decryption key. Don’t screenshot it
into chat; save it in a password manager. (Or scan the QR shown in the terminal to pair without copy-pasting.)
Opening the board
Section titled “Opening the board”- On the same computer: open
http://127.0.0.1:<port>/b/<board-id>#k=<key>.localhost/127.0.0.1is a secure context, so in-browser decryption works over plain HTTP. - On your phone / another device: the relay must be reachable over HTTPS (browsers require a secure
context for decryption + push). Two easy paths:
- Tailscale (you already have it):
tailscale serve --bg <relay-port>→ gives you anhttps://<machine>.<tailnet>.ts.netaddress. Openhttps://…ts.net/b/<board-id>#k=<key>on the phone. - A real domain + cert (for a shared relay) — see deploy-relay.md.
- Tailscale (you already have it):
Phone alerts (PWA)
Section titled “Phone alerts (PWA)”- Open your board link on the phone over HTTPS.
- iPhone: Share → Add to Home Screen (iOS only allows Web Push from an installed PWA), then open it from the home screen. Android/Chrome: works from a normal tab; “Add to Home Screen” optional.
- Tap ENABLE ALERTS → allow notifications. You’ll get a buzz when an agent first needs you or gets stuck — even with the board closed and the phone locked. The notification text is decrypted on your phone; the relay never sees it.
Managing it
Section titled “Managing it”andon hosted status # is hosted on? which relay + board idandon hosted pair # re-print your board link — add a device, or recover a lost linkandon hosted off # stop forwarding — your agents go back to local-onlyandon verify <relay-url> # check the relay serves the exact open-source code (see below)Switching back and forth is free; off just deletes the local config (~/.andon/hosted.json).
What the relay can / can’t see
Section titled “What the relay can / can’t see”| ❌ Cannot read | your prompts, code, project names, titles, messages, leverage tallies |
| • Can see | that you’re active and roughly when (per-event timing), how many sessions, your IP, ciphertext size bucket |
| • Can do | delay/withhold an event, or re-show one of your real past push notifications (a stale “needs you” for an already-resolved session) — but it cannot invent new content, and cannot read it |
Self-host shares nothing and stays the default. Hosted is the convenience-vs-metadata tradeoff, stated plainly.
”Verifiable, not just trusted” (transparency)
Section titled “”Verifiable, not just trusted” (transparency)”Because a web board’s code is served by the relay, the airtight “even if breached, can’t read it” only holds for an installed app. For the web board, the honest claim is “we can’t secretly backdoor you”:
andon verify https://relay.example.comThis fetches the board + service worker the relay actually serves, hashes them, and compares to the bytes in
your own open-source copy. A match means the relay is serving the exact audited code — no hidden
key-stealing. A persistent mismatch at the same version means it’s serving modified code; don’t trust it
with your key. The relay also declares its hashes at GET /version.
Multi-tenant — one URL, many boards
Section titled “Multi-tenant — one URL, many boards”A relay is multi-tenant by design: one process serves many boards, and the entry point is a single URL, not a subdomain per user.
https://relay.example.com (one URL = the shared entry) ├── /b/<A's board-id>#k=<A's key> only A's key decrypts it ├── /b/<B's board-id>#k=<B's key> only B's key decrypts it └── /b/<C's board-id>#k=<C's key> only C's key decrypts it the relay holds only ciphertext for all of themEveryone runs andon hosted setup https://relay.example.com; each gets a 256-bit unguessable board id
under that one URL. Isolation is two-layer and tested:
- Nobody reads anybody: per-board key
K, relay stores ciphertext only (content-blind). - Nobody writes anybody: the board id is the read capability; writing needs that board’s own ingest token
(A’s token on B’s board →
401).
Upgrades (already-installed PWAs)
Section titled “Upgrades (already-installed PWAs)”Automatic — no app store, no re-pairing.
- The board HTML is served
no-storeand nothing caches it, so each launch loads the latest. - The service worker auto-updates (the browser re-checks
/sw.json relaunch/navigation/~24h; itskipWaiting()s so the new version takes over immediately). - Your key
Klives in the browser’s IndexedDB on your device (not the server) and survives updates → you stay paired. Just relaunch the PWA to get the latest.
(A new device still needs to be paired once — that device’s IndexedDB doesn’t have K yet.)
Troubleshooting
Section titled “Troubleshooting”- Lost your board link (the
#k=…)? It isn’t on the relay — the relay never had your key. It lives on the machine where you ranandon hosted setup: runandon hosted pairthere to re-print the full link (or read~/.andon/hosted.jsonand joinrelayUrl+/b/+boardId+#k=+key). A device that was never paired can’t recover the link from the relay — go back to that machine, get the link, and open it once on the new device. - “RE-PAIR — open your board link again on this device.” This device has no key (new device, cleared
storage, or a home-screen launch where the
#kwas stripped). Re-open your full board link (with#k=…) once; it re-caches the key. - Board loads but everything is blank / won’t decrypt. You likely opened a link without the
#k=…part (some tools truncate at#). Re-copy the whole link. - A stale card won’t go away. Cards clear when the agent posts
done/gone, or after a 6h TTL. A finished session normally resolves itself; a dead/test session lingers until the TTL. - No phone push. Push needs HTTPS (so the board over
127.0.0.1won’t push); on iPhone the board must be added to the home screen first; and you must tap ENABLE ALERTS and allow notifications. - Stop everything:
andon hosted off(stop forwarding) and, if you ran your own relay,lsof -ti tcp:<port> | xargs kill.