Agent runtime setup
April 22, 2026 · View on GitHub
Lumina's agent is powered by opencode,
an open-source coding-agent server embedded into the Electron main process
as an in-process HTTP/WS endpoint. This document is everything a new
contributor or CI machine needs to run npm run dev successfully.
Why this setup is load-bearing
thirdparty/opencode is gitignored — the full opencode source tree
(~147 MB) plus its node_modules (~1.6 GB) never land in Lumina's repo.
The Electron main bundle imports a virtual:opencode-server module that
electron-vite resolves to
thirdparty/opencode/packages/opencode/dist/node/node.js — a 18 MB single
file produced by opencode's bun build-node.ts toolchain.
No bundle → npm run dev fails at the main-process build step with a
virtual:opencode-server resolver error.
One-time setup per machine
-
Install bun (required — opencode's build uses
Bun.build):curl -fsSL https://bun.sh/install | bash # macOS alternative: # brew install oven-sh/bun/bun -
Clone opencode into
thirdparty/:git clone https://github.com/anomalyco/opencode thirdparty/opencode -
Install opencode's workspace deps (runs a postinstall native-pty rebuild — ~1.6 GB on disk):
cd thirdparty/opencode && bun install -
Build the Node bundle (rerun whenever you bump opencode):
cd ~/Lumina-Note # back to repo root npm run opencode:bundleProduces
thirdparty/opencode/packages/opencode/dist/node/node.jsplus threetree-sitter-*.wasmsiblings.
After step 4, npm run dev boots normally.
Smoke-testing the bundle
npm run opencode:smoke
Boots the server with a random port + basic auth and hits /global/health.
Exits 0 on success. Useful for CI.
Behind the scenes
Build
scripts/bundle_opencode.mjsshells out tobun thirdparty/opencode/packages/opencode/script/build-node.tswithOPENCODE_CHANNEL=dev.electron.vite.config.tshas two plugins:lumina:virtual-opencode-server— resolves the virtual id to the built bundle; emits a setup guide as the error message if the bundle is missing.lumina:copy-opencode-assets— after Vite writesout/main, copies the.wasmsiblings intoout/main/chunks/.
Runtime (Electron main)
electron/main/agent-v2/server.tsimports{ Log, Server } from "virtual:opencode-server", setsOPENCODE_SERVER_USERNAME/OPENCODE_SERVER_PASSWORDenv vars, thenServer.listen({ port: 0, hostname: "127.0.0.1", cors: [...] }). Binds an ephemeral port and polls/global/healthuntil ready.window.lumina.opencode.getServerInfo()returns{ url, username, password }to the renderer.- The renderer calls
createOpencodeClient({ baseUrl, headers })from@opencode-ai/sdkand subscribes to/eventSSE for session / message / permission updates.
Native dependency
- opencode's
@lydell/node-ptyis aliased at build time toelectron/main/vendor/opencode-node-pty.ts, which loads the platform-specific package from opencode's bun workspace viacreateRequireat runtime. Works fornpm run dev; packaging (npm run dist) is not yet wired — see the open TODO in that file.
Upgrading opencode
(cd thirdparty/opencode && git pull && bun install)
npm run opencode:bundle
No changes to Lumina's source are usually needed. If opencode changes its
Server.listen() signature or @opencode-ai/sdk exports, update
electron/main/agent-v2/virtual-opencode-server.d.ts and the renderer
store respectively.
Customization via plugins
The agent can be extended without forking opencode. opencode's plugin
system exposes hooks (chat.params, permission.ask, tool,
experimental.chat.system.transform, etc.). Lumina-specific behavior
(vault context injection, custom tools, approval UX) will live under
electron/main/opencode-plugins/ once the plugin flow is wired — see
the P5 task in the migration memory.
Troubleshooting
Rollup failed to resolve import "virtual:opencode-server" — run
npm run opencode:bundle. If that itself fails, step 3 hasn't completed
successfully.
ConnectionRefused or ConnectionClosed during bun install —
network / proxy issue, not a code problem. In mainland China you likely
need HTTPS_PROXY=http://127.0.0.1:<port> set before bun install.
bun install pulls from cdn.npmmirror.com and URLs look mangled —
your repo has a stale package-lock.json or a global ~/.npmrc
pointing at a mirror that bun's newer versions can't parse. Use
bun install --registry=https://registry.npmjs.org or clear the lockfile.
electron/main/vendor/opencode-node-pty.ts throws at runtime —
thirdparty/opencode/node_modules/.bun/node_modules/@lydell/node-pty-*
is missing. Either step 3 didn't finish or you're running a packaged
build (not yet supported, see the TODO).