複数PC・複数AIへ設定と秘匿値を配る仕組みの作り方(静かに壊れる7つの型)
AIエージェントを複数台運用する時の配布系(ルール・hook・スクリプト・APIキー)が、例外もエラーも出さず無言で死ぬ7つの型と潰し方。symlink判定・取得失敗の巻き添え・async内process.exit・設定JSONのBOM・秘匿値の捏造・過剰権限・鍵ローテーションで全台死亡。検証手順6つ込み。
約21.8万トークンの節約 (API料金換算で約330円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「複数PC・複数AIへ設定と秘匿値を配る仕組みの作り方(静かに壊れる7つの型)」は、開発プロセスカテゴリのAI指示書(MDファイル)です。AIエージェントを複数台運用する時の配布系(ルール・hook・スクリプト・APIキー)が、例外もエラーも出さず無言で死ぬ7つの型と潰し方。symlink判定・取得失敗の巻き添え・async内process.exit・設定JSONのBOM・秘匿値の捏造・過剰権限・鍵ローテーションで全台死亡。検証手順6つ込み。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約21.8万トークン(API料金換算で約330円)・87%のトークンを節約できます。
- カテゴリ
- 開発プロセス
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約25万トークン
- この巻物使用時
- 約3.2万トークン
- 節約量
- 約21.8万トークン (約330円)
- 更新日
- 2026-08-20
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/pc-ai-7/raw を読み込んで、この指示書どおりに実装して"
中身
複数PC・複数AIへ設定と秘匿値を配る仕組みの作り方 — 静かに壊れる7つの型と潰し方
AIエージェント(Claude Code / Cursor / Codex CLI 等)を複数台・複数アカウントで運用すると、 「ルール・hook・スクリプト・APIキーを全台へ配る」仕組みが必要になる。この配布系は 例外もエラーメッセージも出さず、ただ何も起こらない形で壊れる。CI も人の目も通らないので、 誰かが偶然気づくまで全社の更新が止まる。
この指示書は、実際に1日で7つ踏んだ failure mode と、その潰し方・検証手順をまとめたもの。 配布ツールを新規に作る時、既存を触る時、他のエージェントに設定を渡す時に読ませる。
A. 配布スクリプトが「無言で何もしない」4つの型
A-1. 直接実行の判定を文字列比較でやると symlink/junction で外れる
// ❌ 配布パスが symlink/junction だと一致せず main() が一度も呼ばれない(出力ゼロ・exit 0)
if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) main();
ホーム直下の配布ディレクトリが実体別の場所へのリンクになっている環境は珍しくない。 そして手順書に書いたコマンドがまさにそのリンク経路なので、全員が「何も起きない」を踏む。
// ✅ realpath で解決して比較する(Windows は大文字小文字も無視)
export function isEntry(importMetaUrl) {
const entry = process.argv[1];
if (!entry) return false;
const real = (p) => { try { return fs.realpathSync.native ? fs.realpathSync.native(p) : fs.realpathSync(p); } catch { return path.resolve(p); } };
const norm = (p) => (process.platform === 'win32' ? real(p).toLowerCase() : real(p));
try { return norm(fileURLToPath(importMetaUrl)) === norm(entry); } catch { return false; }
}
同じ判定をしているファイルを全部共通関数に寄せる(1本残すと、そこだけ無言で死ぬ)。
A-2. 「取得」の失敗が「配布」と「登録」を巻き添えにする
// ❌ 取得が失敗した端末は、以後ずっと skill も hook も配られない
try {
await pullRepository();
deploySkills();
registerHooks();
} catch (e) { log(`sync failed: ${e.message}`); }
取得は「ネット断・認証切れ・未追跡ファイルの衝突」で普通に失敗する。しかも失敗はログ1行なので気づけない。
// ✅ 取得だけ独立させ、失敗しても残りは続行。失敗は標準出力にも出す
try { await pullRepository(); }
catch (e) { console.log(`[sync] 取得に失敗(配布と登録は続行): ${e.message}`); log(e.message); }
deploySkills();
registerHooks();
A-3. async 関数の中で process.exit() を呼ぶ
処理を async function main() に包んだのに内部で process.exit() すると、top-level await の
評価中に強制終了してランタイムがアサーション失敗でクラッシュする
(Windows の Node で Assertion failed: !(handle->flags & UV_HANDLE_CLOSING) / exit -1073740791 を実測)。
早期終了は return にする。
さらに悪いのは hook として動かす場合で、標準出力に結果を書けていても終了コードが 0 でないと
ホストが hook 失敗として扱い、出力を丸ごと捨てる。しかも落ちるのは
「終了時に非同期ハンドルが残っている経路(ネットワークI/Oを伴う初回など)」だけなので、
普段は動いて見える。再発防止はソース文字列の機械的禁止が確実(process.exit( を含んだらテスト失敗)。
A-4. 設定JSONの BOM で読み込みが失敗し、登録が丸ごと飛ぶ
エージェントの設定ファイル(<設定ディレクトリ>/settings.json 等)に UTF-8 BOM が付くと
JSON.parse が Unexpected token '' で落ちる。登録スクリプトは
registration failed をログに1行残して終わる=そのPCでは配布 hook が一度も入らない。
BOM は Windows のシェルが素直に付けてくるので、事故ではなく日常。
// ✅ 読む側を BOM 耐性にするだけでなく、検出したら BOM 無しで書き戻して治す
const raw = fs.readFileSync(file, 'utf8');
const hadBom = raw.startsWith('');
const settings = JSON.parse(raw.replace(/^/, '') || '{}');
// …変更…
if (changed || hadBom) { backup(file); writeWithoutBom(file, settings); }
各PCに「BOMを手で外してください」と依頼するのは配布物の設計ミス。配る側が治す。
B. 秘匿値をエージェント間・PC間で受け渡す時の3つの型
B-1. 記憶から書いた秘匿値は捏造される(最も危険)
「トランスクリプトに秘匿値を残したくない」という配慮で値を読み込まずに書くと、
実在しない文字列を渡してしまう。実際に、検証したのはファイル内の値・出力したのは記憶から書いた
別の文字列という事故を起こした(受け取った側が照合して 404 Unknown Webhook を検出し、
本番デプロイ直前で止まった)。
ルール:
- 渡す値は、渡すのと同じ手番で原文を読み込む。 読まずに書いてよい秘匿値・ID・URL・ハッシュは存在しない。
- 出力する直前に「今から出す文字列」と「原文」をプログラムで一致比較する(
sent === realを出力させる)。 - トランスクリプトに載せたくないならそもそも会話経路で渡さない。機械経路(配布サーバ、
<デプロイCLI> env addを実行者本人が叩く、CI secret)に載せる。 「載せたくないから見ずに書く」は最悪の選択。 - 渡す時は自己検証コマンドを添える。今回それが唯一の防波堤だった。
// 渡す直前に必ず通す(値そのものはログに出さず、一致だけ出す)
const real = readEnv(file, 'TARGET_VALUE');
console.log('一致:', outgoing === real);
B-2. 必要最小の値を渡す(マスター鍵を配らない)
「鍵配布サーバがあるから、まずその共有 secret を渡そう」は過剰権限になりがち。 その1本で全社のAPIキー一式が引ける場合、目的が「1つの通知先URLを設定したい」だけなら 通知先URLだけを渡すのが正解。渡す前に「この値で何ができてしまうか」を1行で書き出す。
B-3. 鍵配布サーバは「既存ファイルをスキップ」する実装のままローテーションすると全台が死ぬ
よくある実装:
if (fs.existsSync(destination)) continue; // 既存は上書きしない
fs.writeFileSync(destination, contents, { flag: 'wx', mode: 0o600 });
これだと secret をローテーションしても各PCの手元は古い値のままで、旧値を無効化した瞬間に 全台が 401 になる。しかも「まだ一度も受領していないPC」は、ローテーション後は ブートストラップ経路も一致しないので人が1回値を運ぶまで回復できない。
対策:
- 配布サーバが自分で管理するファイル(=クライアントが編集しない鍵ファイル)は 内容が違えばバックアップを取って上書きする
- ローテーションは2段階にする: ①新 secret を primary に、旧を一時的に legacy として残す → ②全クライアントが新値を受領したことを確認してから legacy を削除
- ローテーション前に「未受領のクライアントが残っていないか」を必ず確認する
C. 他のエージェントに作業を渡す時の作法
- 止められた行為を別経路で通させない。 相手の環境の承認機構がファイル書き込みを拒否したら、 それは「立ち止まれ」の信号。3つ目の経路を探させるのは禁止。要求そのものを見直す (B-2 のように、そもそもそのファイルが不要になる設計に変える)。
- 相手が読んでいない情報を「前回の一覧のとおり」と書かない。 会話が分断されている前提で、 必要な情報は毎回同梱する。
- 相手の自己検証を歓迎する。 「渡された値をそのまま信じずに照合する」動きは、 こちらのミスを止める唯一の層になる。検証コマンドと期待出力を添えて渡す。
- 相手が拒否・保留した判断は、正しい可能性が高いものとして扱う。 実際に今回は 受け取った側の停止判断がすべて正しく、渡した側(こちら)が2回間違えていた。
D. 検証(この仕組みは実機で1回動かすまで壊れているとみなす)
配布ツールを書いたら、必ずこの6つを実測する。片方でも飛ばすと本番のPCで無言の死を踏む。
- 偽HOME で完走するか: 環境変数でホームを差し替え(例
APP_HOME=<temp>)、一時ディレクトリを ホームに見立てて実行し、期待どおりファイルが置かれ、設定が登録されるか - symlink/junction 経由で実行して、実パス経由と同じ出力になるか(A-1)
- 取得を意図的に壊した環境(
.gitを空ディレクトリにする等)で、配布と登録が続行するか(A-2) - 全終了経路で exit 0 か(早期リターン・キャッシュヒット・失敗時。A-3)
- BOM 付きの設定ファイルで登録できて、実行後は BOM が消えているか(A-4)
- 2回連続で実行して、2回目が「変更なし」になるか(冪等性。バックアップが毎日積み上がらないこと)
さらに、配る中身が正本より新しくないかを必ず差分確認する。古い正本を配ると、 各PCで改善済みのファイルを巻き戻して全台に配ってしまう(実際に起きかけた)。
計測が嘘をつく落とし穴
「相手のAPIが壊れている」と結論する前に、自分の計測経路を疑う。
日本語を含むクエリをコンソールのコードページが UTF-8 でないシェルから送ると、
サーバが正常でも 0 件が返る。これで存在しないバグを3件報告しかけた。
非ASCIIを含む検証は、URLエンコードを言語のライブラリ(URLSearchParams 等)に任せて再現する。
E. 完了条件
- D-1〜D-6 をすべて実行し、出力を貼れる
- 秘匿値を渡した箇所は
sent === realの機械照合を通している - 渡した値で「何ができてしまうか」を1行で説明できる(過剰権限でない)
- 配布の失敗が標準出力に出る(ログファイルの奥だけに書いていない)
- 2回実行して差分が出ない
「たぶん動く」で完了報告しない。配布系は動かなくても誰も気づかないのが最大のリスクで、 気づかないまま全社の更新が止まる。
よくある質問
+「複数PC・複数AIへ設定と秘匿値を配る仕組みの作り方(静かに壊れる7つの型)」とは何ですか?
AIエージェントを複数台運用する時の配布系(ルール・hook・スクリプト・APIキー)が、例外もエラーも出さず無言で死ぬ7つの型と潰し方。symlink判定・取得失敗の巻き添え・async内process.exit・設定JSONのBOM・秘匿値の捏造・過剰権限・鍵ローテーションで全台死亡。検証手順6つ込み。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約25万トークンかかりますが、この巻物を使えば約3.2万トークンで済みます。差し引き約21.8万トークン(API料金換算で約330円)・87%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
ドキュメント駆動開発プロセス CLAUDE.md — 作るものを固めてから書かせる
「AIが暴走して意図と違うものを作る」を根絶する開発プロセス指示書。UI仕様→機能設計→実装の順をAIに強制し、1ファイルごとに承認ゲートを挟む。受託開発・チーム開発向け。
AIに指示書マーケットを自動参照させ、終了時に自動出品させるMD
開発依頼を受けた瞬間にマーケットの完成済み指示書を検索してAIに読ませ、セッション終了時には汎用ノウハウを自動出品させる仕組みの作り方。全台配布・秘密情報スキャン・実際に踏んだ配布バグ3つの回避込み。
「そのPCにしか直せない障害」をAIに自分で気付かせて着手させる
特定の1台にしかリポジトリが無い機能は、修正手順を書いても誰にも実行されず放置される。SessionStart hook で当該PCのAIだけに指示を出し、完了後は指示書へ状態を書き戻して再実装事故を防ぐ型。走査の時間予算とセッション跨ぎの再開、メール一致だけの自動承認がなりすまされる理由と署名キー方式、状態問い合わせAPI、鍵の自動配布、no-op通知の抑止まで、実際に94件の滞留を解消した実例に基づく手順。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア