
这是什么
codesight 是一个零依赖的命令行工具:扫一遍项目,把结果写进 .codesight/ 目录,形式是结构化的 markdown——一张合并的上下文地图,加上路由、数据模型、组件、库导出、环境变量、中间件、依赖图各自一份文件;项目里若存在 CI/CD、git 钩子和 Claude Code skill,还会多出对应的几份。它主张的是一件关于 token 的事。安装就是 npx codesight,其余什么都不用配。八个 detector 并行跑,输出是照着「让助手一次读完」来写的,于是 Claude Code、Cursor、Copilot、Codex、Windsurf、Cline,以及任何读 markdown 的东西,开局拿到的就是项目的形状,而不是靠 glob 和 grep 去把它翻出来。围绕这个核心还有:把地图拆成文章的 wiki 模式;把一堆笔记也照同样方式映射的知识模式;在同一套扫描之上暴露十四个工具、并按会话缓存的 MCP 服务器;沿导入图做的影响面查询;以及 --init,一次写出 CLAUDE.md、.cursorrules、.github/copilot-instructions.md、codex.md 和 AGENTS.md。README 里所有省 token 的数字都是项目自己量的:它们来自项目在三个 SaaS 项目、以及一张覆盖各种受支持语言的开源代码库表上跑出来的基准测试,而每个数字是怎么算出来的、哪些是估算、哪些是实测,README 都写明了。这些文件可以提交进仓库,于是每一个新会话从第一句话起就带着整份项目知识。
谁做的仓库所属账号 Houseofmvps 写了 190 次提交里的 93 次,用了两个 git 名字:79 次署 Houseofmvps,14 次署 Kailesk Khumar。README 写明他是 HouseofMVPs 与 Kailxlabs 的创始人,并给出 X 账号、LinkedIn 主页和两家公司的站点;package.json 里是同一个名字,邮箱落在 houseofmvps.com,个人主页填的是 kailxlabs.co。此外 aguerlain-lr 贡献 14 次提交,Fyb3roptik 六次,the-wondersmith 五次,贡献者名单里另有十三个账号。README 末尾还列了同一账号此前的两个项目:一套给 Claude Code 用的专家 skill,以及一个给 Claude Code 做的 SEO 插件。
它是怎么搭起来的
组成 · 6形状是一个核心加三张脸。核心是一次扫描:八个 detector 并行跑在一个由扫描器产出的文件列表上——扫描器遵守 gitignore 式的规则——结果被格式化成为了「一次读完」而裁过尺寸的 markdown。三张脸是命令行、一个在同一套扫描之上暴露十四个工具并按会话缓存结果的 MCP 服务器,以及为五种工具生成的指令文件。把它捏在一起的是两件事。第一是对依赖的硬预算:package.json 里根本没有 dependencies 段,只有四个开发依赖;项目宣传的 AST 精度是借来的而不是装来的——它从被扫描的项目里加载 TypeScript 编译器,对照表因此把依赖写成「Zero (borrows TS from your project)」。第二是精度是按语言分别取得的,而且只在 TypeScript 上回本:其余一切都走正则——正因如此,WebAssembly 插件那套 ABI 才会是一个独立的、显式开启的、不开启时行为逐字节相同的层,而不是默认路径的一次改动。
- src/detectors/
- 仓库的中心:十七个文件、232 KB,每一种值得抽取的东西各一个。
routes.ts一个文件就 66,355 字节,schema.ts41,770 字节;其后是 knowledge 的 22,397、依赖图的 15,780、组件的 15,468 和 GraphQL 的 11,357;openapi、config、库导出、中间件、事件、契约、影响面、token、路由标签与覆盖率填满其余。 - src/ast/
- 十五个文件、149 KB 的抽取器,按语言或关注点各一个:Python 25,706 字节,路由 17,220,Go 15,742,数据模型 11,790,BrightScript 10,110,C# 8,705,Android 8,271,PHP 8,113,其后是组件、Dart、SceneGraph、Swift 与 BrighterScript。
loader.ts是那道伸进被扫描项目去取 TypeScript 的接缝;native-loader.ts(13,933 字节)则是通向 WebAssembly 插件的那道。 - src/ 顶层
- 主干:
scanner.ts53,432 字节,是全仓库最大的文件;index.ts29,191 字节负责命令行;mcp-server.ts27,351;formatter.ts25,548;eval.ts11,173;telemetry.ts11,132;其下还有core.ts、types.ts和config.ts。 - src/generators/ 与 src/monorepo/
- 输出层。
wiki.ts31,664 字节,是最大的生成器,把一张地图拆成一目录文章;ai-config.ts17,156 字节写那五份指令文件和按工具定制的 profile;html-report.ts11,074 字节产出那个仪表盘。相比之下 monorepo 那一半很小——discover、orchestrator、deps、watch 四个文件共 17 KB——它之所以存在,是因为一位用户报告了自己仓库的情况。 - src/plugins/、plugins/ast/ 与 reference/ast-plugin/
- 四棵第一方插件树——CI/CD、git 钩子、Claude Code skill 与 Terraform——共 22 个文件、91 KB,其中 Terraform 的 HCL 解析器 14,263 字节、CI/CD 的 YAML 解析器 12,197 字节。再往旁是用 Rust 和 Go 写的三个 native-AST 插件,其中 Python 那个 20,743 字节,是 JavaScript 树之外最大的单个源文件;还有一个 AssemblyScript 参考插件,编译出 4,385 字节的模块,旁边放着校验和文件。
- tests/、eval/、.codesight/ 与 .github/workflows/
- 仪器。tests 下 141 KB 里,单个测试文件就占了 67,157 字节;
eval/放着五个夹具,每个是「一份仓库描述配一份预期结果」;.codesight/是提交进仓库的自扫描产物。四个工作流里,有一个 6,898 字节的流水线负责构建、压缩并冒烟测试那些 WebAssembly 插件、再把它们作为 release 资源发布;另一个 1,822 字节的负责让上下文地图保持最新。
取舍,以及它替代了什么
借用 TypeScript 编译器,而不是把它当成依赖 替代 把 TypeScript 作为运行时依赖发出去
对照表把这个项目的依赖写成「Zero (borrows TS from your project)」,README 说只要被扫描项目的
node_modules里有 TypeScript,AST 检测就自动生效,npm、yarn、pnpm 三种布局都算,pnpm 严格模式也算。package.json里根本没有dependencies段。也就是说,让这个工具站得住的那份精度,是从被读的代码库那里租来的,而不是让每个装它的人都先付一遍;代价是这份精度只覆盖一种语言。其余语言先走正则,AST 做成可选插件层 替代 把内置 AST 抽取器扩展到每一种语言
引入这套机制的 pull request 在自己的动机里把问题说清楚了:这个项目的长处是「便宜地拿到 AST 级精度的上下文」,但那份精度只属于 TypeScript,因为它由项目自带的编译器驱动,其余受支持的语言一律退回正则检测。宿主侧是被刻意限定范围的,而且这套机制不显式开启就不生效,于是不开启时行为与以前逐字节相同,零运行时依赖的状态也保住了。
npm 包里一个插件都不带 替代 把那些抽取器一起打进包里
README 说得很直白:这个包不带插件,它们是各自独立、需要显式开启的产物。项目把预编译好的 Rust、Python 和 Go 插件作为带校验和的 release 资源发布,用来放进
~/.codesight/plugins/;加进它们的那个 pull request 还写明,流水线会在插件 tag 上发布模块和它们的校验和,而 npm 包既不构建也不包含它们。Terraform 默认关闭,CI/CD 与 git 钩子默认开启 替代 把每一个第一方插件都自动加载
README 用一句话给了理由:Terraform 会刻意读到被扫描目录之外,比如同级的
../infrastructure仓库,而且给它一个明确的服务名时才有用,所以在被要求之前它一直是关的。另外三个插件则被描述成「目标文件不存在时等于不存在」——它们只扫主流程跳过的那些点目录,所以在不用它们的项目上不花代价——并且每个都能在配置文件里按项目关掉。wiki 用 AST 编译,而不是用模型写 替代 让大模型来写这份文档
README 说这个 wiki 受到一个公开的 LLM-wiki 模式的启发,但改成从 AST 编译,因此零 API 调用、200 毫秒出结果;生成的索引在自己的开头也重复了这一点。它给出的好处是:路由、数据模型、影响面和中间件这些,工具已经从 AST 里知道了,所以抽取代码结构根本不需要模型,wiki 只是叠在「代码库本来就有的数据」之上的一层叙述。
评测里加上底线和最差情况,而不是只报平均 替代 只报那个汇总分数
一位用户跑仓库自带的评测,发现汇总报出 87.0% 的平均 F1,而五个夹具里有两个吐出的路由列表几乎全是错的——因为按类别取平均,让模型、环境变量和组件上的满分把路由上的零分盖住了。修法是把最低 F1 印在平均值旁边,对任何「真阳性为零、假阳性大于零」的类别单独点名,并在任何夹具的任何类别跌破 50% 底线时以非零码退出。
依据README.md(51,832 字节,取自仓库)、docs/wasm-plugins.md(20,007 字节)、eval/README.md、package.json、.github/workflows/codesight.yml、提交进仓库的自扫描产物 .codesight/CODESIGHT.md(20,893 字节)连同 .codesight/routes.md 与 .codesight/wiki/index.md、recon 报告里完整复现的 wiki 概览文档,以及带体积的完整 438 个文件树。
制作过程
6 个阶段- 01
五个月、190 次提交,却一个 release 都没有
仓库建于 2026-04-04,最早一次提交就在同一天,而且已经带上了版本号:「v1.0.0: codesight — see your codebase clearly」。按月看,曲线陡起然后走平——4 月 149 次提交,5 月 12 次,6 月 22 次,7 月 7 次——最新一次提交的日期是 2026-07-27 13:30,标题是「chore: update AI context map [skip ci]」。从那天到 2026 年 10 月初,一次提交都没有,但 issue 还在进来:2026-08-13 一条讲 FastAPI 的路由前缀,2026-09-08 一个 pull request 讲要把 Slack 保留的提及关键词排除掉。正是这段空档,让这条记录定成 maintained 而不是 active。版本号是必须手工拼出来的那部分,因为这个仓库既没有 release 也没有 tag——除了提交信息、npm 发布和 issue 回复,没有任何东西标记版本。材料里出现过的版本号从那个 v1.0.0 一直到 v1.19.0:后者既是
package.json里的版本,也是作者在 2026-07-27 关闭四个 bug 报告时引用的版本;README 自己的小标题则分别钉在 v1.6.2、v1.6.4、v1.6.7 和 v1.9.3 上。周围是 1,410 个星、123 个 fork、6 个 watcher、3 个未关 issue、总计三十条 issue 与 pull request,以及十五个贡献账号。README 自己的横幅宣称 4,000+ 次下载、149 个测试,开篇一行就把主张说完了:AST 精度、30+ 个框架检测器、14 个 ORM 解析器、14 个 MCP 工具,一次npx调用。 - 02
产物到底是什么,以及那个把自己也扫了一遍的仓库
产物就是 markdown。一次普通扫描会写出
.codesight/CODESIGHT.md,外加每个 detector 一份文件;其中三份来自内置插件,读的是主流程跳过的点目录——.github/workflows、.circleci、.husky和.claude/。这个项目把自己那份地图也提交进了仓库,所以产物可以直接当成已发布的东西来读:CODESIGHT.md20,893 字节,libs.md12,996 字节,graph.md2,936 字节,另有 routes、config、events、CI/CD、coverage 与 middleware 各自一份,以及一个装着十份文件的wiki/目录。让它保持更新的是一个 GitHub Actions 工作流:每次 push 跑一遍npx codesight@latest --wiki,把变化以codesight-bot的名义、用固定的提交信息chore: update AI context map [skip ci]提交;这个账号占 190 次提交里的 54 次,是全部历史的四分之一出头。在 pull request 上,同一个工作流会把CODESIGHT.md的前五十行贴成评论。这份自扫描对自己看不到什么相当坦白:它自己那张地图把技术栈写成raw-http | none | unknown | typescript,0 个模型、0 个组件,68 个库文件,测试覆盖率 60%,并且报出四条在一个没有服务器的仓库里并不存在的路由:ALL /path、ALL /api、ALL /health和GET /api/users,每一条都带[inferred]标记——而生成的 wiki 索引自己写着,这个标记意味着是正则检测出来的、精度可能更低。同一份 wiki 列出的「必需环境变量」里,有些名字其实住在仓库的测试夹具和它自己的 detector 模式表里。 - 03
那些 token 数字是项目自己量出来的
README 里关于省 token 的一切,都是项目在量自己,而且写明了量法。输出 token 是按真实文件体积、四个字符一个 token 量出来的。探索 token 则是估算的——路由 × 400、模型 × 300、组件 × 250、热点文件 × 150、环境变量 × 30,再乘一个 1.3 的「多轮对话里反复回看」系数,最后减去输出体积——README 说这些估算偏保守。在三个生产环境的 SaaS 项目上,它给出的数字是:人工探索 46,020 个 token 对 3,936 的上下文地图(11.7 倍)、26,130 对 3,629(7.2 倍)、47,450 对 4,162(11.4 倍);改用 wiki 而不是整张地图之后,项目自述的平均综合降幅是 91 倍。第二张表把同一套测量铺到了各种受支持语言的开源代码库上,从 7,509 个文件的 Next.js 工作区大约 9 倍,到只有 47 个文件的 Spring Boot 项目大约 41 倍;对照表则写着基础扫描 7 到 12 倍、用 wiki 做定向查询 60 到 131 倍。一条脚注记录说,有一位开发者手工核对过:同样的项目,Claude Code 要花 40–70K token。有另外两个来自外面的数字与它们并置。issue #31 是一位用户的 monorepo 输出了 约 221,169 个 token,这件事后来变成了 v1.12.4 里的分层 monorepo 模式。issue #54 是一位用户跑仓库自带的评测,发现汇总报的是 87.0% 的平均 F1,而五个夹具里有两个分别吐出十一条和十条路由,几乎没有一条是对的。
- 04
社区的几个回合,各自改掉了什么
功能面的大部分是外面的人用 pull request 送进来的。
Fyb3roptik提了并修掉了对「不做 web 的人」最要紧的那一个:工具把一个 Go 项目报成 TypeScript;随后他加了repoType字段,把单项目、monorepo、微服务和元仓库分开;接着又把 Roku 搬了进来——BrightScript、BrighterScript 和 SceneGraph,锚点是 Roku 自己也在用的纯文本manifest文件,另加三个新 extractor,并教会全部八个 detector 把屏幕映射成路由、把<interface>契约映射成模型。aguerlain-lr报告自己的 monorepo 输出了 221,169 个 token,然后亲手写了分层模式,让每个 workspace 包各自扫描,以 v1.12.4 合入。vakuor报告点目录根本扫不到,以及.codesightignore处理取反的方式和.gitignore不一样;两件都修了——点目录那件以 v1.14.0 发布,取反语义那件在提交0bedd0d里,做法是让取反只精确匹配条目名或相对路径。optimalcharb把 Celery 作为事件框架加了进来,合入前作者把它从 README 的 Routes 行挪到了新开的 Events 行——任务队列不是路由框架。neilwashere贡献了 skill 插件与 git 钩子插件,以及一个 Terraform 插件;后者被以「已被前者取代」关掉。the-wondersmith贡献了那串五个 pull request,把 AST 抽取变成了一套插件系统。 - 05
一天之内,四个 bug 报告,一个版本
看清这个项目怎么运转,最好的窗口是 2026-07-27:同一位用户
jonathanjie的四个报告,全部以「已在 v1.19.0 修复」关闭,四条回复彼此的间隔在四十秒以内。每个报告都点名了文件、版本和原因,每条回复都比报告走得更远。installGitHook把.git/hooks写死,并且只检查.git存在,于是--hook在任何git worktree检出里都以 ENOTDIR 崩掉;修法是去问 git 自己——git rev-parse --git-path hooks——只有在.git确实是目录时才退回.git/hooks。detectTags被传进整个文件的内容,而它的模式表第一个就是裸的/auth/i,于是一句把路由写成公开的注释反而给它打上了「需要鉴权」;现在标注被限定在每条路由自己那一段,TypeScript 抽取器则限定在注册调用本身加上它点名的同文件处理函数体。凡是靠扫代码(而不是读.env文件)发现的环境变量,hasDefault都写死成false,因为模式在变量名处就停了;现在会捕获读取处的兜底值,只有那种会抛 KeyError 的下标写法例外。而--eval被重写,让汇总再也藏不住塌方:概要会把最低 F1 印在平均值旁边,对任何「真阳性为零、假阳性却大于零」的类别单独点名,并在任何类别低于 50% F1 底线时以非零码退出。 - 06
项目写下来的两套方法
有两份文档,把读者本来得自己反推的部分直接写下来了。
docs/wasm-plugins.md共 20,007 字节,是可选的 native-AST 插件的契约:模块必须命名为codesight-<lang>-ast.wasm,并导出memory、alloc、dealloc和contractVersion,后者必须等于宿主当前的契约版本 1,否则被拒绝;但「能力」是靠导出是否存在来判断的——只有当它导出了parseRoutes,才算支持路由——而且没有清单文件。可选的describe()返回语言 id 和一组扩展名,派发是语言驱动的,所以只要声明了扩展名,一个内置抽取器并不支持的语言也能用插件补上。插件在一次扫描里只实例化一次,作为一个长命的 reactor 跑在最小的 WASI 导入对象之下——只有时钟、随机数、exit 和 stderr,没有文件系统、没有网络、没有环境变量与参数——宿主会把自己已经知道的上下文字段盖上去,并忽略插件交给它的任何同名值。npm 包里一个插件都不带;项目把 Rust、Python 和 Go 的构建产物作为带校验和的 release 资源发布。第二份文档是评测套件:五个夹具,每个是一份仓库描述配一份预期结果(路由、模型、环境变量和影响面),跑完 detector 之后按精确率、召回率和 F1 打分。边界也一并写下:生成的 wiki 索引列出了它看不见的八类东西,从循环里注册的路由一直到 WebSocket 处理函数和没走 ORM 的原生 SQL 表。
相关档案
全部档案 →第 067 号
Reticle
一个 MCP 服务器加一个只在开发期生效的 SDK:让编码 agent 从应用内部去读、去操作一个正在运行的 web 或桌面应用,然后给出判词和该改的文件与行号,而不是一张截图。
第 065 号
GSD Core
「Git. Ship. Done.」——一个元提示、上下文工程与规格驱动开发的框架,每个里程碑都重复同一条五步回路:讨论、计划、执行、验证、发版。重活被推给上下文全新的子 agent,主会话因此保持轻量;每一项决定都写进规划目录下的 Markdown 与 JSON,而不是留在对话里。
第 122 号
OKF Agent Memory
把编码 agent 学到的东西以纯 Markdown 留在仓库里——一个用进程内 BM25 检索的 OKF v0.2 知识 bundle——于是这份记忆可以被 diff、被审阅,而不必住进数据库。