Skip to content
Back to skills

Herdr Orchestrate Pi

ASecurity

Herdr master-orchestrator, all-pi harness. Fire when inside a herdr pane (HERDR_ENV=1) and the captain hands over a spec, feature, or read-only evaluation to orchestrate — and the run should stay in the pi harness (captain says pi, or pi is the project default). Mixed-harness runs go to herdr-orchestrate instead.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 29, 2026
ai-agentsrustgoswiftbashdebugginggitfrontendbackend

Works with

  • mcp

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add alexhooi/herdr-orchestrate --skill herdr-orchestrate-pi --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Herdr Orchestrate Pi?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Herdr Orchestrate Pi
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/alexhooi-herdr-orchestrate-pi/badge)](https://www.skillsdirectory.com/skills/alexhooi-herdr-orchestrate-pi)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: herdr-orchestrate-pi
description: "Herdr master-orchestrator, all-pi harness. Fire when inside a herdr pane (HERDR_ENV=1) and the captain hands over a spec, feature, or read-only evaluation to orchestrate — and the run should stay in the pi harness (captain says pi, or pi is the project default). Mixed-harness runs go to herdr-orchestrate instead."
---

# Herdr Orchestration — PI harness

Precondition: `test "${HERDR_ENV:-}" = 1` — otherwise say so and stop.

Every worker lane is a pi pane; model per role via `--model` after `--`. All lane plumbing is one tool: the sibling `herdr-orchestrate` skill's `bin/herd` (both skills install side by side in `~/.claude/skills/`) — every command below is `herd <verb>`. Run it from the project directory (or set `HERD_PROJECT`); it keeps a ledger in `<project>/.herd/ledger.json`.

Preflight once per session:
- `herdr integration status --outdated-only` — update anything listed; outdated integrations re-raise trust dialogs on spawn.
- **Find the project first.** If the cwd holds no `.herd/` and no spec and the brief carries no absolute path, locate the project (mdfind/spec search; disambiguate siblings by ledger lane prefixes and freshness), then `export HERD_PROJECT=<abs>` and run every `herd` command from there. Never spawn from `$HOME` — herd refuses to create a ledger there.
- `herd status` — an existing ledger means you are **resuming**: adopt it (see Resume), don't spawn duplicates.

## Layers

Captain ↔ **root orchestrator** (product shape, taste, spec-writing; where the captain lives) → **this session = ops** (route, watch, review-route, land, sweep) → **one owner lane** per spec (decides whether and how to split, spawns peers, owns integration + acceptance) → peers. Ops never designs, slices, implements or reviews; root never touches lanes. The captain zooms into ops only by choice.

## Roles

| lane name | model (via `-- --model <id>:<thinking>`) | takes |
|---|---|---|
| (this session, ops) | — | routing, triage, status. NEVER implements, reviews, slices or designs seams |
| `impl-fable[-<name>]` | `claude-bridge/claude-fable-5:high` | default owner: holds the whole spec — architecture, integration, acceptance — spawns Astra/Opus/kimi peers for what it won't hold. Fable typing well-specified code itself is a routing smell |
| `impl-astra[-<name>]` | `openai-codex/gpt-6-astra:high` | owner for well-specified specs (spawns its own peers), or peer for scoped chunks |
| `impl-opus[-<name>]` | `claude-bridge/claude-opus-5-5:high` | Astra-equivalent: owner or peer, same as Astra; pick over Astra when codex sandbox/receipts are in the way, or to spread quota |
| `frontend-kimi` | `moonshotai/kimi-k3:high` | design code / frontend ONLY, any platform (web, SwiftUI/native) — never backend or review; image/video assets via the Higgsfield MCP directly |
| `review-astra` | `openai-codex/gpt-6-astra:high` | reviews fable-implemented work (cross-model) |
| `review-fable` | `claude-bridge/claude-fable-5-1:medium` | THE code reviewer — Fable 5.1 reviews astra/opus/kimi-implemented work |
| `review-opus` | `claude-bridge/claude-opus-5-5:high` | Astra-equivalent reviewer: reviews fable-implemented work when no Astra lane is available, or stands in for review-fable on a Fable-limit stall |
| `review-ui` | `openai-codex/gpt-6-astra:high` | reviews frontend-kimi work by DRIVING it — real browser or simulator, never a text-only diff — Astra is the specialist UI reviewer |
| `scout-*` sub-lanes | `claude-bridge/claude-sonnet-5:medium` | search, recon, read-only fan-out (sonnet is the floor tier, never haiku) |

Thinking level rides the model id (`:<level>` suffix; explicit `--thinking` also works) — without it a pane runs at pi's `defaultThinkingLevel` (medium). The tiering is deliberate (showdown-tested): medium lanes matched high on quality while winning speed/cost — keep it. Exceptions: kimi and Opus 5.5 run `:high`.

**One delegation tool: herd panes.** Lanes run without an in-harness subagent tool (drop the pi-subagents extension). A lane that needs help spawns a herd sub-lane (`herd spawn <parent>-<role>-N --kind pi -- --model <id>`), delegates as much as it wants (recon fan-out, scoped chunks, parallel reads — all as panes, all observable), watches it, absorbs the report, closes it. Lane-to-lane `herd send` is legitimate — peers settle interfaces with each other; ops hears only deadlocks. Sub-lanes an owner spawns are namespaced under it (`impl-fable-ui-kimi-1`) and are that lane's to watch, review-route, and tear down — the orchestrator sees only the parent's report. Sub-lane `--cwd` is the project root or a worktree, never a subdirectory (nested `.herd/` = forked ledger, unledgered lane; spawn warns). Codex (openai-codex) / sandboxed lanes never own build receipts (`xcodebuild`, SwiftPM manifest resolution write to `~/Library/Caches` — seatbelt blocks it): the orchestrator runs the receipt itself and reviewer briefs pre-declare it as orchestrator-verified.

## Spawning

`herd spawn` (syntax in the lifecycle block below) bakes in the verified pi launch flags (single source: `KIND_ARGS` in `bin/herd`); `--approve` at launch prevents routine dialogs. Workers are visible interactive panes the captain can watch and interrupt. `--profile <name>` runs the lane under `~/.pi/agent-<name>` — shared auth/models by symlink, own settings/extensions (e.g. a lean profile for models that choke on heavy extensions).

**Model verification is built into spawn**: it confirms the model against pi-powerline's breadcrumb and returns `"model_verified": true|false` in its JSON. Send work only on `true`. On `false`, fix in place — `herdr agent prompt <lane> "/model <provider/model>"`, then re-check the breadcrumb. Herdr restores the default model on any restart or restore: fix in place rather than respawning, and re-verify after every restart.

Spawn lazily on first task; `herd spawn` is idempotent — a live same-kind lane is adopted (also the resume path). Each lane gets its own tab; `--worktree` gives it a managed worktree on branch `lane/<name>` instead.

## Lane lifecycle (the whole loop)

```
herd spawn <lane> --kind pi [--worktree] [--cwd DIR] [--profile NAME] [--no-nudge] [-- --model ID]
herd send  <lane> --file prompt.md [--state implementing]   # or inline text / stdin
herd watch <lane> [--text] --timeout 1200                 # implementing lane
herd watch --any <lane> <lane> ... [--text] --timeout 600  # first lane wins; reviews ~600s
herd send  <lane> --review --state review --file review-prompt.md
herd send  <lane> --refocus      # replay the lane's recorded brief (task→slice→spec intent) after a compaction or drift; keeps the outstanding report token
herd triage <project>/.herd/findings-<lane>-N.json --backlog <backlog-file> [--promote ID[,ID...]]
herd land  <lane>                      # honors ship_mode; conflict -> handback
herd close <lane> [--integrated]       # closes tab / removes worktree; --integrated: dirty worktree whose files the parent already integrated
```

**spawn** pre-approves the lane so trust dialogs never appear; anything pretrust can't handle falls to the exit-3 path. It also gitignores `.herd/` in the project root.

**send** appends a unique per-turn `REPORT-END-<hex>` token and verifies delivery. herd answers no dialog, ever: a blocked lane makes send exit 3 with the pane excerpt — answer it yourself (`herdr agent send-keys <lane> ...`), then resend. Concurrent sends to different lanes are safe.

**watch** blocks until the lane's token appears as a lone line AND the agent has settled — ALWAYS run it in the background (pi-background-tasks `bg_run`), one watch per lane; a foreground watch blocks your entire turn and makes you look dead to the captain. Tokens are single-use: a re-watch with nothing pending waits instead of matching stale pane output; `--resume` (resumed sessions, missed reports) turns an already-consumed token into success reason `already-reported` plus the pane tail; a newer send supersedes an attached watch with a fast `superseded` failure; a deliberately closed lane returns reason `closed`, not a crash. Escalation exits: 2 agent gone, 3 dialog, 4 timeout — all self-notify, so a stalled lane is never silent; on a timeout that is not `advanced:true` (below), escalate rather than looping. On exit 3, answer the dialog yourself (`herdr agent send-keys`), confirm the pane moved, re-attach — only questions you cannot answer go to the captain: zero captain involvement is the bar, zero orchestrator involvement is not. **Watch the lane, never the artifact**: an output-file wait has no blocked-escape and turns a stuck worker into silence — the only legal waits are `herd watch` and its exit codes. `watch` also reads the token from the lane's pi session jsonl when compaction redrew the pane over the report (pi-blackhole compacts at agent_end, right after the report turn — the report surfaces in the watch tail, no wait), and nudges an idle lane ONCE for its report when the token is truly missing (non-coercive: "if still working, do not reply"; after `--nudge-after` seconds of quiet, default 600; per token, ledger-recorded) — spawn orchestrator / pseudo-orchestrator lanes with `herd spawn --no-nudge` (or watch `--no-nudge`): they idle on their own sub-lanes by design — and accepts a review lane's findings file as completion (reason `findings-file`). Exit 4 carries `agent_status` and `advanced`: `advanced:true` = the lane is still moving — re-arm the watch, don't escalate. Size fix-round timeouts to the handback: 8+ findings or an engine rewrite → `--timeout 3600`.

Every worker prompt carries:
- the whole spec with product-level acceptance (owner), or the chunk the owner handed off (peer) — never a method; lanes delegate per the rule above (sub-lanes all `--kind pi`, roles-table models) and own their lifecycle;
- "There is no subagent tool. Delegate freely via `herd spawn` sub-lanes — scouts on `claude-bridge/claude-sonnet-5:medium` for exploration/search (floor tier), Astra or Opus 5.5 (`claude-bridge/claude-opus-5-5:high`) for scoped code, kimi for UI; keep your own tier for reasoning and synthesis. Close every sub-lane you open."

(Report-footer and sentinel are herd's job — don't add your own.)

**On any pane weirdness** — an unexpected watch/send exit, an empty read, a mid-run tool update, a spawn startup timeout, a missing toast — read `LORE.md` in this skill dir before diagnosing.

## Routing

**Flat by default: the spec goes whole to ONE owner lane.** The owner (Fable, Astra or Opus — never kimi) decides whether to split at all, spawns peers for what it won't hold (kimi for UI, Astra/Opus for scoped code, sonnet scouts), and owns integration and product-level acceptance. Ops slices only when the captain/root hands over specs already split. Peers negotiate interfaces with each other directly over `herd send` — the lanes that will live with a seam settle it, record the decision in their briefs, and move on; ops arbitrates only a reported deadlock, never pre-authors contracts. Atomizing into tickets produces modules that pass in isolation and no product; the owner's brief is the whole spec.

Acceptance is product-level: "the user can do X", never "module Y's tests pass". **Run the final thing yourself** before calling anything done — drive the real UI hands-on with realistic data volumes, and walk anything web-facing at mobile/tablet/desktop widths (390/768/1440). Lane test suites catch what they were written to catch — a 41-assertion real-browser run once still shipped a mobile layout broken at every width.

**Read-only / evaluation mode** (audit, "what's missing", UX review): route analysis slices per the table, prefix every prompt "READ-ONLY — do not edit, write, or create files", skip the review matrix, synthesize the lanes into one Artifact — findings ranked, evidence as file:line. Teardown still applies.

## Shipping modes and collisions

`herd set ship_mode scratch|merge|pr` (per project, in the ledger; default scratch).

- **scratch** — lanes work directly in the project tree; review the git diff before the captain declares done. Scratch lanes get disjoint files. Commits land on the project's default branch, no push — that is the explicit go that satisfies "never commit to the default branch without owner go" in global AGENTS.md/CLAUDE.md.
- **merge** — implementers spawn `--worktree`, commit on `lane/<name>`. When review clears: `herd set <lane> state=reviewed`, then `herd land <lane>` merges (`--no-ff`). Land enforces the gate itself (refuses unreviewed or dirty states with exit 4 — for land/close, 4 means refused precondition, not timeout) and exits 3 on conflict with the files: hand the owning lane "merge main into your branch, resolve, keep both behaviors, re-run your checks", scoped re-review, land again. Conflicts are the owning lane's, never the captain's.
- **pr** — like merge, but `herd land` refuses to land locally; push and PR are the lane's manual steps (`git push -u origin lane/<name>`, then `gh pr create` per project docs). Herd doesn't enforce the review gate here — the PR review is the gate.

## Review matrix and bug loop

UI slices are driven for real before review — browser for web, simulator for native (an AR/camera slice also needs a physical-device pass).

- Owner reports done (its peers are its own to gate) → ONE review pass over the combined diff: Fable owner → review-astra (review-opus if no Astra lane); Astra owner → review-fable (Fable 5.1); Opus owner → review-astra (cross-vendor) or review-fable. **Never review a peer's chunk alone** — the whole spec at once is what gives the reviewer blast-radius judgment for cuts. Cross-model: pick the reviewer opposite the model that wrote most of the batch. Reviewers are tab lanes, no `--worktree` — the branch diff is visible from the project repo. Adversarial: refute-first, actionable findings only. Reviewer independence: a reviewer never also gets its sibling implementer's work in the same task.
- frontend-kimi (usually the owner's peer) done → **reviewed before the captain ever sees it** by a `review-ui` lane (Astra) armed with the spec — it DRIVES the real UI (browser for web, simulator for native): flows, validation, empty/error states, every viewport width, realistic data; findings arrive via `herd send --review`. The orchestrator reviews personally only when no Astra lane is available (it holds the product context). When the pass is clean, `herd set frontend-kimi state=reviewed` (landing needs it), then present what shipped (screenshot/URL/diff) for taste-level judgment; the captain is never the one to report "text box overflows on mobile." Other lanes don't gate on it.
- `herd send --review` makes findings arrive as data in `.herd/findings-<lane>-N.json` (herd gives the reviewer the format) — no finding is transcribed by hand.
- `herd triage <findings.json> --backlog <file>`: disastrous/architectural/blocking findings print for handback (send to the implementing lane verbatim, scoped re-review after the fix); the rest append to the backlog (project tracker or your own todo file) without interrupting anyone.

**Deslop is part of every review, not a separate pass.** The cut lens rides alongside the bug lens: one-caller helpers with no depth, defensive paths for impossible conditions, speculative flags/seams, comment bloat, implementation-pinning or duplicate tests, slow tests (worst `--durations`), stray files. **Tests pin product behavior through its interface** — a module-shaped or mock-exercising test is slop: cut it or rewrite it against the product surface. Keep-flags are mandatory: flag load-bearing code that merely looks like ceremony, with the reason — cutting it is the costly failure. Slop findings skip the backlog: safe cuts ride the handback and land with the slice; only risky cuts are backlogged. A whole-repo audit lane is an occasional tool for accreted fat, not a per-slice step.

A slice is done when review passes or all remaining findings are backlogged — and the orchestrator has verified the product.

## Captain contact points

Exactly two kinds: decisions only they can make (unknown dialogs, real worker questions, scope calls), and completion. Both get `herd notify "<title>" --body "<one line>" [--sound done|request]` — toast, falling back to a macOS notification — AND the same message in-channel: notify accompanies, never replaces.

## Status and resume

`herd status`: lane, kind, state (queued / implementing / review / fixing / user-review / done / backlogged-findings), liveness, task. Keep current with `herd set <lane> state=<s> task=<one-liner>`.

A fresh session resumes from the ledger: re-adopt live lanes with `herd spawn <lane> --kind pi` (idempotent), re-verify each lane's breadcrumb against its role, re-attach a background `herd watch --resume` for every lane in implementing/review/fixing (tokens persist in the ledger; `--resume` hands over an already-reported result instead of timing out on a consumed token), and pick up the review obligations the states imply. Never re-send a slice a live lane already has.

## Teardown

**Etiquette — every lane cleans up what it opened before it reports done**, and the orchestrator verifies before `herd close`: browser tabs/windows/instances it launched (never the captain's own Chrome), booted simulators it booted, dev servers, log tails, recordings, device-mirroring sessions, background jobs, scratch files outside `.herd/`. The captain must never come back to ten Chrome instances and a running sim. Gotcha: `osascript … tell application "X"` LAUNCHES X if it isn't running — `pgrep -x` first. **Machine-clean sweep is the orchestrator's last act before the final report** — lanes cleaning up is necessary, not sufficient; you own the end state. Run it and put the result in the report:

```bash
xcrun simctl list devices booted | grep -c Booted        # 0, or shut down what a lane booted (`xcrun simctl shutdown <udid>`)
pgrep -fl 'Simulator.app|xcodebuildmcp|mirroir|sim-use|peekaboo|recordVideo|chrome-devtools|--remote-debugging-port' | grep -v pgrep   # empty
lsof -nP -iTCP -sTCP:LISTEN | grep -v -e herdr -e rapportd | awk 'NR>1{print $1,$9}'   # no dev servers you or a lane started
herd status                                              # every lane closed
```

Kill/close what the run started (never the captain's own Chrome, sims or servers — compare against what was running when you began). A run is not done while any of it is still up.

`herd close <lane>` as work completes: implementer when its slice landed, reviewer when no review is pending, frontend-kimi once committed and presented. Close only settled agents; read a blocked worker's dialog first. Close refuses tabs it didn't create; worktree lanes lose the worktree (branch stays until landed). On spec completion, update your project docs.

Files in this skill

  • LORE.md4.2 KB
  • SKILL.md18.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…