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.
-`commands-lifecycle.js`
- Implements `openchamber stop` and `openchamber restart`.
- Owns lifecycle stop/restart semantics, desktop-managed port rejection, unmanaged instance shutdown attempts, PID/instance cleanup, and restart reuse of stored instance options.
-`commands-status.js`
- Implements `openchamber status`.
- Formats discovered instances and tunnel readiness/status for human, quiet, and JSON output.
-`--relay` builds an end-to-end-encrypted relay pairing link instead: it mints a client token and an offer from the instance's local relay identity (no server URL, no auto-start). The relay endpoint follows `OPENCHAMBER_RELAY_URL` / the stored setting / the default, matching the running host; clients read it from the offer.
- Built-in tunnel provider capability fallbacks used when a live server cannot provide tunnel metadata.
## Placement Rules
- Add new CLI commands as `commands-*.js` modules and wire them from `cli.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:
-`--json` emits JSON only.
-`--quiet` emits concise essential output.
- Prompts are gated by `canPrompt(options)`.
- Validation and policy run in every mode.
- Prefer dependency injection from `cli.js` for cross-command behavior, especially when one command needs another command's implementation.
- Do not import `cli.js` from modules in this directory. The dependency direction is `cli.js` -> command modules -> helper modules.
## Verification
For CLI behavior changes, run the focused CLI suite from `packages/web`:
```sh
bun run test -- bin/cli.test.js
```
Before finalizing source changes that affect CLI behavior, also run: