modules/programs/agents/shared/skills/herdr-dispatch/SKILL.md
Dispatch user-visible coding or research agents through Herdr with Codex-Desktop-like thread ergonomics. Use when the user asks to use Herdr to spawn, dispatch, fan out, inspect, follow up with, or monitor agent workspaces/threads.
npx skillsauth add MichaelVessia/nixos-config herdr-dispatchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use Herdr as the dispatch layer for visible agent work. This skill is for launching and coordinating agents from any shell, including Codex Desktop. Do not inherit the HERDR_ENV=1 restriction from the lower-level herdr pane-control skill.
claude --dangerously-skip-permissions.--dangerously-bypass-hook-trust by default: current Claude builds (>= v2.1.x) reject it, the launched pane exits instantly, and you waste a spawn discovering this. Only add it if the user explicitly asks, and if the pane dies, retry once without it and note the fallback.codex --dangerously-bypass-approvals-and-sandbox --ask-for-approval never --sandbox danger-full-access.Tabs vs Panes.--no-focus unless the user explicitly asks to focus the spawned work.review-pr-4370, impl-auth, or research-herdr.For code repositories, default to a Herdr worktree. For Obsidian vault or research-only work, do not create a git worktree; start the agent directly in the vault or resolved context.
A tab is a full-width thread, like a Codex Desktop thread. A pane is a split inside a single tab, so multiple agents share one screen side by side.
--split right|down to herdr agent start (or herdr pane split). Without --split, an agent lands in its own tab.split, side by side, same screen, as a pane, grid, tile them). When unsure, default to tabs.Pane grids).To guarantee a fresh tab deterministically, create it first and target it by id:
herdr tab create --workspace <workspace-id> --label <agent-name> --no-focus
# parse result.tab.tab_id from the JSON, then:
herdr agent start <agent-name> --tab <tab-id> --no-focus -- claude ...
If you do not pre-create a tab, omit --split and agent start opens a new tab on its own.
When the user wants panes, tile them into a near-square grid so every agent stays readable. Do not chain --split down (or --split right) off the same growing pane; that produces one column (or row) of ever-thinner, eventually-unreadable splits.
For N agents, fill row-major into a grid sized cols = ceil(sqrt(N)), rows = ceil(N / cols):
agent start (own tab, capture each pane_id from the JSON). The first agent's tab becomes the grid tab.pane_id parked at each cell so later moves target the right neighbor:# first pane of a new column: place to the right of the previous column's top pane
herdr pane move <pane-id> --tab <grid-tab-id> --split right --target-pane <top-pane-of-prev-column> --no-focus
# next row within a column: place below the pane directly above it
herdr pane move <pane-id> --tab <grid-tab-id> --split down --target-pane <pane-above> --no-focus
herdr pane resize --direction <left|right|up|down> --amount <float> --pane <id>.Reporting should say grid in tab <label> (<cols>x<rows>) so the user knows the layout.
Resolve repo/context in this order:
web-monorepo./Users/michael.vessia/obsidian as fallback for research or ambiguous non-code work.If the resolved context is /Users/michael.vessia/obsidian or another vault/research folder, skip herdr worktree create.
Before dispatching:
herdr agent list or herdr workspace list.herdr integration status.herdr agent list and avoid duplicate names or obviously duplicate active work.For code work:
herdr worktree create --cwd /path/to/repo --branch codex/herdr-<slug> --label <agent-name> --no-focus --json
result.root_pane.pane_id — see "The orphan root pane" below; you close this at the end.herdr agent start <agent-name> --cwd /path/to/worktree --workspace <workspace-id> --no-focus -- claude --dangerously-skip-permissions "<prompt>"
For Codex:
herdr agent start <agent-name> --cwd /path/to/worktree --workspace <workspace-id> --no-focus -- codex --dangerously-bypass-approvals-and-sandbox --ask-for-approval never --sandbox danger-full-access "<prompt>"
--workspace is required, not optional. The workspace that worktree create returns carries the repo/worktree metadata that nests the thread under its repo in the sidebar. Starting an agent with only --cwd makes Herdr create a plain workspace with no repo association: it renders top-level instead of under the repo, and there is no command to re-associate it afterwards. If worktree create's JSON lacks a usable workspace id, recover one instead of omitting the flag:
# find the worktree's open workspace (open_workspace_id on the matching path)
herdr worktree list --cwd /path/to/repo --json
# or, if no workspace is open for it, open one with metadata attached
herdr worktree open --cwd /path/to/repo --path /path/to/worktree --no-focus --json
Always capture the pane_id from the agent start JSON result (e.g. w4:p3) and keep it as the durable handle for monitoring (see "Follow-Up and Monitoring").
herdr pane close <root-pane-id> # the root_pane.pane_id captured in step 4
workspace_id in the agent start pane id must match the worktree's workspace id. A different id means the agent spawned a plain ungrouped workspace; close that stray workspace and relaunch with the correct --workspace.herdr worktree create (and workspace open) always spawns a default shell pane in the new worktree (returned as result.root_pane). herdr agent start does not reuse it — it opens a second pane beside it. Left alone, every dispatch ends up with two panes: the running agent, plus a dead shell that never had a command run in it. In a fresh worktree that dead pane also shows direnv: error .../.envrc is blocked, which is why the failure looks direnv-caused. It is not: the two panes appear regardless, and priming direnv (below) does not remove the orphan.
Fix: after agent start, close the root pane by the root_pane.pane_id captured at creation. The agent pane is a separate pane in the same tab, so closing the root leaves the agent full-width. Only close the root pane, never the agent pane, and never close the last pane in a workspace (that removes the workspace). For Obsidian/research dispatch there is no worktree and no root pane, so skip this.
By default, do not pass --split here: each agent gets its own tab. When fanning out several agents into the same workspace (no separate worktree per task), create a tab per agent first (herdr tab create --workspace <id> --label <agent-name> --no-focus, parse result.tab.tab_id) and pass --tab <tab-id> to agent start, so they land as separate tabs rather than accidentally splitting one. If the user deliberately wants them in panes, tile them into a grid instead (see Pane grids).
Repos like web-monorepo use direnv (.envrc → devbox/nix) to put the correct toolchain (node, pnpm, env vars) on PATH. A freshly created worktree is broken in two ways, and both must be fixed or the agent runs with the wrong, unpinned global tools and any repo build/test/lint misbehaves:
direnv: error .../.envrc is blocked. Run 'direnv allow'..env are gitignored, so they exist in the main checkout but not the worktree. devbox parses .env on activation and aborts if it is absent (Error: failed parsing .env file), which silently drops you back to system node/pnpm.After herdr worktree create, before herdr agent start, prime the worktree. Only do this when the source repo's .envrc is already trusted (never blindly trust an unvetted .envrc):
REPO=/path/to/repo
WT=/path/to/worktree
if [ -f "$REPO/.envrc" ] && (cd "$REPO" && direnv status | grep -q "Found RC allowed"); then
# 1. seed gitignored local env files that devbox/direnv needs
for f in .env .env.local; do
[ -f "$REPO/$f" ] && [ ! -e "$WT/$f" ] && cp "$REPO/$f" "$WT/$f"
done
# 2. approve direnv for the new worktree path
direnv allow "$WT"
# 3. (optional) pre-warm so the agent's first shell doesn't sit through the devbox build
direnv exec "$WT" true
fi
If the repo has no .envrc, or direnv is unavailable, skip this silently. For Obsidian/research contexts, skip entirely. Verify success by checking the toolchain resolves into the worktree, not system paths: direnv exec "$WT" bash -c 'command -v node' should point at $WT/.devbox/..., not /opt/homebrew/....
For Obsidian or research-only work:
herdr agent start <agent-name> --cwd /Users/michael.vessia/obsidian --no-focus -- claude --dangerously-skip-permissions "<prompt>"
Do not create a worktree for vault work.
After launch, wait only long enough to confirm the agent exists and has started:
herdr agent wait <agent-name> --status working --timeout 30000
If it is already idle or status detection is stale, read recent output instead:
herdr agent read <agent-name> --source recent-unwrapped --lines 80
If agent wait/agent read by name returns agent_not_found, the harness's herdr state hook is outdated (herdr integration status shows it as outdated) and the name never registered. Fall back to the pane_id captured from agent start and read the pane directly:
herdr pane read <pane-id> --source recent-unwrapped --lines 80
# verify the pane is still alive (a pane that vanished means the harness exited at launch):
herdr pane list --workspace <workspace-id>
A pane that disappears seconds after agent start means the launched CLI exited immediately. The usual cause is an unsupported flag (e.g. --dangerously-bypass-hook-trust); relaunch without it.
Return after spawn confirmation. Do not wait for task completion unless the user asks.
Use named agents as durable handles:
herdr agent list
herdr agent read <agent-name> --source recent-unwrapped --lines 120
herdr agent send <agent-name> "<follow-up prompt>"
herdr agent wait <agent-name> --status idle --timeout 600000
herdr agent focus <agent-name>
If agent send does not submit the prompt in the current harness, read the agent/pane metadata and send Enter with the appropriate Herdr pane command.
For a request like use herdr to review PRs 1, 2, 3:
Pane grids).review-pr-1, review-pr-2, review-pr-3.Prompts should be self-contained, like Codex Desktop thread prompts. Include:
After dispatch, tell the user:
no worktree for Obsidian/research.herdr agent read <name>, or herdr pane read <pane-id> if the state hook is outdated and the name does not resolve.Keep the report short.
Use Herdr notifications only when useful:
herdr notification show "agent blocked" --body "<short reason>" --sound request
herdr notification show "agent done" --body "<short result>" --sound done
Do not use notifications for routine spawn success unless the user asks.
development
Restate the last message in plain human language, with no jargon.
testing
Fan out a batch of work items into one PR each via isolated worktree agents, review every PR before it opens, then babysit all PRs through green CI and review feedback. Use when the user wants to fan out PRs, dispatch parallel PR agents over a list of items, or run a batch of independent changes as separate PRs.
development
Generate self-contained HTML visualizations with Plannotator theming. Use for implementation plans, PR explainers, architecture diagrams, data tables, slide decks, and any visual explanation of technical concepts. Plans and PR explainers follow Plannotator's prescriptive approach; all other visual content delegates to nicobailon/visual-explainer.
development
Turn an idea or objective into a goal package for /goal. Interviews the user, builds a reviewed fact sheet via Plannotator, then explores the codebase to produce an execution plan.