AIエージェントから別のコーディングCLIへ安全に委譲するMD — 丸1日hangを止める
監督AIから実装役のコーディングCLIへBash経由で委譲するときの呼び出し方。argvで指示を渡すとシェルがバッククォートを実行して仕様が消え、TTY付き起動はstdin待ちで無限hangする。実測1日hangの死因3つと、フックで機械的に検出する型・回帰テストの書き方まで。
約3.9万トークンの節約 (API料金換算で約59円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「AIエージェントから別のコーディングCLIへ安全に委譲するMD — 丸1日hangを止める」は、AIのしつけカテゴリのAI指示書(MDファイル)です。監督AIから実装役のコーディングCLIへBash経由で委譲するときの呼び出し方。argvで指示を渡すとシェルがバッククォートを実行して仕様が消え、TTY付き起動はstdin待ちで無限hangする。実測1日hangの死因3つと、フックで機械的に検出する型・回帰テストの書き方まで。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約3.9万トークン(API料金換算で約59円)・93%のトークンを節約できます。
- カテゴリ
- AIのしつけ
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約4.2万トークン
- この巻物使用時
- 約3,000トークン
- 節約量
- 約3.9万トークン (約59円)
- 更新日
- 2026-08-27
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/ai-cli-md-1-hang/raw を読み込んで、この指示書どおりに実装して"
中身
AIエージェントから別のコーディングCLIへ安全に委譲するMD
監督役のAIエージェント(Claude Code 等)から、実装役のコーディングCLI(Codex CLI 等)へ Bash 経由でタスクを委譲するときの、沈黙して死なない呼び出し方。
そのまま読ませれば適用できる粒度で書いてある。委譲そのものの是非ではなく「渡し方」の話。
結論(これだけ守れば足りる)
- 指示は必ずファイルで渡す。argv に置かない
- TTY を渡さない(stdio を全て pipe にするか、stdin をファイルからリダイレクトする)
- 上限時間を必ず付ける(既定30分程度)
- 出力を
| tail/| headに流さない
推奨形(ラッパー経由):
node <ツール置き場>/agent-do.mjs --prompt-file <指示ファイル> --cwd <対象パス> --timeout 1800
直に叩く場合:
<コーディングCLI> exec -s workspace-write - < prompt.md
なぜ(実際に起きた事故)
委譲が 丸1日(実測 1日00時間57分)hang し、翌日まで誰も気付かなかった。 調べると同型の hang が他に2本(1日 / 19時間)過去セッションから生き残っていた。 前から起きていたのに気付けていなかった。死因は委譲先ではなく呼び出し方で、 3つ同時に起きていた。
死因1: argv で渡すとシェルが指示文を実行する
次の形で渡した:
<shell> -lc '<CLI> exec --sandbox workspace-write "$(cat prompt.md)"'
指示文の中でファイル名やテーブル名をバッククォートで囲んでいたため、それが コマンド置換として実行された。実際に届いた指示は:
- 「新規ファイル を1つだけ作成する」=作るべきファイル名が消えている
- 参照用に名前を書いただけの既存スクリプトが起動し、その標準出力が 指示本文に混入していた
- ログには
command substitution: syntax error near unexpected tokenや<テーブル名>: command not foundが並ぶ
"$(cat f)" は理屈上は再展開されない。しかしシェル層が2重になると実際に展開された
(コンテナ/WSL などのランチャー → -lc の順で重なるケース)。
理屈で安全と判断せず、シェルを1層も通さない経路にすること。
死因2: TTY 付きで起動すると stdin 待ちで永久に眠る
多くのコーディングCLIは、端末が繋がっていると追加入力を待つ
(Reading additional input from stdin... 等を出したまま止まる)。
ps の stat が Ssl+ になっているのが目印で、末尾の + が
「TTY のフォアグラウンドプロセスグループ」を意味する。誰も打たないので永遠に終わらない。
死因3: | tail でパイプすると進捗が1行も見えない
パイプはバッファされるため、完了するまで何も出力されない。 hang しているのか実行中なのか区別できなくなる。背景実行してログファイルを直接読むこと。
実装(ラッパー側の要点)
子プロセス起動時:
const child = spawn(command, args, { stdio: ['pipe', 'pipe', 'pipe'] }); // TTY を渡さない
const timer = setTimeout(() => { timedOut = true; child.kill('SIGKILL'); }, timeoutSeconds * 1000);
child.stdout.on('data', (c) => process.stdout.write(c)); // そのまま流して進捗を見えるようにする
child.on('close', (status) => { clearTimeout(timer); resolve({ status: timedOut ? 124 : status }); });
child.stdin.end(prompt); // ← 必ず閉じる。閉じないと相手が待ち続ける
--prompt-fileを受け、fs.readFileSyncした中身を指示とする(argv 経由を廃止する)--timeout <秒>を受ける。既定 1800。タイムアウトは exit 124 で区別できるようにする- 「差分が無い=書き込めていない」といった事後判定をしている場合、 タイムアウト時はその判定に落とさない(別の失敗として扱う)
診断(返ってこない時)
ps -eo pid,etime,stat,args | grep '[a-z]*cli-name'
statの末尾に+→ TTY のフォアグラウンド。入力待ちの hang を疑うetimeが時間・日単位 → 明らかに死んでいる。kill してよい- 定期的に見るのではなく、上限時間で自動的に切れるようにしておくのが本筋
機械的に強制する(推奨)
ルールを文書に書くだけでは守られない。エージェントのフック機構 (コマンド実行の直前に割り込める仕組み)で、危険な形を検出して警告する。
検出する形:
| 検出名 | 条件 | なぜ危険か |
|---|---|---|
shell-wrapped | bash -lc / sh -c を経由している | シェル層が増えバッククォート・$() が展開される |
argv-prompt | exec の後に -(stdin) も <(リダイレクト) も無い | 指示が argv に置かれている |
backtick-in-argv | コマンドに ` か $( があり、ファイル/stdin 経由でない | シェルに実行される |
piped-output | 出力を | tail / | head に流している | バッファされ hang と区別がつかない |
no-timeout | --timeout も timeout <数値> も無い | 無限待ちを止める上限が無い |
ブロックはせず警告に留める(正当な例外を殺さないため)。警告文には必ず 正しいコマンドの完成形を併記する。書き換え先を示さない警告は無視される。
落とし穴: 正しい使い方を罰しない
ラッパーが既定タイムアウトを内蔵しているなら、ラッパー利用時は no-timeout を鳴らさない。
推奨した使い方で毎回警告が出る gate は、すぐ読まれなくなる。回帰テストで固定しておくこと。
既存の誘導も直す
同種のフックやドキュメントが古い argv 形を例示していないかを必ず確認する。 今回、別のフックが出す推奨コマンドが argv 形(=事故そのものの形)のままで、 ルールを配っても逆方向に誘導し続ける状態だった。
検証のしかた
実際に事故ったコマンド文字列をフックに食わせ、検出できることを確認する。 テストケースを想像で書かず、事故の実物を回帰テストにする。
最低限のテスト:
- 推奨形(ファイル渡し + timeout)→ 何も出力しない
- argv 渡し → 検出する
- シェル経由 → 検出する
| tail→ 検出する- タイムアウト無し(ラッパー未使用時のみ)→ 検出する
- 無関係なコマンド / 対象外のツール名 → 何も出力しない
- 壊れた入力 → 例外を握りつぶして exit 0(フックが本体を止めない)
委譲先の生成物は必ずレビューする
呼び出し方を直しても、委譲先が指示どおり書くとは限らない。 実例: 「必須項目リストから X を外す」と指示したのに、リストに X を残したまま フォールバック処理を書き足し、先に例外が飛ぶので後段が死にコードになっていた。 構文チェックもテストも通るため、読まないと気付けない。
受け入れ前に必ず:
- 依頼したスコープ外のファイルを触っていないか(差分の削除行まで読む)
- 指示した条件が本当に反映されているか(「それっぽい実装」で満足しない)
- 実際に動かして出力を目視する
よくある質問
+「AIエージェントから別のコーディングCLIへ安全に委譲するMD — 丸1日hangを止める」とは何ですか?
監督AIから実装役のコーディングCLIへBash経由で委譲するときの呼び出し方。argvで指示を渡すとシェルがバッククォートを実行して仕様が消え、TTY付き起動はstdin待ちで無限hangする。実測1日hangの死因3つと、フックで機械的に検出する型・回帰テストの書き方まで。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約4.2万トークンかかりますが、この巻物を使えば約3,000トークンで済みます。差し引き約3.9万トークン(API料金換算で約59円)・93%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
AI運用ルールを機械的に守らせる hook 設計 — ルール文が守られない本当の理由
チームでAIエージェントを使うと運用ルールが必ず守られなくなる。真因は「読んでいない」ではなく hook がそのマシンで登録されていない/委譲先が沈黙して壊れていること。禁止=実行前拒否・誘導=依頼時の具体コマンド注入・担保=セッション開始時の自己修復の3層、明示例外の短命トークン、warn→blockの段階昇格、BOM/サンドボックス/timeout など失敗が沈黙する罠と、環境依存で落ちないテストの作り方までを実測ベースでまとめた導入手順。
マキモノ検索スキル — AIが自分で巻物を探して使えるようになるMD
あなたのAIエージェント (Claude Code等) にこのMDを読ませると、開発タスクを受けたとき自動でマキモノAPIを検索し、最適な指示書を取得してから作業するようになります。導入は貼るだけ。
無人AIセッションのバックグラウンド委譲が静かに殺される事故を潰す
ヘッドレスで起動したAIエージェントがバックグラウンド委譲した子プロセスは、ターン終了で kill されるのに親は exit 0 を返す。機械的に deny するフック、通知の作り方、対応中フラグの戻し忘れ、Windows製worktreeがLinux側から解決できない罠までを含む恒久対策。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア