The annoyance
I had "includeCoAuthoredBy": false in ~/.claude/settings.json. Commits went out without a trailer. I then added the current key and set only "pr": "", so pull request descriptions would drop the footer, and I left the boolean in the file because it had been doing the job. The next commit ended with Co-Authored-By:, the session’s model name, and <noreply@anthropic.com>.
The other fix I reached for was a line in CLAUDE.md that says never add a co-author. The commit still grew the trailer. The boolean was still in the file. One half of attribution was set. That was enough to bring the line back.
What Anthropic actually says
From the official settings reference, under “Git and attribution”, then attribution:
“Once you set commit or pr, Claude Code ignores the deprecated includeCoAuthoredBy setting and uses its default text for whichever of the two you left unset.”
The old key is still read, until you touch the new one. Under includeCoAuthoredBy:
“Claude Code still honors includeCoAuthoredBy: false from settings files that predate attribution, but ignores it once you set attribution.commit or attribution.pr.”
false omits both the commit trailer and the pull request text. The moment either new key is present, that boolean stops, and the unset key falls back to its default.
The commit default, under attribution.commit:
“Default: unset, so Claude Code adds Co-Authored-By: <noreply@anthropic.com>. The name is the session's active model, such as Claude Sonnet 5.”
An empty pr with no commit is a quiet pull request and a commit trailer. The reverse is the same shape: set only commit to an empty string and the pull request line comes back as the default “Generated with Claude Code” footer, linking to claude.com/claude-code.
To hide all of it, the same section is specific:
“To hide all attribution, set commit and pr to empty strings and sessionUrl to false.”
sessionUrl defaults to true. On a cloud or Remote Control commit, Claude Code still adds a Claude-Session trailer until that key is false. Empty commit and pr leave that link in place.
A sentence in CLAUDE.md is the other miss. The system prompt docs, under “Turn off the context your agent replaces”, describe the fight:
“if your prompt tells Claude to write commit messages as PROJ-142: fix login redirect with no trailers, Claude Code still tells Claude to end each commit message with a Co-Authored-By trailer, so Claude receives two conflicting instructions for the same commit.”
The row that turns the trailer off:
“Set attribution.commit and attribution.pr to your own text, or to empty strings to remove them.”
The check on that page is git log -1. Official wording: “The message ends without a Co-Authored-By trailer.”
The fix
This is the file I had. The boolean used to hide both halves. With pr set, it is ignored, and commit is unset, so the trailer is the default.
{
"includeCoAuthoredBy": false,
"attribution": {
"pr": ""
}
}Both strings empty, and sessionUrl false. I keep this in ~/.claude/settings.json, so the NavAIgate repos I commit from stay free of the trailer. A project file accepts the same object. These keys apply from any settings file, and the highest file that sets attribution is the one Claude Code uses, so put all three keys in that file.
{
"attribution": {
"commit": "",
"pr": "",
"sessionUrl": false
}
}Leave includeCoAuthoredBy out. Once either new key is set, Claude Code ignores it.
Prove it
Prove the three keys are in the file that wins, then prove one real commit.
# The settings file that wins must carry all three keys
# ~/.claude/settings.json, or a higher file that sets attribution
# commit: ""
# pr: ""
# sessionUrl: false
# Ask Claude to commit one line in a throwaway repo
git log -1 --format='%B'
# no Co-Authored-By line
# On a cloud or Remote Control commit, also confirm
# the body has no Claude-Session trailerIf git log -1 still shows Co-Authored-By, one of the two strings is unset. If a cloud commit still carries Claude-Session, sessionUrl is still at its default.
Checklist
- Read the object.
commit,pr, andsessionUrlare three keys. An unset key uses its default. - Hide the trailer with
"commit": "". Hide the pull request line with"pr": "". - Set
"sessionUrl": falsewhen you also want the cloud session link gone. Its default is true. - Drop
includeCoAuthoredByonce either new key is set. The boolean is ignored from that point. - A line in
CLAUDE.mdthat bans the trailer leaves the built-in instruction in place. Empty strings remove it. - Put all three keys in the highest settings file that sets
attribution. Rungit log -1after one commit.
Why it fails
I treated includeCoAuthoredBy: false as still in force after I started the attribution object. The reference says setting commit or pr ignores that boolean and fills the half I left out with the default. The commit default is the co-author trailer. Claude then gets two instructions, mine and that default, and the default is the one Claude Code adds.
Same family as CLAUDE.md Never Skips Permission Prompts, where a sentence in the project file never replaces the permission system, and Bypass Permissions in Project Settings Does Nothing, where a setting looks finished and is ignored. This one is a key I did set, beside a key I left out.
Sources
From idea to operation
Make the next AI decision concrete.
NavAIgate helps leadership teams identify high-value AI opportunities, prove them safely and turn the winners into working systems.
