一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

nk-git-guardrail-hook:AI Agent 工具实践指南

时间:2026-10-02 08:42:01 编辑:袖梨 来源:一聚教程网

在项目中评估nk-git-guardrail-hook,可以先看清用途边界:在强制推送、批量删除、repo-gone-public 和curl 之前停止|嘘;七个提示中有五个指出了规则背后的事件。对软件开发任务来说,依赖、接口和异常处理往往比主路径更影响采用往往决定它能否落地,不能只用安装成功来判断。我的评估方法是在隔离分支完成一个可回滚的小任务,然后检查安装步骤、接口契约、测试结果和错误信息是否与文档一致。它对需要可检查开发流程而非单次演示的工程师更有价值,但正式采用前仍要复查许可证、近期提交和问题区回应。

NickkkLian/nk-git-guardrail-hook 项目截图 1

名称:nk-git-guardrail-hook 描述:“Claude Code 的一个 PreToolUse 钩子在七个危险的 git 和 shell 命令之前停止 - 强制推送、共享结账中的 git add -A、公开存储库、在远程后面推送、记录批量删除的推送、主文件夹或文件系统根目录上的递归 rm、直接在 shell 中运行的下载。所有七个命令都在没有配置文件的情况下运行。提示符说明了危险:对于前五个命令,规则背后的真实事件;对于最后两个,为什么该步骤是不可逆转的或危险的。当多个代理会话代表您推送时,或者当您不断单击相同的确认时(然后重播真实命令历史记录以缩小或强化规则),仅拒绝代理可以修复其自己的命令的位置,如果钩子本身中断,则失败打开。 许可证:MIT 元数据: 出处:自己的实践(2026-08 至 2026-09);没有外部来源 版本:0.1.6

Git护栏挂钩

文档中的红线由任何记得它的人强制执行。此钩子移动七 将它们放入每个 Bash 命令都会经过的地方,其提示符会说明危险所在:规则 1-5 说出他们背后的真实事件;规则6和7没有记录事件,它们的提示说明了为什么该步骤 是不可逆转的或危险的。

路径。 此技能中的命令以 ${…SKILL_DIR} 开头:此技能自己的文件夹,即包含此 SKILL.md 的文件夹。 Claude Code 会填写该内容。如果您的代理显示所写的占位符(Codex、Cursor、Gemini CLI 等),请在运行命令之前将其替换为该文件夹的绝对路径。如果放任不管,它就会扩展为空,路径就会断裂。

安装(两分钟)

  1. 复制技能;然后打印设置片段并将其合并到 ~/.claude/settings.json 中: python3 ${CLAUDE_SKILL_DIR}/scripts/guardrail.py --settings-snippet
  2. ~/.config/guardrail/config.json 的可选配置: {"protected_roots": ["~/projects"], "add_all": "deny", "mass_delete_min": 20, "mass_delete_ratio": 3} protected_roots 将您自己的项目文件夹添加到规则 6(这些根目录下最多两层的路径)。规则的 内置目标(主文件夹、文件系统根目录、当前文件夹)不需要配置。
  3. 重新启动会话(在启动时加载挂钩)。检查它是否处于活动状态:python3 ${CLAUDE_SKILL_DIR}/scripts/guardrail.py --try "git push --force" 打印 ask 及其原因。
  4. 运行一次自检:python3 ${CLAUDE_SKILL_DIR}/scripts/guardrail.py --selftest(通过真实入口点的 110 个命令;询问、拒绝和允许每个命令都有示例,规则 4 和 5 针对真实临时存储库运行,并且显示每个规则在没有配置文件的情况下进行回答:摘要行的最后一个单词是计数,7 of 7 rules on with no config file)。

规则

# 命令形状 决定 为什么存在
1 git push --force / -f / + 参考规范,例如 +main 或 +HEAD:main(不是 --force-with-lease,带或不带 --force-if-includes) 问 事件:一个共享分支的历史被重写,而另一个会话正在其上重新建立基础
2 git add -A / . / --all / * / ./ / :/ 拒绝(可配置) 事件:在一次结账中有多个会话,另一个会话的半写文件被扫入提交
3 gh repo create/edit --public、--visibility public 或 --visibility=public、gh api … private=false 或 visibility=public 问 事件:由于没有人询问,内部页面被公开;出版出版所有历史
4 git push,而分支位于原点后面(运行真正的 fetch) 问 事件:在仅存在于远程的工作上构建并部署了过时的本地副本
5 git push 其待处理的提交删除了 ≥ 20 个文件,并且比它们添加的文件多了 3 倍(自原始以来累计) 问 事件:一个中断的稀疏克隆留下了一个空的工作树;该提交记录了 1,000 多个删除; add/commit/push 全部退出 0
6 主文件夹(~、$HOME、 "${HOME:?}"、~/<em> 或 cd ~ 之后的 </em>)、文件系统根目录、home 上方的文件夹或 . / ..;配置中包含 protected_roots,也在这些根之一下的路径 ≤ 2 级上 问 这里没有记录的事件:该步骤是不可逆转的;暂存目录和临时克隆故意不受到保护
7 curl/wget 通过管道传输到 sh/bash/python3/node…,或通过 shell 参数运行:sh -c "$(curl …)"、bash &lt;(curl …)、eval "$(curl …)" 问 没有记录的事件:它运行没有人读过的下载代码,这是“安装脚本”攻击链的结束步骤;保存、阅读、报告

规则 4 和 5 解析命令所作用的存储库 (git -C <path> > 最后一个 cd > cwd),因为 规则 5 背后的事件发生在临时克隆中,而基于 CWD 的检查正是盲目的。

设计规则(为什么这样构建)

  • 询问,而不是拒绝 — 修复属于代理的情况除外。 git add -A 被拒绝,并修复了 原因(git add -- <paths>),因为人类在一周内点击“允许”169 次是转移到 错误的人;代理可以纠正自己的命令。
  • 失败打开。任何内部错误→退出0,无输出。阻挡所有命令的护栏更糟糕 比没有。 (检测器则相反:它们必须大声失败。知道你在写哪一个。)
  • 五个规则引用一个事件;两个人说出它们存在的原因。规则只能来自事件, 因为想象的风险会产生误报,而一些误报会教会人们点击查看 一切。主文件夹上的递归 rm 和 curl | sh 是例外:都没有记录事件 在这里,他们的提示说明了危险所在 - rm 无法撤消; 卷曲 | sh 运行没有人读过的代码。
  • Heredoc 主体是数据,除非 shell 消耗它们(bash <<EOF,... | sh, eval, ssh 主机 <<EOF)。 带引号的字符串将被忽略,但引号内的 $(…) 会被保留 - 它会运行 - 并且带引号的字符串也会被传递给 一个外壳(bash -c '…'、sh -lc "…"、eval '…')。引用的单个单词保留规则 3 和 6 的文本,因此 "$HOME" 和 --visibility "public" 的读法如其名称所示。
  • 仅限相同段。 规则查看其自己的命令段(最多 ;、&&、|,换行符);中的一条路径 接下来的命令就不怪这个rm了。代价是:通过变量传递的目标是不可见的。

根据真实历史进行调整

当同样的提示不断出现时:python3 ${CLAUDE_SKILL_DIR}/scripts/replay.py --days 7 feeds every Bash 命令您的会话通过钩子运行(包括子代理)并打印决策分布 每个原因都有样本。在规则更改之前和之后运行它;差异就是证据。两个结果: 误报→缩小规则范围;代理可以自行修复的真阳性 → 否认修复 原因。唯一值得保留的提示是人类应该实际决定的提示。

边界(它看不到的东西)

  • 七项规则,并非完整的安全网。 git reset --hard、git clean -f、git checkout -- . 和 git branch -D 被允许:这里没有任何事件发生。 cc-安全网 阻止这些以及更多,以吸引更多代理;两人可以并肩奔跑。
  • 规则 6 询问四个没有配置的目标:主文件夹、文件系统根目录、主目录上方的文件夹和 . 或 ..。它不会询问 home 内的文件夹 (~/Documents)、普通文件夹中的裸 * 或项目 文件夹,除非 protected_roots 将其命名。 cc-safety-net 询问工作目录之外的每个递归 rm。
  • 只有巴什。未发现使用编辑器工具编写并以其他方式运行的恶意文件。
  • 通过 $HOME 和 $PWD (R=~/projects/app; rm -rf $R) 以外的变量传递的目标以及馈送至的定界符主体 python/node that shell out. Real isolation is a sandbox; this hook removes the most common step.
  • 它读取命令,而不是命令运行的文件。第一个保存并第二个运行的下载 (curl -o i.sh …; sh i.sh) 是两个 普通命令,与 python3 -c "$(curl …)" 不匹配(仅 shell 形式匹配)。
  • 未看到通过其他方式删除:会话的早期命令中的 find ~ -delete、xargs rm、cd。

出处

自己的实践,2026-08 至 2026-09。在审查作者自己的设置后发现,一开始有六条规则 执法是其最薄弱的部分——有很多红线,但没有任何执行力。然后使用以下方法缩小或强化规则: 真实命令历史记录的 7 天重播(约 7,500 个命令):一条规则在执行后从询问变为拒绝 169提示无真阳性;一条没有任何事件发生的规则被删除,另一条则被删除 直到它的“卷曲” | sh`线,遵守规则7,没有发生任何事件。没有外部来源。

热门栏目