muthr 0.1.53

Zero-trust orchestrator for MLX inference, container-based sandboxes, and MCP services on Apple Silicon
# 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:

| Module        | Responsibility                                    |
| ----------- | ------------------------------------------------- |
| `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.