AI コーディングエージェントは高速です。関数を生成し、モジュールをリファクタリングし、定型コードを人間よりも速く組み上げます。しかしデフォルトでは、チームが合意した規約(lint ルール、シニアエンジニアが PR ごとに指摘するレビューパターン)を強制することはありません。生成された diff は、誰かが CI を実行するか注意深く読むまでは問題がないように見えます。
Chunk CLI はそのギャップをインナーループで埋めます。インナーループとは、コードが CI に届く前に行われる、ローカルの編集・テスト・コミットのサイクルです。特定のコードベースでレビュアーが実際に重視していることを PR 履歴から学習し、すべての AI エージェントセッションに実際の lint とテストチェックを組み込んでエージェントが完了前に自己修正できるようにし、より難しい問題は CircleCI パイプライン内で実行される Chunk タスクに引き渡してチームが他の作業を進められるようにします。
このチュートリアルはサンプル API プロジェクトを対象に Chunk の主要コマンドを解説しますが、同じ原則はどのコードベースにも適用できます。
build-prompt: GitHub Org から実際の PR レビュー履歴をマイニングし、チームの実際のパターンに合わせたレビュープロンプトを生成します。initとskill install: そのプロンプトをコミットゲートおよびオンデマンドレビュースキルとして Claude Code に組み込み、プロンプトに頼ることなく品質チェックを自動実行します。task: 体系的な修正を Chunk に引き渡します。Chunk は CircleCI パイプラインを実行して変更を検証し、ローカル開発を中断することなく PR を作成します。
チュートリアルの最後には、チームのレビュー基準がコード化され、ローカルで適用され、CI でスケールして実行されるようになります。
前提条件
Chunk が特定のチームとコードベースに対して何を提示するかを確認するために、アクティブなレビュー履歴を持つリポジトリを用意してください。
- Homebrew
- Claude Code(このチュートリアルでは Claude Code を使用しますが、ライフサイクルフックをサポートする AI コーディングエージェントであれば同じアプローチが使えます)
- プルリクエスト履歴を持つリポジトリが 1 つ以上ある GitHub アカウント
- GitHub App 経由で GitHub に接続された CircleCI アカウント(OAuth は Chunk タスクに対応していません)
- CircleCI Org で Chunk が有効化されていること(Org 設定 → Advanced → Allow Chunk tasks)
- Anthropic API キー
- CircleCI パーソナル API トークン(
CIRCLECI_TOKEN) - Node.js がインストールされていること
ステップ 1: build-prompt でレビュー履歴をマイニングする
AI エージェントはチームの規約を知りません。スタイルガイドのプロンプトは手動で書くこともできますが、チームの基準が変化するにつれて陳腐化します。build-prompt はこのプロセスを自動化します。GitHub Org から実際の PR レビューコメントをマイニングし、AI でパターン分析を行い、エージェントがコンテキストとして使用できる Markdown プロンプトファイルを生成します。このプロンプトは、レビュアーが実際に指摘した繰り返しのパターンを反映しています。
出力の品質はレビュー履歴の深さに依存します。最適なソースは、詳細で内容のある PR レビューを持つリポジトリです。
インストールと認証
Chunk CLI をインストールして認証します:
brew install CircleCI-Public/circleci/chunk
chunk --version
chunk auth login # prompts for Anthropic API key; stores to ~/.config/chunk/config.json
chunk auth status
build-prompt は PR レビューデータを読み取るために repo スコープ付きの GitHub トークンも必要です:
export GITHUB_TOKEN=<token-with-repo-scope>
実行する
リポジトリのルートから実行します:
cd task-api
chunk build-prompt --org <your-org> --repos <your-repo> --top 5
--top 5 はコメント数が多い上位 5 件の PR に分析を絞り込みます。過去 3 ヶ月間に PR アクティビティがないリポジトリの場合は、--since を追加して検出期間を延長します:
chunk build-prompt --org <your-org> --repos <your-repo> --top 5 --since 2024-01-01
CLI は 3 つのステージ(Discover、Analyze、Generate)を実行し、進捗を随時出力します。
chunk build-prompt の結果
.chunk/context/ に 4 つのファイルが生成されます:
review-prompt.md: 生成されたプロンプト。review-prompt-analysis.md: 選択された PR とその理由。review-prompt-details.json: 抽出されたコメントの生データ。review-prompt-details-pr-rankings.csv: PR スコア。
次のステップに進む前に review-prompt.md を読んでおくことをお勧めします。レビュースキルがコードの変更を評価する際に使用する内容が正確にわかります。以下はデモリポジトリのレビューコメントから生成されたプロンプトの一部です。6 つのコア原則のうち最初の 4 つは、上位レビュー PR においてレビュアーが実際に書いた内容のみから抽出されています。
# PR Review Agent Prompt
You are a senior security-conscious code reviewer for a TypeScript/Node.js backend codebase. Your job is to identify defects, vulnerabilities, and maintainability issues in pull requests before they reach production. You review with the mindset that every merged PR must meet a security and correctness baseline — there are no "fix later" items for authentication flaws, missing validation, or unhandled errors.
## Core Principles
1. **Security is non-negotiable at every layer.** Authentication, authorization, network inputs, secret management, and information disclosure must all be correct before merge. A single oversight in any of these creates a production vulnerability.
2. **Validate everything at the boundary.** No data from `req.body`, `req.query`, `req.params`, or external sources crosses the API boundary without being checked for presence, type, format, and valid domain values. Missing validation is a bug, not a polish item.
3. **TypeScript must provide real safety, not theater.** Using `any` or type-casting to silence the compiler actively harms the codebase. If TypeScript isn't catching your bugs, you're not using it correctly.
4. **Design for failure and concurrency.** Every external call, I/O operation, and parse operation must handle failure explicitly. Code must behave correctly under concurrent access — no shared temp files, no lost events, no race conditions.
これらの原則はどれも手動で書かれたものではありません。build-prompt は、レビュアーが実際に書いた内容(プルリクエスト全体で繰り返し現れたテーマ)から抽出しています。完全なプロンプトには、本番対応と一貫性に関する原則、レビューチェックリスト、before/after コード例、重大度レベルを含む構造化されたレスポンス形式も含まれています。
## Review Rules
### Security
- [ ] Passwords are hashed with bcrypt or argon2 with proper salt rounds — never stored or compared in plaintext
- [ ] Tokens are cryptographically signed (e.g., JWT with HMAC/RSA) and include expiration — base64 encoding alone is not authentication
- [ ] Secrets are never returned in API responses after creation; mask or omit entirely
- [ ] No hardcoded default secrets or API keys — every secret must be explicitly configured
- [ ] User-supplied URLs are validated: scheme restricted (https in production), hostname parsed, private/internal IP ranges blocked (SSRF prevention)
- [ ] Sensitive endpoints require authentication/authorization checks
- [ ] Error responses never leak stack traces, internal paths, or system details to clients
### Input Validation
- [ ] Every endpoint validates all inputs for presence, type, format, and range before processing
- [ ] Enum-like parameters (status, priority, format) validate against known values and return 400 for invalid input
- [ ] Pagination parameters reject zero, negative, or non-numeric values
- [ ] Import/bulk endpoints validate payload existence, format, size limits, and schema of individual records
- [ ] String inputs enforce length limits; email fields validate format
平文の認証情報に関する項目は、ユーザー登録エンドポイントでパスワードが直接保存されているのを発見したレビュアーから来ています。URL バリデーションの項目は、制限なく任意の URL を受け入れていたウェブフック登録エンドポイント(SSRF の脆弱性)から来ています。TypeScript の any ルールは、3 件の異なる PR でレビュアーが指摘したことから来ています。これらのパターンは実際のレビューから来たものであり、汎用的なアドバイスではありません。
生成されたプロンプトには、実際のレビューパターンを基にした before/after コード例も含まれています。
## Code Examples
<details>
<summary>❌ Plaintext passwords → ✅ Hashed passwords</summary>
**Bad:**
```typescript
const user = { email, password: req.body.password, name };
users.push(user);
```
**Good:**
```typescript
import bcrypt from 'bcrypt';
const SALT_ROUNDS = 12;
const hashedPassword = await bcrypt.hash(req.body.password, SALT_ROUNDS);
const user = { email, password: hashedPassword, name };
users.push(user);
```
</details>
後で /chunk-review を実行すると、このプロンプトがレビューサブエージェントによって diff の評価に使用されます。チームのレビュアーがこれまで指摘してきた内容と照合してチェックします。
ステップ 2: chunk init と chunk skill でインナーループを閉じる
インナーループは AI コーディング作業のほとんどが実際に行われる場所です。エージェントが変更を生成し、レビューされ、修正が要求され、サイクルが繰り返されます。プロンプトは決定論的ではありません。「コミット前にテストを実行して」というプロンプトは、コンテキストが圧縮された後に忘れられたり、複雑なマルチファイル編集中にスキップされたり、エージェントが変更が小さすぎると判断したときに静かに無視されたりします。
フックはこの問題を解決します。フックはライフサイクルイベント(セッション開始時、ツール実行時、エージェントがコミットしようとするとき)で発火するコマンドで、エージェントはスキップできません。フックが失敗した場合、エージェントは出力を検知し、続行する前に対応する必要があります。AI コーディングエージェントにおけるフックの仕組みについて詳しくは、AI 開発向けテストフックをご覧ください。
Chunk はフックを使って 2 つの品質チェックを Claude Code に組み込みます:
- コミットゲート: すべての
git commitの前にテストスイートと linter を実行するPreToolUseフック。どちらかが失敗した場合はコミットをブロックし、変更が確定する前に Claude が自己修正します。 - レビュースキル: ステップ 1 で生成されたプロンプトに対して diff を評価するオンデマンドエージェント。実際のチームレビューパターンと照合して変更をチェックします。
どちらもプロンプトに「テストを実行して」や「これをレビューして」と入力する必要はありません。ゲートは Claude がコミットしようとするたびに発火します。レビュースキルは明示的に呼び出したときに実行されます。
プロジェクトを初期化する
npm install -g @anthropic-ai/claude-code
リポジトリのルートから実行します:
chunk init
chunk init はプロジェクトのパッケージマネージャとテストコマンドを検出し、2 つのファイルを書き込んで終了します:
Detected repository: <your-org>/<your-repo>
Detected package manager: npm
Detected command: test (npm test)
✓ Wrote .chunk/config.json
✓ Wrote .claude/settings.json
✓ Project initialized
2 つのファイルの役割:
.chunk/config.json:chunk validateによる手動実行用の検証コマンド。.claude/settings.json: コミットゲートフックを含む Claude Code の初期設定。
config.json は chunk validate による手動チェック実行に便利です。設定されたチェックをコンテンツハッシュキャッシュ付きで実行し、セッション間の素早い検証を可能にします。自動化されたゲートは settings.json です。chunk init が生成する内容は以下の通りです:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git commit*)",
"hooks": [
{ "type": "command", "command": "cd ${CLAUDE_PROJECT_DIR:-.} && npm ci", "timeout": 60 },
{ "type": "command", "command": "cd ${CLAUDE_PROJECT_DIR:-.} && npm test", "timeout": 300 }
]
}
]
}
}
これにより、すべての git commit の前に npm ci と npm test が実行されます。機能しますが、linter は含まれていません。テストと lint の両方をゲートするバージョンに置き換えてください:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": ["Bash(chunk:*)"]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "INPUT=$(cat); echo \"$INPUT\" | grep -q '\"git commit' || exit 0; npx jest --passWithNoTests && npx eslint src/ __tests__/ || exit 2",
"timeout": 120
}
]
}
]
}
}
この設定についての注意点:
matcher: "Bash"はすべての Bash ツール呼び出しをキャッチします。フックは標準入力からツール入力を読み取り、git commit以外はすぐに exit 0 するため、他のシェルコマンドへのオーバーヘッドはありません。|| exit 2はブロッキング動作に必須です。終了コード 2 は Claude Code にツール呼び出しをブロックして出力を Claude に表示するよう指示します。終了コード 1 はフックエラーとして扱われ、ブロックできません。- フックはプロジェクトディレクトリで実行されるため、
claudeをリポジトリルートから起動した場合はcdは不要です。
他のスタックの場合: npx jest --passWithNoTests をプロジェクトのテストランナーに、npx eslint src/ __tests__/ を linter に置き換えてください。構造は同じです。
レビュースキルをインストールする
実行します:
chunk skill install
これにより Chunk のバンドルスキルが ~/.claude/skills/ にインストールされ、このリポジトリだけでなくすべての Claude Code セッションでグローバルに利用できます。Chunk には 3 つのスキルがバンドルされています: chunk-review(チームの生成プロンプトに対するコードレビュー)、chunk-testing-gaps(カバレッジのギャップを見つけるためのミューテーションテスト)、debug-ci-failures(CircleCI 障害の診断)。
このチュートリアルでは chunk-review を使用します。.chunk/context/review-prompt.md を読み込み、過去の会話コンテキストが結果に影響しないよう独立したサブエージェントを通じてレビューを実行します。
セッションの流れ
リポジトリ内から Claude Code セッションを開始します:
claude
Claude にタスクを与えます:
Add a utility function to src/utils/formatDate.ts that takes a JavaScript Date object and returns a string in YYYY-MM-DD format. Include tests. When done, commit the change.
流れは以下の通りです:
- Claude が
src/utils/formatDate.tsを作成して関数を記述します。 - Claude が
__tests__/formatDate.test.tsにテストを追加します。 - Claude が
git commitを実行すると、PreToolUseフックが発火します。コミットが確定する前に Jest と ESLint が実行されます。 - テストが失敗した場合、フックはコード 2 で終了してコミットをブロックします。Claude はテスト出力全体をコンテキストとして解釈します。
- Claude は失敗を読み取り、根本原因を特定して元のコードを修正し、コミットを再試行します。
- テストと lint が通過し、コミットが確定します。
さらに AI レビューを受けるには、セッション内からレビュースキルを呼び出します:
/chunk-review
スキルは .chunk/context/review-prompt.md を読み込み、diff を組み立て、サブエージェントを通じてレビューを実行します。出力はチームの実際の PR パターン(そのコードベースの実際のレビューで明らかになった具体的な問題)に基づいています。
ステップ 3: chunk task で自律的に修正する
フックはインナーループを閉じます。タスクはアウターループを閉じます。Chunk タスクは CircleCI パイプライン内で動作する自律エージェントです。リポジトリを読み込み、必要なコード変更を行い、テストスイートで検証し、パイプラインが通過したときに GitHub PR を作成します。ローカル環境は不要です。開発が他の場所で続く間、作業は CircleCI インフラ上で実行されます。
これは、複数のエンドポイントへの入力バリデーションの追加、エラーハンドリングの補完、テストカバレッジのギャップ解消など、レビュープロンプトが明らかにする体系的な改善に特に役立ちます。パターンはレビュー履歴から明確で、作業は繰り返し的であり、バリデーションループはローカルのターミナルよりも CI に属しています。
始める前に
リポジトリは OAuth ではなく GitHub App 経由で CircleCI に接続する必要があります。GitHub App 接続により Chunk はパイプラインのトリガー、ブランチの作成、PR の作成の権限を得ます。また Chunk は Org レベルで有効化する必要があります: CircleCI の Org 設定 → Advanced に移動し、Allow Chunk tasks を有効にしてください。
chunk task run にはシェル環境に CIRCLECI_TOKEN と GITHUB_TOKEN の両方が必要です。すべてのセッションで利用できるよう、両方を ~/.zshrc(または ~/.bashrc)に追加してください。
タスクランナーを設定する
入力します:
chunk task config
インタラクティブウィザードが CircleCI の Org ID、プロジェクト ID、パイプライン定義の入力を求めます。完了すると .chunk/run.json を書き込みます。
ウィザード実行後に確認すべき点: .chunk/run.json を開いて、definition_id が CircleCI UI の Project Settings → Pipelines にある chunk-task-pipeline エントリと一致していることを確認してください。ウィザードは Chunk のエージェントで機能しない推測されたビルドパイプラインを選択する場合があります。正しい定義は chunk-task-pipeline という名前のもので、Chunk が Org で有効になると CircleCI が自動的に作成します。
生成されるファイルの内容は以下の通りです:
{
"org_id": "<your-circleci-org-id>",
"project_id": "<your-circleci-project-id>",
"org_type": "circleci",
"definitions": {
"dev": {
"definition_id": "<chunk-task-pipeline-id>",
"default_branch": "main"
}
}
}
.chunk/run.json は .gitignore に追加してください。アカウント固有の ID が含まれています。
テスト結果を連携する
Chunk が単なる合否だけでなく個別のテスト失敗を読み取るには、パイプラインが JUnit の結果を保存する必要があります。.circleci/config.yml に以下の内容を入力します:
- run:
name: Run tests
command: npm test -- --reporters=default --reporters=jest-junit
environment:
JEST_JUNIT_OUTPUT_DIR: ./test-results
- store_test_results:
path: ./test-results
store_test_results がない場合、Chunk はパイプラインが通過したか失敗したかを判断できますが、具体的なテスト名と失敗メッセージを読み取ることができません。その詳細な出力こそが、エージェントに何を修正すべきかを正確に伝えるものです。
タスクを実行する
ステップ 1 の分析により、プルリクエスト全体で繰り返されているパターンが特定されました。入力バリデーションの欠如と、チェックなしに任意の入力を受け入れるエンドポイントです。これらをローカルセッションで 1 件ずつ修正するのではなく、Chunk タスクに作業を引き渡します。タスクの説明はレビュープロンプトの具体的なパターンを参照できます:
chunk task run \
--definition dev \
--new-branch \
--prompt "Our review prompt (.chunk/context/review-prompt.md) identifies missing \
input validation as the most common issue across PRs. Add zod schema validation \
to the POST and PUT /tasks endpoints: title must be a non-empty string (max 200 \
chars), status must be one of 'pending', 'in_progress', or 'done', and priority \
must be one of 'low', 'medium', or 'high'. Return 400 with specific error \
messages for invalid input. Add tests for both valid and invalid inputs. Make \
sure all existing tests still pass."
CLI は送信を確認してラン ID を返します。CircleCI UI では chunk-task ワークフローが開始します。Chunk はリポジトリを読み込み、バリデーションロジックとテストを追加し、何も壊れていないことを確認するためにフルテストスイートを実行し、main に対して PR を作成します。
タスクをトリガーした後、CircleCI の Web インターフェースに Chunk が作業している様子が表示されます。
Chunk が完了すると、実行内容のサマリーが出力され、PR の変更を示す diff が作成されます。
PR はタスクエンドポイントにスキーマバリデーションを追加し、すべての無効な入力ケースのテストを含んでいます。まさにレビュープロンプトが指摘したパターンです。修正は、チームの誰かが 1 行読む前に、すべての PR で実行される同じパイプラインで検証されました。
Chunk は CircleCI パイプラインを実行し、すべてのテストが通過してグリーンで返ってきました。
ここで以前の作業が報われます。build-prompt は実際のレビューからパターンを抽出しました。コミットゲートとレビュースキルは、すべてのローカル変更にそれらを適用しました。また、Chunk タスクは、同じパターンを使ってコードベース全体の体系的な修正を推進し、CI で検証されてマージ可能な PR としてランディングしました。
自分のコードで試してみる
これまでの内容を振り返ります:
build-promptは実際の PR レビューコメントをマイニングし、レビュープロンプトとして抽出しました。chunk initとchunk skill installは、コミットゲートとオンデマンドレビュースキルを Claude Code に組み込み、チェックが自動的に実行されるようにしました。chunk taskは体系的な修正を CircleCI パイプラインに引き渡し、変更を検証して PR を作成しました。
Chunk CLI は品質チェックを「エージェントが覚えていることをチームが期待するもの」から「毎回必ず実行されるもの」に変えます。
アクティブなレビュー履歴を持つリポジトリに対して build-prompt を実行し、出力を読んでみてください。生成されたプロンプトはチームのレビュアーが実際に重視していることのスナップショットであり、それらのパターンがいかに一貫しているかに驚くことが多いでしょう。その後、chunk init は数秒で完了し、コミットゲートは最初のセッションからすぐに効果を発揮します。
Chunk を試すには、無料の CircleCI アカウントに登録してください。Chunk CLI リポジトリ、フックガイド、セットアップドキュメントがその後の手順をすべてカバーしています。