Engineering Advanced GitHooksAI Tools

Git Commit Hygiene

Install a commit-msg hook that auto-strips AI tool attribution from git commits.

$skillfish add ~skills/git-commit-hygiene

Real Conversations

See how the Git Commit Hygiene skill responds to actual requests. These are representative examples of what your AI agent will produce.

You

Claude Code keeps adding "Co-Authored-By: Claude Sonnet" to my commits. I've told it not to but it still happens sometimes. How do I enforce this at the git level so it can never slip through?

Agent

Install a commit-msg hook — it runs before every commit is recorded and strips attribution lines automatically, regardless of what the agent wrote.

Create the hook:

cat > .git/hooks/commit-msg << 'EOF'
#!/bin/sh
sed -i '' '/^[[:space:]]*[Cc]o-[Aa]uthored-[Bb]y:/d' "$1"
sed -i '' '/^[[:space:]]*[Gg]enerated by.*AI/d' "$1"
sed -i '' '/^[[:space:]]*[Cc]reated with.*AI/d' "$1"
sed -i '' -e :a -e '/^\n*$/{$d;N;ba' -e '}' "$1"
EOF
chmod +x .git/hooks/commit-msg

On Linux replace sed -i '' with sed -i (no empty string arg).

Verify it works:

git commit --allow-empty -m "test

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>"

git log -1 --format="%B"
# → only "test" — attribution gone

Also add to CLAUDE.md so the agent knows the rule at the prompt level too:

## Git Commit Rules
- NEVER add `Co-Authored-By` lines to git commits
- Commit messages should be concise and human-style

The hook is the backstop. CLAUDE.md is the first line of defence. Both together means attribution never reaches your git history.

Get Started

How to install and use this skill in your preferred environment.

Skills are designed for AI coding agents (Claude Code, Cursor, Windsurf) and IDE-based workflows where the agent can read files, run scripts, and act on your codebase. Web-based AI can use the knowledge and frameworks, but won't have tool access.

Models & Context

Which AI models and context windows work best with this skill.

Recommended Models

Best
Claude Opus 4 Claude Sonnet 4 GPT-4.1 Gemini 2.5 Pro Grok 3 Kimi K2
Good
Claude Haiku 4.5 GPT-4.1 mini Gemini 2.5 Flash Grok 3 mini

Larger models produce more detailed, production-ready outputs.

Context Window

This skill's SKILL.md is typically 3–10 KB — fits in any modern context window.

8K Skill only
32K+ Skill + conversation
100K+ Skill + references + codebase

All current frontier models (Claude, GPT, Gemini) support 100K+ context. Use the full window for complex multi-service work.

Pro tips for best results

1

Be specific

Include numbers — users, budget, RPS — so the skill can size the architecture.

2

Share constraints

Compliance needs, team size, and existing stack all improve the output.

3

Iterate

Start with a high-level design, then ask follow-ups for IaC, cost analysis, or security review.

4

Combine skills

Pair with companion skills below for end-to-end coverage.

Good to Know

Advanced guide and reference material for Git Commit Hygiene. Background, edge cases, and patterns worth understanding.

Contents

Two-Layer Defence

The hook is a backstop, not the only control. Both layers together are more robust:

Layer 1 — CLAUDE.md instructs the agent at the prompt level. Claude Code reads CLAUDE.md at startup and follows its rules. With the rule present, the agent will usually not add attribution lines in the first place.

Layer 2 — commit-msg hook enforces at the git level regardless of what the agent wrote. Even if the agent ignores CLAUDE.md or is replaced by a different tool, the hook silently strips attribution before the commit is recorded.

The combination: the agent tries not to add attribution (Layer 1), and even if it does, the hook removes it before it reaches history (Layer 2).

Disabling Attribution in Your Editor

Editor settings let you turn off attribution at the source — before it ever reaches the commit message. They don't replace the hook; they reduce the noise so the hook rarely needs to fire.

Claude Code

Claude Code writes attribution to commits via the attribution.commit setting in .claude/settings.json. Set it to an empty string to suppress the Co-Authored-By: Claude Sonnet… line.

Commit-only disable (most common):

{
  "attribution": {
    "commit": ""
  }
}

Full disable (commits and pull requests):

{
  "attribution": {
    "commit": "",
    "pr": ""
  }
}

Scope options:

  • User-level: ~/.claude/settings.json — applies to all projects
  • Project-level: .claude/settings.json — applies to one repo only (check this in if your team wants a shared default)

Caveat: This is a soft control. When Claude Code uses the Bash tool to run git commit directly, it may inject attribution via the shell environment rather than through the settings file. The commit-msg hook catches those cases.

Cursor

Cursor adds attribution as a Made with Cursor commit trailer (and in older versions, a Co-Authored-By: Cursor line).

To disable: open Settings (Cmd+, / Ctrl+,) → AgentAttribution → toggle off "Add Cursor as co-author in Git commits".

Critical caveat: Cursor silently re-enables this toggle after IDE updates. Check the setting after every Cursor update — it is the most common reason attribution reappears in teams that thought they had it disabled.

Enterprise teams: Administrators can disable the setting globally from the Cursor Admin Dashboard, which prevents individual users from re-enabling it.

Why the hook still matters

Editor settings are soft controls: opt-in, easy to forget, and reset by updates. A new team member, a Cursor update, or a different AI tool entirely can reintroduce attribution without anyone noticing.

The commit-msg hook enforces the rule at the git level — it runs regardless of which editor or agent is in use, regardless of whether a setting got reset, and regardless of whether the developer knows attribution is being added. The hook is the guarantee; the editor settings reduce the day-to-day noise.

Team Distribution Options

.git/hooks/ is not tracked by git — each developer must install the hook themselves. Three practical approaches:

Option A — core.hooksPath (recommended)

Commit the hook to .githooks/ and point git at it:

mkdir -p .githooks
cp .git/hooks/commit-msg .githooks/commit-msg
git config core.hooksPath .githooks

All developers who run this command (or have it in a setup script or onboarding docs) get the hook automatically.

Option B — package.json postinstall

Runs automatically on npm install:

{
  "scripts": {
    "postinstall": "git config core.hooksPath .githooks"
  }
}

Option C — Husky

For teams already using Husky for other hooks:

npx husky add .husky/commit-msg 'sh .githooks/commit-msg $1'

Auditing Existing History

The hook prevents future attribution but does not rewrite past commits. To check whether attribution already exists in your history:

git log --all --grep="Co-Authored-By" --oneline
git log --all --grep="Co-Authored-By" --oneline | wc -l

Removing attribution from existing history requires rewriting with git filter-repo — a significant operation only appropriate when all collaborators are informed.

How the commit-msg Hook Works

Git runs hooks at specific points in the commit lifecycle. The commit-msg hook fires after you run git commit and write the message, but before git finalises the commit object. It receives one argument: the path to a temporary file containing the raw commit message.

The hook can read and modify that file, exit non-zero to abort the commit entirely, or run any shell command.

Hook execution order:

  1. pre-commit — runs first; can abort if lint/tests fail
  2. prepare-commit-msg — can pre-populate the message
  3. commit-msgthis hook fires here — validate or rewrite the message file
  4. post-commit — runs after; cannot abort; used for notifications

Pattern Reference

Every sed line in the hook targets a distinct attribution pattern:

Pattern Purpose
/[Cc]o-[Aa]uthored-[Bb]y:/ Claude Code, GitHub Copilot, Codex — case-insensitive
/[Mm]ade-with:.*[Cc]ursor/ Cursor-specific Made-with: Cursor line
/[Gg]enerated by [Cc]ursor/ Cursor alternate phrasing
/[Cc]reated with [Cc]ursor/ Cursor alternate phrasing
/[Cc]ursor AI/ Generic Cursor AI mention anywhere in line
/[Gg]enerated by.*AI/ Generic catch-all for any AI tool
/[Cc]reated with.*AI/ Generic catch-all for any AI tool
Trailing blank line loop Removes blank lines left behind after stripping

macOS vs Linux sed

The hook uses sed -i to edit the commit message file in place. The syntax differs between BSD sed (macOS) and GNU sed (Linux):

Platform Correct syntax Notes
macOS / BSD sed -i '' Empty string = no backup file created
Linux / GNU sed -i No argument after -i

The hook ships with sed -i '' for macOS. For cross-platform repos, use the OS-detection variant in the SKILL.md or switch to perl -i -pe which works identically on both.

Ready to try Git Commit Hygiene?

Install the skill and start getting expert-level guidance in your workflow — any agent, any IDE.

$skillfish add ~skills/git-commit-hygiene
← Browse all 169 skills