🚫

Claude Codeに自動で任せる、でも危険なgit操作だけはルールで縛る

Claude Codeに作業を任せていると、便利な一方で「勝手にgit pushされたら」「作業ブランチをgit branch -Dで消されたら」とヒヤッとする瞬間があります。基本的には自動でどんどん進めてほしい。けれど、取り返しのつかない操作だけはしないでほしい。

この記事では、~/.claude/settings.jsonpermissionsを使って、確認を挟みたい操作(ask)と実行そのものを禁止したい操作(deny)を宣言的にルール化する方法を紹介します。CLAUDE.mdに「絶対にpushしないこと」とお願いするのではなく、仕組みとして縛るのがポイントです。

AIに操作を任せる怖さ

Claude Codeに自動でコミットやブランチ操作を任せると、知らぬ間にAIのコミットが積まれていたり、git pushが走っていたりすることがあります。具体的に怖いのは次のようなシナリオです。

  • 意図しないgit push
  • git branch -Dによる作業ブランチの削除
  • git reset —hardによる未コミット変更の消失

削除・破壊系の操作は、何も設定していなくてもClaude Codeが確認を挟んでくれることが多いです。とはいえ「多い」であって「必ず」ではないので、念のため仕組みで縛っておきたいところです。

CLAUDE.md(指示文)に「絶対にpushしないこと」と書く方法もありますが、これはあくまでお願いベースで、強制力としては弱いものです。そこで、設定ファイルでガードを仕込みます。

前提知識:3つの権限レベルと優先順位

permissionsには3つの判定レベルがあります。

  • allow:確認なしで自動実行する
  • ask:実行前に毎回確認する
  • deny:実行そのものをブロックする

参照: https://code.claude.com/docs/ja/settings#permission-settings

肝になるのが優先順位です。1つのコマンドが複数のルールに該当した場合、評価順は deny > ask > allow で、もっとも強い deny が勝ちます。つまり、askとdenyに同じコマンドを書いても、denyが優先されてブロックされます。

設定ファイルの置き場所は複数ありますが、今回はgit操作のガードをすべてのプロジェクトに効かせたいので、基本は~/.claude/settings.jsonに書きます。 プロジェクト毎に.claude/settings.jsonを配置すれば、そのプロジェクトだけで適用する運用もできます。

実装①:commit / push / ブランチ作成は「確認」させる(ask)

コミット・プッシュ・ブランチ作成は、禁止したいわけではありません。やってほしいけれど、勝手にやられたくない。こういう操作は ask(毎回確認)がちょうどよい塩梅です。

"ask": [
  "Bash(git commit)",
  "Bash(git commit:*)",
  "Bash(git push)",
  "Bash(git push:*)",
  "Bash(git checkout -b:*)",
  "Bash(git switch -c:*)",
  "Bash(git branch:*)"
]

こう設定しておくと、Claude Codeが対象のコマンドを実行しようとしたタイミングで、次のように確認のプロンプトが出ます。

ClaudeCodeでaskを実行

構文のコツがいくつかあります。

  • Bash(git push:*)は「git push + 任意の引数」にマッチする
  • 引数なしの素のgit push:*では拾えないので、bare形のBash(git push)も併記する

注意点として、Bash(git branch:*)はブランチ作成だけでなく、git branch -aのような一覧表示にもマッチします。globでは作成と一覧を区別できないため、一覧表示まで確認対象になってしまうトレードオフがあります。気になる場合は確認を許容するか、ルールを細かく書き分ける必要があります。

実装②:削除・破壊系は「完全禁止」する(deny)

取り返しがつかない操作は、確認(ask)では不十分です。確認プロンプトをうっかり通してしまえば終わりだからです。こうした操作は deny でブロックします。

"deny": [
  "Bash(git branch -d:*)",
  "Bash(git branch -D:*)",
  "Bash(git push --delete:*)",
  "Bash(git push -d:*)",
  "Bash(git tag -d:*)",
  "Bash(git tag --delete:*)",
  "Bash(git rm:*)",
  "Bash(git clean:*)",
  "Bash(git stash drop:*)",
  "Bash(git stash clear)",
  "Bash(git remote remove:*)",
  "Bash(git remote rm:*)",
  "Bash(git reset --hard)",
  "Bash(git reset --hard:*)",
  "Bash(git checkout --:*)",
  "Bash(git restore:*)"
]

大きく2系統に分けています。

  • 削除系
    • ブランチ削除(git branch -d / -D)、リモートブランチ削除(git push —delete / -d)
    • タグ削除(git tag -d)、ファイル削除(git rm)、未追跡ファイル削除(git clean)
    • stash破棄(git stash drop / clear)、リモート削除(git remote remove / rm)
  • 破壊系
    • 履歴・作業ツリーの破壊(git reset —hard)、変更の破棄(git checkout — / git restore)

denyに入れた操作は、確認しても実行できません。正当な用途でどうしても実行したいときは、人間が手動実行することになります。

まとめ

二層で守る構図に整理できます。

  • 指示文(CLAUDE.md) = お願い。強制力は弱いが、意図や文脈を伝えられる
  • permissions = 強制ガード。宣言的に効くが、表現の網羅には限界がある

線引きの指針はシンプルです。askは「確認したい操作」、denyは「絶対にやられたくない操作」。あとは自分の運用に合わせて調整していくのがよいと思います。完璧は狙えませんが、ヒヤッとする瞬間を確実に減らせます。

定期的に棚卸しすることも重要です。allow / ask / denyを見直し、不要になったルールや広すぎるルールを整理しましょう。

最後に、ここまでのask / denyをまとめた設定全体を載せておきます。

"permissions": {
  "allow": [],
  "ask": [
    "Bash(git commit)",
    "Bash(git commit:*)",
    "Bash(git push)",
    "Bash(git push:*)",
    "Bash(git checkout -b:*)",
    "Bash(git switch -c:*)",
    "Bash(git branch:*)"
  ],
  "deny": [
    "Bash(git branch -d:*)",
    "Bash(git branch -D:*)",
    "Bash(git push --delete:*)",
    "Bash(git push -d:*)",
    "Bash(git tag -d:*)",
    "Bash(git tag --delete:*)",
    "Bash(git rm:*)",
    "Bash(git clean:*)",
    "Bash(git stash drop:*)",
    "Bash(git stash clear)",
    "Bash(git remote remove:*)",
    "Bash(git remote rm:*)",
    "Bash(git reset --hard)",
    "Bash(git reset --hard:*)",
    "Bash(git checkout --:*)",
    "Bash(git restore:*)"
  ]
}

参考文献

新着記事

関連ネットワーク(beta)

ドラッグで移動 / Ctrl+ホイールでズーム