Reworks how devices connect to an OpenChamber server, end to end. Pairing v2: - One-time pairing links/QR codes (openchamber://connect?v=2) carrying a set of transport candidates (LAN/tunnel/relay) and a single-use secret redeemed server-side; no tokens embedded in links - Add-a-device dialog written for first-time users: intent-based transport choice (Anywhere / Home network only / This computer only) with plain-language descriptions, transparent fallback checkboxes, server-authoritative LAN detection, high-res QR dialog - Private relay folded into pairing as a transport candidate with a demand-driven lifecycle (enables when a relay device is paired, disables when none remain) Multi-transport devices: - A saved device holds all its transports and one token; mobile re-probes on connect, resume, and network change and hot-switches LAN<->relay seamlessly (no re-pairing, no remount, session preserved) - Desktop can import relay pairing links, switch to relay hosts through the E2EE tunnel, and restore a relay default host after relaunch Device management: - Device list (web + desktop) shows live per-device connectivity with the active transport (Connected - Local network / Relay) and platform badges (iOS/Android/macOS/Windows/Linux) - One physical device = one record: stable per-install dedupe keys across pairing and password re-login; typed pairing label names the device, paired devices name the connection by the issuing server hostname - Trusted desktop-local client manages all devices (list, revoke, clear revoked); relay host reaps dead client sockets after 3 missed keepalives Android: - LAN transport unblocked (cleartext + mixed content, mirroring iOS ATS exceptions); resume re-probe retries through network flux and silently auto-reconnects from a disconnected state
6.7 KiB
CLI Module Map
This directory contains the non-entrypoint implementation for the OpenChamber CLI. packages/web/bin/cli.js should stay thin: it owns bootstrap, command wiring, top-level dispatch, signal/cancel handling, and compatibility exports. Domain logic belongs in these modules.
Entrypoint Boundary
../cli.js- Owns process bootstrap, package/version lookup, command table wiring, signal handlers, top-level error handling, and legacy exports used by tests or external consumers.
- Injects runtime dependencies into command factories, such as
serveCommand,stopCommand, package-manager loading, cancel cleanup, and foreground server state setters. - Should not grow command-specific behavior. If a new branch needs more than dispatch/wiring, move it here into a command or helper module instead.
Command Modules
Command modules implement user-facing commands and preserve output contracts across interactive, non-TTY, --quiet, and --json modes. They should use ../cli-output.js for presentation helpers and keep safety validation in command logic, not prompts.
-
commands-serve.js- Implements
openchamber serve. - Owns OpenCode CLI checks, port resolution, log rotation, PID/instance registry writes, foreground/background server launch, startup summaries, and foreground shutdown behavior.
- Implements
-
commands-lifecycle.js- Implements
openchamber stopandopenchamber restart. - Owns lifecycle stop/restart semantics, desktop-managed port rejection, unmanaged instance shutdown attempts, PID/instance cleanup, and restart reuse of stored instance options.
- Implements
-
commands-status.js- Implements
openchamber status. - Formats discovered instances and tunnel readiness/status for human, quiet, and JSON output.
- Implements
-
commands-logs.js- Implements
openchamber logs. - Resolves log files, tails recent lines, and follows log output.
- Implements
-
commands-startup.js- Implements
openchamber startup. - Handles startup subcommand dispatch and presentation around the lower-level startup service helpers.
- Implements
-
commands-connect-url.js- Implements
openchamber connect-url. - Finds or starts a local instance and prints the browser/connect URL according to the selected output mode.
- Emits a pairing v2 link (
openchamber://connect?v=2&p=<base64url>): it creates a one-time pairing session in the shared store (client-pairing-sessions.json) and encodes the pairing id + secret + transport candidates. The client redeems the secret over whichever candidate connects first (/api/client-auth/pairing/redeem). No standalone token is embedded — the QR itself is the single-use credential. - The default form advertises the resolved server URL as a direct (lan/tunnel) candidate and folds in a relay candidate when the host relay is enabled, so one link works on-LAN and off-network.
--relaybuilds a relay-only pairing link (the sole candidate is the relay transport), for sharing with a device that is not on the host's network — no server URL, no auto-start. The relay endpoint followsOPENCHAMBER_RELAY_URL/ the stored setting / the default, matching the running host; the host must be running with the relay enabled to serve the redeem over the tunnel.
- Implements
-
commands-update.js- Implements
openchamber update. - Loads the package-manager helper, performs update flow, and coordinates restart behavior after updates.
- Implements
-
commands-tunnel.js- Implements
openchamber tunneland its subcommands:profile,providers,ready,doctor,status,start,stop, andcompletion. - Owns tunnel-specific command flow, interactive prompt decisions, managed-local/managed-remote startup, QR display rules, tunnel start/stop API calls, and tunnel profile command handling.
- Receives
serveCommandandstopCommandby dependency injection. Do not reach back intocli.jscommand globals from this module.
- Implements
Shared Helper Modules
These modules hold reusable, non-presentational logic for commands.
-
cli-args.js- Argument parsing, defaults, help text, completion script generation, and typo suggestions.
-
cli-errors.js- CLI exit codes and typed tunnel CLI errors.
-
cli-paths.js- Data, run, log, settings, tunnel profile, and managed-local config paths.
-
cli-process.js- PID files, instance registry files, process identity checks, runtime metadata checks, and process termination helpers.
-
cli-lifecycle.js- Instance discovery, live health probing, attachability checks, provider discovery, and status aggregation used by lifecycle/status/tunnel commands.
-
cli-http.js- HTTP helpers for health checks, shutdown requests, JSON API calls, tunnel provider fetches, and system info fetches.
-
cli-network.js- Host resolution, URL building, LAN detection, unsafe browser port validation, and UI password/network exposure checks.
-
cli-ports.js- Port availability checks and available-port resolution.
-
cli-log-files.js- Log rotation, tail reads, and file-follow streaming.
-
cli-executables.js- Executable path resolution and PATH lookup helpers.
-
cli-startup.js- Native startup service detection, install/uninstall/status helpers, and platform-specific startup command execution.
-
cli-tunnel-profiles.js- Tunnel profile normalization, token resolution/redaction, profile storage, migration, file-permission warnings, and managed-remote pair persistence.
-
cli-tunnel-utils.js- Tunnel-specific command string builders, TTL parsing/formatting, and replay command helpers.
-
cli-tunnel-capabilities.js- Built-in tunnel provider capability fallbacks used when a live server cannot provide tunnel metadata.
Placement Rules
- Add new CLI commands as
commands-*.jsmodules and wire them fromcli.js. - Add reusable logic to the narrow helper module that owns the domain. Create a new helper module before mixing unrelated domains into an existing one.
- Keep command modules responsible for user-visible behavior and mode-specific output. Keep helper modules mostly output-free unless the helper exists specifically for CLI rendering.
- Preserve output contracts when moving code:
--jsonemits JSON only.--quietemits concise essential output.- Prompts are gated by
canPrompt(options). - Validation and policy run in every mode.
- Prefer dependency injection from
cli.jsfor cross-command behavior, especially when one command needs another command's implementation. - Do not import
cli.jsfrom modules in this directory. The dependency direction iscli.js-> command modules -> helper modules.
Verification
For CLI behavior changes, run the focused CLI suite from packages/web:
bun run test -- bin/cli.test.js
Before finalizing source changes that affect CLI behavior, also run:
bun run type-check
bun run lint