Repomix 代码压缩(--compress)实战指南:用 Tree-sitter 精炼代码结构、降低 LLM Token 消耗
【免费下载链接】repomix📦 Repomix is a powerful tool that packs your entire repository into a single, AI-friendly file. Perfect for when you need to feed your codebase to Large Language Models (LLMs) or other AI tools like Claude, ChatGPT, DeepSeek, Perplexity, Gemini, Gemma, Llama, Grok, and more.项目地址: https://gitcode.com/GitHub_Trending/rep/repomix
代码压缩(Code Compression)是 Repomix 的一项实验性核心能力:它基于 Tree-sitter 语法解析,在保留 imports、exports、类、函数、接口等关键结构的同时,剥离函数体、循环与条件逻辑等实现细节,从而显著降低打包输出中的 Token 数量。本文以官方指南为主体,结合仓库源码(fileProcessContent.ts、parseFile.ts、TypeScriptParseStrategy.ts 等)逐层剖析其原理、用法、配置与边界,读完后你将能熟练用--compress为 LLM 生成"骨架级"代码包,并理解其内部为何能做到"尽力而为、永不崩溃"。
[!NOTE] 代码压缩属于实验性功能,Repomix 官方声明它将基于用户反馈与真实使用场景持续改进(见 code-compress.md)。
基本用法:一条命令开启压缩
启用代码压缩只需在 CLI 中添加--compress标志:
repomix --compress该标志在 CLI 定义中的完整说明是"使用 Tree-sitter 解析提取核心代码结构(类、函数、接口)",位于 cliRun.ts 的 Repomix Output Options 分组下。压缩对远程仓库同样生效,可与--remote组合使用:
repomix --remote user/repo --compress默认输出文件名仍为repomix-output.xml(可通过-o, --output <file>覆盖),因此压缩前后除内容密度不同外,其余输出流程完全一致。
压缩的工作原理:留下骨架,删去血肉
压缩算法使用 Tree-sitter 将源码解析为抽象语法树(AST),再通过针对每种语言的查询(query)与解析策略(parse strategy)提取并保留必要的结构元素、剔除实现细节。
压缩后保留的元素
- 函数与方法的签名(参数、返回类型等)
- 接口与类型定义
- 类结构与类属性
- 其他关键结构元素(如枚举、导入语句、装饰注释)
压缩后移除的元素
- 函数与方法的实现体
- 循环与条件语句的逻辑细节
- 内部变量声明
- 一切与实现相关的代码
一个直观的示例
原始 TypeScript 代码:
import { ShoppingItem } from './shopping-item'; /** * Calculate the total price of shopping items */ const calculateTotal = ( items: ShoppingItem[] ) => { let total = 0; for (const item of items) { total += item.price * item.quantity; } return total; } // Shopping item interface interface Item { name: string; price: number; quantity: number; }压缩后:
import { ShoppingItem } from './shopping-item'; ⋮---- /** * Calculate the total price of shopping items */ const calculateTotal = ( items: ShoppingItem[] ) => { ⋮---- // Shopping item interface interface Item { name: string; price: number; quantity: number; }可以看到:import语句原样保留;calculateTotal的完整签名连同上方 JSDoc 注释被保留,但函数体被截断;interface Item因属于类型定义而完整保留。不同结构块之间以⋮----分隔。
源码级原理:Tree-sitter 压缩管线是如何工作的
为什么选择 web-tree-sitter(WASM)
parseFile.ts 的头部注释解释了选用 WASM 版 Tree-sitter 而非原生绑定的四个理由:
- 跨平台一致:WASM 在所有平台行为一致,无需原生编译;
- 零构建工具:不需要 Python、C++ 编译器或 node-gyp,任何环境
npm install即可使用; - 依赖更少:所有语言解析器统一打包在
@repomix/tree-sitter-wasms一个包中,而非 15+ 个独立原生包; - 可靠性更高:原生模块在部分 Node.js 版本(如 Node.js v23)存在已知构建问题。
官方同时承认 WASM 存在一定性能开销,但对压缩这一场景而言可接受。
压缩在打包管线中的位置
压缩并非独立于打包之外的功能,而是嵌入文件内容处理管线。在 fileProcessContent.ts 中,每个文件的内容处理顺序为:
- 若配置了
output.removeComments,先由fileManipulate的语言操纵器执行注释移除; - 再依据该文件解析出的"包含级别"(inclusion level)判断是否执行压缩:
compress级别才调用parseFile; parseFile返回undefined(语言不支持、解析失败或 WASM 异常中止)时,回退使用未压缩的原始内容,单个文件的失败绝不影响整个打包任务。
值得注意的是,压缩属于 CPU 密集型转换,与注释移除一样在 worker 线程中执行;而truncateBase64、removeEmptyLines、trim、showLineNumbers等轻量转换则在主线程的processFiles()中处理。
一次压缩的完整数据流
parseFile.ts 中parseFile的核心流程如下:
- 将文件内容按
\n切分为行数组; - 通过单例
LanguageParser(懒初始化,失败会重试而非缓存坏实例)根据文件扩展名猜测语言;语言不支持则静默返回undefined; - 取对应语言的 query 与 parser,将文件解析为 AST;
- 将 query 应用到根节点获得 captures,并按起始行号排序;
- 对每个 capture 调用对应语言的
parseStrategy.parseCapture(...)提取结构块; - 经
filterDuplicatedChunks去重(同一起始行只保留内容最长者)、mergeAdjacentChunks合并相邻块(用数组累积拼接避免 O(k²) 的字符串复制)后,以CHUNK_SEPARATOR = '⋮----'连接输出。
整条成功路径被完整包裹在 try/catch 中,任何失败(语言准备、解析、WASM 运行时中止)都会降级为返回undefined,由调用方回退到未压缩内容,确保"尽力而为"的语义。
支持的语言与逐语言解析策略
languageConfig.ts 注册了 16 种支持的语言:javascript、typescript、python、go、rust、java、c_sharp、ruby、php、swift、c、cpp、css、solidity、vue、dart。每种语言都配置了扩展名列表、Tree-sitter 查询串与解析策略工厂函数,例如:
javascript(js/jsx/cjs/mjs/mjsx)与typescript(ts/tsx/mts/mtsx/cts)共用TypeScriptParseStrategy;python使用PythonParseStrategy,go使用GoParseStrategy,vue使用VueParseStrategy,css使用CssParseStrategy;rust、java、c_sharp、ruby、php、swift、c、cpp、solidity、dart使用通用的DefaultParseStrategy。
以 TypeScript 为例看结构提取细节
TypeScriptParseStrategy.ts 定义了七类捕获:comment、definition.interface、definition.type、definition.enum、definition.class、definition.import、definition.function、definition.method。其关键处理逻辑包括:
- 函数/方法:用正则
/(?:export\s+)?(?:const|let|var)\s+([a-zA-Z0-9_$]+)\s*=/提取函数名用于跨捕获去重;通过findSignatureEnd定位签名结束行()后跟{、=>或;的行),再用cleanFunctionSignature将{或=>之后的实现部分截掉; - 类:仅保留声明行,若下一行含
extends/implements则一并保留继承信息; - 接口/类型/枚举/导入:整段原样保留。
查询串方面,queryTypescript.ts 定义了@definition.import、@definition.function、@definition.method、@definition.class、@definition.interface、@definition.type、@definition.enum、@comment等捕获模式,覆盖import_statement、function_declaration、method_definition、class_declaration、interface_declaration、type_alias_declaration、enum_declaration及箭头函数赋值(lexical_declaration/variable_declaration/assignment_expression+arrow_function)等节点类型——这正是前文示例中const calculateTotal = (...) => {...}能被识别为函数定义的原因。
另外,BaseParseStrategy.ts 特别强调:策略实例在同语言的所有文件间共享,因此解析策略必须保持无状态,所有数据只能来自方法参数,这保证了多文件场景下的线程安全与结果一致。
通过配置文件开启压缩
--compress标志等同于在配置文件中设置output.compress: true:
{ "output": { "compress": true } }在 configSchema.ts 中,output.compress的类型为v.optional(v.boolean(), false),即默认值为false——不显式开启时,所有文件都以原始内容打包。
逐文件覆盖:output.patterns
配置还支持比全局开关更精细的逐文件控制。configSchema.ts 中的output.patterns允许按 glob 匹配规则为指定文件覆盖全局compress设置,规则按数组顺序求值、首个匹配生效:
{ "output": { "compress": true, "patterns": [ { "pattern": "src/**/*.ts", "compress": true }, { "pattern": "tests/**", "compress": false }, { "pattern": "legacy/**", "directoryStructureOnly": true } ] } }注意:directoryStructureOnly(仅在目录结构中列出、不输出内容块)优先级高于compress。这些逐文件级别会在主线程预先计算并贯穿到 worker 线程,同时兼顾output.patterns覆盖与全局output.compress设置(见 fileProcessContent.ts)。
适用场景
代码压缩在以下场景中尤其有价值:
- 代码结构与架构分析:快速概览整个代码库的骨架,聚焦模块边界与依赖关系;
- 为 LLM 处理降低 Token 数:在信息密度与上下文长度之间取得平衡,让模型在有限的上下文窗口内看到更多文件;
- 高层文档撰写:基于结构而非实现生成架构文档、模块说明;
- 理解代码模式与签名:快速扫描 API 形状、函数参数与类型约束;
- 分享 API 与接口设计:只公开契约,隐藏实现,便于评审与协作。
与其他选项的组合使用
压缩可与以下选项组合,进一步控制输出密度:
| 选项 | 作用 |
|---|---|
--remove-comments | 移除代码注释(comment-removal.md),与压缩叠加可进一步减少 Token;在管线中先于压缩执行 |
--remove-empty-lines | 移除所有空行 |
--output-show-line-numbers | 在输出中为每行添加行号 |
例如,"最小化 Token 包"的组合用法:
repomix --compress --remove-comments --remove-empty-lines需要说明的是:由于压缩会截断函数体并移除实现细节,它更适合作为"结构快照"而非完整代码交付;当需要保留全部实现时(如代码审查、精确调试),应关闭compress并使用原始输出。
注意事项与已知边界
- 实验性:官方明确标注为实验性功能,输出格式与行为可能随版本演进;
- 尽力而为(best-effort)语义:语言不支持、解析失败或 WASM 异常中止时,对应文件会静默回退到未压缩内容(见 fileProcessContent.ts),并通过日志提示;
- 极端文件的 WASM 中止:某个病态文件可能触发 WASM 运行时中止,导致同一 worker 后续文件也降级为未压缩输出,该影响按 worker 隔离并有日志告警(见 parseFile.ts 注释);
- 策略共享约束:解析策略实例被同语言所有文件共享,必须在实现上保持无状态。
相关资源
- 注释移除指南:通过移除注释进一步降低 Token 数
- 配置指南:在配置文件中使用
output.compress与output.patterns - 命令行选项参考:完整的 CLI 选项清单
- 压缩核心实现:压缩入口、去重与相邻块合并逻辑
- 语言配置注册表:16 种支持语言与解析策略映射
- TypeScript 解析策略:函数/类/接口提取的具体实现
- 内容处理管线:注释移除与压缩在打包流程中的位置
【免费下载链接】repomix📦 Repomix is a powerful tool that packs your entire repository into a single, AI-friendly file. Perfect for when you need to feed your codebase to Large Language Models (LLMs) or other AI tools like Claude, ChatGPT, DeepSeek, Perplexity, Gemini, Gemma, Llama, Grok, and more.项目地址: https://gitcode.com/GitHub_Trending/rep/repomix
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考