@volter/supercode-teams
v0.2.177
Published
A machine daemon serving this machine's doors, and a local or remote Teams server for shared session discovery, OpenTelemetry ingestion and access to enrolled machines.
Readme
@volter/supercode-teams
Harness Teams, the harness's part of Volter Teams, has a server and machines. A machine daemon, one per OS user, serves this machine's
doors: panes, launch, files, ports, attention, titles, a signed describe, and harness.v1.
A Teams server retains a shared session catalog, membership and access rules, and routes
callers to enrolled machines. It runs as a Node process (server/index.mjs) or as a Cloudflare
Worker with one Durable Object (worker/); both host the same server/core.mjs. Existing OpenTelemetry pipelines can publish
evidence without installing Volter Harness on each developer's machine. Start with the
Teams guide; the design is
Teams server, CLI and API.
The server uses SQLite and requires Node 22.13 or newer. Package exports: . (the daemon,
channel and client), /machine, /client, /admission, /fleet, /server,
/workspace-client, /connector, /connector/native-continuation and /contracts. The
workspace client is browser-safe and takes explicit credentials. Native capture and execution use
the matching harness SDK and native core; source capabilities and fidelity remain explicit.
Fresh-session materialization supports Claude Code and Codex with requested value_lossless;
telemetry alone does not establish resumable native history.
See the public client declarations, contracts, and implementation specification.
The machine daemon
supercode teams machine start runs it with its local door only; supercode teams connect runs
the same daemon enrolled to the selected Teams context, adding catalog sync and the server link.
The daemon owns one supercode harness serve and the tmux terminal host.
Two doors reach it:
- Local: an owner-only Unix socket,
$SUPERCODE_HOME/teams/machine.sock(or, when that path is too long for a socket address, a per-user 0700 directory under/tmp). On Windows it is a named pipe,\\.\pipe\supercode-<hash>, which by default only its owner may open. Whoever can open it is this OS user, an operator. The local CLI, the agent inside the machine and a service on the same box (RH2's connector) use it. - Remote: the Teams server. The daemon holds one outbound WebSocket link; the server forwards a caller's channel over it after checking the caller's machine grants, and the daemon re-derives that admission from its own synced copy of the grants before every door.
The machine's custodian holds it as operator. Anyone else holds a machine grant:
operate (the whole machine: harness.v1 and launch), or view, observe, interact,
control, files, ports on named targets (pane:<key>, runtime:<id>, root:/path,
port:<pane>/<n>), or on every target of one kind (pane:*, port:*). * carries only
operate and view: a grant that reaches more names the kind it reaches, so it never covers
a kind another product serves on the same machine. title.set needs control on its target.
observe on a root:/path reads it (stat, list, read, search); files also changes it.
A workplace can open one pane or one folder for someone who is not a member of the team. A
server trusts only admin-consented app installations with
delegation.surfaces or delegation.sessions for that team. Register the exact issuer origin
on the app; install the needed module separately. Operator issuer allowlists grant no access.
Keys are cached separately per origin, and each token must match a
publication or session binding for that exact issuer. Staging never opens a production
binding or publication. Tokens use Ed25519 (keys at ORIGIN/.well-known/jwks.json, audience this server's
public origin), each naming a pane (pane:<key>) or a folder (root:/path) on one machine of one
team, and view or control. A token opens only a surface the machine's custodian published on
this server (the machine's publications, /machines/{id}/publications): the same team, machine and
exact target, published to that workplace and to the Room the token names, by the machine's current
custodian while still an active member of the team. A token naming no Room, or one for
anything else, for a wildcard (pane:*) or for the whole filesystem (root:/) opens nothing, and a
token must carry iat and live at most 15 minutes (exp - iat and exp - now). The hosted viewer
at /view#token=… opens it; the server turns the token into a machine grant on exactly that target
(a pane: observe, and control to type; a folder: observe to read, files to change) that
expires with the token, and closes the channel then. Before it writes that grant, and while the
channel is open every 15 seconds, the server asks the workplace whether the token still admits what it was issued for
(POST <issuer>/api/v3/delegated/status); when the workplace answers that it does not (the member's
binding revoked, their Task closed, their contract ended), the grant is deleted and the channel closes
with access_revoked, which the viewer shows rather than reconnecting; an open with such a token is
refused (403 access_revoked) and writes no grant. An unreachable workplace leaves the channel to
the token's expiry. A page embedding the viewer sends it a fresh
token by postMessage({ type: 'delegated-token', token }), which the viewer asks for with
delegated-token-needed.
teams publish records the surface on this server (only the machine's custodian can), then puts
the pane or folder of the connected machine (or --machine NAME) into a workplace Room as a
Surface, through the workplace's own door with a session token of yours; if the workplace refuses,
the record is withdrawn. teams unpublish SURFACE (the surface key or the publication id)
deletes this server's record first, on whichever of your machines holds it, which deletes the
grants minted on it and closes their channels at once, then retires it in the workplace. It fails
when this server holds no such record, unless --workplace-only; --record-only deletes the
record here without a workplace call or token. Removing a member likewise ends every delegated
grant on the surfaces they published. A surface published before this server kept records opens nothing until its custodian
records it with teams publish … --record-only (no workplace call, no workplace token):
supercode teams publish pane <ctx> --room room_… --workplace https://pilot.runhuman.com --organization acme --token-stdin
supercode teams publish root ./reports --room room_… --workplace https://pilot.runhuman.com --organization acme --token-stdinsupercode teams machine start # local door only
supercode open --new bash --detach # a pane; prints its contextKey
supercode open <ctx> # attach; ctrl-] detaches
supercode teams input <ctx> "make test"
supercode teams input <ctx> --key Escape # keys by tmux name: C-c, "Down Enter", …
supercode teams title set <ctx> "rate-limit rescue" # also names the owned tmux window
supercode teams suspend <ctx> # remote input refused; observe keeps streaming
supercode teams resume <ctx> --input "carry on" # the input that hands the pane back
supercode teams log verify # the hash chain across every rotation
supercode teams machines access grant laptop --to user:usr_… --caps observe,control --on pane:<ctx> --ttl 1h
supercode open <ctx> --on laptop # through the selected context's server
supercode discover --fleet # every reachable machine of the context
supercode open --new claude --on laptop # a pane on an enrolled machineProducts served behind the daemon
Another product serves its own kind of target on the machine (Volter Browsers:
browser-profile:<name>) through the daemon's product stream, opened with
{ target: '<kind>:<name>', ...params }. The product calls serveProduct from products.mjs,
which listens on loopback and writes a receipt, products/<name>.json, naming the kinds it
serves, its endpoint and a token. The daemon admits the caller first. Then it dials the newest
live receipt's endpoint and tells the product the principal, the capabilities held on that
target and the caller's params. Each side first proves it holds the receipt's token, the
product before it hears anything, and the token never crosses the wire. The daemon then
relays text messages both ways, each under the channel's frame limit. The product enforces what each
capability admits on its kind. A grant on * reaches a product's target only for view.
A remote caller is re-admitted every 15 s and when a grant it holds expires. The daemon decides from the grants it holds, then refreshes them from the server, at most once per interval. Wider capabilities are passed on; narrower ones close the stream. The server closes a member's channels when their membership is deactivated, or when a group they reached a machine through loses them or is deleted.
supercode teams browser <profile> --machine <name> serves a machine's browser profile as a
local CDP endpoint: chromium.connectOverCDP('<printed address>') drives it, each connection
riding its own product stream. The machine's own CDP address and Volter Browsers' publication token
never leave it. The endpoint answers any local process that reaches it, like a browser's own
debugging port.
A target whose kind has no live receipt is refused as not served on this machine. The
harness's own kinds (pane, runtime, root, port) are never served by a product.
Files (under $SUPERCODE_HOME/teams)
machine.key|pub (the host key; it signs describe and nothing else) · machine.sock ·
machine.json · launches.jsonl · log.jsonl (hash-chained, rotating to log.<ts>.jsonl) ·
attention.json · titles.json · suspended.json · limits.json · products/ (receipts of
products served behind the daemon) · workspaces/ (Teams contexts, credentials and connector
enrollments).
limits.json is read when the daemon starts: maxAttachmentsPerPrincipal (16),
protocolFloor (2), logRotateBytes (16 MiB), logKeep (8).
RH2 agent DMs
Share a session as its RH2 agent with supercode teams sessions bind REF --room ROOM --agent PRINCIPAL --rh2 ORIGIN.
Only the session custodian can grant this binding. The returned session can be passed to RH2’s room-member door;
no session-backed channel is created. The agent DM uses the exact resource ${ROOM}:dm:${PRINCIPAL}.
unbind accepts the same flags. --conversation remains available for existing grants; it is mutually exclusive
with --agent. Opening a DM reads the existing session; sending a turn is a separate action.
