claude-code-conductor 0.6.4__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/project-setup.md +18 -0
  2. claude_code_conductor-0.7.0/.claude/docs/settings.json.md +492 -0
  3. claude_code_conductor-0.7.0/.claude/hooks/permission_handler.py +154 -0
  4. claude_code_conductor-0.7.0/.claude/hooks/restore_session.py +75 -0
  5. claude_code_conductor-0.7.0/.claude/permission_rules.json +14 -0
  6. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/settings.json +26 -0
  7. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/setup/SKILL.md +4 -0
  8. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.gitignore +3 -0
  9. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/PKG-INFO +1 -1
  10. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/__init__.py +1 -1
  11. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/CLAUDE.md +0 -0
  12. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/architect.md +0 -0
  13. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/code-reviewer.md +0 -0
  14. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/developer.md +0 -0
  15. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/doc-writer.md +0 -0
  16. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/interviewer.md +0 -0
  17. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/planner.md +0 -0
  18. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/security-reviewer.md +0 -0
  19. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/systematic-debugger.md +0 -0
  20. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/tdd-develop.md +0 -0
  21. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/agents/tester.md +0 -0
  22. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/docs/parallel-orchestra-manifest.md +0 -0
  23. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/clear_file_history.py +0 -0
  24. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/enable_sandbox.py +0 -0
  25. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/pre_compact.py +0 -0
  26. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/pre_tool.py +0 -0
  27. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/session_utils.py +0 -0
  28. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/statusline.py +0 -0
  29. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/stop.py +0 -0
  30. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/validate_skill_change.py +0 -0
  31. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/hooks/worktree_guard.py +0 -0
  32. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/memory/.gitkeep +0 -0
  33. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/rules/code-review-checklist.md +0 -0
  34. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/rules/promoted/index.md +0 -0
  35. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/rules/security-review-checklist.md +0 -0
  36. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/settings.local.json +0 -0
  37. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/code-review/SKILL.md +0 -0
  38. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/dev-workflow/SKILL.md +0 -0
  39. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/develop/SKILL.md +0 -0
  40. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/doc/SKILL.md +0 -0
  41. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/extract-lib/SKILL.md +0 -0
  42. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/init-session/SKILL.md +0 -0
  43. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/mcp-config/SKILL.md +0 -0
  44. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/pattern-status/SKILL.md +0 -0
  45. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/promote-pattern/SKILL.md +0 -0
  46. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/report-timestamp/SKILL.md +0 -0
  47. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/report-timestamp/scripts/get_timestamp.py +0 -0
  48. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/start/SKILL.md +0 -0
  49. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/wave-execution/SKILL.md +0 -0
  50. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/.claude/skills/worktree-tdd-workflow/SKILL.md +0 -0
  51. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/CHANGELOG.md +0 -0
  52. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/LICENSE +0 -0
  53. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/README.md +0 -0
  54. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/hatch_build.py +0 -0
  55. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/pyproject.toml +0 -0
  56. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/__main__.py +0 -0
  57. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/_excludes.py +0 -0
  58. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/cli.py +0 -0
  59. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/cli_doctor.py +0 -0
  60. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/cli_init.py +0 -0
  61. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/cli_list.py +0 -0
  62. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/cli_po.py +0 -0
  63. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/cli_update.py +0 -0
  64. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/paths.py +0 -0
  65. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/po/__init__.py +0 -0
  66. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/po/manifest.py +0 -0
  67. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/c3/po/run.py +0 -0
  68. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/parallel_orchestra/__init__.py +0 -0
  69. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/parallel_orchestra/_exceptions.py +0 -0
  70. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/parallel_orchestra/cli.py +0 -0
  71. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/parallel_orchestra/manifest.py +0 -0
  72. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/parallel_orchestra/report.py +0 -0
  73. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/src/parallel_orchestra/runner.py +0 -0
  74. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/__init__.py +0 -0
  75. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/conftest.py +0 -0
  76. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/hooks/__init__.py +0 -0
  77. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/hooks/test_clear_file_history.py +0 -0
  78. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/hooks/test_enable_sandbox.py +0 -0
  79. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/hooks/test_session_utils.py +0 -0
  80. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/hooks/test_statusline.py +0 -0
  81. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/hooks/test_statusline_template_sync.py +0 -0
  82. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/__init__.py +0 -0
  83. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/conftest.py +0 -0
  84. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_cli.py +0 -0
  85. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_manifest.py +0 -0
  86. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_report.py +0 -0
  87. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_retry_backoff.py +0 -0
  88. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_review_fixes.py +0 -0
  89. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_review_fixes2.py +0 -0
  90. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_review_fixes3.py +0 -0
  91. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_review_fixes4.py +0 -0
  92. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_review_fixes5.py +0 -0
  93. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_runner_t7.py +0 -0
  94. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_runner_v04_fix.py +0 -0
  95. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_runner_v04_m1.py +0 -0
  96. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/parallel_orchestra/test_runner_v04_m2.py +0 -0
  97. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_clear_file_history.py +0 -0
  98. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_cli_init.py +0 -0
  99. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_cli_list.py +0 -0
  100. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_cli_po.py +0 -0
  101. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_cli_po_tempfile.py +0 -0
  102. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_docstring_consistency.py +0 -0
  103. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_enable_sandbox.py +0 -0
  104. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_excludes.py +0 -0
  105. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_manifest_fixes.py +0 -0
  106. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_manifest_yaml_escape.py +0 -0
  107. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_paths.py +0 -0
  108. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_po_manifest.py +0 -0
  109. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_po_run.py +0 -0
  110. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_po_waves.py +0 -0
  111. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_pre_compact.py +0 -0
  112. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_pre_tool_hook.py +0 -0
  113. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_precompact_additional.py +0 -0
  114. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_precompact_toctou_fixes.py +0 -0
  115. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_session_utils_additional.py +0 -0
  116. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_statusline.py +0 -0
  117. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_stop_additional.py +0 -0
  118. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_stop_hook.py +0 -0
  119. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_stop_precompact_fixes.py +0 -0
  120. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_sync_template_clear_file_history.py +0 -0
  121. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_sync_template_stop.py +0 -0
  122. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_sync_validate_skill.py +0 -0
  123. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_template_pre_tool_hook.py +0 -0
  124. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_validate_skill_change.py +0 -0
  125. {claude_code_conductor-0.6.4 → claude_code_conductor-0.7.0}/tests/test_worktree_guard.py +0 -0
@@ -46,7 +46,25 @@ Glob で `.claude/rules/coding-standards.md` と `.claude/rules/project-conventi
46
46
 
47
47
  **Step 3: `.claude/rules/coding-standards.md` を生成**
48
48
 
49
+ 言語に応じた `paths` を YAML フロントマターに設定し、関係するファイルを編集している時だけこのルールが適用されるようにする。
50
+
51
+ 言語 → 拡張子の対応例(複数言語の場合は全て列挙する):
52
+ - Python → `**/*.py`
53
+ - TypeScript → `**/*.ts`, `**/*.tsx`
54
+ - JavaScript → `**/*.js`, `**/*.jsx`, `**/*.mjs`, `**/*.cjs`
55
+ - TypeScript + JavaScript → 上記すべて
56
+ - Go → `**/*.go`
57
+ - Java → `**/*.java`
58
+ - Kotlin → `**/*.kt`, `**/*.kts`
59
+ - C# → `**/*.cs`
60
+ - Rust → `**/*.rs`
61
+ - Ruby → `**/*.rb`
62
+
49
63
  ```markdown
64
+ ---
65
+ paths:
66
+ - "**/*.{拡張子}"
67
+ ---
50
68
  # Coding Standards: {スタック名}
51
69
  <!-- /agent-project-setup により生成。言語・フレームワークのバージョンアップ時に更新する。-->
52
70
  最終更新: YYYY-MM-DD
@@ -0,0 +1,492 @@
1
+ # settings.json リファレンス
2
+
3
+ Claude Code の設定ファイル。プロジェクトルートの `.claude/settings.json` に配置する。
4
+ ユーザーローカルの上書きは `.claude/settings.local.json`(`.gitignore` 推奨)。
5
+
6
+ > 設定の優先順位: `settings.local.json` > `settings.json` > グローバル設定(`~/.claude/settings.json`)
7
+ > ただし `hooks` セクションは `settings.local.json` が `settings.json` を**完全に上書き**する(マージしない)。
8
+
9
+ ---
10
+
11
+ ## `permissions`
12
+
13
+ ツール呼び出しの許可・拒否ルールを定義する。
14
+
15
+ ```json
16
+ {
17
+ "permissions": {
18
+ "allow": [
19
+ "Bash(git status*)",
20
+ "Read(**)",
21
+ "Write(.claude/reports/**)"
22
+ ],
23
+ "deny": [
24
+ "Read(.env)",
25
+ "Read(**/.env)"
26
+ ]
27
+ }
28
+ }
29
+ ```
30
+
31
+ ### パターン書式
32
+
33
+ | 書式 | 説明 |
34
+ |---|---|
35
+ | `ToolName` | 引数なしでツールを許可 |
36
+ | `ToolName(pattern)` | 引数が `pattern` にマッチする場合のみ許可 |
37
+ | `ToolName(domain:example.com)` | WebFetch の場合はドメイン指定も使える |
38
+ | `**` | パス境界を越えるワイルドカード |
39
+ | `*` | パス境界内のワイルドカード(`/` を越えない) |
40
+
41
+ > `promoted-*` のように境界以外に `*` を置くとバリデーションエラーになる。
42
+
43
+ ### 利用できるツール名
44
+
45
+ `Bash` / `Read` / `Write` / `Edit` / `Glob` / `Grep` / `WebFetch` / `WebSearch` / `Agent` / `Skill` / `TodoWrite` / `NotebookEdit` など。
46
+
47
+ ---
48
+
49
+ ## `sandbox`
50
+
51
+ Claude Code のサンドボックス(プロセス分離)を設定する。
52
+
53
+ ```json
54
+ {
55
+ "sandbox": {
56
+ "enabled": true,
57
+ "autoAllowBashIfSandboxed": true,
58
+ "allowUnsandboxedCommands": false,
59
+ "excludedCommands": [],
60
+ "network": {
61
+ "allowUnixSockets": [],
62
+ "allowAllUnixSockets": false,
63
+ "allowLocalBinding": false,
64
+ "allowedDomains": []
65
+ },
66
+ "enableWeakerNestedSandbox": true
67
+ }
68
+ }
69
+ ```
70
+
71
+ | キー | 型 | 説明 |
72
+ |---|---|---|
73
+ | `enabled` | boolean | サンドボックスを有効にする |
74
+ | `autoAllowBashIfSandboxed` | boolean | サンドボックス有効時に Bash を自動許可する |
75
+ | `allowUnsandboxedCommands` | boolean | サンドボックス外でのコマンド実行を許可する |
76
+ | `excludedCommands` | string[] | サンドボックスから除外するコマンドのリスト |
77
+ | `network.allowUnixSockets` | string[] | 許可する Unix ソケットのパス一覧 |
78
+ | `network.allowAllUnixSockets` | boolean | 全 Unix ソケットを許可する |
79
+ | `network.allowLocalBinding` | boolean | ローカルポートへのバインドを許可する |
80
+ | `network.allowedDomains` | string[] | 許可するネットワークドメイン一覧 |
81
+ | `enableWeakerNestedSandbox` | boolean | ネストされたサブエージェントに緩いサンドボックスを適用する |
82
+
83
+ ---
84
+
85
+ ## `hooks`
86
+
87
+ Claude Code のイベントに対してフックを登録する。マッチした全フックは並列実行され、同一コマンドは自動で重複排除される。
88
+
89
+ ```json
90
+ {
91
+ "hooks": {
92
+ "PreToolUse": [
93
+ {
94
+ "matcher": "Bash",
95
+ "hooks": [
96
+ {
97
+ "type": "command",
98
+ "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre_tool.py\"",
99
+ "if": "Bash(git *)",
100
+ "timeout": 30
101
+ }
102
+ ]
103
+ }
104
+ ]
105
+ }
106
+ }
107
+ ```
108
+
109
+ > `disableAllHooks: true` をトップレベルに設定すると全フックを無効化できる。
110
+
111
+ ---
112
+
113
+ ### イベント一覧
114
+
115
+ | イベント | タイミング | ブロック可否 |
116
+ |---|---|---|
117
+ | `SessionStart` | セッション開始・再開時 | 不可 |
118
+ | `Setup` | `--init-only` / `--init` / `--maintenance` 起動時 | 不可 |
119
+ | `UserPromptSubmit` | プロンプト送信時(Claude 処理前) | 可(exit 2) |
120
+ | `UserPromptExpansion` | スキル/コマンドの展開時(Claude 処理前) | 可(exit 2) |
121
+ | `PreToolUse` | ツール実行の直前 | 可(exit 2 または JSON) |
122
+ | `PermissionRequest` | 許可ダイアログが表示される時 | 可(JSON で allow/deny) |
123
+ | `PermissionDenied` | auto モードがツールを拒否した時 | — |
124
+ | `PostToolUse` | ツール実行の直後(成功) | 可(JSON `decision: "block"`) |
125
+ | `PostToolUseFailure` | ツール実行の直後(失敗) | — |
126
+ | `PostToolBatch` | 並列ツール呼び出しバッチ完了後 | 可(JSON `decision: "block"`) |
127
+ | `Stop` | Claude が応答を完了した時 | 可(JSON `decision: "block"`) |
128
+ | `StopFailure` | API エラーでターン終了時 | 不可(出力・終了コードは無視) |
129
+ | `SubagentStart` | サブエージェントが実行を開始した時 | 不可 |
130
+ | `SubagentStop` | サブエージェントが完了した時 | 不可 |
131
+ | `TaskCreated` | `TaskCreate` でタスク作成時 | — |
132
+ | `TaskCompleted` | タスクが完了マークされた時 | — |
133
+ | `TeammateIdle` | agent team の teammate が idle になる時 | — |
134
+ | `InstructionsLoaded` | CLAUDE.md / `rules/*.md` がロードされた時 | — |
135
+ | `ConfigChange` | 設定ファイルが変更された時 | 可(exit 2 または JSON) |
136
+ | `CwdChanged` | 作業ディレクトリが変更された時(`cd` 等) | — |
137
+ | `FileChanged` | 監視ファイルがディスク上で変更された時 | — |
138
+ | `WorktreeCreate` | worktree が作成される時(デフォルト git 動作を置換) | — |
139
+ | `WorktreeRemove` | worktree が削除される時 | — |
140
+ | `PreCompact` | コンテキスト圧縮の直前 | 不可 |
141
+ | `PostCompact` | コンテキスト圧縮完了後 | — |
142
+ | `Notification` | 通知が発生した時 | 不可 |
143
+ | `Elicitation` | MCP サーバーがユーザー入力を要求した時 | — |
144
+ | `ElicitationResult` | MCP 引き出し応答が返される前 | — |
145
+ | `SessionEnd` | セッション終了時 | — |
146
+
147
+ ---
148
+
149
+ ### イベント別 matcher の対応
150
+
151
+ | イベント | matcher がフィルタリングするもの | 値の例 |
152
+ |---|---|---|
153
+ | `PreToolUse` / `PostToolUse` / `PostToolUseFailure` / `PermissionRequest` / `PermissionDenied` | ツール名 | `Bash`, `Edit\|Write`, `mcp__github__.*` |
154
+ | `SessionStart` | 開始方法 | `startup`, `resume`, `clear`, `compact` |
155
+ | `Setup` | CLI フラグ | `init`, `maintenance` |
156
+ | `SessionEnd` | 終了理由 | `clear`, `resume`, `logout`, `prompt_input_exit`, `other` |
157
+ | `Notification` | 通知タイプ | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog` |
158
+ | `SubagentStart` / `SubagentStop` | エージェント型名 | `general-purpose`, `Explore`, カスタム名 |
159
+ | `PreCompact` / `PostCompact` | 圧縮のトリガー | `manual`, `auto` |
160
+ | `ConfigChange` | 設定ソース | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |
161
+ | `StopFailure` | エラータイプ | `rate_limit`, `authentication_failed`, `billing_error`, `server_error` |
162
+ | `InstructionsLoaded` | ロード理由 | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |
163
+ | `FileChanged` | リテラルファイル名(パイプ区切り) | `.envrc\|.env` |
164
+ | `Elicitation` / `ElicitationResult` | MCP サーバー名 | 設定したサーバー名 |
165
+ | `UserPromptExpansion` | コマンド/スキル名 | スキル名 |
166
+ | `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `CwdChanged` | 非対応 | 常に全発生で発火 |
167
+
168
+ ---
169
+
170
+ ### フックグループ構造
171
+
172
+ ```json
173
+ {
174
+ "matcher": "Edit|Write",
175
+ "hooks": [
176
+ {
177
+ "type": "command",
178
+ "command": "スクリプトパス",
179
+ "if": "Edit(*.ts)",
180
+ "timeout": 60
181
+ }
182
+ ]
183
+ }
184
+ ```
185
+
186
+ | キー | 説明 |
187
+ |---|---|
188
+ | `matcher` | グループレベルのフィルタ。空文字列は全てにマッチ |
189
+ | `hooks[].type` | フックの種類(下記参照) |
190
+ | `hooks[].if` | フックレベルの追加フィルタ。許可ルール構文(`Bash(git *)`、`Edit(*.ts)` 等)。ツールイベントのみ有効 |
191
+ | `hooks[].timeout` | タイムアウト秒数。デフォルト 600秒(10分) |
192
+
193
+ ---
194
+
195
+ ### hook の type 一覧
196
+
197
+ #### `command`(標準)
198
+
199
+ シェルコマンドを実行する。最も一般的。
200
+
201
+ ```json
202
+ { "type": "command", "command": "python script.py" }
203
+ ```
204
+
205
+ #### `http`
206
+
207
+ イベントデータを HTTP エンドポイントに POST する。
208
+
209
+ ```json
210
+ {
211
+ "type": "http",
212
+ "url": "http://localhost:8080/hooks",
213
+ "headers": { "Authorization": "Bearer $MY_TOKEN" },
214
+ "allowedEnvVars": ["MY_TOKEN"]
215
+ }
216
+ ```
217
+
218
+ - `headers` の値は `$VAR` 形式の環境変数補間をサポート(`allowedEnvVars` に列挙したもののみ)
219
+ - レスポンスボディで command フックと同じ JSON 形式で結果を返す
220
+
221
+ #### `prompt`(LLM 評価)
222
+
223
+ シングルターン LLM 呼び出しで判断を行う。デフォルトモデル: Haiku。
224
+
225
+ ```json
226
+ { "type": "prompt", "prompt": "Check if all tasks are complete...", "model": "sonnet" }
227
+ ```
228
+
229
+ - `"ok": true` → 続行
230
+ - `"ok": false` + `"reason": "..."` → イベントに応じてブロックまたはフィードバック
231
+
232
+ #### `mcp_tool`
233
+
234
+ 接続済み MCP サーバーのツールを呼び出す。
235
+
236
+ #### `agent`(実験的)
237
+
238
+ マルチターン・ツールアクセス付きの検証。デフォルトタイムアウト 60秒、最大 50 ターン。
239
+
240
+ ```json
241
+ { "type": "agent", "prompt": "Verify all tests pass...", "timeout": 120 }
242
+ ```
243
+
244
+ ---
245
+
246
+ ### 終了コードによる動作
247
+
248
+ | 終了コード | 動作 |
249
+ |---|---|
250
+ | `0` | 続行。`UserPromptSubmit` / `UserPromptExpansion` / `SessionStart` は stdout を Claude のコンテキストに注入 |
251
+ | `2` | アクションをブロック。stderr の内容が Claude へのフィードバックになる。ブロック不可イベントでは stderr をユーザーに表示し続行 |
252
+ | その他 | 続行。トランスクリプトに `<hook name> hook error` 通知 + stderr 1行目を表示 |
253
+
254
+ > **注意**: exit 2 と JSON 出力を混在させないこと。Claude Code は exit 2 時に JSON を無視する。
255
+
256
+ ---
257
+
258
+ ### 構造化 JSON 出力(exit 0 + stdout)
259
+
260
+ より細かい制御が必要な場合、exit 0 で stdout に JSON を出力する。
261
+
262
+ #### `PreToolUse` の決定制御
263
+
264
+ ```json
265
+ {
266
+ "hookSpecificOutput": {
267
+ "hookEventName": "PreToolUse",
268
+ "permissionDecision": "deny",
269
+ "permissionDecisionReason": "Use rg instead of grep"
270
+ }
271
+ }
272
+ ```
273
+
274
+ | `permissionDecision` | 動作 |
275
+ |---|---|
276
+ | `"allow"` | インタラクティブ許可プロンプトをスキップ(deny ルールより優先されない) |
277
+ | `"deny"` | ツール呼び出しをキャンセル。`permissionDecisionReason` が Claude へのフィードバック |
278
+ | `"ask"` | 通常通りユーザーに許可プロンプトを表示 |
279
+ | `"defer"` | `-p` 非インタラクティブモードでのみ有効。プロセスを終了しツール呼び出しを保留 |
280
+
281
+ #### `PostToolUse` / `Stop` / `PostToolBatch` のブロック
282
+
283
+ ```json
284
+ { "decision": "block", "reason": "Tests are failing" }
285
+ ```
286
+
287
+ #### `PermissionRequest` の決定制御
288
+
289
+ ```json
290
+ {
291
+ "hookSpecificOutput": {
292
+ "hookEventName": "PermissionRequest",
293
+ "decision": {
294
+ "behavior": "allow",
295
+ "updatedPermissions": [
296
+ { "type": "setMode", "mode": "acceptEdits", "destination": "session" }
297
+ ]
298
+ }
299
+ }
300
+ }
301
+ ```
302
+
303
+ #### `UserPromptSubmit` へのコンテキスト注入
304
+
305
+ ```json
306
+ { "additionalContext": "現在のブランチ: feature/auth" }
307
+ ```
308
+
309
+ #### `PermissionDenied` でリトライ許可
310
+
311
+ ```json
312
+ { "retry": true }
313
+ ```
314
+
315
+ ---
316
+
317
+ ### 環境変数
318
+
319
+ フックスクリプト内で使える環境変数:
320
+
321
+ | 変数 | 内容 |
322
+ |---|---|
323
+ | `$CLAUDE_PROJECT_DIR` | プロジェクトのルートディレクトリの絶対パス |
324
+ | `$CLAUDE_ENV_FILE` | このファイルに書いた内容が各 Bash コマンド実行前にプリアンブルとして実行される(`direnv` 等との連携に使う) |
325
+
326
+ イベントデータ(ツール名・入力 JSON 等)は **stdin を通じて JSON として渡される**。`jq` 等で解析する。
327
+
328
+ ```bash
329
+ INPUT=$(cat)
330
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
331
+ ```
332
+
333
+ ---
334
+
335
+ ### hook の配置場所によるスコープ
336
+
337
+ | 場所 | スコープ | 共有 |
338
+ |---|---|---|
339
+ | `~/.claude/settings.json` | 全プロジェクト | なし(マシンローカル) |
340
+ | `.claude/settings.json` | このプロジェクトのみ | git 管理可能 |
341
+ | `.claude/settings.local.json` | このプロジェクトのみ | `.gitignore` 推奨 |
342
+ | skills / agents のフロントマター `hooks:` | スキル/エージェントがアクティブな間のみ | コンポーネントファイルで定義 |
343
+
344
+ ---
345
+
346
+ ## `statusLine`
347
+
348
+ Claude Code のステータスバーに表示するカスタム情報を定義する。
349
+
350
+ ```json
351
+ {
352
+ "statusLine": {
353
+ "type": "command",
354
+ "command": "python \"$CLAUDE_PROJECT_DIR/.claude/hooks/statusline.py\""
355
+ }
356
+ }
357
+ ```
358
+
359
+ | キー | 型 | 説明 |
360
+ |---|---|---|
361
+ | `type` | string | `"command"` のみ(現時点) |
362
+ | `command` | string | 実行するコマンド。stdout の1行目がステータスバーに表示される |
363
+
364
+ ---
365
+
366
+ ## `model`
367
+
368
+ デフォルトで使用するモデルを上書きする。
369
+
370
+ ```json
371
+ {
372
+ "model": "claude-opus-4-7"
373
+ }
374
+ ```
375
+
376
+ 有効なモデル ID 例: `claude-sonnet-4-6` / `claude-opus-4-7` / `claude-haiku-4-5-20251001`
377
+
378
+ ---
379
+
380
+ ## `env`
381
+
382
+ Claude Code セッション全体で使う環境変数を設定する。
383
+
384
+ ```json
385
+ {
386
+ "env": {
387
+ "MY_VAR": "value",
388
+ "DEBUG": "1"
389
+ }
390
+ }
391
+ ```
392
+
393
+ ---
394
+
395
+ ## `outputStyle`
396
+
397
+ Claude のシステムプロンプト全体を差し替える出力スタイルを指定する。
398
+
399
+ ```json
400
+ {
401
+ "outputStyle": "Explanatory"
402
+ }
403
+ ```
404
+
405
+ | 値 | 説明 |
406
+ |---|---|
407
+ | `"Default"` | ソフトウェアエンジニアリング向けデフォルト |
408
+ | `"Explanatory"` | 教育的インサイト付き(実装選択肢・パターン解説を追加) |
409
+ | `"Learning"` | 協調学習モード。一部コードを `TODO(human)` マーカーに置き換えてユーザーに実装を促す |
410
+ | カスタム名 | `.claude/output-styles/<name>.md` または `~/.claude/output-styles/<name>.md` のファイル名 |
411
+
412
+ - 変更は次のセッション開始時に有効になる
413
+ - `/config` → Output style からも変更できる(`settings.local.json` に保存される)
414
+ - CLAUDE.md・rules/・`--append-system-prompt` とは異なり、**システムプロンプト本体を置換**する
415
+
416
+ ---
417
+
418
+ ## `includeCoAuthoredBy`
419
+
420
+ git コミットの `Co-Authored-By` トレーラーに Claude の情報を含めるかを制御する。
421
+
422
+ ```json
423
+ {
424
+ "includeCoAuthoredBy": true
425
+ }
426
+ ```
427
+
428
+ デフォルト: `true`
429
+
430
+ ---
431
+
432
+ ## `apiKeyHelper`
433
+
434
+ API キーを取得するカスタムコマンドを指定する。`ANTHROPIC_API_KEY` 環境変数の代わりに使う。
435
+
436
+ ```json
437
+ {
438
+ "apiKeyHelper": "cat ~/.secrets/anthropic_key"
439
+ }
440
+ ```
441
+
442
+ ---
443
+
444
+ ## `cleanupPeriodDays`
445
+
446
+ ログファイルを自動削除するまでの日数。
447
+
448
+ ```json
449
+ {
450
+ "cleanupPeriodDays": 30
451
+ }
452
+ ```
453
+
454
+ ---
455
+
456
+ ## `mcpServers`
457
+
458
+ MCP(Model Context Protocol)サーバーを登録する。登録されたサーバーのツールが Claude から利用できるようになる。
459
+
460
+ ```json
461
+ {
462
+ "mcpServers": {
463
+ "my-server": {
464
+ "type": "stdio",
465
+ "command": "node",
466
+ "args": ["path/to/server.js"],
467
+ "env": {
468
+ "API_KEY": "..."
469
+ }
470
+ }
471
+ }
472
+ }
473
+ ```
474
+
475
+ | キー | 型 | 説明 |
476
+ |---|---|---|
477
+ | `type` | string | `"stdio"` / `"sse"` / `"http"` |
478
+ | `command` | string | サーバーを起動するコマンド(stdio の場合) |
479
+ | `args` | string[] | コマンドの引数 |
480
+ | `env` | object | サーバープロセスに渡す環境変数 |
481
+ | `url` | string | サーバーの URL(sse / http の場合) |
482
+
483
+ ---
484
+
485
+ ## C3 での使い分け
486
+
487
+ | ファイル | 用途 |
488
+ |---|---|
489
+ | `.claude/settings.json` | プロジェクト共通設定。git 管理する |
490
+ | `.claude/settings.local.json` | 開発者個人の設定(追加 `allow` 等)。`.gitignore` に追加して git 管理しない |
491
+
492
+ > `hooks` を `settings.local.json` に書くと `settings.json` の `hooks` が**完全に無効化**される。フックは `settings.json` のみに書くこと。
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ permission_handler.py: PermissionRequest hook.
4
+ 権限確認ダイアログが出るタイミングで通知を表示し、
5
+ permission_rules.json のパターンにマッチすれば自動承認する。
6
+ """
7
+
8
+ import json
9
+ import os
10
+ import platform
11
+ import re
12
+ import subprocess
13
+ import sys
14
+
15
+ try:
16
+ sys.stdin.reconfigure(encoding='utf-8')
17
+ sys.stdout.reconfigure(encoding='utf-8')
18
+ sys.stderr.reconfigure(encoding='utf-8')
19
+ except AttributeError:
20
+ pass
21
+
22
+ _HOOKS_DIR = os.path.dirname(os.path.abspath(__file__))
23
+ _CLAUDE_DIR = os.path.dirname(_HOOKS_DIR)
24
+ RULES_PATH = os.path.join(_CLAUDE_DIR, 'permission_rules.json')
25
+
26
+ DEFAULT_RULES: dict = {'auto_allow': [], 'notify_on_auto': True}
27
+
28
+
29
+ def notify(message: str) -> None:
30
+ system = platform.system()
31
+ try:
32
+ if system == 'Darwin':
33
+ safe = message.replace('\\', '\\\\').replace('"', '\\"')
34
+ subprocess.run(
35
+ ['osascript', '-e', f'display notification "{safe}" with title "Claude Code"'],
36
+ capture_output=True, timeout=5
37
+ )
38
+ elif system == 'Linux':
39
+ subprocess.run(
40
+ ['notify-send', 'Claude Code', message],
41
+ capture_output=True, timeout=5
42
+ )
43
+ elif system == 'Windows':
44
+ safe = message.replace('"', '`"')
45
+ ps = (
46
+ 'Add-Type -AssemblyName System.Windows.Forms; '
47
+ '$n = New-Object System.Windows.Forms.NotifyIcon; '
48
+ '$n.Icon = [System.Drawing.SystemIcons]::Information; '
49
+ '$n.Visible = $true; '
50
+ f'$n.ShowBalloonTip(4000, "Claude Code", "{safe}", '
51
+ '[System.Windows.Forms.ToolTipIcon]::Info); '
52
+ 'Start-Sleep -Milliseconds 4500; '
53
+ '$n.Dispose()'
54
+ )
55
+ subprocess.Popen(
56
+ ['powershell', '-WindowStyle', 'Hidden', '-Command', ps],
57
+ creationflags=0x08000000 # CREATE_NO_WINDOW
58
+ )
59
+ except Exception as e:
60
+ print(f'[permission_handler] 通知エラー: {e}', file=sys.stderr)
61
+
62
+
63
+ def load_rules() -> dict:
64
+ if not os.path.exists(RULES_PATH):
65
+ return DEFAULT_RULES
66
+ try:
67
+ with open(RULES_PATH, 'r', encoding='utf-8') as f:
68
+ return json.load(f)
69
+ except (json.JSONDecodeError, OSError) as e:
70
+ print(f'[permission_handler] permission_rules.json の読み込みエラー: {e}', file=sys.stderr)
71
+ return DEFAULT_RULES
72
+
73
+
74
+ def _glob_to_regex(pattern: str) -> str:
75
+ """glob パターン(* と **)を正規表現に変換する。"""
76
+ # ** を一時プレースホルダーに退避してから * と ** を別々に処理する
77
+ parts = pattern.split('**')
78
+ escaped = [re.escape(p).replace(r'\*', '[^/]*') for p in parts]
79
+ return '.*'.join(escaped)
80
+
81
+
82
+ def matches_pattern(tool_name: str, tool_input: dict, pattern: str) -> bool:
83
+ """
84
+ "Bash(git *)" / "Write(.claude/**)" 形式のパターンとマッチするか判定する。
85
+ ToolName のみ(引数なし)も許容する。
86
+ """
87
+ m = re.match(r'^(\w+)(?:\((.+)\))?$', pattern.strip())
88
+ if not m:
89
+ return False
90
+
91
+ p_tool, p_arg = m.group(1), m.group(2)
92
+ if tool_name != p_tool:
93
+ return False
94
+ if not p_arg:
95
+ return True
96
+
97
+ # ツール別に照合対象を決定
98
+ if tool_name == 'Bash':
99
+ subject = tool_input.get('command', '')
100
+ elif tool_name in ('Write', 'Edit', 'Read', 'Glob'):
101
+ subject = tool_input.get('file_path', tool_input.get('pattern', ''))
102
+ elif tool_name == 'WebFetch':
103
+ url = tool_input.get('url', '')
104
+ if p_arg.startswith('domain:'):
105
+ domain = p_arg[len('domain:'):]
106
+ return domain in url
107
+ subject = url
108
+ else:
109
+ subject = str(tool_input)
110
+
111
+ regex = _glob_to_regex(p_arg)
112
+ return bool(re.fullmatch(regex, subject))
113
+
114
+
115
+ def describe_tool(tool_name: str, tool_input: dict) -> str:
116
+ if tool_name == 'Bash':
117
+ cmd = tool_input.get('command', '')
118
+ return f"{tool_name}({cmd[:60]}{'...' if len(cmd) > 60 else ''})"
119
+ if tool_name in ('Write', 'Edit', 'Read'):
120
+ return f"{tool_name}({tool_input.get('file_path', '')})"
121
+ if tool_name == 'WebFetch':
122
+ return f"{tool_name}({tool_input.get('url', '')})"
123
+ return f"{tool_name}({str(tool_input)[:60]})"
124
+
125
+
126
+ def main() -> None:
127
+ try:
128
+ payload = json.loads(sys.stdin.read())
129
+ except (json.JSONDecodeError, ValueError):
130
+ sys.exit(0)
131
+
132
+ tool_name = payload.get('tool_name', '')
133
+ tool_input = payload.get('tool_input', {})
134
+ rules = load_rules()
135
+ description = describe_tool(tool_name, tool_input)
136
+
137
+ for pattern in rules.get('auto_allow', []):
138
+ if matches_pattern(tool_name, tool_input, pattern):
139
+ if rules.get('notify_on_auto', True):
140
+ notify(f'✓ 自動承認: {description}')
141
+ print(json.dumps({
142
+ 'hookSpecificOutput': {
143
+ 'hookEventName': 'PermissionRequest',
144
+ 'decision': {'behavior': 'allow'}
145
+ }
146
+ }))
147
+ return
148
+
149
+ # マッチなし → ダイアログが出る前に通知
150
+ notify(f'⚠ 承認が必要: {description}')
151
+
152
+
153
+ if __name__ == '__main__':
154
+ main()