Code review is the one quality control almost every engineering team agrees on. It is in the onboarding docs, it is in the branch protection rules, and it is the first thing anyone points at after an incident. So we went and measured how much of it actually happens on the most-starred projects on GitHub - the ones whose practices the rest of the industry copies.
Across 164 projects and 64,435 merged pull requests in August 2026, 53.4% of human-authored changes reached the default branch without another person approving them. 37.8% got no review of any kind - not an approval, not a comment, not even a bot. 60% were merged by the same person who opened them.
That is not a scandal, and the point of this is not to embarrass anyone. Open source runs on maintainers with commit rights and a great deal of earned trust, and a one-line version bump does not need a formal sign-off. But it is a useful mirror. If the projects with the most eyes on them merge like this, the quiet assumption that your own team's review process is working because it exists deserves a second look - and unlike these repositories, nobody is publishing your numbers.
What we measured, and what it does not say
GitHub records four things about every merged pull request that we can read back: who opened it, who merged it, every review it received with the reviewer's identity and verdict, and the timestamps at both ends. That is enough to ask a narrow, answerable question - did anyone else sign off on this before it shipped? - without guessing at anything the data does not contain.
What “no human approval” means, exactly
No review in the APPROVED state from a person who is neither a bot nor the author. GitHub does not let you approve your own pull request, so this is a real second pair of eyes or it is nothing. It is not proof nobody read the diff - an approval is a signal, not a guarantee - but it is the strongest signal GitHub records, and the only one you can check yourself on any of the repositories named below.
The busiest projects review the least
The single most useful number here is not the average, it is the gap between two averages. Pooled across every pull request, 53.4% merged without a human approval. But the median project in the same sample sits at 16.7%. When those two diverge that hard, it means a small number of very high-volume projects are doing something different from everyone else.
They are. Split the sample by how much it merges:
| Merged PRs / month | Projects | No human approval | Self-merged | Bot reviewed |
|---|---|---|---|---|
| 100-249 | 47 | 34.1% | 48% | 29.7% |
| 250-499 | 19 | 27% | 47.6% | 18.9% |
| 500-999 | 17 | 41.1% | 52.7% | 36.9% |
| 1,000+ | 15 | 70% | 69.9% | 36.9% |
Projects merging 1,000+ pull requests a month land 70% of them with no human approval - roughly double the rate of the mid-volume band. It is not a clean gradient, and we will not pretend it is: the smallest band here sits above the next one up. But the busiest projects are plainly different from everything below them, and they carry the most pull requests, which is why they dominate the pooled figure and why quoting that figure alone would be misleading.
Throughput and scrutiny are not naturally in tension. But in this sample, the projects that ship the most are the ones that check the least.
How concentrated this is, before you quote the pooled number
Merge volume is not spread evenly. openclaw/openclaw alone accounts for 17.2% of every human-authored merged pull request in this sample - 10,071 of them - and it merges 99.4% of those without a human approval. The five busiest projects are 31.1% of the total between them.
That is why the pooled 53.4% and the median project's 16.7% are so far apart, and why we would rather you quoted the second one, or the band table, than the first. A pooled average over a population this skewed is not wrong; quoting it without saying how skewed the population is would be.
Two ways to merge a thousand pull requests a month
The high-volume band is not uniform, and that is the encouraging part. Among the busiest projects in the sample, microsoft/vscode merged 1,562 human-authored pull requests with just 0.7% lacking a human approval, and home-assistant/core managed 1,778 at 4.3%. Enormous throughput is clearly compatible with near-total review discipline.
At the other end sit a cluster of projects with a common thread. Reading their own GitHub descriptions: anomalyco/opencode is “the open source coding agent” (99.7% merged with no human approval), stablyai/orca is an environment for “a fleet of parallel agents” (97.9%), NousResearch/hermes-agent is “the agent that grows with you” (97.1%), and unslothai/unsloth trains and runs LLMs locally (94.1%). The projects building autonomous coding agents are, so far, the ones merging with the least human sign-off - which may be the point, or may be worth a conversation inside those teams.
One entry needs a caveat rather than a raised eyebrow. firstcontributions/first-contributions shows 100% and is a tutorial repository that exists so beginners can practice opening a pull request. It clears the sample rule honestly, but it is not an engineering project and should not be read as one. A handful of other high-star entries are awesome-lists and course material rather than software.
The bot column moves with volume too. In the busiest band, 36.9% of merges drew at least one bot review, against 10.4% for the median project. vscode is the clearest case: 99.7% of its merges were bot-reviewed and 92.8% were merged by their own author - and yet almost all of them carried a human approval too. Which is the shape you want, and a good reminder that self-merge on its own tells you very little.
The full index
Every project in the sample that merged at least 100 human-authored pull requests in August 2026. Sort by any column, or search for the one you care about - the point of publishing it this way is that you can go and check your own dependencies rather than take our word for the pattern.
98 projects
| firstcontributions/first-contributions | 55,803 | 1,700 | 100% | 95.5% | 0% | 90.5% | 4.2% |
|---|---|---|---|---|---|---|---|
| open-webui/open-webuiPython | 150,783 | 202 | 100% | 98% | 2% | 4% | 1.5% |
| commaai/openpilotPython | 63,558 | 145 | 100% | 96.6% | 82.1% | 20% | 0% |
| dockur/windowsShell | 53,149 | 142 | 100% | 75.4% | 100% | 57% | 24.6% |
| remotion-dev/remotionTypeScript | 58,169 | 598 | 99.8% | 8.9% | 88.1% | 2% | 91.1% |
| anomalyco/opencodeTypeScript | 203,398 | 1,331 | 99.7% | 89% | 95.8% | 9.9% | 10.4% |
| lobehub/lobehubTypeScript | 82,189 | 731 | 99.6% | 33.7% | 95.5% | 4.2% | 65.9% |
| openclaw/openclawTypeScript | 388,702 | 10,071 | 99.4% | 97.5% | 86.5% | 0.7% | 1.5% |
| paperclipai/paperclipTypeScript | 79,920 | 599 | 98.3% | 36.2% | 87.8% | 4% | 62.9% |
| stablyai/orcaTypeScript | 60,463 | 1,925 | 97.9% | 34.2% | 90.5% | 4.4% | 65% |
| NousResearch/hermes-agentPython | 240,455 | 2,700 | 97.1% | 93.2% | 89.1% | 9.4% | 0.6% |
| public-apis/public-apisPython | 474,765 | 103 | 96.1% | 89.3% | 0% | 0% | 1.9% |
| earendil-works/piTypeScript | 101,278 | 144 | 95.1% | 87.5% | 50.7% | 9% | 0% |
| unslothai/unslothPython | 75,538 | 1,368 | 94.1% | 30.3% | 64.5% | 4.2% | 67.6% |
| oven-sh/bunRust | 95,862 | 1,031 | 92.7% | 0.2% | 23.1% | 2.6% | 99.6% |
| LadybirdBrowser/ladybirdC++ | 65,989 | 421 | 85.3% | 35.9% | 69.4% | 0% | 54.2% |
| rails/railsRuby | 58,749 | 190 | 81.6% | 61.6% | 31.1% | 0% | 1.1% |
| neovim/neovimVim Script | 102,082 | 279 | 81.4% | 61.6% | 56.6% | 0.7% | 1.1% |
| infiniflow/ragflowGo | 89,974 | 1,008 | 79.1% | 10.2% | 14.2% | 1.2% | 73.7% |
| Significant-Gravitas/AutoGPTPython | 187,095 | 128 | 78.9% | 3.9% | 90.6% | 0.8% | 93% |
| TryGhost/GhostJavaScript | 55,134 | 527 | 77.8% | 40.6% | 89.8% | 0.8% | 48.6% |
| kubernetes/kubernetesGo | 125,948 | 150 | 76% | 27.3% | 0% | 0% | 2% |
| webpack/webpackJavaScript | 65,959 | 218 | 75.2% | 13.3% | 76.1% | 1.8% | 72.5% |
| github/spec-kitPython | 133,213 | 130 | 74.6% | 0.8% | 23.8% | 11.5% | 99.2% |
| tldraw/tldrawTypeScript | 50,100 | 304 | 74.3% | 56.2% | 89.8% | 0.7% | 27.6% |
| nuxt/nuxtTypeScript | 60,811 | 121 | 72.7% | 46.3% | 73.6% | 0.8% | 33.9% |
| MemPalace/mempalacePython | 58,821 | 132 | 72% | 29.5% | 40.2% | 7.6% | 43.2% |
| career-ops-hq/career-opsJavaScript | 69,985 | 544 | 71.7% | 18% | 7.9% | 0.6% | 75% |
| coollabsio/coolifyPHP | 61,339 | 166 | 70.5% | 48.2% | 56% | 20.5% | 22.3% |
| langchain-ai/langchainPython | 145,567 | 148 | 66.2% | 4.7% | 69.6% | 18.2% | 82.4% |
| rust-lang/rustRust | 116,983 | 952 | 60.2% | 37.2% | 0% | 0% | 0.2% |
| python/cpythonPython | 75,593 | 976 | 54.7% | 51.9% | 28.3% | 0% | 0.1% |
| ghostty-org/ghosttyZig | 60,637 | 282 | 53.2% | 52.1% | 47.2% | 1.4% | 1.1% |
| cline/clineTypeScript | 67,392 | 353 | 51.6% | 23.5% | 77.6% | 5.1% | 49.3% |
| headroomlabs-ai/headroomPython | 68,709 | 281 | 51.6% | 45.2% | 38.4% | 0.7% | 23.8% |
| TanStack/queryTypeScript | 50,255 | 131 | 49.6% | 35.1% | 52.7% | 4.6% | 31.3% |
| denoland/denoRust | 108,358 | 152 | 49.3% | 39.5% | 69.1% | 0% | 0% |
| twentyhq/twentyTypeScript | 56,117 | 657 | 46.7% | 5.2% | 88% | 1.7% | 82.3% |
| langflow-ai/langflowPython | 154,170 | 325 | 43.7% | 20% | 74.8% | 6.8% | 67.7% |
| cypress-io/cypressTypeScript | 51,022 | 193 | 42.5% | 1% | 89.6% | 1% | 75.6% |
| penpot/penpotClojure | 59,529 | 192 | 41.1% | 37% | 63.5% | 1.6% | 0% |
| swiftlang/swiftSwift | 70,318 | 500 | 40% | 33.8% | 88.2% | 5.8% | 0% |
| bitcoin/bitcoinC++ | 90,082 | 149 | 35.6% | 6.7% | 5.4% | 0% | 0% |
| elastic/elasticsearchJava | 77,883 | 1,546 | 34% | 32.2% | 71.2% | 0.6% | 6.1% |
| dbeaver/dbeaverJava | 51,640 | 163 | 31.3% | 19.6% | 22.1% | 0% | 11% |
| huggingface/transformersPython | 164,740 | 270 | 30.7% | 25.2% | 57.8% | 3.3% | 4.8% |
| appwrite/appwriteTypeScript | 57,267 | 226 | 30.1% | 21.2% | 89.8% | 4% | 25.7% |
| netdata/netdataGo | 80,417 | 203 | 28.1% | 9.4% | 74.9% | 4.4% | 67.5% |
| astral-sh/uvRust | 89,387 | 158 | 24.1% | 21.5% | 66.5% | 0.6% | 2.5% |
| vitejs/viteTypeScript | 82,661 | 106 | 21.7% | 12.3% | 31.1% | 0.9% | 8.5% |
| ggml-org/llama.cppC++ | 126,872 | 510 | 16.3% | 13.9% | 41.2% | 2.9% | 5.7% |
| ant-design/ant-designTypeScript | 99,370 | 178 | 13.5% | 0.6% | 21.9% | 0% | 52.2% |
| ultralytics/ultralyticsPython | 61,239 | 274 | 12.8% | 0.7% | 26.6% | 1.5% | 2.6% |
| opencv/opencvC++ | 90,704 | 112 | 11.6% | 6.2% | 6.2% | 0% | 29.5% |
| zed-industries/zedRust | 89,690 | 394 | 10.9% | 9.6% | 48.2% | 0% | 2% |
| apache/supersetPython | 74,608 | 505 | 10.7% | 1% | 50.5% | 0% | 63.8% |
| angular/angularTypeScript | 101,001 | 268 | 7.8% | 7.8% | 10.4% | 5.6% | 0% |
| Comfy-Org/ComfyUIPython | 131,295 | 166 | 7.2% | 1.8% | 51.8% | 8.4% | 94% |
| scrapy/scrapyPython | 64,180 | 152 | 7.2% | 6.6% | 27% | 3.9% | 0% |
| nexu-io/open-designTypeScript | 93,757 | 387 | 6.7% | 4.4% | 53% | 2.8% | 7.8% |
| vllm-project/vllmPython | 90,868 | 1,232 | 6.6% | 0% | 15.1% | 0.6% | 98.6% |
| storybookjs/storybookTypeScript | 90,989 | 199 | 6.5% | 1.5% | 80.4% | 2% | 76.4% |
| n8n-io/n8nTypeScript | 203,208 | 1,079 | 6.4% | 3% | 89% | 1.5% | 92.8% |
| bytedance/deer-flowPython | 81,304 | 188 | 5.3% | 3.2% | 3.7% | 0% | 29.3% |
| expo/expoTypeScript | 52,002 | 588 | 4.9% | 3.7% | 74.1% | 1.9% | 7% |
| microsoft/PowerToysC | 138,333 | 134 | 4.5% | 1.5% | 48.5% | 1.5% | 36.6% |
| home-assistant/corePython | 90,223 | 1,778 | 4.3% | 0% | 16.6% | 0.7% | 97.8% |
| BerriAI/litellmPython | 57,921 | 1,267 | 3.9% | 0.6% | 85.1% | 1% | 76.5% |
| aaif-goose/gooseRust | 53,871 | 300 | 3.7% | 0.7% | 44.7% | 0% | 59.3% |
| freeCodeCamp/freeCodeCampTypeScript | 454,935 | 276 | 3.3% | 1.1% | 5.1% | 0% | 6.2% |
| OpenHands/OpenHandsTypeScript | 86,050 | 153 | 3.3% | 0% | 54.9% | 0% | 7.2% |
| mozilla/pdf.jsJavaScript | 53,818 | 130 | 3.1% | 2.3% | 46.9% | 1.5% | 1.5% |
| warpdotdev/warpRust | 64,763 | 100 | 3% | 0% | 77% | 0% | 100% |
| grafana/grafanaTypeScript | 76,559 | 1,018 | 2.9% | 0.3% | 90.6% | 0.1% | 40.5% |
| CherryHQ/cherry-studioTypeScript | 51,396 | 856 | 2.9% | 2% | 44.6% | 1.2% | 28.4% |
| DefinitelyTyped/DefinitelyTypedTypeScript | 51,420 | 105 | 2.9% | 2.9% | 6.7% | 0% | 1.9% |
| strapi/strapiTypeScript | 73,064 | 103 | 2.9% | 1.9% | 58.3% | 0% | 6.8% |
| crewAIInc/crewAIPython | 58,036 | 108 | 2.8% | 0% | 74.1% | 6.5% | 72.2% |
| godotengine/godotC++ | 116,542 | 374 | 2.7% | 1.1% | 7% | 0% | 0% |
| Stirling-Tools/Stirling-PDFJava | 91,214 | 190 | 2.1% | 1.1% | 51.1% | 0.5% | 30% |
| langgenius/difyTypeScript | 154,307 | 832 | 1.8% | 1.6% | 60.3% | 1.7% | 3% |
| vercel/next.jsJavaScript | 142,073 | 491 | 1.8% | 0.4% | 84.1% | 0.2% | 17.7% |
| withastro/astroTypeScript | 62,251 | 139 | 1.4% | 1.4% | 38.1% | 2.2% | 10.8% |
| flutter/flutterDart | 178,744 | 669 | 1.3% | 0% | 9.3% | 0% | 70.1% |
| JetBrains/kotlinKotlin | 53,363 | 540 | 1.3% | 0.2% | 1.1% | 0% | 1.5% |
| go-gitea/giteaGo | 57,792 | 267 | 1.1% | 0% | 31.8% | 0.4% | 15.4% |
| supabase/supabaseTypeScript | 108,776 | 503 | 1% | 0.4% | 84.3% | 0% | 69.2% |
| electron/electronC++ | 122,848 | 292 | 1% | 1% | 43.2% | 0.7% | 2.1% |
| prometheus/prometheusGo | 65,932 | 119 | 0.8% | 0.8% | 23.5% | 0% | 2.5% |
| microsoft/vscodeTypeScript | 190,440 | 1,562 | 0.7% | 0.1% | 92.8% | 0% | 99.7% |
| immich-app/immichTypeScript | 113,322 | 222 | 0.5% | 0% | 55.4% | 1.8% | 2.3% |
| nodejs/nodeJavaScript | 120,250 | 408 | 0% | 0% | 10% | 0% | 3.9% |
| tldr-pages/tldrMarkdown | 63,572 | 209 | 0% | 0% | 13.9% | 0% | 0.5% |
| tensorflow/tensorflowC++ | 198,352 | 167 | 0% | 0% | 0% | 0% | 92.2% |
| mastodon/mastodonRuby | 50,265 | 163 | 0% | 0% | 81.6% | 0% | 0.6% |
| microsoft/playwrightTypeScript | 95,562 | 139 | 0% | 0% | 81.3% | 2.2% | 2.9% |
| moby/mobyGo | 72,034 | 135 | 0% | 0% | 23% | 0% | 31.1% |
| nocodb/nocodbTypeScript | 64,815 | 118 | 0% | 0% | 28% | 13.6% | 0% |
A few things worth doing with it. Sort by No approval descending for the projects merging with the least human sign-off, then sort ascending for the opposite end - the projects that almost never merge without one, several of which are also among the busiest. Sort by Bot reviewed to see how far AI reviewers have spread, which is the column we expect to look completely different a year from now. And sort by Self-merged to see how weak that signal is on its own: it runs high across projects with excellent and poor approval rates alike.
Our take
What stays with us is the distance between what a review policy says and what the merge log shows, in projects with tens of thousands of contributors watching. A branch protection rule is a statement of intent. The merge log is the record of what actually happened.
We would not tell any of these maintainers to change a thing. Trust earned over years is a legitimate substitute for process, and the projects at the top of the self-merge table are frequently the healthiest in the sample. What we would say is this: whatever your review numbers are, you should know them. Most teams assume theirs are fine because the policy exists, and the policy is not the measurement.
A merge with no approval is not evidence of carelessness. A team that cannot say how often it happens is a different matter.
The bot-review column is the one we expect to age fastest. AI reviewers are now leaving reviews on a meaningful share of merges in this sample, and every one of them raises the same question a human reviewer does not: was the change actually scrutinized, or did something merely comment on it? We count bots separately for that reason, and we would encourage anyone quoting these figures to keep the two apart. It is the difference between a colleague disagreeing with you and a linter having an opinion.
Methodology
Every figure here comes from GitHub's own GraphQL API, queried directly for August 2026. That matters, because the obvious alternative does not work. The public GH Archive event feed is the usual source for studies like this, and we started there - but GitHub stripped the analytical fields from event payloads on 7 October 2025, and even before that the archive carried only a fraction of merge events. On one spot check it held 26 of the 48 pull requests GitHub reports as merged in microsoft/vscode that day, with the misses spread through the day rather than bunched at the edges. A rate computed over an incomplete sample of unknown bias cannot carry a headline, so we stopped using it.
The sample is organization-owned, not a fork, not archived, >=5,000 stars, pushed since 2026-08-01; top 250 by stars. It is chosen by rule rather than by hand so that the list is reproducible and nobody has to take our word for which projects were included.
For every merged pull request in the window we read who opened it, who merged it, every review it received, each reviewer's identity and each review's state. A review counts as human only if its author is not a bot account and not the pull request's own author. Bot-authored pull requests are excluded from the review measures and reported separately: a dependency bot merging its own version bump is an automation policy, not a review practice.
Rates are pooled - the sum of numerators over the sum of denominators - so a project merging thousands of pull requests counts for more than one merging twenty. Medians across projects are given separately and labelled: the median project in this sample merged 16.7% of its pull requests without a human approval, against 53.4% of all pull requests pooled. Where those two diverge, the difference is telling you that the busiest projects behave differently from the typical one.
Named leaderboards require at least 100 human-authored merged pull requests. A project with twenty can reach 100% on any of these measures through one quiet week, and naming it as the worst offender would say more about our method than about its engineering. Personal accounts are excluded from the sample entirely.
Four things this does not measure. It cannot see private repositories, so it says nothing directly about how companies review internally. It cannot see conversation that happened outside the pull request, in a chat or over a desk. A formal approval is not proof that anybody read the diff - it is the strongest signal GitHub records, not a guarantee.
And it cannot see review that does not happen on GitHub at all. Several major projects in the star-ranked sample review elsewhere - golang/go runs on Gerrit, and others use mailing lists or Phabricator - so they register zero merged pull requests here and drop out below the volume floor. That is an absence of GitHub pull requests, not an absence of review, and it is why a project missing from these tables should never be read as a finding.
Frequently asked questions
Does "no human approval" mean nobody looked at the code?
Why are bot reviews counted separately?
Why exclude bot-authored pull requests?
Why these projects and not others?
Is a high self-merge rate a problem?
Are these projects doing something wrong?
Can this be reproduced?
Where does your team sit?
These three signals - merges with no review comment, merges by their own author, merges too fast to have been read - are the ones that matter on private repositories too. CodePulse tracks all three per repository and per team, so you find out before an incident does. Five-minute setup, flat pricing, no per-seat billing.
Start free