Skip to content
Configuration

Configuration

Running ocman

./ocman                                      # default: listens on 127.0.0.1:8228
./ocman -addr localhost:9090                 # custom listen address
./ocman -db /path/to/opencode.db             # custom OpenCode database path
./ocman -platforms opencode,claude-code      # enable multiple platforms

Ocman’s own state (archived/seen flags, auth secret, favorites, cached projects) lives in ~/.local/share/ocman/state.db, auto-created on first run with automatic schema migration. Startup enforces owner-only permissions (0700 for the directory and 0600 for the database and SQLite sidecars) and fails rather than continuing if existing paths cannot be secured.

The HTTP server limits request-header read time and idle keep-alive connections. Browser responses deny framing and MIME sniffing and use a Content Security Policy. The policy intentionally permits inline styles, external/data/blob images, blob workers, and WebSocket connections because the current SPA, attachments, service worker, and terminal require them. Privileged localhost routes reject cross-origin browser requests. Origin-less local CLI and MCP clients remain supported, but when password auth is configured they must present a valid auth cookie like everyone else — a loopback peer address is not a credential behind a reverse proxy. Use -auth-trust-localhost to restore the unauthenticated local path. Browser access through a local reverse proxy requires password authentication and an OCMAN_PUBLIC_BASE_URL matching the external origin.

Every request is also checked against a Host allowlist before routing, which blocks DNS rebinding. Allowed hosts are loopback names (localhost, *.localhost, 127.0.0.1, ::1), bare IP literals, and the host of OCMAN_PUBLIC_BASE_URL. Anything else gets 421 Misdirected Request. If you reach ocman through a hostname (a tunnel, a Tailscale MagicDNS name, a reverse proxy), set OCMAN_PUBLIC_BASE_URL to that external origin.

Flags

FlagDefaultDescription
-addr127.0.0.1:8228Listen address.
-db~/.local/share/opencode/opencode.dbPath to OpenCode’s SQLite DB. Opened read-only.
-platformsopencodeComma-separated list of platforms to enable (opencode, claude-code).
-auth-password(unset)Password to require. Prefer OCMAN_AUTH_PASSWORD or -auth-password-file.
-auth-password-file(unset)Read auth password from file (trailing whitespace trimmed).
-auth-session-ttl720h (30 days)Auth cookie lifetime.
-auth-trust-localhostfalseExempt loopback clients from auth. Also OCMAN_AUTH_TRUST_LOCALHOST=1.
-opencode-server-password-file(unset)Read the managed OpenCode API password from a file (trailing whitespace trimmed).
-opencode-server-generate-passwordfalseGenerate an ephemeral managed OpenCode API password at startup.
-remote-listen(unset, off)Bind address for the remote-access gRPC server (multi-remote), e.g. 0.0.0.0:8230. Empty disables it.
-remote-tls-cert(unset)TLS certificate file for the remote-access gRPC server (enables TLS with -remote-tls-key).
-remote-tls-key(unset)TLS key file for the remote-access gRPC server.
-remote-trusted-overlayfalseExplicitly allow plaintext remote gRPC on a trusted overlay network.

Environment variables

VariableDescription
OCMAN_AUTH_PASSWORDAuth password. Empty string is treated as unset.
OCMAN_AUTH_TRUST_LOCALHOSTTruthy value enables the loopback auth bypass.
OPENCODE_SERVER_PASSWORDPassword for managed OpenCode servers and all ocman-to-OpenCode HTTP/SSE traffic.
OCMAN_ALLOWED_HOSTSVite dev/preview only: comma-separated extra hostnames allowed by the dev server (e.g. foo.tailnet.ts.net,bar.lan).

Authentication

By default ocman binds 127.0.0.1:8228 and serves unauthenticated. To require a password — for example when exposing over a tunnel, Tailscale, or any non-loopback listener — set one of the following (precedence in order listed):

  1. OCMAN_AUTH_PASSWORD env var (preferred)
  2. -auth-password-file /path/to/file
  3. -auth-password '<plaintext>' (visible in ps; use only for testing)

Once auth is configured it applies to every client, including localhost. For local dev loops, pass -auth-trust-localhost (or OCMAN_AUTH_TRUST_LOCALHOST=1) to restore the loopback bypass.

The password is bcrypt-hashed at startup. Auth cookies are HMAC-signed (stateless) with a key persisted in state.db so sessions survive restarts. Login attempts are rate-limited to 5/min per IP; trusted-localhost clients skip the limiter.

OpenCode: enabling interactive features

Sessions launched from ocman (command palette, Worktrees view, PR/Issue sidebar) are interactive out of the box: ocman manages one OpenCode instance per project on a port it allocates itself.

For OpenCode instances you start yourself, use an explicit port so ocman can discover them:

opencode --port 0   # let OpenCode pick a free port
# or pin a specific port, e.g. opencode --port 4096

Ocman discovers listening OpenCode processes via lsof and auto-connects. Without --port, externally launched sessions are still readable from the database but interactive features stay disabled.

OpenCode server authentication

OpenCode authentication is disabled by default, preserving compatibility with native instances started without authentication. To protect ocman-managed instances, configure one source in this precedence order:

  1. OPENCODE_SERVER_PASSWORD environment variable
  2. -opencode-server-password-file /path/to/file
  3. -opencode-server-generate-password

Ocman injects the selected password as OPENCODE_SERVER_PASSWORD when it launches OpenCode and uses OpenCode’s default opencode HTTP Basic Auth username for every API and SSE request. The password stays in backend memory and the managed process environment; it is not stored in state.db, returned to the browser, or included in runtime diagnostics.

To rotate a supplied password, update the environment variable or file and restart ocman, then restart each managed OpenCode instance from its session action (or let the next managed ensure replace an instance whose credential no longer matches). Generated passwords are intentionally ephemeral: every ocman restart creates a new value, and recovered managed instances are stopped and relaunched on first use. Unmanaged authenticated instances must use the same configured password; otherwise ocman reports an authentication failure rather than an unreachable instance.

Multi-remote support (optional)

Attach other ocman instances over the network and manage every machine’s sessions from one hub. On a machine you want to manage remotely, start its gRPC server:

ocman -remote-listen 0.0.0.0:8230 \
  -remote-tls-cert cert.pem -remote-tls-key key.pem   # secure default
ocman -remote-listen 0.0.0.0:8230 -remote-trusted-overlay # Tailscale/WireGuard only

Then attach it from the hub’s Settings → Remotes page using the remote’s address and access token. Off by default — a fresh install with no remotes is unchanged. See multi-remote for the full step-by-step guide, security notes, and troubleshooting.

OpenTelemetry (optional)

Pass --otel=<endpoint> (or set OTEL_EXPORTER_OTLP_ENDPOINT) to ship traces and metrics to an OTLP collector. Empty / unset disables telemetry with zero overhead.

The URL scheme selects the transport:

  • http(s)://... → OTLP/HTTP
  • grpc(s)://... or bare host:port → OTLP/gRPC

All other configuration uses standard OTEL_* env vars (OTEL_SERVICE_NAME, OTEL_RESOURCE_ATTRIBUTES, OTEL_TRACES_SAMPLER, OTEL_EXPORTER_OTLP_HEADERS, etc.).

For local dev, make otel-up starts a bundled Grafana LGTM stack on :3000 / :4317 / :4318. The make dev* targets automatically export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 and OTEL_SERVICE_NAME=ocman-dev. See observability/ for dashboard provisioning.