Field note · 7 October 2026 · Daniel Wright

I set attribution.pr and left commit unset. The Co-Authored-By trailer came back. Official docs: the unset half uses the default, and includeCoAuthoredBy is ignored.

A cream card printed PR ONLY lies on a dark wooden desk beside a brass plate engraved COMMIT EMPTY, with a closed navy notebook and a slate-blue desk pad
The cream card is the half I set. The brass plate is both keys, empty.

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.

Wrong · pr only · boolean ignored
{
  "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.

~/.claude/settings.json · hide all attribution
{
  "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.

Self-check · git log -1
# 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 trailer

If 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

  1. Read the object. commit, pr, and sessionUrl are three keys. An unset key uses its default.
  2. Hide the trailer with "commit": "". Hide the pull request line with "pr": "".
  3. Set "sessionUrl": false when you also want the cloud session link gone. Its default is true.
  4. Drop includeCoAuthoredBy once either new key is set. The boolean is ignored from that point.
  5. A line in CLAUDE.md that bans the trailer leaves the built-in instruction in place. Empty strings remove it.
  6. Put all three keys in the highest settings file that sets attribution. Run git log -1 after 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

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.