Add a shared OpenChamber control service with two thin adapters — a native `openchamber` tool injected into managed OpenCode, and new CLI commands — so users can manage parallel sessions, worktrees, and scheduled tasks conversationally through agents or from the terminal. Control plane: - New openchamber-control service owning a fixed action contract: projects.list, models.list, session list/create/send/fork/status/messages, and schedule list/create/run/delete/toggle. Session and worktree deletion and project registration are deliberately not exposed. - New openchamber-sessions module owning create/worktree/prompt orchestration, Goal Mode dispatch, wait semantics (initial idle never counts as completion; timeout and cancellation are failures), and explicit partial-failure results. - Scheduled-task logic extracted into a service shared by routes, CLI, and the agent tool. Agent tool: - Managed OpenCode gets a materialized plugin registering one typed tool with a loopback-only callback, per-child ephemeral bearer (timing-safe, never persisted or logged), and abort propagation into the service. - The ~1.5k-token schema applies progressive disclosure: short descriptions, server-side validation returning actionable usage errors, and intent guardrails — created sessions/tasks are user-facing work (not age self-delegation); worktree/goal/agent/variant/wait are omit-by-default; dispatches produce no completion notification, and later result r to session.messages, which now returns the authoritative sessionStatus. - session.create without a user-named model picks from favorites/re send/fork omit the selection and the service reuses the target session's last user-message model, agent, and variant before falling back t - An "Agent control tool" setting (default on, Save + Reload to apply) disables plugin injection entirely. CLI: - New `openchamber session`, `schedule`, `projects`, and `models` commands with automatic instance targeting, --wait/--timeout/--last-assist worktree flags, and Goal Mode, preserving interactive, non-TTY, --quiet, and --json contracts. The control HTTP timeout derives from the w instead of the 4-second default. UI: - New built-in "Schedule a Task" starter (/schedule-task) running a dialogue that defines a task and offers to create it via the tool after explicit confirmation; Craft a Goal and Feature Planning gain the handoff offer, and guided starters reserve the question tool for concrete option choices. Localized in all 10 locales, migrated into custom starter lists, hidden on VS Code. - Sidebar shows CLI/agent-created sessions live via the control eve - openchamber tool calls render with per-action titles and metadata.
247 lines
14 KiB
Markdown
247 lines
14 KiB
Markdown
# <picture><source media="(prefers-color-scheme: dark)" srcset="https://github.com/openchamber/openchamber/raw/HEAD/docs/references/badges/openchamber-logo-dark.svg"><img src="https://github.com/openchamber/openchamber/raw/HEAD/docs/references/badges/openchamber-logo-light.svg" width="32" height="32" align="absmiddle" /></picture> @openchamber/web
|
|
|
|
[](https://github.com/openchamber/openchamber/stargazers)
|
|
[](https://github.com/openchamber/openchamber/releases/latest)
|
|
[](https://discord.gg/ZYRSdnwwKA)
|
|
|
|
Run [OpenCode](https://opencode.ai) in your browser. Install the CLI, open `localhost:3000`, done. Works on desktop browsers, tablets, and phones as a PWA.
|
|
|
|
Full project overview, screenshots, and all features: [github.com/openchamber/openchamber](https://github.com/openchamber/openchamber)
|
|
|
|
## Install
|
|
|
|
```bash
|
|
curl -fsSL https://raw.githubusercontent.com/openchamber/openchamber/main/scripts/install.sh | bash
|
|
```
|
|
|
|
Or install manually: `bun add -g @openchamber/web` (or npm, pnpm, yarn).
|
|
|
|
> **Prerequisites:** [OpenCode CLI](https://opencode.ai) installed, Node.js 22+.
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
openchamber # Start on port 3000
|
|
openchamber --port 8080 # Custom port
|
|
openchamber --lan --port 3000 # Listen on LAN (0.0.0.0)
|
|
openchamber --ui-password secret # Password-protect UI
|
|
openchamber startup enable # Start at login as a native service
|
|
OPENCHAMBER_UI_PASSWORD=secret openchamber startup enable # Save service password env
|
|
openchamber startup status # Show startup service status
|
|
openchamber startup disable # Remove startup service
|
|
openchamber tunnel help # Tunnel lifecycle commands
|
|
openchamber tunnel providers # Show provider capabilities
|
|
openchamber tunnel profile add --provider cloudflare --mode managed-remote --name prod-main --hostname app.example.com --token <token>
|
|
openchamber tunnel start --profile prod-main
|
|
openchamber tunnel start --provider cloudflare --mode quick --qr
|
|
openchamber tunnel start --provider cloudflare --mode managed-local --config ~/.cloudflared/config.yml
|
|
openchamber tunnel status --all # Show tunnel state across instances
|
|
openchamber tunnel stop --port 3000 # Stop tunnel only (server stays running)
|
|
openchamber connect-url --port 3000 # Add this server to OpenChamber Desktop
|
|
openchamber connect-url --server http://host:3000 --qr
|
|
openchamber connect-url --port 3000 --qr
|
|
openchamber logs # Follow latest instance logs
|
|
OPENCODE_PORT=4096 OPENCODE_SKIP_START=true openchamber # Connect to external OpenCode server
|
|
OPENCODE_HOST=https://myhost:4096 OPENCODE_SKIP_START=true openchamber # Connect via custom host/HTTPS
|
|
openchamber stop # Stop server
|
|
openchamber update # Update to latest version
|
|
```
|
|
|
|
`startup enable` snapshots your current environment into the native service so startup behaves like you launched `openchamber` from the same shell. This preserves provider tokens, PATH, SSH agent settings, and other CLI auth/config env vars. Use `--no-env-snapshot` for a minimal service env.
|
|
|
|
When OpenChamber launches the local OpenCode server, it also registers a native
|
|
`openchamber` agent tool for project, session, and scheduled-task orchestration.
|
|
The tool is not injected when connecting to an external OpenCode server.
|
|
|
|
### Tunnel behavior notes
|
|
|
|
- One active tunnel per running OpenChamber instance (port).
|
|
- Starting a different tunnel mode/provider on the same instance replaces the active tunnel.
|
|
- Replacing or stopping a tunnel revokes existing connect links and invalidates remote tunnel sessions.
|
|
- Connect links are one-time tokens; generating a new link revokes the previous unused link.
|
|
|
|
### Connect other OpenChamber apps
|
|
|
|
Use `connect-url` when a web/API server should be added to OpenChamber Desktop or another OpenChamber app. If no server is running on the selected port, OpenChamber starts one first.
|
|
|
|
```bash
|
|
openchamber connect-url --port 3000
|
|
openchamber connect-url --port 3000 --qr
|
|
openchamber connect-url --port 3000 --json
|
|
openchamber connect-url --port 3000 --name "Workstation"
|
|
openchamber connect-url --port 3000 --lan --server http://workstation.local:3000 --qr
|
|
```
|
|
|
|
### Headless/API-only server for Desktop
|
|
|
|
Use this on a remote machine when you want OpenChamber running as a web/API server, then connect to it from OpenChamber Desktop on another machine:
|
|
|
|
```bash
|
|
openchamber connect-url --port 3000 --api-only --lan --server http://workstation.local:3000 --qr --ui-password your-password
|
|
```
|
|
|
|
`--api-only` starts API routes without serving browser UI assets. `--lan` binds the server so other machines can reach it. `--server` is the address saved into the Desktop connection link. `--ui-password` protects browser access if UI routes are enabled elsewhere; the generated client token is what Desktop uses for API access.
|
|
|
|
This creates a remote client token and prints an `openchamber://connect?...` link. The link contains the server URL, token, label, and payload version. In OpenChamber Desktop, paste it in **Settings -> Remote Instances -> Direct Instances -> Import Link** to add that server as an Instance.
|
|
|
|
If the server was started with `--lan` or `--host 0.0.0.0`, `connect-url` automatically advertises a detected LAN IP instead of `127.0.0.1`. Use `--server <url>` when you want to advertise a specific DNS name, Tailscale address, reverse proxy URL, or HTTPS endpoint.
|
|
|
|
If you are exposing the server beyond localhost, start it with a password:
|
|
|
|
```bash
|
|
openchamber serve --lan --port 3000 --ui-password your-password
|
|
```
|
|
|
|
Generating a client token does not automatically password-protect the hosted browser UI. `--ui-password` protects browser access; the client token lets another OpenChamber app connect to this server.
|
|
|
|
<details>
|
|
<summary>Connect to external OpenCode server</summary>
|
|
|
|
```bash
|
|
OPENCODE_PORT=4096 OPENCODE_SKIP_START=true openchamber
|
|
OPENCODE_HOST=https://myhost:4096 OPENCODE_SKIP_START=true openchamber
|
|
```
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `OPENCODE_HOST` | Full base URL of external server (overrides `OPENCODE_PORT`) |
|
|
| `OPENCODE_PORT` | Port of external server |
|
|
| `OPENCODE_SKIP_START` | Skip starting embedded OpenCode server |
|
|
| `OPENCHAMBER_OPENCODE_HOSTNAME` | Bind hostname for managed OpenCode server (default: `127.0.0.1`, use `0.0.0.0` for LAN/remote access — trusted networks only) |
|
|
| `OPENCHAMBER_HOST` | Bind hostname for the OpenChamber web server (default: `127.0.0.1`; use `0.0.0.0` for LAN/remote access — trusted networks only) |
|
|
| `OPENCHAMBER_VERBOSE_REQUEST_LOGS` | Set to `true` to log every HTTP request; disabled by default to keep user logs small |
|
|
| `OPENCHAMBER_SKIP_API_COMPRESSION` | Set to `true` to disable gzip compression for `/api/*` responses |
|
|
| `OPENCHAMBER_COMPRESS_API` | Set to `true` to force `/api/*` compression, or `false` to disable it. Desktop runtime disables API compression by default to reduce local sidecar CPU use |
|
|
| `OPENCHAMBER_TERMINAL_SHELL` | Preferred terminal shell executable used by the `Auto` setting before platform defaults |
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Bind managed OpenCode to LAN / Tailscale</summary>
|
|
|
|
```bash
|
|
OPENCHAMBER_OPENCODE_HOSTNAME=0.0.0.0 openchamber --port 3000
|
|
```
|
|
|
|
**Security note:** binding to `0.0.0.0` exposes the server on all network interfaces — use only on trusted networks and protect with firewall rules or `--ui-password`.
|
|
|
|
</details>
|
|
|
|
**Optional env vars:**
|
|
```yaml
|
|
environment:
|
|
UI_PASSWORD: your_secure_password
|
|
OPENCHAMBER_TUNNEL_MODE: quick # quick | managed-remote | managed-local
|
|
OPENCHAMBER_TUNNEL_PROVIDER: cloudflare
|
|
```
|
|
|
|
For `managed-remote` mode, also set:
|
|
|
|
```yaml
|
|
environment:
|
|
OPENCHAMBER_TUNNEL_MODE: managed-remote
|
|
OPENCHAMBER_TUNNEL_HOSTNAME: app.example.com
|
|
OPENCHAMBER_TUNNEL_TOKEN: <token>
|
|
```
|
|
|
|
For `managed-local` mode, you can set:
|
|
|
|
```yaml
|
|
environment:
|
|
OPENCHAMBER_TUNNEL_MODE: managed-local
|
|
OPENCHAMBER_TUNNEL_CONFIG: /home/openchamber/.cloudflared/config.yml
|
|
```
|
|
|
|
Managed-local path note: `OPENCHAMBER_TUNNEL_CONFIG` must use a container path under `/home/openchamber/...`. If the config file references `credentials-file`, ensure that JSON path is also mounted and reachable inside the container.
|
|
|
|
**Data directory:** mount `data/` for persistent storage. Ensure permissions:
|
|
```bash
|
|
mkdir -p data/openchamber data/opencode/share data/opencode/config data/ssh
|
|
chown -R 1000:1000 data/
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Background & daemon mode</summary>
|
|
|
|
```bash
|
|
openchamber # Runs in background by default
|
|
openchamber stop # Stop background server
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>systemd service (VPN / LAN access)</summary>
|
|
|
|
Use `--foreground` to keep the CLI process alive so systemd (or any other process manager) can track and restart it. Combine with `OPENCODE_HOST` to connect to an OpenCode instance running as a separate service.
|
|
|
|
**`~/.config/systemd/user/opencode.service`**
|
|
```ini
|
|
[Unit]
|
|
Description=OpenCode Server
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=opencode serve --port 4095
|
|
Environment="PATH=/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/YOU/.local/bin:/home/YOU/.npm-global/bin:/usr/local/bin:/usr/bin:/bin"
|
|
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
```
|
|
|
|
> **Why set `PATH` and `SSH_AUTH_SOCK`?**
|
|
> systemd user services start with a minimal environment — no shell profile is sourced.
|
|
> Without an explicit `PATH`, OpenCode won't find tools installed via Homebrew, npm, or `~/.local/bin`.
|
|
> Without `SSH_AUTH_SOCK`, git operations over SSH (push, pull, clone) will fail.
|
|
> `%t` expands to `$XDG_RUNTIME_DIR` (e.g. `/run/user/1000`), where most SSH agents write their socket.
|
|
|
|
**`~/.config/systemd/user/openchamber.service`**
|
|
```ini
|
|
[Unit]
|
|
Description=OpenChamber Web Server
|
|
After=opencode.service
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=openchamber serve --port 3000 --host 0.0.0.0 --ui-password your-password --foreground
|
|
Environment="OPENCODE_HOST=http://localhost:4095"
|
|
Environment="OPENCODE_SKIP_START=true"
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
```
|
|
|
|
```bash
|
|
systemctl --user daemon-reload
|
|
systemctl --user enable --now opencode openchamber
|
|
```
|
|
|
|
`--host 0.0.0.0` is required to listen on all interfaces (the default is `127.0.0.1`). Use `--host <ip>` or `OPENCHAMBER_HOST=<ip>` to bind to a specific interface instead.
|
|
|
|
</details>
|
|
|
|
## What makes the web version special
|
|
|
|
- **Remote access** - Cloudflare tunnel with QR onboarding. Scan from your phone, start coding.
|
|
- **Mobile-first PWA** - optimized chat controls, keyboard-safe layouts, drag-to-reorder projects
|
|
- **Background notifications** - know when your agent finishes, even from another tab
|
|
- **Self-update** - update and restart from the UI, server settings stay intact
|
|
- **Cross-tab tracking** - session activity stays in sync across browser tabs
|
|
|
|
- Cloudflare tunnel access with quick, managed-remote, and managed-local modes
|
|
- One-scan onboarding with tunnel QR + password URL helpers
|
|
- Mobile-first experience: optimized chat controls, keyboard-safe layouts, and attachment-friendly UI
|
|
- Background notifications plus reliable cross-tab session activity tracking
|
|
- Built-in self-update + restart flow that keeps your server settings intact
|
|
|
|
## License
|
|
|
|
MIT
|