# Set up Heimdall

For AI coding agents (Claude Code, Codex, OpenCode or another) setting Heimdall up for a user, and for people doing it themselves. Human page: https://tobynoskillson.com/heimdall/docs/

## Rules for agents

- The command is the app itself: `"/Applications/Heimdall Alpha.app/Contents/MacOS/Heimdall" setup` (written `heimdall setup` below). Heimdall must be running.
- Start with `heimdall setup --help` and follow it. Ask the user one question only if `--defaults` can't pick the provider (exit 2 says so).
- Do everything you can yourself. The user makes only the clicks macOS reserves for them and any sign-in; tell them each in one sentence.
- Never put a key on the command line. `--custom-key-env` takes the name of the environment variable that holds it.

## What you need

- A Mac with Apple silicon (arm64 only).
- macOS Sonoma 14.4 or later; macOS 26 recommended.
- 3.78 GB free disk for the models at the defaults, plus 17.4 GB if the agent runs on this Mac.
- One agent: a Codex (ChatGPT), Claude Code or OpenCode Go subscription, this Mac's model (about 20 GB of free memory), or your own OpenAI- or Anthropic-compatible server.

## Install

```sh
brew install --cask tobynoskillson/tap/heimdall-alpha
```

Without Homebrew (replace VERSION with the newest tag from https://github.com/TobyNoSkillSon/Heimdall/releases, for example 0.1.0-alpha.1):

```sh
V=VERSION; cd ~/Downloads
curl -LO "https://github.com/TobyNoSkillSon/Heimdall/releases/download/v$V/Heimdall-Alpha-$V-arm64.zip"
ditto -x -k "Heimdall-Alpha-$V-arm64.zip" /Applications
xattr -dr com.apple.quarantine "/Applications/Heimdall Alpha.app"
open "/Applications/Heimdall Alpha.app"
```

- App: `/Applications/Heimdall Alpha.app`, bundle ID `com.tobynoskillson.heimdall`, about 255 MB to download. Updates come through Homebrew (`brew upgrade --cask heimdall-alpha`) or a newer zip; the in-app updater is off in this alpha.
- The first launch opens Setup. Closing it before it is finished asks to quit; a relaunch reopens it where it was. The menu's Set Up… opens it again later.

## Let the agent set it up

The Welcome page's Let My Agent Set It Up gives the user this line to paste:

```text
Set up Heimdall for me. Run "/Applications/Heimdall Alpha.app/Contents/MacOS/Heimdall" setup --help and follow it.
```

An agent's run:

```sh
heimdall setup --plan --defaults --json
heimdall setup --defaults --open-permissions --json   # exit 2: tell the user each click in one sentence
heimdall setup --wait --json                          # until green or a row needs the user
# exit 2 with only the "phrase" row left: tell the user to say "Heimdall, show me what you can do"
heimdall setup --finish                               # waits for them to say it
```

The command hands its choices to the running app, which applies them through the Setup window's own actions, and reads back the window's checklist. There are no setup tools on Heimdall's MCP server; agents use the command.

| Command | Does |
|---|---|
| `heimdall setup --help` | The short guide for agents: the one question, the commands, the user's clicks |
| `heimdall setup --plan [flags] [--json]` | What would happen (provider, downloads and sizes, the user's clicks); changes nothing |
| `heimdall setup --defaults [flags] [--json]` | Applies the defaults, with any flag given taking precedence |
| `heimdall setup [flags] [--json]` | Applies only the flags given |
| `heimdall setup --check [--json]` | Getting ready's checklist, now: the models, Microphone, Voice, Listening, Decider, Agent, and last the `phrase` row, which only the user can turn green |
| `heimdall setup --wait [--timeout SECONDS] [--json]` | `--check` repeated until all green, a row needs the user, or the timeout (default 1800) |
| `heimdall setup --wizard` | Opens the Setup window |

### Flags

| Flag | Values | Default | Step |
|---|---|---|---|
| `--provider` | `claude-code` · `codex` · `opencode-go` · `local` · `custom` | see below | 3 |
| `--custom-url URL` | the server's base URL | | 3 |
| `--custom-kind` | `openai` · `anthropic` | `openai` | 3 |
| `--custom-key-env VAR` | the name of the environment variable holding the key | none (keyless server) | 3 |
| `--user-name TEXT` | the user's name | none | 2 |
| `--decider-precision` | `4` · `8` · `16` | `4` | 4 |
| `--voice NAME` | one of Phonon S's 25 voices | `Edwin` | 5 |
| `--open-permissions` | Allow All: the macOS prompts appear for the user | | 6 |
| `--home PATH` | an existing folder | the current one | 8 |
| `--t3` | `connect` · `skip` | `connect` with `claude-code` | 9 |
| `--harnesses` | `set` · `leave` | `leave` | 10 |
| `--vella`, `--arsenal` | `add` · `skip` | `skip` | 11, 12 |
| `--name TEXT` | the assistant's name and wake word | `Heimdall` | 13 |
| `--mark NAME` | `helmet` · `sparkle` · `leaf` · `moon.stars` · `bird` · `cat` · `hare` · `flame` · `bolt` · `crown` · `eye` · `atom` (brings its name and voice unless given) | `helmet` | 13 |
| `--finish` | once every row but `phrase` is green, waits (up to `--timeout`, default 1800 s) for the user to say the phrase; exit 0 when they have, 2 if not green yet or timed out | | 14 |
| `--json` | one JSON object per line | | |

Provider under `--defaults`: `claude-code` inside Claude Code (`CLAUDECODE=1`); `codex` inside Codex (`CODEX_HOME` or `CODEX_SANDBOX` set); else none, and the command exits 2. Then ask the user exactly one thing: "Which should run Heimdall's agent: your Claude Code, Codex or OpenCode Go subscription, this Mac (a 17.4 GB model), or a server of your own?" and run again with `--provider`. Everything else takes the window's suggestions (decider 4-bit, Edwin, the name Heimdall, the current home, T3 Code connected for `claude-code`, Vella and Arsenal skipped).

Output: with `--json`, one object per line, `{"step": "...", "state": "done" | "working" | "needs_user" | "failed", "detail": "..."}` (`planned` under `--plan`), the readiness rows last as `"step": "ready:<row>"` with state `ready`, `working`, `needs_user`, `failed` or `optional`. With only `ready:phrase` left, tell the user to say "Heimdall, show me what you can do" (with the assistant's name), then run `--finish`.

| Exit code | Meaning |
|---|---|
| 0 | All green (`--check`, `--wait`), or the choices were handed to the app |
| 2 | Needs the user: a click, a sign-in, the one question, or the phrase; `detail` says which |
| 4 | A provider or key failed |
| 1 | Anything else (Heimdall not running, a bad flag, still working) |

## What only the user can do

| What | Where |
|---|---|
| Microphone (required) | Click Allow in the macOS prompt (after Allow All, or `--open-permissions`); plug one in if there is none |
| Screen Recording (optional) | System Settings ▸ Privacy & Security ▸ Screen Recording: turn on Heimdall Alpha |
| Accessibility (optional) | System Settings ▸ Privacy & Security ▸ Accessibility: turn on Heimdall Alpha |
| System Audio Recording (optional) | Click Allow in the prompt macOS shows after Allow All or the Allow page's row; without it listening runs on the microphone alone |
| A subscription sign-in | Approve in the browser page Heimdall opens (ChatGPT, OpenCode) |
| Claude Code's own sign-in | `claude` in a terminal, once, if it was never signed in |
| T3 Code's Connect | The Connect click (or `--t3 connect`, the user's yes given to their agent) |
| The last step | Say "Heimdall, show me what you can do" (with the assistant's name) when Getting ready asks |

## Setup, step by step

One window, fourteen pages, Back and Continue. Setup ends when every required check is green and the user says one sentence to Heimdall.

1. **Welcome to Heimdall.** Set Up, or Let My Agent Set It Up (shows the line to paste, above).
2. **What should I call you?** Optional; the greeting uses it.
3. **Do you have a subscription, or do you want a local model?** No default; the first one connected becomes the agent, a later one only adds its models.
   - Codex: Sign In… opens ChatGPT's sign-in in the browser; the account's default model becomes the agent's.
   - Claude Code: Add installs T3 Code if missing, connects it and makes Claude Code the agent. Needs Claude Code signed in.
   - OpenCode Go: Sign In… opens OpenCode's device sign-in; Claude Haiku 5.5 becomes the agent's model.
   - This Mac: the built-in Splash engine with Qwen3.8 27B (`huihui-ai/Huihui-Qwen3.8-27B-abliterated-GGUF`, `UD-Q4_K_XL`), 17.4 GB download, about 20 GB of free memory.
   - Custom: an OpenAI- or Anthropic-compatible server, its URL and a key if it needs one. Its `/models` list must answer; its first runnable model becomes the agent's.
4. **How should I listen?** Parakeet (INT8 + FP16, 603 MB). The decider's precision: 4-bit (default; 1.37 GB disk, 2.4 GB RAM; same answer as 16-bit on 474 of 500 test moments), 8-bit (2.10 GB, 3.1 GB, 495 of 500), 16-bit (3.48 GB, 4.2 GB). Continue starts the model downloads.
5. **How should I sound?** One of Phonon S's 25 voices (Edwin default), inside the app. A pick here is kept over a mark's voice.
6. **Allow Heimdall.** Allow All; see "What only the user can do". The Microphone is required; Screen Recording, Accessibility and System Audio Recording are optional, read Optional until allowed and never hold Setup back. When a macOS prompt closes, Setup comes back to the front.
7. **Can you hear me?** The microphone: macOS's default input until the user picks another from the pop-up of connected inputs (saved as the menu's Settings ▸ Microphone). A level meter moves only while sound comes in; it records nothing. With no input: "No microphone found", and Getting ready's Microphone row stays red until one is plugged in or chosen.
8. **Where should I keep my files?** The home folder (default: the user's home); Heimdall's own files go in `<home>/.heimdall`. Choose… picks another; Move and Restart moves them.
9. **Setting up T3 Code.** Install (if missing: newest stable from `github.com/pingdotgg/t3code` into `~/Applications`), Connect (the user's consent). Already done when Claude Code was picked.
10. **Let coding agents work without asking?** Set Up or Leave as Is. Set Up: each coding agent on the Mac runs without asking, except deletes outside the home folder, disk erasing, Keychain access and system settings (refusals enforced for Claude Code).
11. **Do you want dictation with Vella?** Add Vella (32 MB, Homebrew cask `tobynoskillson/tap/vella`; shares Parakeet) or Not now.
12. **Do you want Arsenal?** Add Arsenal (70 MB, cask `tobynoskillson/tap/arsenal`; 102 local models Heimdall can call as tools) or Use it when installed, or Not now.
13. **Customise me.** A mark and the name (also the wake word). Each mark brings its name and voice; a typed name or a picked voice is kept. Helmet Heimdall/Edwin, Sparkle Lumi/Lottie, Leaf Ivy/Everly, Moon Selene/Bryony, Bird Wren/Juniper, Cat Felix/Hugh, Hare Hazel/Pippa, Flame Ember/Delia, Bolt Volta/Russell, Crown Rex/Miles, Eye Argus/Preston, Atom Niko/Micah.
14. **Getting ready.** A checklist (below). There is no Start button: once every required row is green, the card shows "Heimdall, show me what you can do" (with the assistant's name; English). The user says it; Setup closes when Heimdall hears it. Those words are the agent's first message, and it answers with a short spoken demo of what it can do. The phrase also enrols the user's voice; until then only the wake name wakes Heimdall. After about 8 s of silence the card says "Say it a little louder" and keeps listening. Only a truly failed microphone (no input, a capture that didn't start) shows why, its fix (Retry or Choose…) and Start without speaking, which ends Setup with a plain greeting.

## What downloads

From the official Hugging Face repositories at pinned revisions, checked by SHA-256, into `<home>/.heimdall/models`. One at a time, resumed after a dropped connection, retried by itself after a failure.

| Model | Repository @ revision | Size | For |
|---|---|---|---|
| Parakeet | `FluidInference/parakeet-ultra-coreml` @ `95eaa59a` | 632 MB | listening |
| Speakers | `nvidia/Nemotron-3-Diarization` @ `f667ed73`, `soniqo/ReDimNet2-B6-ONNX-FP32` @ `e911e3f0` | 158 MB | who is speaking |
| Decider 4-bit | `Toby-NoSkillSon/heimdall-d1-v6` @ `c015ecf6`, `int4/` | 1.37 GB | when to answer |
| MossFormer2 | `ipsilondev/MossFormer2-SS-16K-ONNX` @ `abd8b126` | 91 MB | separating voices |
| EmbeddingGemma 2 | `google/embeddinggemma-2` @ `914f7f89` | 1.53 GB | memory search |
| **At the defaults** | | **3.78 GB** | |
| Decider 8-bit / 16-bit (instead of 4-bit) | same repository, `int8/` / `bf16/` | 2.10 / 3.48 GB | if chosen |
| Qwen3.8 27B 4-bit | `huihui-ai/Huihui-Qwen3.8-27B-abliterated-GGUF`, `UD-Q4_K_XL` | 17.4 GB | This Mac only |
| T3 Code | `github.com/pingdotgg/t3code`, newest stable | | if missing |
| Vella, Arsenal | Homebrew casks in `tobynoskillson/tap` | 32 MB, 70 MB | if added |

## Ready when (Getting ready's rows)

| Row | Green when | Fix offered |
|---|---|---|
| Each model but the decider | downloaded and its SHA-256 matched | Retry |
| This Mac's model (when chosen) | downloaded and loaded by the engine | Retry |
| Microphone | sound arrived from the chosen input in the last five seconds (ten seconds of silence turn it red) | Choose… ("No microphone found", "No sound from …"); Retry when the capture didn't start |
| Voice | Phonon S loaded with the chosen voice | Retry |
| Listening | Parakeet loaded, listening running and the Microphone row green | Allow… (the microphone), or wait for the models |
| Decider | downloaded and its SHA-256 matched, then loaded and answering | Retry |
| Agent | one real request to the agent's model answered | Choose… (no agent yet), Sign In… (a sign-in failed), Retry |
| Memory search (optional) | its worker loaded and indexed; needs 8 GB free memory, else "Needs 8 GB free memory" in grey (`--check`: `optional`); never holds Setup back | none |
| System audio (optional, only while its ask is out, failed or denied) | never required; nothing once its taps run | Allow… |
| Your words (`phrase` in `--check`) | the user said "Heimdall, show me what you can do" | none: only the user can |
