Docs/Reference/CLI reference

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 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.
fermix chat Alias for fermix ask — identical behavior and flags (a one-shot prompt, not an interactive session).
fermix acp Bridge an ACP client’s standard input and output to the running daemon over the Unix socket (a local channel between processes on the same machine) at ~/.fermix/acp.sock. The client launches it; it never starts a daemon. With no daemon listening it prints one line naming that socket and telling you to start it with fermix run, then exits 1. It never retries — the client decides whether to launch it again.
fermix acp forget NPUB|--all Delete a remembered ACP client identity. --all deletes every record and reports how many. Reads the on-disk store directly, so it works whether or not the daemon is running.
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.
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.
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. Includes a “coding harness” check (vendor CLIs and login state, consent, run counts, artifact quota, and a restart hint when a CLI was installed or removed since the daemon booted) and warns when the installed service unit has drifted from what the current binary would write (fermix setup rewrites it). The daemon-socket check warns rather than passes when the daemon is running a different version than the installed binary. An “acp surface” row reports whether ACP clients are accepted: when they are, it names the socket path and whether the listener is actually up (asked of the daemon, not probed locally); when they are not, it reports only disabled. Either way it lists every remembered client identity with the time it was last seen, because disabling the surface deletes none of them, and it never prints key material. A “cosign” row reports whether the signature verifier cosign is on your PATH, because fermix upgrade and fermix plugins install both refuse without it. A “home perms” row fails when ~/.fermix is not mode 0700 (readable only by you). A “skill curation” row names the private conversation skill proposals are delivered to, and warns when there is none. A “place search” row reports whether the shared Brave key is set and the place_search tool is advertised — offline, no network call. A “channel streaming” row lists every configured channel that streams and the mode in effect, and warns when a channel is set to draft but cannot edit a message in place, because that setting is ignored at runtime. Where a channel’s mode is written out in config.toml and differs from the one that channel would derive from its own capabilities, the row names the derived value alongside it, so a hand-written key that shadows a different default stays visible; an explicit value equal to the derived one is not flagged. On macOS a “browser” row reports whether the browser tool can launch Chrome: it names the Chrome it found when the launch helper is present and working, warns when no Chrome or Chromium is installed, and fails when the helper is missing or refuses to run — while it fails, every browser launch refuses loudly rather than starting Chrome anyway. On other operating systems the row records that the helper is not required. With --full, a separate “place probe” row makes one live, metered request to the place endpoint and names auth, rate-limit, schema, and network failures independently.
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.
--acp-enabled / --no-acp-enabled Accept or refuse ACP clients. Accepted by default.
--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.

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:

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 [--stdin] Store a static API key for an api_key-auth plugin (keychain-secured). Prompts on the terminal with the typing hidden; --stdin reads the key from a pipe instead. Passing the key as an argument is refused with exit code 2.
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. Any argument to fermix acp other than forget is a usage error too: it prints the usage lines on standard error and exits 2, and never falls through to the bridge.
3 Daemon is not running. Returned by the commands that need it: status, health, ask/chat, agents, capabilities, skills.

fermix acp is not in that last set: with no daemon listening it exits 1, after printing the socket path and the fermix run that starts one.

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, and the ACP socket at ~/.fermix/acp.sock, both with the same permissions. None of these sockets is reachable over the network.

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), fermix doctor reports the unit as stale and names the fix: re-run fermix setup, which rewrites and reloads the unit — something a plain restart never does — without a manual fermix service install.

See 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. ACP clients are the exception: that surface has no commands, so a message starting with / reaches the model as ordinary text.

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. At most 8 run at once daemon-wide; past that the command is refused with a message naming the limit, never queued.
/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. It also cancels every active local coding-agent run, including one a scheduled job started; a stopped run reports as cancelled and never auto-continues, and Codex cloud run tracking is not touched. Scheduled jobs themselves 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.
/skills [review|proposals|approve TOKEN|deny TOKEN|list|archive NAME|unpark TOKEN|restore [NAME]] Operator-only skill curation. /skills review runs a curation pass now; /skills proposals lists pending, denied, and parked proposals; /skills approve TOKEN and /skills deny TOKEN action one; /skills list shows your skills with usage counters; /skills archive NAME, /skills unpark TOKEN, and /skills restore [NAME] manage what curation made. review, proposals, and list print your own mined history, so they run only in a direct chat or the CLI.

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 and 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.

# 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.

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.

# 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.

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 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.

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.

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.

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

See traces and telemetry.

Next steps