最終更新: 2026年11月8日
Skillselion の git スキルガイドでインストール数1位になっている git-guardrails-claude-code の hook を、2026年11月8日に手元で検証しました。危険系として用意した30パターンのうち、止まったのは15個です。git -C . push やスペース2つの git push、git clean -xfd は終了コード0で通りました。jq が入っていない環境では git push も通ります。
私たちは Claude Code などのスキルを実際のインストール数で並べるディレクトリ Skillselion を運営しています。この記事は、そのデータで1位だった git スキルを自分たちで叩いてみた記録です。
git-guardrails-claude-code は何をするスキルですか?
mattpocock/skills に入っているスキルで、git-guardrails-claude-code スキルの掲載ページでは 542,705 インストールです(2026年11月8日時点、skills.sh 集計)。リポジトリ mattpocock/skills のスター数は同日 318,023 でした。
中身は PreToolUse hook の設定手順と、block-dangerous-git.sh という25行のシェルスクリプトです。Claude Code が Bash ツールを呼ぶ直前に、コマンド文字列を JSON で受け取り、危険なパターンに当たれば終了コード2で止めます。Claude Code の hooks ドキュメントでは、PreToolUse の終了コード2は「Blocks the tool call」と書かれています。
スクリプトの判定部分はこれだけです(upstream のスクリプトから、2026年11月8日取得)。
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
DANGEROUS_PATTERNS=(
"git push"
"git reset --hard"
"git clean -fd"
"git clean -f"
"git branch -D"
"git checkout \."
"git restore \."
"push --force"
"reset --hard"
)
grep -qE で部分一致を見るだけなので、文字列の形が少しずれると当たりません。SKILL.md 側は「git push (all variants including --force)」をブロックすると書いていますが、実測では全部の書き方は止まりませんでした。
どうやって測りましたか?
upstream の最新版を gh api で取得し、SKILL.md の検証手順と同じ形の JSON({"tool_input":{"command":"..."}})をパイプで流して終了コードを記録しました。スクリプト自体の最終変更は 2026年4月28日のコミット 62f43a1817 です。
jq -cn --arg c "git -C . push origin main" '{tool_input:{command:$c}}' \
| ./block-dangerous-git.sh
echo $? # 0 なら通過、2 ならブロック
環境は macOS、bash 3.2.57、jq 1.8.1 です。Claude Code のセッション内で実行したわけではなく、スクリプト単体の挙動を見ています。
どのコマンドが hook を素通りしましたか?
危険系30パターンのうち、元のスクリプトで終了コード0(通過)になった15個です。右の列は後半で紹介する強化版の結果です。
| コマンド | 元の hook | 強化版 |
|---|---|---|
git -C . push origin main |
0(通過) | 2 |
git -c push.default=current push origin main |
0 | 2 |
git 'push' origin main |
0 | 2 |
git push origin main(スペース2つ) |
0 | 2 |
git<TAB>push origin main(タブ区切り) |
0 | 2 |
git clean -xfd |
0 | 2 |
git clean -dfx |
0 | 2 |
git clean --force -d |
0 | 2 |
git branch --delete --force feature |
0 | 2 |
git checkout -- . |
0 | 2 |
git checkout -f main |
0 | 2 |
git stash drop |
0 | 2 |
git stash clear |
0 | 2 |
git reflog expire --expire=now --all |
0 | 2 |
git config alias.p push |
0 | 2 |
原因は3種類に分けられます。
- git とサブコマンドの間に何か挟まると「git push」という連続文字列ではなくなる(
-C .、-c、クォート、スペース2つ、タブ) - オプションの並び順や長い形式が登録パターンと違う(
-xfd、--force -d、--delete --force) - そもそもパターンに入っていない(
checkout -- .、checkout -f、stash drop/clear、reflog expire、エイリアス作成)
git -C <パス> は worktree を複数使うときに出てくる書き方です。なお git -C . reset --hard HEAD~1 は止まりました。汎用パターン reset --hard が別に登録されているからです。push には同じ保険がありません。
逆に、ちゃんと止まった15個はこちらです。
元の hook で終了コード2になったコマンド(15個)
-
git push origin main/git push --force-with-lease/git push origin HEAD/git push origin HEAD --force-with-lease -
/usr/bin/git push origin main/command git push origin main/cd /tmp && git push/bash -c "git push" -
git reset --hard HEAD~1/git -C . reset --hard HEAD~1 -
git clean -fd/git clean -f -
git branch -D feature/git checkout ./git restore .
部分一致なので、&& でつないだものや bash -c で包んだものは拾えています。git commit -m "docs: never git push from CI" のように、コミットメッセージに「git push」と書いただけでも止まります(誤検知)。
jq が入っていないとどうなりますか?
全部通ります。PATH に cat、grep、tr だけを置いた環境で流した結果です。
$ printf '{"tool_input":{"command":"git push origin main"}}' \
| env -i PATH=./nojq-bin /bin/bash block-dangerous-git.sh
block-dangerous-git.sh: line 4: jq: command not found
$ echo $?
0
git push origin main、git reset --hard HEAD~1、git clean -fd の3つとも終了コード0でした。jq が無いと COMMAND が空文字になり、どのパターンにも当たらずに最後の exit 0 へ進みます。
ここで注意したいのは、Claude Code の onFailure: "block" でも救えない点です。hooks ドキュメントによると onFailure が拾う「失敗」は、起動できない、0と2以外の終了コード、タイムアウトなどです。このスクリプトは正常に終了コード0を返すので、Claude Code から見ると「問題なし」です。
Claude Code の permissions の deny ルールで代わりになりますか?
半分だけです。settings.json の permissions.deny に Bash(git push *) を書けば、標準的な git push origin main は止まります。ただし Claude Code の permissions ドキュメント自身が、Bash(git push *) は git -C . push origin main、git -c push.default=current push origin main、git 'push' origin main を止めない、と表で明記しています。hook の素通りパターンとほぼ同じです。
ドキュメントは、コマンド文字列を自前のロジックで検査したいなら PreToolUse hook を使うよう案内しています。deny ルールは hook が壊れたときの下支え、hook は書き方の揺れを拾う役、と分けて両方入れるのが現実的です。もう一つ、allow に Bash(git *) を入れていると、hook が止めず deny にも当たらなかった書き方は、確認なしで実行されます。
実際にどう固めればいいですか?
3つの手を重ねます。
1. hook の冒頭で jq を確認し、無ければ止める
if ! command -v jq >/dev/null 2>&1; then
echo "BLOCKED: jq が見つからないため git ガードがコマンドを検査できません。" >&2
exit 2
fi
jq の入れ方は macOS なら brew install jq、Ubuntu や WSL なら sudo apt install jq です。この1ブロックを足した強化版は、jq の無い環境で3コマンドとも終了コード2になりました。
2. パターンを「git とサブコマンドの間に何かあっても当たる」形にする
空白をまとめてクォートを外してから、git と危険なサブコマンドの間に -C <パス>、-c <設定>、--no-pager のようなオプションだけを許す正規表現で照合します。オプション以外の単語を挟めないようにしているので、コミットメッセージに push と書いただけでは止まりません。
COMMAND=$(jq -r '.tool_input.command // empty')
NORM=$(printf '%s' "$COMMAND" | tr -s '[:space:]' ' ' | tr -d "'\"")
G='(^|[;&|( /])git( (-C|-c) [^ ]+| --?[a-zA-Z][a-zA-Z-]*(=[^ ]*)?)* '
DANGEROUS_PATTERNS=(
"${G}push( |$)"
"${G}reset --hard"
"${G}clean (-[a-zA-Z]*f|--force)"
"${G}branch (-D|--delete --force|-d --force|-df|-fd)"
"${G}checkout (-- )?\.( |$)"
"${G}checkout (-f|--force)( |$)"
"${G}restore \.( |$)"
"${G}stash (drop|clear)"
"${G}reflog expire"
"${G}config [^;&|]*alias\."
)
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
if printf '%s' "$NORM" | grep -qE "$pattern"; then
echo "BLOCKED: '$COMMAND' matches '$pattern'. The user has prevented you from doing this." >&2
exit 2
fi
done
exit 0
同じ38コマンド(危険系30、それ以外7、誤検知確認1)で比べると、強化版は危険系30個すべてで終了コード2を返しました。git status、git log --oneline -5、git diff --stat、git restore src/、git rebase -i origin/main、gh pr create ... は元のスクリプトと同じく通過です。
トレードオフもあります。git -C "/tmp/my repo" push のように、スペースを含むパスをクォートで渡すと強化版でも通ります。また、コミットメッセージの中に「git push」と続けて書いた場合は、元の hook と同じく強化版でも止まります。git worktree add、git branch -d(小文字)、git stash list、git pull --rebase は通過を確認しました。
3. settings.json に deny と onFailure を足す
{
"permissions": {
"deny": [
"Bash(git push *)",
"Bash(git reset --hard *)",
"Bash(git clean *)",
"Bash(git branch -D *)",
"Bash(git stash drop *)",
"Bash(git stash clear *)",
"Bash(git reflog expire *)"
]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous-git.sh",
"onFailure": "block"
}
]
}
]
}
}
onFailure: "block" は Claude Code v2.1.295 以降で使えます。スクリプトのパス間違いや chmod +x 忘れで hook が起動できないとき、未設定だと Bash コマンドはそのまま実行されます(hooks ドキュメントでは non-blocking error 扱い)。push を Claude に任せつつ毎回確認したい場合は、Bash(git push *) を deny ではなく ask に置き、hook の push パターンを外す選択肢もあります。
エイリアスは hook では追いきれません。git p のように既存のエイリアス経由だと、元の hook も強化版も通過しました。git config --get-regexp '^alias\.' で、push や reset を指すエイリアスが無いか一度確認しておくと安心です。
ほかの git スキルと組み合わせるときの注意は?
git スキルガイドで紹介しているほかのスキルも、upstream の SKILL.md を読んで hook との相性を確認しました。インストール数は各掲載ページの2026年11月8日時点の値です。用途別の比較は Claude Code 向け git スキルガイドにまとめています。
-
caveman-commit スキル(429,597 インストール、juliusbrussee/caveman): コミットメッセージを書くだけのスキルです。SKILL.md に「Does not run
git commit, does not stage files, does not amend.」とあり、hook と衝突しません。件名は50文字以内を目安に、上限72文字です。パック全体は caveman スキルの解説ガイドにまとめています。 -
using-git-worktrees スキル(228,418 インストール、obra/superpowers): 既存の分離を確認し、ネイティブの worktree 機能を優先、最後に
git worktree addへ落ちる順番です。git worktree addは元の hook でも強化版でも止まりません。 -
create-pull-request スキル(813 インストール、cline/cline): 現行の SKILL.md は
git push origin HEADで push し、gh pr create --body-file /tmp/pr-body.mdで PR を作ります。このgit push origin HEADは git-guardrails で終了コード2になりました。両方入れると push の手順で止まるので、push だけ自分で打つか、前述のask運用にします。gh pr create自体は通過です。 -
git-commit スキル(48,232 インストール、github/awesome-copilot)と graphite スキル(9,991 インストール、withgraphite/agent-skills)は、コミット形式とスタック PR 向けです。graphite の
gt submit --no-interactiveは文字列にgit pushを含まないため、元の hook でも強化版でも終了コード0でした。文字列で照合する hook は gt 経由の push を止めない、と覚えておいてください。
開発ツール系スキル全体は開発ツール向けスキルのおすすめランキングと開発ツールスキルのカテゴリ一覧、hook 以外の守りはセキュリティスキルのカテゴリ一覧で探せます。
よくある質問
git-guardrails-claude-code は入れる価値がありますか?
あります。標準的な git push、git reset --hard、git clean -fd は実測で止まりました。ただ文字列の部分一致なので、書き方の揺れと jq 未導入には弱いです。入れたら jq の確認とパターン追加までやって完成と考えてください。
deny ルールだけで十分ですか?
十分ではありません。Claude Code の permissions ドキュメントが、Bash(git push *) は git -C . push などを止めないと明記しています。deny は hook が動かないときの下支えとして併用します。
自分の hook が効いているかはどう確認しますか?
この記事と同じく、jq -cn --arg c "<コマンド>" '{tool_input:{command:$c}}' | <スクリプト> を流して echo $? を見ます。2なら止まり、0なら通ります。git -C . push と、jq を外した状態の2つは必ず試してください。
出典: Skillselion の git スキルガイド(インストール数は skills.sh、GitHub、MCP レジストリから毎日更新している実インストール数のランキング)。hook の実測値は2026年11月8日に私たちが計測したものです。