New Vercel project igneum-relay from relay/: one function (api/relay.mjs) over Neon tables relay_items and relay_machines, files in Vercel Blob store igneum-relay (50 MB client uploads, 4 MB through the function), phone-first web page at /r/<token>/ with the site tokens. Mac CLI tools/relay.mjs (feed, read, drop, task, run, watch, inbox, machines, role, name). Windows clients send.bat/send.ps1 and the igneum-agent (registers hostname, role, GPUs, WSL, nvcc; runs queued PowerShell scripts, posts results, reboot-continue via scheduled task + RunOnce), bash twins send.sh and agent.sh (verified live), playbooks for WSL setup, prover setup, prove-block, miner v4, one-click placeholder. make-clients.sh bakes the secrets into a zip; the repo copies hold placeholders. Screenshots under docs/design/relay. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
4.8 KiB
Igneum relay
Text, files and tasks between the project lead's devices without Gmail: the Mac, PC1, PC2 and the phone post to one feed and read from it. Vercel project igneum-relay, served at https://relay.igneum.network. Built 4 October 2026.
The secret is the path
The web page lives at /r/<token>/ and every API call sits under /r/<token>/api/<fn>. The token is 20 base32 characters generated once and stored at ~/.config/igneum/relay-token on the Mac (and as RELAY_TOKEN in the project). Anyone with the link can read and post, so the link stays with the project lead. Scripts may present the log intake key in x-igneum-key instead (RELAY_KEY, the same value as ~/.config/igneum/log-intake-key). There is no other login. Blob file URLs carry a random segment and a random suffix; they are not listed anywhere.
What is stored where
| Thing | Where | Limit |
|---|---|---|
| Items (text, title, who, kind, flags, read and done marks) | Neon table relay_items (database igneum) |
body 1 MB |
| Machines (name, hostname, role, GPU and WSL facts, last seen) | Neon table relay_machines |
|
| Files | Vercel Blob store igneum-relay (public URLs with random path and suffix, London) |
50 MB per file through a client token; 4 MB when pushed through the function |
| The token and key | ~/.config/igneum/relay-token, ~/.config/igneum/log-intake-key; project env |
never in the repo |
Kinds: text (a note), file, task (for a person or a Claude session on a PC), run (a script the agent executes), result (what a task produced, linked by task_id). Roles: miner, prover, bench, mac, phone.
API (all under /r/<token>/api/)
| Call | Does |
|---|---|
GET feed?since=&before=&machine=&limit= |
items newest first (200 by default) plus every machine with its unread count |
GET item?id= |
one item with its full body |
GET file?id=[&download=1] |
302 to the file |
| `GET inbox?machine=PC1&kind=run | task&ack=1` |
GET machines |
names, roles, hostnames, last seen |
POST drop |
JSON {from,to,kind,title,body,file_name,file_url,size,task_id,flags}; or raw bytes with Content-Type: application/octet-stream and x-file-name (4 MB cap) |
POST task |
same fields; kind task or run; run needs one named machine and flags {elevated, reboot_continue} |
POST upload |
{name,size} returns a one-hour Blob client token and put_url; PUT the bytes there, then drop with the returned url |
POST ack {ids} POST done {id,exit_code} POST delete {id} |
marks |
POST register {hostname,info} |
a machine checks in; returns its name, role and whether it is named |
POST name {hostname,name} POST role {name,role} |
naming and roles, from the Mac |
Mac
node tools/relay.mjs (feed), read <id>, drop "<text>"|<file>, task PC2 "title" [file], run PC2 "title" script.ps1 [--elevated] [--reboot-continue], watch, inbox PC1, machines, role PC2 prover, name DESKTOP-XYZ PC2, ack|done|rm <id>, url. Playbooks live in relay/playbooks/; run fills __DL_BASE__ in from ~/.config/igneum/dl-token.
PCs
relay/clients/make-clients.sh bakes the URL, key and token into copies of the clients and writes ~/Desktop/igneum-relay-clients.zip. Unzip anywhere on the PC. send.bat for people and Claude sessions (see CLAUDE-PC.md), igneum-agent.bat for the automatic runner: double-click once, leave it open. It registers the PC (hostname, GPUs, WSL, nvcc), polls every 20 s, runs each run task in order, posts a result (exit code, last 64 KB inline, full log as a file when longer) and marks it done. A script that prints RELAY-REBOOT triggers shutdown /r /t 10; with reboot_continue the agent re-arms (scheduled task at logon with highest privileges, RunOnce as a fallback) and re-runs the task after the restart with RELAY_PASS incremented. The PC must sign in by itself for that to be unattended.
An unknown hostname that registers appears in the feed with a "name this machine" box, or node tools/relay.mjs name <hostname> PC2. PC1 is DESKTOP-KMCV30N.
Deploy
cd relay && npx --yes vercel@latest --global-config ~/.config/igneum/vercel deploy --prod --yes --scope igneum
Env on the project: DATABASE_URL, RELAY_KEY, RELAY_TOKEN, BLOB_READ_WRITE_TOKEN (added by vercel blob create-store). DNS: relay CNAME cname.vercel-dns.com in the deSEC zone.
Untested until a PC runs it (4 Oct 2026)
send.ps1, igneum-agent.ps1 and the five PowerShell playbooks were written and syntax-reviewed on the Mac (no pwsh here). The bash twin agent.sh and send.sh ran end to end against the live relay. Expect a first-run fix on Windows: Start-Process -Wait exit codes through the wrapper, wsl --install --no-launch on pass 2, the RunOnce path after a reboot.