Greenlight is the pre-flight and coordination layer for open-source contribution: the software that stands between an outside contributor (increasingly an AI agent) and the maintainers of a public repo, and answers the questions no other tool answers. Can I contribute here at all? Is this issue secretly taken? What are the house rules? Who else is racing me? And for maintainers: who is flooding my queue, and what is safe to merge?
Follow the venture money and you will see where it is not going. Cognition (Devin) raised about $2B at a $48B valuation, and Factory raised $200M at a $5B valuation, to run autonomous coding agents inside enterprises' own repos. CodeRabbit raised $88M (valued near $550M), Graphite raised a $52M Series B before being acquired by Cursor, and Greptile raised a $25M Series A, all reviewing a team's own pull requests. OpenHands is an agent runtime. Every funded player assumes you are inside the org.
Nobody owns the boundary. No VC-backed tool answers the outside contributor's questions: can I contribute here, is this issue secretly taken, what are this repo's gates and AI policies, who else is racing me. And no VC-backed tool answers the maintainer's questions: which of these 30 open PRs are duplicates, who is claiming what, which claims have gone stale, which agent-written PRs are safe to merge. Greenlight is that layer, built from running real contribution campaigns through it every week.
AI made code cheap. Contribution coordination is now the bottleneck, and it breaks in specific, repeatable ways:
- Hidden competition. Issue list views lie. In a hand-vetted focus session on usebruno/bruno, 6 of 7 promising issues were secretly taken by PRs visible only in the issues' timelines, not in the list view or search results. You can spend a weekend on work that was already done.
- Gates and bans. Greenlight's own Agent Policy Index now tracks 505 repos: 127 of them (25%) carry contribution gates, and 19 ban agent contributions outright. Whole repos (nuxt, uv, Gradio, Activepieces) have closed their doors to outside PRs entirely. Nobody told you; it was in AGENTS.md.
- Duplicate AI PRs. When several contributors (human or agent) race the same issue, maintainers get three overlapping PRs and no way to arbitrate. GitHub has no claim system, only comments.
- House rules everywhere. CLAs, DCO sign-off, changesets, commit formats, assignment requests. Every repo invents its own, hides them in different files, and rejects your PR on the technicality.
These are coordination problems, not coding problems. The code agents keep getting better; the boundary keeps getting messier. Greenlight works the boundary.
Three layers, from decide to solve to coordinate:
| Layer | Question it answers | Flagship commands |
|---|---|---|
| Decide | Is this issue mine to take? Is this repo worth my time? | check, scan, friction, xray, preflight |
| Solve | Will my PR pass? What broke? What do I do next? | ci-prep, ci, review, brief, verify, autopilot, babysit, evidence |
| Coordinate | Who is working on what, and who resolves conflicts? | claim (+ Claim Protocol), guard, radar, digest, passport |
- Decide.
checkreads an issue, its comments, linked and mentioned PRs (timeline plus search plus comment references), and the repo's rules, then answers in plain words: GO, RISKY, TAKEN, GATED, or STALE.scanranks a repo's open issues so you pick a winnable one first.frictionscores a repo 0 to 100 on how hard it really is to get a PR merged, with every gate quoting the file its evidence came from.xray(Timeline X-Ray) deep-verifies candidates against their issue timelines before you write a line, catching hidden in-flight PRs including reporter-owned fix PRs;scan --deepdemotes anything taken before it shows you the list. - Solve.
ci-prepruns a repo's own pull-request checks locally before you push (tests, lint, typecheck, plus conventions like changesets, commit format, DCO), so avoidable CI failures never appear in front of a maintainer.citriages red PRs into pre-existing vs likely-yours vs external-blocker against base-branch history.reviewclassifies every review thread as likely-real, likely-noise, or needs-decision and drafts your replies.verifyreports the honest red-green test delta of your change.autopilotverifies bot findings against the code at head and fixes the mechanical items (DCO surgery, conflict re-merges, formatting) itself.briefassembles a verified one-screen brief for any PR: change shape by area and risk, CI triaged against base-branch history, findings classified real vs false-positive with evidence, test evidence present or explicitly marked absent, merge blockers, and a one-line look-at-this-first.babysitwatches your open PRs and reports one prioritized action list. - Coordinate.
claimposts a protocol claim (expiring lease, public queue, heartbeats; full spec inprotocol/SPEC.md), with a hosted app client option via--via-api.guardanalyzes an incoming PR for a maintainer: competing fix, prior claims, missing artifacts, first-time contributor.digestreports a repo's PR races, claimed-by-other conflicts, stale claims, and assignment-gate conflicts.radarscans the whole open-PR queue and clusters competing or duplicate PRs with evidence per cluster and a suggested keep, labeled a heuristic, never a verdict.passportrenders a contributor's merged work plus claim record.
Every verdict and every report cites its evidence: the quoted policy line, the claim comment URL, the PR number, the failing check. Nothing is asserted without a source.
- Contributors (human). Run
checkbefore you spend an evening on an issue. Runscanwhen you are picking what to work on. Runci-prepbefore you push. - AI agents and coding tools. One command (
init --agent claude-code, also cursor, copilot, windsurf, cline) installs the MCP config plus the one behavior rule: check Greenlight before opening a PR. Agents waste the most tokens fixing already-taken issues; 27 MCP tools make the whole engine available mid-run. - Maintainers.
guardon each incoming PR,radaracross the whole open queue,digestfor the weekly triage, and the roadmap below for the control room: stale-claim sweeps, policy enforcement, AI-PR filtering.
- 965 tests, all passing, including a fixture corpus pinned to real campaign cases (a taken issue, a weak PR mention, claim-first gates, scoped claims, half-shipped issues, stale claims, paused-PR workflows).
- Dogfooded on real campaigns: the toolkit has authored 80+ pull requests across dozens of public open-source repos. Every feature exists because a real contribution died without it.
- Distributed everywhere the audience already looks: npm (
@reneturcios/greenlight), the MCP Registry, and GHCR (ghcr.io/cloudcorprecords/greenlight), plus Docker and direct MCP stdio. - Two living datasets ship with it: the Contribution Friction Index (
data/friction-index.json) and the Agent Policy Index (505 repos, 127 gated, 19 agent bans, published atdocs/policy.html), both built from real campaign field work, not scraped guesses.
The 59-second demo: real issue checks on real repos, an AI-caught hidden claim, a GATED agent ban, campaign scouting, and the claims babysitter. Full narrated video.
npx @reneturcios/greenlight check <issue-url>Set up your AI coding tool and verify the setup:
npx @reneturcios/greenlight init --agent claude-code # one-command MCP setup (cursor, copilot, windsurf, cline work too)
npx @reneturcios/greenlight doctor # checks Node version, token, GitHub quota, cacheOr from source:
npm install
npm run buildSet GITHUB_TOKEN (a classic personal access token, no scopes needed for public repos) to raise the GitHub API rate limit from 60 to 5000 requests per hour. Greenlight caches API responses under ~/.cache/greenlight.
Run the MCP server with npx @reneturcios/greenlight mcp (stdio), or point your agent at the greenlight command with the single argument mcp.
Greenlight also ships as a container image on GHCR: ghcr.io/cloudcorprecords/greenlight.
Use it as a stdio MCP server:
docker run -i ghcr.io/cloudcorprecords/greenlightAny CLI command can be passed after the image name instead of the default mcp argument:
docker run ghcr.io/cloudcorprecords/greenlight check <issue-url>
docker run ghcr.io/cloudcorprecords/greenlight --versionOne command sets it up:
npx @reneturcios/greenlight init --agent claude-code(also cursor, copilot, windsurf, cline; repeat --agent for more than one). Init copies the MCP config into your project and installs the workflow instruction snippet that teaches your agent the one behavior rule: check Greenlight before it opens a PR. Prefer doing it by hand? The integrations/ drop-in pack has ready-to-copy MCP configs plus the same snippets. Then verify with a "list your MCP tools" prompt; the greenlight server carries 27 tools (see the list below).
# One-command setup for your AI coding tool (cursor, copilot, windsurf, cline work too)
npx @reneturcios/greenlight init --agent claude-code
# Verify the setup: Node version, token, GitHub quota, cache (exit 1 when anything fails)
npx @reneturcios/greenlight doctor
# Help: overview, one command's flags, or the version
npx @reneturcios/greenlight help check
npx @reneturcios/greenlight --version
# Verdict for one issue
npx @reneturcios/greenlight check https://github.com/batrapulkit/squidbrake/issues/74
# [GO] batrapulkit/squidbrake#74
# Taint: tell the approver when an agent edits its own setup right after reading outside content
# - open, unassigned, no linked PRs, no claim signals, no blocking gates
# Rank a repo's starter issues, GO first (falls back to recent open
# unassigned issues when the repo does not use those labels; --no-fallback to opt out)
npx @reneturcios/greenlight scan PrefectHQ/fastmcp
# Deep-verify candidates against their timelines first (catches hidden in-flight PRs)
npx @reneturcios/greenlight xray usebruno/bruno --issues 8149,9319
npx @reneturcios/greenlight scan usebruno/bruno --deep
# Friction score for a repo
npx @reneturcios/greenlight friction triggerdotdev/trigger.dev
# CI triage for a red PR: is each failing check yours or pre-existing?
npx @reneturcios/greenlight ci https://github.com/reticlehq/reticle/pull/1620
# [pre-existing] install-gate (windows-latest)
# same check failing on base: 2 of 3 recent base runs, last at 2026-10-14T10:00:00Z
# [external-blocker] Vercel - Authorization required
# check name matches the Vercel deploy/auth pattern; this failure is infrastructure, not the PR
# JSON output for scripting
npx @reneturcios/greenlight ci <pr-url> --json
# CI pre-flight: run a repo's own PR checks locally before pushing (exit 1 on NO-GO)
npx @reneturcios/greenlight ci-prep ~/work/bruno
# [PASS] tests (workflow ci, job build)
# [SKIPPED] publish (workflow release, job release) - publishes a package
# [PASS] convention: DCO sign-off
# Verdict: GO
# Review triage for a PR with review feedback: which comments need you?
npx @reneturcios/greenlight review https://github.com/n8n-io/n8n/pull/41235
# Verified review brief for any PR: change shape by area and risk, CI
# triaged against base-branch history, findings classified with evidence,
# test evidence present or explicitly marked absent, merge blockers, and
# a one-line look-at-this-first
npx @reneturcios/greenlight brief https://github.com/usebruno/bruno/pull/9569
# Brief: 4 files (+335/-11), 2 source + 2 tests
# CI: code checks green; external blockers named (fork workflows require maintainer approval)
# review: NO FINDINGS
# blockers: none
# lookFirst: No blockers or real findings. Start here: 2 source files carry the change.
# Campaign scout: rank repo targets, dedupe against the campaign file, append as SCOUTED
npx @reneturcios/greenlight scout --repos acme/widgets,acme/gadgets --campaign campaign.json --write
# Babysit your registered claims: linked, linked-dead, healthy-active, heartbeat-due, expiring, unlinked-stale, queue-lost
npx @reneturcios/greenlight babysit --claims-only
# A claim whose linked PR closed unmerged reads linked-dead, with a release
# prompt: the issue is free, but the stale marker needs an explicit release.
# Pacing: claim posts never trip GitHub's anti-spam flag
# Every post attempt is ledgered at ~/.greenlight/posting-ledger.json
# (timestamp, kind, target, outcome). Claim posts enforce a minimum
# interval (default 90s, jittered; GREENLIGHT_CLAIM_MIN_INTERVAL_S, or
# --min-interval) and a daily soft cap (default 25 per rolling day;
# GREENLIGHT_CLAIM_DAILY_CAP, 0 disables). A post that fails with a block
# or an uncertain network error is marked UNCONFIRMED; the tool re-reads
# the target against the API before ever posting to it again, so a
# "failed" post that actually landed is marked confirmed and never
# reposted. --force overrides any pacing refusal, and the override is
# ledgered. greenlight status shows your pacing posture.
npx @reneturcios/greenlight status https://github.com/owner/repo/issues/123
# Maintainer guard for an incoming PR: competing fix, prior claims, missing
# artifacts (changeset / DCO / CLA), first-time contributor. Renders markdown
# ready to post as one comment; Greenlight itself never posts.
npx @reneturcios/greenlight guard https://github.com/owner/repo/pull/123
# Greenlight guard: 1 thing to check
# - Missing release-note file (repo uses .changes/): expected .changes/123-slug.md
npx @reneturcios/greenlight guard <pr-url> --quiet # exit 3 when flagged, silent otherwise
# Duplicate/competing PR radar for the whole queue: clusters PRs fixing the
# same issue or touching the same files, with evidence and a suggested keep
# per cluster (always labeled a heuristic, never a verdict)
npx @reneturcios/greenlight radar usebruno/bruno --limit 100
# 100 open PRs scanned in 6 API calls: 3 competing clusters, 94 unclustered
# cluster (same issue #5011): #5016 "Fix: Param table UI breaks bug" ~ #5074 "fix: Param Table UI Breaks on resize" - suggested keep #5016 (heuristic)
# cluster (file overlap, 100% Jaccard in packages/): #3484 ~ #5747 - suggested keep #3484 (heuristic)
# Verified comment for a maintainer-only repo: the issue takes no outside
# PRs (inspector, servers), so the contribution is a detailed, verified
# comment. Assembles from your notes or a markdown file; sections you
# leave empty render as explicit gaps, never filler. Never posts.
npx @reneturcios/greenlight verify-comment https://github.com/modelcontextprotocol/inspector/issues/2723 \
--claim "TUI tests append to the developer's real ~/.mcp-inspector/auth.log" \
--env "modelcontextprotocol/inspector @ 3a4b5c6, 2026-10-15" \
--repro $'point HOME at a scratch dir\nrun: vitest run __tests__/App.test.tsx' \
--observed "155 lines appear in the scratch HOME's auth.log" \
--expected "test runs leave the developer's home directory untouched" \
--root-cause "clients/tui/__tests__/setup.ts does not isolate the log dir" \
--fix "per-test-file temp dir via fs.mkdtempSync, set MCP_INSPECTOR_LOG_DIR, remove on exit" \
--ran "vitest run __tests__/App.test.tsx: 130 passed" \
--by "@CloudCorpRecords"
# or: greenlight verify-comment <issue-url> --from-file notes.md
# Honest red-green test delta, in your repo checkout: runs the detected
# test command on a base worktree and your working tree, and reports what
# your change actually did: newly passing (fixed), newly failing (yours),
# still failing (pre-existing, not yours). Says "unverifiable" with the
# reason instead of guessing when it cannot run or parse.
cd your-repo && npx @reneturcios/greenlight verify --base origin/main
# exit 3 when new failures exist, 1 when unverifiable
# PR babysitter: one prioritized action list across your open PRs --
# needs you now, waiting on them, quiet. Reruns report what changed.
npx @reneturcios/greenlight babysit --mine --repos acme/widgets,acme/gadgets
# or: greenlight babysit --prs <url1>,<url2> --fail-on-action (exit 3 when action is needed)
# Verified PR evidence pack: guard + CI triage + review triage + protocol
# status of linked issues, in one markdown document where every claim
# cites its source. The test delta comes from a verify report you pass in.
npx @reneturcios/greenlight evidence https://github.com/acme/widgets/pull/42 --out EVIDENCE.md
# or: greenlight evidence <pr-url> --verify-json verify.json
# Contributor passport: protocol claims from the public Claim Ledger plus
# merged PRs from GitHub. No Ledger file yet? It says so plainly.
npx @reneturcios/greenlight passport CloudCorpRecords
# The proxy, for authenticated reads (60/hr anonymous -> 5000/hr token):
# reads GITHUB_TOKEN once at startup, attaches it server-side, binds
# 127.0.0.1 only, and refuses to start without a token.
export GITHUB_TOKEN=<your-classic-token> && greenlight proxy &
export GREENLIGHT_GITHUB_BASE_URL=http://127.0.0.1:8792 GITHUB_TOKEN=proxy
# Verify every link of a release chain (tag, commit, release, npm, registry)
npx @reneturcios/greenlight shipcheck <owner/repo> --version x.y.zReal examples from our vetting:
batrapulkit/squidbrake#74scores GO: 0 comments, labeled help wanted, no claims, no gates.shadcn-labs/pdfcn#58scores RISKY (claimed flag): a volunteer asked for assignment the same day we vetted it.langchain-ai/langchain#41185scores TAKEN (claim race): 3 strong claimants while still "unassigned".PrefectHQ/fastmcp#5718scores GATED: FastMCP requires assignment or a "prs welcome" label before a PR.triggerdotdev/trigger.dev#5016scores GATED: unvouched-author PRs are auto-closed, a vouch request goes first.
The same engine is exposed over stdio for coding agents (Claude, Cursor, Cline). The wedge: agents waste the most tokens fixing already-taken issues. Have the agent pre-flight the issue before writing code.
{
"mcpServers": {
"greenlight": {
"command": "npx",
"args": ["-y", "@reneturcios/greenlight", "mcp"],
"env": { "GITHUB_TOKEN": "your-token" }
}
}
}Tools (27):
check_issue- verdict for one issue URLscan_repo- rank a repo's open issues, GO first (label-tagged starter issues, falling back to recent open unassigned issues;deep: truetimeline-x-rays the candidates first)xray_issues- Timeline X-Ray: deep-verify candidate issues against their timelines (hidden in-flight PRs, reporter-owned fix PRs, comment claims); GO / RISKY / TAKEN per issue with PR evidencerepo_friction- friction score for a repoclaim_issue- verdict-gated claim comment (dry run unlessexecute: true)prep_issue- fork and branch check plus a local PREP.md checklist with the repo's learned conventions (dry run unlessexecute: true)open_pr- DCO-aware PR opening from a fork branch (dry run unlessexecute: true)ci_prep- run a repo's own PR checks locally before pushing (exit 1 on NO-GO)ci_triage- classify each failing check on a PR as pre-existing, likely-yours, indeterminate (with a stated lean), or external-blocker, by comparing against the base branch's recent check historyreview_triage- triage the review feedback on your PR: each finding classified likely-real / likely-noise / needs-decision with its reason and a reply draft (humans are never called noise; drafts only, nothing posted)pr_brief- verified review brief for any PR: files grouped by area/risk, CI triage against base-branch history, findings classified real vs false-positive with evidence, test evidence present or explicitly marked absent, merge blockers, and a one-line look-at-this-first (never invents findings)guard_pr- maintainer-side analysis of an incoming PR: competing fix, prior claims by someone other than the author, missing artifacts (changeset / DCO / CLA), first-time contributor. Returns comment-ready markdown (never posts).repo_digest- repo-level maintainer report: PR races with first-claim arbitration, claimed-by-other conflicts, stale claims, assignment-gate conflicts, triage-held issues (never posts).pr_radar- maintainer-side duplicate/competing PR radar: clusters a repo's open PRs into competing sets (same target issue, or high changed-file overlap) with evidence per cluster and a suggested keep (always labeled a heuristic, never a verdict; never posts).claim_status- Claim Protocol pre-flight for one issue: who holds it, until when, who is queued, competing PRs, gates, whether the repo honors the protocolpreflight- the one-call answer: claim_status plus the repo friction summaryverify_comment- draft the verified-finding comment for maintainer-only repos (draft only, never posts)babysit_prs- watch open PRs and get the one prioritized action list (needs you now, waiting on them, quiet), diffed against stored watermarks; also watches the my-claims registry (linked, healthy-active, heartbeat-due, expiring, unlinked-stale, queue-lost)evidence_pack- the Verified PR evidence pack for one PR: guard verdict, CI triage, review triage, protocol status of linked issues, every claim citing its sourcescout_campaign- campaign mode: rank repo targets, dedupe against the campaign file, resume on API-budget exhaustionmy_claims- the claims registry: linked, healthy-active, heartbeat-due, expiring, unlinked-stale, queue-lostsync_campaign- reconcile local tracking with API truth (drift, state mismatches, stale claims)campaign_portfolio- one-screen campaign summary: census counts, claims by state, pending queue, drift countautopilot_report- per-PR feedback classification (read-only; verify bot findings, triage CI, mechanical fixes as plans)api_status- hosted claim API statusclaim_via_api- claim through the hosted claim APIheartbeat_via_api- heartbeat through the hosted claim API
Run it locally: npm run dev (MCP entry is src/index.ts; CLI is src/cli.ts).
The verdict engine is deterministic (no LLM) and checks, in order:
- Closed issue: TAKEN (never landable).
- Any assignee: TAKEN.
- An open linked PR that closes the issue: TAKEN. A PR that merely mentions the issue number (like pdfcn PR #91, which closes #70 but lists sibling issues in its body) only adds a
weak-pr-mentionflag and downgrades an otherwise-GO verdict to RISKY. Marked a duplicate of an issue closed as completed: RISKY with theduplicate-of-closedflag (the work already shipped; a still-open duplicate target only adds aduplicate-of-openwarning with its URL). - Two or more strong claimants: TAKEN (claim race).
- One strong fresh whole-issue claim (under 45 days): RISKY with the
claimedflag. A fresh claim scoped to part of the issue ("taking the remaining fallback ask"): RISKY withclaimed+partial-claimflags and a reason naming the claimer and the scope, never TAKEN. - One strong claim older than 45 days with no closing PR: RISKY with the
stale_claimflag. The claimant probably walked away, but nobody knows for sure. Stale scoped claims get the same treatment. - A hard gate (assignment, vouch, collaborators-only, paused unsolicited PRs, external PRs auto-closed by workflow) with nobody assigned: GATED. The last two come from CONTRIBUTING language ("paused unsolicited pull requests") and a scan of
.github/workflowsfor close-external-PR automation. - No activity for 180+ days: STALE.
- A soft claim-first gate (the repo asks contributors to comment before starting, like pdfcn): never GATED; it caps an otherwise-GO verdict at RISKY with a note, the same downgrade shape as a weak PR mention.
- Otherwise: GO.
- An open PR referenced in a non-author comment whose title/body mentions the issue number: downgrades an otherwise-GO verdict to RISKY with the
comment-mentioned-prflag ("may already cover part of this issue"). Neither can produce TAKEN; only closing PRs do that. Fix-announcement comments ("/attempt #N" commands or "Submitted fix for ... in " narratives, often linking PRs in sibling repos) get the same downgrade under their own reason quoting the PR URL, with theattempt-linked-prflag, even when the PR never names the issue./attemptcomments also register as strong claims. - Partially-addressed: merged PRs that reference the issue number (comment-mentioned or linked), or maintainer comments signaling part of the work already shipped ("Half addressed by #905, leaving this open for half B", "Shipped in v3.1.0" next to the issue reference). A plain GO hides the scoping work this needs, so the flag
partially-addressedis added, an otherwise-GO verdict is capped at RISKY with a reason like "part of this issue already shipped (PR #905, merged); scope your work to what remains". Never TAKEN.
Friction score starts at 100 and subtracts gate weights (assignment -25, vouch -35, collaborators-only -50, paused unsolicited PRs -40, external PRs auto-closed -50, discussion-first -10, claim-first -5, CLA/DCO -5 each), adjusts for external PR merge rate and review/response times when computable, and adds up to +10 for open good-first-issues. Unknown signals stay null and are skipped, never guessed. See src/friction.ts for the exact formula.
Policy files are read where repos actually keep them: AGENTS.md, CLAUDE.md, CONTRIBUTING.md, and AI_POLICY.md at the repo root, in .github/, and in docs/ (first hit per filename wins), plus the org-level .github/AI_POLICY.md. Two gate kinds parse agent rules:
agents_bannedis a hard gate: a repo that bans autonomous-agent contributions scores GATED, with the quoted policy line as evidence, andclaimrefuses it like TAKEN unless--force.agents_disclosureis a flag, never a verdict change: repos that require an AI prefix or disclosure get concrete required actions fromprepandcheck.
A bot triage notice ("wait until maintainers remove the triage or approval label before opening a pull request") or a triage label marks an issue as held: check names the hold and caps an otherwise-GO verdict at RISKY with the triage-hold flag (never TAKEN), and scan demotes held issues below clean ones. Held issues are future pipeline, not current work.
The pattern layer cannot know every way a human says "I'm taking this" (one evening it missed "I'm looking into contributing a fix here" on a real issue). Set FIREWORKS_API_KEY and check gains an optional second pair of eyes: a cheap Fireworks model reads the eligible comments (bots and the issue author excluded, same pool as the patterns) and flags statements of intent the patterns missed.
The governance is plain:
- Off by default. No key, no calls, output byte-identical to the pattern-only engine.
- Patterns stay primary and cheaper. The AI only runs when they found no strong claim.
- Flags, never verdicts. An AI flag adds the
llm-claimflag with the exact quote as evidence and downgrades an otherwise-GO verdict to RISKY. It can never produce TAKEN and never overrides GATED. Verdicts stay deterministic. - No invented evidence. The quote must be an exact substring of the comment body; anything else is dropped before it can reach the verdict.
- Failures are silent. A timeout, a non-200 response, or an unparseable reply returns no signal, never an error into the check path. Classifications are cached by comment id and model id, so repeat checks cost nothing.
greenlight doctor reports whether the layer is configured (the key is never printed).
Greenlight automates the contribution pipeline its author ran by hand for four real PRs (shadcn-labs/pdfcn #92-#95): verdict, claim comment, fork branch, and opening the PR, with DCO awareness throughout.
# 1. Claim the issue: verdict first, comment shaped by the repo's gates
greenlight claim https://github.com/shadcn-labs/pdfcn/issues/65
# 2. Prepare: fork/branch check (learning the repo's branch convention) plus a PREP.md checklist
greenlight prep https://github.com/shadcn-labs/pdfcn/issues/65 --dir /tmp/prep65
# 3. Open the PR from your fork branch (verifies DCO sign-off on DCO repos)
greenlight pr https://github.com/shadcn-labs/pdfcn/issues/65 --branch feat/quarterly-report-blockSafety defaults, and this is a feature:
- Dry run by default. All three commands print exactly what they would
post or create and exit. Nothing is posted or created without
--yes(CLI) orexecute: true(MCP). - Writes need a token. Read ops work with no token at all. Write ops
require
GITHUB_TOKEN(orGH_TOKEN); without one they print a clear error naming the env var and exit non-zero. - Verdict-gated.
claimrefuses TAKEN or STALE verdicts unless--force, and refuses vouch-gated repos outright (a vouch cannot be automated). Assignment-gated repos get an assignment request instead of an intent comment; claim-first repos (comment before starting) get the standard intent comment, which satisfies the ritual. - Repo-aware branch names.
prepreads the head branches of recent closed PRs and follows a dominant convention (pdfcn'sfeat/<slug>-block) while still showing thefeat/<slug>-<number>default. - DCO-aware. On DCO repos,
prverifies every commit on the branch carries aSigned-off-by:line and refuses, listing the unsigned commits, when one is missing. - Repo-aware prep.
prepalso learns the repo's contribution rituals for the PREP.md checklist: which house-rules files exist, the verify command they insist on (likepnpm verify), whether the repo assembles its changelog from a.changes/directory, which root package.json scripts exist, and whether recent commits follow Conventional Commits. Binding rules increasingly live inAGENTS.mdrather than CONTRIBUTING, and prep reads those too.
Greenlight is the front door of a four-tool lifecycle for open-source contribution work, all published under the same npm scope and cross-wired:
- gatefile (
npx @reneturcios/gatefile extract owner/repo) extracts a repo's contribution gates into a committedcontribution-gates.json. Greenlight consumes that file directly:greenlight check <issue-url> --gates-file contribution-gates.json, or automatically when the file sits in the working directory, so gates are answered once and reused instead of re-derived from prose. - greenlight verdicts, scans, claims, prep, and PR opening (this tool).
- claimcheck (
npx @reneturcios/claimcheck claims owner/repo) watches claimed issues for stale claims and finished fixes parked on forks, the two ways claimed work silently dies. - prwatch (
npx @reneturcios/prwatch attention --user you) triages your open PRs by what needs you right now: review threads, failing checks, conflicts, reviewer silence.
Each tool is a CLI and an MCP server (<tool> mcp).
data/friction-index.json is a checked-in, growing dataset of scored repos. It starts with the MCP/AI ecosystem we hand-vetted on 2026-10-13 (FastMCP, trigger.dev, langchain, deepagents, openclaw, squidbrake, reticle, pdfcn, chatflow-agent, and the three MCP SDK repos). Regenerate it with npm run index.
Entries labeled hand-verified 2026-10-13 come from reading the repos' actual policies and issue trackers by hand. Entries labeled live were parsed from live house-rules files (CONTRIBUTING variants, AGENTS.md, CLAUDE.md). Each gate records which file its evidence came from. Computed outcome fields (merge rates, review times) stay null until we can compute them honestly, never fabricated.
The published page (cloudcorprecords.github.io/greenlight) adds the Agent Policy Index: 505 repos evaluated for contribution gates and AI policies, with quoted evidence per entry. Nobody else publishes this map.
npm test # tsx --test, includes fixture tests that reproduce our real verdicts
npm run buildClearly marked: these are not shipped yet. (v0.15.0 moved two roadmap items into the product: radar is duplicate/competing PR clustering, and brief is the verified review brief for any PR.)
- Maintainer control room.
guardworks per PR andradarclusters the queue (both shipped); the control room is the hosted per-repo surface built on top: stale-claim sweeps with one-click release requests, first-time-contributor risk notes, and a weekly maintainer digest. The engine pieces exist; the product is the assembly plus hosting. - Policy enforcement packs. Repos keep inventing the same rules (changeset required, release note required, DCO, AI disclosure). A policy-pack format (built from
gatefileoutput) that a maintainer adopts in one file, enforced by the Action with the same quoted-evidence style. - AI PR volume defense. The filter, not the ban:
guardscoring incoming PRs for claim legitimacy, repro evidence, and test deltas, so maintainers can keep the door open to good agent work while filtering spam. The campaign data (refused claims, honest verify, evidence packs) is the proof set. - Claim arbitration as a service. Two claims, one queue, public ordering, maintainer override: live arbitration of competing claims, the piece maintainers cannot build themselves.
- Browser extension that scores issues inline on github.com.
- Parked-fix detection and auto-nudges: scan forks for branches referencing open issues and nudge when the gate is satisfied.
Full release history lives in CHANGELOG.md.
MIT. See LICENSE.
