0xByteBard404/readignore
GitHub: 0xByteBard404/readignore
readignore 通过生成 .readignore 文件并将其适配为各 AI 编码代理的原生防护机制,防止代理在运行时读取仓库中的敏感文件和密钥。
Stars: 0 | Forks: 0
# readignore
**English** | [中文](README.zh-CN.md)
**AI 编码代理的 `.gitignore` —— 声明你的 AI 代理绝对不能读取的文件。**
[](https://github.com/0xByteBard404/readignore/actions/workflows/ci.yml)
[](https://goreportcard.com/report/github.com/0xByteBard404/readignore)
[](https://github.com/0xByteBard404/readignore/blob/main/LICENSE)
[](https://go.dev/)
🌐 **网站**: [readignore.vercel.app](https://readignore.vercel.app)
AI 编码代理(Claude Code, Cursor, Codex, opencode, kilo code, …)在运行时可以读取仓库中的
任何文件——**包括机密信息**,如 `.env`、`*.pem`、
`id_rsa`、`credentials.json`。现有的防御机制存在漏洞:
- `.gitignore` 仅能阻止 **git** 进行提交;代理依然能读取该文件。
- Claude Code 的 `permissions.deny: Read(.env)` 仅拦截了 **Read** 工具——
代理可以通过 `Grep`、`Glob` 或 `Bash` 绕过(执行 `grep . .env` 即可奏效)。
**readignore** 通过一个 `.readignore` 文件(使用 gitignore 语法)填补了这一漏洞,该文件会被适配转化为每个代理的原生防御机制——并作用于该代理实际支持的最高强度级别。
## 工作原理
你只需编写一个声明式的 `.readignore` 文件。readignore 会将其转化为每个目标代理**可用的最强机制**——并**如实标注**各自的执行强度,因为各个代理的能力并不对等。
## 能力矩阵
readignore 会将 `.readignore` 适配为每个代理最强的*真实*机制。
强度等级是**真实的**,而非营销噱头:
| 代理 | 强度 | 机制 | 状态 |
|---|---|---|---|
| **Claude Code** | **hard** | `PreToolUse` hook——在工具运行**之前**拦截调用(Read, Grep, Glob, Bash)。运行时的程序化拦截。 | ✅ 已发布 |
| **codex CLI** | **hard** | `.codex/hooks.json` Claude 风格的 `PreToolUse` hook(bash,调用 `readignore match`)。与 Claude Code 采用相同的运行时拦截机制;首次运行时需要信任 hook。详情见下方的 [codex 说明](#codex-platform-note)。 | ✅ 已发布 |
| **pi** | **hard** | `.pi/extensions/readignore.ts` TypeScript 扩展,该扩展会**重写**内置的 `read` 工具——调用 `readignore match`,并在读取文件之前对匹配的路径返回 `Access denied`。在启动时自动加载。 | ✅ 已发布 |
| **opencode** | **config** | `opencode.json` 中的 `permission.read` 拒绝/允许通配符;在 opencode 加载配置时生效。 | ✅ 已发布 |
| **Cursor** | soft | `.cursor/rules` 自然语言建议(模型可能会遵从)。 | 🗓 路线图 |
| **kilo code** | config | `kilo.json` 中的 `permission.read` 拒绝/允许通配符;在 kilocode 加载配置时生效。 | ✅ 已发布 |
### “强度”的含义
- **hard** —— 代码在工具执行*之前*(或在其输出到达模型之前)运行,并且可以拒绝调用。
目前有三种形式,均在运行时被切实执行:
- **Claude Code / codex** —— 一个 `PreToolUse` hook 脚本返回
`permissionDecision: "deny"`,随后该工具**永远不会执行**。
- **pi** —— 一个注册了与内置 `read` 工具同名的 TypeScript 扩展会*重写*它;匹配的路径将返回 `Access denied`,且文件永远不会被读取。
- **config** —— readignore 写入原生的拒绝配置(如 opencode 的
`permission.read`)。其执行取决于代理是否能如实地加载它。
opencode 的程序化 `permission.ask` hook 目前在运行时是不起作用的([opencode #7006](https://github.com/anomalyco/opencode/issues/7006)),因此我们暂时还无法在此达到
`hard` 级别。
- **soft** —— 一条要求模型*遵守*的自然语言规则。无强制执行力。针对 Cursor 类工具的未来适配器将归入此类。
readignore **并不**承诺跨代理的等效性。它会自动适配为每个代理实际能够强制执行的机制。
## 快速开始
```
# 1. 安装(npm —— 无需 Go;其他选项见下文的 Installation)
npm i -g readignore
# 2. 在你的 repo 中:
cd your-repo
readignore init # generates .readignore with common secret patterns
# 3. 编辑 .readignore 以匹配你的项目,然后为你的 agent(s) 安装:
readignore install claude-code # single agent
readignore install codex # codex CLI (Claude-style PreToolUse hook)
readignore install pi # pi (.pi/extensions/ TS override, auto-loaded)
# 或者为在此 repo 中检测到的每个 agent 安装:
readignore install --all
```
除非你传递 `--force` 参数,否则 `init` 会拒绝覆盖现有的 `.readignore` 文件。
## 命令
```
# 生成 .readignore 模板(包含 .env, *.pem, id_rsa, .aws/, … 等模式)
readignore init [--force]
# 列出已注册的 adapter 及其强度,以及在此 repo 中的检测状态
readignore adapters
# Dry-run:解析 .readignore 并打印 adapter 将会生成的内容(stdout)
readignore generate claude-code
readignore generate codex
readignore generate pi
readignore generate opencode
# 将 adapter 的输出写入磁盘
readignore install claude-code # one adapter
readignore install --all # all adapters detected here
readignore install claude-code --force # overwrite existing files
# 将 adapter 的文件刷新至当前的 readignore 版本(= install --force)
readignore update # all adapters detected (default = --all)
readignore update claude-code # one adapter
# 移除 adapter 生成的文件(install 的逆操作)
readignore uninstall claude-code # one adapter
readignore uninstall --all # all adapters detected here
readignore uninstall claude-code --dry-run # preview only, don't delete
# 验证 .readignore 语法并报告每个 adapter 的安装状态
readignore check
# 检查某个路径是否被 .readignore 拒绝(exit 0=允许,1=拒绝)
# 这就是 hooks 在 runtime 调用的内容 —— 你可以直接用它进行 debugging
readignore match .env
```
如果目标文件已存在,除非你传递 `--force` 参数,否则 `install` 会**跳过它**(并提示你手动合并)。这可以避免覆盖你现有的
`.claude/settings.json` 或 `opencode.json`。
## `.readignore` 语法
100% 兼容 gitignore。零学习成本:
```
# readignore —— 此 repo 的 AI agent 禁止读取的文件
# Secrets & keys
.env
.env.*
!.env.example # ! un-ignores (negation): allow the template through
*.pem
*.key
# SSH / cloud credentials
**/id_rsa
.aws/
.gcp/
# Sensitive directories
secrets/
credentials.json
# 末尾的 / 仅锚定到目录
build/
```
支持:`*`、`**`、`?`、`[abc]` 字符匹配、`!` 取反
(最后匹配生效,与 gitignore 完全相同)、用于锚定目录的尾部 `/`、
`#` 注释。请参阅 [gitignore 规范](https://git-scm.com/docs/gitignore)。
## 生成的内容
### Claude Code (`readignore install claude-code`)
在 `.claude/` 目录下生成两个文件:
```
.claude/hooks/readignore.sh (0755) # extracts target path, calls `readignore match`
.claude/settings.json # registers the hook on PreToolUse
```
该 hook 会在 `Read | Grep | Glob | Bash` 时触发,调用 `readignore match `
(gitignore 匹配的 **go-git 权威标准**),并在路径匹配时**在执行前拒绝**(`exit 1` = 拒绝)。Claude Code 的设置监听器会实时获取更改——**无需重启**。
**编辑 `.readignore` 会立即生效**——hook 会在每次调用时通过 `readignore match` 重新读取
`cwd/.readignore`,因此在编辑规则后你永远无需重新运行
`install`。与 `.gitignore` 一样提供即编即用的体验。
### opencode (`readignore install opencode`)
生成一个包含 `permission.read` 拒绝/允许通配符的 `opencode.json`:
```
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"read": {
".env": "deny",
".env.*": "deny",
".env.example": "allow"
}
}
}
```
opencode 会在启动时读取此配置。
### codex CLI (`readignore install codex`)
在 `.codex/` 目录下生成两个文件,镜像映射了 Claude Code 的目录结构:
```
.codex/hooks/readignore.sh (0755) # extracts target path, calls `readignore match`
.codex/hooks.json # registers the hook (Claude-style PreToolUse)
```
codex 的 hook 协议采用 [Claude 风格](https://github.com/openai/codex)
(`PreToolUse` + `permissionDecision: "deny"`),因此可以运行相同的 bash hook——它
调用 `readignore match`(go-git 权威标准)并在工具执行前拒绝调用。与
Claude Code 一样,**编辑 `.readignore` 会立即生效**
(无需重新安装)。
#### codex 平台说明 —— 仅限 Bash 的 hook 触发器
与 Claude Code 不同,**codex 没有独立的 `Read` / `Grep` / `Glob` 工具**。
codex 代理完全通过 **shell 命令**(`cat .env`、
`head -n 50 file`、`grep pattern file`)来读取文件。因此,`PreToolUse` hook *原生*仅会在 `tool_name="Bash"` 时触发(目标路径包含在
`tool_input.command` 中),并且 readignore 的匹配器会从该
`command` 字符串中提取路径。
`hooks.json` 中的 `matcher: "Read|Grep|Glob|Bash"` 是刻意为之的,并不是 bug:
- 它保持了 codex 适配器与 Claude Code 适配器的**对称性**(相同的
共享 bash hook,均调用 `readignore match`);
- 它涵盖了安装了向 codex 暴露 `Read`/`Grep`/`Glob` 的 **MCP 工具**的用户——这些
MCP 工具也会被拦截。
但对于 codex 的**原生**工具集,只有 `Bash` 分支会被触发。原生
的“读取此文件”调用始终是一个 Bash 命令,而该 hook 确实可以拦截它。
### pi (`readignore install pi`)
生成一个单一的 TypeScript 扩展:
```
.pi/extensions/readignore.ts (0644) # overrides pi's built-in `read` tool
```
pi 在启动时[自动加载 `.pi/extensions/*.ts`](https://github.com/earendil-works/pi-coding-agent)。
该扩展注册了一个名为 `read` 的工具——与 pi 的
内置工具同名——从而**重写**它:它会调用 `readignore match `(go-git
权威标准),并且匹配的路径在文件被读取前就会返回 `Access denied`;其他所有操作则委派给正常的读取流程。由于未导入任何 pi 类型,因此该
文件可以独立进行类型检查。与 hook 适配器一样,**编辑
`.readignore` 会立即生效**。
## 安装
**npm(推荐——无需 Go):**
```
npm i -g readignore # or: npx readignore
```
npm 包装器的 `postinstall` 脚本会从 [GitHub Releases](https://github.com/0xByteBard404/readignore/releases) 为你的平台下载相应的 Go 二进制文件。
**`go install`(如果你使用的是 Go 1.25+):**
```
go install github.com/0xByteBard404/readignore/cmd/readignore@latest
```
**二进制下载:**从 [Releases](https://github.com/0xByteBard404/readignore/releases) 获取适用于你平台的压缩包,解压,并将 `readignore` 放入你的 PATH 中。
**`curl | sh` 一键脚本(Linux / macOS,无需 Go 或 npm):**
```
curl -fsSL https://raw.githubusercontent.com/0xByteBard404/readignore/main/install.sh | sh
```
该脚本会检测你的操作系统/架构,从最新版本中获取相应的二进制文件和 `checksums.txt`,验证 SHA256,并将 `readignore` 安装到 `/usr/local/bin`(如果失败则回退到 `~/.local/bin`,并在需要时提供 PATH 提示)。
Windows 用户:请使用 npm、Scoop 或 Releases 中的 `.zip` 文件。
**Homebrew:**
```
brew tap 0xByteBard404/tap
brew install readignore
```
(需要 `0xByteBard404/homebrew-tap` 仓库。)
**即将推出:** Scoop (Windows)。
## 为什么不直接用 `.gitignore` 或 `permissions.deny`?
| 方案 | 无法拦截的情况 |
|---|---|
| `.gitignore` | 代理在运行时读取文件(gitignore 仅拦截提交)。 |
| Claude Code `permissions.deny: Read(.env)` | `Grep`、`Glob`、`Bash`(`grep . .env`)均可绕过。 |
| 按代理手动配置 | 在 5 个以上的代理中重复工作;容易产生不同步。 |
readignore 采用**一次声明,按代理适配**的方式,作用于每个代理最强的
执行点。
## 项目状态
v0.3.0 —— 三个 **hard** 适配器(Claude Code、codex CLI、pi)+ 一个 **config**
适配器。所有 hook 现在都会调用 `readignore match`(go-git 权威标准),
因此**编辑 `.readignore` 会立即生效**——无需重新安装。
通过 npm、`curl | sh` 或 Homebrew 安装。Cursor 和 kilo code 适配器已列入
路线图。
有关版本历史,请参阅 [CHANGELOG.md](./CHANGELOG.md)。
## 许可证
[MIT](./LICENSE) © 2026 0xByteBard404
标签:AI编程助手, EVTX分析, Go, Ruby工具, SOC Prime, Streamlit, StruQ, 密钥保护, 开发工具, 日志审计, 暗色界面, 访问控制