claude-task-worker 0.1.0

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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +386 -0
  3. package/dist/commands/init.d.ts +1 -0
  4. package/dist/commands/init.js +84 -0
  5. package/dist/commands/init.js.map +1 -0
  6. package/dist/gh.d.ts +47 -0
  7. package/dist/gh.js +113 -0
  8. package/dist/gh.js.map +1 -0
  9. package/dist/git.d.ts +1 -0
  10. package/dist/git.js +14 -0
  11. package/dist/git.js.map +1 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +1890 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/process-manager.d.ts +8 -0
  16. package/dist/process-manager.js +218 -0
  17. package/dist/process-manager.js.map +1 -0
  18. package/dist/random-name.d.ts +1 -0
  19. package/dist/random-name.js +59 -0
  20. package/dist/random-name.js.map +1 -0
  21. package/dist/slack.d.ts +5 -0
  22. package/dist/slack.js +125 -0
  23. package/dist/slack.js.map +1 -0
  24. package/dist/usage.d.ts +2 -0
  25. package/dist/usage.js +52 -0
  26. package/dist/usage.js.map +1 -0
  27. package/dist/workers/create-issue.d.ts +1 -0
  28. package/dist/workers/create-issue.js +55 -0
  29. package/dist/workers/create-issue.js.map +1 -0
  30. package/dist/workers/exec-issue.d.ts +1 -0
  31. package/dist/workers/exec-issue.js +50 -0
  32. package/dist/workers/exec-issue.js.map +1 -0
  33. package/dist/workers/fix-review-point.d.ts +1 -0
  34. package/dist/workers/fix-review-point.js +62 -0
  35. package/dist/workers/fix-review-point.js.map +1 -0
  36. package/dist/workers/triage-issues.d.ts +3 -0
  37. package/dist/workers/triage-issues.js +54 -0
  38. package/dist/workers/triage-issues.js.map +1 -0
  39. package/dist/workers/triage-prs.d.ts +3 -0
  40. package/dist/workers/triage-prs.js +56 -0
  41. package/dist/workers/triage-prs.js.map +1 -0
  42. package/dist/workers/update-issue.d.ts +1 -0
  43. package/dist/workers/update-issue.js +61 -0
  44. package/dist/workers/update-issue.js.map +1 -0
  45. package/dist/worktree.d.ts +2 -0
  46. package/dist/worktree.js +34 -0
  47. package/dist/worktree.js.map +1 -0
  48. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Toshifumi Kiyono (getty104)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,386 @@
1
+ # claude-task-worker
2
+
3
+ GitHub Issues/PRを定期ポーリングし、Claude Codeに処理を委譲するCLIツール。
4
+
5
+ 本リポジトリに同梱されている `claude-task-worker` Claude Code プラグイン(`plugin/` ディレクトリ)と組み合わせることで、GitHub Issue の実装からPRのレビュー対応、Dependabot PRの対応までを自動化する。CLI 本体(npm パッケージ)とプラグイン(Claude Code マーケットプレイス)は同じリポジトリ・同じ名前で提供される。
6
+
7
+ ## アーキテクチャ
8
+
9
+ `claude-task-worker` CLI がGitHubラベルを検知してタスクを起動し、`claude-task-worker` プラグインのスキルが実際の処理を担う。
10
+
11
+ ```
12
+ ┌────────────────────────────────────────────────────────┐
13
+ │ GitHub │
14
+ │ │
15
+ │ Issue (cc-exec-issue) ──┐ │
16
+ │ Issue (cc-triage-scope, blockedBy all closed) ──┤ │
17
+ │ Issue (cc-update-issue) ──┤ │
18
+ │ Issue (cc-answer-issue-questions) ──┤ │
19
+ │ Issue (cc-issue-created + cc-triage-scope) ──┤ │
20
+ │ Issue (cc-epic-issue, all sub-issues closed) ──┤ │
21
+ │ PR (cc-fix-onetime) ──┤ │
22
+ │ PR (cc-triage-scope) ──┤ │
23
+ │ PR (cc-resolve-conflict) ──┤ │
24
+ │ PR (dependencies, Dependabot) ──┤ │
25
+ └─────────────────────────────────────────────────────┼──┘
26
+
27
+
28
+ ┌────────────────────────┐
29
+ │ claude-task-worker │
30
+ └───────────┬────────────┘
31
+ │ invoke
32
+
33
+ ┌────────────────────────┐
34
+ │ Claude Code CLI │
35
+ │ + claude-task-worker │
36
+ │ plugin │
37
+ └────────────────────────┘
38
+ ```
39
+
40
+ ### Worker と claude-task-worker プラグインのスキル対応
41
+
42
+ | Worker | トリガーラベル | 呼び出されるスキル | デフォルト間隔 |
43
+ |---|---|---|---|
44
+ | `exec-issue` | `cc-exec-issue` | `/claude-task-worker:exec-issue` | 1分 |
45
+ | `create-issue` | `cc-triage-scope` (Issue, blockedBy が全て Close) | `/claude-task-worker:create-issue-from-issue-number` | 1分 |
46
+ | `update-issue` | `cc-update-issue` | `/claude-task-worker:update-issue` | 1分 |
47
+ | `answer-issue-questions` | `cc-answer-issue-questions` | `/claude-task-worker:answer-issue-questions` | 1分 |
48
+ | `fix-review-point` | `cc-fix-onetime` | `/claude-task-worker:fix-review-point` | 1分 |
49
+ | `triage-created-issue` | `cc-issue-created` + `cc-triage-scope` (Issue) | `/claude-task-worker:triage-created-issue` | 1分 |
50
+ | `triage-pr` | `cc-triage-scope` (PR) | `/claude-task-worker:triage-pr` | 1分 |
51
+ | `resolve-conflict` | `cc-resolve-conflict` (PR) | `/claude-task-worker:resolve-conflict` | 1分 |
52
+ | `check-dependabot` | `dependencies` (PR) | `/claude-task-worker:check-dependabot` | 1時間 |
53
+ | `epic-issue` | `cc-epic-issue` (Issue, sub-issues が全て Close) | `/claude-task-worker:create-epic-pr` | 5分 |
54
+
55
+ > ℹ️ Issue 系ワーカーはすべて GitHub Issue Dependencies の `-is:blocked` 検索 qualifier でサーバ側絞り込みを行うため、未解決の blockedBy Issue を持つ Issue は対象外となる。
56
+
57
+ ### Epic(親Issue)連携
58
+
59
+ 親Issue (Issue Dependencies の Parent) を持つサブIssueを処理する場合、ワーカーはデフォルトブランチではなく `cc-epic-<親Issue番号>` ブランチから worktree を作成する。エピック単位でブランチをまとめることで、サブIssueごとのPRを単一の統合ブランチに集約しやすくなる。エピックブランチが remote に無い場合はデフォルトブランチから自動派生して push される。
60
+
61
+ `epic-issue` ワーカーは、`cc-epic-issue` ラベル付きの親Issueに紐づくサブIssueがすべて Close されたタイミングで `/claude-task-worker:create-epic-pr` を起動し、エピックブランチからまとめてPRを作成する。
62
+
63
+ ## セットアップ
64
+
65
+ ### 前提条件
66
+
67
+ - [GitHub CLI (`gh`)](https://cli.github.com/) がインストール・認証済みであること
68
+ - [Claude Code (`claude`)](https://docs.anthropic.com/en/docs/claude-code) がインストール済みであること
69
+ - `claude-task-worker` プラグインがインストール済みであること(下記インストール手順を参照)
70
+
71
+ ### インストール
72
+
73
+ #### 推奨手順(一発セットアップ)
74
+
75
+ 以下のコマンド一発で、Claude Code マーケットプレイスの追加・プラグインのインストール・CLI本体のグローバルインストールをまとめて行える。
76
+
77
+ ```bash
78
+ npx claude-task-worker install
79
+ ```
80
+
81
+ - `claude plugin marketplace add getty104/claude-task-worker` — マーケットプレイスの追加(追加済みの場合のエラーはログのみで無視して続行)
82
+ - `claude plugin install claude-task-worker@claude-task-worker` — プラグインのインストール
83
+ - `npm install -g claude-task-worker@latest` — CLI 本体のグローバルインストール(`npx` 実行時でも `claude-task-worker` コマンドを常設化する)
84
+
85
+ インストール後、Claude Code のセッションを再起動するとプラグインが有効化される。
86
+
87
+ #### 手動手順(代替)
88
+
89
+ 個別にインストールしたい場合は以下の手順でも良い。
90
+
91
+ CLI(npm パッケージ):
92
+
93
+ ```bash
94
+ npm install -g claude-task-worker
95
+ ```
96
+
97
+ 開発版をローカルから使う場合:
98
+
99
+ ```bash
100
+ npm install
101
+ npm run build
102
+ npm link
103
+ ```
104
+
105
+ Claude Code プラグイン(このリポジトリを Claude Code マーケットプレイスとして追加し、プラグインをインストールする):
106
+
107
+ ```bash
108
+ claude plugin marketplace add getty104/claude-task-worker
109
+ claude plugin install claude-task-worker@claude-task-worker
110
+ ```
111
+
112
+ インストール後、Claude Code のセッションを再起動するとプラグインが有効化される。
113
+
114
+ #### 更新
115
+
116
+ CLI とプラグイン(マーケットプレイス)をまとめて更新する。
117
+
118
+ ```bash
119
+ claude-task-worker update
120
+ ```
121
+
122
+ - `claude plugin marketplace update claude-task-worker` — マーケットプレイスの更新
123
+ - `claude plugin update claude-task-worker@claude-task-worker` — プラグインの更新(反映にはセッション再起動が必要)
124
+ - `npm install -g claude-task-worker@latest` — CLI 本体の更新
125
+
126
+ ### 初期化
127
+
128
+ 対象リポジトリで実行すると、必要なGitHubラベル・Issueテンプレート・GitHub Actionsワークフロー・設定ファイルが作成される。既存ファイルは保護され、`--force` を指定すると上書きされる。
129
+
130
+ ```bash
131
+ claude-task-worker init # 既存ファイルは保護
132
+ claude-task-worker init --force # 既存ファイルを強制上書き
133
+ ```
134
+
135
+ 作成されるラベル:
136
+
137
+ | ラベル名 | 用途 |
138
+ |---------|------|
139
+ | `cc-update-issue` | Issue更新トリガー |
140
+ | `cc-answer-issue-questions` | Issue確認事項への回答トリガー |
141
+ | `cc-exec-issue` | Issue実行トリガー |
142
+ | `cc-fix-onetime` | PR修正トリガー(1回) |
143
+ | `cc-triage-scope` | トリアージ対象マーク(Issue/PR) |
144
+ | `cc-resolve-conflict` | PRコンフリクト解消トリガー |
145
+ | `cc-in-progress` | 処理中ステータス |
146
+ | `cc-need-human-check` | 人間の確認が必要なマーク(付与中はIssueワーカーの処理対象から除外される) |
147
+ | `cc-issue-created` | `/claude-task-worker:create-issue` 由来のIssueマーク(triage-created-issue のトリガー条件) |
148
+ | `cc-pr-created` | PR作成完了マーク |
149
+ | `cc-epic-issue` | エピックIssueマーク(サブIssueが全Closeで `epic-issue` ワーカーが起動) |
150
+
151
+ 作成されるファイル:
152
+
153
+ - `.github/ISSUE_TEMPLATE/cc-triage-scope.yml` — `cc-triage-scope` ラベル付きIssue作成用テンプレート
154
+ - `.github/workflows/assign-creator-on-cc-triage-scope.yml` — Issue作成者を自動アサインするワークフロー
155
+ - `claude-task-worker.json` — 設定ファイル(コマンド実行ディレクトリ直下)
156
+
157
+ ## コマンド
158
+
159
+ ```bash
160
+ claude-task-worker <command> [--epic <issue-number>]... [--label <label-name>]...
161
+ ```
162
+
163
+ ### `--epic <issue-number>` オプション
164
+
165
+ `all` / `yolo` および Issue 系の各ワーカー(`exec-issue` / `create-issue` / `update-issue` / `answer-issue-questions` / `triage-created-issue` / `epic-issue`)で、指定したエピックIssueのサブIssueのみを処理対象に絞り込む。エピック単位でロールアウトしたいときに使用する。
166
+
167
+ 複数指定可能で、複数指定した場合はいずれかのエピックを親に持つサブIssueが対象になる(OR)。
168
+
169
+ > ℹ️ `epic-issue` ワーカーはエピックIssue自体を処理対象とするため、`--epic` で指定した番号は「サブIssueの親」ではなく「エピックIssue自身の番号」として照合される。`--epic 100` を指定した場合、Epic PR が作成されるのは #100 のみになる。
170
+
171
+ ```bash
172
+ claude-task-worker all --epic 100
173
+ claude-task-worker all --epic 100 --epic 200 # #100 または #200 の sub-issue
174
+ ```
175
+
176
+ ### `--label <label-name>` オプション
177
+
178
+ `all` / `yolo` および Issue 系の各ワーカーで、トリガーラベルに加えて指定したラベルが付いているIssueのみを処理対象に絞り込む。優先度・スプリント・スコープ等で対象を限定したいときに使用する。
179
+
180
+ 複数指定可能で、複数指定した場合は指定したすべてのラベルが付いているIssueが対象になる(AND)。`--epic` と併用すれば両条件のANDで絞り込まれる。
181
+
182
+ ```bash
183
+ claude-task-worker all --label priority-high
184
+ claude-task-worker all --label priority-high --label needs-design # 両方付いている Issue のみ
185
+ claude-task-worker yolo --epic 100 --epic 200 --label priority-high
186
+ ```
187
+
188
+ > ℹ️ `--label` で指定したラベルはユーザーのスコープ指定なので、タスク完了時にワーカー側で除去されることはない(トリガーラベルだけが除去される)。
189
+
190
+ ### exec-issue
191
+
192
+ `cc-exec-issue` ラベルが付いた自分にアサインされたIssueを定期取得し、Claude Codeで処理を実行する。(デフォルト1分間隔)
193
+
194
+ - `cc-in-progress` ラベルを付与
195
+ - `/claude-task-worker:exec-issue <issue番号>` を非同期で実行
196
+ - 親Issueがある場合は `cc-epic-<親Issue番号>` ブランチから worktree を切って実行
197
+ - 完了後、`cc-exec-issue` ラベルを除去し、`cc-pr-created` ラベルを付与
198
+
199
+ ### fix-review-point
200
+
201
+ `cc-fix-onetime` ラベルが付いたPRを定期取得し、Claude Codeで修正を実行する。(1分間隔)
202
+
203
+ - CI完了済みで `cc-in-progress` がないPRが対象
204
+ - 完了後、設定ファイルに `fixReviewPointCallbackCommentMessage` が設定されていればPRにコメント投稿
205
+
206
+ ### create-issue
207
+
208
+ `cc-triage-scope` ラベルが付いており、かつ Open な blockedBy Issue を持たないIssueを定期取得し、Claude CodeでIssue作成を実行する。(1分間隔)
209
+
210
+ `init` コマンドで作成されるIssueテンプレートを使えば、`cc-triage-scope` ラベル付与と作成者アサインが自動で行われる。ブロック中の依存 Issue が残っている間はワーカーが拾わず、依存がすべて Close された時点で処理が開始される。
211
+
212
+ 除外ラベル: `cc-issue-created` / `cc-pr-created` / `cc-update-issue` / `cc-answer-issue-questions` / `cc-exec-issue` のいずれかが付いている Issue は対象外。
213
+
214
+ ### update-issue
215
+
216
+ `cc-update-issue` ラベルが付いたIssueを定期取得し、最新コメントの依頼内容に基づいてClaude CodeでIssue更新を実行する。(1分間隔)
217
+
218
+ ### answer-issue-questions
219
+
220
+ `cc-answer-issue-questions` ラベルが付いたIssueを定期取得し、Issueに記載された確認事項への回答をClaude Codeで生成する。(1分間隔)
221
+
222
+ - 完了後、`cc-update-issue` ラベルを付与して update-issue ワーカーに引き継ぎ
223
+
224
+ ### triage-created-issue
225
+
226
+ `cc-issue-created` と `cc-triage-scope` の両方のラベルが付いたIssueを定期取得し、Claude Codeでトリアージを実行する。(1分間隔)
227
+
228
+ - `cc-pr-created` / `cc-update-issue` / `cc-answer-issue-questions` / `cc-exec-issue` のいずれかが付いているIssueは除外
229
+ - 確認事項の有無に応じて `cc-answer-issue-questions` または `cc-exec-issue` ラベルを付与(または不要ならクローズ)
230
+
231
+ ### triage-pr
232
+
233
+ `cc-triage-scope` ラベルが付いたPRを定期取得し、Claude Codeでトリアージを実行する。(1分間隔)
234
+
235
+ - `cc-fix-onetime` が付いているPRは除外
236
+ - `cc-resolve-conflict` が付いているPRは除外
237
+
238
+ ### resolve-conflict
239
+
240
+ `cc-resolve-conflict` ラベルが付いたPRを定期取得し、`/claude-task-worker:resolve-conflict` を実行してコンフリクト解消を行う。(1分間隔)
241
+
242
+ - 完了後、`cc-resolve-conflict` ラベルを除去
243
+
244
+ ### check-dependabot
245
+
246
+ `dependencies` ラベルが付いたDependabot PRを定期取得し、依存ライブラリのバージョンアップ内容を確認する。(1時間間隔)
247
+
248
+ - `cc-triage-scope` が付いているPRは除外
249
+ - 完了後、`cc-triage-scope` ラベルを付与して triage-pr ワーカーに引き継ぎ
250
+
251
+ ### epic-issue
252
+
253
+ `cc-epic-issue` ラベルが付いた親Issueを定期取得し、紐づくサブIssueがすべて Close されたタイミングで `/claude-task-worker:create-epic-pr` を起動してエピックPRを作成する。(デフォルト5分間隔)
254
+
255
+ - `cc-pr-created` が付いているIssueは除外
256
+ - サブIssueが存在しない、または1つでも未Closeのものがあればスキップ
257
+ - 完了後、`cc-pr-created` ラベルを付与
258
+
259
+ ### all
260
+
261
+ 通常ワーカー7つ(exec-issue, fix-review-point, create-issue, update-issue, answer-issue-questions, resolve-conflict, epic-issue)を同時にポーリングする。`--epic` / `--label` オプションでIssue系ワーカーの処理対象を絞り込み可能(どちらも複数指定可)。
262
+
263
+ ### yolo
264
+
265
+ すべてのワーカー(`all` + triage-created-issue + triage-pr + check-dependabot)を同時にポーリングする。`--epic` / `--label` オプションでIssue系ワーカーの処理対象を絞り込み可能(どちらも複数指定可)。
266
+
267
+ ### usage
268
+
269
+ 現在のClaude API使用状況をSlackに通知する。
270
+
271
+ ### install
272
+
273
+ `claude-task-worker` マーケットプレイスの追加・プラグインのインストール・CLI本体のグローバルインストールを一括で行う。
274
+
275
+ ```bash
276
+ npx claude-task-worker install
277
+ ```
278
+
279
+ - `claude plugin marketplace add getty104/claude-task-worker` — マーケットプレイスの追加(追加済みの場合のエラーはログのみで無視して続行)
280
+ - `claude plugin install claude-task-worker@claude-task-worker` — プラグインのインストール
281
+ - `npm install -g claude-task-worker@latest` — CLI 本体のグローバルインストール
282
+
283
+ いずれかのステップが失敗しても処理は継続し、`[install]` プレフィックス付きでエラー内容がログ出力される。
284
+
285
+ ### update
286
+
287
+ `claude-task-worker` プラグイン/マーケットプレイスとCLI本体を更新する。
288
+
289
+ ```bash
290
+ claude-task-worker update
291
+ ```
292
+
293
+ - `claude plugin marketplace update claude-task-worker` — マーケットプレイスの更新
294
+ - `claude plugin update claude-task-worker@claude-task-worker` — プラグインの更新(反映にはセッション再起動が必要)
295
+ - `npm install -g claude-task-worker@latest` — CLI 本体の更新
296
+
297
+ いずれかのステップが失敗しても処理は継続し、`[update]` プレフィックス付きでエラー内容がログ出力される。
298
+
299
+ ## 設定ファイル
300
+
301
+ コマンドを実行したディレクトリ直下の `claude-task-worker.json` を読み込む。
302
+
303
+ | キー | 型 | デフォルト | 説明 |
304
+ |---|---|---|---|
305
+ | `fixReviewPointCallbackCommentMessage` | string | - | fix-review-point 完了時にPRへ投稿するコメント(未設定の場合は投稿しない) |
306
+ | `workers` | object | `{}` | ワーカーごとに Claude CLI に渡すスキル、`--model` / `--effort`、ポーリング間隔、クールダウン時間、最大同時実行数を上書きする設定(詳細は下記) |
307
+
308
+ ### ワーカーごとの設定
309
+
310
+ `workers` キーにワーカー名ごとの設定オブジェクトを指定することで、Claude CLI の `-p` に渡すスキル(スラッシュコマンド)、`--model` / `--effort`、ポーリング間隔、タスク完了後のクールダウン時間、最大同時実行数を個別に上書きできる。未指定のワーカー・フィールドは下記のワーカー別デフォルト値が使用される。
311
+
312
+ | ワーカー名 | デフォルト `skill` | デフォルト `model` | デフォルト `effort` | デフォルト `pollingIntervalSeconds` | デフォルト `cooldownSeconds` | デフォルト `maxConcurrentTasks` |
313
+ |---|---|---|---|---|---|---|
314
+ | `answer-issue-questions` | `/claude-task-worker:answer-issue-questions` | `opus` | `xhigh` | 60 | 0 | 1 |
315
+ | `create-issue` | `/claude-task-worker:create-issue-from-issue-number` | `opus` | `xhigh` | 60 | 0 | 1 |
316
+ | `update-issue` | `/claude-task-worker:update-issue` | `sonnet` | `xhigh` | 60 | 0 | 1 |
317
+ | `exec-issue` | `/claude-task-worker:exec-issue` | `sonnet` | `xhigh` | 60 | 0 | 1 |
318
+ | `fix-review-point` | `/claude-task-worker:fix-review-point` | `sonnet` | `xhigh` | 60 | 0 | 1 |
319
+ | `triage-created-issue` | `/claude-task-worker:triage-created-issue` | `sonnet` | `xhigh` | 60 | 0 | 1 |
320
+ | `triage-pr` | `/claude-task-worker:triage-pr` | `sonnet` | `xhigh` | 60 | 0 | 1 |
321
+ | `resolve-conflict` | `/claude-task-worker:resolve-pr-conflict` | `sonnet` | `xhigh` | 60 | 0 | 1 |
322
+ | `check-dependabot` | `/claude-task-worker:check-dependabot` | `sonnet` | `xhigh` | 3600 | 0 | 1 |
323
+ | `epic-issue` | `/claude-task-worker:create-epic-pr` | `sonnet` | `xhigh` | 300 | 0 | 1 |
324
+
325
+ 各フィールドの値:
326
+
327
+ | フィールド | 型 | 説明 |
328
+ |---|---|---|
329
+ | `skill` | string | Claude CLI の `-p` に渡すスラッシュコマンド(例: `/claude-task-worker:exec-issue`, `/my-plugin:my-skill`)。ワーカーは `"<skill> <issue-or-pr-number>"` の形で Claude を起動する |
330
+ | `model` | string | Claude CLI の `--model` に渡す値(例: `sonnet`, `opus`, `haiku`) |
331
+ | `effort` | string | Claude CLI の `--effort` に渡す値(例: `high`, `medium`, `low`) |
332
+ | `pollingIntervalSeconds` | number | GitHub をポーリングする間隔(秒)。正の数を指定する |
333
+ | `cooldownSeconds` | number | タスク完了後に次のポーリングを停止する時間(秒)。`0` でクールダウンなし |
334
+ | `maxConcurrentTasks` | number | そのワーカーが同時に実行できるタスクの最大数。正の整数を指定する |
335
+
336
+ 設定例:
337
+
338
+ ```json
339
+ {
340
+ "workers": {
341
+ "exec-issue": { "skill": "/my-plugin:exec-issue", "model": "opus", "effort": "high", "pollingIntervalSeconds": 60, "cooldownSeconds": 600, "maxConcurrentTasks": 3 },
342
+ "fix-review-point": { "skill": "/claude-task-worker:fix-review-point", "model": "sonnet", "effort": "high", "maxConcurrentTasks": 2 },
343
+ "triage-pr": { "effort": "medium", "pollingIntervalSeconds": 120 },
344
+ "check-dependabot": { "model": "haiku", "pollingIntervalSeconds": 7200 }
345
+ }
346
+ }
347
+ ```
348
+
349
+ > 💡 **推奨:** 重い実装タスク(`exec-issue`, `fix-review-point`)では `/advisor` を有効にすることを推奨する。事前/事後に強力なレビューモデルへ相談することで、アプローチの誤りや見落としを早期に検出でき、完了率と品質が向上する。各ワーカーが呼び出すスキルのプロンプト内で `advisor` ツールを活用する運用を推奨。
350
+
351
+ ## Slack通知
352
+
353
+ 環境変数 `CLAUDE_TASK_WORKER_SLACK_WEBHOOK_URL` にSlack Incoming Webhook URLを設定すると、各ワーカーのタスク完了時・失敗時にSlackへ通知が送信される。
354
+
355
+ ```bash
356
+ export CLAUDE_TASK_WORKER_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx/yyy/zzz
357
+ claude-task-worker all
358
+ ```
359
+
360
+ 通知にはClaude APIの使用状況(5時間/7日間の利用率とリセット時刻)も含まれる。未設定の場合、通知は送信されない。
361
+
362
+ ## プロセス管理
363
+
364
+ 実行中のタスクはリアルタイムのステータステーブルで表示される。
365
+
366
+ - タスクID・タイトル・ステータス(running/completed/failed)・開始時刻・経過時間を表示
367
+ - 同一Issue/PRの重複実行を自動防止
368
+ - SIGTERM/SIGINTで全子プロセスをgraceful shutdown
369
+
370
+ ## 開発
371
+
372
+ ```bash
373
+ npm install
374
+ npm run build # TypeScript → dist/
375
+ npm run dev # Watch mode (auto-rebuild)
376
+ ```
377
+
378
+ コントリビューションを歓迎します。開発環境のセットアップ・PRの出し方は [CONTRIBUTING.md](./CONTRIBUTING.md) を参照してください。バグ報告・機能要望は [Issue テンプレート](https://github.com/getty104/claude-task-worker/issues/new/choose) から作成してください。
379
+
380
+ セキュリティ上の脆弱性は公開Issueではなく [SECURITY.md](./SECURITY.md) の手順で報告してください。
381
+
382
+ 本プロジェクトへの参加にあたっては [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md)(Contributor Covenant)を遵守してください。
383
+
384
+ ## ライセンス
385
+
386
+ MIT License. 詳細は [LICENSE](./LICENSE) を参照してください。
@@ -0,0 +1 @@
1
+ export declare function init(): Promise<void>;
@@ -0,0 +1,84 @@
1
+ import { mkdir, writeFile, access } from "node:fs/promises";
2
+ import { createLabel } from "../gh.js";
3
+ const LABELS = [
4
+ { name: "cc-create-issue", color: "0075ca" },
5
+ { name: "cc-update-issue", color: "e4e669" },
6
+ { name: "cc-exec-issue", color: "7057ff" },
7
+ { name: "cc-fix-onetime", color: "d93f0b" },
8
+ { name: "cc-fix-repeat", color: "b60205" },
9
+ { name: "cc-in-progress", color: "0e8a16" },
10
+ { name: "cc-issue-created", color: "f9a825" },
11
+ { name: "cc-pr-created", color: "006b75" },
12
+ { name: "cc-triage-scope", color: "c5def5" },
13
+ ];
14
+ const ISSUE_TEMPLATE = `name: "[claude-task-worker] Issue作成依頼"
15
+ description: claude-task-workerでGitHub Issueを作成する
16
+ title: "[claude-task-worker] Issue作成依頼"
17
+ labels:
18
+ - cc-create-issue
19
+ body:
20
+ - type: textarea
21
+ id: request
22
+ attributes:
23
+ label: 依頼内容
24
+ description: 作成してほしいIssueの内容を記述してください
25
+ validations:
26
+ required: true
27
+ `;
28
+ const ASSIGN_CREATOR_WORKFLOW = `name: Assign creator on cc-create-issue
29
+
30
+ on:
31
+ issues:
32
+ types: [opened]
33
+
34
+ jobs:
35
+ assign:
36
+ if: contains(github.event.issue.labels.*.name, 'cc-create-issue')
37
+ runs-on: ubuntu-latest
38
+ permissions:
39
+ issues: write
40
+ steps:
41
+ - uses: actions/github-script@v7
42
+ with:
43
+ script: |
44
+ await github.rest.issues.addAssignees({
45
+ owner: context.repo.owner,
46
+ repo: context.repo.repo,
47
+ issue_number: context.issue.number,
48
+ assignees: [context.payload.issue.user.login]
49
+ });
50
+ `;
51
+ async function createFileIfNotExists(path, content) {
52
+ try {
53
+ await access(path);
54
+ return false;
55
+ }
56
+ catch {
57
+ await writeFile(path, content, "utf-8");
58
+ return true;
59
+ }
60
+ }
61
+ export async function init() {
62
+ console.log("[init] Creating labels...");
63
+ for (const label of LABELS) {
64
+ const ok = await createLabel(label.name, label.color, true);
65
+ if (ok) {
66
+ console.log(`[init] Ensured label: ${label.name}`);
67
+ }
68
+ else {
69
+ console.log(`[init] Failed to create label: ${label.name}`);
70
+ }
71
+ }
72
+ console.log("[init] Creating issue template...");
73
+ await mkdir(".github/ISSUE_TEMPLATE", { recursive: true });
74
+ const templatePath = ".github/ISSUE_TEMPLATE/cc-create-issue.yml";
75
+ const templateCreated = await createFileIfNotExists(templatePath, ISSUE_TEMPLATE);
76
+ console.log(templateCreated ? `[init] Created: ${templatePath}` : `[init] Already exists: ${templatePath}`);
77
+ console.log("[init] Creating GitHub Actions workflow...");
78
+ await mkdir(".github/workflows", { recursive: true });
79
+ const workflowPath = ".github/workflows/assign-creator-on-cc-create-issue.yml";
80
+ const workflowCreated = await createFileIfNotExists(workflowPath, ASSIGN_CREATOR_WORKFLOW);
81
+ console.log(workflowCreated ? `[init] Created: ${workflowPath}` : `[init] Already exists: ${workflowPath}`);
82
+ console.log("[init] Done.");
83
+ }
84
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
package/dist/gh.d.ts ADDED
@@ -0,0 +1,47 @@
1
+ interface Issue {
2
+ number: number;
3
+ title: string;
4
+ labels: {
5
+ name: string;
6
+ }[];
7
+ body: string;
8
+ state: string;
9
+ }
10
+ interface PullRequest {
11
+ number: number;
12
+ headRefName: string;
13
+ labels: {
14
+ name: string;
15
+ }[];
16
+ title: string;
17
+ }
18
+ interface RepoInfo {
19
+ owner: string;
20
+ name: string;
21
+ defaultBranch: string;
22
+ }
23
+ export declare function getCurrentUser(): Promise<string>;
24
+ export declare function getRepoInfo(): Promise<RepoInfo>;
25
+ export declare function listIssues(assignee: string, label: string): Promise<Issue[]>;
26
+ export declare function listAllIssues(assignee: string): Promise<Issue[]>;
27
+ interface StatusCheck {
28
+ __typename: string;
29
+ status?: string;
30
+ state?: string;
31
+ }
32
+ interface PullRequestWithChecks extends PullRequest {
33
+ statusCheckRollup: StatusCheck[];
34
+ }
35
+ export declare function isCICompleted(checks: StatusCheck[]): boolean;
36
+ export declare function listPullRequestsWithChecks(assignee?: string, options?: {
37
+ triageScope?: boolean;
38
+ }): Promise<PullRequestWithChecks[]>;
39
+ export declare function addLabel(type: "issue" | "pr", number: number, label: string): Promise<void>;
40
+ export declare function removeLabel(type: "issue" | "pr", number: number, label: string): Promise<void>;
41
+ export declare function getLastIssueComment(issueNumber: number): Promise<{
42
+ author: string;
43
+ body: string;
44
+ } | null>;
45
+ export declare function commentOnIssue(issueNumber: number, body: string): Promise<void>;
46
+ export declare function createLabel(name: string, color?: string, force?: boolean): Promise<boolean>;
47
+ export {};
package/dist/gh.js ADDED
@@ -0,0 +1,113 @@
1
+ import { execFile } from "node:child_process";
2
+ function execGh(args) {
3
+ return new Promise((resolve, reject) => {
4
+ execFile("gh", args, (error, stdout, stderr) => {
5
+ if (error) {
6
+ reject(new Error(`gh ${args.join(" ")} failed: ${stderr || error.message}`));
7
+ return;
8
+ }
9
+ resolve(stdout.trim());
10
+ });
11
+ });
12
+ }
13
+ export async function getCurrentUser() {
14
+ return execGh(["api", "user", "--jq", ".login"]);
15
+ }
16
+ export async function getRepoInfo() {
17
+ const output = await execGh(["repo", "view", "--json", "owner,name,defaultBranchRef"]);
18
+ const parsed = JSON.parse(output);
19
+ return { owner: parsed.owner.login, name: parsed.name, defaultBranch: parsed.defaultBranchRef.name };
20
+ }
21
+ export async function listIssues(assignee, label) {
22
+ const output = await execGh([
23
+ "issue", "list",
24
+ "--assignee", assignee,
25
+ "--label", label,
26
+ "--json", "number,title,labels",
27
+ "--limit", "100",
28
+ ]);
29
+ return JSON.parse(output);
30
+ }
31
+ export async function listAllIssues(assignee) {
32
+ const output = await execGh([
33
+ "issue", "list",
34
+ "--assignee", assignee,
35
+ "--label", "cc-triage-scope",
36
+ "--search", "sort:created-asc",
37
+ "--json", "number,title,labels",
38
+ "--limit", "5",
39
+ ]);
40
+ return JSON.parse(output);
41
+ }
42
+ export function isCICompleted(checks) {
43
+ if (checks.length === 0)
44
+ return true;
45
+ return checks.every(check => {
46
+ if (check.__typename === "CheckRun") {
47
+ return check.status === "COMPLETED";
48
+ }
49
+ return check.state !== "PENDING";
50
+ });
51
+ }
52
+ export async function listPullRequestsWithChecks(assignee, options) {
53
+ const args = [
54
+ "pr", "list",
55
+ "--json", "number,headRefName,labels,title,statusCheckRollup",
56
+ "--limit", "100",
57
+ ];
58
+ if (options?.triageScope) {
59
+ args.push("--label", "cc-triage-scope");
60
+ }
61
+ if (assignee) {
62
+ args.push("--assignee", assignee);
63
+ }
64
+ const output = await execGh(args);
65
+ return JSON.parse(output);
66
+ }
67
+ async function withRetry(fn, maxRetries = 3, delayMs = 1000) {
68
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
69
+ try {
70
+ return await fn();
71
+ }
72
+ catch (err) {
73
+ if (attempt === maxRetries)
74
+ throw err;
75
+ console.error(`[gh] Attempt ${attempt}/${maxRetries} failed, retrying in ${delayMs}ms...`);
76
+ await new Promise(resolve => setTimeout(resolve, delayMs));
77
+ }
78
+ }
79
+ throw new Error("unreachable");
80
+ }
81
+ export async function addLabel(type, number, label) {
82
+ await withRetry(() => execGh([type, "edit", String(number), "--add-label", label]));
83
+ }
84
+ export async function removeLabel(type, number, label) {
85
+ await withRetry(() => execGh([type, "edit", String(number), "--remove-label", label]));
86
+ }
87
+ export async function getLastIssueComment(issueNumber) {
88
+ const output = await execGh(["issue", "view", String(issueNumber), "--json", "comments"]);
89
+ const parsed = JSON.parse(output);
90
+ const comments = parsed.comments ?? [];
91
+ if (comments.length === 0)
92
+ return null;
93
+ const last = comments[comments.length - 1];
94
+ return { author: last.author.login, body: last.body };
95
+ }
96
+ export async function commentOnIssue(issueNumber, body) {
97
+ await execGh(["issue", "comment", String(issueNumber), "--body", body]);
98
+ }
99
+ export async function createLabel(name, color, force) {
100
+ try {
101
+ const args = ["label", "create", name];
102
+ if (color)
103
+ args.push("--color", color);
104
+ if (force)
105
+ args.push("--force");
106
+ await execGh(args);
107
+ return true;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ //# sourceMappingURL=gh.js.map