●WWDC — WWDC 2026 opens Jun 8; the revamped Siri is reported to run on Google Gemini, with Claude among the third-party AI choices●BILLING — From Jun 15, Agent SDK, headless Claude Code, GitHub Actions, and third-party agents move off subscription limits to API-rate monthly credit (1 week left)●FALLBACK — Claude Code adds a fallbackModel setting that tries up to three models in order when the primary is overloaded (Jun)●DENY-GLOB — Deny rules now support glob patterns in the tool-name position, with stronger cross-session message security (Jun)●OPUS4.8 — Claude Opus 4.8 is now the default on Max, Team Premium, Enterprise pay-as-you-go, and the Anthropic API (Jun)●MANAGED-AGENTS — Claude Managed Agents can run in a sandbox you control and connect to your private MCP servers (Jun)●WWDC — WWDC 2026 opens Jun 8; the revamped Siri is reported to run on Google Gemini, with Claude among the third-party AI choices●BILLING — From Jun 15, Agent SDK, headless Claude Code, GitHub Actions, and third-party agents move off subscription limits to API-rate monthly credit (1 week left)●FALLBACK — Claude Code adds a fallbackModel setting that tries up to three models in order when the primary is overloaded (Jun)●DENY-GLOB — Deny rules now support glob patterns in the tool-name position, with stronger cross-session message security (Jun)●OPUS4.8 — Claude Opus 4.8 is now the default on Max, Team Premium, Enterprise pay-as-you-go, and the Anthropic API (Jun)●MANAGED-AGENTS — Claude Managed Agents can run in a sandbox you control and connect to your private MCP servers (Jun)
Claude Code HTTP Hooks × GitHub Actions Integration Guide — Production Patterns for Automated Code Review, Testing, and Deployment
A deep dive into integrating Claude Code HTTP Hooks with GitHub Actions to build production-grade pipelines for automated code review, quality checks, and deployment — with detailed code examples throughout.
Setup and context: How HTTP Hooks Transform Development Workflows
Claude Code's hook system is a powerful mechanism for connecting AI agent behavior to external systems. HTTP Hooks in particular unlock "cloud-native automation" that simply isn't possible with local-process stdio hooks.
Combining GitHub Actions with HTTP Hooks enables workflows like these:
The moment a pull request is opened, Claude Code automatically reviews the code
Every commit triggers security scanning and quality checks in real time
When tests fail, Claude Code analyzes the error log and posts a fix suggestion directly on the PR
After a staging deployment, Claude Code runs regression tests autonomously
This article explains these patterns as production-ready implementations — not toy examples. We assume familiarity with stdio hooks and basic CI/CD, and go deep on HTTP Hooks-specific design considerations and implementation patterns.
Understanding the HTTP Hooks Architecture
How HTTP Hooks Differ from stdio Hooks
Claude Code supports two kinds of hooks:
stdio hooks: Runs as a local process, communicating via stdin/stdout JSON
HTTP hooks: POSTs JSON to a specified URL (Webhook endpoint) and reads the response
While Claude Code Hooks and Automation covers the basics of stdio hooks, HTTP Hooks go a step further by enabling real-time integration with external services.
PreToolUse: Before a tool runs (e.g., before a file write or bash command)
PostToolUse: After a tool runs (trigger follow-up processing on results)
Notification: Notifications from Claude (progress updates on long tasks)
Stop: When Claude ends a session
SubagentStop: When a subagent ends its session
For CI/CD integration, PostToolUse and Stop are the most critical. A practical pattern is: use PostToolUse to detect file changes and run quality checks in real time, then use Stop to finalize a report and post it to GitHub.
Configuring HTTP Hooks via CLAUDE.md
HTTP Hooks are configured in .claude/settings.json or CLAUDE.md.
Environment variable interpolation like ${CLAUDE_HOOK_SECRET} is handled automatically by Claude Code. In local development, define variables in a .env file; in CI, use GitHub Actions Secrets.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦Understand HTTP Hooks architecture and implement bidirectional integration with GitHub Actions
✦Master production-grade pipeline design for automating code review, testing, and deployment with Claude Code
✦Learn how to build a robust Webhook server with security, authentication, and error-retry patterns
Secure payment via Stripe · Cancel anytime
Designing and Implementing the Webhook Server
Production-Grade Webhook Server (Node.js / Hono)
The server that receives Webhooks must be designed with security, reliability, and scalability in mind. Below is an implementation using Hono — a lightweight framework with first-class Cloudflare Workers support.
By including a decision field in your HTTP Hooks response, you directly control what Claude Code does next:
"proceed": Continue as normal (default)
"block": Cancel the tool call and inject the reason into Claude's context
"approve": Auto-approve any confirmation prompt
When "block" is returned, the tool invocation is cancelled and the reason text is injected into Claude's active context. Claude then reads that reason and decides how to handle it. This enables a powerful self-correcting feedback loop where the AI understands quality constraints and fixes its own output iteratively.
GitHub Actions Integration Patterns
Pattern 1: Automatic Code Review on PR Open/Update
This pattern launches Claude Code when a PR is created or updated, then posts the review as a PR comment.
# .github/workflows/claude-code-review.ymlname: Claude Code Reviewon: pull_request: types: [opened, synchronize]jobs: review: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: "22" - name: Install Claude Code run: npm install -g @anthropic-ai/claude-code - name: Get changed files id: changed-files run: | CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | head -20) echo "files<<EOF" >> $GITHUB_OUTPUT echo "$CHANGED" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Run Claude Code review env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} CLAUDE_HOOK_SECRET: ${{ secrets.CLAUDE_HOOK_SECRET }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} run: | CHANGED_FILES="${{ steps.changed-files.outputs.files }}" claude --dangerously-skip-permissions \ --print \ --settings .claude/settings.json \ "Please review the following changed files for bugs, security issues, performance problems, and coding convention violations. Provide specific, actionable feedback for each issue found. Changed files: $CHANGED_FILES After the review, post the results as a GitHub PR comment." \ 2>&1 | tee review-output.txt - name: Post review results if: always() uses: actions/github-script@v7 with: script: | const fs = require('fs'); const output = fs.readFileSync('review-output.txt', 'utf8').slice(-3000); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `## 🤖 Claude Code Automated Review\n\n\`\`\`\n${output}\n\`\`\`` });
Pattern 2: Auto-Fix Suggestions on Test Failures
When CI tests fail, Claude Code analyzes the error log and posts a fix suggestion directly on the PR.
# .github/workflows/claude-auto-fix.ymlname: Claude Code Auto Fixon: workflow_run: workflows: ["Tests"] types: [completed]jobs: auto-fix: if: github.event.workflow_run.conclusion == 'failure' runs-on: ubuntu-latest permissions: contents: read pull-requests: write issues: write steps: - name: Checkout uses: actions/checkout@v4 - name: Download test logs uses: actions/download-artifact@v4 with: name: test-results run-id: ${{ github.event.workflow_run.id }} github-token: ${{ secrets.GITHUB_TOKEN }} - name: Analyze failures with Claude Code env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | TEST_LOG=$(cat test-results.txt 2>/dev/null || echo "Could not retrieve test log") claude --dangerously-skip-permissions \ --print \ "Analyze the following test failure log. 1. Identify the root cause of the failure 2. Explain the fix in concrete terms 3. Provide a code snippet if possible Output your answer in clean markdown suitable for a GitHub PR comment. ===Test Log=== $TEST_LOG ===" \ > fix-suggestion.txt 2>&1 - name: Post fix suggestion uses: actions/github-script@v7 with: script: | const fs = require('fs'); const suggestion = fs.readFileSync('fix-suggestion.txt', 'utf8'); const prs = await github.rest.pulls.list({ owner: context.repo.owner, repo: context.repo.repo, state: 'open', head: context.ref }); if (prs.data.length > 0) { await github.rest.issues.createComment({ issue_number: prs.data[0].number, owner: context.repo.owner, repo: context.repo.repo, body: `## 🔧 Claude Code Test Failure Analysis\n\n${suggestion}` }); }
Pattern 3: Claude Code Determines Semantic Versioning
Claude Code reads the commit history and diff statistics to decide the appropriate semver bump (patch / minor / major).
# .github/workflows/claude-version-bump.ymlname: Claude Code Version Bumpon: push: branches: [main]jobs: version-bump: runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 10 token: ${{ secrets.GITHUB_TOKEN }} - name: Determine version bump env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} run: | COMMITS=$(git log --oneline -10) DIFF=$(git diff HEAD~5..HEAD --stat) BUMP_TYPE=$(claude --dangerously-skip-permissions --print \ "Based on the commits and diff below, determine the semantic version bump. Output EXACTLY ONE of: patch, minor, or major — no other text. Rules: - Breaking changes → major - New features (backward-compatible) → minor - Bug fixes / refactoring → patch Commits: $COMMITS File changes: $DIFF" 2>&1 | tr -d '[:space:]') if [[ "$BUMP_TYPE" != "patch" && "$BUMP_TYPE" != "minor" && "$BUMP_TYPE" != "major" ]]; then BUMP_TYPE="patch" fi echo "BUMP_TYPE=$BUMP_TYPE" >> $GITHUB_ENV echo "Version bump determined: $BUMP_TYPE" - name: Bump version run: | npm version ${{ env.BUMP_TYPE }} --no-git-tag-version git config user.email "bot@example.com" git config user.name "Claude Code Bot" git add package.json package-lock.json git commit -m "chore: bump version [${{ env.BUMP_TYPE }}] via Claude Code" git push
Security Design: What to Lock Down for Production
Authentication and Authorization
Your HTTP Hooks endpoint must be publicly reachable, but allowing anyone to POST to it is dangerous. Use layered defense:
IP Allowlisting: If your CI runs on a known IP range (e.g., GitHub Actions runners), firewall your endpoint accordingly. GitHub publishes its runner IP ranges through the meta API.
In CI, store all secrets in GitHub Actions Secrets (secrets.CLAUDE_HOOK_SECRET) or a managed secrets service like AWS Secrets Manager or GCP Secret Manager.
Advanced Patterns: Designing Claude Code Feedback Loops
Block → Rewrite → Verify Loop
The most powerful HTTP Hooks pattern is a self-correcting loop where Claude Code rewrites code until it passes quality checks autonomously:
[Claude Code writes a file]
↓
[PostToolUse HTTP Hook fires]
↓
[Webhook server runs quality checks]
↓
Issues found → decision: "block" + reason returned
↓
[Claude Code reads reason and revises]
↓
[Writes again → hook fires → checks run...]
↓
No issues → decision: "proceed"
↓
[Claude Code moves to next step]
The key insight is to centralize quality rules in the Webhook server, not in the prompt. Claude learns "what went wrong" from the reason field and handles it autonomously.
HTTP Hooks endpoints need to be fast and highly available. Cloudflare Workers runs at 300+ edge locations worldwide, has near-zero cold start times, and offers 100,000 requests/month free.
wrangler deploywrangler secret put CLAUDE_HOOK_SECRETwrangler secret put GITHUB_TOKEN
Using ngrok for Local Development
To test HTTP Hooks locally during development, expose your local server with ngrok.
# Start local dev servernpm run dev # listening on localhost:8787# Create a public tunnelngrok http 8787# Update .claude/settings.json to point at the ngrok URL# "url": "https://xxxx.ngrok-free.app/hooks/file-changed"
Monitoring, Observability, and Debugging
Structured Logging for Production Webhooks
When HTTP Hooks run in production, you need visibility into what's happening. Structured JSON logging makes it easy to query, alert on, and trace issues across your Webhook server.
With structured logs flowing into a platform like Datadog, Axiom, or Cloudflare Workers Logs, you can build dashboards that answer questions like:
How often does Claude Code trigger a block decision vs. proceed?
Which files or file types generate the most quality issues?
What is the p95 latency of the Webhook server under CI load?
How many iterations does Claude typically need before passing quality checks?
Tracking Hook Invocation Metrics
Instrumenting your Webhook server with lightweight counters gives you a clear picture of overall system health over time.
// Simple metrics using Cloudflare Workers Analytics Engineasync function recordMetric( env: Bindings, event: string, data: Record<string, number | string>) { if (!env.ANALYTICS) return; // Optional binding env.ANALYTICS.writeDataPoint({ blobs: [event, data.decision as string || ""], doubles: [data.duration_ms as number || 0], indexes: [event], });}// In your hook handlerawait recordMetric(env, "hook_invocation", { decision: result.pass ? "proceed" : "block", duration_ms: Date.now() - start,});
Debugging Hook Payloads
During development, it's invaluable to inspect the raw JSON payload Claude Code sends to your endpoint. A simple echo endpoint makes this easy:
// Debug endpoint — never expose in productionapp.post("/debug/echo", async (c) => { if (c.env.NODE_ENV !== "development") { return c.json({ error: "Not available in production" }, 403); } const payload = await c.req.json(); console.log("Hook payload:", JSON.stringify(payload, null, 2)); return c.json({ decision: "proceed", echo: payload });});
Point your .claude/settings.json at this endpoint during local development to inspect exactly what Claude Code sends. You'll notice that the payload structure varies between hook events — PreToolUse includes tool arguments before execution, while PostToolUse includes both the input and the result.
End-to-End Tracing with Session IDs
Every HTTP Hooks payload includes a session_id that uniquely identifies the Claude Code session. Use this as a correlation ID to trace a single Claude Code run across all your external systems.
// Propagate session_id as a trace header to downstream servicesasync function callDownstreamService( url: string, payload: unknown, sessionId: string) { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", "X-Session-Id": sessionId, // Carry session_id through the call chain "X-Request-Id": crypto.randomUUID(), }, body: JSON.stringify(payload), }); return response.json();}
This makes it straightforward to reconstruct the full sequence of events for any Claude Code session — from the first file write to the final session-complete notification — even when those events span multiple services and log streams.
Handling Edge Cases and Failure Modes
Graceful Degradation When the Webhook Server Is Down
If your Webhook server is unreachable, Claude Code will time out waiting for a response. By default this blocks the tool from executing. In many cases, you want CI to continue even if the quality-check server is temporarily unavailable.
One approach is to run a lightweight health-check job at the start of your CI pipeline and skip hook-dependent steps if the server is degraded:
# .github/workflows/claude-code-review.yml (with graceful degradation)jobs: check-webhook-health: runs-on: ubuntu-latest outputs: healthy: ${{ steps.health.outputs.healthy }} steps: - id: health run: | STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ https://your-webhook-server.example.com/health) if [ "$STATUS" = "200" ]; then echo "healthy=true" >> $GITHUB_OUTPUT else echo "healthy=false" >> $GITHUB_OUTPUT echo "⚠️ Webhook server is degraded (status $STATUS). Continuing without hooks." fi review: needs: check-webhook-health if: needs.check-webhook-health.outputs.healthy == 'true' # ... rest of review job
Idempotency and Duplicate Events
CI systems can retry jobs on transient failures, meaning the same hook payload may arrive more than once. Design your Webhook handlers to be idempotent — processing the same payload twice should produce the same result without side effects.
// Use a cache (KV, Redis, or in-memory) to deduplicate based on session_id + tool call indexconst dedupeKey = `${session_id}:${tool_call_index}`;const cached = await env.KV.get(dedupeKey);if (cached) { // Already processed — return the cached decision return c.json(JSON.parse(cached));}const result = await processHook(payload);// Cache with a short TTL (e.g., 5 minutes)await env.KV.put(dedupeKey, JSON.stringify(result), { expirationTtl: 300 });return c.json(result);
Retry Logic for Flaky Downstream Services
Quality checks often call downstream services (linters, type checkers, security scanners) that can occasionally fail. Implement exponential backoff to avoid cascading failures.
Before taking your HTTP Hooks integration to production, run through this checklist. Each item represents a real failure mode encountered in production deployments.
Webhook Server Security
Bearer Token or HMAC signature verification is implemented on every endpoint
All secrets are stored in a managed secrets service (GitHub Actions Secrets, Wrangler Secrets, etc.) — nothing hardcoded
TLS is enforced (HTTPS only); HTTP is rejected
IP allowlisting is in place if your CI runner IPs are static
Health check endpoint (/health) is publicly accessible and returns 200 when healthy
Reliability and Resilience
Hook handlers respond within the configured timeout (default 10 seconds)
Heavy operations (security scans, type checks) complete within the timeout or are made async
Exponential backoff is implemented for calls to flaky downstream services
Handlers are idempotent — processing the same payload twice is safe
Graceful degradation is configured in CI so pipelines continue if the Webhook server is degraded
Observability
Structured JSON logging is in place with session_id as a correlation field
Slow hooks (> 3 seconds) generate alerts
decision: "block" events are tracked and reviewed periodically to tune quality rules
End-to-end traces span from Claude Code through the Webhook server to downstream services
Quality Rule Design
reason strings in block responses are specific and actionable (not vague)
The maximum retry count is explicitly configured to prevent runaway loops
Quality rules are version-controlled alongside the Webhook server code
Rules are tested in a staging environment before rollout to production
CI/CD Integration
GitHub Actions Secrets are scoped to the minimum required repositories
The ANTHROPIC_API_KEY is not shared across unrelated workflows
--dangerously-skip-permissions is only used inside isolated CI job environments, never on developer machines
PRs include a record of which Claude Code session performed the review (for auditability)
Summary
Claude Code's HTTP Hooks are the connective tissue that plugs AI agents into your existing development workflows. Here's what we covered:
HTTP Hooks enable bidirectional integration with external services; the decision field gives you direct control over Claude Code's behavior
Webhook servers need layered security: HMAC signature verification, Bearer Token auth, and IP allowlisting
The three most practical GitHub Actions integration patterns are: automated code review, test failure analysis, and semantic version determination
A Block → Rewrite → Verify feedback loop lets Claude Code autonomously meet quality standards without manual intervention
Cloudflare Workers is the ideal deployment target — global edge presence, no cold starts, generous free tier
Combining this with Claude Code Parallel Development Mastery opens up an even more advanced workflow: multiple agents writing code in parallel, each output verified in real time by HTTP Hooks, with results consolidated into a single coherent PR.
The best way to start is small — add a single Claude Code review step to one existing CI pipeline and see where it has the most impact. Once you experience the feedback loop firsthand, you'll naturally see where HTTP Hooks can take you next.
Share
Thank You for Reading
Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.