Window: Aug 2026 to Oct 2026Updated Nov 5, 2026

Methodology

The question is narrow on purpose: for each commit on a repository’s default branch, does the commit itself say an AI agent wrote it? Everything below is the whole definition. Nothing else is inferred.

The fraction

Numerator. Commits on the default branch, in the window, that match at least one rule below.

Denominator. All commits on the default branch in the window, minus automation commits, minus merge commits (two or more parents). Squash-merges count as one commit.

Each commit is classified once, in this order: merge, then automation, then AI, then human. The first that applies wins, so a bot-authored commit that carries a Claude trailer is automation.

The rules

From scanner/signatures.json, version 2026-11-01. The website runs these exact patterns.

AI attribution rules
Rule idToolWhat matchesAI commits
claude_trailerClaude

Co-authored-by trailer with an @anthropic.com address, claude[bot], or the name Claude Code

  • Co-authored-by trailer: @anthropic\.com or \bclaude\[bot\] or \bclaude[ -]?code\b
68,207
claude_generatedClaude

Footer 'Generated with [Claude Code]' / 'Generated by [Claude Code]' (any line wrapping)

  • Message body: generated\s+(with|by)\s+\[?claude\s+code\b
3,814
copilot_trailerGitHub Copilot

Co-authored-by trailer mentioning copilot; a Copilot-Session trailer; the footer 'Authored with GitHub Copilot'

  • Co-authored-by trailer: copilot
  • Message body: ^[ \t]*copilot-session:[ \t]*\S or authored with github copilot
13,208
copilot_authorGitHub Copilot

Author or committer login is a Copilot agent account

  • Exact login or name: copilot-swe-agent[bot] or copilot or github-copilot[bot] or copilot-pull-request-reviewer[bot]
1,222
codex_trailerCodex

Co-authored-by trailer mentioning codex, or a noreply@openai.com address

  • Co-authored-by trailer: \bcodex\b or noreply@openai\.com or chatgpt-codex-connector
1,716
cursorCursor

Cursor agent trailer, identity or bot (cursoragent, Cursor Agent, @cursor.com, cursor[bot])

  • Co-authored-by trailer: cursoragent or \bcursor agent\b or @cursor\.com or \bcursor\[bot\]
  • Message body: \bcursoragent@cursor\.com\b
  • Git author or committer name: ^cursor agent$ or ^cursoragent$
  • Exact login or name: cursor[bot]
4,086
devinDevin

Author/committer devin-ai-integration[bot], or a Devin AI trailer

  • Co-authored-by trailer: devin-ai-integration or \bdevin ai\b
  • Exact login or name: devin-ai-integration[bot]
824
geminiGemini / Jules

gemini-code-assist, google-labs-jules[bot] or gemini-cli as author or trailer

  • Co-authored-by trailer: gemini-code-assist or google-labs-jules or gemini-cli
  • Exact login or name: gemini-code-assist[bot] or google-labs-jules[bot]
126
aiderAider

Subject starts with 'aider:', an aider trailer, or a git identity ending in '(aider)'

  • Co-authored-by trailer: \baider\b
  • First line: ^aider:\s
  • Git author or committer name: \(aider\)\s*$
1
openhandsOpenHands

openhands or all-hands in a trailer or the git identity

  • Co-authored-by trailer: openhands or all-hands\.dev or \ball-hands\b
  • Git author or committer name: ^openhands\b
  • Exact login or name: openhands-agent[bot]
282
amp_factoryAmp / Factory

Amp (amp-ai, Sourcegraph Amp, @ampcode.com) or Factory (factory-droid) trailer or bot

  • Co-authored-by trailer: amp-ai or sourcegraph amp or @ampcode\.com or factory-droid
  • Exact login or name: factory-droid[bot]
185
other_bot_agentOther agent bot

Author login is an AI agent bot on the explicit AGENT_BOTS allowlist (not already claimed by a rule above)

  • Exact login or name: amazon-q-developer[bot] or chatgpt-codex-connector[bot] or claude[bot] or codegen-sh[bot] or coderabbitai[bot] or sweep-ai[bot] or tembo-io[bot]
500

All patterns are case-insensitive and multiline. A trailer is any line that matches ^[ \t>*-]*co-authored-by:[ \t]*(.+)$. Logins are compared exactly, in lowercase.

Left out of both sides

36 listed automation accounts.

Automation: all-contributors[bot], allcontributors[bot], autofix-ci[bot], bors[bot], changeset-bot[bot], crowdin-bot, deepsource-autofix[bot], dependabot, dependabot-preview[bot], dependabot[bot], dependency-update-bot, electron-roller[bot], github-actions, github-actions[bot], greenkeeper[bot], hosted weblate, imgbot[bot], kodiakhq[bot], lingohub[bot], mergify[bot], octokitbot, pre-commit-ci[bot], pyup-bot, pyup.io bot, release-please[bot], renovate-bot, renovate[bot], renovatebot, semantic-release-bot, snyk-bot, stainless-app[bot], stainless-bot, svc-renovate, transifex-integration[bot], trunk-io[bot], weblate, and any other login ending in [bot] that is not on the agent list. Merge commits are left out as well.

Limitations

  1. Signed-only, so every number is a floor.

    A commit counts only if it carries a signature: a trailer, a footer or an agent's own account. An agent that commits under the developer's identity with no trailer, or a developer who deletes the trailer, is invisible and counted as human.

  2. A commit is not a line of code.

    One commit that an agent wrote counts the same as one it touched lightly. The share is of commits, not of code, effort or value.

  3. Squash-merges count as one commit.

    When a pull request is squashed, the many commits behind it become one on the default branch. Only that commit's message is read, and it keeps a trailer only if the squash message does.

  4. Merge commits are excluded.

    Any commit with two or more parents is dropped from both sides of the fraction.

  5. Automation is excluded from both sides.

    Dependabot, Renovate, release bots, CI bots and pre-commit-ci are not people and not agents. They are recorded as automation and appear in neither the numerator nor the denominator. Any other account ending in [bot] that is not a known AI agent is treated the same way.

  6. Only the default branch.

    Work on other branches counts when, and only when, it reaches the default branch.

  7. Prose mentions never count.

    A commit that merely says the word claude, cursor or codex in its message is human. Rules match structure (a trailer, a footer, an exact login), not words, which also means the rules are deliberately narrow.

  8. A commit can match several rules.

    The per-rule counts count each match, so they can add up to more than the AI total.

  9. Incomplete scans are flagged.

    When the scanner hits its request budget on a large repository, the repository is marked incomplete and only its newest months are trustworthy. Its page says so.

  10. The universe is chosen, not random.

    Leaderboards cover the repositories with the most stars plus every repository someone has looked up on this site. They describe popular public projects, not all of GitHub, and private code is invisible. Rankings require at least 100 commits in the window.

  11. Live lookups read a shorter history.

    A badge or repo page for a repository outside the scanned set reads its newest 500 default-branch commits (200 when the site has no GitHub token), over whatever period that covers. It is not the same window as the leaderboard.

  12. User cards are a small sample.

    A user card reads up to 300 of the user's newest commits across their 10 most recently pushed public repositories, skipping forks. Work in organizations' repositories, private repositories, and older history is not seen.

  13. Lookups are logged.

    Every repository or username looked up here is appended to data/requests.log in the project repository so the nightly scan can add it to the universe. Nothing else about the visitor is recorded.

Reproduce it yourself

You need Python 3.11+ and a GitHub token with no special scopes.

git clone https://github.com/vijay-kapse/ghostwritten
cd ghostwritten/scanner
export GITHUB_TOKEN=ghp_yourtoken
python3 scan_repo.py owner/repo --fresh --months 2026-08..2026-10

# or the same rules over the last 500 commits, through this site's API
curl https://ghostwritten.vercel.app/api/repo/owner/repo

The scan writes data/repos/owner__repo.json and prints the share for the months you ask for. The numbers on this site come from the same files; they are committed in the data folder.