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). Open source: the connector, pairing, frame codec and relay are on GitHub at github.com/witbitzchat/witbitz-code. A Python implementation is on PyPI:pipx install witbitz-code.
The Code section (Spaces → ☰ → Code) is a chat for OpenCode, 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.
No computer of your own? Use a cloud computer. Code → ☰ → Computers → New cloud computer makes one for the agent: a protected virtual machine (an AWS Nitro Enclave) only you can open — Witbitz cannot read its files, which are saved encrypted after every turn. It sleeps after 30 minutes unused and wakes when you open it, and the agent's keys stay outside it, added to each call by a separate protected machine. You choose what it may reach — nothing (the default), package registries and GitHub, or hosts you list — and its agent has a browser you can watch and take over from any device. With Private browsing on, that browser forgets cookies, logins and history every time the computer opens or closes. Cloud computers are part of the Plus plan; during early access they are open to invited accounts. The steps are in the Spaces guide, section "Cloud computers" (also in the app: Help).
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│
└──────────────────────────────────────┘- OpenCode stays on your computer, listening on
127.0.0.1only. Nothing on the network can reach it. - 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. - 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.
- 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, from your computer. That is OpenCode's own traffic, outside Witbitz. Pick a confidential model (below) and that request is provably handled inside attested hardware; any other model is an ordinary API call to its provider.
- 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, stop it,
undo or redo it, and compact the conversation; answer a permission prompt or a question the agent asks; read the model,
agent, command and skill catalogs, the agent's todo list, and which sessions are running; list folder names under your
home folder for a new session; save the files a turn carries and hand them back to your devices (below); show the files
a reply produced inside that session's folder; say which suggested tools are installed; keep the record of which
sessions you have seen; run Auto mode's checks; 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. That includes OpenCode's own route for
running a /command, which executes shell snippets from the typed arguments without asking: the Code page fills a
command's template in itself and sends it as an ordinary message instead.
You don't have to take this on trust. The allowlist is ALLOW in spaces/public/codeRelay.js in the
public repository, and the connector that enforces it is
tools/opencode-connector.mjs in the same place.
The page's egress lock 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.
With Hide my IP on (Settings), the app's own traffic goes through OHTTP, but the relay connection is a plain WebSocket that would see your device's IP address. The Code section therefore asks before it connects, and remembers a yes on that device while the setting stays on.
Set it up
You need a computer that stays on while you work (macOS, Linux, or Windows), and the Spaces app on your phone.
No keys to bring. Pairing the computer with your Spaces account gives that computer its own model keys —
TrustedRouter for the AI models (the · confidential ones included) and
Tinfoil for reading images and documents confidentially — capped by the providers (today up to
$50 of models and $5 of tools a month per computer, at most three computers per account). They are sent sealed to the
computer and never given to OpenCode: witbitz-code puts them on each call. Model calls go from your computer straight to
TrustedRouter and Tinfoil; Witbitz is not in the middle. Free to try: an account that is not invited gets the free
allowance — one computer, $1 of models and $0.25 of tools a month; invited accounts get the full caps above. At the cap the
provider stops, and Code says "This computer's Code allowance for the month is used up — it comes back on …" with a link
to your plan; an invitation later raises the caps in place, with no new pairing.
On Windows
Open PowerShell — Start menu → type PowerShell → Enter. Use a normal window, not Run as administrator: nothing here needs administrator rights, and the installer stops if it is run as one. Paste this line and press Enter:
irm https://app.witbitz.chat/code-vaulted.ps1 | iexThat is the line for the Spaces app at app.witbitz.chat. Each Spaces app has its own installer and its own Witbitz Code —
a computer installed for one app cannot be paired with another — and the app shows its own line in Code → Computers →
Add a computer (the regular app's is irm https://witbitz-spaces.pages.dev/code.ps1 | iex).
It asks nothing. It puts everything in one folder of yours, %LOCALAPPDATA%\Witbitz Vaulted (Witbitz for the regular app):
uv (which brings its own Python), OpenCode for Windows, witbitz-code from
PyPI, Git Bash (Git for Windows' portable build, only if Git is not installed)
and a Python for the agent's own scripts — each pinned to a version, and every download checked against the SHA-256
written in the script, so a file that does not match is never used. The script is short and readable at
app.witbitz.chat/code-vaulted.ps1. On Windows the agent works in Git Bash, with UTF-8 Python
and a note telling it how Windows paths work: measured on teacher-style tasks with Hebrew files, that is what took Windows
from 45 to 48 correct results out of 48.
When it is done, Witbitz Code starts in the background — no window to keep open — and its page opens in your browser. You can close PowerShell. Finish there (see The Witbitz Code page):
- Pair this computer — the page shows a QR code. On your phone, open Spaces → Settings → Privacy & security → Add a device and scan it.
- Tools — if the agent's tools for audio, video, PDFs and scans are missing (Poppler, Tesseract, Pandoc…), the page lists them with what it would run; Install them does it. Windows may ask once to allow an installer.
- Start when I log in — tick it to have Witbitz Code start in the background each time you sign in to Windows.
Start menu → Witbitz Code opens the page again. Quit at the bottom of the page stops Witbitz Code. To update, paste the same line again: it stops the running copy, updates it and opens the page. To remove it, see Removing it on Windows.
In WSL (Linux on Windows)
In your WSL terminal:
pipx install witbitz-code # or: uv tool install witbitz-code
witbitz-code setupSetup checks that OpenCode is installed (and offers to install it without sudo), then opens the same page in your
Windows browser and runs in the background — Windows holds WSL open with a hidden process, so you can close the
terminal. Pair, install the tools and tick Start when I log in on the page, as on Windows. The Start menu gets its own
entry, Witbitz Code (WSL witbitz-code setup --here does every step in the terminal instead.
Windows and WSL on one laptop can both run: they are two computers in your account — Laptop and Laptop (WSL) —
on their own ports (the second one takes 4097 when 4096 is in use). To update: pipx upgrade witbitz-code (or
uv tool upgrade witbitz-code), then witbitz-code setup once. To remove it: witbitz-code uninstall in WSL.
On a Mac or Linux
1. Install Node.js
Download the LTS installer from nodejs.org and run it (on a Mac you can also
use brew install node). witbitz-code needs Node.js 22 or newer.
2. Paste one line in Terminal
Open Terminal on that computer (on a Mac: press ⌘-Space, type Terminal, press Enter). Paste this line and press Enter:
curl -fsSL https://app.witbitz.chat/code-vaulted.sh | bash(The regular app's line is curl -fsSL https://witbitz-spaces.pages.dev/code.sh | bash.)
It checks that Node.js is there, downloads witbitz-code.mjs into your home folder, checks the file against the app's
asset manifest — the list of file hashes the signed build certificate commits to — and starts the setup.
A file that does not match is never used. The script is short and readable at
app.witbitz.chat/code-vaulted.sh. Paste the same line again later to update.
Pairing a computer from its own screen. A laptop's camera cannot scan a QR code on its own screen. In Add a
device, choose a picture of the code (a screenshot, or the image the setup saves) or paste the code — the setup
prints it after raw:. Only ever use a code from a computer in front of you: a code someone sends you would give them
your account.
The setup walks through four steps and skips whatever is already done, so it is safe to run again:
- OpenCode — if it is not installed, it offers to install it without
sudo: with npm where npm can install for you, otherwise with OpenCode's own installer (curl -fsSL https://opencode.ai/install | bash, into~/.opencode). - Pairing — a QR code appears. On your phone, open Spaces → Settings → Privacy & security → 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.
- Coding keys — the computer asks your account for its own keys, with the sign-in your phone just handed over. They
arrive sealed to the computer and are kept in
~/.witbitz/code/account-keys.json(readable only by you). Nothing to paste. A computer paired before this asks you to scan once more. - Keep it running — it offers to start
witbitz-codenow and whenever you log in: a systemd user service on Linux, a launch agent on macOS. Where that is not available (WSL without systemd), or if you say no, it runs in the terminal window — keep it open.
If an OpenCode you started yourself is already running, setup asks you to close it first: only an OpenCode that
witbitz-code starts can use your account's keys.
Several accounts on one computer pay for their own prompts: OpenCode names the conversation on every model call, the computer knows which account sent each prompt, and each call is billed to that account. A prompt typed straight into OpenCode on the computer is refused ("coding runs from the Spaces app"), and while one account's reply is being written another account cannot add to it. Accounts on one computer share its files and shell, so this splits the bill fairly; it is not a wall between them.
Open Code
On your phone: Spaces → ☰ → Code. Your sessions appear; open one, or start a new one, and type. A new computer starts on DeepSeek V4.1 Flash · confidential; the model chip changes it, and the choice is remembered per computer.
The Witbitz Code page
On Windows and in WSL, witbitz-code is managed from a page in your browser, served by witbitz-code itself on
127.0.0.1 and opened only through the Start-menu entry or witbitz-code ui (it carries a one-time key; other sites and
other users of the computer cannot use it). It shows:
- whether the computer is reachable from Code — Online, Connecting…, Stopped — with Start and Stop;
- Pair this computer, Pair again and Unpair, with the QR code on the page;
- Tools for audio, video, PDFs and scans — what is missing and an Install them button (a step that needs your
password, such as Linux's
apt, is shown for you to run in a terminal, never run from the page); - Start when I log in;
- Details — the last lines
witbitz-codeprinted, the first place to look when something is wrong; - Quit, which stops Witbitz Code (it has no window to close).
If witbitz-code is already serving in another window (an earlier setup, say), the page says Running in another
window and names the process; Run it here stops that copy and starts one under the page. On a Mac or Linux,
witbitz-code ui (Python package) opens the same page, but it runs only while its terminal stays open.
Other ways to get witbitz-code
Download it yourself and check the hash. The file ships inside the Spaces app build, so its hash is in the app's asset manifest:
curl -fsSLo witbitz-code.mjs https://app.witbitz.chat/downloads/witbitz-code.mjs
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
node witbitz-code.mjs setupBuild it from source. The file is built with a pinned esbuild from github.com/witbitzchat/witbitz-code:
git clone https://github.com/witbitzchat/witbitz-code && cd witbitz-code
npm ci && npm run build # → spaces/public/downloads/witbitz-code.mjs
shasum -a 256 spaces/public/downloads/witbitz-code.mjs # (Linux: sha256sum) — compare with the manifest line aboveIts hash matches the manifest when the repository and the live app are the same release — the repository's latest commit message names the release and its hash.
Python instead of Node? A second, independent implementation of the same protocol is on
PyPI — it is what Windows and WSL run: pipx install witbitz-code
(Python ≥ 3.10), then witbitz-code setup. It pairs with the same coding keys and enforces confidential models the same
way. On Windows and in WSL it runs in the background and is managed from the page; on a Mac or
Linux it runs in its terminal window, and it does not make text copies of attached documents yet.
Step by step, without setup
The same thing one command at a time, in the folder that holds witbitz-code.mjs (your home folder, if the line above
downloaded it):
npm install -g opencode-ai # or: curl -fsSL https://opencode.ai/install | bash
node witbitz-code.mjs pair --name "my laptop" # scan the QR code with the Spaces app — this brings the computer's keys
node witbitz-code.mjs serve # starts OpenCode on 127.0.0.1:4096, then the connector — leave it runningTo start it with the computer afterwards: node witbitz-code.mjs service install.
Everyday use
On Windows and in WSL, the page does all of this (Start menu → Witbitz Code). The commands
below are for the Node file on a Mac or Linux; the Python package takes the same commands as witbitz-code <command>.
| Commands | run them in your home folder, where the one-line install saved witbitz-code.mjs (a new Terminal window starts there) |
| 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's menu (☰) → Computers → the computer → 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 |
| Background service | node witbitz-code.mjs service status (it prints where the logs are); service uninstall stops it starting with the computer |
| Update | paste the install line again — it downloads the new file and runs setup, and the background service switches to it |
| Another port | node witbitz-code.mjs setup --port 4097 — for a second OpenCode, or when 4096 is someone else's; an existing pairing moves with one question, no new scan |
| Uninstall | node witbitz-code.mjs uninstall — see below |
Removing it on Windows
Settings → Apps → Installed apps → Witbitz Code → ⋯ → Uninstall. A window lists what it will remove and asks about
the rest — answer y to each to remove everything: it takes the computer out of your account (its coding keys are
cancelled and your devices stop showing it), stops Witbitz Code, deletes .witbitz\code, and asks whether to also
delete your project notes, all OpenCode sessions on the computer and OpenCode itself. Then it removes the Start-menu
and log-in entries, the Settings entry, the PATH line and the %LOCALAPPDATA%\Witbitz folder. OpenCode's own settings in
.config\opencode stay; delete that folder too to remove everything.
The same from PowerShell, with no questions:
powershell -ExecutionPolicy Bypass -File "$env:LOCALAPPDATA\Witbitz\uninstall.ps1" --yes --remove-keys --remove-notes --remove-sessions --remove-opencodeA computer installed from an Administrator PowerShell by a version before 1.6.6 may answer "Access is denied … pairings.json" — run that line from a Run as administrator PowerShell instead.
Removing witbitz-code on a Mac or Linux
node witbitz-code.mjs uninstallNo witbitz-code.mjs any more? The install line can fetch it and run uninstall instead of setup:
curl -fsSL https://app.witbitz.chat/code-vaulted.sh | bash -s uninstall (the regular app's: its own address).
It lists what it will remove and asks first: the background service, this computer from every account it is paired with
(its coding keys go back to the account first, and your devices stop showing it), ~/.witbitz/code (the pairing secrets, the files you attached in Code, the Auto-mode log),
the project-notes plugin if it is installed, and the downloaded witbitz-code.mjs itself. Then it asks — Enter keeps
each — whether to also remove:
- keys you saved yourself before coding keys came from the account: a Tinfoil key, and a TrustedRouter key in OpenCode's credentials;
- your project notes in
~/.local/share/witbitz-notes(they exist only where the notes plugin was installed); - all OpenCode sessions on this computer — every conversation, from Code and from the OpenCode app, since they share
one store (
~/.local/share/opencode). Your provider logins stay. If an OpenCode on this computer still has them open (a terminal running it, or the OpenCode app), it names it and offers to stop it first. - OpenCode itself. It says how OpenCode was installed and removes it that way: OpenCode's installer (
~/.opencode, plus the# opencodePATH line it added to your shell's startup file — the file is kept as<file>.before-witbitz-uninstall), npm (npm uninstall -g opencode-ai; if that needssudo, it tells you the command instead of running it), or Homebrew. Open a new terminal window afterwards.
Your projects always stay. If the computer is offline,
uninstall still removes everything here and tells you to remove the computer from your phone (Code's menu → Computers → the computer →
Remove) — that also cancels its coding keys, which is how you cut off a lost laptop. For scripts: uninstall --yes, plus --remove-keys, --remove-notes, --remove-sessions,
--remove-opencode for each of those.
In the Code section
- Type / in the message box for your OpenCode commands and skills, plus /undo, /redo and /compact. Undo takes back your last turn — and, in a git project, the file changes it made; Redo brings them back until you send a new message.
- When the agent asks you a question, or asks permission for a step, the card appears above the composer. A card you missed — asked while the app was closed, or on another device — comes back when you return.
- The agent's todo list shows as one line above the conversation; tap it to see every item.
- The bar shows the conversation's title and, under it, the folder it works in (
~for your home folder). - A spark next to a session in the list means it is running a turn right now, wherever it was started. A green dot means activity you have not seen yet (on ☰ too, while the list is closed). What you have seen is kept on your computer, so a conversation you read on your phone is not news on your laptop.
- Long conversations open on their newest messages; scroll up, or tap Load earlier messages, for the rest. Switching back to a conversation you opened before is instant.
- Write in Hebrew and the agent narrates and answers in Hebrew.
- Steer a running turn. While the agent works, the send button is a stop square; type (or dictate) and it turns back into the arrow, and what you send goes into the turn — the agent reads it at its next step, without stopping.
- The model menu has an Effort row, as in a room: Default or a level, for models that offer them. The chip shows it.
What the agent is doing
A reply's work — its commands, file reads and edits, and what it wrote between them — collapses into one line. While it runs, the line says what it is doing now and for how long ("✶ Running a command · 1m 12s"), or "Waiting for your approval" when a card is up; afterwards it sums up ("Ran 3 commands, created 5 files · 2m 35s"). Tap it for an outline: a line per group of steps, with the agent's note before each one; tap a step for its command, output or diff. The answer itself stays outside, in full, once the reply is done.
The agent works quietly. When something comes up that you should know before it finishes — a significant discovery, a change of direction, a limit it ran into, a decision where your view helps — it tells you in a short update that stands in the conversation, and its work carries on in a new line under it. A short task has none; a long one a few.
When the agent keeps a plan (its todo list), the plan stands above its work as a card — open while the turn runs, with the current item in bold and finished ones ticked, and folded to "Plan · 5 of 5" afterwards. The agent's own first sentence about how it will go about the task stands above the work line too, and while it thinks, the line shows the last thing it thought.
When the agent starts agents of its own (to explore a codebase in parallel, say), each one gets a card in the conversation, and the agents glyph at the top right lists them with a count. Tap one to read its own conversation, live; ‹ takes you back.
Modes: Manual · Accept edits · Plan · Auto
The chip beside the model sets how much the agent may do without asking (Shift+Tab in the message box steps through it):
- Manual — every permission the agent asks for is a card.
- Accept edits — file edits in the project go ahead; protected files (
.env, keys,.git/) and everything else still ask. - Plan — the agent plans without changing anything (shown when OpenCode has a plan agent).
- Auto — a check on your computer answers each ask first. Plainly harmless steps (reading files,
git status, edits inside the project) pass at once; the rest is judged by the conversation's own model, which allows routine work, refuses what must not run — telling the agent why, so it tries something safer — and leaves anything unclear to you as a card. Nothing is ever allowed "always". Each decision is a 🛡 line under the step that asked (a refusal in red), and all of them are logged in~/.witbitz/code/auto-log.jsonl. It keeps working with your phone closed.
Tools for the agent
The first time a computer connects, a card at the top of the session list names the tools it is missing that coding and
document work often needs — Git, ripgrep, jq, Python 3, uv, ffmpeg, Whisper, Poppler, qpdf, Tesseract, Pandoc and
ImageMagick — each with a line on why. Untick what you do not want, then Install with the agent: it opens a
Set up this computer conversation in your home folder in Manual mode, so every command asks. It never runs sudo: on
Linux, the packages that need admin rights are one line on the card for you to copy and run. Not now is remembered for
that computer; Settings → Tools checks again. The setup conversation tidies itself away once everything it was asked
for is installed.
witbitz-code serve also gives the agent tools of its own, on your computer:
- Media tools (
witbitz-media) — look at an image or a PDF page and zoom into part of it, measure, read text (OCR), compare two images, read QR codes and barcodes, read a file's metadata, find one image inside another, pull frames and scenes from a video or follow something through it, and transcribe audio to timestamped text with whisper.cpp — the audio never leaves the computer. A picture a tool makes reaches the model as a picture. Engines it lacks are fetched once, pinned by hash. - Web search (
web_search) — the same confidential search the Spaces assistant uses, answered inside a Tinfoil enclave, with numbered sources. It needs a Tinfoil key in the media tools' environment — a cloud computer's has one; on a laptop it is not wired to the account's key yet and says so. - A browser (
browser_open,browser_navigate,browser_snapshot, …) — a Chromium with its own profile (never your cookies or logins), opened only when the agent needs one. From the Code section on any paired device, Watch it, or Take over to drive it yourself while the agent waits. It needs Node.js 22 or newer. Turn it off withwitbitz-code serve --no-browser. On your own computer the agent runs as you, so Take over pauses the agent's browser tools but is not a security boundary the way it is on a cloud computer. Private browsing wipes the browser's cookies, logins and history every time it opens or closes: on a cloud computer chosen when you create it (or on its card), on your own computer with the switch on its card in Code orwitbitz-code serve --private-browser(witbitz-code 1.11 or later; 1.13 from the Windows installer or pipx). Without it, what you log into there stays, and the agent can use it afterwards — never type a password you use anywhere else. - ast-grep for search and rewrite by code structure rather than text, and OpenCode's lsp tool where a language server is set up — and the agent is asked to run the project's own checks before it calls the work done.
Files you attach
Tap + to attach a file (up to 5 MB each): a PDF, a Word or Excel file, an image, text. The way it reaches the agent is the way a coding agent on your own machine works — the file is saved on your computer and the agent reads it there:
witbitz-codesaves it under~/.witbitz/code/attachments/<session>/(readable only by you) and puts a note in your message saying where it is. Apart from an image (which a model that can see still gets directly), OpenCode never receives the raw file — it cannot take Word or Excel files at all.- For a PDF, Word or Excel file it also writes a text copy beside it, made by Tinfoil's attested document reader with the Tinfoil key your account gave this computer. The note tells the agent to read that copy. Without a key there is no copy; the agent reads what it can and asks before converting anything.
- The agent may read that session's folder without asking; any other folder outside your project still asks.
- Your message shows the file as a chip — a preview for a PDF or an image. Tap it: the download glyph saves it (on a phone, the share sheet — Save to Files, AirDrop…; on a computer, a plain download), and View text shows the copy the agent read.
Saved files are deleted with their session, or after 30 days unused. Limits: 25 MB per file, 200 MB per session, 2 GB in all. (The Python package saves files but makes no text copies yet.)
Files a reply produces
When a reply creates or changes a file — a PDF, a picture, a spreadsheet — it shows under the answer, without asking:
a PDF's first page, the picture, the first lines of a table or a text; a Word, Excel or PowerPoint file, an archive or a
recording as a chip. A screenshot the agent takes of its browser (ask it: "show me the page") shows the same way —
it is saved in Witbitz's own folder for that session (~/.witbitz/screens/), never in your project. Code files show nothing here (their changes are in the steps). Tap one to see it large, with the
download glyph and ✕ at the top.
- A card is a file the reply wrote with its file tools, or one its answer names — not files it only read, not scratch files it mentioned while working, and never a path from your own message. At most six per reply.
- Only files inside the conversation's folder, and never a name that looks like a secret (
.env, keys,.git/). Your computer refuses anything else before it touches the disk, sends at most 20 MB, and logs each file it hands out in~/.witbitz/code/output-log.jsonl— as a hash of the path, not the path. - A card says "changed since this reply" when the file was modified later, and "not on the computer any more" when it is gone.
Confidential models
The model menu includes models marked · confidential (DeepSeek V4.1 Flash — the default — GLM 5.3 Flash, GLM 5.3,
GPT-OSS 120B, Gemma 4 31B, Llama 3.3 70B). The mark is enforced on your computer, not asserted: OpenCode's
TrustedRouter calls go through witbitz-code on 127.0.0.1, and for these models it
- sends the request only after TrustedRouter's gateway proves (Google Confidential Space, Intel TDX) that it runs its
published code, and with TrustedRouter's hard floor
min_privacy: confidential— never routed to an ordinary endpoint; - checks TrustedRouter's signed receipt for that exact request and answer: which enclave served it and that the gateway verified that enclave. A receipt that does not verify ends the step with "not confidential: …" — no tool runs on it;
- reads images and documents a confidential model cannot see through Tinfoil's attested
enclave:
witbitz-codeverifies Tinfoil's AMD SEV-SNP evidence and pins the connection to the attested key before a byte is sent, then gives the model the text. This uses the Tinfoil key your account gave this computer (the account of the prompt it reads for).
Without a key, an image for a confidential model is not sent anywhere; the turn stops with a message saying so.
- asks once more when a proof lapses mid-answer. TrustedRouter renews its proof of each model's enclave every 15 minutes; an answer still being written when that proof expires gets a receipt that fails the time check. Only that failure is retried — a fresh request, checked from the start — and only when every other part of the receipt holds. Words already on your screen stay; from the new answer only its actions are used, so nothing appears twice. An answer that starts close to the end of a proof is held back until its receipt verifies, so a lapse there is retried unseen. A second lapse, or any other fault, still stops the step.
While a confidential model works, the working line says what it is doing even when nothing has reached the conversation yet: "Kimi K3 is reading the conversation" (a long conversation can take minutes before the first word), "Writing report.pdf · 12 KB" (a file being written is held back until its receipt verifies), "Checking TrustedRouter's receipt", or "TrustedRouter renewed its proof — asking again".
Each call is paid with the coding keys your account gave this computer, straight to TrustedRouter and Tinfoil; Witbitz is
not on this path. Other models pass through unchanged. Both versions of witbitz-code — the Node file and the Python
package that Windows and WSL run — enforce all of this the same way.
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 setup on it (it starts it, and offers to keep it running) |
| "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 | install on the computer — Set it up |
| the QR expires | the scan did not complete within 5 minutes | run pair again — nothing changed in the meantime |
| the QR in the terminal looks broken or will not scan | the terminal's font draws the half-block characters badly | WITBITZ_QR=large node witbitz-code.mjs setup draws it the old, larger way — or open the .svg file it names and scan that |
| "OpenCode is not installed" | opencode is not on PATH |
run setup — it offers to install it |
| "… (confidential) cannot read images or files, and this computer has no Tinfoil key" | a confidential model was sent a picture before the account's Tinfoil key arrived | wait a minute (serve asks for it again) or pick a model that can see |
| "On this computer, coding runs from the Spaces app" | a prompt was typed straight into OpenCode, or the conversation's account unpaired | send it from the Code section |
| "This computer must be paired again to use your Spaces account" | its coding keys were cancelled (Remove on a phone), or it was paired before account keys | run pair again |
| "… is not offered on Witbitz" | a model outside Witbitz's list was picked in OpenCode | pick one of the models the Code section lists |
| "another account on this computer is running this conversation" | a second account on the same computer tried to add to a reply the first one started | wait for that reply to finish |
| "This computer's Code allowance for the month is used up — it comes back on …" | the free allowance ($1 of models a month) is spent | wait for the 1st, or see your plan at getspaces.witbitz.chat/account |
| pairing says "the free Code allowance is for one computer …" | the free allowance covers one computer, and this account already has one | remove the other computer in Code first |
| "not confidential: TrustedRouter's receipt … did not verify" | the proof for that answer failed; it was not used, and no step it asked for ran | send again, and tell us if it repeats — a lapsed proof is retried by itself, so this is another fault |
| "… TrustedRouter renewed its proof of the model's enclave while this answer was on its way …" | a long answer outlived its proof twice, or its receipt had another fault too | send your message again — a fresh proof lasts 15 minutes |
| "… hasn't started answering after 60 s" | the model is queued or unavailable (the working line says so instead when a confidential model is just reading a long conversation) | wait, stop it, or pick another model |
| " |
the computer's connector predates a feature the page uses (tools, previews, the seen record) | update witbitz-code on that computer — see Set it up for its system |
| a reply made a file but shows no card under it | the file is outside the conversation's folder, or the computer runs an older witbitz-code |
move it into the folder, or update witbitz-code |
| "Code asks before connecting" with Hide my IP on | the relay would see this device's IP address | connect anyway on this device, or turn Hide my IP off |
| "That file is no longer on the computer" | its session was deleted, or it was unused for 30 days | attach it again |
| "To open saved files from here, update witbitz-code" | the computer runs an older witbitz-code |
update witbitz-code — see Set it up |
| no · confidential models in the menu | OpenCode was already running when serve started, or TrustedRouter is not connected |
close that OpenCode and run node witbitz-code.mjs setup — it connects TrustedRouter and starts OpenCode the right way |
| "Port 4096 is taken by a program that is not yours" during setup | something else listens there — on WSL, another Linux distro's OpenCode (distros share ports) | say yes to the free port it offers; the pairing moves with it, no new scan |
| "Already running on 127.0.0.1:4096: opencode …" during setup | an OpenCode you started yourself | let setup stop it — witbitz-code must start OpenCode itself for the confidential-model checks |
| "This computer is paired, but for OpenCode on another port" | the pairing points at a different OpenCode port than setup used | run setup with that port, or setup --port <n> and say yes to moving it |
| the page says Running in another window | another witbitz-code serves this computer (an earlier setup window, a log-in start) |
Run it here takes it over, Stop stops it |
| "Witbitz Code installs for your own account - it does not need administrator rights" | the Windows install line ran in an Administrator PowerShell | paste it in a normal PowerShell window |
| the Auto chip stays grey on Windows | that computer runs a witbitz-code older than 1.6.5 (Auto did not accept Windows or network-share folders) |
paste the Windows install line again |
| Witbitz Code (WSL …) in the Start menu opens nothing | witbitz-code in WSL is older than 1.6.3 |
pipx upgrade witbitz-code, then witbitz-code setup |
| "Background start is not available" during setup | WSL without systemd, or another system | in WSL, use the Python witbitz-code (it starts in the background there); otherwise keep the window open, or turn systemd on in WSL (/etc/wsl.conf: [boot] systemd=true, then wsl --shutdown) and run setup again |
Reference
- Source: github.com/witbitzchat/witbitz-code — the connector and
pairing (JavaScript and Python), the frame codec, and the relay itself (
relay/relay.mjs). Build the download from it and its hash matches the one in the app's asset manifest for the same release (see Other ways to get witbitz-code). Issues and questions go there too. - Wire format, key derivation, replay protection and the relay's limits:
docs/opencode-relay.mdin the same repository.
Machine-readable source: code.md · Generated 2026-10-27T07:05:42Z · build f301388c · every doc in one fetch: llms-full.txt (HTML)