Claude Code Remote Control で /goal を外部制御 — GitHub Actions / curl / API統合パターン

Claude Code を CI/CDパイプラインから自動実行 すれば、デプロイ前検証・自動レビュー・夜間バッチ等をAIに任せられる。
この記事では claude -p の Headless mode を中心に、GitHub Actions・curl・JavaScript・Python の 実装パターンを完全形 で示す。
Headless mode とは
Headless mode は、対話UIなしでClaude Codeを1回限りで実行するモードだ。 CI/CDジョブ内・cron・別アプリからの呼び出しに使う。
# 基本形
claude -p "<プロンプト or /goal文>"
# /goal を非対話で実行
claude -p "/goal test/auth 全件通過, or stop after 10 turns"
# 認証はAPI Keyまたは保存済みOAuthトークン
ANTHROPIC_API_KEY=sk-... claude -p "/goal ..."
完了すると exit code(0=成功、非0=失敗) を返してプロセス終了。ジョブのpass/fail判定に直接使える。
パターン1: GitHub Actions 統合
CIでテストカバレッジが80%未満になったらAIに自動で改善させる例。
.github/workflows/auto-improve-coverage.yml
name: Auto Improve Test Coverage
on:
pull_request:
branches: [main]
jobs:
check-and-improve:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run coverage
id: coverage
run: |
npm test -- --coverage
COVERAGE=$(jq '.total.lines.pct' coverage/coverage-summary.json)
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
- name: Install Claude Code
if: ${{ steps.coverage.outputs.coverage < 80 }}
run: npm install -g @anthropic-ai/claude-code
- name: Auto improve via /goal
if: ${{ steps.coverage.outputs.coverage < 80 }}
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
claude -p "/goal カバレッジ80%未満のモジュールにテストを追加し、
全体のtotal.lines.pctが80以上になる状態, or stop after 15 turns"
- name: Commit changes
if: ${{ steps.coverage.outputs.coverage < 80 }}
run: |
git config user.name "claude-bot"
git config user.email "[email protected]"
git add .
git commit -m "test: auto-improved coverage via /goal" || echo "no changes"
git push
特徴:
- PR作成時にカバレッジ80%未満なら自動で改善PR
- Anthropic API Key は GitHub Secrets で管理
- ターン上限15で暴走防止
- 変更がなければ commit をスキップ
パターン2: curl から呼び出す
シェルスクリプトや別言語からの呼び出し。SSH先のサーバーで定期実行する想定。
#!/bin/bash
# scripts/nightly-report.sh — 毎晩02:00に cron で実行
export ANTHROPIC_API_KEY="$(cat ~/.config/claude/api-key)"
claude -p "/goal 前日のGitHub PR一覧を取得し、
レビュー観点別にカテゴリ分けして report-$(date +%Y-%m-%d).md に出力, or stop after 10 turns" \
--permission-mode auto \
--verbose 2>&1 | tee logs/nightly-$(date +%Y-%m-%d).log
EXIT_CODE=${PIPESTATUS[0]}
if [ $EXIT_CODE -eq 0 ]; then
curl -X POST -H 'Content-Type: application/json' \
-d "{\"text\":\"夜間 /goal 完了: $(date +%Y-%m-%d)\"}" \
"$SLACK_WEBHOOK_URL"
else
curl -X POST -H 'Content-Type: application/json' \
-d "{\"text\":\"夜間 /goal 失敗 (exit $EXIT_CODE): $(date +%Y-%m-%d)\"}" \
"$SLACK_WEBHOOK_URL"
fi
cron設定:
0 2 * * * /home/user/scripts/nightly-report.sh
パターン3: JavaScript(Node.js)から呼び出す
Webアプリのバックエンドから /goal を起動するパターン。Express ルートからジョブをキック。
// src/routes/trigger-goal.js
import { spawn } from 'node:child_process'
import express from 'express'
const router = express.Router()
router.post('/api/trigger-goal', async (req, res) => {
const { goalCondition, maxTurns = 10 } = req.body
// セキュリティ: ホワイトリスト形式で許可済みゴールのみ受け付け
const allowedGoals = ['daily-report', 'weekly-summary', 'health-check']
if (!allowedGoals.includes(req.body.goalKey)) {
return res.status(400).json({ error: 'goalKey not allowed' })
}
const child = spawn('claude', [
'-p',
`/goal ${goalCondition}, or stop after ${maxTurns} turns`,
'--permission-mode', 'auto',
], {
env: { ...process.env, ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
detached: true,
})
child.unref() // バックグラウンド実行
return res.json({
status: 'started',
pid: child.pid,
goalKey: req.body.goalKey,
})
})
export default router
重要なセキュリティポイント:
- 任意プロンプトを受け付けない(コマンドインジェクション防止)
- ホワイトリスト形式で許可済みゴールのみ
- 環境変数
ANTHROPIC_API_KEYを子プロセスに引き継ぐ
パターン4: Python から呼び出す
データ分析パイプラインから呼び出すパターン。Airflow や Prefect のタスクとして組み込める。
# tasks/run_goal.py
import subprocess
import os
import sys
from datetime import datetime
def run_goal(condition: str, max_turns: int = 10, timeout_sec: int = 1800) -> dict:
"""
Claude Code /goal を非対話で実行。
timeout_sec: タイムアウト(秒)、デフォルト30分
"""
env = os.environ.copy()
if 'ANTHROPIC_API_KEY' not in env:
raise EnvironmentError('ANTHROPIC_API_KEY not set')
start = datetime.now()
result = subprocess.run(
[
'claude', '-p',
f'/goal {condition}, or stop after {max_turns} turns',
'--permission-mode', 'auto',
],
env=env,
capture_output=True,
text=True,
timeout=timeout_sec,
)
duration = (datetime.now() - start).total_seconds()
return {
'exit_code': result.returncode,
'stdout': result.stdout,
'stderr': result.stderr,
'duration_sec': duration,
'success': result.returncode == 0,
}
if __name__ == '__main__':
res = run_goal(
condition='reports/daily-sales-$(date +%Y%m%d).md が生成された状態',
max_turns=8,
)
print(f'Success: {res["success"]}, duration: {res["duration_sec"]:.1f}s')
sys.exit(0 if res['success'] else 1)
並列ジョブと rate limit
複数 /goal を同時実行する場合、Anthropic APIのレート制限に注意する。
- 個人プラン: 50リクエスト/分が目安
- Pro/Enterprise: 上限緩和あり(要確認)
GitHub Actions の matrix strategy 例:
strategy:
matrix:
target: [auth, billing, dashboard, settings]
max-parallel: 3 # 並列度を3に制限
Kanau Tech™ の運用では max-parallel: 3 を推奨。それ以上だと評価器のrate limitで 429 Too Many Requests を踏む。
認証の選び方
| 認証方式 | 用途 | 設定 |
|---|---|---|
| ANTHROPIC_API_KEY | CI/CD、サーバー実行 | GitHub Secrets / .env |
| ChatGPT OAuth | ローカル開発 | claude login chatgpt |
| 保存済みOAuthトークン | 本番デーモン実行 | ~/.claude/auth.json |
CI/CDではAPI Key、ローカル開発ではChatGPT OAuthが標準パターン。
CI/CD統合のセキュリティ注意点
| 注意点 | 対処 |
|---|---|
| API Key の漏洩 | GitHub Secrets / Vault で管理、ログに出力しない |
| 任意プロンプトの注入 | ホワイトリスト or 厳格バリデーション |
| 本番DBへの書き込み | CI/CD環境では本番接続文字列を渡さない |
| コスト爆発 | --timeout と max_turns 必須、月予算アラート設定 |
| 並列暴走 | max-parallel 制限、Rate Limit監視 |
よくある質問
Headless mode とは何ですか?
対話画面を出さずに、コマンドラインから1回限りの実行を行うモードだ。claude -p "<プロンプト>" で起動でき、CI/CDジョブ内や定期バッチから呼び出せる。実行が完了するとexit codeを返して終了する。
GitHub Actions のシークレットはどう設定する?
Repository Settings → Secrets and variables → Actions で、ANTHROPIC_API_KEY または CLAUDE_AUTH_TOKEN を登録する。ジョブ内で env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} で参照する。
結果を後続ジョブに渡せますか?
可能だ。/goal 完了時にファイル(例: result.json)に出力させ、後続ジョブで読み取る。GitHub Actionsの upload-artifact でアーティファクト経由、または outputs でジョブ間変数として渡せる。
Webhook で通知できますか?
可能だ。/goal の done when に「Slack Webhook URL に POST して通知」を含めるか、CI/CD側で完了時にSlack/Discord通知を実装する。Webhook URLはシークレット管理してほしい。
並列ジョブは可能ですか?
可能だ。GitHub Actionsのmatrix strategyで複数 /goal を並列実行できる。ただしAnthropic APIのレート制限(個人プラン50リクエスト/分など)を超えないよう注意。Kanau Tech™の運用では max-parallel: 3 を推奨している。
関連記事
- Claude Code /goal 完全ガイド — シリーズPillar
- Claude Code /goal 実務事例集 — テスト・デプロイ監視・リファクタリング — CI/CD適用例
- Claude Code Workspace・Hooks・信頼ダイアログ設定 — 環境設定の前提
