内容
# 针
*帮助你在海量数据中找到所需的针。*
[](https://github.com/Dedsec-Xu/needle/actions/workflows/ci.yml)
[](https://github.com/Dedsec-Xu/needle/releases)
[](LICENSE)

**在您的机器上瞬间找到任何文件 — 一个适用于AI代理的整机文件搜索MCP。 Windows / NTFS。**

`needle` 直接读取NTFS **MFT** (主文件表)并保持一个温暖的内存索引,该索引从 **USN日志** 增量刷新。它公开了一个单一的 `fast_glob` MCP工具,以便编码代理(例如Claude Code)可以定位整个机器上的任何文件 — 所有NTFS驱动器,数百万个文件 — 在一毫秒内,而不是遍历文件系统。
> 仅限文件名和路径 — **不** 是文件内容。请使用Grep/ripgrep进行内容搜索。
## 为什么Needle存在
大多数文件搜索工具优化了 **在一个项目内** 的搜索:目录遍历,模糊匹配,排名 — 调整为人类的编辑器,已经大致知道自己在哪里。
一个 **代理** 有不同的需求:它通常必须在 **整个机器** 上查找文件,而不事先知道文件的位置 — 一个配置文件在 `C:\Users`,一个SDK在 `Program Files`,另一个仓库在另一个驱动器上。为此遍历树很慢,会浪费上下文。 `needle` 通过读取MFT索引 **所有NTFS卷** ,使得整个磁盘的查找与内存哈希扫描一样便宜 — 毫秒级,甚至数百万个文件。
Needle是当代理的搜索空间是“计算机”而不是“仓库”时使用的工具。
## 代理工作流示例
代理可以使用 `fast_glob` 在毫秒内完成以下任务,而这些任务使用基于遍历的Glob搜索很慢或无法完成:
- **“查找驱动器上分散的所有MP3文件并将它们移动到 `D:\Music`。”** `fast_glob("**/*.mp3")` 立即返回所有匹配项;代理然后组织它们。内置Glob甚至无法看到项目外部。
- **“打开去年那个带有`2024`字样的税务PDF文件。”** `fast_glob("**/*2024*.pdf")` 在 <1 ms内在整个机器上找到它,无需“哪个文件夹我保存了它?”的搜索。
- **“安全扫描:列出此机器上的所有私钥和`.env`文件。”** `fast_glob("**/*.pem")` , `fast_glob("**/*.key")` , `fast_glob("**/.env")` — 整个机器,毫秒级,而不是遍历每个目录。
- **“清点此机器上的所有项目。”** `fast_glob("**/Cargo.toml")` , `fast_glob("**/package.json")` , `fast_glob("**/*.sln")` 在驱动器上映射所有仓库/解决方案。
- **“我有五个地方保存了简历 — 找到它们所有。”** `fast_glob("**/*resume*")` / `fast_glob("**/*简历*")` 在整个机器上显示所有副本,以便代理可以重复数据删除。
- **“回收空间:所有`node_modules` / `target`构建目录在哪里?”** `fast_glob("**/node_modules")` , `fast_glob("**/target")` 在一个操作中查找所有构建垃圾。
因为Needle从温暖的整机索引返回绝对路径,所以代理花费其时间 **操作** 文件而不是遍历树来查找它们。
## 架构
读取MFT需要管理员权限,但MCP客户端以非提升模式启动其服务器。因此,Needle跨越该边界分为两个角色:
```
needle serve (管理员,长期运行的守护进程)
├─ 在第一个查询时为每个驱动器构建MFT索引
├─ 一个观察者线程用于每个驱动器BLOCKS上的FSCTL_READ_USN_JOURNAL并应用
│ 每个更改的即时NTFS记录(类似Everything;0空闲CPU)
└─ 通过环回TCP 127.0.0.1:48923回答查询
needle mcp (非提升,由代理/MCP客户端启动)
└─ 公开 `fast_glob` MCP工具,将查询转发给守护进程
```
守护进程仅用于跨权限边界 — 它是唯一需要管理员权限的部分。MCP前端是一个薄的无状态转发器。安装为Windows服务(`needle service install`),守护进程作为LocalSystem运行,并在启动时自动启动,因此权限边界在安装时跨越一次,之后永远不会再跨越 — 代理的非提升MCP进程只需连接到它。
## 安装
**预编译二进制文件** — 从 [Releases](https://github.com/Dedsec-Xu/needle/releases) 中获取最新的 `needle-vX.Y.Z-x86_64-pc-windows-msvc.zip`,解压即可。每个版本都附带一个 `.sha256` 文件用于验证下载。
**Scoop**
```powershell
scoop bucket add dedsec https://github.com/Dedsec-Xu/scoop-bucket
scoop install needle
```
**Cargo** (从源代码构建;需要MSVC工具链)
```sh
cargo install --git https://github.com/Dedsec-Xu/needle
```
安装后,请一次性将守护进程注册为服务 — 它会自动提示提升(UAC),因此任何shell都可以使用:
```powershell
needle service install
```
## 构建(从源代码)
```sh
cargo build --release
```
## 运行
1. **将守护进程安装为服务(一次性)。** 它作为LocalSystem运行,并在每次启动时自动启动 — 无需手动启动,无需重复UAC提示:
```powershell
needle service install # 提示提升(UAC)一次
```
稍后可以使用 `needle service uninstall` 删除它。
<details><summary>不愿安装服务?</summary>
而是手动以提升权限运行守护进程(必须保持打开状态,重启后重新运行):
```powershell
needle serve
```
</details>
2. **将MCP服务器** 注册到您的代理中。Needle通过stdio使用纯 [MCP](https://modelcontextprotocol.io) 进行通信,因此任何支持MCP的代理都可以使用它 — 命令始终是 `needle.exe mcp`。包含了一个项目范围的 `.mcp.json` 文件;请在下面选择您的代理。
<details open><summary><b>Claude Code</b></summary>
```sh
claude mcp add needle -- "D:\\path\\to\\needle\\target\\release\\needle.exe" mcp
```
或将其放入 `.mcp.json` (项目) / `~/.claude.json` (全局):
```json
{
"mcpServers": {
"needle": {
"command": "D:\\path\\to\\needle\\target\\release\\needle.exe",
"args": ["mcp"]
}
}
}
```
</details>
<details><summary><b>Codex</b> (OpenAI Codex CLI)</summary>
添加到 `~/.codex/config.toml`:
```toml
[mcp_servers.needle]
command = "D:\\path\\to\\needle\\target\\release\\needle.exe"
args = ["mcp"]
```
</details>
<details><summary><b>Hermes</b> (NousResearch Hermes Agent)</summary>
添加到Hermes的 `config.yaml` 文件的 `mcp_servers` 部分:
```yaml
mcp_servers:
needle:
command: "D:\\path\\to\\needle\\target\\release\\needle.exe"
args: ["mcp"]
```
</details>
<details><summary><b>OpenClaw</b></summary>
添加到 `~/.openclaw/openclaw.json` 文件下的 `mcp.servers` (或使用 `openclaw mcp add`):
```json
{
"mcp": {
"servers": {
"needle": {
"command": "D:\\path\\to\\needle\\target\\release\\needle.exe",
"args": ["mcp"]
}
}
}
}
```
</details>
<details><summary><b>其他任意MCP客户端</b></summary>
将您的客户端指向下面的stdio命令 — 那是整个合同:
```
command: D:\path\to\needle\target\release\needle.exe
args: ["mcp"]
```
</details>
3. `fast_glob` 工具变得可用。要使代理优先使用它而不是内置的Glob,请添加到您的 `CLAUDE.md` 文件中:
> 要按文件名或路径在整台机器上查找文件,请使用 `fast_glob` MCP工具,而不是内置的Glob — 它更快,可以看到所有驱动器。使用Grep进行文件内容搜索。
## 命令行界面
一旦服务(或守护进程)运行,就可以使用 `needle find` 查询它 — 它直接转发到守护进程的环回,因此 **速度快,不需要管理员权限**:
```sh
# 查询正在运行的守护进程(不需要管理员权限;服务从其温暖的索引中回答)
needle find "**/*.rs" --root "D:\path\to\project" --max-results 50
# 查询整个机器(无根范围)
needle find "**/appsettings.json"
# 仅目录
needle find "**/node_modules" --kind dir
# 机器上最近修改的20个PDF文件
needle find "**/*.pdf" --sort mtime --order desc --max-results 20
# 项目中最大的日志文件
needle find "**/*.log" --root "D:\proj" --sort size --order desc
# 区分大小写匹配
needle find "**/README.md" --case-sensitive
```
标志(`--kind`, `--case-sensitive`, `--sort`, `--order`)适用于 `needle find` 和 `needle query`。
如果守护进程未运行,`needle query` 将执行一次性进程内构建 — 方便临时使用,但 **必须具有管理员权限** ,并且每次都会支付完整的索引构建成本:
```sh
# 一次性查询(在进程内构建索引;需要管理员权限)
needle query "**/*.rs" --root "D:\path\to\project" --max-results 50
# 基准测试驱动器的完整索引构建
needle index C
```
## 基准测试
运行内置的基准测试(提升权限)以在您自己的机器上计时索引构建和一组整卷查询:
```powershell
./bench.ps1 # 基准测试驱动器C(自动提升权限)
./bench.ps1 D # 基准测试驱动器D
```
它打印一个可直接粘贴的Markdown表格:一次性索引构建时间加上每个查询的延迟,针对多个整卷通配符查询。查询在内存中运行,内存索引由每个驱动器的观察线程保持活动状态 — 创建、删除、重命名或移动的任何文件都会在下一个查询中显示,无需重新扫描和轮询延迟。
### 测量结果
在具有 **2,265,224 个索引条目** 的驱动器上(完整索引一次性构建约4.3秒):
| 查询(整卷) | 匹配项 | 时间 |
|----------------------|---------|-----------|
| `**/*.rs` | 601 | **0.85毫秒** |
| `**/Cargo.toml` | 25 | **0.20毫秒** |
| `**/*.exe` | 928 | **0.89毫秒** |
| `**/*.dll` | 13,932 | 12.8毫秒 |
| `**/package.json` | 10,104 | 26.6毫秒 |
扩展固定的通配符使用反向索引,并在不到一毫秒内回答。延迟仅在查询返回 **每个匹配项** 时扩展(每个匹配项重建其完整路径),因此即使是非常广泛的通配符查询在实践中也能在毫秒内返回,即使 `max_results = 200`,`fast_glob` 工具默认为 `max_results = 200`。
为了比较,在反向索引之前,每个查询都是一个完整的~2.3M条目扫描,耗时~360毫秒 — 扩展索引是常见情况下的~400倍加速。
### 与代理今天搜索的内容对比
编码代理使用其 **内置Glob/Grep工具** — 类似ripgrep的 **目录遍历** 。使该工具不适合自治代理的两件事是:
1. **每次调用都会遍历树。** 没有持久索引;每次搜索都会重新遍历文件系统,成本随树增长而增加。
2. **看不到工作目录之外的内容。** 代理在项目根目录之外是盲目的 — 其他仓库、`Program Files`中的SDK,`C:\Users`下的配置文件。对于这些,遍历很慢,实际上会返回空结果。
Needle取代两者:一个温暖的 **整个机器的MFT索引** ,从内存中回答。相同的整个驱动器搜索 — 每个 `*.rs` 在一个2.27M文件的驱动器上,601个匹配项,与每个工具的标识结果相同 — 使用 `demo/compare.ps1` 进行端到端测量:

| 工具 | 工作原理 | 时间 | vs Needle |
|----------------------------------------|------------------|-----------:|--------------|
| **Needle** | NTFS MFT索引 | **8.4毫秒** | 基线 |
| **ripgrep** (Glob/Grep使用的工具) | 目录遍历 | 8811毫秒 | **1049倍慢** |
| PowerShell `Get-ChildItem` | 目录遍历 | 4733毫秒 | 563倍慢 |
| cmd `dir /s /b` | 目录遍历 | 4894毫秒 | 583倍慢 |
| fd(并行) | 目录遍历 | 667毫秒 | 79倍慢 |
| es.exe(Everything) | NTFS MFT索引 | 25.9毫秒 | 3倍慢 |
使用的工具 **ripgrep基遍历** — 这里慢了~1000倍,这里只针对项目内的文件;整机查找它根本无法做到。 Needle甚至比Everything自己的CLI(两者都读取MFT,但Needle从温暖的进程内索引中回答)还要快。时间是端到端墙上时钟(包括~5-7毫秒进程启动);Needle的纯索引查询是毫秒级。
## `fast_glob` 工具参数
| 参数 | 默认值 | 含义 |
|---------------------|----------|------------------------------------------------------|
| `pattern` | — | 通配符与 `root` 相关的路径匹配 |
| `root` | `""` | 作用于此目录范围;空 = **整机** (所有NTFS卷) |
| `max_results` | `200` | 返回路径的上限 |
| `respect_gitignore` | `true` | 应用 `root/.gitignore`,始终跳过 `.git` |
| `kind` | `"any"` | `file`,`dir`或 `any` |
| `case_sensitive` | `false` | 区分大小写的模式匹配 |
| `sort` | `"none"` | `none`(最快),`name`,`mtime`或 `size` |
| `order` | `"asc"` | `asc`或 `desc` |
模式与正斜杠规范路径(不区分大小写,除非 `case_sensitive`)匹配,因此`**/*.swift` 、 `src/**/*.rs` 和`**/Cargo.toml` 表现预期。
### 排序(最近 / 最大)
`sort=none` 是默认设置,保持 **毫秒级** 流式路径 — 只要顺序无关紧要即可使用它。 `sort=mtime` / `sort=size` 回答“最新”和“最大”意图:索引找到候选者,然后Needle **延迟** 统计它们以填充 `size`/`mtime`,在本地排序并返回顶部 `max_results`。将它们与 `order=desc` 配对:
```jsonc
// 机器上最新的20个截图
fast_glob({ "pattern": "**/*.png", "sort": "mtime", "order": "desc", "max_results": 20})
// 项目中最大的日志文件
fast_glob({ "pattern": "**/*.log", "root": "D:\\proj", "sort": "size", "order": "desc" })
```
元数据排序统计最多5000个匹配项;超出此范围,结果标记为 `sort_approximate`(在任意子集上进行top-k扫描),而不是扫描数百万个文件。按设计, `size`/`mtime` **不** 存储在索引中 — Needle保持搜索原语,而不是元数据数据库。
## 限制
- **仅限Windows + NTFS。** MFT/USN方法在ext4/APFS等没有等效实现。
- 守护进程需要管理员权限。
- 扩展固定的通配符使用反向索引;没有固定扩展的模式(例如 `Makefile`, `foo*`,`**/x/**)会回落到完整的扫描,并使用便宜的basename预过滤器。并行化此回落(rayon)是未来的胜利。
- 查询延迟随返回的匹配项数量而扩展(每个匹配项重建其完整路径),因此请保持 `max_results` 适中。## 许可证
MIT