はじめに
この記事では、GitHubのIssueに実装内容と@claudeを書くだけで、AIコーディングツール「Claude Code」が自動でブランチを切り、実装し、PRまで作ってくれる仕組みを、実際に構築した手順に沿って初心者向けに解説します。
結論:GitHub ActionsとClaude Codeを組み合わせれば実現できる
先に結論です。この仕組みは以下の3つの要素の組み合わせで作れます。
- GitHub Actions: 「Issueが作られたら」等のイベントをきっかけに処理を自動実行するGitHubの自動化機能。
- Claude Code CLI: プロンプトを渡すとコードの読み書き・実行を自律的にこなすAIコーディングツール。
- 安全網(guard.mjs): CI環境では確認プロンプトなしで自律実行させるため、危険な操作を機械的にブロックするスクリプトを必ずセットで用意します。
この3つで、Issueを起点に「実装 → コミット → PR作成」までが自動化されます。ただしPRが作られるところまでが終着点で、マージするかどうかの判断は必ず人間が行います。
補足: Anthropic公式もこの仕組みを提供するGitHub Action(
anthropics/claude-code-action)を配布しており、/install-github-appで数分でセットアップできます。最短で試したい方はそちらを。本記事は内部の仕組みと独自の安全網を組み込む方法を、あえて1から解説します。
全体の流れを図にすると次のようになります。
ステップ1:APIキーを発行し、GitHub Secretsに登録する
Claude Codeを動かすには、Anthropic社のAPIキーが必要です。管理画面「Claude Console」(platform.claude.com)のAccount Settings → API Keysから発行します。利用料金は実際の使用量に基づく従量課金です(公式料金ページ)。
発行したキーは、対象のGitHubリポジトリの Settings → Secrets and variables → Actions から登録します。
| Secret名 | 用途 |
|---|---|
ANTHROPIC_API_KEY |
Claude Codeの認証用。手動で登録が必要 |
GITHUB_TOKEN |
ワークフロー実行ごとにGitHubが自動生成(公式)、登録不要 |
ステップ2:ワークフローファイルを作る
.github/workflows/auto-implement.yml を作成します。ポイントは3つです。
-
issue_commentはPRへのコメントでも発生する(公式)ためpull_requestの有無で除外 - 個人リポジトリでは
GITHUB_TOKENのデフォルトが読み取り専用(公式)なのでpermissionsを明示 - 再実行時は同じブランチ・PRを引き継ぐ
name: Claude Code Auto Implement
on:
issues:
types: [opened]
issue_comment:
types: [created]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
auto-implement:
if: |
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude')) ||
(github.event_name == 'issue_comment' && !github.event.issue.pull_request && contains(github.event.comment.body, '@claude'))
runs-on: ubuntu-latest
env:
BRANCH: feature/issue-${{ github.event.issue.number }}
PROMPT: ${{ github.event.comment.body || github.event.issue.body }}
steps:
- uses: actions/checkout@v4
- name: ブランチ準備
# 宛先を明示してfetchすることで、リポジトリ側のfetch設定に依存せず確実にトラッキング参照を作る
run: |
git fetch origin "$BRANCH:refs/remotes/origin/$BRANCH" 2>/dev/null || true
git checkout -B "$BRANCH" "origin/$BRANCH" 2>/dev/null || git checkout -B "$BRANCH"
- name: Claude Codeを実行
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
npm install -g @anthropic-ai/claude-code
claude --print --dangerously-skip-permissions "$PROMPT"
- name: コミット & push
run: |
git config user.email "claude-bot@users.noreply.github.com"
git config user.name "claude-bot"
git add -A
git commit -m "Auto: Issue #${{ github.event.issue.number }}" || echo "No changes"
git push -u origin "$BRANCH"
- name: PRがなければ作成
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr view "$BRANCH" >/dev/null 2>&1 || \
gh pr create --title "Auto: Issue #${{ github.event.issue.number }}" \
--body "Closes #${{ github.event.issue.number }}" --head "$BRANCH"
--print(-p)は結果を出力して終了するフラグ、--dangerously-skip-permissions はその名の通り確認を全て無効化するフラグです(公式)。CIでは必要ですが単体使用は危険なため、次のステップで安全網を用意します。
ステップ3:安全網(guard.mjs)を用意する
唯一の安全網として、危険な操作を機械的に拒否するスクリプトを用意します。Claude CodeのPreToolUseフックはツール実行直前にJSONを標準入力で受け取り、終了コード2を返すと拒否できます(公式)。
#!/usr/bin/env node
// .claude/hooks/guard.mjs
import { readFileSync } from "node:fs";
const input = JSON.parse(readFileSync(0, "utf-8"));
const command = input.tool_input?.command ?? "";
const DENY_RULES = [
[/\bDROP\s+(TABLE|DATABASE)\b/i, "DB破壊コマンド"],
[/\bDELETE\s+FROM\s+\S+\s*;?\s*$/i, "WHERE無しDELETE"],
[/rm\s+-rf\s+(\/|~|\*)/, "危険なrm -rf"],
[/push\s+(--force|-f)\b/, "push --force"],
[/reset\s+--hard\b/, "reset --hard"],
[/\.env\b/, ".env読み書き"],
];
for (const [pattern, reason] of DENY_RULES) {
if (pattern.test(command)) {
console.error(`[guard.mjs] blocked: ${reason}`);
process.exit(2);
}
}
process.exit(0);
.claude/settings.jsonのhooks.PreToolUseに登録します。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guard.mjs" }
]
}
]
}
}
このdenylist方式(危険パターンを列挙して拒否)は、列挙漏れを防げない限界があります。全操作を許可制にするallowlistの方が網羅的ですが、Issue対応は内容が予測しにくいため、まず既知の危険操作から潰すのが現実的です。
注意点:
guard.mjsとsettings.json自体がリポジトリにコミットされていないと機能しません。新しいリポジトリに導入するたびに、この2つも必ずセットで複製してください。
ステップ4:Issueテンプレートを整えて動作確認する
(任意)Issueテンプレートを整える
Issueを毎回一から書くと、実装内容の書き漏らしや@claudeの消し忘れが起きがちです。
.github/ISSUE_TEMPLATE/auto-implement.ymlとして次のように配置すると、リポジトリのIssuesタブで「New issue」を押した際にテンプレート選択画面が表示され、これを選ぶとフォームが開きます。
name: 自動実装タスク
description: Claude Codeに実装させるタスク。本文に@claudeを含めてIssueを作成するとauto-implement.ymlが発火する
body:
- type: textarea
id: summary
attributes:
label: 概要
description: 何を作るか・なぜ必要かを1〜3文で。先頭の@claudeは発火トリガーなので消さないこと
value: |
@claude
(ここに実装内容を書く。例: トップページに共通ヘッダー(ロゴ+ナビゲーション)を追加してください)
validations:
required: true
- type: textarea
id: acceptance
attributes:
label: 受け入れ条件
description: 「何ができたら完了か」を検証可能な形で列挙する
value: |
- [ ] 既存のテスト・Lintが通ること
validations:
required: true
- type: textarea
id: constraints
attributes:
label: 制約
description: 触ってはいけない場所・やってはいけないこと
value: |
- `.env` / `.github/` は変更しないこと
- 依存パッケージを追加しないこと
validations:
required: true
valueに@claudeを埋め込んでいるため、テンプレートから作成するだけで自動的にトリガー条件を満たします。
validations.required: trueはその項目が空欄のままでは投稿できないようにする設定です。
実際に動かして確認する
Issueを新規作成し、本文に実装してほしい内容と @claude を書き込みます(テンプレートを使う場合は各項目を埋めるだけです)。
Actionsタブでワークフローが起動し、数分待つとブランチとPRが自動作成されます。追記コメントでの再実行時は、ステップ2で宛先を明示したfetchによりトラッキング参照が確実に作られるため、同じブランチ・PRに追記されます。
ステップ5(任意):ブランチ保護を設定する
guard.mjsに加え、リポジトリの Settings → Branches でmainに「マージ前にPRを必須とする」ルールを設定すると、コード上とGitHub側の二重の安全網になります。


