Host orchestrator for opencode + OpenWork server + opencode-router. This is a CLI-first way to run host mode without the desktop UI.
Published on npm as openwork-orchestrator and installs the openwork command.
npm install -g openwork-orchestrator
openwork start --workspace /path/to/workspace --approval autoWhen run in a TTY, openwork shows an interactive status dashboard with service health, ports, and
connection details. Use openwork serve or --no-tui for log-only mode.
openwork serve --workspace /path/to/workspaceopenwork ships as a compiled binary, so Bun is not required at runtime.
If npm skips the optional platform package, postinstall falls back to downloading the matching
binary from the openwork-orchestrator-v<version> GitHub release. Override the download host with
OPENWORK_ORCHESTRATOR_DOWNLOAD_BASE_URL when you need to use a mirror.
openwork downloads and caches the openwork-server, opencode-router, and opencode sidecars on
first run using a SHA-256 manifest. Use --sidecar-dir or OPENWORK_SIDECAR_DIR to control the
cache location, and --sidecar-base-url / --sidecar-manifest to point at a custom host.
Use --sidecar-source to control where openwork-server and opencode-router are resolved
(auto | bundled | downloaded | external), and --opencode-source to control
opencode resolution. Set OPENWORK_SIDECAR_SOURCE / OPENWORK_OPENCODE_SOURCE to
apply the same policies via env vars.
By default the manifest is fetched from
https://github.com/different-ai/openwork/releases/download/openwork-orchestrator-v<version>/openwork-orchestrator-sidecars.json.
OpenCode Router is optional. If it exits, openwork continues running unless you pass
--opencode-router-required or set OPENWORK_OPENCODE_ROUTER_REQUIRED=1.
For development overrides only, set OPENWORK_ALLOW_EXTERNAL=1 or pass --allow-external to use
locally installed openwork-server or opencode-router binaries.
Add --verbose (or OPENWORK_VERBOSE=1) to print extra diagnostics about resolved binaries.
OpenCode hot reload is enabled by default when launched via openwork.
Tune it with:
--opencode-hot-reload/--no-opencode-hot-reload--opencode-hot-reload-debounce-ms <ms>--opencode-hot-reload-cooldown-ms <ms>
Equivalent env vars:
OPENWORK_OPENCODE_HOT_RELOAD(router mode)OPENWORK_OPENCODE_HOT_RELOAD_DEBOUNCE_MSOPENWORK_OPENCODE_HOT_RELOAD_COOLDOWN_MSOPENWORK_OPENCODE_HOT_RELOAD(start/serve mode)OPENWORK_OPENCODE_HOT_RELOAD_DEBOUNCE_MSOPENWORK_OPENCODE_HOT_RELOAD_COOLDOWN_MS
Or from source:
pnpm --filter openwork-orchestrator dev -- \
start --workspace /path/to/workspace --approval auto --allow-externalWhen OPENWORK_DEV_MODE=1 is set, orchestrator uses an isolated OpenCode dev state for config, auth, data, cache, and state. OpenWork's repo-level pnpm dev commands enable this automatically so local development does not reuse your personal OpenCode environment.
The command prints pairing URLs by default and withholds live credentials from stdout to avoid leaking them into shell history or collected logs. Use --json only when you explicitly need the raw pairing secrets in command output.
Use --detach to keep services running and exit the dashboard. The detach summary includes the
OpenWork URL and a redacted opencode attach command, while keeping live credentials out of the detached summary.
openwork can run the sidecars inside a Linux container boundary while still mounting your workspace
from the host.
# Auto-pick sandbox backend (prefers Apple container on supported Macs)
openwork start --sandbox auto --workspace /path/to/workspace --approval auto
# Explicit backends
openwork start --sandbox docker --workspace /path/to/workspace --approval auto
openwork start --sandbox container --workspace /path/to/workspace --approval autoNotes:
--sandbox autoprefers Applecontaineron supported Macs (arm64), otherwise Docker.- Docker backend requires
dockeron your PATH. - Apple container backend requires the
containerCLI (https://github.com/apple/container). - In sandbox mode, sidecars are resolved for a Linux target (and
--sidecar-source/--opencode-sourceare effectivelydownloaded). - Custom
--*-binoverrides are not supported in sandbox mode yet. - Use
--sandbox-imageto pick an image with the toolchain you want available to OpenCode. - Use
--sandbox-persist-dirto control the host directory mounted at/persistinside the container.
You can add explicit, validated mounts into /workspace/extra/*:
openwork start --sandbox auto --sandbox-mount "/path/on/host:datasets:ro" --workspace /path/to/workspaceAdditional mounts are blocked unless you create an allowlist at:
~/.config/openwork/sandbox-mount-allowlist.json
Override with OPENWORK_SANDBOX_MOUNT_ALLOWLIST.
openwork emits a unified log stream from OpenCode, OpenWork server, and opencode-router. Use JSON format for
structured, OpenTelemetry-friendly logs and a stable run id for correlation.
OPENWORK_LOG_FORMAT=json openwork start --workspace /path/to/workspaceUse --run-id or OPENWORK_RUN_ID to supply your own correlation id.
OpenWork server logs every request with method, path, status, and duration. Disable this when running
openwork-server directly by setting OPENWORK_LOG_REQUESTS=0 or passing --no-log-requests.
The router keeps a single OpenCode process alive and switches workspaces JIT using the directory parameter.
openwork daemon start
openwork workspace add /path/to/workspace-a
openwork workspace add /path/to/workspace-b
openwork workspace list --json
openwork workspace path <id>
openwork instance dispose <id>Use OPENWORK_DATA_DIR or --data-dir to isolate router state in tests.
- Use the OpenWork connect URL and client token to connect a remote OpenWork client.
- The OpenWork server advertises the OpenCode connect URL plus optional basic auth credentials to the client.
openwork approvals list \
--openwork-url http://<host>:8787 \
--host-token <token>
openwork approvals reply <id> --allow \
--openwork-url http://<host>:8787 \
--host-token <token>openwork status \
--openwork-url http://<host>:8787 \
--opencode-url http://<host>:4096Create a short-lived workspace file session and sync files in batches:
# Create writable session
openwork files session create \
--openwork-url http://<host>:8787 \
--token <client-token> \
--workspace-id <workspace-id> \
--write \
--json
# Fetch catalog snapshot
openwork files catalog <session-id> \
--openwork-url http://<host>:8787 \
--token <client-token> \
--limit 200 \
--json
# Read one or more files
openwork files read <session-id> \
--openwork-url http://<host>:8787 \
--token <client-token> \
--paths "README.md,notes/todo.md" \
--json
# Write a file (inline content or --file)
openwork files write <session-id> \
--openwork-url http://<host>:8787 \
--token <client-token> \
--path notes/todo.md \
--content "hello from openwork" \
--json
# Watch change events and close session
openwork files events <session-id> --openwork-url http://<host>:8787 --token <client-token> --since 0 --json
openwork files session close <session-id> --openwork-url http://<host>:8787 --token <client-token> --jsonopenwork start --workspace /path/to/workspace --check --check-eventsThis starts the services, verifies health + SSE events, then exits cleanly.
Point to source CLIs for fast iteration:
openwork start \
--workspace /path/to/workspace \
--allow-external \
--openwork-server-bin apps/server/src/cli.ts \
--opencode-router-bin apps/opencode-router/dist/cli.js