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