{"id":51576288,"url":"https://github.com/wanggang316/claw-github-hook","last_synced_at":"2026-07-11T00:32:47.190Z","repository":{"id":346483858,"uuid":"1189140084","full_name":"wanggang316/claw-github-hook","owner":"wanggang316","description":"Connect openclaw to github using github hook","archived":false,"fork":false,"pushed_at":"2026-03-24T05:25:25.000Z","size":93,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-25T04:08:24.349Z","etag":null,"topics":["cloudflare","github","openclaw","tunnel","webhooks"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wanggang316.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-23T02:37:17.000Z","updated_at":"2026-03-24T05:25:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/wanggang316/claw-github-hook","commit_stats":null,"previous_names":["wanggang316/claw-github-hook"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/wanggang316/claw-github-hook","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanggang316%2Fclaw-github-hook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanggang316%2Fclaw-github-hook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanggang316%2Fclaw-github-hook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanggang316%2Fclaw-github-hook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wanggang316","download_url":"https://codeload.github.com/wanggang316/claw-github-hook/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wanggang316%2Fclaw-github-hook/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35347554,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-10T02:00:06.465Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudflare","github","openclaw","tunnel","webhooks"],"created_at":"2026-07-11T00:32:47.041Z","updated_at":"2026-07-11T00:32:47.166Z","avatar_url":"https://github.com/wanggang316.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# claw-github-hook\n\nA Cloudflare Worker that receives GitHub App webhook events and relays them to a local [OpenClaw](https://openclaw.ai) AI agent, enabling AI-powered Q\u0026A, code review, and code modification directly from GitHub issues and pull requests.\n\n## How It Works\n\n```\nGitHub App Webhook (issue/PR event)\n  │\n  ▼ HTTPS POST\nCloudflare Worker (edge)\n  │ 1. Verify HMAC-SHA256 signature\n  │ 2. Parse GitHub event payload\n  │ 3. Route intent: qa / code-review / code-mod / ignore\n  │ 4. Build structured message with gh CLI hints\n  │ 5. POST to OpenClaw /hooks/agent\n  ▼\nOpenClaw (local, via Cloudflare Tunnel)\n  │ Agent reads workspace Skills\n  │ Uses gh CLI for all GitHub interactions\n  ▼\nGitHub (reply posted via gh CLI)\n```\n\n## Features\n\n- **HMAC-SHA256 signature verification** — rejects forged webhooks\n- **Intent routing** — `@mention /review`, `@mention /fix`, `@mention \u003cquestion\u003e`\n- **Multi-org routing** — route installations and repos to different OpenClaw agents via Cloudflare KV\n- **Multi-account support** — `gh auth switch` per route for multiple GitHub accounts\n- **Custom bot mention** — defaults to `@ghAccount`, configurable per route\n- **Zero runtime dependencies** — Web Crypto API only, no npm packages at runtime\n\n## Setup\n\n### Step 1: Set Up Cloudflare Tunnel\n\nThe tunnel exposes your local OpenClaw instance to the internet so the Cloudflare Worker can reach it.\n\nInstall `cloudflared` if you haven't: `brew install cloudflared`\n\n**Option A: Named tunnel with custom domain (recommended for production)**\n\nThis gives you a stable URL that doesn't change on restart.\n\n```bash\n# 1. Login (if you haven't already)\ncloudflared tunnel login\n# Opens browser — select the domain you want to use\n\n# 2. Create the tunnel\ncloudflared tunnel create openclaw\n# Output:\n#   Tunnel credentials written to /Users/you/.cloudflared/\u003cTUNNEL_ID\u003e.json\n#   Created tunnel openclaw with id \u003cTUNNEL_ID\u003e\n# Save the TUNNEL_ID for the next step.\n\n# 3. Create config file\ncat \u003e ~/.cloudflared/config.yml \u003c\u003c 'EOF'\ntunnel: \u003cTUNNEL_ID\u003e\ncredentials-file: /Users/you/.cloudflared/\u003cTUNNEL_ID\u003e.json\n\ningress:\n  - hostname: openclaw.yourdomain.com\n    service: http://localhost:18789\n  - service: http_status:404\nEOF\n# Replace:\n#   \u003cTUNNEL_ID\u003e with the ID from step 2\n#   /Users/you/ with your actual home directory path\n#   openclaw.yourdomain.com with your chosen subdomain\n#   18789 with your OpenClaw Gateway port (18789 is the default)\n\n# 4. Add DNS record\ncloudflared tunnel route dns openclaw openclaw.yourdomain.com\n# This creates a CNAME record in Cloudflare DNS automatically\n\n# 5. Start the tunnel\ncloudflared tunnel run openclaw\n# Keep this running. Your OpenClaw is now reachable at:\n#   https://openclaw.yourdomain.com\n```\n\n**Option B: Quick tunnel (for testing only)**\n\n```bash\ncloudflared tunnel --url http://localhost:18789\n# Output:\n#   Your quick Tunnel has been created! Visit it at:\n#   https://random-words.trycloudflare.com\n# ⚠️ This URL changes every time you restart the tunnel.\n# You'll need to update your KV routes config each time.\n```\n\n**Verify the tunnel works:**\n\n```bash\ncurl https://openclaw.yourdomain.com/api/v1/check\n# Should return a 200 response from OpenClaw\n```\n\n### Step 2: Clone and Install\n\nRequires Node.js 20+ (`brew install node`).\n\n```bash\ngit clone https://github.com/wanggang316/claw-github-hook.git\ncd claw-github-hook\nnpm install\nnpm run check    # Should show no errors\n```\n\n### Step 3: Create KV Namespace\n\nInstall Wrangler CLI if you haven't: `npm install -g wrangler \u0026\u0026 wrangler login`\n\nKV (Key-Value) stores the routing config that maps GitHub App installations and repos to OpenClaw agents.\n\n```bash\nwrangler kv namespace create ROUTES_KV\n# Output:\n#   ✨ Success!\n#   Add the following to your configuration file:\n#   [[kv_namespaces]]\n#   binding = \"ROUTES_KV\"\n#   id = \"abc123...\"\n```\n\nCopy the `id` value and edit `wrangler.toml`:\n\n```toml\n[[kv_namespaces]]\nbinding = \"ROUTES_KV\"\nid = \"abc123...\"   # ← paste your actual ID here\n```\n\n### Step 4: Set Worker Secrets\n\nSecrets are sensitive values stored securely in Cloudflare, not in code.\n\nMake sure your OpenClaw config has hooks enabled (see [https://docs.openclaw.ai](https://docs.openclaw.ai)):\n\nGenerate a strong token for `hooks.token` first. For example:\n\n```bash\nopenssl rand -hex 32\n```\n\nYou can also use any long, random string you create yourself, as long as you use the exact same value later when setting the Worker secret.\n\n```json\n{\n  \"hooks\": {\n    \"enabled\": true,\n    \"path\": \"/hooks\",\n    \"token\": \"\u003copenclaw_hooks_token\u003e\",\n    \"defaultSessionKey\": \"hook:github\",\n    \"allowRequestSessionKey\": false,\n    \"allowedAgentIds\": [\"\u003cagent_id\u003e\"]\n  }\n}\n```\n\n```bash\n# 1. Generate and set the webhook secret\n# Or skip openssl and manually enter your own long random string for GITHUB_WEBHOOK_SECRET\nopenssl rand -hex 32\n# Copy the output, then:\nwrangler secret put GITHUB_WEBHOOK_SECRET\n# Paste the random string when prompted\n# ⚠️ Save this string — you'll need it again in Step 7 for GitHub webhook config\n\n# 2. Set auto-review preference\nwrangler secret put AUTO_REVIEW\n# Enter: false (or true if you want every PR auto-reviewed)\n\n# 3. Set OpenClaw token\nwrangler secret put TOKEN_PROJ1\n# Enter: the exact hooks.token value from your OpenClaw config\n```\n\nIf you have multiple OpenClaw instances with different tokens, add more secrets:\n\n```bash\nwrangler secret put TOKEN_PROJ2\nwrangler secret put TOKEN_PROJ3\n```\n\n### Step 5: Upload Routes\n\nRoutes tell the Worker which GitHub App installation and repo go to which OpenClaw agent.\n\n**Recommended setup (organization defaults + repo overrides):**\n\n```bash\nwrangler kv key put routes '[\n  {\n    \"installationId\": 12345678,\n    \"owner\": \"myorg\",\n    \"defaults\": {\n      \"openclawUrl\": \"https://openclaw.yourdomain.com\",\n      \"openclawToken\": \"$TOKEN_PROJ1\",\n      \"agentId\": \"\u003cdefault_agent_id\u003e\",\n      \"ghAccount\": \"your-github-username\",\n      \"autoReview\": true\n    },\n    \"repos\": {\n      \"api\": {\n        \"agentId\": \"\u003capi_agent_id\u003e\"\n      },\n      \"web\": {\n        \"agentId\": \"\u003cweb_agent_id\u003e\",\n        \"autoReview\": false\n      }\n    }\n  }\n]' --binding ROUTES_KV --remote\n```\n\nReplace:\n\n- `12345678` — your GitHub App installation ID\n- `myorg` — the organization login\n- `https://openclaw.yourdomain.com` — your tunnel URL from Step 1\n- `$TOKEN_PROJ1` — keep as-is, this references the secret from Step 4\n- `\u003cdefault_agent_id\u003e` / `\u003capi_agent_id\u003e` / `\u003cweb_agent_id\u003e` — your OpenClaw agent IDs\n- `your-github-username` — your GitHub username if you want `gh auth switch` and `@username` mention defaults\n\n**Route field reference:**\n\n| Field | Required | Description |\n| --- | --- | --- |\n| `installationId` | No but recommended | GitHub App installation ID; best primary key in multi-org setups |\n| `owner` | Yes | Organization login used as readable key and fallback matcher |\n| `defaults` | Yes | Default OpenClaw target for the installation/org |\n| `repos` | No | Repo-name keyed overrides, for example `\"api\"` or `\"web\"` |\n| `defaults.openclawUrl` | Yes | Tunnel URL from Step 1 |\n| `defaults.openclawToken` | Yes | Token reference like `\"$TOKEN_PROJ1\"` |\n| `defaults.agentId` | Yes | Default OpenClaw agent ID |\n| `defaults.ghAccount` | No | GitHub username for `gh auth switch` |\n| `defaults.botMention` | No | Custom trigger mention |\n| `defaults.autoReview` | No | Default PR auto-review policy |\n\nRoute resolution priority: `installationId` → `owner` → `defaults` merged with `repos[repoName]`.\n\n### Step 6: Deploy the Worker\n\n```bash\nwrangler deploy\n# Output:\n#   Published claw-github-hook (x.xx sec)\n#   https://claw-github-hook.your-account.workers.dev\n# Save this URL for Step 7\n```\n\n### Step 7: Configure the GitHub App\n\nCreate a GitHub App and set its webhook URL to your Worker URL from Step 6.\n\n1. Go to **GitHub Settings → Developer settings → GitHub Apps → New GitHub App**\n2. Set **Webhook URL** to your Worker URL\n3. Set **Webhook secret** to the same value as `GITHUB_WEBHOOK_SECRET`\n4. Subscribe only to:\n  - `Issue comment`\n  - `Pull request`\n  - `Pull request review comment`\n5. Grant repository permissions:\n  - `Metadata: Read-only`\n  - `Issues: Read-only`\n  - `Pull requests: Read-only`\n6. Install the App into each target organization\n7. For each installation, either select all repositories or the subset you want routed\n\nGitHub will send webhook deliveries to the App webhook automatically after installation.\n\n### Step 8: Install Skills in OpenClaw\n\nThe skills guide OpenClaw's agent on how to handle each type of GitHub event. There are three skills:\n\n- `github-qa` — answer questions from issue/PR comments\n- `github-review` — perform code review on pull requests\n- `github-code-mod` — make code changes and open PRs\n\n**Option 1: Ask your Agent to install them**\n\nGive your OpenClaw agent a prompt like this:\n\n```text\nPlease install these 3 skills from https://github.com/wanggang316/claw-github-hook.git into OpenClaw:\n- skills/github-qa\n- skills/github-review\n- skills/github-code-mod\n\nIf OpenClaw needs a restart or reload to detect new skills, do that too.\n```\n\n**Option 2: Manually install them**\n\nClone this repo, enter it, then copy the three skill folders:\n\n```bash\ngit clone https://github.com/wanggang316/claw-github-hook.git\ncd claw-github-hook\ncp -r skills/github-qa skills/github-review skills/github-code-mod ~/.openclaw/skills/\n```\n\n- Global install: `~/.openclaw/skills/`\n- Install for one agent: `~/agents/\u003cagent_id\u003e/skills/` (replace the `cp` target path)\n\nRestart OpenClaw or wait for the skills watcher to pick them up.\n\n### Step 9: Verify End-to-End\n\n1. Make sure OpenClaw is running and the Cloudflare Tunnel is active\n2. Go to a GitHub issue in your configured repo\n3. Post a comment: `@your-github-username hello, can you see this?`\n4. Watch the Worker logs: `wrangler tail`\n5. Check OpenClaw logs for the incoming message\n\nIf the Worker log shows `FORWARDED: success` but OpenClaw doesn't respond, check:\n\n- Is the tunnel URL correct and reachable?\n- Is the agent ID correct?\n- Are the skills installed in the OpenClaw workspace?\n\n## Usage\n\nOnce everything is set up, mention the bot in any GitHub issue or PR comment.\n\n### Bot Mention\n\nThe bot responds to mentions based on this priority:\n\n1. `**botMention**` in route config (if set) — e.g. `@my-ai-bot`\n2. `**@ghAccount**` (if `ghAccount` is set in route config) — e.g. `@superada2026`\n3. `**@claw**` (default fallback when neither is set)\n\n### Commands\n\n\n| Comment                                    | Action                                                         |\n| ------------------------------------------ | -------------------------------------------------------------- |\n| `@mention what does this function do?`     | **Q\u0026A** — agent answers the question and posts a reply         |\n| `@mention /review`                         | **Code Review** — agent fetches the PR diff and posts a review |\n| `@mention /fix null pointer in auth.ts`    | **Code Mod** — agent fixes the code and opens a PR             |\n| `@mention /implement add input validation` | **Code Mod** — agent implements the feature and opens a PR     |\n\n\n*(Replace `@mention` with your bot mention — see priority above.)*\n\n## Updating Routes\n\nTo change routing without redeploying:\n\n```bash\nwrangler kv key put routes '\u003cnew JSON\u003e' --binding ROUTES_KV --remote\n```\n\nChanges take effect immediately — no `wrangler deploy` needed.\n\n## Troubleshooting\n\n\n| Symptom                                     | Cause                                          | Fix                                                                                          |\n| ------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------------------- |\n| GitHub shows 401                            | Signature mismatch                             | Ensure `GITHUB_WEBHOOK_SECRET` matches the GitHub webhook Secret field                       |\n| Worker log: `IGNORED: no route`             | No matching installation/org route in KV      | Check `wrangler kv key get routes --binding ROUTES_KV --remote` and verify `installationId`, `owner`, and repo override names |\n| Worker log: `IGNORED: intent=ignore`        | Comment doesn't contain the bot mention        | Check which mention is configured — run `wrangler tail` to see the logs                      |\n| Worker log: `FORWARD FAILED: 530`           | Tunnel is down or URL changed                  | Restart `cloudflared tunnel run` and update KV routes if using quick tunnel                  |\n| Worker log: `FORWARD FAILED: 400`           | OpenClaw rejected the request                  | Check OpenClaw logs; verify `agentId` is in `allowedAgentIds`                                |\n| OpenClaw receives message but doesn't reply | Skills not installed or `gh` not authenticated | Run `gh auth status` and check `~/.openclaw/skills/`                                         |\n\n\n## Development\n\n```bash\nnpm run dev       # Local dev server with wrangler\nnpm run check     # TypeScript type check\nwrangler tail     # Live Worker logs\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwanggang316%2Fclaw-github-hook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwanggang316%2Fclaw-github-hook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwanggang316%2Fclaw-github-hook/lists"}