The RAPP Brainstem, running 100% in your browser. Same engine, same UI, same guided tour ("The First Interview") as the on-device brainstem — real CPython via Pyodide, zero install, no admin rights. This is the zero-friction install: open the page and you are running a brainstem.
Live: https://kody-w.github.io/vbrainstem/
Doorman guide: https://kody-w.github.io/vbrainstem/guide.html — set up Claude as the sealed doorman to any machine's brainstem (WebRTC + kite tethers, kited twins, end-to-end AES-256-GCM).
index.html is the local brainstem UI (rapp_brainstem/index.html) copied
verbatim, plus one boot block injected after <title>. The boot block loads
vbrainstem-boot.js, which patches window.fetch so every same-origin brainstem
route (/chat, /health, /agents, /login, /models, ...) is dispatched to
brainstem_web.py — a faithful, route-for-route port of
rapp_brainstem/brainstem.py v0.6.16 — running in Pyodide inside a Web
Worker. The disk is Pyodide MEMFS persisted to IndexedDB (IDBFS), so agents,
soul.md and memories survive reloads.
Auth: GitHub device-code sign-in goes through the CORS proxy worker
https://rapp-auth.kwildfeuer.workers.dev (github.com sends no CORS headers).
After that, the Copilot token exchange (api.github.com/copilot_internal/v2/token)
and chat completions (api.individual.githubcopilot.com) go direct to
GitHub — both endpoints send Access-Control-Allow-Origin: * (empirically
verified). Tokens live in localStorage (vb_gh_token) and the worker's MEMFS;
they never touch any third-party server. brainstem_web.py honors env overrides
(GITHUB_TOKEN, COPILOT_TOKEN_URL, VB_AUTH_WORKER) seeded from the
localStorage key vb_env (a JSON object).
| File | Role |
|---|---|
index.html |
The local brainstem UI, verbatim, + the vBrainstem boot block |
vbrainstem-boot.js |
Page-side bridge: fetch interception, SSE bridging, window.rapp, Brainstem Studio (VS Code shell + Copilot Chat), deep links |
vbrainstem-worker.js |
Pyodide host Web Worker: boots Python, runs the micropip pre-pass, dispatches requests |
brainstem_web.py |
The brainstem itself — faithful port of rapp_brainstem/brainstem.py v0.6.16 |
local_storage.py |
Same storage shim as the local brainstem (.brainstem_data/ under MEMFS) |
agents/ |
Starter agents (basic_agent.py, memory agents); user agents land here too |
soul.md |
System prompt — knows it is in a browser and when to offer the tether |
VERSION |
Parity version (matches the local brainstem release it ports) |
rapp-guide.html |
The 14-step RAPP production guide, wired to the in-browser chat |
tether.ps1 / tether.sh |
One-command move to the on-device brainstem (see below) |
tools/autopilot/ |
Browser-driving test harness (see below) |
The route contract is identical to the local server:
| Route | Status |
|---|---|
POST /chat |
identical — agents, tool-calling loop, memory injection |
POST /chat/stream |
SSE, via the local server's own documented non-streaming fallback (whole-round deltas, "streamed": false) |
GET /health |
identical |
POST /login, /login/poll, GET /login/status, POST /login/switch, /login/retry |
identical shapes; device-code start/poll rides the rapp-auth worker |
GET /models, POST /models/set |
identical (including auto selection) |
GET /agents, POST /agents/import, GET /agents/export/<f>, DELETE /agents/<f> |
identical — drag-drop import, hot reload every request |
GET/POST /voice* |
identical |
GET /diagnostics, /diagnostics/book.json, POST /diagnostics/clear, /diagnostics/report, GET /version, GET /debug/auth |
identical |
GET /workspace/export |
browser-only addition — workspace zip for the tether |
Deliberate browser deltas, all minimal:
- Streaming — buffered XHR can't expose partial bodies without cross-origin
isolation, so
/chat/streamtakes the same non-streaming fallback path the local server documents, marking frames"streamed": false. The UI's streaming renderer, agent-log events and abort handling work unchanged. - Device-code auth — start/poll goes through the rapp-auth worker; everything after that is direct to GitHub.
- No
ghCLI link in the auth chain (no subprocess in the sandbox). - pip auto-install — served by an async micropip pre-pass in the worker
before each dispatch, instead of
pip installat agent import time. - No LAN mode / Host checks (a browser tab has no LAN surface).
Live: open the vBrainstem and click the 🩺 Brain Surgeon tab on the right edge.
Not a shell — the real GitHub Copilot agent loop (the same think→edit→test loop
VS Code's Agent mode runs), side-by-side with the brainstem chat. Describe an agent
and Copilot writes the single-file *_agent.py into this vBrainstem's workspace,
hot-loads it, and tests it live against /chat, iterating until it works — no
VS Code, no install. It runs on your signed-in GitHub Copilot account.
- Completions:
POST /surgeon/complete→brainstem_web.call_copilot()(real Copilot token, model, and fallbacks) returns the assistant message verbatim; the page drives the loop with tools (list_agents,read_file,write_agent,delete_agent,test_brainstem). - Tools operate on the LOCAL vBrainstem via
__vbrainstem.local()/.fs(), so the Surgeon always builds in this vBrainstem's own workspace. - Files:
surgeon.js(loop + side panel),brainstem_web.py(/surgeon/complete). This is how the Brain Surgeon builds agents without VS Code.
Give the in-browser vBrainstem (GitHub Copilot) the same on-device power the local brainstem + Copilot have — shell, files, Python on your real machine — with no brainstem, no VS Code, no pip, from one line:
# macOS / Linux
curl -fsSL https://kody-w.github.io/vbrainstem/burrow.sh | bash# Windows (PowerShell)
irm https://kody-w.github.io/vbrainstem/burrow.ps1 | iexIt installs a single stdlib-only Python daemon (burrow.py, ~250
lines) to ~/.rapp-burrow/ and runs it. The daemon is a loopback server that
hosts the sealed SPAKE2 pairing page and a
secret-gated /exec that runs shell / python / file ops on the machine. It
opens the pairing page; open it in the vBrainstem and type the 8-digit code
(human sign-off), then the Brain Surgeon's 🕳️ Burrow tools run on your real
computer. Chat stays in the browser (this host has no brainstem — chat:false);
only sealed host ops cross to the machine. Close the pairing tab or Ctrl-C the
daemon to end access. Apple-grade pairing: the 8-digit code is a true password via SPAKE2 (an
audited-primitive PAKE, P-256) — even an active man-in-the-middle on the
signaling broker can't learn the code or the session key, and can't brute-force
it offline. Devices pin each other's Ed25519 identity on first pair, so
re-pairing is code-free (like an iPhone ↔ Apple TV). Plus the same host gates:
loopback /exec, per-install secret, human sign-off.
Some RAPP agents can't run in the browser sandbox — they need the native OS
(subprocess to pac/az/gh, local files, native libs), e.g. the Power Apps
code-app agent. When you're burrowed, GitHub Copilot can run those agents on
your real machine: the burrow daemon exposes an agent op that runs an
unmodified BasicAgent subclass standalone (with a minimal BasicAgent +
utils.azure_file_storage shim), calls perform(**kwargs), and returns the
result. The Surgeon's run_device_agent tool (burrow-only) drives it — get
the agent's source with read_file (workspace) or run_python (fetch from RAR),
then run it on-device. So "run the Power Apps code-app agent on my machine"
works from the browser, on the real OS.
When you outgrow the sandbox — agents that shell out, raw sockets, local files,
CORS-hostile APIs — you don't start over. Ask the in-browser brainstem to
"download my workspace" (or hit GET /workspace/export); it saves
brainstem-workspace-YYYY-MM-DD.zip — your agents/*.py, soul.md and
.brainstem_data/ memories, no tokens — into Downloads. Then run one command:
Windows (PowerShell):
irm https://raw.githubusercontent.com/kody-w/vbrainstem/main/tether.ps1 | iexMac/Linux:
curl -fsSL https://raw.githubusercontent.com/kody-w/vbrainstem/main/tether.sh | bashIt installs the on-device brainstem, imports the freshest workspace zip from
Downloads, and opens localhost:7071 — every agent and memory carried over.
Credentials never leave the browser; you sign in fresh on the machine.
The header's Open in VS Code button opens Brainstem Studio: the VS Code shell built around Monaco (the same editor engine VS Code ships), over the live virtual workspace.
- Activity bar + Explorer — a file tree that reflects the on-device
rapp_brainstemlayout (agents/folder,soul.md, the engine files). Save an agent and it hot-loads on the next message — agents are re-discovered every request, no restart, exactly like editingagents/on disk. - Copilot Chat panel (right side) — a chat docked next to the editor, wired
to the brainstem's streaming
/chat. The human talks to the brainstem here while editing; the brain surgeon drives that same panel in the user's place viarapp.editor.send("…")— the browser twin of VS Code + GitHub Copilot Chat. It shares the same memory and agents as the main chat, and an agent the brainstem writes shows up in the Explorer immediately.
Full VS Code in the browser (code-server / vscode.dev) can't reach the in-page Pyodide brainstem, so the Studio wires the VS Code shell directly to it instead.
rapp-guide.html is the 14-step RAPP production methodology — the same guide
the AIBAST library ships — with every interview-loop prompt wired directly to
the in-browser chat. Click a prompt in the guide and the brainstem runs it.
tools/autopilot/ drives the page like a person: boots it in a real browser,
signs in, chats, imports agents, and asserts on what the UI shows.
- Mock-LLM mode (default, used in CI) — no token needed, deterministic.
--real— run the same script against the live Copilot API with your own token.--base http://localhost:7071— point the identical assertions at an on-device brainstem, side by side. If autopilot passes against both, parity holds.
It also verifies the structural invariant that index.html is the local UI
verbatim plus the boot block after <title>.
Do not hand-edit the UI here. When rapp_brainstem/index.html changes:
- Re-copy
rapp_brainstem/index.htmloverindex.htmlverbatim. - Re-add the vBrainstem boot block (the
<template id="vb-kite-mark">+<script src="./vbrainstem-boot.js">block, delimited by its banner comments) immediately after the<title>line.
That boot block is the only divergence from the local UI —
tools/autopilot verifies this property, and brainstem-ui-reference.html
holds the pristine local copy for diffing.
A browser tab can't open a port, but the same agent runtime can run headless. vbrainstem_sdk.py
is a single-file, stdlib-only server that loads the live RAR catalog and runs agents in real
CPython (full stdlib, real network + filesystem — so secret/network agents work), drivable like
brainstem.py:
python3 vbrainstem_sdk.py serve --port 7173 # HTTP API on a port
python3 vbrainstem_sdk.py run @aibast-agents-library/account_intelligence "360 for Acme"
python3 vbrainstem_sdk.py agents --grep fraud
python3 vbrainstem_sdk.py eval "import sys; print(sys.version)"HTTP (CORS-enabled — drive it from curl, the rapp-brainstem skill, an agent, or the browser):
GET /health → {status, agents, runtime}
GET /agents[?grep=] → {agents:[…]}
POST /run {"slug":"@pub/agent","request":"…","args":{}} → {executed, output|error}
POST /eval {"code":"…python…"} → {output}
Secrets: export OPENAI_API_KEY=… before serve — agents read them via os.environ.
Browser mirror (window.rapp). The live tab exposes the same shape on the JS console — no server, no port. Open DevTools and call:
rapp.health() // = GET /health
rapp.agents('fraud') // = GET /agents
await rapp.run('@aibast-agents-library/account_intelligence', 'Acme Corp') // = POST /run
await rapp.eval('import sys; print(sys.version)') // = POST /eval
// plus: rapp.summon(slug), rapp.secrets.list()/.unlock(pass)/.set(k,v), rapp.help()So vbrainstem_sdk.py (headless CPython) and the browser tab (Pyodide) are one API contract — identical request/response shapes, two runtimes.
https://kody-w.github.io/vbrainstem/?agent=@kody/registry_client_agent
Opens the brainstem with that agent summoned from the live
RAR registry
(https://raw.githubusercontent.com/kody-w/RAR/main/registry.json — RAR stays
the single source of truth; the registry panel reads it live).
share.html renders an agent shared as a link — the full source rides inside
the URL after #a=…, nothing server-side. Drag it into a vBrainstem to
install, scan the QR, or open it directly. #prompt= prefills also work; every
previously shared URL keeps working.
virtual-brainstem.html and virtual-brainstem-summon.html are the previous
generation (LisPy VM + transpiler engine) and remain available unchanged.
kited-demo.html and brainstem_bridge.html are likewise still served.
Canonical spec: kody-w/rapp-neighborhood-protocol (
rapp-neighborhood-protocol/1.0) — owns the vocabulary (vTwin · Kited · Tethered · the String · Kited Neighborhood · Neighbor · Scan-to-Join · Sealed · Doorman) and the kite mark. Companions: rapp-sealed (therapp-sealed/1.0codec) · kite-mark (the mark). This repo is the reference implementation; the inlined codec + mark are CI-checked against canonical (neighborhood-canon). Tools have their own repos too (working copies here are CI-synced viacanon-tools): rapp-doorman · rapp-brainstem-sdk · rapp-kite. Full ecosystem map → rapp-map.
Two brainstems — a local brainstem.py, a vBrainstem tab, a person, or Claude — meet as
uniform peers speaking rapp-twin-chat/1.0; nobody can tell what's on the other end. A
tether is the live link between them. There are two §5a transports:
- WebRTC tether (
5a-tether) — direct P2P between two browser peers. The PeerJS public broker is used for the handshake only (SDP/ICE); data flows DTLS-encrypted P2P and the broker never sees it.index.htmlexposesrapp.neighborhood.host()/join()/ask()/operate(). - Kite tether (
5a-kite) — an operator (Claude) holds the string: drives a browser tab's console over the Chrome DevTools Protocol and relays. No broker, no STUN, no CORS — the string-holder is the transport. For "thing-in-the-middle", or when P2P can't form.
A kited twin is a tab flown on a kite string. It is tethered when the string also
reaches the locally-running brainstem (5a-kite+tether) — its turns are answered by that
local brainstem; with no local brainstem it is just kited (answered by the tab's own
in-page brainstem). CDP is unauthenticated, so the kite/CDP hop must stay on-device —
across machines, ride the WebRTC tether instead.
Any envelope can be sealed: rapp-sealed/1.0 = AES-256-GCM, key derived (PBKDF2-SHA256,
210k) from a secret that travels only in the pairing link you copy out-of-band — never to
the broker. The wire / broker / TURN see opaque ciphertext, can't forge or modify it (GCM auth
tag), and only the two secret-holders can read or speak. Layered over WebRTC's DTLS, the whole
network is fully untrusted and still safe. Secrets at rest use the same primitive (the
vault). A wrong-key peer can't even read the rejection. The same scheme/salt runs in the
browser, the bridge, the CLI, and Node — so every hop is one contract.
You open the tab → it host()s → mints a peer-id + token (the token doubles as the channel
secret). Share the operator link with yourself out-of-band (another browser, same account).
Closing the tab destroys the peer + secret → the session ends, exactly like stopping
brainstem.py. Plaintext chat (say) is open; operating the console (run/eval/chat/…)
goes over the sealed channel, where key-possession is the authorization.
| Tool | Role |
|---|---|
index.html → window.rapp.neighborhood |
host / join / ask(peer,text,secret) / operate(peer,method,args,secret); _seal/_open exposed |
brainstem_bridge.html |
front a local brainstem into the neighborhood (sealed) so a remote browser can drive this machine's brainstem |
vbridge.sh <peer> <token> <ask|eval|run|chat|agents|health> … |
CLI peer — operate a hosted tab from a shell, sealed |
kited_twin.js --port <cdp> [--brainstem <url>] [--once] |
the kite string — fly a tab via CDP; --brainstem makes it tethered |
doorman.skill.md |
feed its raw URL to a fresh Claude on another machine → it sets up and guards a sealed door to that machine's brainstem (Claude as the "doorman") |
doorman_selftest.sh |
one command that proves a machine can be a sealed doorman (hosts the bridge, drives it from a separate sealed peer, asserts the real brainstem answered) |
These working copies must stay byte-identical to their canonical repos — the
canon-tools workflow fails CI on any drift. Sync them from upstream; never
edit them here:
| Working copy | Canonical source |
|---|---|
doorman.skill.md |
kody-w/rapp-doorman |
doorman_selftest.sh |
kody-w/rapp-doorman |
vbrainstem_sdk.py |
kody-w/rapp-brainstem-sdk |
vbridge.sh |
kody-w/rapp-kite |
kited_twin.js |
kody-w/rapp-kite |
kite_vtwin.js |
kody-w/rapp-kite |
claude_bridge.js |
kody-w/rapp-kite |
MIT © Kody Wildfeuer. Brainstem engine ported from rapp_brainstem; agent registry from kody-w/RAR.