Skip to content

Background service is a per-user singleton: the first launch's env applies to every profile / config dir #58141

Open

Description

@jskswamy

Version / platform

opencode v2.0.32, macOS

Summary

OPENCODE_CONFIG_DIR and XDG_DATA_HOME give each profile its own config and data, and opencode service set env ... stores service settings per config dir (in service.json). But the background service is a single process on one fixed port (127.0.0.1:49374) shared by every config dir and data dir. Whichever launch starts it fixes the environment for all later launches. A later profile's env and service.json are never used.

This silently runs the wrong account: a profile that sets ANTHROPIC_API_KEY is ignored whenever another launch started the service first.

Steps to reproduce

opencode service stop
mkdir -p /tmp/ocA /tmp/ocB

# Profile A starts the service with an Anthropic key
OPENCODE_CONFIG_DIR=/tmp/ocA ANTHROPIC_API_KEY=keyA opencode auth list
# -> Anthropic  ANTHROPIC_API_KEY  environment

# Profile B: different config dir, only an OpenRouter key
OPENCODE_CONFIG_DIR=/tmp/ocB OPENROUTER_API_KEY=keyB opencode auth list
# -> Anthropic  ANTHROPIC_API_KEY  environment    <- A's env; no OpenRouter

OPENCODE_CONFIG_DIR=/tmp/ocA opencode service status   # http://127.0.0.1:49374
OPENCODE_CONFIG_DIR=/tmp/ocB opencode service status   # http://127.0.0.1:49374

The same happens with a different XDG_DATA_HOME per profile. lsof -iTCP -sTCP:LISTEN shows a single listener on 49374, and /tmp/ocB never gets a service.json.

Starting the profile first instead (so the service sees its env) works, which is why it looks intermittent:

opencode service stop
ANTHROPIC_API_KEY=dummy opencode auth list    # works

With --standalone each profile sees only its own env and config, so the data model works; it is the singleton that doesn't:

OPENCODE_CONFIG_DIR=/tmp/ocA ANTHROPIC_API_KEY=keyA opencode auth list --standalone   # Anthropic
OPENCODE_CONFIG_DIR=/tmp/ocB OPENROUTER_API_KEY=keyB opencode auth list --standalone  # OpenRouter

Expected

One of:

  • a service per config dir, or
  • the client sends its env / config dir and the server scopes to it, or
  • documented behavior ("one service per user, env is whatever the first launch had") plus a warning when a client's env or config dir differs from the running service's.

Impact

  • Per-profile credentials are silently ignored; the wrong account is used.
  • Wrappers that inject secrets or apply an OS sandbox per launch cannot isolate profiles, because the service lives outside the wrapper. They have to pass --standalone.
  • service set env is per config dir but only takes effect for the first launch, which is confusing.

Workaround

opencode --standalone (or run --standalone), or opencode service stop before switching profiles.

Activity

  1. opencode-agent commented on Oct 22, 2026

    @opencode-agent
    Contributor

    Thanks for the clear write-up and the reproduction steps.

    You're asking for each profile (OPENCODE_CONFIG_DIR / XDG_DATA_HOME) to be isolated when the background service is used. That could mean one service per config dir, a service that scopes requests to the client's config and env, or at least a warning when your env or config dir doesn't match the running service's.

    What you're seeing is how v2 currently works. The Background service docs describe one shared server per user account, and that server owns configuration, integrations and credentials. Its registration lives in the state dir and it listens on a fixed port, so a launch with a different config dir finds the running service and reuses it, including its env. The documented way to keep profiles separate today is --standalone, or opencode service set disabled true to make private servers the default.

    That said, credentials being ignored without any warning is a real problem, especially for wrappers that inject secrets on each launch. I've marked this as a feature request for maintainers to consider. A plugin can't do this, because the CLI chooses and starts the service before plugins load.

    Related issues:

  2. added 3 commits that reference this issue on Oct 23, 2026
    3392451
    ab283d9
    73e9a3f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions