greploop について
Greploopは、PR、MR、またはPerforce changelistに対するGreptileのレビュー指摘を、最大5回の反復で解消するスキルです。プラットフォームを判定し、レビュー結果の取得、対応可能な指摘の修正、最終状況の報告を行います。
主な機能
- 01GitHub、GitLab、Perforceの判定
- 02レビュー対象の変更の特定
- 03Greptileレビューの実行と確認
- 04対応可能なレビュー指摘の修正
- 05対応済みディスカッションの解決
- 06信頼度と未解決指摘の報告
活用シーン
- 01GitHub PRのレビュー指摘への対応
- 02GitLab MRのGreptile指摘への対応
- 03Perforce changelistレビューの反復
- 04未解決指摘とレビュー信頼度の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ greptileai/ skills --skill greploopインストール後、Claude Code で/greploopを入力して読み込まれたか確認します。
同梱ファイルreferences/gitlab-api.mdreferences/graphql-queries.md
詳細
Greploop
Greptile のレビューで完璧な評価(信頼度 5/5、未解決コメントゼロ)が得られるまで、PR/MR/CL を繰り返し修正します。
入力
- PR/MR/CL 番号(任意):指定されていない場合は、現在のブランチの PR/MR、または p4 のデフォルトの保留中チェンジリストを検出します。
手順
0. プラットフォームを検出する
まず Perforce を確認し、該当しない場合は git のリモート検出に切り替えます。
# Check for Perforce environment
if p4 info >/dev/null 2>&1; then
VCS="perforce"
else
REMOTE_URL=$(git remote get-url origin)
if echo "$REMOTE_URL" | grep -qi "gitlab"; then
VCS="gitlab"
else
VCS="github"
fi
fi
ホスト名に「gitlab」が含まれないセルフホスト型 GitLab インスタンスの場合、ユーザーは入力として --vcs gitlab を渡して上書きできます。Perforce の場合は、--vcs perforce を渡します。
1. PR/MR/CL を特定する
GitHub:
gh pr view --json number,headRefName -q '{number: .number, branch: .headRefName}'
GitLab:
glab mr view --output json | jq '{iid: .iid, branch: .source_branch}'
まだ PR/MR のブランチに切り替わっていない場合は、切り替えます。
Perforce:
# List pending changelists for current user/client
p4 changes -s pending -u $P4USER -c $P4CLIENT
# Describe a specific CL
p4 describe -s <CL_NUMBER>
続行する前に、正しいワークスペース(p4 client)が設定されていることを確認します。
主なフィールドの違い:
- GitHub:
number、headRefName、headRefOid - GitLab:
iid、source_branch、sha - Perforce:チェンジリスト番号、
P4CLIENT、シェルフ上のファイル
2. ループ
次のサイクルを繰り返します。暴走するループを避けるため、最大 5 回までとします。
A. Greptile のレビューを開始する
最新の変更があれば、プッシュまたはシェルブします。
GitHub/GitLab:
git push
Perforce:
# Re-shelve to update the shelved files for review
p4 shelve -f -c <CL_NUMBER>
プッシュまたはシェルブの後、チェックが開始されるまで待ちます。
sleep 5
GitHub — 新しいトリガーコメントを投稿する前に、Greptile がすでに実行中かどうかを確認します。
GREPTILE_STATE=$(gh pr checks <PR_NUMBER> --json name,state | jq -r '.[] | select(.name | test("greptile"; "i")) | .state')
Greptile がすでに実行中(PENDING または IN_PROGRESS)でない場合は、新しいレビューをリクエストします。
if [ "$GREPTILE_STATE" != "PENDING" ] && [ "$GREPTILE_STATE" != "IN_PROGRESS" ]; then
gh pr comment <PR_NUMBER> --body "@greptile review"
fi
次に、Greptile のチェック実行が完了するまでポーリングします。
HEAD_SHA=$(gh pr view <PR_NUMBER> --json headRefOid -q .headRefOid)
ATTEMPTS=0
MAX_ATTEMPTS=60
POLL_INTERVAL_SECONDS=10
while true; do
ATTEMPTS=$((ATTEMPTS + 1))
if [ "$ATTEMPTS" -gt "$MAX_ATTEMPTS" ]; then
echo "Timed out waiting for the Greptile check run after approximately 10 minutes." >&2
exit 1
fi
GREPTILE_CHECK=$(gh api "repos/{owner}/{repo}/commits/$HEAD_SHA/check-runs" \
--jq '.check_runs[] | select(.name | test("greptile"; "i"))' 2>/dev/null)
if [ -z "$GREPTILE_CHECK" ]; then
echo "Waiting for Greptile check to appear..."
sleep "$POLL_INTERVAL_SECONDS"
continue
fi
STATUS=$(echo "$GREPTILE_CHECK" | jq -r '.status // "completed"')
CONCLUSION=$(echo "$GREPTILE_CHECK" | jq -r '.conclusion // "pending"')
if [ "$STATUS" = "completed" ]; then
if [ "$CONCLUSION" = "success" ]; then
echo "Greptile check passed!"
else
echo "Greptile check completed with: $CONCLUSION"
fi
break
fi
echo "Waiting for Greptile... (status: $STATUS)"
sleep "$POLL_INTERVAL_SECONDS"
done
ポーリングがタイムアウトした場合は、greploop ワークフローを停止し、タイムアウトしたことを報告します。古いレビュー結果やレビュー結果がない状態で続行しないでください。
GitLab — トリガーコメントを投稿する前に、Greptile がすでに実行中かどうかを確認します。
PIPELINES=$(glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines")
GREPTILE_RUNNING=$(echo "$PIPELINES" | jq '[.[] | select(.status == "running" or .status == "pending")] | length')
実行中のパイプラインがない場合は、トリガーコメントを投稿します。
if [ "$GREPTILE_RUNNING" = "0" ]; then
glab mr note <MR_IID> --message "@greptile review"
fi
Perforce — Perforce にはネイティブのチェック実行機能がありません。p4 shelve で起動する Webhook を介して Greptile が統合されている場合は、処理が完了するまで待ちます。レビューのステータスは、Greptile のインストール環境にある Webhook エンドポイントまたはダッシュボードで確認します。スコアが表示されるまで、CL に関する Greptile のレビューコメントを再取得してポーリングします。
次に、Greptile のパイプラインジョブが完了するまでポーリングします(GitLab API リファレンスを参照)。
HEAD_SHA=$(glab mr view <MR_IID> --output json | jq -r '.sha')
ATTEMPTS=0
MAX_ATTEMPTS=60
POLL_INTERVAL_SECONDS=10
while true; do
ATTEMPTS=$((ATTEMPTS + 1))
if [ "$ATTEMPTS" -gt "$MAX_ATTEMPTS" ]; then
echo "Timed out waiting for the Greptile pipeline job after approximately 10 minutes." >&2
exit 1
fi
PIPELINES=$(glab api "projects/:fullpath/merge_requests/<MR_IID>/pipelines")
# Find the most recent pipeline for this SHA
PIPELINE_ID=$(echo "$PIPELINES" | jq -r --arg sha "$HEAD_SHA" \
'[.[] | select(.sha == $sha)] | sort_by(.id) | last | .id // empty')
if [ -z "$PIPELINE_ID" ]; then
echo "Waiting for Greptile pipeline to appear..."
sleep "$POLL_INTERVAL_SECONDS"
continue
fi
JOBS=$(glab api "projects/:fullpath/pipelines/$PIPELINE_ID/jobs")
GREPTILE_JOB=$(echo "$JOBS" | jq '.[] | select(.name | test("greptile"; "i"))')
if [ -z "$GREPTILE_JOB" ]; then
echo "Waiting for Greptile job to appear..."
sleep "$POLL_INTERVAL_SECONDS"
continue
fi
JOB_STATUS=$(echo "$GREPTILE_JOB" | jq -r '.status')
if [ "$JOB_STATUS" = "success" ] || [ "$JOB_STATUS" = "failed" ] || [ "$JOB_STATUS" = "canceled" ]; then
echo "Greptile job completed with: $JOB_STATUS"
break
fi
echo "Waiting for Greptile... (status: $JOB_STATUS)"
sleep "$POLL_INTERVAL_SECONDS"
done
ポーリングがタイムアウトした場合は、greploop ワークフローを停止し、タイムアウトしたことを報告します。古いレビュー結果やレビュー結果がない状態で続行しないでください。
B. Greptile のレビュー結果を取得する
Greptile は複数の場所にスコアを表示する場合があります。該当するすべての情報源を確認してください。
GitHub:
1. PR の説明(本文):
gh pr view <PR_NUMBER> --json body -q '.body'
2. PR の一般コメント(Issue コメント):
gh api --paginate "repos/{owner}/{repo}/issues/<PR_NUMBER>/comments?per_page=100"
Greptile が投稿したコメントを絞り込み、最も新しく作成されたコメントではなく、最も最近更新されたコメント(updated_at)の本文を使用します。Greptile はレビューサイクルごとに同じ一般的な PR コメントを編集する場合があります。問題が残っていないと判断する前に、「Prompt to fix all with AI」セクションを含む現在の本文を解析してください。
3. PR レビュー:
gh api repos/{owner}/{repo}/pulls/<PR_NUMBER>/reviews
greptile-apps[bot] または greptile-apps-staging[bot] による最新のエントリーを探してください。
GitLab:
1. MR の説明(本文):
glab mr view <MR_IID> --output json | jq -r '.description'
2. MR のノート(コメント):
glab api "projects/:fullpath/merge_requests/<MR_IID>/notes"
Greptile ボットユーザーによるノートを絞り込みます(author.username フィールドを確認してください。正確なユーザー名はインストールごとに異なる場合があるため、初回実行時に確認してください)。
Perforce:
1. CL の説明:
p4 describe -s <CL_NUMBER>
説明フィールドで、Greptile が追加したスコアブロックを確認してください。
2. CL のコメント/レビューのノート: インストール環境で Helix Swarm などのレビューツールを使用している場合は、その API 経由でコメントを取得します。
例(Swarm API): GET /api/v11/comments?topic=reviews/<REVIEW_ID>
通常、注目するレスポンスフィールドは次のとおりです。
- user(投稿者のユーザー名)
- body(コメント本文)
- コメントが解決済みかどうかを示す flags/state
Greptile ボットが投稿したコメントに絞り込みます。
- ユーザー名がわかっている場合は、完全一致を優先します
- それ以外の場合は、投稿者名に「greptile」が含まれるかどうか(大文字と小文字を区別しない)で判定します
すべてのプラットフォームで、次の内容をテキストから解析します。
- 信頼度スコア:
3/5や5/5(またはConfidence: 3/5)のようなパターン。 - コメント数:要約に記載されたインラインレビューコメントの数。
スコアが最も最近更新された情報源を使用してください。GitHub では、編集された Greptile の要約と古いレビューエントリーを比較する際、Issue コメントの updated_at を優先してください。
未解決のインラインコメントもすべて取得します。
GitHub:
gh api repos/{owner}/{repo}/pulls/<PR_NUMBER>/comments
インラインコメントのエンドポイントから未解決のコメントが 0 件返された場合でも、最新の Greptile の一般的な PR コメントから、特に「Prompt to fix all with AI」セクションの対応項目を引き継いでください。
GitLab:
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions"
最新のコミットに紐づき、まだ解決されていない("resolved": false)Greptile の DiffNote 型のディスカッション(notes[0].type == "DiffNote")に絞り込みます。
Perforce: Swarm を使用している場合:
CL に関連付けられたレビューのインライン差分コメントを取得
GET /api/v11/comments?topic=reviews/<REVIEW_ID>
Greptile ボットユーザーによるもので、解決済み/対応済みとマークされていないコメントに絞り込みます。
C. 終了条件を確認する
次のいずれかに該当する場合、ループを停止します。
- 信頼度スコアが 5/5 で、未解決のコメントが 0 件
- 最大反復回数に達した場合(現在の状態を報告)
D. 対応が必要なコメントを修正する
未解決の Greptile コメントごとに、次の手順を実行します。
- ファイルを読み、コメントの文脈を把握します。
- 対応が必要か(コード変更が必要か)、それとも情報提供のみかを判断します。
- 対応が必要な場合は修正します。
- 情報提供のみの場合や誤検出の場合は、その旨を記録したうえでスレッドを解決します。
E. スレッドを解決する
GitHub — 未解決のレビュースレッドを取得し、対応済みのものをすべて解決します(GraphQL リファレンスを参照)。
gh api graphql -f query='
query($cursor: String) {
repository(owner: "OWNER", name: "REPO") {
pullRequest(number: PR_NUMBER) {
reviewThreads(first: 100, after: $cursor) {
pageInfo { hasNextPage endCursor }
nodes {
id
isResolved
comments(first: 1) {
nodes { body path author { login } }
}
}
}
}
}
}'
対応済みのスレッドを解決します。
gh api graphql -f query='
mutation {
t1: resolveReviewThread(input: {threadId: "ID1"}) { thread { isResolved } }
t2: resolveReviewThread(input: {threadId: "ID2"}) { thread { isResolved } }
}'
GitLab — 未解決のディスカッションを取得し、それぞれを解決します(GitLab API リファレンスを参照)。
glab api "projects/:fullpath/merge_requests/<MR_IID>/discussions?per_page=100"
"resolved": false のディスカッションに絞り込みます。その後、それぞれの id を指定して解決します。
glab api --method PUT \
"projects/:fullpath/merge_requests/<MR_IID>/discussions/<DISCUSSION_ID>" \
--field resolved=true
未解決のディスカッション ID ごとに繰り返します。(GitLab には一括解決機能がないため、1 件ずつ処理します。)
F. コミットしてプッシュ/再シェルブする
GitHub/GitLab:
git add -A
git commit -m "address greptile review feedback (greploop iteration N)"
git push
Perforce:
# Stage changes back into the CL and re-shelve for the next review round
p4 shelve -f -c <CL_NUMBER>
プッシュ/シェルブ後、チェックが開始されるまで待ちます。
sleep 5
その後、手順 A に戻ります。
3. レポート
ループの終了後、次の内容を要約します。
| フィールド | 値 |
|---|---|
| プラットフォーム | GitHub / GitLab / Perforce |
| イテレーション数 | N |
| 最終信頼度 | X/5 |
| 解決済みコメント数 | N |
| 未解決コメント数 | N(ある場合) |
最大イテレーション数に達してループが終了した場合は、未解決のコメントを一覧表示し、次のステップを提案します。
出力形式
Greploop complete.
Platform: GitHub
Iterations: 2
Confidence: 5/5
Resolved: 7 comments
Remaining: 0
完全に解決していない場合:
Greploop stopped after 5 iterations.
Platform: GitLab
Confidence: 4/5
Resolved: 12 comments
Remaining: 2
Remaining issues:
- src/auth.ts:45 — "Consider rate limiting this endpoint"
- src/db.ts:112 — "Missing index on user_id column"
Perforce の例:
Greploop complete.
Platform: Perforce
Changelist: 12345
Iterations: 3
Confidence: 5/5
Resolved: 9 comments
Remaining: 0