Repository navigation
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Context
We run opencode acp under an OS sandbox (sandbox-runtime:
Seatbelt on macOS, bubblewrap on Linux) so that the agent can write only inside one git worktree
and reach only its model. OpenCode works well this way on Linux. On macOS it only starts if the
sandbox is opened much wider than it should be, and the cause is one detail of how acp starts.
What happens
opencode acp spawns a second OpenCode process as its server and talks to it over HTTP on
127.0.0.1. The port is assigned by the OS, so it is different on every start. Three starts in a
row, unsandboxed, with lsof -nP -iTCP -sTCP:LISTEN:
opencode 127.0.0.1:59774
opencode 127.0.0.1:59783
opencode 127.0.0.1:59793
In the source this is packages/cli/src/services/standalone.ts, which runs the server with
--stdio --port 0. We found no flag on acp, no config key and no environment variable that
changes it. A server.port entry in opencode.json and an OPENCODE_PORT variable had no effect
on this listener.
Why it matters under a sandbox
-
Linux (bubblewrap): no problem. The sandbox has its own network namespace, so the listener
is private to the sandboxed process tree. -
macOS (Seatbelt): a sandboxed process may not bind a TCP port unless the sandbox allows it.
Without that,opencode acpexits before its first protocol message:Error: Standalone server exited before reporting readinessThe only setting sandbox-runtime has for this allows binding any local port and connecting to
localhoston any port. With it OpenCode runs, and so does a connect from the agent's shell
to any other service on the machine's loopback: a local database, a dev server, another agent's
listener. A per-port allowance is proposed there, but it needs the port in advance, and this one
cannot be known in advance. We raised that side as sandbox-runtime [bug] Interruption in GPT-4.1 prevents continuation #817.
So today the choice on macOS is "OpenCode does not start" or "OpenCode can reach everything on
localhost". For people who pick a local model because nothing should leave their control, the
second is the wrong default.
Request
Either of these would fix it. The first is the smaller change; the second is the better one.
- A way to set the internal server's port. For example
opencode acp --server-port <n>, or
an environment variable thatstandalone.tspasses through instead of0.opencode serve
already takes--port, so the plumbing exists. A supervisor can then pick a free port, allow
exactly that port in its sandbox policy, and tell OpenCode to use it. - No TCP listener for this hop. The two processes are parent and child, and the child is
already started with--stdio. Carrying the client's requests over the child's stdio, or over
a Unix socket in OpenCode's state directory, removes the port altogether.
If neither is wanted, a line in the ACP documentation would still help. It says ACP mode "doesn't
open a network port for ACP", which is true of the protocol side but not of this internal
listener, and it is the internal listener that a sandbox trips over.
How we would verify
- With option 1:
lsofshows the listener on the requested port, and under sandbox-runtime with
only that port allowed,opencode acpcompletesinitialize,session/newand a prompt turn
while a connect to a listener on a second loopback port is refused. - With option 2:
lsofshows no TCP listener for theacpprocess tree, and the same session
works under a sandbox that allows no local binding at all. - On Linux nothing changes.
We have a harness that runs exactly these checks on macOS and Linux and can test a build.
Environment
- OpenCode 2.2.6 (Homebrew on macOS arm64; the
opencode-linux-x64release build on Ubuntu 24.04) - macOS 27.2; sandbox-runtime 0.0.81
- ACP client:
agent-client-protocol5.1.0 (Rust), protocol version 1
Activity
opencodejr commentedon Nov 9, 2026
Thanks for the detailed write-up and the verification plan, @pauljsymonds.
To restate the request:
opencode acpstarts its internal server with an OS-assigned loopback port (serve --stdio --port 0inpackages/cli/src/services/standalone.ts). You'd like a way to pin that port, or better, to drop the TCP listener for this parent-to-child hop altogether (stdio or a Unix socket). Then a macOS Seatbelt sandbox can allow exactly that port, or no local binding at all, without opening all of localhost.I checked the code and it matches what you found. The port is hardcoded to
0, and neither theacpcommand,server.port/OPENCODE_PORTnor any other setting reaches it. A plugin can't work around this, because the child server is spawned before plugins load. You're also right that the ACP docs' "doesn't open a network port for ACP" line doesn't mention this internal listener.The maintainers will consider this. Related issues:
port/hostnamesettings (a different listener, not the ACP internal server)