mcpField
H
herdr-pair

herdr-pair

github.com/hcaianoAgent workflows49 installs
Repository

About herdr-pair

A skill for pairing Claude and Codex in a Herdr tab and keeping their session bound to the verified tab across tasks. It defines scoped write leases, message types, delivery receipts, and recovery steps for continuing coordinated work.

Key features

  1. 01Pairs Claude and Codex in one Herdr tab
  2. 02Verifies caller and pane identity before changes
  3. 03Routes partner messages through a helper script
  4. 04Uses scoped write leases and task handoffs
  5. 05Tracks delivery receipts and resumes after compaction

Use cases

  1. 01Coordinate separate coding tasks between agents
  2. 02Request partner review of a change
  3. 03Resume a pair session after context compaction
  4. 04Handle uncertain message delivery without duplicate sends

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/hcaiano/skills --skill herdr-pair

After installing, type/herdr-pairin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

agents/
openai.yaml
references/
caller-pane-resolution.md
workbench-tab.md
scripts/
herdr-pair.mjs
herdr-pair.test.mjs
skill-contract.test.mjs

Details

From the project README

Herdr Pair

Pair Claude and Codex in one Herdr tab. Keep the pair and its sid alive across tasks, accepted work cycles, and context compaction. The user can read and interject in either pane. Keep protocol headers and identifiers literal.

Preconditions

Set SKILL_DIR to this skill directory and PAIR_SCRIPT="$SKILL_DIR/scripts/herdr-pair.mjs". Always use that absolute path; the project cwd is unrelated to the installed skill path.

Require herdr with the agent automation commands (herdr agent start, herdr agent prompt), jq, and trash on PATH, plus HERDR_ENV=1. If any is missing, stop and tell the user to install or start (or update) Herdr.

Before any Herdr mutation, read and execute Caller pane proof. It resolves the explicit task repository, proves the unique caller from its own process ancestry — falling back to conversation markers when that ancestry matches anything other than exactly one pane — and returns PAIR_PROOF plus the pinned PAIR_ID, including --tab-id. Stop when that proof does not complete exactly.

Guardrails

  1. Scope every pane operation to the transcript-proven workspace_id, tab_id, pane_id, agent kind, terminal identity, and repository. Never address a pane discovered only by workspace, focus, label, cwd, direction, session metadata, or pane number.
  2. Use herdr-pair.mjs send as the sole partner transport. Reserve normal assistant output for a header-free user handoff. SendMessage, subagent messaging, and direct pane writes are different channels.
  3. Give one agent the write lease for each file scope: owner, target files, forbidden changes, validation, and stop point. The partner stays read-only on that scope until handoff.
  4. A submitted user message overrides partner traffic. Surface any conflict in the next reply. One failed partner spawn ends the attempt.
  5. Between work steps return to the prompt; never hold the pane in long foreground loops (sleep-and-poll receives, foreground CI watchers). A permanently-working pane starves inbound partner traffic — run long-running watchers in a background terminal and keep this pane promptable.
  6. Announce every deliberate broken-checkout window. Before mutation testing, bisect, or a deliberate revert, send a task naming the affected paths and stop condition; send ready after the tree is restored and verified. Do not wait for accepted: the notices are the protection. A partner that has seen an open window treats that checkout's test results as unusable until the close notice arrives, and asks rather than reports. Run an experiment that cannot be announced, or that lasts more than a few minutes, in a separate worktree.

Protocol

Messages start with:

[agent <from> -> <to> kind=<kind> sid=<sid>]
[herdr-pair control seq=<n>: ...]

<body>

The helper injects the control line. It contains the exact executable receive command for this message and the rule to reply through the sender. This line is the recovery anchor when model context has been compacted.

Use these kinds:

  • task: propose or update the work split and its write leases. Begin a mid-flight stop with STOP — <reason>.
  • review: request review with file paths and a short change summary.
  • question: ask for clarification before proceeding.
  • ready: report changed files, validation, and residual risk.
  • accepted: accept the partner's ready and advance the work cycle.
  • blocked: name the user decision required to continue.
  • stalemate: report the same disagreement repeated twice without movement.
  • handoff: return control to the user in normal local output.

Start or resume

  1. Run node "$PAIR_SCRIPT" discover "${PAIR_ID[@]}". If no opposite agent exists, run node "$PAIR_SCRIPT" spawn "${PAIR_ID[@]}" once. Stop on multiple candidates or spawn failure.
  2. Run node "$PAIR_SCRIPT" init "${PAIR_ID[@]}". It creates a new tab-scoped session or idempotently resumes the exact live session. Record its exact sid as PAIR_SID; every send is bound to it so a wrong same-kind pane cannot borrow another tab's session.
  3. Send the first task through the helper. The partners are equals: propose a scope split — one write lease per scope, each partner implementing its own scopes and reviewing the other's ready — and include enough context for independent work; the partner accepts or counters before implementing. A task with no independent scopes takes one lease: the holder drives while the partner reviews, and the lease alternates across tasks.

Done when the exact tab has one verified session and the first task has a recorded receipt. Skill reload and compaction always resume that session.

Send

Write only the body to a temp file, then invoke:

BODY=$(mktemp); trap 'trash "$BODY"' EXIT
# Write the partner message body to "$BODY".
node "$PAIR_SCRIPT" send "${PAIR_ID[@]}" --sid "$PAIR_SID" \
  --kind "$KIND" --body-file "$BODY"

The sender gives a busy partner a short grace period, then delivers anyway. Measured on Herdr 0.8.0, Claude accepts a mid-turn prompt atomically, while a multi-line prompt to Codex still needs Enter. When the partner is still working, the helper sends exactly one agent prompt with the header, control line, and body, then runs the harmless Enter loop. It skips the visible-arrival check and the full resend because that status has no reliable composer signal and a resend may duplicate a queued body. Only receive proves the exact sequence in session.json; without that ACK the receipt says the delivery is unproven.

For an idle partner, the helper proves landing from the composer: the composer must first be seen to change, because a paste that never arrived and one already submitted look identical; then it sends Enter until the composer releases the text, performs one full resend, and fails loudly if delivery still cannot be proved. The sequence ACK can recover an interruption immediately after submission on either path.

  • receipt=acknowledged: the partner ran receive for this message.
  • receipt=pending-partner-may-be-busy-do-not-retry: the message landed and the partner is working, so it is queued but not acknowledged yet. Do not resend. Later run node "$PAIR_SCRIPT" reconcile; the status advances only after its ACK.
  • receipt=unproven-working-inspect-that-pane-then-reconcile: the partner was working, received one prompt plus the Enter protection, but did not ACK before the deadline. The helper cannot distinguish a queued prompt from a silent drop. Do not resend while its reservation is pending; inspect after the agent settles, then reconcile or clear the proved-absent delivery before retrying.
  • receipt=lost-partner-idle-inspect-that-pane-then-reconcile: the partner is idle and never acknowledged, so it did not receive the message. Read that pane, confirm the message is absent, and clear the pending delivery below. Long bodies are the usual cause; send those as a short message naming a file path.
  • A nonzero exit after reservation is a transport failure. The pending reservation remains so an ACK can reconcile it; never claim delivery or clear it without inspection.

If inspection proves a pending message never reached the partner, clear only that delivery with explicit user approval:

node "$PAIR_SCRIPT" reconcile "${PAIR_ID[@]}" --sid "<sid>" \
  --clear-pending true

Receive and recover after compaction

For inbound [agent ...] traffic:

  1. Run the exact command in [herdr-pair control ...]. It calls receive with --sid, --from, and --seq, validates the live tab binding, and persists the receipt acknowledgement.
  2. Process the message, write the reply body to a temp file, and run node "$PAIR_SCRIPT" send ....

Done when receive records the sequence and the reply has a recorded receipt. On failure, give the user a header-free transport report. After compaction, reconstruct pane IDs, sid, task status, and close state from the control line and verified session.

Work cycles and persistence

Continue while producing useful artifacts. Five consecutive turns with no new code, test result, decision, or narrowed option require a handoff. Reset the count on real progress. Settle a factual disagreement with one direct proof or focused test before it can become a stalemate. Send stalemate after the same judgment call repeats twice without movement.

Two accepted statuses complete one work cycle. The initiator gives the user a local handoff naming the result, verification evidence, unresolved issues, and every pair pane, worktree, or watcher still active. Both agents may idle; the next task resumes the same pair and sid. The session remains active.

blocked and stalemate also hand off without deleting the session. Use node "$PAIR_SCRIPT" reset "${PAIR_ID[@]}" only to clear work-cycle counters/statuses in a verified live pair; it preserves identity and delivery history.

End and trash the session only when the user explicitly asks to end the pair:

node "$PAIR_SCRIPT" end "${PAIR_ID[@]}" --sid "<sid>"

The script verifies sid, workspace, tab, and participants itself, and refuses while delivery is pending (wait for the ACK or use the inspected clear path). If old pane IDs or a missing partner prevent resume, explain the mismatch and use end "${PAIR_ID[@]}" --sid "<sid>" --stale true only with explicit user approval — a stale end may discard pending state only when the partner pane is gone, its recorded binding is stale, or its foreground agent process/repository no longer matches. Closing the Herdr tab ends the panes naturally; stale state is never borrowed by another tab.

Workbench tab

Read references/workbench-tab.md only when a separate tab is needed for a long-running shared process.

Deprecated

This skill is frozen. Its successor is the pair skill in the same repository, which keeps this Herdr backend byte-for-byte and adds a headless backend for pairing outside Herdr. Install pair for new work; herdr-pair stays here so existing installs keep running.

Comments

Markdown supported