一键导入
wt
タスクの説明からブランチ名を自動生成し、herdr の worktree + workspace を立ち上げ、必要なら作業担当エージェントに委任する。ユーザーが新しい作業を始めたい・worktree を切りたい・「/wt」と言った時に使う。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
タスクの説明からブランチ名を自動生成し、herdr の worktree + workspace を立ち上げ、必要なら作業担当エージェントに委任する。ユーザーが新しい作業を始めたい・worktree を切りたい・「/wt」と言った時に使う。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
学習ループ用の教師モード — セッションの内容や設計判断を、段階的な説明・チェックリスト・ クイズでユーザーが深く理解するまで伴走する理解ゲート。 ユーザーが「/learn」「理解ゲート通して」「これ教えて」「クイズ出して」などと言った時に使う。 また、リポジトリの CLAUDE.md が理解ゲートを規定している場合(例: hexhive)、 設計判断を含む PR のマージ前にこちらから発火を提案してよい。
エージェントセッションの意思決定・洞察・成果物を Obsidian の ResearchNotes に昇格させる(蒸留パイプライン層1)。 ユーザーが「セッションをまとめて」「記録して」「/session-log」と言ったときに使う。 また、設計判断・アーキテクチャ決定・重要な学びが生まれたセッションの区切り(タスク完了時・終了間際)には、こちらから記録を提案してよい。 生ログの全転写ではなく、対話で生まれた判断・設計・学びの厳選記録。
Question Behind the Question — 実装プランを出す前に、要望の下にある設計判断を1段掘り、 「本当に問うべき問い」の候補を提示する。 ユーザーが「/qbq」「問いから掘って」「本当に問うべきことは何?」などと言った時に使う。 また、インフラ・ワークフロー・アーキテクチャ系の相談で、要望の背後に未言語化の 設計判断がありそうな時は、実装プランを提示する直前に自発的にこの手順を提案してよい。
マージ済み PR に対応する worktree / workspace / ローカルブランチを安全に掃除する。/wt で作った worktree のライフサイクルの後始末。ユーザーが「worktree を掃除して」「片付けたい」「/wtclean」と言った時に使う。
herdr を介して、ユーザー・Claude Code・Copilot CLI・copilot-quorum の四者が pane 越しに対話するためのプロトコル。相手 pane の見つけ方、宛先プレフィックス付き メッセージ形式、送信・応答待ちの手順、ループ防止の原則を定める。 ユーザーが「Copilot と相談して」「quorum に合議させて」「他のエージェントに聞いて」 「隣の pane と話して」などと言った時、または他エージェントからの宛先付きメッセージ (【from→to】形式)を pane 上で検知した時に使う。 司令塔↔作業者プロトコル(herdr スキルの `agent send` / 上り報告)とは別物 — あちらは 上下関係の報告経路、こちらは対等な対話。既存プロトコルは変更しない。
Obsidian デイリーノートの自動作成・更新(朝)と対話型の振り返り(夜)を行う。 cowork環境の「クラウディア」ワークフローのターミナル移植。 ユーザーが「デイリーノート作って」「振り返りしたい」「/daily」などと言った時に使う。
| name | wt |
| description | タスクの説明からブランチ名を自動生成し、herdr の worktree + workspace を立ち上げ、必要なら作業担当エージェントに委任する。ユーザーが新しい作業を始めたい・worktree を切りたい・「/wt」と言った時に使う。 |
タスクの説明からブランチ名を自動生成し、herdr の worktree + workspace を立ち上げます。
/wt に続けて入力する自然文。ブランチ名の生成、worktree/workspace の作成、および該当する場合はエージェントへの作業指示プロンプト作成の入力になる(実体は末尾の 引数 セクション参照)Constraints:
git rev-parse --show-toplevel でリポジトリルートを確認するユーザーの入力からブランチ名を生成する。
Constraints:
feat/ fix/ chore/ ci/ docs/ などの type を prefix にする)feat/ か fix/ に寄せるgit branch --list <name> で確認するworktree を作成する前に、司令塔自身に安定した名前を付ける。作業者からの上り報告(手順5「(3) 上り=内容」参照)の push 先として使うため。
herdr agent rename "$HERDR_PANE_ID" "commander-$(basename "$(git rev-parse --show-toplevel)")"
Constraints:
$HERDR_PANE_ID は herdr が各ペインのシェルに注入する環境変数で、司令塔自身の pane を自己識別する(実機確認済み)commander-<repo名>(git rev-parse --show-toplevel の basename)とする。複数リポジトリで司令塔が並行稼働しても衝突しないagent_name_taken で失敗した場合、サフィックス付きの名前で空いているものまで採って再試行する。デフォルトは数字サフィックス(commander-<repo名>-2, -3...)。タスク由来の意味サフィックス(例: commander-dotfiles-dpp)も可 — 同一リポジトリで複数司令塔が同時稼働している場合、どの司令塔か人間が識別しやすくなる。要件はユニークであることのみcommander-<repo名> 箇所すべて。【相談】【報告】の2箇所)を実際に採用した名前に統一するherdr agent rename は司令塔が自分自身($HERDR_PANE_ID)に対してのみ実行する。作業者や他ペインの名前を司令塔側から書き換えないherdr worktree create --cwd <repo-root> --branch <branch-name> --base main --focus
Constraints:
git fetch origin && git merge --ff-only origin/main でローカル main を最新化する(特にマージ直後に続けて次の worktree を切る連続運用で必須。詳細: /wtclean Troubleshooting「git branch -d の not yet merged to HEAD 警告」参照)main。ユーザーが入力内で別のベースを指定した場合はそれに従うworktree 作成直後に以下を行う:
Constraints:
mise trust <worktree-path> を実行する(詳細: Troubleshooting「mise trust 忘れ」参照)mkdir -p <worktree-path>/.claude && cp ~/.claude/templates/wt-settings.local.json <worktree-path>/.claude/settings.local.json
<repo-root>/.config/claude/templates/... ではなく ~/.claude/templates/... を使う。<repo-root> は /wt を呼び出した対象リポジトリ次第で変わり、dotfiles 以外のリポジトリではこのテンプレートを含まないため~/.claude への反映は home-manager 経由(home.nix の home.file ".claude".source = ./.config/claude)で、mise run nix:switch 実行時に /nix/store スナップショットへの per-file symlink が生成される方式。テンプレートを追加・変更したら mise run nix:switch を実行しないと ~/.claude/templates/ に反映されない(詳細: Troubleshooting「allowlist テンプレートの cp 失敗」参照)git・gh・mise・herdr の一部サブコマンド、司令塔がタスク指示を置くスクラッチパッドの読み取り)を宣言的に許可し、作業者の permission 往復(A類)を設計で消す。詳細は allowlist テンプレート本体を参照タスク内容が具体的な場合、新しい workspace でエージェントを起動してタスクを渡す:
herdr agent start claude-<branch-name 由来のユニーク名> --workspace <workspace-id> --cwd <worktree-path> --split down --focus -- claude --model claude-sonnet-5 --effort <effort> --permission-mode auto "$(cat <<'PROMPT'
<作業指示プロンプト(複数行可)>
PROMPT
)"
Constraints:
--cwd は必須。省略すると呼び出し元シェルの cwd(リポジトリ本体)を引き継ぎ、worktree 外で作業が始まってしまう--split down で pane を上下分割にする(省略時はデフォルトの right で左右分割になってしまう)claude ではなくブランチ名由来の名前にする。変換ルール: ブランチ名から prefix(fix/ 等)を除き、_ と / を - に置換して claude- を前置する(例: fix/wt_agent_start_options → claude-wt-agent-start-options)claude-sonnet-5(司令塔=メインセッションが計画とレビュー、作業者が実装を担う分業)。ユーザーが入力内で別モデルを指定した場合はそれに従う--permission-mode auto で起動する。定型操作は自動承認され、判断が必要な操作だけが blocked として表面化する--dangerously-skip-permissions は使わない(監督を全て外すのではなく、エスカレーションのレーンを残すのが目的)司令塔がタスクの難易度を見て判断する:
| effort | 使いどころ |
|---|---|
| medium | 定型・機械的な変更(バージョン bump、typo 修正、設定1行の変更) |
| high | 通常の実装タスク(迷ったらこれ。Sonnet 5 のデフォルト) |
| xhigh | 難しい実装・複数ファイルにまたがる変更・設計判断を含むタスク |
Constraints:
low は /wt では使わない(under-thinking のリスクがあるため)medium 以下では Sonnet 5 が指示を literal に解釈するため、作業指示プロンプトの完了条件を具体的に書くあなたは worktree <worktree-path>(ブランチ <branch-name>)で作業する実装担当エージェントです。
## タスク
<ユーザー入力を司令塔が具体化したタスク説明>
## 背景
<司令塔が把握している文脈・関連ファイルのパス・調査済みの事実>
## 完了条件
- <具体的な完了条件を箇条書き>
- 変更をコミットし、gh pr create で main 向け PR を作成する(タイトル・本文は日本語)
- 関連 Issue があれば PR 本文に Closes #<番号> を入れる
## 制約
- 作業はこの worktree 内で完結させる(リポジトリ本体には触らない)
- コミットメッセージ・PR・ドキュメントは日本語
- 判断に迷う大きな設計変更はせず、迷った点は最終報告に書く(ただし実装の方向を左右する判断は最終報告まで抱え込まず、下記「## 相談」の手順でその場でエスカレーションする。最終報告に書くのは、エスカレーションするほどではない小さな迷いの受け皿)
- ドキュメントの大規模なフォーマット変換・構造変換を行う場合、変換前にコードブロック等の不変であるべき部分を機械的に diff できるチェック(例: awk でコードブロックを抽出して新旧比較)を仕込み、変換後に意図しない変更がないことを確認する
- ライブセッション(稼働中のデスクトップ等)で検証する場合、自分が起動したプロセスの PID は起動時に `$!` で捕捉する
- ライブセッションでの検証時、名前ベースの `pgrep` で見つけた PID を kill しない
- ライブセッションでの検証時、起動・生成が確認できない場合は検証を中止して報告する(推測で続行しない)
- ライブセッションでの検証時、ユーザーの既存ウィンドウ・既存プロセスは操作しない(読み取りのみ可)
## 相談
実装の方向を左右する判断で確信が持てないときは、最終報告まで抱え込まず、その場で司令塔へ相談を push する。判断に迷う点のうち、実装の方向を左右しない小さなものは上記「## 制約」の通り最終報告に書けばよい。
エスカレーションすべき判断の例:
- 複数の妥当な実装方式があり、どれを選ぶかで挙動やインターフェースが変わる
- Issue や指示の内容と、現状のコードベースの実態が食い違っている
- 破壊的変更(既存の挙動・データ・API 等を壊しうる変更)を伴う判断
**丸投げ禁止**: 相談には必ず「選択肢(A/B...) + 自分の推奨」をセットで送る。判断材料を示さず「どうしましょう」とだけ聞かない。
```bash
COMMANDER_PANE=$(herdr agent get "commander-<repo名>" | jq -r .result.agent.pane_id)
if [ -n "$COMMANDER_PANE" ] && [ "$COMMANDER_PANE" != "null" ]; then
herdr pane send-text "$COMMANDER_PANE" "【相談】<branch>: <選択肢A/B + 自分の推奨>"
herdr pane send-keys "$COMMANDER_PANE" Enter
fi
```
相談を送ったら、司令塔からの回答(pane に届く追加指示)を待つ。回答が届くまで、相談した論点については実装を進めない。
- `commander-<repo名>` が見つからない等、push が失敗した場合はエラーで止まらない。返答を待ち続けると作業が止まってしまうため、その場で自分の推奨案を採用して実装を進め、判断の経緯を最終報告に書く(push はあくまで即時性のための冗長化で、必須経路ではない)
## 報告
報告の正はこの会話へのテキスト出力(司令塔が `herdr agent read` で回収する)。**`SendMessage` は使わない** — 作業者は自セッションの main のため司令塔という宛先が存在せず、`You are the main conversation` エラーになる。
完了したら、変更ファイル・PR の URL・確認した動作を簡潔にまとめてこの会話に書く。指示外の気づき(環境の摩擦・想定外の挙動・自分で編み出した回避策)があれば、解決済みであっても必ず報告する(該当なしなら「なし」と明記する)。
会話内報告に加えて、完了時に司令塔へ1行の push 報告を送る(フォーマット: `【報告】<branch>: <一行サマリ>(<PR URL>)`。詳細は上記の会話内報告に書き、push は要約1行のみでよい):
```bash
COMMANDER_PANE=$(herdr agent get "commander-<repo名>" | jq -r .result.agent.pane_id)
if [ -n "$COMMANDER_PANE" ] && [ "$COMMANDER_PANE" != "null" ]; then
herdr pane send-text "$COMMANDER_PANE" "【報告】<branch>: <一行サマリ>(<PR URL>)"
herdr pane send-keys "$COMMANDER_PANE" Enter
fi
```
- `commander-<repo名>` が見つからない等、push が失敗した場合はエラーで止まらず、会話内報告のみに縮退して続行する(push はあくまで即時性のための冗長化で、必須経路ではない)
Constraints:
commander-<repo名>(【相談】【報告】2箇所)はプレースホルダ。司令塔が手順3で実際に名乗った名前(サフィックス付きの場合はそれを含む)に置き換えてから作業者に渡すエージェント起動後、司令塔(このセッション)と作業者エージェントの間のやり取りは、以下の4本柱からなる対話プロトコルとして運用する(設計の背景は #332、上り=内容の push 設計は #341 参照)。(4) 供養 は /wtclean 側で扱う。
委任時の指示は手順4の heredoc テンプレートで渡す。委任後に追加の指示を送りたい場合は、pane へのテキスト送信と Enter 送信を分けた2段で行う。作業者からの【相談】(手順4テンプレート「## 相談」参照)への回答もこの手順で送る(詳細な判別・応答フローは下記(2)「相談 idle の判別」参照):
herdr pane send-text <pane-id> "<追加指示のテキスト>"
herdr pane send-keys <pane-id> Enter
Constraints:
<pane-id> は対象エージェント名から herdr agent list で引く(pane_id フィールド)agent send / pane send-text はテキストを引数としてそのまま送るだけで、確認や取り消しは挟まらない)herdr agent read で対象 pane の状態を確認する。AskUserQuestion 等のメニューが表示中は send-text を使わない(ハイライトされている選択肢の Enter 確定にしかならず、誤確定の実害が出ている。詳細: Troubleshooting「AskUserQuestion メニュー表示中の誤確定事故」参照)herdr agent list で引き直し、古い pane-id を使い回さない(詳細: Troubleshooting「pane-id は非永続」参照)委任直後、作業者の状態が working に遷移したことを確認してから、blocked(詰まり)と idle(完了)の2状態を同時にバックグラウンドで待ち受ける(詳細: Troubleshooting「wait の即時解決」参照):
# gotcha: 対象が既に指定ステータスだと即座に解決してしまうため、working に遷移済みか確認してから仕掛ける
AGENT_NAME=<agent-name>
herdr agent get "$AGENT_NAME"
herdr agent wait "$AGENT_NAME" --status blocked > "/tmp/wait-blocked-${AGENT_NAME}.json" 2>&1 &
BLOCKED_PID=$!
herdr agent wait "$AGENT_NAME" --status idle > "/tmp/wait-idle-${AGENT_NAME}.json" 2>&1 &
IDLE_PID=$!
wait -n "$BLOCKED_PID" "$IDLE_PID"
# 生き残っている方が「発火しなかった側」。kill -0 で存否確認してから判別する
if kill -0 "$BLOCKED_PID" 2>/dev/null; then
FIRED_STATUS=idle
kill "$BLOCKED_PID" 2>/dev/null
else
FIRED_STATUS=blocked
kill "$IDLE_PID" 2>/dev/null
fi
Constraints:
<agent-name> を含める。複数 worktree を並行監視しているときに固定ファイル名だと内容が上書きされてしまうためwait -n は先に終了した方を検知する。ただし wait -n 自身はどちらが終了したかを返さないため、直後に kill -0 "$BLOCKED_PID"(シグナルを送らず存否だけ確認する)で生死を見て、生きている方=発火しなかった方、と判別してから後処理する。判別できたら $FIRED_STATUS を見て、blocked ならユーザーに承認を仰ぎ、idle なら herdr agent read "$AGENT_NAME" --source recent --lines 50 で完了報告を確認する<agent-name> は手順4でエージェントに付けたユニーク名。herdr agent wait / herdr agent read は pane-id ではなく agent 名を直接ターゲットにできるため、監視中に pane-id を引き直す必要がないherdr pane list 等を一定間隔で呼び続けるループ)は禁止。コストが高いうえ、このプロトコルが解消したいアンチパターンそのもの--status done は使わない(詳細: Troubleshooting「herdr agent wait は done を拒否する」参照)herdr wait agent-status <pane-id> --status <...|done|...> というコマンドもあるが、こちらは pane-id が必須かつ done を受け付ける UI 向けのコマンド。CLI 主導のこのプロトコルでは agent 名を直接使える herdr agent wait <agent-name> を使う--timeout(ミリ秒)は省略可能で、省略すると無期限にブロックする。バックグラウンドで放置する分には問題ないが、安全弁として妥当な値を指定してもよい相談 idle の判別:
作業者は【相談】送信後も司令塔からの回答を待つ間 idle に遷移する(手順4テンプレート「## 相談」参照)。そのため idle 発火は「完了」と「相談待ち」のどちらもありうる。
idle 発火時は完了と断定せず、herdr agent read "$AGENT_NAME" --source recent --lines 50 で直近ログを確認する。末尾付近に 【相談】 があれば「相談待ちの idle」、なければ「完了の idle」と判定するworking に遷移したことを確認したうえで、blocked/idle の2状態待ちを仕掛け直す(詳細: Troubleshooting「相談待ち idle と完了 idle の判別」参照)作業者からの報告内容そのもの(進捗・完了・気づき)を受け取るチャネル。主チャネルはあくまで手順5(2)の herdr agent wait で、作業者が idle/blocked に遷移したのを検知してから herdr agent read "$AGENT_NAME" --source recent --lines 50 で会話内容を読みに行くプル型。
作業者は完了時、上記のプル型に加えて司令塔へ1行の push 報告も送る(作業指示プロンプトの「## 報告」欄に規定。手順4「作業指示プロンプトのテンプレート」参照)。push はこのプロトコルの主チャネルではなく、agent wait が発火する前に司令塔の手が空いていた場合などに拾える即時性のための副次的な冗長化と位置づける。
作業者はこれとは別に、完了を待たず判断に迷った時点で【相談】push を送ることがある(作業指示プロンプトの「## 相談」欄に規定。手順4「作業指示プロンプトのテンプレート」参照)。【報告】が完了時の事後報告なのに対し、【相談】は判断時点でのエスカレーションで、送信後に作業者が idle 化する点が異なる。判別と応答の手順は上記(2)「相談 idle の判別」を参照。
Constraints:
idle/blocked の検知は push の有無に関わらず herdr agent wait(手順5(2))で行う。push は agent wait を代替しない【報告】<branch>: <一行サマリ>(<PR URL>)。詳細は会話内報告(プル型で回収する側)に書き、push は要約1行のみcommander-<repo名> が見つからない等)を理由に作業者の完了報告そのものを止めない。push はベストエフォートで、失敗時は会話内報告のみに縮退する作業者から PR 作成の完了報告(idle)を確認したら、司令塔はマージ可否を判断する(背景: #355)。マージ可能なのは以下の3条件が揃った(AND)ときだけ:
gh pr view <PR番号> --json mergeStateStatus --jq .mergeStateStatus
mergeStateStatus 別の対応:
| mergeStateStatus | 対応 |
|---|---|
| BEHIND | gh pr update-branch <PR番号> で base に追随させる |
| CLEAN | マージしてよい(実行はユーザー承認のもとで) |
| DIRTY | コンフリクトあり。作業者に rebase/merge を差し戻すか、ユーザーにエスカレーションする |
| BLOCKED | 単体では判別不能な複合ステータス。下記の GraphQL で切り分ける(詳細: Troubleshooting「BLOCKED は複合ステータス」参照) |
BLOCKED 検知時は reviewThreads の未解決数を確認する:
gh api graphql -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr) {
reviewThreads(first: 100) { nodes { isResolved } }
}
}
}' -f owner=<owner> -f repo=<repo> -F pr=<PR番号> \
--jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length'
Constraints:
BLOCKED を検知したら、CI実行中と conversation 未解決を区別するため上記 GraphQL で reviewThreads の未解決数を確認するmergeStateStatus が CLEAN になる前にマージを実行しない--delete-branch を付けない。worktree が生存中はローカルブランチ削除が必ず失敗して紛らわしいため、ブランチ削除(リモート含む)は /wtclean の領分とする運用中に踏んだ罠・バグ・環境摩擦の知見を、該当する skill/command の SOP に還流するプロトコル(背景: #358)。入力は以下のいずれか:
idle 確認時に読む)/wtclean の供養ステップ(手順6「知見の回収(供養)」)で抽出された Issue 候補Constraints:
/wt CIのキャッシュが壊れてるのを直したい
/wt nvimにcopilot連携を追加する
mise trust は絶対パス単位で管理されるため、新規 worktree は毎回 untrusted で始まる。忘れると mise run が「no tasks defined」で失敗する — #335。
~/.claude への反映は home-manager 経由で、mise run nix:switch を実行しないと ~/.claude/templates/ に反映されない。cp が No such file or directory で失敗したら、まず nix:switch 漏れを疑う。
auto mode での起動自体がハーネス(auto mode 分類器)に「ユーザーの明示許可がない」として拒否されることがある。その場合は AskUserQuestion 等でユーザーに auto mode 起動の許可を明示的に確認してから再実行する。
2026-07-05、作業者エージェントが検証用に起動したはずの Alacritty が実際にはマップされておらず、直後に pgrep -af alacritty で拾った PID をテスト用ウィンドウと誤認して kill し、ユーザーが元から開いていた既存の Alacritty(workspace 2)を誤終了させた(#354、PR #353)。自分が起動したプロセスは起動時の $! で PID を捕捉して追跡し、事後に名前ベースの pgrep で「自分のものらしきプロセス」を探して kill するのは禁止。
pane send-text は pane の入力欄にテキストを挿入するだけで、送信(実行)はされない。実機確認済み: send-text の直後に pane read してもコマンドは未実行のまま入力欄に残っており、続けて pane send-keys <pane-id> Enter を送って初めて実行される。
2026-07-26、#494/#466 の並行 worktree 運用(worker 2体 + 司令塔)で、作業者への追加指示のつもりで送った send-text + Enter が、表示中だった AskUserQuestion メニューの選択肢1「GPG エージェントをリセットして再試行」を誤確定させた。作業者が gpgconf --kill gpg-agent を実行し、ユーザーが直前に温めたパスフレーズキャッシュが消える実害が出た(#498)。手順5(1)の Constraint の通り、送信前に必ず herdr agent read で pane の状態を確認し、メニュー表示中は send-text を使わない(選択肢の Enter 確定のみで応答するか、メニューの解除を待つ)。
2026-07-26、#494/#466 の並行運用で、pane の入力欄にテキストが置かれたまま pane send-keys <pane-id> Enter が繰り返し効かず、作業者が再開できなくなった(同じ pane でメニューの選択肢確定には Enter が効いていたため、原因切り分けに時間を要した)。これは上記「send-text は単体では実行されない」(send-text だけでは実行されず別途 Enter が要る、という話)とは別の話 — real Enter を送っても Claude Code の chat 入力側で submit されないケースがある、という話。回避策(実機確認済み): herdr pane run <pane-id> "" — pane run はテキストと real Enter を1リクエストで送るため、空文字を渡せば real Enter のみを送って pending テキストを submit できる。下り=指示の標準手順(send-text + send-keys の2段)を pane run ベースに変える案もあるが、今回は採用を見送り、詰まった場合の回避策としてここに留める(#498)。
worker pane は tty を持たず(GPG_TTY も stale)、pinentry を表示できない構造がある。gpg-agent のパスフレーズキャッシュ(このリポジトリは TTL 8h)は agent プロセスのメモリ内にあり、gpgconf --kill gpg-agent や agent の再起動を行うと TTL に関係なく消える。運用(実機確認済み、2026-07-26、#494/#466、#498): ユーザーが自分の生きている端末で1回署名(例: echo test | gpg --clearsign -o /dev/null)してキャッシュを温めれば、同一セッションの全 worker のコミットが通るようになる。司令塔は gpg-connect-agent 'keyinfo --list' /bye の出力の cached フラグ(1)でキャッシュの有無を確認できる。署名コミットで詰まった場合、worker に gpgconf --kill gpg-agent 等でエージェントを殺させず、ユーザーに1回解除(署名)を依頼する。
pane-id はセッション中に compact されうる非永続 ID(詳細は .config/claude/skills/herdr/SKILL.md 参照)。
gotcha(実機確認済み): herdr agent wait は対象が既に指定ステータスだと即座に解決する。作業者がまだ working に遷移していない段階で idle 待ちを仕掛けると、起動直後の未初期化状態を完了と誤検知しかねない。
herdr agent wait に done を渡すとエラーになる(実機確認済みのエラーメッセージ: done is a UI attention state; use idle for CLI agent completion waits)。done は「人間がまだ見ていない完了」を表す UI 向けの状態で、CLI から作業完了を検知するときは idle を使う。
2026-07-05 の運用で、PR #348/#350 の mergeStateStatus: BLOCKED を「CI待ち」と解釈し、監視スクリプトが90分待機した(#355)。実際のブロック要因は Copilot レビューの未解決 conversation で、このリポジトリのブランチ保護では conversation 未解決はマージ不可。BLOCKED は CI実行中と conversation 未解決を区別できない複合ステータスのため、検知時は必ず GraphQL で reviewThreads の未解決数を確認する。
2026-07-04、copilot-quorum #303 の作業者が完了報告のため SendMessage を試行し、You are the main conversation エラーで失敗した(#341)。Claude Code のセッション間に直接チャネルはなく、作業者は自セッションの main のため司令塔という宛先が存在しない。上り報告は SendMessage ではなく、会話内テキスト出力(司令塔が herdr agent read で回収するプル型)と、herdr 経由の push(手順5「(3) 上り=内容」参照)の組み合わせで行う。
herdr が使えない環境(worktree だけで完結させたい等)では、作業者が report ファイルをスクラッチパッドに書き、司令塔が Monitor 等でポーリングするファイルベースのフォールバックも考えられる(#341 案C)。ただしポーリングコストがあり、herdr が使える環境では手順5「(3) 上り=内容」の下位互換にとどまるため、標準経路には採用していない。
作業者は【相談】送信後も司令塔からの回答を待つ間 idle に遷移するため、herdr agent wait の idle 発火だけでは完了と断定できない(#394)。判別・応答の手順は手順5「(2) 上り=イベント」の「相談 idle の判別」参照。
同リポジトリの過去セッション pane が名前を保持していると herdr agent rename が
agent_name_taken で失敗する。他 pane の rename は禁止(MUST NOT)のため、
commander-<repo名>-2 のように数字サフィックス(またはタスク由来の意味サフィックス)を付けて自分を命名し、
作業指示プロンプト内の宛先(【相談】【報告】の2箇所)も同じ名前に揃えること。
サフィックス付き名でも上り報告プロトコルはそのまま機能する(実機確認済み)。
3件の実例で再発しており、衝突は1回きりの偶発事象ではなく再発する運用パターンであることを示す:
commander-copilot-quorum → -2commander-dotfiles → -2 → -3(サフィックスが2つ埋まっている状態での発生)commander-dotfiles → 意味サフィックス -dpp。このケースでは保持者(pane w3C:p2)が過去セッションの残骸ではなく、同リポジトリで別タスクを進行中の同時稼働 live セッションだったことが判明した。この種の衝突は正当な同時運用が原因のため、stale 名の掃除では解決せず、サフィックス命名規定そのものが本質的な対応になる(意味サフィックスは複数司令塔が並行稼働時にどれがどれか識別しやすい利点がある)Nerd Font の PUA グリフ等をツール呼び出しで直接タイプすると、バイト列が消失して空文字列になったり、意図せず \uXXXX テキストに化けたりする(不可視文字はエディタ・diff・レビューUIのどこでも見えず、目視でのミス検出ができない構造的な罠 — #363、PR #366)。該当する書き込みは以下の手順で行う: JSON ファイルへは、コードポイントが BMP 内(U+FFFF 以下)なら \uXXXX エスケープをリテラル ASCII 文字列として書いてよいが、U+10000 以上(サロゲートペアが必要。Nerd Fonts 由来の記号で頻出、例: U+F0A1E)では \uXXXX 単体では表現できず手順が破綻するため、python3 -c "import json; print(json.dumps('<文字>', ensure_ascii=True))" 等でサロゲートペアのエスケープを機械生成して貼る。JSON 以外のファイルは Python の chr() でコードポイントから機械的に文字列を組み立ててファイル I/O で書き込む。書き込み後は hex dump(xxd 等)で機械的に検証する(目視確認は禁止)。コードポイントの正典は ryanoasis/nerd-fonts リポジトリの glyphnames.json。