A standalone CLI tool and GitHub Action that detects AI-generated contributions in git repositories. It works entirely from git-level data (commit emails, messages, trailers) using go-git, with no platform API dependencies in the core. A separate text-scanning mode lets wrappers pipe in PR descriptions, issue comments, or any other text.
The goal is to help open source maintainers understand when AI tools are involved in contributions, and to give community health projects like Augur and GrimoireLab a way to track AI usage across repositories.
Four detectors run against each commit, each producing findings at a confidence level:
High confidence -- strong signals that an AI tool authored or co-authored the commit:
- Known AI bot committer emails (Claude, Copilot, Cursor, Codex, Gemini Code Assist, Amazon Q, Devin, Cline, Continue.dev, Cody, JetBrains AI, CodeRabbit). Also matches on the numeric prefix of GitHub noreply emails, so bot username renames don't break detection.
Co-Authored-Bytrailers with known AI tool emails (Claude Code, Cursor, Aider).
Medium confidence -- patterns in the commit message itself:
aider:prefix (Aider's default commit format).Generated with Claude Codefooter.
Low confidence -- mentions of AI tool names in text:
- Word-boundary matches for tool names like Claude, Copilot, Cursor, Aider, ChatGPT, Windsurf, Devin, etc. This detector also runs against commit messages, and is the primary detector for the text-scanning mode (PR bodies, comments).
ai-detection scan [--range=BASE..HEAD] [--format=json|text] [--min-confidence=low|medium|high] [repo-path]
ai-detection text [--format=json|text] [--input=FILE|-]
ai-detection version
Exit codes: 0 = no AI detected, 1 = AI detected, 2 = error.
# Scan all commits in the current repo
ai-detection scan
# Scan a specific range, JSON output
ai-detection scan --range=abc123..def456 --format=json
# Only report high-confidence findings
ai-detection scan --min-confidence=high /path/to/repoReads from stdin by default, or from a file with --input:
echo "I used Claude to write this PR" | ai-detection text --format=json
ai-detection text --input=pr-body.txtThe exit code makes it usable in shell pipelines and CI scripts:
if ai-detection scan --range=$BASE..$HEAD --min-confidence=medium; then
echo "No AI detected"
else
echo "AI involvement detected"
fiAdd to your workflow to automatically label PRs with detected AI involvement:
- uses: chaoss/ai-detection-action/action@main
with:
label: 'ai-detected' # label to apply (default: ai-detected)
min-confidence: 'low' # low, medium, or high (default: low)
scan-pr-body: 'true' # scan PR description for tool mentions (default: true)The action builds the CLI from source, scans the PR's commits and optionally its body, then applies the configured label if anything is found. It exposes two outputs:
ai-detected--trueorfalsereport-- JSON object with the full findings from both the commit scan and text scan
The labeling logic lives entirely in the action layer. The CLI reports findings; the action decides what to do with them.
The detection packages can be imported directly into other Go projects:
go get github.com/chaoss/ai-detection-actionScan a repo's commits with the built-in detectors:
package main
import (
"fmt"
"github.com/chaoss/ai-detection-action/detection"
"github.com/chaoss/ai-detection-action/detection/coauthor"
"github.com/chaoss/ai-detection-action/detection/committer"
"github.com/chaoss/ai-detection-action/detection/message"
"github.com/chaoss/ai-detection-action/detection/toolmention"
"github.com/chaoss/ai-detection-action/scan"
)
func main() {
detectors := []detection.Detector{
&committer.Detector{},
&coauthor.Detector{},
&message.Detector{},
&toolmention.Detector{},
}
report, err := scan.ScanCommitRange("/path/to/repo", "base..head", detectors)
if err != nil {
panic(err)
}
fmt.Printf("%d commits, %d with AI signals\n", report.Summary.TotalCommits, report.Summary.AICommits)
for _, cr := range report.Commits {
for _, f := range cr.Findings {
fmt.Printf(" [%s] %s: %s\n", f.Confidence, f.Tool, f.Detail)
}
}
}Scan arbitrary text without a git repo:
findings := scan.ScanText("I used Claude to write this", detectors)You can also write your own detector by implementing the detection.Detector interface:
type Detector interface {
Name() string
Detect(input detection.Input) []detection.Finding
}Pass it alongside the built-in detectors and the scan functions will run it the same way.
go build -o ai-detection .Requires Go 1.24+.
go test ./...detection/ Core types: Detector interface, Finding, Confidence, Input
detection/committer/ Known AI bot committer emails
detection/coauthor/ Co-Authored-By trailer parsing
detection/message/ Commit message pattern matching
detection/toolmention/ AI tool name mentions in text
gitops/ go-git wrapper for reading commits
scan/ Orchestration: run detectors over commits or text
output/ JSON and human-readable text formatters
cmd/ CLI subcommands
action/ GitHub Action (composite action + labeling)
See CONTRIBUTING.md.