You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Keep the opencode sandbox alive past the end of run.mjs
run.mjs printed a preview URL and told you to open it in a browser, then
`await using` terminated the sandbox as the scope ended — the URL 404'd
before anyone could click it. Caught by running run.mjs for the first time.
It now creates the sandbox without `await using`, holds the process open,
and disposes on SIGINT, so the URL stays reachable until Ctrl-C.
idleTimeoutMinutes: 30 reaps a sandbox that gets forgotten.
Holding the loop open needs a ref'd handle: an unsettled top-level await
makes Node exit 13 with "Detected unsettled top-level await".
Dropping `await using` also drops the Node 24 requirement for this example;
run.mjs now parses on Node 22.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uz85xGA4zWSge1BtiDNnSN
setInterval(() => {}, 1<<30); // hold the event loop open; an unsettled await would exit 13
42
53
```
43
54
44
-
Open the printed `/app` URL in a browser and you are looking at OpenCode's own UI, driving a repo inside the microVM. The same URL serves the JSON API — `/session`, `/agent`, `/project/current` — so a script can drive it just as easily.
55
+
The script stays in the foreground so the URL keeps working. Open the printed `/app` URL in a browser and you are looking at OpenCode's own UI, driving a repo inside the microVM; the same URL serves the JSON API — `/session`, `/agent`, `/project/current` — so a script can drive it just as easily. Ctrl-C terminates the sandbox and the URL with it.
-**This example deliberately does not use `await using`.** It would terminate the sandbox at the end of the script's scope, and the URL it just printed would `404` before you could open it — the whole point here is a machine that outlives the script. So it disposes on `SIGINT` instead, and sets `idleTimeoutMinutes: 30` so a forgotten sandbox still reaps itself. Holding the process open needs a ref'd handle (`setInterval`); an unsettled top-level `await` makes Node exit 13 with `Detected unsettled top-level await`.
66
77
-**Set `OPENCODE_SERVER_PASSWORD`, always.** Without it the server logs `OPENCODE_SERVER_PASSWORD is not set; server is unsecured` and answers every caller — and `exposePort` has just put it on the public internet, so that is an open coding agent with a shell. With it set, unauthenticated requests get `401`. Auth is HTTP **Basic** (any username, that password); a `Bearer` token is rejected. `verify.mjs` asserts the `401` precisely so this cannot regress unnoticed.
67
78
-**Port 7681 is spoken for.** Tenki's own `ttyd` console listens there, and `exposePort(7681)` fails with `[invalid_argument] port 7681 cannot be exposed as a preview`. Pick any other port for your server.
68
79
-**`--hostname 0.0.0.0` is required.**`opencode serve` defaults to `127.0.0.1`, which the gateway cannot reach, so the preview URL would just hang.
0 commit comments