# opencode-tmux-dsflash-openrouter-gb10 opencode 1.18.23's own terminal UI, running in a tmux session inside the sandbox and served to the browser by ttyd 1.7.7 (xterm.js over a WebSocket). Model: DeepSeek V4.1 Flash on OpenRouter. No GPU. The container's only egress is `openrouter.ai:443`, through the m64 gate, which adds the OpenRouter key: the container never holds it. This capsule is for a human at a browser. It has no API kind: there is nothing for an agent to call besides status. An agent that wants to drive opencode programmatically should use `opencode-dsflash-openrouter-gb10` (sessions API + `opencode attach`); one that wants only the model should use `deepseek-flash-openrouter-gb10` (OpenAI chat completions). ## Ports and routes Main port (the capsule's URL): | Method | Path | What | | --- | --- | --- | | GET | `/status` | phase, and `app_url`: the terminal | | GET | `/agent` | this document plus live status (`?format=json`: with `app_url`) | | GET | `/human/` | landing page linking to the terminal | | GET | `/health` | 200 once ttyd answers | App port (`app_url`, the front's port + 1 unless `--app-port`): ttyd, raw. - `GET /` is ttyd's page; `GET /token` its (empty) auth token; `GET /ws` the WebSocket, subprotocol `tty`. ttyd's protocol: the client first sends a JSON text frame `{"AuthToken":"","columns":C,"rows":R}`; then binary frames, first byte the command: client `0`+bytes = input, `1`+JSON `{"columns":C,"rows":R}` = resize; server `0`+bytes = output, `1` = window title, `2` = preferences. - Every client attaches to the tmux session `opencode` (`tmux new-session -A`), so all tabs share one opencode, and it survives disconnects. If opencode is quit, the next client starts a new one. The workspace is `/scratch/work` (the run's scratch). ## Security - ttyd runs without its own auth and without `--check-origin`. The app front gives this port exactly the main front's protections: tailnet peers only, a Host allowlist (DNS rebinding), same-site/CSRF refusal, the token rule, and a 403 for any WebSocket upgrade whose `Origin` is present and not the app's own origin (tested: a foreign Origin, or the main port's origin, gets 403; a fake Host gets 400 on HTTP and 403 on the upgrade). - ttyd's own `--check-origin` is left off on purpose. The front forwards Host and Origin verbatim, so behind it ttyd's check would pass for a browser on the right origin, but it adds nothing the front does not already enforce, and it drops every upgrade that carries no Origin at all (non-browser clients such as scripts and tests). - On the tailnet (the default) there is no token: anyone on your tailnet can open the terminal, i.e. run any command opencode or a shell can run in this container, and spend the OpenRouter key. With a token, open `app_url?token=` once (it becomes a cookie).