* feat(server): add scoped tokens, inbox/outbox, toy UI, and auth hardening - TokenService with file-based persistence (tokens.json) - /tokens CRUD (host auth), /whoami (client auth) - Bearer token auth accepting OPENWORK_TOKEN or scoped tokens - POST /workspace/:id/inbox (multipart upload) - GET /workspace/:id/artifacts, /workspace/:id/artifacts/:id - Toy UI at /ui with SSE, prompt send, inbox upload, outbox download - Extended GET /capabilities with schemaVersion, serverVersion, approvals info - Updated README with all new endpoints and auth model * feat(headless): add sandbox runtime with Docker and Apple container backends - --sandbox none|auto|docker|container CLI flag - --sandbox-image, --sandbox-persist-dir, --sandbox-mount options - Mount security: allowlist, blocked patterns, symlink resolution - Docker backend: workspace/persist volumes, sidecar staging, entrypoint - Apple container backend: --mount type=bind for ro mounts - Sandbox mode proxies all OpenCode access through openwork-server - Proxy health check (waitForHealthyViaProxy) avoids SDK auth issues - Sandbox-specific check suite (runSandboxChecks) for --check mode - Non-fatal verifyOpenworkServer in sandbox mode for version mismatches - Updated README with sandbox docs and mount security * feat(packaging): add Docker/docker-compose PaaS packaging - Dockerfile (node:22-bookworm-slim, installs openwrk via npm) - docker-compose.yml with workspace and data volumes - README with usage instructions * fix(headless): define sandbox owpenbot internal health port
5.5 KiB
Openwrk
Headless host orchestrator for OpenCode + OpenWork server + Owpenbot. This is a CLI-first way to run host mode without the desktop UI.
Quick start
npm install -g openwrk
openwrk start --workspace /path/to/workspace --approval auto
When run in a TTY, openwrk shows an interactive status dashboard with service health, ports, and
connection details. Use openwrk serve or --no-tui for log-only mode.
openwrk serve --workspace /path/to/workspace
openwrk ships as a compiled binary, so Bun is not required at runtime.
openwrk downloads and caches the openwork-server, owpenbot, and opencode sidecars on
first run using a SHA-256 manifest. Use --sidecar-dir or OPENWRK_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 owpenbot are resolved
(auto | bundled | downloaded | external), and --opencode-source to control
opencode resolution. Set OPENWRK_SIDECAR_SOURCE / OPENWRK_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/openwrk-v<openwrk-version>/openwrk-sidecars.json.
Owpenbot is optional. If it exits, openwrk continues running unless you pass
--owpenbot-required or set OPENWRK_OWPENBOT_REQUIRED=1.
For development overrides only, set OPENWRK_ALLOW_EXTERNAL=1 or pass --allow-external to use
locally installed openwork-server or owpenbot binaries.
Add --verbose (or OPENWRK_VERBOSE=1) to print extra diagnostics about resolved binaries.
Or from source:
pnpm --filter openwrk dev -- \
start --workspace /path/to/workspace --approval auto --allow-external
The command prints pairing details (OpenWork server URL + token, OpenCode URL + auth) so remote OpenWork clients can connect.
Use --detach to keep services running and exit the dashboard. The detach summary includes the
OpenWork URL, tokens, and the opencode attach command.
Sandbox mode (Docker / Apple container)
openwrk 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)
openwrk start --sandbox auto --workspace /path/to/workspace --approval auto
# Explicit backends
openwrk start --sandbox docker --workspace /path/to/workspace --approval auto
openwrk start --sandbox container --workspace /path/to/workspace --approval auto
Notes:
--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.
Extra mounts (allowlisted)
You can add explicit, validated mounts into /workspace/extra/*:
openwrk start --sandbox auto --sandbox-mount "/path/on/host:datasets:ro" --workspace /path/to/workspace
Additional mounts are blocked unless you create an allowlist at:
~/.config/openwork/sandbox-mount-allowlist.json
Override with OPENWRK_SANDBOX_MOUNT_ALLOWLIST.
Logging
openwrk emits a unified log stream from OpenCode, OpenWork server, and Owpenbot. Use JSON format for
structured, OpenTelemetry-friendly logs and a stable run id for correlation.
OPENWRK_LOG_FORMAT=json openwrk start --workspace /path/to/workspace
Use --run-id or OPENWRK_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.
Router daemon (multi-workspace)
The router keeps a single OpenCode process alive and switches workspaces JIT using the directory parameter.
openwrk daemon start
openwrk workspace add /path/to/workspace-a
openwrk workspace add /path/to/workspace-b
openwrk workspace list --json
openwrk workspace path <id>
openwrk instance dispose <id>
Use OPENWRK_DATA_DIR or --data-dir to isolate router state in tests.
Pairing notes
- 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.
Approvals (manual mode)
openwrk approvals list \
--openwork-url http://<host>:8787 \
--host-token <token>
openwrk approvals reply <id> --allow \
--openwork-url http://<host>:8787 \
--host-token <token>
Health checks
openwrk status \
--openwork-url http://<host>:8787 \
--opencode-url http://<host>:4096
Smoke checks
openwrk start --workspace /path/to/workspace --check --check-events
This starts the services, verifies health + SSE events, then exits cleanly.
Local development
Point to source CLIs for fast iteration:
openwrk start \
--workspace /path/to/workspace \
--allow-external \
--openwork-server-bin packages/server/src/cli.ts \
--owpenbot-bin ../owpenbot/dist/cli.js