这两天,Claude Code 源码泄漏成了一个热门话题。
为了更方便的导出源码来询问LLM,比如将claude code的源码去问claude。我做了一个小工具 bundlr 。
bundlr 是什么
bundlr 是一个很简单的 CLI 工具,用来把源代码打包成一个单文件,方便直接粘贴给 LLM。
它会遍历项目目录,收集你关心的文件,然后把它们合并成一个输出文件,并且为每段代码保留清晰的路径标识。这样模型在阅读时,至少能知道每段内容来自哪个文件,而不是面对一坨失去上下文的代码片段。
bundlr 解决了什么问题
如果你经常拿代码去问 LLM,大概率会遇到下面这些场景:
- 需要一次性提供多个相关文件
- 需要跳过
vendor、dist、node_modules、缓存目录或生成文件 - 只想让模型看某一层代码,比如 handler、tests 或某几个模块
- 想保留文件路径,避免模型分不清片段来源
手动做这些事当然也可以,但很烦,而且每次都在重复劳动。
bundlr 的思路就是把这一步工具化:
- 指定要扫描的目录
- 指定要收集的后缀
- 用
-include精确保留你关心的文件 - 用
-exclude排除噪音内容 - 最后输出成一个可直接粘贴给 LLM 的文件
安装
如果你本地有 Go 环境,最直接的方式就是自己编译:
go mod tidy
go build -o bundlr bundlr.go
mv bundlr /usr/local/bin/bundlr
# 可选:复制一份示例配置
cp bundlr.yaml ~/.bundlr.yaml
也可以直接去 GitHub Releases 页面下载已经打包好的 Windows、Linux 和 macOS 版本。
项目地址:
https://github.com/Abyss-emmm/bundlr
快速开始
最基础的用法很直接:
# 打包当前目录下的所有 Python 文件
bundlr . -o bundle.py
# 打包所有 Go 文件,排除 vendor 目录
bundlr . -o bundle.go -ext .go -exclude vendor
打包完成之后,把输出文件内容贴到 LLM 对话里,就可以继续提问。
这里有一个默认设计:如果你没有显式传 -ext,bundlr 会尝试使用输出文件 -o 的后缀来推断文件类型。比如你输出成 bundle.py,它就默认收集 Python 文件;输出成 bundle.go,就默认收集 Go 文件。
使用方式
命令格式:
bundlr [参数] [src]
其中 src 是要扫描的目录,不传时默认就是当前目录。
常用参数有五个:
-c:YAML 配置文件路径-o:输出文件路径,默认是all_in_one.py-ext:要收集的文件扩展名-include:只包含匹配特定相对路径 glob 的文件-exclude:排除匹配特定相对路径 glob 的目录或文件
核心参数
-ext
用来指定要收集哪些后缀的文件。
可以逗号分隔,也可以重复传入:
bundlr -ext .go
bundlr -ext .go,.ts,.js
bundlr -ext go -ext ts
如果不传 -ext,就会尝试从 -o 的后缀推断;如果 -o 也没有后缀,程序会直接报错退出。
-exclude
用来排除不需要进入输出的目录或文件。它匹配的是相对于 src 的路径,并统一使用 / 作为分隔符。
bundlr -exclude vendor
bundlr -exclude venv -exclude dist
bundlr -exclude 'internal/generated/*.go'
bundlr -exclude '**/*.pb.go'
bundlr -exclude 'cmd/api/*.go,cmd/web/*.go'
如果你不想把隐藏目录、缓存目录或者生成文件交给 LLM,这个参数会非常有用。
-include
和 -exclude 相反,它是白名单机制,只保留你指定的文件。
bundlr -include 'cmd/api/*.go'
bundlr -include '**/*_test.go'
bundlr -include 'internal/**/handler_*.go'
当你不是想“打整个仓库”,而是只想让模型看某一个切面时,-include 比单纯依赖 -exclude 更高效。
-c
如果你不想每次都重复输入一堆默认规则,比如 -exclude venv -exclude node_modules,可以把这些规则写进 YAML 配置文件,再通过 -c 指定:
bundlr -c ~/.bundlr.yaml . -o bundle.py
配置文件不会自动加载,必须显式传入 -c。
它只提供 ext、include、exclude 的默认值,src 和 -o 仍然只能通过命令行指定。
一个常见示例如下:
# ~/.bundlr.yaml
exclude:
- venv
- .venv
- vendor
- node_modules
- dist
- build
- "**/*.pb.go"
- "**/*_generated*"
这里几个合并规则也值得注意:
src和-o只支持 CLI,不会从配置文件读取-ext、-include如果在 CLI 里显式传入,会直接覆盖配置文件-exclude会和配置文件里的规则合并,CLI 传入的规则会追加在后面
所以配置文件里的 exclude 很适合放长期默认值,而每次运行时再补一两个临时排除项。
输出格式
bundlr 输出的不是简单拼接,而是会给每个文件加上明确的分隔标题。类似这样:
# ===== File: internal/handler/user.go =====
package handler
...
# ===== File: internal/router/router.go =====
package router
...
几个实际使用场景
1. 把整个项目的某种语言代码打成一个文件
bundlr . -o bundle.go -ext .go -exclude vendor
适合快速把一个 Go 项目的核心代码整理出来,让模型做整体分析。
2. 只给模型看测试文件
bundlr . -o tests.go -ext .go -include '**/*_test.go'
适合让模型帮你分析测试覆盖、补测试思路,或者梳理现有测试结构。
3. 只聚焦某一层,比如 handler
bundlr . -o handlers.go -ext .go -include '**/handler_*.go' -exclude vendor
适合当你只想讨论某一层业务逻辑,不希望模型被项目其他内容干扰。
4. 多语言项目一起打包
bundlr . -o bundle.txt -ext .go,.ts -exclude node_modules -exclude vendor
适合前后端混合仓库,或者工具链项目。
一个很实用的小技巧:先看目录里有哪些后缀
如果你不确定该传哪些 -ext,可以先把项目里实际出现的后缀列出来,再决定打包哪些文件。
macOS / Linux 下可以直接这样看:
find . -type f -name "*.*" | sed 's/.*\.//' | sort -u
如果你想更严谨一点,过滤方式可以写成:
find . -type f | awk -F. 'NF>1 {print $NF}' | sort -u
如果你还想顺手看每种后缀有多少文件:
find . -type f -name "*.*" | awk -F. '{print $NF}' | sort | uniq -c
这样你在一个陌生仓库里,很快就能判断应该用 .go、.ts、.py 还是多种后缀一起打包。
如果你在 Windows 下用 PowerShell,也可以这样:
Get-ChildItem -Recurse -File | Where-Object { $_.Extension -ne "" } |
Select-Object -ExpandProperty Extension | Sort-Object -Unique
统计每种后缀数量:
Get-ChildItem -Recurse -File | Where-Object { $_.Extension } |
Group-Object Extension | Sort-Object Count -Descending
项目地址:
https://github.com/Abyss-emmm/bundlr