org-setup: 組織の許可設定を一括配置
組織の各ロールが必要とする permissions allow と環境変数を、
正しいスコープの settings ファイルに配置する。
輸送層 両系(ORG_TRANSPORT: 既定 renga / opt-in broker): 本スキルが配る messaging MCP の allow は 既定 renga(ORG_TRANSPORT 無設定)で mcp__renga-peers__* tier。references/permissions.md は renga アンカー(byte 比較対象)として不変であり、broker への置換は prose ではなく生成/検証ツール側で行う: tools/org_setup_prune.py(per-role allow / --user-common-allowlist)と tools/check_role_configs.py が ORG_TRANSPORT=broker のとき mcp__renga-peers__* ブロックを broker messaging tier(mcp__org-broker__*)に射影する(runtime の transport_allowlist descriptor 駆動、Epic #6 E)。既定 renga は恒等(生成物 byte 等価・file no-op)なので本スキルの手順・報告文はそのまま使えばよい。設計 SoT は transport-lab docs/design/ja-migration-plan.md §5.3、契約面は docs/contracts/backend-interface-contract.md Surface 8(ratified 2026-06-14)。
設定ファイルの配置先とスコープ
Claude Code は起動ディレクトリの .claude/ 配下から設定を読み込む。
ただしリポジトリ直下の .claude/settings.local.json は、サブディレクトリで起動したセッション(ディスパッチャー等)にも読まれる(.claude/skills/org-setup/references/permissions.md 窓口節の sandbox.network.allowedDomains の注記)。
そのため、ロール固有の設定はロールごとの設定ファイルに置き、窓口の local ファイルには他ロールに掛かって困るキーを足さない。
| スコープ | ファイルパス | 対象 |
|---|
| ユーザー共通 | ~/.claude/settings.json | 全プロジェクト・全ロール |
| 窓口 | <repo>/.claude/settings.local.json | リポジトリルートで起動した窓口 |
| ディスパッチャー | <repo>/.dispatcher/.claude/settings.local.json | .dispatcher/ で起動したディスパッチャー |
| キュレーター | <repo>/.curator/.claude/settings.local.json | .curator/ で起動したキュレーター |
| ワーカー | ワーカーディレクトリの .claude/settings.local.json | org-delegate が動的に作成 |
sandbox 内からは書けない書き先(窓口・ユーザー共通)
Claude Code の Bash sandbox は、書き込みを許した範囲の中でも作業ディレクトリとその親の .claude 設定ファイル、および ~/.claude 配下の大半への書き込みを拒否し、例外指定もできない(https://code.claude.com/docs/en/sandboxing 「Protected paths」)。リポジトリルートで動く窓口から見ると、上表のうち次の 2 つがこれに当たる:
- 窓口の
<repo>/.claude/settings.local.json(tools/org_setup_prune.py の role_settings_path が secretary に返すパス)
- ユーザー共通の
~/.claude/settings.json(Step 6 の --user-common-sandbox の書き先)
ディスパッチャー・キュレーター用(.dispatcher/ / .curator/ 配下)は窓口の作業ディレクトリより下なので sandbox 内から書ける。読むだけの --dry-run も sandbox 内でよい。
この 2 つに書くコマンド(Step 5 の --role secretary / --all、Step 6 の --user-common-sandbox。いずれも --dry-run なし)は、次の 2 段で実行する:
-
最初から sandbox 外で実行する: Bash tool に dangerouslyDisableSandbox: true を付けて実行する。sandbox 内で一度失敗させてから付け直す必要はない
-
それが拒否されたら人に頼む: 承認が拒否された、または dangerouslyDisableSandbox が効かず(allowUnsandboxedCommands: false の環境では無視される: 同ページ「Turn off the retry with strict sandbox mode」)Read-only file system / Permission denied で失敗した場合は、dangerouslyDisableSandbox を再要求せず(繰り返すと安全分類器のロックアウトで作業不能になる)、ユーザーに次の文言でプロンプトへの入力を頼む:
窓口用の許可設定ファイルは安全機構の都合で私からは書き込めません。
お手数ですが、プロンプト欄に次の 1 行を入力して実行してください(先頭の ! まで含めて):
! python3 tools/org_setup_prune.py --role secretary
コマンド行は実際に止まったものに差し替える(--all / --user-common-sandbox 等。Windows native は py -3)。! 付きの行はユーザーのシェルで sandbox を通らずに実行され、出力が会話に入る。その出力で成否を確認してから Step 4 の報告に進む
各ロールの必要設定
正典は tools/org_extension_schema.json。.claude/skills/org-setup/references/permissions.md に、その schema を満たす全ロールの JSON テンプレートがある(一致は tools/check_role_configs.py が CI で検査する)。以下の手順でこのテンプレートを参照する。
実行手順
Step 1: 現在の設定を読み取る
以下の4ファイルを読み取る(存在しない場合は空オブジェクト扱い):
~/.claude/settings.json
<repo>/.claude/settings.local.json
<repo>/.dispatcher/.claude/settings.local.json
<repo>/.curator/.claude/settings.local.json
Step 2: 差分を特定する
各ファイルについて、上記「各ロールの必要設定」と比較し、不足しているエントリを特定する。
Step 3: マージして書き込む
不足分を追加する。既存の設定は削除しない(ユーザーや他ロールが足した設定を失うため)。
permissions.allow は配列なので、既存エントリを保持しつつ新規エントリを追加する。
env はオブジェクトなので、既存キーを保持しつつ新規キーを追加する。
claudeMdExcludes(ディスパッチャー)も配列として既存を保持して追加する。{claude_org_path} は絶対パスに置換する。
sandbox.network.allowedDomains(窓口・ディスパッチャー。/work-discovery 判定段の api.anthropic.com)も配列として既存を保持して追加する。sandbox の他のキー(enabled / filesystem)はテンプレートに無いので足さない(理由は .claude/skills/org-setup/references/permissions.md 窓口節の sandbox.network.allowedDomains の注記)。
Step 3.5: operator-local な生成ファイルを配置する(未配置時のみ)
許可設定と同じく、fresh clone 直後に無い operator-local ファイルをここで揃える。
いずれも既存があれば上書きしない(operator の実データが入っているため)。
registry/projects.md(プロジェクトレジストリ、Issue #811)— コミットされているのは
テンプレート registry/projects.example.md の方で、実体は git 管理外:
python3 tools/ensure_projects_registry.py # Mac/Linux
py -3 tools/ensure_projects_registry.py # Windows native
Step 4: 結果を報告する
変更があった場合:
設定を更新しました:
- ~/.claude/settings.json: renga, renga-peers の許可を追加
- .dispatcher/.claude/settings.local.json: claude 起動コマンドの許可を追加
- (変更なし: .curator/.claude/settings.local.json)
変更がなかった場合:
全ての設定は最新です。変更はありません。
Step 5: drift を解消する(--prune モード)
通常の Step 1〜3 は additive-only(不足分を追加するだけで既存は削除しない)。
過去に蓄積した広すぎる allow や旧エントリは残り続けるため、
permissions.md のテンプレートで settings.local.json を完全に書き換える prune モードを用意している。
実行は tools/org_setup_prune.py を使う(Windows native は python3 を py -3 に読み替える):
# 差分プレビュー(書き換え無し)
python3 tools/org_setup_prune.py --role secretary --dry-run
python3 tools/org_setup_prune.py --all --dry-run
# 実行(タイムスタンプ付き .bak を自動生成 → 書き換え)
python3 tools/org_setup_prune.py --role secretary
python3 tools/org_setup_prune.py --all
対象ロール: secretary / dispatcher / curator。
--role secretary と --all(--dry-run なし)は窓口用ファイルに書くので、
「sandbox 内からは書けない書き先」の 2 段で実行する。
(user_common は ~/.claude/settings.json で他プラグインと同居するため対象外。
ワーカーは org-delegate が動的生成するため対象外。)
user 拡張の保護: settings.local.override.json
prune は permissions.md の role テンプレートで丸ごと書き換えるため、
個人で追加した allow / env / hook をそのままにすると消えてしまう。
これを避けるため、各 settings ファイルと同じディレクトリに
settings.local.override.json を置くと、prune 時に deep-merge される。
例: 窓口で Bash(my-private-tool:*) を恒久的に許可したい場合は
.claude/settings.local.override.json に以下を書く(このファイルは
prune ツールが読むだけで、書き換えはしない):
{
"permissions": {
"allow": ["Bash(my-private-tool:*)"]
}
}
マージ規則:
permissions.allow / permissions.deny: base 順を保ったまま和集合
env: キー単位 merge(override 側が勝つ)
hooks.PreToolUse[] 等: 等値判定で重複排除した上で append
- それ以外のスカラー: override が勝つ
override と .bak は .gitignore で ignore 済み(個人設定のため。.curator/.claude/ と
.dispatcher/.claude/ 配下はディレクトリごと ignore)。チームで共有したい設定は
schema (tools/org_extension_schema.json) → permissions.md の順で追加する。
tools/check_role_configs.py は同じ override ファイルを読み、その allow を
closed-world 検証から除外する(_load_override_allow)。よって override に追加した
個人 allow は CI / --include-local で unknown allow entry にならない。
ただし schema の global.forbidden_allow_exact(Bash(git *) 等の wide allow)、
global.forbidden_allow_regex(旧名 ^mcp__claude-peers__)、roles.<role>.disallow_allow_regex
(^Bash(*)$ 等)に当たる allow は override 側にあっても ERROR となる。安全契約は override で迂回できない。
{claude_org_path} の解決(窓口 / dispatcher / worker)
窓口・dispatcher・worker のテンプレートには {claude_org_path} プレースホルダがある
(hook command を絶対パスで固定するため。相対パスだと cwd が org ルート以外のロールで
hook が解決されず、ガードが無言で無効化する)。prune ツールは以下の優先順で解決する:
--claude-org-path <abs> 引数
- 既存
settings.local.json の env.CLAUDE_ORG_PATH
- 既存 hook command 内の
bash "<abs>/.hooks/..." の <abs>
- audit root(
--root、既定はリポジトリルート)。<root>/.hooks/ に schema の
required_hook_scripts が全て実在する場合のみ採用する
窓口テンプレートには env.CLAUDE_ORG_PATH が無いため、初回実行では 2 も 3 も取れず 4 で解決される。
4 の条件を満たさない(org checkout ではない)場合は unresolved placeholders で中断するので、
誤った --root の内容が黙って書き込まれることはない(4 の条件の理由は .claude/skills/org-setup/references/rationale.md)。
いずれも取れない場合(fresh install など)は --claude-org-path を明示する:
python3 tools/org_setup_prune.py --role dispatcher --claude-org-path "C:/Users/me/work/claude-org"
バックアップ
書き換え前に settings.local.json.bak.YYYYMMDD-HHMMSS を同ディレクトリに作成する。
失敗時はこの .bak を mv で戻せば原状復帰できる。
不要であれば --no-backup で抑止できる。
Step 6: ユーザー共通の sandbox denyRead / denyWrite 補強(--user-common-sandbox)
初回セットアップで 1 回実行する: 本リポジトリを clone したら python3 tools/org_setup_prune.py --user-common-sandbox を 1 回実行する(冪等。Windows native は py -3)。共有 .claude/settings.json には個人 path を置いていないため、未実行だと 個人環境の sandbox denyRead / denyWrite 補強が欠けたままになる。
--user-common-sandbox は ~/.claude/settings.json の sandbox.filesystem.denyRead と denyWrite(~/.claude/settings.json 自身)に idempotent な union-merge を行う専用モード(他キーは無触):
# diff プレビュー
python3 tools/org_setup_prune.py --user-common-sandbox --dry-run
# 実行(既存があれば .bak 自動生成、上書き候補がない場合は no-op)
python3 tools/org_setup_prune.py --user-common-sandbox
書き先の ~/.claude/settings.json は sandbox 内から書けないため、実行(--dry-run なし)は
「sandbox 内からは書けない書き先」の 2 段で行う。
denyRead の対象ディレクトリ(~/.ssh / ~/.aws / ~/.kube / ~/.gnupg / ~/.docker / ~/.config/aws-vault)のうち、実在し、かつ realpath が HOME を escape しない symlink でない ものだけが追加される。WSL2 + DriveFS の ~/.aws → /mnt/c/... のようなケースは自動 skip(bwrap bootstrap 失敗の予防)。~/.config/gh は対象外で、既存の entry は自動で除去される。
仕様詳細は .claude/skills/org-setup/references/permissions.md の「ユーザー共通の sandbox denyRead / denyWrite 補強」節を参照。
注意事項
settings.local.json は .gitignore に入っている前提(個人設定のため)
- ユーザーレベルの
~/.claude/settings.json は既存の設定(plugins 等)を壊さないよう注意する
- ワーカーの設定はこのスキルでは配置しない(org-delegate が担当)
- prune の挙動の詳細は
tools/org_setup_prune.py の docstring と tools/test_org_setup_prune.py のテストを参照