Every PR is a PrayRequest. 合併之前,先讀一段。
A GitHub bot that drops a context-aware Bible verse on every Pull Request — matched to the title, description, and diff. Just the verse and the reference; readers interpret it however they want.
| What | GitHub bot that comments a Bible verse on PRs, matched to the PR's context |
| Why | Team's YOLO-PR culture has no artifact. Canonize the vibe. |
| How | GitHub App on Cloudflare Workers → Claude Haiku 4.5 (Workers AI binding) → POST comment |
| Cost | ~$0.002 per PR. ~$2/month at 1,000 PRs. |
| Build effort | PoC in 1 day. MVP in 2–3 days. |
| Risk | Religious sensitivity → opt-in per repo, alternate quote sources optional. |
Problem. YOLO PRs — Friday 6pm hotfixes, no-test merges, 3,000-line refactors, "I'll add tests later" — are a recurring team meme but leave no artifact. The vibe deserves canonization.
Solution. PrayRequest auto-comments a fitting Bible verse and reference. It reads the PR context (title, description, diff shape) and picks scripture that matches the energy. No editorial commentary — the verse stands alone.
Why it works.
- Context-aware, not random. A
hotfixPR gets a different verse than a refactor. That's the joke. - No commentary, no offense. Verse + reference only. The reader does the interpretation. Lowers religious-sensitivity risk and makes the bot easy to localize without rewriting tone.
- Low-cost to run. Cloudflare Workers free tier swallows everything pre-viral. ~$0.002/PR for the LLM call once v1 lands.
- Opt-in per PR. Auto-bless only fires when
@prayrequestappears in the PR title or body. Repos that install the App don't get a verse on every PR — only on the ones that ask for one.
Three trigger modes:
| Mode | Trigger | Behavior |
|---|---|---|
| Auto-bless | PR opened / ready_for_review with @prayrequest in title or body |
Drop one verse + reference on PR open |
| Summon | @prayrequest in any PR comment |
Reply contextually to the thread |
| Reroll | @prayrequest reroll |
Generate an alternate verse if the first didn't land |
Optional future modes:
- Last rites — verse on merge ("rest in peace, prod")
- Point-blessing —
@prayrequest bless @reviewerto bless someone else - Daily verse — scheduled team-wide verse via repo discussions
┌─────────────────┐
│ GitHub PR / │ opened / commented
│ comment event │
└────────┬────────┘
│
▼
┌─────────────────────────────┐
│ Cloudflare Worker │
│ /webhook │
│ │
│ 1. Verify HMAC signature │
│ 2. Mint installation token │
│ 3. Extract context: │
│ • title + description │
│ • diff stats │
│ • file paths touched │
│ • signals (no tests, │
│ hotfix, security, │
│ TODO/FIXME, size) │
└────────┬────────────────────┘
│
▼
┌─────────────────────────────┐
│ Claude Haiku 4.5 │
│ (Workers AI env.AI binding)│
│ │
│ System prompt asks for: │
│ • Bible verse matching │
│ the PR's energy │
│ • Reference (book ch:v) │
│ • JSON output │
│ (No commentary — verse │
│ speaks for itself) │
└────────┬────────────────────┘
│
▼
┌─────────────────────────────┐
│ POST /repos/:o/:r/ │
│ issues/:n/comments │
│ (installation token) │
└─────────────────────────────┘
The Worker subscribes to pull_request and issue_comment webhook events.
It dispatches on X-GitHub-Event. PR comments arrive as issue_comment because
GitHub treats PRs as a subtype of issues at the API layer.
Before calling Claude, the Worker enriches the PR with cheap heuristic signals that bias verse selection:
| Signal | Detection | Vibe |
|---|---|---|
| Friday-late hotfix | title contains hotfix|urgent, time after 5pm Fri |
YOLO max |
| No tests | diff touches src/ but no test|spec files |
faith-without-works |
| Security path | files in auth/|middleware/|admin/ |
watchman of the city |
| TODO debt | diff adds TODO|FIXME|XXX |
hidden things |
| Massive diff | >500 lines or >20 files changed | new creation |
| Force push | commit count drop | revisionist |
Signals are passed to Claude as structured input so verse matching is predictable and non-random.
| Layer | Choice | Why |
|---|---|---|
| Trigger / runtime | Cloudflare Workers | Free tier, sub-100ms cold start, native WebCrypto for HMAC + RS256 |
| Web framework | Hono | Tiny (~12 KiB), Workers-native routing |
| GitHub auth | jose for App JWT + raw fetch for token exchange |
Two endpoints; Octokit would be overkill |
| LLM | Claude Haiku 4.5 via the Cloudflare Workers AI env.AI binding (proxied; billed through Unified Billing) |
Accurate bilingual CUV+KJV recall, no reasoning-token trap, no separate API key. Cheap Workers AI models mis-recalled the CUV and couldn't be constrained via the binding. |
| Verse fallback | Curated JSON of pre-tagged verses + default | Used if API fails, rate-limits, or hallucinates |
| Config | .github/prayrequest.yml per repo (planned) |
Verse language, opt-out paths, alternate quote sources |
| Optional analytics | PostHog | Track 👍/👎 reactions to learn which verses land |
Earlier drafts shipped as a GitHub Action because it had no infra cost. That path is gone — the App needs hosted GitHub App credentials (App ID, private key, webhook secret) and a billing-enabled LLM path anyway, which kills the "drop two files, no secrets" pitch the Action existed for. The hosted App is now the only distribution.
| GitHub App on Workers | (former) Action path | |
|---|---|---|
| Setup | Install once at org level | Drop workflow file per repo |
| Latency | sub-100ms cold start | ~10s runner spin-up |
| Auth | App JWT → installation token | Default GITHUB_TOKEN |
| LLM secrets | None — Workers AI binding + Unified Billing | Per-repo ANTHROPIC_API_KEY |
| Summon UX | @mention + (planned) reviewer-add |
Workflow listens on issue_comment |
GitHub Apps can be added to requested_reviewers and respond on
pull_request: [review_requested], the same way CodeRabbit and
Greptile do. So @prayrequest could plausibly work both as an
@-mention summon and as a "add the bot as a reviewer" target. The UI
affordance of appearing in the reviewer picker without typing is
currently a Copilot-only privilege (first-party integration), but the
underlying API capability exists for any App with the right
permissions. Worth confirming against GitHub docs before locking the
v2 spec.
Per-PR cost breakdown using Claude Sonnet 4.6 with prompt caching:
| Item | Tokens | Cost |
|---|---|---|
| Cached system prompt | ~800 in (cached) | negligible |
| PR context (title + desc + diff summary) | ~500 in | $0.0015 |
| Output (verse + reference) | ~50 out | $0.0008 |
| Per PR | ~$0.002 |
At 1,000 PRs/month: ~$2. At 10,000: ~$20. Cloudflare Workers free tier covers the webhook traffic at this volume.
A Haiku-only "cost mode" cuts this by ~5×.
Bash + jq workflow that proved the comment plumbing. Removed once the
App took over; the keyword-matching logic moved to TypeScript at
app/src/verse-picker.ts and the verse JSON moved with it.
app/— Cloudflare Workers + TypeScript + Hono. Webhook handler verifiesX-Hub-Signature-256, mints installation tokens, posts via the App's bot identity.- Install once at the org or user level, no per-repo workflow file.
- Auto-bless on
pull_request: [opened, ready_for_review]only when@prayrequestis in the PR title or body (opt-in per PR). @prayrequestin any PR comment → summon.@prayrequest reroll→ walks the issue's comments, finds the bot's last verse, excludes it from the next pick (matched via hidden HTML comment anchor<!-- prayrequest:ref=… -->).- Keyword matcher with word-boundary tag matching against PR title,
JSON-order priority, and a
massive-tag override for big diffs — now the fallback beneath the v1 LLM (see below). - Open: Request-review as trigger — add
@prayrequestas a reviewer, respond onpull_request: [review_requested]. Underlying API supports this for any App; UI sidebar prominence may stay Copilot-only. To be confirmed.
pickVerseWithLLMinapp/src/verse-picker.tscalls Claude Haiku 4.5 with PR context (title + description + diff size + recent commits).- Reached via the Cloudflare Workers AI
env.AIbinding (proxiedanthropic/*) — noANTHROPIC_API_KEY; needs Unified Billing enabled on the account instead. - Validates the reference against the Bible canon (
bible-canon.ts) and falls back to the keyword matcher on failure, timeout, or invalid ref. - Same surface (auto-bless, summon, reroll), smarter picks.
- Still pending: deterministic signal extraction, hybrid ref→canonical-text lookup, prompt caching, and the daily per-repo comment cap (Cloudflare KV).
- React-emoji feedback loop (👍/👎 → log to PostHog)
- Verse-fatigue dampening (don't repeat same verse within N PRs)
- Per-repo config (
.github/prayrequest.yml): language, alternate quote sources (Tao Te Ching, Sun Tzu, Shakespeare for non-religious teams) - Publish App on Marketplace, landing page, docs
Each scenario assumes the author included
@prayrequestin the PR title or body to opt in. Without that, auto-bless is silent.
PR: @prayrequest hotfix: payment gateway timeout (URGENT) — +3 / −1, no tests
人若賺得全世界,賠上自己的生命,有甚麼益處呢? — 馬太福音 16:26
— 🙏 PrayRequest
PR: refactor: rewrite auth module — +2,847 / −3,102, 30 files
看哪,我將一切都更新了。 — 啟示錄 21:5
— 🙏 PrayRequest
PR: feat: add user export to CSV — +312 / −4, 0 test files
信心若沒有行為就是死的。 — 雅各書 2:17
— 🙏 PrayRequest
PR: fix: bypass JWT check for internal calls — touches middleware/auth.ts
若不是耶和華看守城池,看守的人就枉然儆醒。 — 詩篇 127:1
— 🙏 PrayRequest
Diff:
+ // TODO: handle edge case when user has no email
+ // FIXME: this is a hack, refactor later掩蓋自己罪過的,必不亨通;承認且離棄罪過的,必蒙憐恤。 — 箴言 28:13
— 🙏 PrayRequest
| Risk | Mitigation |
|---|---|
| Religious sensitivity | Opt-in per repo. Allow alternate quote sources (Tao Te Ching, Sun Tzu, Shakespeare). Verse + reference only — no editorial commentary, so the bot never appears to be mocking the verse or the author. |
| Cost runaway | Daily comment cap per repo. Fallback to curated verse list if API errors. Skip bot-authored PRs. |
| Spam fatigue | Auto-bless is opt-in per PR (@prayrequest must appear in title or body); silent on every PR that doesn't ask for it. Don't auto-bless on synchronize events (only initial open). |
| Verse repetition | Track recently-used verses per repo, dampen reuse within N PRs. |
| LLM hallucination of verses | Validate Claude's output against a known verse index; fall back to curated list if reference doesn't exist. |
| Verse–context mismatch | Maintain a small eval set of PR scenarios + expected verse category; run before each prompt change. |
- Default language: English, Cantonese, or bilingual? Bilingual is the most "us" but verbose in comments.
- Should it bless reviewers too, or only authors? Reviewer-blessing is funnier but adds noise.
- App reviewer integration: confirm
requested_reviewersworks for a third-party App without Copilot-tier UI privileges. If yes, advertise "add@prayrequestas a reviewer" as a first-class summon mode (and solves the autocomplete-discoverability gap). - Marketplace listing: keep private install (single-link) or publish on the Marketplace for public discovery. Marketplace requires a verified publisher, listing copy, screenshots, and a separate review process.
> [verse]
> — *[reference]*
*— 🙏 PrayRequest*
v1 ✅ shipped — App is deployed and installed on this repo; auto-bless + summon + reroll all work end-to-end, and verse selection is LLM-driven (Claude Haiku 4.5 via the Workers AI binding) with the keyword matcher as fallback.
Next: the items deferred from v1 — deterministic signal extraction before the LLM call, the hybrid ref→canonical-text lookup (so recalled verse text is verified, not just the reference), prompt caching, and the daily per-repo comment cap (Cloudflare KV) as the runaway-cost guard.