A script that prints an Assisted-by: trailer for the AI coding agent that runs it, in the format the Linux kernel documents:
Assisted-by: HARNESS:MODEL [TOOL1] [TOOL2]
The agent commits with it:
t=$(assisted-by); git commit ${t:+--trailer} ${t:+"$t"} -m "Fix the thing"
The two-expansion form works in sh, bash, and zsh, and passes no --trailer when the script prints nothing.
For example:
Assisted-by: claude-code:claude-opus-5 spekk
It reads the harness and the model from the agent's own session record, not from what the model says about itself. A model is not reliable about its own version, and no environment variable follows a model switch made in the middle of a session. When it finds no agent session or no model, it prints nothing and exits 1, so a commit gets no trailer rather than a wrong one.
Claude Code and opencode are supported.
mkdir -p ~/.local/bin
curl -fsSL https://gist.githubusercontent.com/whusterj/01be8cde934ed45ea5264c30163d9cf5/raw/assisted-by -o ~/.local/bin/assisted-by
chmod +x ~/.local/bin/assisted-by
git config --global trailer.assisted-by.ifExists addIfDifferent
~/.local/bin must be on your PATH. The ifExists entry keeps an amend or a rebase from adding a second copy of the trailer.
Then tell your agent to use it. The rule in my agent instructions is: commit with the form above, never type the trailer or a tool name by hand, and if the script fails, commit without the trailer and say so.
The first version was a global prepare-commit-msg hook under core.hooksPath. Git resolves that setting by precedence, and a repository's own core.hooksPath wins. Husky sets one on purpose, and Claude Code writes one as a side effect when it creates a worktree, so the hook silently stopped in those repositories. The reverse also held: a global core.hooksPath hides a repository's .git/hooks for every hook name the global directory does not chain, so a pre-commit framework hook went quiet with no error. The trailer is a fact about the agent session, not about the repository, so the mechanism now lives with the agent.
- It needs
python3, andsqlite3for opencode. - A specialized tool is listed only when the environment is configured for it.
spekkis listed when the binary is installed and the repository has aspecs/directory. Add a tool by adding a check in the script, not by hand on the command line. - A commit you make yourself gets no trailer, because the script sees no agent session.
git config assisted-by.enabled falseturns the trailer off for a repository, for commits and pull requests alike. Unset means on.assisted-by --prprints the same line for a pull request description, and only in a repository that hasgit config assisted-by.pr true. Unset means off, so a pull request carries no attribution by default.
Turn off Claude Code's own Co-authored-by trailer in ~/.claude/settings.json:
{
"attribution": {
"commit": "",
"pr": ""
}
}