はじめに
「AIに任せておけば大丈夫」
この認識が完全に崩れた。
Codex CLI でリファクタリングをお願いしていたら、突然こんなコマンドが実行された。
git restore --staged .
git restore .
git clean -fd
「え、待って、今なにした?」と思ったときにはもう遅い。未コミットの変更、全部消えた。数日分の作業が一瞬で。
調べてみると、同様の報告が GitHub Issues に複数上がっていた。
- Claude Code で確認なしに
git checkoutが実行され、4日分の作業が消失(#11237、Open) - Codex CLI がパッチ適用失敗時にファイルを上書きし、1日分の作業が消失(#5904、Closed)
AI エージェントが予期せずデータを消失させてしまう問題は、珍しくないらしい。
この記事では、今回の失敗から学んだ多層防御の考え方と、Codex CLI / Claude Code それぞれの具体的な設定方法を整理する。
この記事で学べること
- 破壊的な git コマンドの種類と復旧可能性
- Codex CLI / Claude Code の安全設定(コピペで使える)
- 設定が効かないケースと Hooks による回避策
- 作業前チェックリスト
対象読者
- AIコーディングエージェントを使っている方
- 「そのうちやらかしそう」と薄々感じている方
破壊的な git コマンドと復旧可能性
まず、どんなコマンドが危険で、何が復旧できるのかを整理する。
復旧可能性の一覧
| コマンド | 何が消えるか | 復旧可能性 |
|---|---|---|
git restore . |
作業ディレクトリの変更 | ❌ 不可能 |
git restore --staged . |
ステージング | △ git fsck で一部可能 |
git clean -fd |
未追跡ファイル | ❌ 不可能 |
git reset --hard |
未コミットの変更すべて | ❌ 不可能 |
git checkout -- . |
作業ディレクトリの変更 | ❌ 不可能 |
⚠️ 重要: Git が確実に守れるのは「コミットされた変更」だけ。
ステージング済みの変更はgit fsckで一部復旧できる可能性があるが、
作業ディレクトリのみの変更はゴミ箱にも残らない。
Codex CLI の安全設定
execpolicy(.rules ファイル)
Codex CLI では、~/.codex/rules/ ディレクトリに .rules ファイルを置くことで、コマンドの実行ポリシーを設定できる。Starlark 形式で記述する。
# ~/.codex/rules/block_destructive_git.rules
# git restore を禁止
prefix_rule(
pattern = ["git", "restore"],
decision = "forbidden",
match = ["git restore ."],
)
# git clean を禁止
prefix_rule(
pattern = ["git", "clean"],
decision = "forbidden",
match = ["git clean -fd"],
)
# git reset --hard を禁止
prefix_rule(
pattern = ["git", "reset", "--hard"],
decision = "forbidden",
match = ["git reset --hard HEAD"],
)
# git checkout -- を禁止
prefix_rule(
pattern = ["git", "checkout", "--"],
decision = "forbidden",
match = ["git checkout -- ."],
)
# rm -rf を禁止
prefix_rule(
pattern = ["rm", "-rf"],
decision = "forbidden",
)
decision の種類
| 値 | 動作 | 用途 |
|---|---|---|
forbidden |
完全に禁止 | 破壊的コマンド |
prompt |
実行前に確認 | 注意が必要なコマンド |
allow |
自動で許可 | 安全なコマンド |
config.toml の設定
# ~/.codex/config.toml
# 常に確認を求める
approval_policy = "on-request"
# サンドボックスモード(workspace-write で書き込みを制限)
sandbox_mode = "workspace-write"
設定の確認
# ルールが正しく適用されるか確認
codex execpolicy check --rules ~/.codex/rules/block_destructive_git.rules -- git restore .
Claude Code の安全設定
settings.json の基本設定
.claude/settings.json に禁止ルールを記述する。
{
"permissions": {
"deny": [
"Bash(git restore:*)",
"Bash(git checkout:*)",
"Bash(git reset --hard:*)",
"Bash(git clean:*)",
"Bash(rm -rf:*)",
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)"
]
}
}
設定ファイルの優先順位
| 優先度 | ファイル | 用途 |
|---|---|---|
| 1(最高) | .claude/settings.local.json |
ローカル設定(git 管理外) |
| 2 | .claude/settings.json |
プロジェクト共有設定 |
| 3(最低) | ~/.claude/settings.json |
ユーザー設定 |
サンドボックスの有効化
{
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true,
"excludedCommands": ["docker"]
}
}
設定が効かない問題と Hooks による回避
なぜ設定が効かないのか
調べてみると、deny 設定が無視される事例が複数報告されていた。
- Claude Code Issue #6699: v1.0.93 で deny 設定が完全に無視される
- Claude Code Issue #6631: Read/Write ツールの deny が機能しない
-
Codex CLI Issue #6022:
AGENTS.mdで禁止した git checkout が実行される
原因は様々だが、設定だけに頼るのは危険。
⚠️ 注意: deny 設定はバージョンによって効かないケースが報告されている。Hooks との併用を推奨。
Hooks で確実にブロックする(Claude Code)
Claude Code の Hooks 機能を使うと、ツール実行前にスクリプトを挟める。deny 設定より確実。
.claude/hooks/block_dangerous_git.sh:
#!/bin/bash
# stdin から JSON を読み取り
json_input=$(cat)
command=$(echo "$json_input" | jq -r '.tool_input.command // empty')
# 危険なパターンをチェック
dangerous_patterns=(
"git restore"
"git clean"
"git reset --hard"
"git checkout -- "
"rm -rf"
)
for pattern in "${dangerous_patterns[@]}"; do
if [[ "$command" == *"$pattern"* ]]; then
echo "BLOCKED: '$pattern' is not allowed" >&2
exit 2 # exit code 2 = ブロック
fi
done
exit 0 # 許可
.claude/settings.json に Hook を登録:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/block_dangerous_git.sh"
}
]
}
]
}
}
Hook の動作確認
# 実行権限を付与
chmod +x .claude/hooks/block_dangerous_git.sh
# テスト(ブロックされるはず)
cat << 'EOF' | .claude/hooks/block_dangerous_git.sh
{"tool_input":{"command":"git restore ."}}
EOF
echo $? # 2 が返れば成功
多層防御の考え方
1つの防御が突破されても、次の層で止める。これがセキュリティの基本。
| 層 | 対策 | 備考 |
|---|---|---|
| 第1層 | ツールの deny 設定 | 効かないことがある |
| 第2層 | Hooks によるブロック | より確実 |
| 第3層 | チェックポイント機能 | Cursor/Cline/Windsurf |
| 第4層 | こまめなコミット | 最も確実 |
チェックポイント機能があるツール
一部の AI コーディングツールには、変更前の状態を自動保存する機能がある。
| ツール | 機能 |
|---|---|
| Cursor | 変更前に自動保存、ワンクリック復元 |
| Cline | Task 単位でスナップショット |
| Windsurf | Cascade で変更履歴を保持 |
Codex CLI / Claude Code にはこの機能がない。ここが今回ハマったポイント。
作業前チェックリスト
AI エージェントに作業を依頼する前に確認すること。
必須
-
未コミットの変更がないか確認(
git status) - 重要な変更はコミット済みか
- 安全設定(.rules / settings.json)が有効か
推奨
- Hooks スクリプトに実行権限があるか
- 長時間コミットしていないなら WIP コミット
- 重要なファイルは別途バックアップ
作業中
- AI の実行コマンドを目視確認
- 怪しいコマンドは即キャンセル(Ctrl+C)
まとめ
| 対策 | 効果 | 備考 |
|---|---|---|
| deny 設定 | △ | 効かないケースあり |
| Hooks | ○ | deny より確実 |
| チェックポイント機能 | ◎ | Cursor/Cline/Windsurf のみ |
| こまめなコミット | ◎ | 最も確実 |
AI コーディングエージェントは便利だけど、過信は禁物。
設定を入れても効かないことがある。チェックポイント機能がないツールもある。結局、こまめにコミットする習慣が一番の防御になる。
実務での使い分けのポイント:
- 設定ファイルだけに頼らない → Hooks と併用
- チェックポイント機能がないツール(Codex CLI / Claude Code) → より慎重に
- 長時間の作業 → 30分ごとに WIP コミット
- 迷ったら → こまめにコミット
今回の失敗で「数日コミットしてなかったな」と気づいたときにはもう遅かった。
参考文献
本記事は以下の情報源を参考に、筆者の実務経験を加えて執筆しました。
公式ドキュメント
- Codex CLI - Configuration
- Codex CLI - Execpolicy
- Claude Code - Settings
- Claude Code - Hooks reference
GitHub Issues
データ消失の報告
- Claude Code #11237 - git command without prompting resulting in data loss(Open)
- Codex CLI #5904 - Deleted/Reset File Without Backup(Closed)
設定が効かない問題
最後まで読んでいただきありがとうございました!
質問やフィードバックがあれば、コメントでお知らせください。