你让 Claude Code/Codex 等智能体 改个项目。它为了理解上下文,顺手 cat .env——你的数据库密码就这么进了模型上下文。而你浑然不觉。
用了 .gitignore 就安全了?不。
.gitignore 只挡住 git 提交,挡不住 AI 编程智能体在运行时读取文件。Claude Code、Cursor、Codex、opencode……这些智能体可以读你仓库里的任何文件——包括密钥:.env、*.pem、id_rsa、credentials.json。
你可能会说:我在 Claude Code 里配了 permissions.deny: Read(.env)。
还不够。它只挡住了 Read 工具。智能体可以用 Grep、Glob 或 Bash 绕过:
grep . .env # 走的是 Bash,不是 Read
cat id_rsa
Read 这条路堵了,Bash 那条路还敞着——grep 也是一次工具调用,照样把密钥塞进上下文。
这就是 readignore 要补的缺口。
readignore 是什么
AI 编程智能体的 .gitignore。
你写一份 .readignore(100% gitignore 语法,零学习成本),声明哪些文件 AI 智能体禁止读取。readignore 把这一份声明,适配成每个智能体**当前真正支持的最强防御机制。
# readignore —— 本仓库 AI 智能体禁止读取的文件
# 密钥
.env
.env.*
!.env.example # ! 取反:放行模板
*.pem
*.key
# SSH / 云凭证
**/id_rsa
.aws/
.gcp/
# 敏感目录
secrets/
credentials.json
关键在于:它不假装跨智能体等价。每个智能体能做到的强度不一样,readignore 适配到各自实际能强制的那个点,并诚实标注。
能力矩阵:强度诚实分级
| 智能体 | 强度 | 机制 | 状态 |
|---|---|---|---|
| Claude Code | hard | PreToolUse 钩子——在工具调用执行前拦截 Read / Grep / Glob / Bash | ✅ 已发布 |
| codex CLI | hard | .codex/hooks.json,Claude-style PreToolUse 钩子 | ✅ 已发布 |
| pi | hard | .pi/extensions/readignore.ts 覆写内置 read 工具 | ✅ 已发布 |
| opencode | config | opencode.json 的 permission.read deny / allow glob | ✅ 已发布 |
| Cursor | soft | .cursor/rules 自然语言建议(模型可能遵守) | 🗺 路线图 |
| kilo code | — | 机制待定 | 🗺 路线图 |
“强度”到底是什么意思
- hard:代码在工具执行前(或输出到达模型前)运行,能直接拒绝这次调用。三种形态:
- Claude Code / codex:一个
PreToolUse钩子脚本返回permissionDecision: "deny",工具根本不会执行。 - pi:一个 TypeScript 扩展,以与内置
read工具同名注册从而覆写它;匹配的路径返回Access denied,文件根本不会被读取。
- Claude Code / codex:一个
- config:写出原生 deny 配置(如 opencode 的
permission.read)。能否生效取决于智能体是否忠实加载它。opencode 的permission.ask程序化钩子目前在运行时是空操作(opencode issue #7006),所以暂时到不了 hard。 - soft:一条自然语言规则,请求模型遵守,无强制力。Cursor 风格工具的未来适配器会落在这里。
同一份 .readignore,在不同智能体上落到的防线强度不同。
工作原理
你只维护一份 .readignore,readignore 翻译成每个目标智能体的原生机制。
快速开始
# 安装(任选其一)
npm i -g readignore
# 或(Linux / macOS,无需 Go / npm)
curl -fsSL https://raw.githubusercontent.com/0xByteBard404/readignore/main/install.sh | sh
# 或(有 Go 1.25+ 环境)
go install github.com/0xByteBard404/readignore/cmd/readignore@latest
# 在你的仓库里
cd your-repo
readignore init # 生成 .readignore,内置常见密钥模式
# 编辑 .readignore 使之匹配你的项目,然后:
readignore install claude-code # 单个智能体
readignore install --all # 或:为本仓库检测到的全部智能体
init 拒绝覆盖已有的 .readignore(除非 --force);install 遇到已有配置文件会跳过并提示手动合并(除非 --force),避免覆盖你已有的 .claude/settings.json 或 opencode.json。
各适配器到底生成了什么
Claude Code(hard)
.claude/hooks/readignore.sh (0755) # 提取目标路径,调 readignore match
.claude/settings.json # 在 PreToolUse 上注册钩子
钩子在 Read | Grep | Glob | Bash 时触发,调用 readignore match <path> 做权威匹配,路径命中(exit 1 = deny)时在执行前拒绝。Claude Code 的 settings 监听器会实时感知变更,无需重启。
codex CLI(hard)
.codex/hooks/readignore.sh (0755)
.codex/hooks.json # Claude-style PreToolUse 钩子
codex 的钩子协议与 Claude Code 一致(permissionDecision: "deny"),共用同一套 bash 钩子。
一个诚实的平台说明:codex 没有独立的 Read / Grep / Glob 工具,agent 读文件一律走 shell 命令(cat .env、grep pattern file)。所以 PreToolUse 钩子原生只在 tool_name="Bash" 时触发,readignore 的匹配器从该 command 字符串里抽取路径参与匹配。原生「读文件」调用始终是 Bash 命令,而这条路径钩子确实会拦。项目级钩子首次运行需通过 codex 的信任提示。
pi(hard)
.pi/extensions/readignore.ts (0644) # 覆写 pi 内置 read 工具
pi 启动时自动加载 .pi/extensions/*.ts。该扩展注册一个名为 read 的工具——与内置工具同名——从而覆写它:匹配的路径在文件被读取前返回 Access denied,其余情况委托给正常读取。不引入任何 pi 类型,文件可独立通过类型检查。
opencode(config)
{
"permission": {
"read": {
".env": "deny",
".env.*": "deny",
".env.example": "allow"
}
}
}
opencode 启动时读取。注意 opencode 的 glob 引擎没有 gitignore 的顺序 / 取反语义,readignore 用「更具体的 allow 击败更宽泛的 deny」来近似 ! 取反——常见场景正确,复杂取反链可能与 gitignore 不一致。若依赖复杂取反,优先用 Claude Code 适配器(完整 gitignore 语义)。
核心价值:改完立即生效
这是我最想强调的一点。
所有钩子现在统一调用 readignore match 子命令(基于 go-git 的 format/gitignore 引擎,权威匹配)。钩子每次工具调用都实时重读 cwd/.readignore。
意味着什么?改 .readignore 立即生效,无需重新 install——和 .gitignore 一样改完即用。
以前改 .readignore 后必须重跑 install,把模式重新冻结进生成的钩子文件。现在这层去掉了:.readignore 是唯一真相,钩子只是个调用 readignore match 的薄壳。
为什么不直接用现有方案
| 方案 | 漏掉什么 |
|---|---|
.gitignore | 智能体运行时仍会读取文件(gitignore 只挡提交) |
Claude Code permissions.deny: Read(.env) | Grep / Glob / Bash(grep . .env)可绕过 |
| 每个智能体单独手配 | 5+ 个智能体间重复劳动,容易失同步 |
readignore 用一份声明替代逐个手配,每个智能体落到自己能做到的最强防线。
项目状态
三个 hard 适配器(Claude Code、codex CLI、pi)+ 一个 config 适配器(opencode)。Cursor、kilo code 在路线图上。许可证 MIT。
- GitHub:0xByteBard404/readignore
- 安装:npm /
curl | sh/ Homebrew / go install / Releases 二进制
如果你在用 Cursor、kilo code 或其他智能体,欢迎来开 issue 讨论适配器设计——每个适配器实现一个小的 Adapter 接口,并在 init() 中自注册。
如果你也担心 AI 智能体读到不该读的文件,花一分钟试试:
npm i -g readignore && readignore init && readignore install --all
📦 项目地址:github.com/0xByteBard4…
Star / Issue / PR 都欢迎。如果觉得有用,点赞 + 收藏支持一下,关注我追后续 Agentic 系列👇