On this page
Policy guides¶
Two rules are off by default because they encode a decision only your project can make: whether contributors must certify the origin of their work, and whether AI assistance is welcome, disclosed, or refused.
Commit Check does not take a side on either. It gives you a way to enforce the position you have already taken, so it stops being relitigated in every review.
Require signoff (DCO)¶
Projects that use the Developer Certificate of Origin
require every commit to carry a Signed-off-by trailer. The Linux kernel and
much of the CNCF work this way.
A DCO bot rejecting a pull request after the fact is a poor experience: the contributor has to rewrite history for every commit in the branch. A local check catches a missing sign-off at commit time, before there is anything to rewrite.
Turn it on¶
This enables CC012, which is off by default.
Signing off¶
The trailer is appended automatically from your user.name and user.email:
Forgot it? Fix the last commit in place:
Fix a whole branch:
Make it automatic
Signing off is easy to forget. Combine this rule with the pre-commit hook so a missing trailer is caught at commit time, not at review time.
Identity matters¶
The DCO is a statement about who wrote the code, so it only means something if the identity is real. CC101 and CC102 check the author name and email, and are enabled by default when their check runs:
To require a company address:
To refuse GitHub's no-reply addresses, which cannot receive mail and can lose their link to the author's account after a username change:
Bots¶
Automation cannot meaningfully sign the DCO, and forcing it to produces meaningless trailers. Exempt bots instead:
ignore_authors matches the commit author and any Co-authored-by: trailers.
AI attribution¶
AI coding tools stamp their own trailers on the commits they help with.
Whether that is welcome, required or unacceptable is a decision each project
makes for itself, and the industry has landed in three places — which are the
three values ai_attribution takes:
ai_attribution |
The project's position | Rules |
|---|---|---|
"ignore" (default) |
no stated position | — |
"forbid" |
no AI attribution in the history | CC013 |
"disclose" |
AI is welcome, said out loud, and not credited as a person | CC014–CC016 |
Whichever you pick, the check reads what the message says. It cannot see assistance that left no trace — see the note below.
The default: no opinion¶
CC013 is off. Commits carrying AI trailers pass, and so do commits without them.
Forbidding AI-attributed commits¶
Commits carrying a recognised AI signature now fail:
CC013 ai-attribution check failed ==> Claude Code
AI attribution is forbidden in this project — detected: Claude Code
Suggest: This project does not accept AI attribution in commit messages. Remove the AI trailer lines and re-commit.
Docs: https://commit-check.com/rules/#cc013
Recognised signatures are co-author and sign-off lines naming Claude Code,
GitHub Copilot, Codex, Gemini, Cursor, Devin, Aider, Windsurf, Tabby, Amp,
OpenHands, Factory Droid, Jules, Continue, Mistral Vibe, Qwen Code, Warp and
Crush, credit trailers such as Reviewed-by: or Suggested-by: naming one of
those tools, the disclosure trailers Assisted-by: and
Generated-by:, vendor marks such as 🤖 Generated with Claude Code, Amp's
Amp-Thread-ID:, the Copilot coding agent's Agent-Logs-Url: and Cursor's
Made-with: Cursor, agent run links on their own line, and generic AI model
names; CC013 has the full list. This is the
position Kubernetes
takes — no AI trailers in the history, disclosure in the pull request
instead.
These rules read only the message. Jules and OpenHands can commit under their
own bot identity instead of adding a co-author line, and such a commit passes
when its message contains no recognized AI signature. The Copilot coding agent
also commits as its own account, but every commit it makes carries an
Agent-Logs-Url: trailer, so its commits are caught.
This checks disclosure, not authorship
These rules read commit metadata. They detect a commit that says it was AI-assisted; they cannot detect one that was AI-assisted and did not say so.
Set against a policy of "no AI contributions", it is an honesty check on contributors who are already following the rules — not an enforcement mechanism against those who aren't. Be clear with yourself about which of those you are buying.
Checking AI attribution and nothing else¶
ai_attribution sits alongside the message rules that are on by default, so
--message still applies Conventional Commits and the subject length limits
(80 characters at most, 5 at least). A project that has its own commit style
and only wants the AI check turns those off:
Or, in the GitHub Action, without a config file:
- uses: commit-check/commit-check-action@v2
env:
CCHK_AI_ATTRIBUTION: forbid
CCHK_CONVENTIONAL_COMMITS: false
CCHK_SUBJECT_MAX_LENGTH: 0
CCHK_SUBJECT_MIN_LENGTH: 0
with:
message: true
branch: false
Leave the length limits on and a long subject fails the job too. Dependency
bots write long ones: Renovate's Update dependency
com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer to
v20261103 is 95 characters.
Checking a pull request description¶
Agents leave their mark in the pull request description as often as in the
commits: 🤖 Generated with Claude Code, Link to Devin run: https://app.devin.ai/sessions/...,
a Codex task or Cursor agent link. --ai-only holds any text to the AI rules
alone, so the description is not judged as a Conventional Commit:
$ set -o pipefail # a failed `gh` must not pass as an empty description
$ gh pr view 42 --json body -q .body | commit-check --ai-only
Under ai_attribution = "forbid" a description with an agent's mark fails
CC013; under "disclose" it has to disclose the tool,
like a commit. Under the default "ignore" no rule runs and the check
passes; --format json still lists what it found in ai_tools, which is
enough to label the pull request:
$ gh pr view 42 --json body -q .body | commit-check --ai-only --format json | jq -c '.ai_tools'
["Devin"]
Asking for disclosure instead¶
Most projects that allow AI assistance ask to be told about it.
Fedora and
FluxCD want an Assisted-by: trailer, as the
Linux kernel did
until its maintainers decided in October 2026 to drop the tag; the
Apache Software Foundation
recommends Generated-by:. The kernel still says an AI agent must
never add a Signed-off-by: line, because only a person can certify the
DCO.
That turns on three rules, each about one of those conditions:
| Rule | Asks that |
|---|---|
| CC014 | the assistance is disclosed with an accepted trailer |
| CC015 | the tool is not credited as a co-author |
| CC016 | the tool did not sign off the commit |
A commit that a vendor stamped and nobody disclosed fails the first two, and the failure carries the disclosure already written:
CC014 ai-disclosure check failed ==> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AI assistance is not disclosed with Assisted-by or Generated-by — detected: Claude Code
Suggest: Disclose the tool with "Assisted-by: Claude Opus 5"
Docs: https://commit-check.com/rules/#cc014
CC015 ai-co-author check failed ==> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An AI tool is credited as a co-author: Claude Code
Suggest: Use "Assisted-by: Claude Opus 5" in place of the co-author line
Docs: https://commit-check.com/rules/#cc015
Both carry the same correction in --format json: the co-author line rewritten
as the project's disclosure trailer, keeping the name the tool gave itself.
Once the tool is disclosed, CC015 asks only for the co-author line to go, and
a commit in the kernel's Assisted-by: format passes all three:
printf 'feat: add caching layer\n\nAssisted-by: LLM coccinelle sparse\nSigned-off-by: Jane Dev <jane@example.com>' | commit-check -m
Choosing the format¶
ai_disclosure_trailers is the list of trailers that count as a disclosure,
and the first one is what a correction is written with:
Listing Co-authored-by says the project accepts the tool as a co-author —
pytest and
IREE do — and CC015 then passes. Signed-off-by is refused whatever else you
list, so CC016 cannot be configured away.
ai_disclosure_pattern asks for a particular shape, such as FluxCD's
agent/model:
CC014 ai-disclosure check failed ==> Assisted-by: Claude Code
The Assisted-by value does not match the required pattern: ^\S+/\S+$
Suggest: Write the Assisted-by value so that it matches ^\S+/\S+$ (set by ai_disclosure_pattern in the [commit] config)
That failure carries no correction, because the tool should not guess which model or format you meant.
Refusing the tool as a co-author, without asking for disclosure¶
pip and
attrs
close any pull request that lists an LLM as a co-author, but they don't ask
contributors to disclose AI use. Put CC014 in the top-level warn list and
the other two keep enforcing:
CC014 ai-disclosure check warning ==> 🤖 Generated with [Claude
AI assistance is not disclosed with Assisted-by or Generated-by — detected: Claude Code
Suggest: Disclose the tool with "Assisted-by: Claude Code"
Docs: https://commit-check.com/rules/#cc014
This rule is set to warn in the config; it does not fail the run.
The run still passes. The warning still suggests a disclosure that pip and attrs don't ask for: commit-check has no switch that turns off a single rule, so reporting CC014 is as quiet as it gets. See Report a rule without enforcing it.
CPython sets no rule
for commits at all: disclosing AI use is appreciated but not required, and
triagers judge each contribution by whether its author can explain it in their
own words. A policy like that leaves nothing for commit-check to enforce, so
keep ai_attribution at its default, "ignore".
Recipes from real projects¶
Many projects enforce their AI policy with a hand-written grep step in CI.
Each policy below fits in a few lines of cchk.toml. Add
conventional_commits = false if your project does not use Conventional
Commits (see Checking AI attribution and nothing else).
| Project | Its rule for commits | cchk.toml |
|---|---|---|
| Kubernetes | No AI co-author, no AI sign-off, no Assisted-by |
ai_attribution = "forbid" |
| Linux kernel | Every commit signed off by a person; an AI never signs off | ai_attribution = "disclose", require_signed_off_by = true, top-level warn = ["ai_disclosure"] |
| Nextcloud | Assisted-by: AGENT_NAME:MODEL_VERSION on AI-assisted commits; an AI never signs off |
ai_attribution = "disclose", ai_disclosure_pattern = '^[^:\s]+:\S+' |
| pip, attrs | No AI co-author; disclosure not required | ai_attribution = "disclose", top-level warn = ["ai_disclosure"] |
| Fedora, FluxCD | Disclose with Assisted-by: |
ai_attribution = "disclose", ai_disclosure_trailers = ["Assisted-by"] |
The Nextcloud recipe, in full:
Assisted-by: ClaudeCode:claude-sonnet-4-6 passes. Assisted-by: Claude Code
fails CC014 because it names no model, and Signed-off-by: Claude
<noreply@anthropic.com> fails CC016.
Some projects ask every commit to say whether AI was used, with
Assisted-by: none when it was not. disclose only asks when a commit shows
signs of AI, so pair it with a message_pattern that requires the trailer:
message_pattern replaces the Conventional Commits check, so this recipe
cannot be combined with conventional_commits = true. A commit with no
Assisted-by: line fails CC001; Assisted-by: none passes.
Exempting automation¶
Bots that legitimately carry AI trailers can be excluded:
Documenting the decision¶
Whichever way you go, the config file is not where contributors look. State the
policy where they will see it — CONTRIBUTING.md, the pull request template —
and let Commit Check be the mechanism rather than the announcement.
Enforcing an undocumented policy produces a confusing failure for somebody acting in good faith.