A small Claude Code hook that automatically commits and pushes any change you
make to your claude-skills repo (or whatever repo you store your custom
Claude skills in) during a Claude Code session.
If you keep your Claude skills in a git repo and use them across multiple machines, every edit you make in one Claude Code session needs to be committed and pushed before the other machines can pull it. It is very easy to forget. The result is the same skill in different states on different machines, and the wrong version showing up in a session you wished was running the latest one.
This hook removes the chance of forgetting. Every time Claude Code edits a
file inside your skills repo, the change is committed and pushed
immediately, with a clear Auto-commit: prefix in the message so you can
distinguish it from your manual commits.
| Step | Behavior |
|---|---|
Claude Code calls Edit, Write, or MultiEdit |
The PostToolUse hook fires |
The hook reads tool_input.file_path from stdin |
|
| Path is not inside your skills repo | Hook exits 0 silently. No effect on other projects. |
| Path is inside your skills repo | cd into the repo, git add only the specific file (not -A, so unrelated WIP is safe), check if anything actually changed |
| Nothing actually changed | Exit 0 silently |
| Real change | Commit with message Auto-commit: update <rel-path> from Claude Code session plus session ID, tool name, timestamp, and a Co-Authored-By: Claude Code trailer |
| Push succeeds | Logged and done |
| Push fails (offline, conflicts, etc.) | Logged, but commit is safe locally — push manually later |
| Anything fails | Hook exits 0 anyway — never blocks Claude Code |
mkdir -p ~/.claude/hooks
curl -fsSL https://gist.githubusercontent.com/dmccreary/693a3ebacd14bae3add9c5a931e0f011/raw/auto-commit-claude-skills.sh \
-o ~/.claude/hooks/auto-commit-claude-skills.sh
chmod +x ~/.claude/hooks/auto-commit-claude-skills.shAdd this entry under hooks.PostToolUse. If PostToolUse already exists,
just add a new object to its array — don't replace what's there.
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/auto-commit-claude-skills.sh"
}
]
}A complete settings.json with only this hook configured looks like:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/auto-commit-claude-skills.sh"
}
]
}
]
}
}The script defaults to $HOME/Documents/ws/claude-skills. If your skills
repo lives somewhere else, set CLAUDE_SKILLS_REPO in your shell startup
file (~/.zshrc, ~/.bashrc, etc.):
export CLAUDE_SKILLS_REPO="$HOME/code/my-claude-skills"Restart your terminal (and Claude Code) so the new env var is picked up.
After installing:
-
Bail-out test — confirm the hook ignores files outside your skills repo:
echo '{"tool_name":"Edit","tool_input":{"file_path":"/tmp/not-a-skill.txt"},"session_id":"test"}' \ | bash ~/.claude/hooks/auto-commit-claude-skills.sh echo "exit=$?"
Expected:
exit=0and no output. The hook bailed out silently. -
JSON validation — confirm
settings.jsonstill parses:jq . ~/.claude/settings.json > /dev/null && echo "JSON OK"
-
End-to-end test — start Claude Code, edit a file inside your skills repo (or just touch the description in a
SKILL.md), and watch:tail -f ~/.claude/activity-logs/auto-commit-claude-skills.logYou should see a
Committedline and aPushedline within a second or two of the edit completing.
| File | What it tells you |
|---|---|
~/.claude/activity-logs/auto-commit-claude-skills.log |
Every commit, push, and failure with timestamps |
cd $CLAUDE_SKILLS_REPO && git log --oneline --grep='^Auto-commit:' |
All hook-generated commits, separated from your manual ones |
cd $CLAUDE_SKILLS_REPO && git status |
Anything still pending locally (e.g., if push has been failing) |
Two ways:
- Temporary — comment out the new entry in
~/.claude/settings.json, restart Claude Code. - Permanent — delete the script and remove the entry from
settings.json.
Both are reversible in seconds.
- One commit per edit. If you edit 5 skill files in a single Claude
Code session, you get 5 commits. This is intentional — eager commits
beat batched commits when the goal is "never forget to push." If
commit-history noise becomes a problem, you can interactively rebase
later, or fork the script to commit on every edit but only push on
Stop(the session-end Claude Code hook). - Pre-commit hooks still run. The script does not pass
--no-verify. If your skills repo has a linter or other pre-commit hook, it runs on every auto-commit. That's the right default — never bypass safety checks silently. - Only
Edit,Write, andMultiEditare watched. If something else modifies files in your skills repo (a script you ran via theBashtool, a file generated by a build step, etc.), the hook does not fire. For those cases, manualgit add && git commit && git pushis still required. - Push runs synchronously. On a slow network the hook will block
Claude Code for the duration of the push. In practice this is usually
under one second. If you ever notice it as a lag, change the
git pushline togit push &to background it. - The hook needs
jq. It is preinstalled on macOS via Homebrew if you haveghworking, and on most Linux distros via the package manager.brew install jqorapt install jqif needed.
I work on five different machines. Forgetting to push my Claude skills repo from one of them was a recurring source of "wait, why is the new version of my skill not running here?" frustration. This hook ended that class of problem entirely. If you also juggle skills across machines, it might end yours too.
Public domain / CC0 / do whatever you want. No warranty.