--- name: fathom-doctor description: > Run and interpret `fathom doctor`, the deterministic wiring-diagnosis checklist for a fathom-adopting repo — MCP registration, daemon reachability, binary freshness, the hook stack (installed AND firing), the AGENTS.md stanza and whether Claude Code loads it, shipped skills, config validity, obligations serving, and surface traffic. Use when asked "is fathom actually wired here", when troubleshooting missing or silent fathom behavior, right after `fathom init`, or before trusting a fresh session's tool access. --- ## 1. Run the checklist ```sh fathom doctor [--harness=claude|codex|auto|] [--path ] [--service ] [--url ] [--json] ``` - `--harness` defaults to `auto`: the first harness whose config markers exist (`fathom harness list` shows the registry), else `claude`. Pass it explicitly when you know which harness you are diagnosing. - `--path` defaults to the current directory. `--service` defaults to the identities the hooks probe (the directory's basename, then the git toplevel's), checked against the daemon's service list, so a repository indexed under another name is named rather than guessed. - `--url` defaults to `http://localhost:7575` (or `$FATHOM_HTTP`); doctor only reads from the daemon. - `--json` for machine output; otherwise a table. Exit codes: `0` no row failed; `1` at least one row failed; `2` doctor itself could not run (bad flags, an unresolvable `--path`). ## 2. Read the report honestly Every row is `{name, status, reason, remedy}`. Keep the four statuses apart when you summarize: - **PASS**: verified true; the evidence is in `reason`. - **FAIL**: an observable problem; `remedy` is one command. - **WARN**: worth attention, never fails the exit code (a dead guard, a leftover scratch daemon). - **SKIP**: doctor could not check it (daemon down, no call log, a feature not configured). It is neither a failure nor a pass. Report it as "could not verify: ". **A fresh install, read correctly.** In v0.11.0 a correct `fathom init --skills` usually prints about 60 rows with three FAIL rows that are not wiring faults: | Row | Why it fails on day one | What to do | |---|---|---| | `lefthook_gates` | The repository has no `lefthook.yml` with a `fathom verify` pre-push step | Nothing, unless you want the gate (`fathom-verify` skill) | | `obligations_served` | The obligations layer has never been compiled | Optional, and it spends LLM tokens: `fathom compile --service --dry-run=false` | | `surface_traffic` | No MCP tool call has reached the daemon yet | Make one call (`find_symbol`) after restarting the session | Rows that SKIP on day one and need nothing: `mcp_registration` (until the harness config is readable), `binary_fresh` outside fathom's own checkout, `hooks_firing` and `stanza_loaded` (no session has run yet), the provider rows (`providers`, `compile_layer`, `decision_provider`) with the default provider `none`, and the module-binding rows when no module is bound. The rows that decide whether fathom works: | Row | What it proves | |---|---| | `daemon_reachable` | `GET /healthz` answers | | `mcp_registration` | The harness's MCP config points at `/rpc/agent` (or `/rpc/extended`) | | `hooks_installed` | The hook stack is wired in some settings scope (project, local or user) | | `hooks_firing` | The call log has seen hook traffic: configured is not the same as firing | | `stanza_present` | `AGENTS.md` has a well-formed fathom region; it WARNs when Claude Code will not load `AGENTS.md` (a root `CLAUDE.md` without `@AGENTS.md`, a parent CLAUDE file, the agents-md plugin's `instructionFiles` setting at `claude-md` or `managed-only`, or Claude Code older than 2.1.277). The plugin is `cc-plugin-agents-md@builtin` from Claude Code 2.1.285 and `agents-md@builtin` in 2.1.277 through 2.1.284; its setting is user-global, so fathom never writes it | | `skills_installed` | Every shipped skill is present, fathom-owned and current; each missing one is named | | `wiring_drift` | Hooks, stanza and skills match the shipped template; `fathom fleet reconcile --repo .` shows the diff | | `config_valid` | `.fathom/config.toml` (user and project) validates | | `concerns` | Every registered config concern holds (`fathom config audit` has the evidence) | ## 3. Apply remedies with the operator's approval, one at a time Never run a remedy without saying what it does and getting the operator's go-ahead: - `fathom init [--harness ] [--skills] [--path ]` is idempotent (stanza, hooks, skills; `--json` lists every write); still confirm before writing to the operator's repository. - **Daemon down** (`daemon_reachable`): on macOS the remedy names this machine's launchd label, or `fathom daemon install` when none exists; elsewhere it is `fathom serve-http` under the operator's own supervisor. Never restart a daemon from an agent's own sandboxed shell: hand the operator the exact command. - **A new binary** (`binary_fresh`): the daemon must be restarted on the new build. Never copy over a running daemon's binary, which truncates it. - **A recompile** (`obligations_served`) spends real tokens with a configured LLM provider. `--dry-run` (the default) prints the estimate. Re-run `fathom doctor` after each remedy instead of assuming it worked. ## 4. Prove the session sees it A clean report proves configuration, not that this session loaded it. A session started before registration or before a daemon restart never sees the tools. Make one real call (`find_symbol` on a symbol you know exists); a connection error despite a clean report means "restart this session". To check the edit hook's cost, time one call (the hook's own timeout is 5 s; its payload is capped at about 150 tokens and is empty on a clean file): ```sh time fathom edit-hook <<< '{"tool_input":{"file_path":""}}' ``` Well under a second is healthy. A hook that nears 5 s is dropped by Claude Code on slow runs: file it with `fathom observe` (the `fathom-feedback` skill). ## 5. Report back Give a short PASS/FAIL/WARN/SKIP tally and the remedy for each failure, ready to copy. Never a bare "N checks failed".