# pi-team troubleshooting

Every failure or warning line `pi-team doctor`, `pi-team init`, `pi-team install`, and `/team on` can print — what it means, and how to fix it. Run `pi-team doctor` first; it prints most of these in one shot.

- [Platform support](#platform-support)
- [Prerequisite lines (bun / pi / git)](#prerequisite-lines)
- [`/team on` won't start](#team-on-wont-start)
- [Install / doctor lines](#install--doctor-lines)
- [Install refusals](#install-refusals)
- [`pi-team init` messages](#pi-team-init-messages)
- [`/team finalize` won't finish](#team-finalize-wont-finish)
- [`pi-team smoke`](#pi-team-smoke)
- [Agents launch but never respond (API keys)](#agents-launch-but-never-respond)

---

## Platform support

pi-team's last line from `doctor`/`init` states your platform:

| Line | Meaning |
|---|---|
| `platform: darwin — supported` | macOS is the supported target. Everything works, including the terminal window fan-out. |
| `platform: linux — best-effort (untested — expect rough edges; please report issues)` | The core (CLI, extension, coms-net, worktrees) runs, but the multi-window launcher fan-out is macOS-only and Linux is untested. |
| `platform: <other> — unsupported` | Windows and other platforms are not supported. Use macOS (or Linux, best-effort). |

pi-team **never hard-fails** on platform — it reports and continues. The window fan-out that opens one terminal per agent is macOS-only (`osascript`).

---

## Prerequisite lines

pi-team needs three tools: **Bun**, the **Pi CLI**, and **git**. `doctor`, `init`, and the first `/team on` all check them and print the exact install command when one is missing. pi-team **never installs anything for you** — it only tells you the command.

| Line | Fix |
|---|---|
| `Bun: found` | ✅ nothing to do. |
| `Bun: missing — install with: curl -fsSL https://bun.sh/install \| bash` | Run that command, then re-open your shell. |
| `Pi CLI: found` | ✅ nothing to do. |
| `Pi CLI: missing — install with: npm install -g @mariozechner/pi-coding-agent` | Run that command (needs Node/npm). |
| `git: found` | ✅ nothing to do. |
| `git: missing — install with: xcode-select --install` | macOS: run that command to install the Command Line Tools. |
| `git: missing — install with: install git with your distro package manager (e.g. sudo apt-get install git)` | Linux: install git via your package manager. |
| `git: missing — install with: install git from https://git-scm.com/downloads` | Other platforms: download git from that URL. |

The remediation line is **identical** wherever it appears (CLI doctor, CLI init, and the in-session `/team on` error) — that's guaranteed by construction, so you only ever have to learn one command per tool.

---

## `/team on` won't start

If a prerequisite is missing, the first `/team on` of a run fails closed rather than starting a broken team:

```
pi-team cannot start — missing required tool:
  Bun: missing — install with: curl -fsSL https://bun.sh/install | bash
Install the tool(s) above and re-run /team on. pi-team never installs anything for you.
```

**Fix:** install the listed tool(s) using the exact line shown, then re-run `/team on`. (The header reads `missing required tool:` for one missing tool and `missing required tools:` for two or more — never `tool(s):`; the `Install the tool(s) above` line below it is a fixed string.)

Other `/team on` situations:
- **It prompts "What should the team do?"** — you ran `/team on` with no subject. Type a task, preset, or workflow name (or run `/team on "your task"` directly).
- **Lead mode activates but no agents start** — you gave a bare preset name with no task; that's expected (bare presets launch without an initial prompt). Use `/team send` or `/team add <specialist> <task>` to give work, or start with a plain-language task.

---

## Install / doctor lines

`pi-team doctor` prints one line per install component. Here's what each state means.

**Command symlinks** (`pi-team shim:` and `pi- launcher:`):

| Line | Meaning → fix |
|---|---|
| `installed (<dest> -> <source>)` | ✅ healthy symlink. |
| `missing` | Not installed → run `pi-team install`. |
| `source missing (<source>)` | The checkout the symlink came from moved or was deleted → re-run `pi-team install` (or `pi-team repair`) from the current checkout. |
| `foreign non-symlink (<dest>)` | A real file (not a symlink) already occupies that path → remove it, or run `pi-team install --force` / `pi-team repair`. |
| `foreign symlink (<dest> -> <target>)` | A symlink points somewhere other than this checkout → `pi-team repair` to re-point it. |

**Extension:**

| Line | Meaning → fix |
|---|---|
| `extension source: found <path>` | ✅ the extension is present in the checkout. |
| `extension source: missing <path>` | The checkout is incomplete → re-clone or fix the checkout. |
| `extension registration: registered` | ✅ Pi will load `/team`. |
| `extension registration: not registered` | Pi doesn't know about the extension → run `pi-team install`. |

**Shell PATH block:**

| Line | Meaning → fix |
|---|---|
| `managed (<rc>)` | ✅ pi-team's PATH block is present and correct. |
| `healthy (unmanaged, <rc>)` | ✅ your rc already puts the prefix on PATH (you added it yourself) — pi-team left it alone. |
| `missing (<rc>)` | No PATH entry for the install prefix → run `pi-team install` (it adds the block) or add the prefix to PATH yourself. |
| `stale, different prefix (<rc>)` | The managed block points at a different prefix than doctor is checking → run `pi-team repair` (or `install --prefix`). |
| `malformed (<rc>)` | The `# >>> pi-team installer >>>` / `# <<< pi-team installer <<<` markers are broken → hand-edit the rc file to fix or delete the block, then `pi-team install`. |
| `unreadable (<rc>): <error>` | pi-team couldn't read your rc file (permissions, or it's a directory) → fix the file, then re-run. |

**`pi- on PATH:`**

| Line | Meaning → fix |
|---|---|
| `found` | ✅ the `pi-` launcher resolves on PATH. |
| `missing` | The install prefix isn't on your PATH **in this shell** → open a new terminal (so the rc block loads) or `source ~/.zshrc`. |

---

## Install refusals

`pi-team install` is deliberately non-destructive. It refuses rather than clobber:

| Line | Fix |
|---|---|
| `pi-team: refusing to relink existing symlink to a different source: <dest> -> <current>` | A symlink already points elsewhere. Re-run with `--force`, or `pi-team repair`, if you really want to repoint it. |
| `pi-team: refusing to overwrite non-symlink: <dest>` | A real file occupies the target. Re-run with `--force`, or `pi-team repair`, to replace it. |
| `pi-team: malformed pi-team managed block in <rc>` | The PATH-block markers in your rc are broken. Hand-fix or delete the block, then re-install. |
| `pi-team: missing source script: <source>` | The `scripts/pi-team` source is gone — your checkout is incomplete. Re-clone. |
| `pi-team: invalid JSON in Pi settings: <path>` | `~/.pi/agent/settings.json` isn't valid JSON. Fix the JSON, then re-run install. |
| `pi-team: unknown command: <cmd>` | Typo — run `pi-team help` for the command list. |
| `pi-team: unknown option: <arg>` | Typo in a flag — run `pi-team help`. |

`pi-team uninstall` similarly **leaves foreign files in place** and warns (`leaving non-symlink command in place`, `leaving foreign symlink in place`, `leaving malformed PATH block in place`) rather than deleting something it didn't create — remove those by hand if you want them gone.

---

## `pi-team init` messages

`pi-team init` is idempotent — re-running it only prints `ok:` skip lines.

| Line | Meaning |
|---|---|
| `created: <path>/.pi/team-lead.yaml (commented starter — edit to override defaults)` | ✅ seeded a fresh config. |
| `ok: <path> already exists; leaving it untouched` | Config already there — nothing changed. |
| `updated: added pi-team init block (...) to <path>/.gitignore` | ✅ added `.pi/team-lead/` and `.worktrees/` to `.gitignore`. |
| `ok: <path> already has the pi-team init block; leaving it untouched` | `.gitignore` already had the block. |
| `pi-team: not a git repository; skipped .gitignore. When this becomes a repo, ignore: .pi/team-lead/, .worktrees/` | You ran `init` outside a git repo. The config is still seeded; add those two `.gitignore` entries once the directory becomes a repo. |

Run `pi-team init --dry-run` first to preview every write without touching disk.

---

## `/team finalize` won't finish

`/team finalize` fails closed — it won't push a half-finished run:

| Message | Fix |
|---|---|
| `pi-team cannot finalize <run>: worktree has uncommitted changes — commit or discard them first: <paths>` | Commit or discard the listed changes in the shared worktree, then re-run `/team finalize`. |
| `pi-team has nothing to finalize: <branch> has no commits ahead of <base>.` | The team hasn't committed any work yet. There's nothing to push. |
| Output contains `no remote — push manually: <git push command>` | The repo has no git remote. Finalize still completed locally; run the printed `git push` command to publish the branch. |
| Output contains `PR not opened (gh failed) — run: <gh pr create command>` | `gh` was present but the PR call failed. Run the printed `gh pr create` command yourself. |
| Output contains `PR not opened — run: <gh pr create command>` | `gh` (the GitHub CLI) isn't installed. Install it, or run the printed `gh pr create` command after installing. |

`/team finalize` **never merges, force-pushes, or removes the worktree**. Cleanup of the worktree is a separate, explicit step: `/team tidy --apply`. Re-running `finalize` on an already-finalized run just reports the recorded outcome.

---

## `pi-team smoke`

`pi-team smoke` runs **operator-only real-agent** tests and is gated hard.

| Line | Meaning |
|---|---|
| `pi-team: smoke script not found: <path> ... The real-agent smokes ship only in a repo checkout, not the published package.` | You're running from an installed package, not the repo checkout. The smokes are checkout-only. |
| `gate now: NOT satisfied — a real run would refuse` | (dry-run) A real run is blocked. |
| `gate needs: PI_TEAM_REAL_SMOKE=1 AND a provider key ...` | To run for real, set `PI_TEAM_REAL_SMOKE=1` **and** export a provider key (`OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `GEMINI_API_KEY` / `OPENROUTER_API_KEY`). Only the variable **name** is checked — never the value. |

Always start with `pi-team smoke all --dry-run` — it prints the full plan and spawns nothing. A real smoke launches real Pi agents and spends tokens; it is not part of `bun test` or `pi-team e2e`.

---

## Agents launch but never respond

If a team starts but agents produce auth errors or never reply, the usual cause is **missing API keys in the environment**. Pi does **not** auto-load `.env` files — the provider key must already be in the shell environment when `pi` launches.

- Copy the template and fill in a key: `cp .env.sample .env`, then edit `.env`.
- Source it before launching: `source .env && pi` (or use `just pi`, which loads `.env` automatically).
- **Silent-blank gotcha:** if you resolve keys through a secret manager (e.g. 1Password) that is **locked**, the resolver can return an empty value with a success exit code — the key looks "set" but is blank, and agents fail with auth errors. Unlock the secret manager and re-launch. Verify a key is present without printing it: `[ -n "$ANTHROPIC_API_KEY" ] && echo present`.

For the coms-net hub specifically: a non-loopback bind (`0.0.0.0`, LAN/remote) refuses to start unless `PI_COMS_NET_AUTH_TOKEN` is set. Localhost binds generate a token automatically.

---

## Still stuck?

- Run `pi-team doctor` and `/team doctor` (the in-session one) — between them they surface hub health, agent availability, worktree state, prerequisites, and recent errors.
- See [`commands.md`](commands.md) for what each command expects.
- File issues against the repo (see the [README](../README.md) for the repo link).
