# CLI reference

> Complete reference for the fermix binary subcommands, flags, exit codes, and developer Mix tasks.

This page lists every `fermix` command and flag. Most subcommands do their job and exit right away. Only `run` keeps the daemon (the long-running background process) in the foreground, and `setup` starts the system up far enough to write its initial prompt files before exiting.

## Subcommands

| Command | Description |
|---------|-------------|
| `fermix setup [flags]` | Run the setup wizard. See [Setup flags](#setup-flags) below. |
| `fermix run` | Start the daemon in the foreground. Boots the full system, binds the web endpoint, daemon socket, and Realtime socket, then streams logs. Used by OS service units (the files that tell the operating system how to run Fermix in the background). |
| `fermix service install [--user\|--system]` | Write and enable the OS service unit (launchd `.plist` on macOS, systemd `.service` on Linux). |
| `fermix service uninstall [--user\|--system]` | Remove the OS service unit. |
| `fermix start [--user\|--system]` | Start the installed OS service. |
| `fermix stop [--user\|--system]` | Stop the installed OS service. |
| `fermix restart [--user\|--system]` | Restart the installed OS service. |
| `fermix status [--full] [--json]` | Print daemon and overview status via the control socket. Warns when the running daemon's version differs from the installed binary. Exits `3` if the daemon is not running. |
| `fermix health [--json]` | Daemon-evaluated health (config paths, provider status, channel status, memory backend, Realtime voice). |
| `fermix voice status [--json]` | Show local Realtime voice companion status. |
| `fermix agents [--json]` | Show MainAgent and worker status. |
| `fermix capabilities [--kind builtin\|skill\|mcp] [--json]` | List registered capabilities (the tools the agent can use), optionally filtered by kind. |
| `fermix ask <text>` | Send one prompt to the running daemon and print the MainAgent reply. See [ask / chat flags](#ask--chat-flags). |
| `fermix chat` | Alias for `fermix ask` — identical behavior and flags (a one-shot prompt, not an interactive session). |
| `fermix logs [-f] [-n LINES]` | Show or follow the daemon log file at `~/.fermix/logs/fermix.log`. |
| `fermix auth login [--provider codex\|anthropic\|xai] [flags]` | Start the OAuth login flow (sign in to a provider in the browser instead of pasting an API key). Default provider is Codex. Anthropic accepts `--setup-token TOKEN` or `--import-claude-code`; xAI uses a browser PKCE flow (a secure browser sign-in). See [auth flags](#auth-flags). |
| `fermix auth status [--provider codex\|anthropic\|xai]` | Show stored OAuth credentials for the given provider (default: codex). |
| `fermix auth logout [--provider codex\|anthropic\|xai]` | Remove stored OAuth tokens and revert the provider to API-key mode. |
| `fermix skills [list\|view NAME\|reload] [--json]` | Inspect and reload installed skills without a daemon restart. |
| `fermix plugins <subcommand> [--json]` | Manage plugins. See [plugins subcommands](#plugins-subcommands). |
| `fermix memory review --now [--conversation channel:id] [--json]` | Trigger an immediate background memory review, rebuilding USER.md and MEMORY.md. |
| `fermix memory restore ID [--json]` | Restore a previous memory row by ID. |
| `fermix upgrade [--check]` | Self-update from signed releases. `--check` prints available version without installing. |
| `fermix doctor [--full]` | Post-install diagnostics. `--full` adds network reachability checks. The daemon-socket check warns rather than passes when the daemon is running a different version than the installed binary. |
| `fermix sandbox <subcommand>` | Manage sandbox config (the safety boundary on which files and commands tools may touch). Subcommands: `status`, `explain`, `mode <mode>`, `env` (`allow`/`deny`/`set`/`get`/`unset NAME`), `commands profile <profile>`, `commands enable`/`disable <preset>`, `command list`, plus the `grant`/`revoke` forms below (also reachable as `fermix sandbox grant`/`revoke`). |
| `fermix grant path <path>` | Allow tool access to a specific path (adds it as an allowed sandbox root). |
| `fermix grant command <name> -- <cmd> [args...]` | Allow a specific command to run as a tool. |
| `fermix revoke path <path>` | Remove a previously granted path. |
| `fermix revoke command <name>` | Remove a previously granted command. |
| `fermix version` | Print the release version. |
| `fermix help` | Print top-level usage. |

## Setup flags

`fermix setup` is the single entry point for first-run configuration. It installs and starts the OS service, then opens the browser setup at `http://127.0.0.1:4030/setup`. On a headless host (a machine with no desktop or browser, such as a remote server) it runs a terminal wizard instead.

| Flag | Effect |
|------|--------|
| `--web` | Force the browser setup even on a headless host (prints an SSH port-forward hint when no display is available). |
| `--cli` / `--terminal` | Force the terminal wizard even when a browser is available. |
| `--no-browser` | Print the setup URL instead of opening it. |
| `--no-service` | Configure without installing the OS service. |
| `--reconfigure` | Force the provider, model, and effort (how hard the model thinks) prompts again (a plain rerun with no flags is safe and only fills in missing prompt files). |
| `--print-state` | Print the current persisted setup state and exit. |
| `--migrate-secrets` | Migrate secrets to the current keychain layout. |
| `--import-codex` | Import OAuth tokens from the Codex CLI into the provider token store. |
| `--realtime-enabled` | Enable the local Realtime voice companion. |
| `--realtime-api-key <key>` | Set the OpenAI Realtime API key non-interactively. |
| `--realtime-voice <voice>` | Override the Realtime voice. |
| `--realtime-persist-transcripts` | Persist voice-session transcripts. |
| `--realtime-max-session-minutes <n>` | Per-session voice duration cap. |
| `--realtime-max-cost-cents <n>` | Per-session estimated cost cap in cents. |
| `--transcription-backend <backend>` | Select the speech-to-text backend (`openai`, `xai`, `deepgram`). |
| `--transcription-model <model>` | Override the transcription model. |
| `--transcription-api-key <key>` | Set the API key for the selected transcription backend (stored under that backend's slot — the `--transcription-backend` value if given, otherwise the backend already configured). |
| `--openai-api-key <key>` | Set the OpenAI API key non-interactively. |
| `--telegram-bot-token <token>` | Set the Telegram bot token non-interactively. |

Additional per-provider and per-channel flags follow the same `--<key> <value>` pattern. There is no per-subcommand help: `fermix help`, `--help`, and `-h` all print the same top-level usage, whose `fermix setup` line is truncated, and `fermix setup --help` is rejected as an invalid option.

`fermix setup` also self-heals a drifted service unit: when an installed unit no longer matches what the current binary would write (for example, after an upgrade changed the `PATH` template), setup rewrites and reloads the unit automatically. A manual `fermix service install` is an escape hatch, not a required post-upgrade step.

For a full walkthrough, see [setup](/docs/setup).

## ask / chat flags

| Flag | Effect |
|------|--------|
| `--stdin` | Read the prompt from stdin instead of the positional argument. |
| `--session <name>` | Route the turn to a named session instead of the default. |
| `--timeout <ms>` | Override the per-turn timeout in milliseconds. |
| `--json` | Emit the reply as a JSON object. |
| `--attach <path>` | Attach a local image to the turn (`.png`/`.jpg`/`.jpeg`/`.gif`/`.webp`; repeatable; ~20 MB cap per file). |

Example:

```bash
fermix ask "say pong"
fermix ask --session scenario-web-fetch "validate web_fetch localhost rejection"
fermix ask --attach screenshot.png "what is in this image?"
echo "summarize current health" | fermix ask --stdin --json
```

## auth flags

`fermix auth login` defaults to the Codex (OpenAI) OAuth flow. Pass `--provider` to target a different provider:

| Provider | Login mechanism |
|----------|----------------|
| `codex` (default) | Browser-based Authorization Code + PKCE against `auth.openai.com`. Flags: `--no-browser`, `--port N`, `--timeout SECONDS`. |
| `anthropic` | Requires `--setup-token TOKEN`, `--import-claude-code`, or `CLAUDE_CODE_OAUTH_TOKEN` in the environment. Sets `auth_mode = oauth` in config. |
| `xai` | Browser-based PKCE flow for the Grok Build subscription. Sets `auth_mode = oauth` in config. Flags: `--no-browser`, `--port N`, `--timeout SECONDS`. |

`fermix auth status` and `fermix auth logout` also accept `--provider codex|anthropic|xai`. Logout reverts the provider's `auth_mode` to `api_key`. Restart the daemon after any auth change.

## plugins subcommands

`fermix plugins` manages the local plugin store under `~/.fermix/plugins/`. Bundled plugins (Gmail, Google Calendar, Google Drive) cannot be uninstalled; use `disable` instead.

| Subcommand | Description |
|-----------|-------------|
| `list` | Show all plugins with status and connected account. |
| `catalog` | Show the full signed catalog with auth type and category. |
| `installed` | Show locally installed plugin versions. |
| `enable NAME` | Enable a plugin (auto-installs from the catalog if not present). |
| `disable NAME` | Disable a plugin. Takes effect on the daemon's next turn. |
| `doctor [NAME]` | Health check one or all plugins. |
| `reload` | Reload plugin state into the running daemon without a restart. |
| `install NAME[@VERSION]` | Install a plugin from the signed catalog. |
| `upgrade NAME` | Upgrade an installed plugin to the latest catalog version. |
| `pin NAME@VERSION` | Install and pin a plugin at a specific version. |
| `uninstall NAME` | Remove an installed plugin (non-bundled only). |
| `gc` | Remove orphaned plugin artifacts from the local store. |
| `auth login NAME` | Connect an OAuth plugin. Also: `reauthorize`, `refresh`, `logout`. |
| `auth set NAME VALUE` | Store a static API key for an `api_key`-auth plugin (keychain-secured). |
| `auth clear NAME` | Remove a stored API key. |
| `auth status [NAME]` | Show OAuth status for one or all plugins. |
| `config NAME` | Show manifest-declared config keys and current values for a plugin. |
| `config set NAME KEY VALUE` | Set a manifest-declared config value (injected into the plugin's process env for MCP plugins). |

## Exit codes

| Code | Meaning |
|------|---------|
| `0` | Success. |
| `1` | Runtime error (the command ran but failed). |
| `2` | Usage error — unknown command, or missing/invalid flags. `fermix upgrade` also exits `2` when it refuses to mutate a package-manager install. |
| `3` | Daemon is not running. Returned by the commands that need it: `status`, `health`, `ask`/`chat`, `agents`, `capabilities`, `skills`. |

## Daemon socket

When the daemon is running (via `fermix run` or an installed service), CLI clients communicate with it through the Unix socket (a local channel between processes on the same machine) at `~/.fermix/daemon.sock`. The protocol is length-prefixed JSON: each request and reply is a JSON payload preceded by a 4-byte length header, up to 4 MiB per frame. The socket is created with permissions `0600` (readable and writable only by the owner). The Realtime voice socket, when enabled, lives at `~/.fermix/realtime.sock` with the same permissions.

## Service scope

`--user` scope (the default) requires no elevated privileges and sets up a per-user service. On Linux, it enables `loginctl enable-linger` (a setting that lets your service keep running while you are logged out) so the service survives logout. `--system` scope starts at boot and requires sudo.

## upgrade behavior

`fermix upgrade` detects package-manager installs (Homebrew, dpkg) and refuses to mutate them. It prints the correct `brew upgrade` or `apt upgrade` command, names the `fermix restart` that has to follow it, and exits non-zero. For unmanaged installs, the sequence is: fetch, verify (sha256 + cosign), snapshot to `~/.fermix/.previous`, atomic rename, daemon restart, health check. If the post-swap health check fails, the previous binary is restored from `~/.fermix/.previous`.

A package-manager upgrade only swaps the binary on disk — the daemon keeps running the old version until you run `fermix restart`. `fermix status` and `fermix doctor` warn while the running daemon's version differs from the installed binary. If the service unit drifted across the upgrade (for example, an updated `PATH` or template), re-run `fermix setup` instead: it rewrites and reloads the unit — which a plain restart never does — without a manual `fermix service install`.

See [distribution and upgrade](/docs/distribution-and-upgrade) for more detail.

## Channel commands

These plain-text commands work in every channel (Telegram, Slack, and so on) and locally through `fermix ask` / `fermix chat`.

| Command | Description |
|---------|-------------|
| `/compact` | Summarize the current conversation window and keep the summary in history. |
| `/new` | Clear the current conversation history. |
| `/clear` | Alias for `/new`. |
| `/help` | List available commands. |
| `/whoami` | Show the stable channel user ID used for command authorization. |
| `/background` | Run the current request as a durable background job. |
| `/bg` | Alias for `/background`. |
| `/tasks` | List in-flight background tasks for this channel. |
| `/stop` | Emergency stop — cancels every active turn, clears queued messages, and stops background work across all conversations. Scheduled jobs and Realtime voice are unaffected. |
| `/pause` | Pause computer use and hand the cursor and keyboard back to you (the session stays alive). Owner-only. |
| `/resume` | Resume a paused computer-use session. Owner-only. |
| `/ultra` | Run the next turn in exhaustive multi-agent mode (spreads the work across more helper agents for a deeper but slower answer). |
| `/sandbox` | Inspect and adjust the workspace sandbox (allow/deny/set env, command presets, path grants). |
| `/grant path PATH` | Add an allowed sandbox root. Owner-only; may require `/confirm`. |
| `/revoke path PATH` | Remove a previously granted path. Owner-only. |
| `/confirm TOKEN` | Confirm a pending sandbox change or directory-access request. Owner-only, single-use, origin-bound, and valid for 60 seconds. |
| `/soul [review\|apply\|diff\|history\|revert\|reset]` | Operator-only persona curation. Bare `/soul` shows current revision; `/soul review [instruction] [--with-context]` drafts an edit; `/soul apply TOKEN` applies a draft; `/soul history`, `/soul revert N`, `/soul reset` manage revisions. |

Mutating commands outside the local CLI require a per-channel owner configured in `~/.fermix/config.toml`. Use `/whoami` from the target account to discover the user ID, then persist it with `fermix setup --reconfigure` or by editing config directly. See [channels](/docs/channels) and [ingress and trust](/docs/ingress-and-trust).

## Developer Mix tasks

These tasks are available in the source tree (not in the packaged binary) and are the primary development workflow interface.

### mix fermix.dev

The dev mirror of `fermix run`. Boots core, channels, and web in one process with the daemon control socket, Realtime voice socket, and web endpoint enabled. `fermix ask`, `fermix status`, channel pollers (the parts that check each channel for new messages), and the macOS voice companion all attach to the same process.

```bash
# Full stack
FERMIX_HOME=~/.fermix-dev \
OPENAI_API_KEY=sk-... \
FERMIX_REALTIME_ENABLED=true \
mix fermix.dev

# Attached shell
iex -S mix fermix.dev
```

| Flag | Effect |
|------|--------|
| `--no-channels` | Skip Telegram, WhatsApp, Slack, Discord, and Signal adapters. |
| `--no-realtime` | Skip the Realtime voice socket. |
| `--no-web` | Skip the Phoenix endpoint. |

On startup, the daemon prints a readiness banner showing what actually started. If a layer is not configured, the banner shows the reason rather than crashing.

Two Fermix instances checking the same Telegram bot token for messages collide and produce `409 Conflict` errors. Use a distinct bot token for each `FERMIX_HOME`. If secrets are stored in the OS keychain, set a distinct `[fermix_core] profile` (for example, `profile = "dev"`) in the non-default install so its keychain entries are kept separate.

### mix quality

The canonical "does everything pass" command. Runs format check, `compile --warnings-as-errors`, `credo --strict`, `dialyzer`, and `test` in sequence. The git pre-commit hook enforces the same gates.

```bash
mix quality
```

### mix fermix.bench

Deterministic latency benchmark harness using a mock provider and `Req.Test` channel stubs. Does not call real LLMs or external networks.

```bash
# List available scenarios
FERMIX_HOME=~/.fermix-dev mix fermix.bench --list

# Run with output
FERMIX_HOME=~/.fermix-dev mix fermix.bench --output=bench/current.json

# Run specific scenarios with custom sample counts
FERMIX_HOME=~/.fermix-dev mix fermix.bench \
  --scenarios=shared_text_minimal \
  --samples=1000 \
  --warmup=20 \
  --output=bench/current.json

# Run adapter and E2E scenarios
FERMIX_HOME=~/.fermix-dev mix fermix.bench \
  --scenarios=telegram_send_short_text,telegram_e2e_text \
  --samples=200 \
  --warmup=10 \
  --output=bench/adapter.json

# Soak test
FERMIX_HOME=~/.fermix-dev mix fermix.bench.soak --output=bench/soak.json

# Diff two runs
mix fermix.bench.diff bench/baseline.json bench/current.json
```

Use `--compare=bench/baseline.json` with `mix fermix.bench` to print the p95 delta table (the change in the 95th-percentile, near-worst-case, latency) inline after the run. Relative paths are resolved from the umbrella root.

### mix fermix.resource.*

Inspect and manage versioned prompt and memory resources. These are Mix tasks, not binary subcommands.

```bash
mix fermix.resource.list
mix fermix.resource.history user_md --limit 10
mix fermix.resource.show user_md 3
mix fermix.resource.diff user_md 2 3
mix fermix.resource.rollback user_md 2
```

Use `--scope <conversation-key>` for checkpoint resources. Checkpoint revisions are audit records only and do not support rollback. Rolling back `USER.md` or `MEMORY.md` restores the file-backed prompt resource, but future memory rebuilds can overwrite the file if the underlying promoted memories are unchanged.

See [resource versioning](/docs/resource-versioning) for the full model.

### mix fermix.eval.matrix

Prints the provider-by-model matrix that the capability evaluation sweeps over, as JSON on stdout. It reads the in-code provider and model registries only — no daemon, socket, or network — so it is safe to run in any state. Part of the repo's tracked `benchmark/` evaluation harness.

```bash
mix fermix.eval.matrix
```

### mix fermix.eval.transcription

Runs the bundled audio fixtures (`apps/fermix_core/priv/eval/transcription/`) through the speech-to-text backends you have configured and grades each transcript by keyword recall — every expected keyword is looked for as a substring of the cleaned transcript, so punctuation and capitalization differences between backends do not count against it.

```bash
mix fermix.eval.transcription
mix fermix.eval.transcription --backend openai --threshold 0.9
```

`--backend openai|xai|deepgram` limits the run to one backend; an unknown name is an error. `--threshold` sets the recall a fixture must clear to pass (default `0.8`).

This is a live eval: it uploads the sample audio to the real transcription APIs, so it costs API credits and needs network access. It is deliberately not part of `mix test`. It reads your configuration from `FERMIX_HOME` without starting the daemon. With no backend configured it prints "No transcription backend configured — set one via `fermix setup`." and exits `0`; it exits non-zero when any fixture scores below the threshold.

## Logs

The daemon writes to a rotating log file at `~/.fermix/logs/fermix.log` (10 MB per file, 5 files retained by default). Structured JSONL traces are written separately under `~/.fermix/traces/YYYY-MM-DD/<type>.jsonl`. Override paths with `FERMIX_LOG_FILE` and `FERMIX_TRACE_DIR`.

```bash
fermix logs          # print recent lines
fermix logs -f       # follow (tail -f equivalent)
fermix logs -n 200   # print last 200 lines
```

See [traces and telemetry](/docs/traces-and-telemetry).
