内容
# splinter
[](https://github.com/yesitsfebreeze/splinter/actions/workflows/ci.yml)
[](LICENSE)
基于MCP的函数级代码索引,具有每个文件持久的代理内存。每次加载一个函数而不是整个文件;一次调用即可跨所有函数搜索。
## 安装
```bash
/plugin marketplace add yesitsfebreeze/splinter
/plugin install splinter@yesitsfebreeze
```
无需工具链 — 在第一次运行时,插件会为您的平台(linux x86_64/aarch64,macOS x86_64/aarch64)下载预编译的二进制文件并缓存。语言语法也会以相同的方式下载:第一次索引某种语言时,其tree-sitter语法会被获取一次并在整个机器上缓存(参见[语言](#languages))。其他平台:[从源代码构建](#build-from-source)。
## 默认使用
插件使Claude自动进行索引优先 — 两层,无需设置:
- **技能**是自动发现的,因此Claude知道工具以及何时使用它们。
- **`SessionStart`钩子**在每个会话中注入导航规则:*使用`search_bodies`/`open_source`/`read_splinter` → `read_body`,并且仅当这不够时才`Read`/`Grep`整个文件。* 非阻塞 — 它从不阻止读取,只是排序。
可选的额外强化 — 在您的项目`CLAUDE.md`中添加一行:
```md
使用`splinter` MCP工具来探索代码(splinter技能):`open_source` → 函数映射,`read_body` → 一个函数,`search_bodies` → grep,`read_splinter`/`write_splinter` → 每个文件的内存。编辑源代码;索引会跟随。
```
## 工作原理
```
src/parser.rs → .splinter/src/parser.skel.rs 骨架(主体替换为// §<ref>)
.splinter/src/parser.splinter.md 代理内存
.splinter/src/parser/parse.fs 每个文件一个函数
.splinter/src/parser/load.fs
```
- 源代码是真实的;`.splinter/`是一个派生的缓存。单向观察器:源代码更改 → 重新分割。
- 分割使用每种语言的[tree-sitter](https://tree-sitter.github.io/)语法进行解析;每种语言的查询定义了什么是函数(参见[语言](#languages))。无LSP,无实时服务器 — 在分割时解析一次,然后所有内容都是静态文件。
- `.fs`主体是只读的 — 编辑源代码。主体行1(`// §head src/parser.rs:42-89 parse`)映射回源代码行;可选的`// §sig …`行后面跟着函数的声明。标记行永远不计为代码。
- `*.splinter.md`是持久内存:创建一次,重新分割时从不覆盖,通过下面的`.gitignore`排除项提交。
## 工具
| 工具 | 功能 |
|---|---|
| `index_dir(src_dir)` | 引导:分割整个树,每个已安装的语言一次(跳过隐藏/构建/供应商目录) |
| `open_source(path)` | 函数列表(带有签名)按大小 + 文件的splinter注释 |
| `read_body(path)` | 一个函数主体(`.fs`路径 — 绝对,相对存储库或索引相对) |
| `search_bodies(query)` | 跨所有函数使用Ripgrep;命中映射回`source:line [fn]` |
| `grep_files(query)` | 在根目录下使用Ripgrep原始源代码;命中归因于所属函数 — 甚至可以找到未索引的文件 |
| `search_names(query)` | 函数名称 + 源代码路径(非内容)使用Ripgrep;返回路径,标记便宜 |
| `ref_graph(path)` | 调用图:调用者(`in`)+ 被调用者(`out`)用于函数名称或`.fs`主体 |
| `list_bodies(dir)` | 目录中的函数,按大小 |
| `find_large()` | 函数超过`SPLINTER_MAX_LOC` |
| `read_splinter` / `write_splinter` | 读取/写入每个文件的内存 |
| `list_languages()` | 已安装的语言 |
另外:`split`,`dry_run_split`,`grep_source`,`validate`,`body_stats`,`diff_body`,`outline`。
搜索由ripgrep自己的crates(`grep` + `rayon`)提供,在索引上并行运行 — 与`rg`具有相同的匹配器质量,并在上面添加splinter的函数级归因。
## 配置
环境变量或可提交的`splinter.ini`(环境 > ini > 默认)。
| 变量 | 默认值 | 目的 |
|---|---|---|
| `SPLINTER_SRC_DIR` | `src` | 监视的源代码目录 |
| `SPLINTER_EXT` | 所有已安装的语言 | 限制索引/监视到逗号分隔的扩展列表 |
| `SPLINTER_MAX_LOC` | `256` | ⚠ / `find_large`阈值 |
| `SPLINTER_DEBOUNCE_MS` | `500` | 监视器去抖动 |
| `SPLINTER_EXCLUDE` | — | 索引时要跳过的额外目录名称(逗号分隔;隐藏的/`target`/`node_modules`始终被跳过) |
## 语言
splinter包含[tree-sitter](https://tree-sitter.github.io/)并自动处理语言:`rs`,`py`,`odin`,`go`,`php`,`html`,`cpp`(+ `c`/头文件),`js`(+ `jsx`/`mjs`/`cjs`),`ts`(+ `tsx`/`mts`/`cts`),`java`,`cs`,`kt`(+ `kts`),`swift`,`sh`(+ `bash`),`lua`,`rb`,`sql` — 无需安装或配置每种语言。
语法**下载,而不编译**:每种语言的预编译语法wasm来自其在第一次使用时固定的官方发布版本,并在整个机器上缓存到`~/.config/splinter/grammars/`(所有语法大约18MB)。解析器在splinter的嵌入式wasm运行时运行 — 无需编译器,无需node,无需tree-sitter CLI,无需任何语言工具。唯一的网络要求是每台机器每种语言一次。
什么是函数是一个小的每语言查询(`queries/*.scm`)编译到二进制文件 — 捕获`@def`和`@name`及`@body`,以及可选的`@qualifier` / `@container`模式用于方法限定。无主体声明永远不会与`@body`匹配,因此通过构造跳过原型,特征签名和抽象方法。SQL发布语法wasm,而是通过模式层分割 — 定义正则表达式和语言自己的作用域分隔符(`$tag$…$tag$`, `BEGIN…END`)— 相同的函数级主体。未知扩展名(和语法失败,例如离线和冷缓存)存储整个文件为一个主体。
添加其他语言而不需修改splinter:在`.splinter/languages/<ext>.wasm`(项目)或`~/.config/splinter/languages/<ext>.wasm`(用户)中放置tree-sitter语法,并将提取查询放在其旁边为`<ext>.scm`;解析项目 > 用户 > 默认。如果wasm的语法名称与扩展名不同,请以第一行`; grammar: <name>`指令在查询中命名。
## .gitignore
```
.splinter/**
!.splinter/**
!.splinter/**/.splinter.md
```
## 从源代码构建
```bash
cargo install --git https://github.com/yesitsfebreeze/splinter
```
启动器覆盖:`SPLINTER_BIN=/path/to/splinter`使用本地构建(跳过下载);`SPLINTER_DOWNLOAD_BASE=<url>`从备用镜像下载二进制文件而不是GitHub发布。
## 开发/发布
- `cargo test` · `cargo clippy --all-targets -- -D warnings` · `cargo fmt` — CI强制执行这三个。测试演练真实语法,因此第一次运行会下载它们(CI缓存语法目录以`src/language.rs`为键)。
- **版本是单一来源:** `.claude-plugin/plugin.json`持有**版本。** 启动器在运行时读取它并下载确切的`v<that>` — `bin/splinter`中没有重复版本。
- **自动更新:** 预推钩子在每次推送到`master`时更新锁定的版本(`Cargo.toml`,`Cargo.lock`,`plugin.json`,`marketplace.json`)。在每个克隆中启用一次:`git config core.hooksPath .githooks`。使用`SPLINTER_NO_BUMP=1 git push`跳过。 它重新推送,以便更新随同一次`git push`,因此git打印一个无害的`failed to push some refs`(原始推送被取代)— 推送成功,树保持干净。标签/功能分支不更新。
- **自动发布:** `release.yml`在每次推送到`master`时运行;如果当前`plugin.json`版本尚未发布,它会构建每个平台的二进制文件并发布`v<version>`。因此,每个发布的版本都有可下载的二进制文件。(手动推送`vX.Y.Z`标签也可以。)
## 许可证
MIT