dg について
dgは、GilfoyleとDineshの2つのエージェントが対立形式で問題を探り、評価するコードレビュー用スキルです。git diffまたは指定ファイルを確認し、実行可能な要約と軽妙なやり取りをまとめます。
主な機能
- 01ステージ済み・未ステージの差分をレビュー
- 02指定ファイルやディレクトリをレビュー
- 032エージェントによる複数ラウンドの対立レビュー
- 04依存関係の脆弱性情報を考慮
- 05構造化レビューと任意のコミック生成
活用シーン
- 01コミット前の変更にある問題の発見
- 02指定したソースファイルやディレクトリのレビュー
- 03コードレビューでの依存リスク評価
- 04レビュー中のやり取りをコミック化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ v1r3n/ dinesh-gilfoyle --skill dgインストール後、Claude Code で/dgを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
comic-template.htmldinesh-agent.mdgilfoyle-agent.md詳細
Dinesh 対 Gilfoyle のコードレビュー
HBO の『Silicon Valley』に着想を得た、2 人のエージェントによる対抗形式のコードレビューです。Gilfoyle は容赦ない技術的な正確さでコードを批判します。Dinesh は動揺しながらも有能に反論します。掛け合いは楽しめるだけでなく、やり取りを重ねることで、実際により良いレビューが生まれます。
実行方法
/dg— git diff(ステージ済み + 未ステージ)をレビュー/dg 3— git diff を最大 3 ラウンドレビュー/dg src/auth.ts— 指定したファイルをレビュー/dg src/auth.ts 3— 指定したファイルを最大 3 ラウンドレビュー
引数の解析
- 引数なし → 対象 = git diff、上限 = 5
- 数字のみ → 対象 = git diff、上限 = その数字
- パスのみ → 対象 = そのパス、上限 = 5
- パス + 数字 → 対象 = そのパス、上限 = その数字
オーケストレーション
ステップ 1:コードを収集する
git diff の場合:
git diff HEAD
git diff --staged
両方の差分を結合します。両方とも空の場合は、レビュー対象がないことをユーザーに伝えます。
ファイル/パスの場合: 対象のファイルを読み込みます。パスがディレクトリの場合は、その中にあるすべてのソースファイルを読み込みます。
常に実行:依存関係のコンテキストを収集します。 プロジェクトのルートディレクトリにある依存関係ファイルを探し、エージェントに渡すコンテキストに含めます。
package.json、package-lock.json、yarn.lock、pnpm-lock.yaml(Node.js)requirements.txt、pyproject.toml、Pipfile.lock(Python)go.mod、go.sum(Go)pom.xml、build.gradle(Java)Gemfile、Gemfile.lock(Ruby)Cargo.toml、Cargo.lock(Rust)composer.json、composer.lock(PHP)
これらは、Gilfoyle が依存関係の脆弱性をスキャンするために必要です。
ステップ 2:討論を実行する
初期化:round = 0、debate_history = []
digraph debate {
"Gather code" [shape=box];
"Dispatch Gilfoyle" [shape=box];
"New issues found?" [shape=diamond];
"Dispatch Dinesh" [shape=box];
"All conceded, no pushback?" [shape=diamond];
"Round >= cap?" [shape=diamond];
"Ask user: continue?" [shape=diamond];
"Synthesize final review" [shape=doublecircle];
"Gather code" -> "Dispatch Gilfoyle";
"Dispatch Gilfoyle" -> "New issues found?";
"New issues found?" -> "Synthesize final review" [label="no — converged"];
"New issues found?" -> "Dispatch Dinesh" [label="yes"];
"Dispatch Dinesh" -> "All conceded, no pushback?";
"All conceded, no pushback?" -> "Synthesize final review" [label="yes — converged"];
"All conceded, no pushback?" -> "Round >= cap?";
"Round >= cap?" -> "Dispatch Gilfoyle" [label="no — next round"];
"Round >= cap?" -> "Ask user: continue?" [label="yes"];
"Ask user: continue?" -> "Dispatch Gilfoyle" [label="yes — extend cap"];
"Ask user: continue?" -> "Synthesize final review" [label="no"];
}
各ラウンドで:
-
Gilfoyle エージェントを呼び出す(Agent ツール、汎用)際に、以下を渡します。
- このスキルのディレクトリにある
gilfoyle-agent.mdの全内容 - レビュー対象のコード
- 討論履歴全体
- ラウンド番号
- 指示:「調査のみを行ってください。コードを読んでレビューを作成してください。ファイルは編集しないでください。」
- このスキルのディレクトリにある
-
Gilfoyle の掛け合いをユーザーに表示します。
-
収束を確認します: Gilfoyle の FINDINGS セクションを解析します。すべての指摘が前のラウンドの繰り返しであれば、収束したと判断します。
-
Dinesh エージェントを呼び出す(Agent ツール、汎用)際に、以下を渡します。
- このスキルのディレクトリにある
dinesh-agent.mdの全内容 - レビュー対象のコード
- Gilfoyle の直近の完全な応答
- 討論履歴全体
- ラウンド番号
- 指示:「調査のみを行ってください。コードを読んで反論を作成してください。ファイルは編集しないでください。」
- このスキルのディレクトリにある
-
Dinesh の掛け合いをユーザーに表示します。
-
収束を確認します: Dinesh の FINDINGS セクションを解析します。すべての指摘が
[concede]で、[defend]または[dismiss]が 1 つもなければ、収束したと判断します。 -
両者の応答を
debate_historyに追加し、ラウンドを 1 増やします。 -
ラウンド数が上限以上の場合: ユーザーに質問します。「この 2 人はいつまでも続けそうです。さらにラウンドを重ねますか?(y/N)」
- はい → 元の上限分だけ上限を延長し、ループを続けます
- いいえ → 総括に進みます
収束時のメッセージ(状況に合うものを選択):
- 「Gilfoyle の批判材料が尽きたようです。前例のないことです。」
- 「Dinesh が敗北を認めました。予想どおりです。」
- 「この 2 人は同じ話を繰り返しています。手が出る前に引き離しましょう。」
ステップ 3:最終レビューを総括する
討論の終了後、討論記録全体から構造化された要約を作成します。
表示形式:
## Dinesh vs Gilfoyle Review — [target]
### [N] rounds of mass destruction
---
### Best of the Banter
[2-4 of the funniest or most insightful exchanges from the debate]
---
### Verdict
#### Critical (Gilfoyle won, Dinesh conceded)
[Issues where Dinesh couldn't mount a defense — these are real and need fixing]
- `file:line` — issue — fix
#### Important (Gilfoyle won after debate)
[Issues Dinesh tried to defend but Gilfoyle's argument was stronger]
- `file:line` — issue — fix
#### Contested (Dinesh held his ground)
[Issues where Dinesh's defense was valid — code is likely fine]
- `file:line` — what was raised — why the defense holds
#### Dismissed (Gilfoyle was nitpicking)
[Issues both sides agree don't matter]
- `file:line` — what was raised — why it's a non-issue
### Strengths
[Things even Gilfoyle grudgingly acknowledged were good]
### Score
Gilfoyle: X | Dinesh: Y
[Tongue-in-cheek tally of who won more arguments]
### Recommended Changes
[Clean checklist — no banter, no context, just what to do]
- [ ] `file:line` — what to change
- [ ] `file:line` — what to change
- [ ] ...
If no changes needed: "Nothing to fix. Gilfoyle is furious."
ステップ 4:コミックストリップを提案する
最終レビューを表示した後、ユーザーに尋ねます。
「ベストなやり取りをコミックストリップにしますか?(y/N/pr)」
- y — 生成してブラウザーで開く
- pr — 生成して PNG に変換し、現在の PR にコメントとして添付する
- N — スキップする
y または pr の場合は、HTML コミックストリップを生成します。
- このスキルのディレクトリにある
comic-template.htmlからコミックのテンプレートを読み込みます。 - テンプレートのプレースホルダーを埋めます。
{{REVIEW_TARGET}}— レビュー対象(例:「UI Codebase」、「git diff」、ファイルパス){{ROUND_COUNT}}— 議論のラウンド数{{GILFOYLE_SCORE}}/{{DINESH_SCORE}}— 最終スコア{{DATE}}— 現在の日付{{PANELS}}— ベストな掛け合いからコミックのパネルを 4~8 個生成します。各パネルには次の HTML 構造を使用します。
<div class="panel gilfoyle">
<span class="panel-number">1</span>
<div class="panel-header">
<div class="avatar"><svg><use href="#gilfoyle-avatar"/></svg></div>
GILFOYLE
</div>
<div class="panel-body">
<div class="speech">The quote goes here. Use <code>inline code</code> for technical references.</div>
</div>
</div>
<div class="panel dinesh">
<span class="panel-number">2</span>
<div class="panel-header">
<div class="avatar"><svg><use href="#dinesh-avatar"/></svg></div>
DINESH
</div>
<div class="panel-body">
<div class="speech">The response goes here.</div>
</div>
</div>
<div class="panel gilfoyle full-width">
<span class="panel-number">3</span>
<div class="panel-header">
<div class="avatar"><svg><use href="#gilfoyle-avatar"/></svg></div>
GILFOYLE
</div>
<div class="panel-body">
<div class="speech">A particularly devastating line that deserves the full width.</div>
</div>
</div>
{{VERDICT_ITEMS}}— 最終レビューから判定項目を生成します。
<div class="verdict-item">
<span class="tag tag-fixed">FIXED</span> CSP nonce replaced with deploy-time placeholder
</div>
<div class="verdict-item">
<span class="tag tag-contested">CONTESTED</span> MutationObserver lifetime — Dinesh held ground
</div>
<div class="verdict-item">
<span class="tag tag-dismissed">DISMISSED</span> prop-types — tree-shakes out
</div>
-
パネルに使うベストな場面を選びます。 次の点を優先します。
- 最もおもしろいやり取り(応酬のある掛け合いが最適です)
- ギルフォイルが譲歩した場面(めったにない、劇的な場面)
- ディネシュの最高の切り返し
- 技術的に最も痛烈な指摘
- 引用は簡潔にします。吹き出しごとに 1~3 文にまとめます。
-
埋めた HTML をタイムスタンプ付きのファイルに書き込みます。
/tmp/dg-comic-{timestamp}.html
y の場合:
5. ブラウザーで開きます。open /tmp/dg-comic-{timestamp}.html
6. ファイルの保存先をユーザーに伝えます。
pr の場合:
5. ヘッドレスブラウザーを使って PNG に変換します。
# Try puppeteer/chromium first, fall back to wkhtmltoimage, then to Safari
npx --yes puppeteer-screenshot /tmp/dg-comic-{timestamp}.html /tmp/dg-comic-{timestamp}.png 2>/dev/null \
|| wkhtmltoimage --quality 90 /tmp/dg-comic-{timestamp}.html /tmp/dg-comic-{timestamp}.png 2>/dev/null \
|| /usr/bin/osascript -e 'tell application "Safari" to open POSIX file "/tmp/dg-comic-{timestamp}.html"'
スクリーンショットツールが利用できない場合は、ブラウザーから手動でスクリーンショットを撮るようユーザーに伝えます。 6. 現在の PR を検出します。
gh pr view --json number,url --jq '.number'
- 画像をアップロードし、PR にコメントします。
注:gh pr comment {PR_NUMBER} --body "$(cat <<'EOF' ## /dg Review Comic Strip  _Generated by [/dg](https://github.com/v1r3n/dinesh-gilfoyle)_ EOF )"gh pr commentがローカル画像のアップロードに対応していない場合は、PR の本文に画像をドラッグ&ドロップする方法を提案するか、base64 に変換して埋め込みます。 - PR へのリンクを添えて、コメントを投稿したことをユーザーに伝えます。
重要な原則
- 掛け合いは飾りではなく、機能です — レビューを楽しく、かつ徹底したものにします
- ディネシュの譲歩は最も強いシグナルです — 反論できない場合は、実際に問題があります
- 反論が成功すればコードの妥当性が裏付けられます — ギルフォイルの追及に対してディネシュが正当化できるなら、そのコードは堅実です
- 最後は必ず実行可能な要約で締めくくります — 外側は楽しく、内側は役に立つ内容にします
- 技術的な正確さを保ちます — 技術的な中身が本物であってこそ、ユーモアが機能します