Skip to content
Go back

bundlr小工具

这两天,Claude Code 源码泄漏成了一个热门话题。

为了更方便的导出源码来询问LLM,比如将claude code的源码去问claude。我做了一个小工具 bundlr

bundlr 是什么

bundlr 是一个很简单的 CLI 工具,用来把源代码打包成一个单文件,方便直接粘贴给 LLM。

它会遍历项目目录,收集你关心的文件,然后把它们合并成一个输出文件,并且为每段代码保留清晰的路径标识。这样模型在阅读时,至少能知道每段内容来自哪个文件,而不是面对一坨失去上下文的代码片段。

bundlr 解决了什么问题

如果你经常拿代码去问 LLM,大概率会遇到下面这些场景:

手动做这些事当然也可以,但很烦,而且每次都在重复劳动。

bundlr 的思路就是把这一步工具化:

安装

如果你本地有 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 对话里,就可以继续提问。

这里有一个默认设计:如果你没有显式传 -extbundlr 会尝试使用输出文件 -o 的后缀来推断文件类型。比如你输出成 bundle.py,它就默认收集 Python 文件;输出成 bundle.go,就默认收集 Go 文件。

使用方式

命令格式:

bundlr [参数] [src]

其中 src 是要扫描的目录,不传时默认就是当前目录。

常用参数有五个:

核心参数

-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

它只提供 extincludeexclude 的默认值,src-o 仍然只能通过命令行指定。

一个常见示例如下:

# ~/.bundlr.yaml
exclude:
  - venv
  - .venv
  - vendor
  - node_modules
  - dist
  - build
  - "**/*.pb.go"
  - "**/*_generated*"

这里几个合并规则也值得注意:

所以配置文件里的 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

Share this post on: