# Code — run OpenCode on your computer from the Spaces app > **Status: Beta.** The Code section ships in the Spaces app; your computer joins through a single-file download > (`witbitz-code.mjs`, Node ≥ 22). A `pipx install witbitz-code` package is built but **not yet published**. The **Code** section (Spaces → ☰ → **Code**) is a chat for [OpenCode](https://opencode.ai), the open-source coding agent — running on **your own computer**, against **your own code**, reached from any device you are signed in on: your phone on cellular, a tablet, another laptop. There is no server address to type, no port to open, no VPN to run. ## How it works ``` your phone (Spaces app → Code) your computer ┌─────────────────────────┐ ┌────────────────────────────────┐ │ the Code page │ │ opencode serve 127.0.0.1:4096│ │ seals every request │ │ ▲ local HTTP only │ └───────────┬─────────────┘ │ witbitz-code (the connector) │ │ wss — dials out │ opens and answers each request │ ▼ └───────────┬────────────────────┘ ┌──────────────────────────────────────┐ wss — dials out │ │ wss://code-relay.witbitz.chat │◂──────────────────────────────────┘ │ forwards sealed frames it cannot read│ └──────────────────────────────────────┘ ``` 1. **OpenCode stays on your computer**, listening on `127.0.0.1` only. Nothing on the network can reach it. 2. **The connector** (`witbitz-code serve`) runs beside it and makes one **outbound** WebSocket to the relay. It does for the Code page what a browser on the same machine would do — calls OpenCode's API and streams its events back. 3. **The Code page** opens its own outbound WebSocket to the same relay channel. Every frame in both directions is **encrypted end to end** (AES-256-GCM) with keys only your devices and your computer hold. 4. **The relay** — a Witbitz service — pairs the two sockets and forwards bytes it cannot read. ### The keys Pairing creates one random **32-byte secret** for this computer and your account. From it, both ends derive (HKDF-SHA-256) the relay channel name and two encryption keys, one per direction. The secret is stored in two places only: - on your computer, in `~/.witbitz/code/pairings.json` (readable only by you), and - in your account's **encrypted** index, which is how every signed-in device learns about the computer — the same end-to-end encrypted sync that carries your Spaces list. Witbitz stores it sealed and cannot read it. The OpenCode password (`OPENCODE_SERVER_PASSWORD`) never leaves the computer; the connector adds it locally. ### What Witbitz can and cannot see | | sees | cannot | |---|---|---| | **The relay** | a random channel name, IP addresses, when sockets connect, frame sizes and timing | read or alter any request, response or event; replay a frame | | **The account store** | that your encrypted index changed | read your computers, their names or secrets | | **Anyone who guesses nothing** | nothing | join a channel usefully — the name is 256 bits derived from the secret | Two honest limits: - **Your prompts and code go to the model you configure in OpenCode**, directly from your computer. That is OpenCode's own traffic, outside Witbitz — the Code section is not part of the [attested tier](./the-attested-tier.md). - The relay sees **metadata** (who is online, when, how much). It is the same class of metadata the rest of the platform sees; the content is the part that is sealed. ### What the connector will do Only what the Code page itself does: list, open, create, rename, archive and delete sessions, send a turn, answer a permission prompt, abort, read the model and agent catalogs, and follow the event stream. Any other OpenCode API call is refused **on your computer**, before it reaches OpenCode — OpenCode can run shell commands, so a leaked secret must not unlock more than the page can. The page's [egress lock](./verify.md) lists `wss://code-relay.witbitz.chat` — a Witbitz origin. Your computer's address never appears in the app, and no third-party host is added to the allowlist. ## Set it up You need a computer that stays on while you work (macOS, Linux, or Windows with WSL), and the Spaces app on your phone. ### 1. Install Node.js `witbitz-code` needs **Node.js 22 or newer**: (or `brew install node`, or your package manager). Check with `node --version`. ### 2. Install OpenCode and give it a model ```bash npm install -g opencode-ai # or: curl -fsSL https://opencode.ai/install | bash opencode auth login # choose a provider and paste its API key ``` See [opencode.ai/docs](https://opencode.ai/docs) for providers and models. Run `opencode` once in a project to check it answers. ### 3. Download `witbitz-code` ```bash curl -fsSLo witbitz-code.mjs https://app.witbitz.chat/downloads/witbitz-code.mjs node witbitz-code.mjs --help ``` **Verify it (optional).** The file ships inside the Spaces app build, so its hash is in the app's asset manifest — the same manifest the [signed build certificate](./verify.md) commits to: ```bash curl -s https://app.witbitz.chat/assets-manifest.json | python3 -c 'import json,sys; print(json.load(sys.stdin)["files"]["downloads/witbitz-code.mjs"])' shasum -a 256 witbitz-code.mjs # (Linux: sha256sum) — the two must match ``` ### 4. Pair the computer with your account ```bash node witbitz-code.mjs pair --name "my laptop" ``` A QR code appears. On your phone, open **Spaces → Settings → Back up & recovery → Add a device** and scan it. The QR carries no secret — your phone seals your account to a one-time key the computer just made. When it finishes: ``` opencode-pair: ✓ "my laptop" is in you@example.com's computers (1 paired) opencode-pair: ✓ paired "my laptop" with you@example.com ``` ### 5. Start it ```bash node witbitz-code.mjs serve ``` This starts OpenCode on `127.0.0.1:4096` if it is not already running, then the connector. Leave it running (a terminal tab, `tmux`, or a login service). ### 6. Open Code On your phone: **Spaces → ☰ → Code**. Your sessions appear; open one, or start a new one, and type. ## Everyday use | | | |---|---| | **See what is paired** | `node witbitz-code.mjs status` | | **Computer offline** | the Code page says *"my laptop is offline — start it"* and reconnects by itself when it returns | | **Several computers** | pair each one; a picker at the top of the Code list chooses which computer you are looking at | | **Remove a computer** | from the phone: Code → Settings → **Remove**; or on the computer: `node witbitz-code.mjs unpair` | | **New secret** | `node witbitz-code.mjs rotate`, then restart `serve` — devices pick up the new secret on their next sync | ### More than one account on one computer Each account pairs separately (run `pair` again and scan with the other account). **OpenCode has no users**: every account paired to the same OpenCode sees the same sessions, files and shell. That is fine for your own work and personal accounts. For **another person**, run a separate OpenCode — another port, ideally another operating-system user — and pair it on its own: `node witbitz-code.mjs pair --port 4097`, then `node witbitz-code.mjs serve --port 4097`. ## Troubleshooting | you see | means | do | |---|---|---| | *"… is offline — start it"* | the connector is not running (or the computer is asleep) | run `node witbitz-code.mjs serve` on it | | *"OpenCode is not answering at http://127.0.0.1:4096"* | the connector runs, OpenCode does not | start OpenCode, or let `serve` start it | | *"pair your computer"* | this account has no paired computer | step 4 | | the QR expires | the scan did not complete within 5 minutes | run `pair` again — nothing changed in the meantime | | *"OpenCode is not installed"* | `opencode` is not on `PATH` | step 2 | ## Reference - Wire format, key derivation, replay protection and the relay's limits: the design in the Witbitz repository, `docs/opencode-relay.md`. - The relay is open for inspection in the same repository: `relay/relay.mjs`.