m64_7796c3cb05e5 / AGENT.md
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 /tokenits (empty) auth token;GET /wsthe WebSocket, subprotocoltty. ttyd's protocol: the client first sends a JSON text frame{"AuthToken":"","columns":C,"rows":R}; then binary frames, first byte the command: client0+bytes = input,1+JSON{"columns":C,"rows":R}= resize; server0+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 whoseOriginis 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-originis 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=<token>once (it becomes a cookie).