没问一声就跑了不可逆命令
Ran an irreversible command without asking
智能体为了摆脱卡住的状态,执行了强推、`rm -rf`、`git reset --hard` 或删表,工作成果或数据就没了。
适用于: Claude Code · Cursor · Codex · Copilot agent
症状
未提交的工作消失、远程分支被改写、开发或生产数据库被清空。
为什么会这样
“推倒重来”是摆脱混乱状态的捷径,除非被强制,智能体不会掂量可逆性。agent-failure-modes 列为 AFM-15 破坏性越权;developertoolkit.ai 把不安全的智能体操作归入安全类,控制点在会话层(权限、沙箱)。
示例
示意。
bash# Agent, after a merge conflict:
git reset --hard origin/main && git push --force
复制即用的修复
按你用的智能体挑选文件。规则片段用英文写,放进任何仓库都能用。
规则
Claude Code:加入 CLAUDE.md
CLAUDE.md## Irreversible actions need a human
- Never run destructive or irreversible commands without explicit approval in this conversation:
`rm -rf`, `git push --force`, `git reset --hard`, `git clean -f`, history rewrites, `DROP`/`TRUNCATE`,
`DELETE` without `WHERE`, infrastructure destroy, or anything touching production.
- When stuck, stop and describe the state and options instead of wiping it.
- Before risky local operations, make a backup branch (`git branch backup/<date>`).
规则
Codex、Copilot 编码智能体等:加入 AGENTS.md
AGENTS.md## Irreversible actions need a human
- Never run destructive or irreversible commands without explicit approval in this conversation:
`rm -rf`, `git push --force`, `git reset --hard`, `git clean -f`, history rewrites, `DROP`/`TRUNCATE`,
`DELETE` without `WHERE`, infrastructure destroy, or anything touching production.
- When stuck, stop and describe the state and options instead of wiping it.
- Before risky local operations, make a backup branch (`git branch backup/<date>`).
Cursor 规则
Cursor:项目规则
.cursor/rules/destructive-command.mdc---
description: "AgentFails: Ran an irreversible command without asking"
alwaysApply: true
---
## Irreversible actions need a human
- Never run destructive or irreversible commands without explicit approval in this conversation:
`rm -rf`, `git push --force`, `git reset --hard`, `git clean -f`, history rewrites, `DROP`/`TRUNCATE`,
`DELETE` without `WHERE`, infrastructure destroy, or anything touching production.
- When stuck, stop and describe the state and options instead of wiping it.
- Before risky local operations, make a backup branch (`git branch backup/<date>`).
钩子
Claude Code PreToolUse 钩子:拦截破坏性 shell 命令
用 matcher "Bash" 注册。正则清单是安全带,不是沙箱;备份和最小权限凭据同样要有。
.claude/hooks/block_destructive.py#!/usr/bin/env python3
"""Block high-blast-radius shell commands; the agent must ask the user instead."""
import json, re, sys
call = json.load(sys.stdin)
if call.get("tool_name") != "Bash":
sys.exit(0)
cmd = call["tool_input"].get("command", "")
dangerous = [
r"\brm\s+-[a-zA-Z]*r[a-zA-Z]*f|\brm\s+-[a-zA-Z]*f[a-zA-Z]*r", # rm -rf / rm -fr
r"\bgit\s+push\b.*(--force\b|-f\b|--force-with-lease)",
r"\bgit\s+reset\s+--hard\b",
r"\bgit\s+clean\s+-[a-zA-Z]*f",
r"\bgit\s+checkout\s+--\s+\.",
r"\b(drop|truncate)\s+(table|database|schema)\b",
r"\bdelete\s+from\s+\w+\s*;?\s*$", # DELETE without WHERE
r"\b(terraform|tofu)\s+destroy\b",
r"\bkubectl\s+delete\b",
]
for pat in dangerous:
if re.search(pat, cmd, re.IGNORECASE):
print(f"BLOCKED destructive command: {cmd!r}\n"
"Explain what you want to run and why, and let the user run it or approve it.", file=sys.stderr)
sys.exit(2)
sys.exit(0)
配置
Claude Code 权限:硬性禁止敏感路径,安装依赖前先询问
CLAUDE.md 里的规则只是上下文;权限规则由工具强制执行。按你的仓库调整路径。
.claude/settings.json{
"permissions": {
"deny": [
"Edit(./migrations/**)",
"Edit(./.env*)",
"Edit(./package-lock.json)",
"Edit(./pnpm-lock.yaml)",
"Edit(./src/generated/**)"
],
"ask": [
"Bash(npm install:*)",
"Bash(pnpm add:*)",
"Bash(yarn add:*)",
"Bash(pip install:*)",
"Bash(git push:*)"
]
}
}