Skip to content

Processes & servers

Run a server in one process and reach it from another over loopback.

Terminal window
$ cat > server.js <<'EOF'
require('http').createServer((req, res) => res.end('ok from another isolate'))
.listen(3000, () => console.log('listening on 3000'));
EOF
$ node server.js
listening on 3000
$ curl http://127.0.0.1:3000/
ok from another isolate

That curl crossed an isolate boundary. Each process runs in its own V8 isolate with a 128 MiB heap, so the platform’s memory cap is a per-process budget. The supervisor joins processes through its port registry. Start a server and it automatically becomes resident, with a keyed isolate and a registered port.

One-shot processes run, stream their writes back, and exit. Residents survive across requests and own ports. Attached TTYs are residents with an interactive tab (terminal & shell, alpha). The supervisor owns the process table, so ps stays accurate after a facet eviction. A process that cannot be restored is marked dead with a reason, so you never get a zombie. Logs are durable and bounded. Node supports child_process.spawn, exec, and execFile with piped stdio.

Listening ports open and focus preview tabs. The path uses real Request/Response objects and streams as data arrives. SSE ticks, chunked bodies, and curl output stay live; Ctrl+C cancels. Vite HMR measures 302 ms median end to end.

Outbound access is open. fetch, Node HTTP clients, npm, pip, gem, and git use it. WASI binaries get TCP through /dev/tcp/<host>/<port>. Inbound access is HTTP(S) through session routes. The platform has no raw public TCP inbound.

Loopback lets one app span cooperating isolates. The opencode server and TUI pair is alpha. fork() runs inside the installable bash program, whose facet carries a fork, exec, and waitpid scheduler. The default process model does not fork yet (the process fabric).