--- read_when: - adding a CLI subcommand or flag - changing bootstrap, migrations, backup, or export behavior --- # CLI The single binary is `clickclack`. Source: `apps/api/cmd/clickclack/main.go`. It can host a server and act as a scriptable local or remote chat client. The broader agent-friendly contract is documented in [agent-friendly-cli.md](agent-friendly-cli.md). ```text clickclack [flags] Commands: serve run the HTTP/WebSocket server (default if no command given) migrate apply embedded SQL migrations admin bootstrap, user create, invite create, magic-link create backup write a SQLite backup file export write a JSON dump to a file or stdout login consume a magic-link token and store/print a session token logout remove stored client credentials whoami print the current server-side user status print selected server/user/workspace/channel workspaces list channels list send messages send messages list threads open threads reply ``` Client commands accept these common flags before the command or on the command itself: | Flag | Env | Default | Notes | | --- | --- | --- | --- | | `--server` | `CLICKCLACK_SERVER` | `http://localhost:8080` | Remote server URL. | | `--token` | `CLICKCLACK_TOKEN` | stored config | Sends `Authorization: Bearer`. | | `--user`, `--user-id` | `CLICKCLACK_USER_ID` | unset | Sends `X-ClickClack-User`; local development/test escape hatch. | | `--workspace` | `CLICKCLACK_WORKSPACE` | first visible workspace | ID, slug, or name. | | `--channel` | `CLICKCLACK_CHANNEL` | `general`, then first visible channel | ID or name. Channel IDs are resolved across visible workspaces unless `--workspace` is set. | | `--json` | — | false | Machine-readable JSON output. | | `--plain` | — | false | Stable single-field output, usually an ID or token. | | `--no-input` | — | false | Reserved for non-interactive flows. | Stored client config lives at `~/.config/clickclack/config.json`. Stored token, workspace, and channel defaults are scoped to their saved server URL. If `--server` or `CLICKCLACK_SERVER` points somewhere else and no explicit `--token` is supplied, the CLI will not reuse the saved bearer token. It also will not reuse the saved workspace or channel unless the selected server matches. If `--user` or `CLICKCLACK_USER_ID` is set and no explicit `--token` is supplied, the CLI also skips the stored bearer token so the server can honor the requested dev user. If both `--token` and `--user` are supplied, the server's auth order applies and the bearer token wins. ## `serve` ```sh clickclack serve \ --addr :8080 \ --data ./data \ --db sqlite://./data/clickclack.db \ --config ./clickclack.json \ --dev-bootstrap=true ``` - Loads config from `--config` (JSON) layered on top of env vars (`CLICKCLACK_*`). CLI flags win when explicitly set. See [configuration.md](configuration.md). - Creates ``, `/uploads`, `/logs`. - Opens SQLite (modernc) with WAL, foreign keys, and `busy_timeout=5000`, then runs migrations. - When `--dev-bootstrap=true` (the default), creates a `Local Captain` user and a `ClickClack` workspace if the DB is empty. Disable in production. - Logs the resolved listen URL and the dev-auth user ID. ## `migrate` ```sh clickclack migrate --data ./data --db sqlite://./data/clickclack.db ``` Idempotent: each migration in `apps/api/internal/store/sqlite/migrations/` is recorded in `schema_migrations` and skipped on subsequent runs. Use this in deployments before flipping traffic to a new build. ## `admin` ### `admin bootstrap` ```sh clickclack admin bootstrap --name "Peter" --email steipete@gmail.com ``` Creates the first user, workspace, and `general` channel if none exist. Idempotent — re-running prints the existing user's ID. Output is the `usr_...` ID on stdout, ready to capture in a shell script. ### `admin user create` ```sh clickclack admin user create --name "Ari" --email ari@example.com [--workspace wsp_...] ``` Creates a user. With `--workspace`, also adds them to that workspace as a `member`. Prints the new user ID. ### `admin invite create` ```sh clickclack admin invite create --workspace wsp_... ``` Mints an invite token (created by the first user in the DB, which is the owner in single-tenant deployments). Prints the token. There is no consume endpoint over HTTP yet — invite tokens are reserved for V1 work. ### `admin magic-link create` ```sh clickclack admin magic-link create --email steipete@gmail.com --name "Peter" ``` Mints a magic-link token. Hand it to the user; they POST it to `/api/auth/magic/consume` to get a session. See [features/auth.md](features/auth.md). ## `backup` ```sh clickclack backup --data ./data --out ./data/backup.db ``` Uses SQLite's online backup API to write a hot copy of the database. Safe to run while `serve` is up. The destination must be on the same filesystem as `` if you want a fast atomic move afterwards. ## `export` ```sh clickclack export --data ./data --out ./data/export.json clickclack export --out - # stdout ``` Writes a JSON dump of users, workspaces, channels, messages, threads, reactions, uploads metadata, and DMs. Useful for migrations between SQLite files or for one-off audits. ## Client auth ```sh clickclack --server http://localhost:8080 login \ --magic-token mgt_... \ --plain ``` Consumes a magic-link token through `/api/auth/magic/consume`. By default it stores the returned session token in the client config file. Use `--no-store` for CI or tests that only need stdout. `logout` removes the stored client config. For remote or hosted agents, prefer `login` plus stored credentials or `CLICKCLACK_TOKEN`. Reserve `--user` for local/dev servers where explicit user impersonation is acceptable. ## Client reads ```sh clickclack --server http://localhost:8080 --token sst_... whoami clickclack --server http://localhost:8080 --token sst_... workspaces list clickclack --server http://localhost:8080 --token sst_... channels list --workspace clickclack clickclack --server http://localhost:8080 --token sst_... messages list --channel general --json clickclack --server http://localhost:8080 --token sst_... threads open msg_... --json ``` `workspaces list` prints `id slug name` in human mode. `channels list` prints `id name kind`. `messages list` prints `seq id author body`. ## Client writes ```sh clickclack --server http://localhost:8080 --token sst_... send --channel general "hello" printf 'long body\n' | clickclack --server http://localhost:8080 --token sst_... send --channel general --stdin clickclack --server http://localhost:8080 --token sst_... threads reply msg_... --stdin