# remits-cli

Local CLI for rapid Remits component testing without push/sync cycles.

## Install

```bash
npm install -g @remits/remits-cli
```

On each command run, `remits-cli` checks the npm `latest` version for `@remits/remits-cli`. If a newer version exists, it installs it globally with npm and re-runs the original command. To skip this check for one run, pass `--no-auto-update`; to disable it for a process environment, set `REMITS_CLI_AUTO_UPDATE=0`.

## Common Commands

```bash
remits-cli auth --base-url https://your-remits-host --account-id 123
remits-cli start
remits-cli status
remits-cli whoami
remits-cli stop
remits-cli install --skills
remits-cli tools
remits-cli tool --base-url http://localhost:8080 --name "My Tool" --input '{"foo":"bar"}'
remits-cli tool --name mcp_firestore_search --input '{"collection":"statements","documentId":"1234"}' --scope children
remits-cli workspace use --auto               # once per checkout: your own staging lane
remits-cli components stage --workset         # normal iteration: stage exactly what you changed
remits-cli components stage                   # FULL SNAPSHOT of the repo into the lane
remits-cli components status
remits-cli components clear
remits-cli test run --test 45
remits-cli test run --test "My New Test" --names "test case 1|test case 2"
git add -A
git commit -m "sync passing changes"
git push
remits-cli components sync --safe             # variant branch: gated, dry-runs first, refuses surprises
remits-cli components sync
remits-cli components sync --branch feature_branch --dry-run
remits-cli components sync --branch feature_branch --dry-run --summary
remits-cli components sync --branch feature_branch --force-tombstones
remits-cli token --path page/my-embeddable    # returns tokenKey/embeddableUrl, plus embedTokenKey/embedSnippet for host embeds
remits-cli token --path page/my-embeddable --variant-branch feature_branch
remits-cli token inspect --token https://example.test/s/<tokenKey>/page/my-embeddable
remits-cli tool --name mcp_account_user_admin --data-mode prod --input '{"action":"account_create","parentAccountId":4,"name":"Freto","type":"PRODUCT","dryRun":true}'
remits-cli data-mode
remits-cli data-mode set prod
remits-cli sessions list
remits-cli config set --agent codex
remits-cli activity inspect --account-id 4 --scope children --data-mode test
```

## Skill Install

```bash
remits-cli install --skills
```

Optional:

```bash
remits-cli install --skills --target codex
remits-cli install --skills --target claude
remits-cli install --skills --target gemini
remits-cli install --skills --overwrite true
```

## How It Works

- `cli/index.js` opens with a line-numbered code Table of Contents. Section entries are generated from
  the `##` section marker comments in the file. Run `npm run prepare:index-toc` after moving sections;
  `npm test` checks that the prepared line numbers still point at the real headings.
- `components stage` has three modes, and the difference decides what a run in the lane resolves:
  - **default (full snapshot)** — uploads the whole repository manifest and reconciles the lane to it, so stale aliases from prior stages are removed. Correct as a complete snapshot and as a "what is stale here?" reset; a poor progress signal, because the lane then holds every component in the repo.
  - **`--workset`** — uploads only the components git reports changed and reconciles the lane to exactly those. The normal iteration mode. `--changed-only --replace-lane` is the explicit spelling.
  - **`--changed-only`** — uploads only the changed components and MERGES, leaving every other staged entry in place. It therefore cannot shrink a lane inherited from an earlier full snapshot; the command warns when it retains entries that way.
- An **empty workset never clears a lane**: `--workset` on a clean working tree stages nothing and leaves the lane as it is. Pass `--empty-workset clear` to opt in, or use `components clear --all`.
- A **deleted component file cannot be represented in Redis staging** — clearing a staged entry falls back to the committed row, so the component still resolves. Those changes are reported as NOT REPRESENTABLE. On a non-trunk variant branch, prove a deletion through `components sync --dry-run --summary --fail-on-errors`; on trunk there is no dry-run plan, so use the full pre-sync safety check before any mutating reconcile.
- Schema `.meta.yml` sidecars can stage/sync the schema flags: `enableTrigger`, `enableFullText`, `enableRAG`, `enableRevisions`, `enableBigQuerySync`, `enableRules`, `anchor`, and `auxiliary`.
- `components status` shows the branch/user staging entries that can shadow DB components during CLI-scoped test-mode execution, plus the other live lanes on the account.
- `components lanes` lists every indexed staging lane on the account. `components entries --lane-id <id>` reads the authoritative staged files for one lane without switching your workspace, clearing anything, or using SQL.
- `components clear` clears staged entries. Scope it with `--component-type` and/or `--component-id`. Component ids are type-local, so an id alone clears that one component when the id is staged in only one family; if the same id is staged across multiple families it returns an ambiguity error asking you to add `--component-type`. With no filter it clears every staged entry for the current branch; pass `--all` to force the full-branch wipe explicitly.
- `components stage`, `components status`, `components lanes`, `components entries`, and `components clear` print concise summaries by default. Add `--json` or `--verbose` to print the full server response.
- `activity inspect` is a read-only workstream view for operator/agent review. It joins staging lanes, verification envelopes, Test runs, corpus measurements, live agent presence, and heuristic smell signals. Use `--scope children` from a platform/root account and `--user-email` or `--user-id` to focus on one CLI user.
- `components stage` and `components status` report three separate numbers, and they answer three different questions: the **workset** (components git reports this working tree changed), what was **submitted**, and the materialized **overlay** the lane now holds — which is what a run resolves. A number that could not be established prints as `unknown`, never as `0`.
- `components sync` performs a server-side sync from the git remote into the Remits platform for the selected branch. It does not run local git commands. After a successful non-dry-run sync, the platform clears the branch/user staging scope so staged aliases cannot keep shadowing the newly synced DB rows.
- On trunk, `components sync` performs the full repo-to-DB reconcile. On a non-trunk branch, it writes `ComponentVariant` overlays only and may refresh branch-local `account-info.json`, `account-hierarchy.json`, and `account-configurations.json` for the subscribing account that initiated the sync. `--dry-run` is accepted only for non-trunk variant syncs and reports overrides/additions/tombstones without writing variants, caching the sync SHA, updating metadata, or clearing staging. Add `--summary` to dry-run output when you only need counts, removals/tombstones, errors, skipped items, and warnings. `--force-tombstones` is accepted only for non-trunk variant syncs and should be used only when missing trunk component files are intentional tombstone overrides.
- `components commit` is a convenience wrapper that performs local git commit/push, then `components sync`, then local `git fetch`/`git pull --ff-only`.
- `components sync` returns the post-sync branch SHA produced by the platform. `components commit` verifies that `origin/<branch>` and local `HEAD` both match that exact SHA after the final pull.
- `components push` is deprecated and currently behaves the same as `components stage`.
- `accountId` resolution for CLI commands: explicit `--account-id` flag wins, then the current repo's `account-info.json` (`resolution.accountId`, then the short-lived `repoContext.accountInfoAccountId`, then the legacy top-level id — legacy files are rooted at the hierarchy ROOT, so their top-level `id` may be an ancestor), then the active session.
- For `remits-cli tool`, read/discovery tools treat that resolved account as the **scope root**. You do not need the owning child account id for an exact document/record lookup: pass `--scope children`, or put `scope:"children"` in `--input`, and use the returned `resolvedTargetAccountId` for follow-up writes/runs. Use `--target-account-id` when you already know the exact owner, `--account-ids` for an explicit bounded owner list, and `--anchor-account-id` only to disambiguate multi-parent paths. Mutating tools still require an exact target.
- Auth sessions are stored per `accountId + dataMode + baseUrl`, so the same account can stay authenticated against both localhost and production without overwriting the other session.
- Active verification envelopes are scoped per `baseUrl + accountId + branch + workspace + dataMode`, so a localhost envelope does not silently capture evidence from a production command. Pass `--verify-envelope <id>` for an intentional cross-context attachment.
- `--base-url` and `--data-mode` are independent. `--base-url` chooses the Remits host (`http://localhost:8080` vs deployed prod), while `--data-mode` chooses the data segment on that host (`test` vs `prod`). Do not assume `--data-mode prod` means the deployed prod host, or that `--data-mode test` means localhost.
- `remits-cli start` scans the machine for `account-info.json` files and rebuilds `~/.remits-cli/account-repos.json` before bringing up the background service.
- Front-stage guides are **not** bundled with the CLI npm package. For account-work commands (`components`, `test`, `token`, `tools`, `tool`) and on `auth`, `remits-cli` downloads the latest guides from the authenticated `/cli/guides` endpoint and writes them into the current account repo: root `platform-overview.md` / `development-guide.md`, `guides/*.md`, `guides/features/*.md`, and the agent-guidance files `CLAUDE.md` / `AGENTS.md` / `GEMINI.md` (from `docs/front-stage/remits-components-zip-readme.md`).
- Guide sync requires authentication. If no valid session exists and the terminal is interactive, the CLI auto-authenticates first; in non-interactive contexts (CI, agent sandboxes) it skips silently so guides are only ever delivered to users who can authenticate to the platform.
- On every command, `remits-cli` refreshes the installed remits-cli `SKILL.md` and reference files for `claude`, `codex`, and `gemini` so local agents stay on the latest packaged instructions.
- The platform repo's `docs/front-stage/` tree remains the single source of truth; the platform serves it from the classpath, so published CLI versions never carry guide content.
- Authenticated users also get the **core Remits platform repo** locally. After guide sync (and on `auth` / discovery), `remits-cli` first reuses any existing local copy it already knows about, can detect directly (`REMITS_PLATFORM_DIR`, the running CLI source in dev, `~/remits`), or can discover under the configured scan roots; only if none is found does it clone `git@github.com:tmillhouse/remits.git` (default `~/remits`, override with `REMITS_PLATFORM_DIR`; cloning only runs in an interactive terminal). On each authenticated run it also fast-forwards the repo (`git pull --ff-only`, once per process) so back-stage analysis runs against current code — skipped automatically if the working tree is dirty, so local work is never clobbered. The repo is tracked in `~/.remits-cli/account-repos.json` under the reserved `platform` entry so agents can analyze back-stage seams and open a fix PR when a front-stage failure turns out to be platform brittleness.
- Branch defaults to the current local git branch.
- Data mode defaults to `test`. For `remits-cli test run`, that default is now enforced even if the most-recent authenticated session for the account is `prod`; a production test run therefore requires an explicit `--data-mode prod` on the command line. Use `remits-cli data-mode set prod` only for production investigation.
- If the same account is authenticated against more than one host and you omit `--base-url`, the CLI auto-resolves the best matching session and now prints the resolved host. Pass `--base-url` explicitly whenever the target host matters.
- `--names` is `|`-delimited and may be repeated. A comma still splits a single value for compatibility,
  so a case name containing a comma should be passed with `|` or by repeating `--names`.
- Nested help is available before required-argument validation, including `remits-cli test run --help`, `remits-cli components sync --help`, and `remits-cli tool --help`.
- `components sync --safe` is the recommended agent path on a variant branch. It expands to `--summary --changed-only --fail-on-errors --fail-on-removed`, resolves `--changed-since` from the branch's merge base with trunk when you did not name one (local refs only; it never runs an implicit `git fetch`), and prints the planned writes before mutating unless `--yes` is passed. On trunk there is no plan to gate, so it states what a trunk reconcile does and requires `--yes`.
- `components sync` has fail-closed safety gates for unattended/agent use. Each exits non-zero instead of printing a wall of JSON: `--changed-only` (fail unless every planned write is a component this checkout edited), `--names-only` (print only `BUCKET type:id name` lines), `--fail-on-removed`, `--fail-on-errors`, and `--expected-removed <type:id>` (repeatable or comma-delimited; implies `--fail-on-removed`, so any removal you did not name fails). `--changed-only` also fails closed when the checkout is not a git working tree, because "git could not answer" must never be read as "nothing changed".
- Any command that can touch production prints a `PROD DATA` banner naming the operation, the resolved account, and the host, and distinguishes a live **write** from a live **read** (and from a dry run). This covers `tool`, `test run`, and `components sync`.
- When a tool call fails inside the platform runtime rather than inside the tool — Groovy reflective dispatch of a runtime-compiled component, an empty connection pool, a Redis reconnect, a lock-wait timeout — the server returns `503` with `failureClass: "transient_infrastructure"` and `retryable: true`, and the CLI prints `TRANSIENT INFRASTRUCTURE FAILURE (retryable)`. A genuine tool error stays a `500` with `failureClass: "tool_error"`. Retry the first; do not retry the second.
- Test activity is streamed from websocket `TestSuite` events while final status is also polled from `/cli/test`.
- Tool execution writes the full response to a separate file so large payloads do not bloat the session log.
- `--variant-branch <name|none>` is available on `test run`, `token`, `tools`, and `tool`. Use it to probe a committed branch variant from any checkout; omit it to resolve the execution account's normal subscription, or pass `none`/`trunk` to force subscription semantics from a variant checkout.
- On `test run`, `--branch <name>` is only the Redis staging namespace. Pair an unused value with `--variant-branch none` when existing staged entries on the real git branch would shadow committed trunk/variant rows. Do not apply that shortcut to `components sync` or `components commit`, where `--branch` names the GitHub branch to reconcile.

## Service, Dashboard, and WebSocket Lifecycle

- The primary lifecycle commands are `remits-cli start`, `remits-cli stop`, and `remits-cli status`.
- `remits-cli listen`, `remits-cli listen stop`, and `remits-cli listen status` still work as compatibility aliases.
- Most non-lifecycle commands auto-start the background service if authenticated sessions already exist and no service is running.
- Successful `remits-cli auth` also attempts to auto-start the background service.
- `remits-cli start` starts a detached background process by default. Use `remits-cli start --foreground true` only when you want to run the daemon in the current terminal.
- `remits-cli status` reports whether the background service is alive, prints the dashboard URL when available, and prints the resolved session tuple: Account ID, User ID, current git branch, and active data mode.
- `remits-cli whoami` prints only the resolved session tuple. Use `--base-url`, `--account-id`, and `--data-mode` to prove the exact host/account/lane before running a tool or test.
- Both print **two** data modes. "Data mode" governs `tool` / `tools` / `token` and falls back to the stored session lane; "Data mode (test run)" governs `test run`, which ignores the session and defaults to `test` unless `--data-mode prod` is passed. The test-run line also reports its source, such as `cliDefault` or `explicitFlag`.
- `remits-cli stop` stops the background service.
- The service starts a localhost dashboard that acts as a control center for remits-cli integration state.
- The dashboard shows websocket connection health, topic subscriptions, registered agents, live and recent worker runs, the discovered account repo index, global state files, and per-repo remits-cli files.
- If websocket connections are disconnected, the dashboard exposes an action to reconnect them.
- The service groups sessions by `baseUrl` so one websocket connection can service multiple authenticated accounts on the same Remits environment.
- Websocket subscriptions are deduplicated by user topic. If multiple authenticated accounts share the same websocket topic, the listener subscribes once and maps that topic back to all related accounts.
- The daemon keeps STOMP heartbeats enabled and runs a maintenance watchdog that recreates unhealthy websocket connections.
- If the machine sleeps, the network drops, or auth sessions change while the daemon is already running, the service now attempts to reconnect and resubscribe automatically once connectivity returns.
- Support tickets are the primary unit of dispatched work. A serving agent launches one fresh worker process per routed ticket.
- Agent sessions register themselves with `remits-cli agent register` or `remits-cli agent serve`; `serve` also starts the local supervisor.
- Tickets are delivered by durable routing on the ticket record, then the agent asks for routed work with `remits-cli agent work`.
- The preferred worker comes from `remits-cli config set --agent claude|codex|gemini`. The default is `claude`.

## Support Tickets

- Support tickets are stored as documents in the `support_tickets` collection.
- New tickets and ticket updates are recorded centrally; local agents receive work by polling for tickets routed to their registered session.
- Think of this as a lightweight local support queue: the platform owns the record and lifecycle verbs, while account components can layer their own helpdesk workflow on top.
- `accountId` / `accountName` identify the account that owns the ticket.
- If present, `implementationAccountId` / `implementationAccountName` identify the platform or product context that owns the shared implementation.
- Worker repo resolution prefers `implementationAccountId` when present, then falls back to `accountId`. If one of those repos is indexed locally in `~/.remits-cli/account-repos.json`, it is used as the worker's directory.
- Agents must resolve account `type` (`PLATFORM`, `PRODUCT`, `CLIENT`) before deciding which local repo to use. A `CLIENT` ticket may still require code changes in a parent `PLATFORM` or `PRODUCT` repo.
- Use `remits-cli ticket` to manage the generic platform ticket lifecycle:

```bash
remits-cli ticket read --ticket 123 --data-mode prod
remits-cli ticket accept --ticket 123 --data-mode prod
remits-cli ticket status --ticket 123 --status in_progress --notes "Investigating logs" --data-mode prod
remits-cli ticket complete --ticket 123 --resolution "Fixed and verified" --data-mode prod
```

- Recommended ticket flow: `read` first, then `accept`, then `status` as work progresses, then `complete`, `ask`, or `release`.

## Logging and State Files

There are two separate state areas:

- Repo-local state in `./.remits-cli/` for request/response artifacts tied to the current working tree.
- Global state in `~/.remits-cli/` for authentication, listener lifecycle, and cross-repo account mapping.

### Repo-local state

- `./.remits-cli/sessions/<current-session>.jsonl`
  Records all `/cli/*` HTTP requests made from the current repo session.
- `./.remits-cli/tool-responses/<callId>.json`
  Stores full tool responses for `remits-cli tool`.
- `./.remits-cli/tools/tools.json`
  Cached tool definitions for the current repo.
- `./.remits-cli/current-session.txt`
  Tracks the active local session log name.

### Global state

- `~/.remits-cli/sessions.json`
  Auth sessions keyed by account ID, base URL, and data mode so local and production sessions can coexist safely.
- `~/.remits-cli/config.json`
  CLI config such as the preferred agent.
- `~/.remits-cli/listener.pid`
  PID for the background remits-cli service process.
- `~/.remits-cli/service-state.json`
  Dashboard URL, repo scan summary, and websocket state snapshot for the running service.
- `~/.remits-cli/account-repos.json`
  Index of known account repositories on this machine, rebuilt by `remits-cli start` via account-info discovery and also refreshed when commands run inside an account repo.
- `~/.remits-cli/agents.json`
  Agent sessions registered from this machine, including the process each one is anchored to.
- `~/.remits-cli/workers.json`
  Active and recent ticket worker state for serving agents.
- `~/.remits-cli/activity.log`
  Human-readable global activity log for service lifecycle, websocket events, agent registration, and ticket routing.

## Control Center

- `remits-cli start` prints or records a localhost dashboard URL such as `http://127.0.0.1:8787/`.
- Open that page in a browser to inspect the full local remits-cli integration state without manually opening JSON files.
- The page refreshes automatically and includes the latest global state files plus per-repo `account-info.json`, local tools snapshot, and current session log tail for every indexed account repo. Large account configuration fields live in `account-configurations.json` and should be opened only when needed.

## Activity Log

- `~/.remits-cli/activity.log` is the quickest way to understand what the service, websocket clients, and local agents are doing.
- It records timestamped lifecycle events such as service start/stop, websocket connect/disconnect, topic subscription, agent registration/heartbeat, ticket routing, worker launch, and worker completion.
- Prompt bodies are not written verbatim to this log. The log stores summarized metadata such as `accountId`, `ticketId`, available keys, and prompt length.
- Typical inspection commands:

```bash
tail -f ~/.remits-cli/activity.log
tail -n 200 ~/.remits-cli/activity.log
```

## Operational Notes

- In sandboxed local agent environments, `remits-cli` network calls may fail with `ENOTFOUND`, `EAI_AGAIN`, `ECONNREFUSED`, `EPERM`, or similar errors even when dispatch worked correctly. That means the command needs escalated permissions or must be run outside the sandbox.
- If the platform returns a 500 or other unexpected server-side failure, stop normal task execution and escalate to a Remits system admin. Agents should not invent workarounds for platform faults.
- Recommended durable update flow for agents: `components stage --workset` for testing, then `git add/commit/push`, then `remits-cli components sync --safe`, then `git pull --ff-only` to confirm platform-generated files like `account-info.json`. To verify the COMMITTED variant rather than your staging, run `components clear --all` first — staged entries still win for CLI-scoped runs.
- In sandboxed agent environments, local git writes may require a single approval step. If you want to minimize approval churn, `remits-cli components commit` consolidates the local git and sync phases into one CLI command.
- If account repo discovery fails for a websocket message, dispatch is skipped because the listener does not know which local directory to open for that account.
- If you authenticate a new account while the listener is already running, the listener now refreshes its websocket clients automatically instead of requiring a manual restart.
- Session logs redact token fields and replace large component content fields with length summaries.
