anomalyco / anomalyco/opencode

[FEATURE] Desktop: persist sidecar server URL/credentials to disk (XDG_STATE_HOME) so companion tools can auto-discover

Open
#47,206 0 comments 0 reactions 1 assignee View on GitHub

@Hona is already working on this.

Since Sep 4, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

The Desktop app's embedded server (sidecar) is only reachable by the app's own renderer. Companion tools running on the same machine (status-bar widgets, CLI wrappers, IDE extensions, automation scripts) cannot discover or authenticate to it, because the server URL/credentials are generated in memory and never persisted.

Currently the only working "API" for external tools is scraping main.log for the URL:

[info] server ready { url: 'http://127.0.0.1:62057' }

…but the log never contains the password, so discovery always ends in HTTP 401.

Current behavior (v1.18.26, macOS)
  • out/main/index.js: const password = randomUUID(); — a fresh password per launch, passed to the sidecar via postMessage, never written to disk.

  • out/main/sidecar.jsprepareSidecarEnv() unconditionally overwrites the environment:

    Object.assign(process.env, {
      OPENCODE_SERVER_USERNAME: "opencode",
      OPENCODE_SERVER_PASSWORD: password,   // always the IPC-provided value
      ...
    })
    

    so externally fixing the password (e.g. launchctl setenv OPENCODE_SERVER_PASSWORD ...) has no effect.

  • The password is only visible inside processes the server itself spawns (session tool processes). Tools outside that process tree cannot read it: ps -E shows the kernel-initial env, and the runtime-injected value is not there.

Result: every desktop restart rotates port + password, and each external tool has to implement a hack — e.g. running a "bridge" script inside an opencode session that dumps its own env to a well-known file — which only works after a session has started, and silently breaks again on the next restart.

Proposal

After server ready, persist the endpoint once, atomically, with 0600 perms, e.g.:

// $XDG_STATE_HOME/opencode/server.json  (sidecar already sets XDG_STATE_HOME)
{
  "url": "http://127.0.0.1:62057",
  "username": "opencode",
  "password": "<uuid>",
  "pid": 52431,
  "writtenAt": 1788490335685
}
  • Rewrite it on every (re)start; remove or invalidate it on clean shutdown.
  • Loopback-only listener + same-user-readable file puts it in the same trust domain as the existing env-var mechanism used by the CLI (OPENCODE_SERVER_PASSWORD), so no new attack surface.

(Alternative, also fine: let the desktop honor an externally provided OPENCODE_SERVER_PASSWORD instead of always generating one. Then tools can pin credentials via launchctl setenv and discover the port from main.log/lsof as they already do.)

Precedent inside the same codebase

The v2 CLI background-service path already treats credentials as externally retrievable:

const url = await run(binary, ["service", "start"], ...)
const password = await run(binary, ["service", "get", "password"], ...)

The desktop sidecar is currently the only server mode whose credentials are unreachable from outside the process tree.

Alternatives considered (and why they don't work today)
  1. A plugin that writes credentials on startup — natural place for it, but desktop plugin loading is broken/limited on 1.18.x (see #41033, #38604, #44367), so it can't be relied on.
  2. Scraping ps -E for OPENCODE_SERVER_PASSWORD — the value is injected at runtime, so it only appears in short-lived session tool processes; not a stable discovery channel.

Persisting the endpoint (or honoring an external password) would let the growing ecosystem of companion tools connect zero-touch, instead of every tool shipping its own rebridge hack.

Environment
  • OpenCode Desktop 1.18.26, macOS 15 (arm64)
  • Reproduction: start desktop → curl -u opencode:anything http://127.0.0.1:<sidecar-port>/global/health → 401, with no supported way to learn the real password from outside the app.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.