# muthr — Agent Instructions
## First Steps
- **Always run `muthr init` first** — config doesn't exist until `muthr init` clones `tappunk/muthr-specs` into `~/.config/muthr/`.
- Running `muthr` with no subcommand shows engine status (same as `muthr engine status`).
## Build & Verify
```bash
cargo build # development build
cargo test # no tests exist yet, but cargo test runs
```
No CI workflows. Release gate (`scripts/release.sh`) runs `cargo fmt --check`, `cargo clippy --all-targets --all-features -- -D warnings`, and `cargo test` before bumping.
Do not run `cargo update` without updating the Nix flake too.
## Rust Toolchain
Edition 2024, MSRV 1.95. Dependency versions pinned to exact semver in Cargo.toml (clap = 4.6.1, tokio = 1.52.3, etc.).
Nix flake at root builds for aarch64-darwin only:
```bash
nix build
nix develop
```
## Architecture
`src/main.rs` dispatches to modules:
| `engine` | mlxcel-server lifecycle (start/stop/status/presets) |
| `sandbox` | per-project Lima VM provisioning and management |
| `services` | persistent muthr-services VM (MCP + SearXNG) |
| `config` | muthr.toml loading, env var overrides |
| `init` | bootstrap config by cloning muthr-specs |
| `ui` | interactive prompts, TTY detection |
| `download` | GGUF model fetching from HuggingFace |
| `model` | mlxcel health checks, model metadata polling |
| `preset` | INI preset file parsing |
| `catalog` | manifest/profile YAML resolution |
| `shutdown` | graceful teardown of all owned components |
CLI commands: `engine`, `sandbox`, `services`, `run` (boots engine + services), `shutdown`, `download`, `completion`, `init`, `config`.
## CLI Conventions
Nested subcommands: `muthr engine start`, `muthr sandbox ls`, etc.
Output formats via `--output` / `-o`: `text`, `json`, `ndjson`. Text mode → stderr; json/ndjson → stdout.
TTY detection: human formatting gated on `ui::is_human_output()` — checks `stderr.is_terminal()`, `NO_COLOR`, `CLICOLOR`, `CLICOLOR_FORCE`.
## Config
Config source: `~/.config/muthr/` — populated by `muthr init`.
```
~/.config/muthr/
├── muthr.toml # main config; env vars override values
├── provider.d/llama/*.ini # inference presets (created by init)
├── manifests/*.yaml # VM YAML templates
├── provision.d/*.sh # boot scripts for VMs
└── clients/opencode-config.json # template for OpenCode runtime config
```
Runtime state: `~/.cache/muthr/` (PID files, logs, generated JSON).
Env var overrides: `MUTHR_SERVER_PORT`, `MUTHR_WORKSPACE_ROOT`, `MUTHR_MODEL_DIR`, `MUTHR_PROVISION_PROFILE`.
## Workspace Context
Sandbox commands resolve VM name from cwd relative to workspace root (default: `~/src`). Project directory name → VM suffix: `muthr-{project-name}`.
Agents must be inside a project directory under the workspace root. Running from outside triggers exit code 64. Special case: `~/.config/muthr/` resolves to `muthr-config`.
## Error Exit Codes
Hardcoded `std::process::exit()` (not returned as Result):
- `64` — usage error (bad flags, missing context, outside workspace)
- `66` — file/target does not exist
- `77` — permission denied (deletion without terminal/force)
- `1` — all other errors via `color_eyre::Report`
## Gotchas
- **`muthr init` is a prerequisite** — config must exist before most commands work.
- **`sandbox start` with no `--profile`** triggers an interactive prompt on stderr. Always pass `--profile`.
- **`muthr init` silently exits** (returns `Ok(())`) if `~/.config/muthr/` already has content — no error, no overwrite unless `--force`.
- **`engine stop` defaults to `llama` engine** (not `mlxcel`) — see `main.rs:327`.
## muthr-specs Dependency
`tappunk/muthr-specs` provides manifests, provision scripts, and preset templates. Run `muthr init` to clone it. Cross-repo changes may require updates in both muthr and muthr-specs.
## Related Repositories
1. **muthr-specs** (`~/src/muthr-specs`) — Lima templates, provision scripts, client config templates.
2. **homebrew-muthr** (`~/src/homebrew-muthr`) — Homebrew tap. Release script auto-updates this.
3. **vitepress-tappunk-com** (`~/src/homepage`) — VitePress source for muthr docs at https://tappunk.com. Deploy output is in `~/src/homepage/github-pages/` (tappunk.github.io).
## Release
`scripts/release.sh [patch|minor|major] [notes]` — validates repo is clean, runs format/clippy/tests, bumps version in Cargo.toml + flake.nix, builds release binary for `aarch64-apple-darwin`, packages `muthr-{version}-bin-macos-arm64.tar.gz`, commits + tags, pushes to Forgejo (staging), publishes GitHub release with assets, updates homebrew tap formula, and runs `cargo publish`.
Pre-release gates: `cargo fmt --check`, `cargo clippy --all-targets --all-features -- -D warnings`, `cargo test`. Must be on `main` branch with no untracked/uncommitted changes.
Local tap mirror at `~/src/homebrew-muthr` is updated automatically if it exists and is clean.