CodeGraph 语言接入实战:/add-lang 技能如何端到端为新语言接通 tree-sitter 提取管线并通过 A/B 基准证明其价值 CodeGraph 语言接入实战/add-lang 技能如何端到端为新语言接通 tree-sitter 提取管线并通过 A/B 基准证明其价值【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph本文基于 CodeGraph 仓库内的 Claude Code 技能定义 SKILL.md 展开完整讲解该技能的 10 步工作流如何为 CodeGraph 接入一种新的 tree-sitter 语言——从语法grammar选型与健康检查、AST 节点类型发现、四处有时是五处源码接线到构建验证循环、提取测试、真实仓库语料挑选直至最终的带/不带 CodeGraph 检索 A/B 基准对比。读完本文你既能理解 CodeGraph 提取管线的语言扩展点LanguageExtractor接口、wasm 语法加载、文件扫描白名单在哪里也能照单复制出一套“接入新语言并自证提取质量与检索收益”的完整工程流程。一、这个技能是什么一次“全自动接入 自动验收”add-lang是仓库内置的 Claude Code 技能其 frontmatter 声明的触发条件是用户执行/add-lang language或要求“在 codegraph 中新增/支持一种语言”如 Lua、Elixir、Zig、OCaml。技能的目标在 SKILL.md 中写得很明确Wire a new tree-sitter language into codegraphs extraction pipeline, prove it extracts real symbols on popular repos, and prove it beats no-codegraph for an agent.也就是说它不止是“把语言接上”还要求双重证明提取证明在 3 个按规模分层的真实流行仓库上索引后确认提取到了真实的符号节点而不只是file/import这类结构性节点检索证明在同样的架构问题上对比“有 CodeGraph”与“无 CodeGraph”两个 agent 实验臂arm用真实的claude -p运行数据工具调用次数、文件 Read 次数、codegraph 工具调用次数、耗时、花费证明接入后确实更省。两条贯穿全程的“house rule”也值得注意全程自动运行但绝不commit/push/publish/tag——所有改动留给用户审查发布走 GitHub Actions Release 工作流参数是Language联合类型里的 token且必须用小写单 token 形式csharp而不是c#因为该 token 会贯穿Language联合、EXTRACTORS映射、wasm 文件名和配置 glob。前置条件技能要求从 codegraph 仓库根目录运行并具备node、git、ghGitHub CLI用于按 star 搜索仓库已登录的claudeCLI——因为 Step 8 的基准会派生真实的claude -p运行基准使用本地开发构建Step 8 会先构建并把它软链到 PATH 上通过 scripts/local-install.sh后续所有codegraph命令指向同一份构建。二、10 步工作流总览SKILL.md 要求把下面的检查单拷下来逐步执行- [ ] 1. Resolve language; bail early if already supported (just benchmark) - [ ] 2. Find a grammar health-check it (ABI / heap corruption) - [ ] 3. Discover the grammars AST node types (dump-ast.mjs) - [ ] 4. Wire the language (4 files; sometimes a 5th core touch) - [ ] 5. Build verify-extraction loop until PASS - [ ] 6. Add extraction tests; make them green - [ ] 7. Auto-pick 3 popular repos by size tier; add to corpus.json - [ ] 8. Benchmark all 3: extraction with/without A/B - [ ] 9. Update README CHANGELOG - [ ] 10. Report; do NOT commit整体节奏是“先验证语法健康 → 发现节点类型 → 写接线 → 构建-验证循环 → 测试 → 真实语料基准 → 文档 → 报告”每一步都有明确的退出码或 PASS/FAIL 判据失败时就地回环修复而不是带病前进。下面按步骤展开并结合仓库源码说明每个接线点为什么存在。三、Step 1 — 解析语言 token 并短路已支持的语言第一步是判断该语言是否已经接入。判断方法是查两个位置LANGUAGES常量——位于 src/types.ts。当前仓库中该常量已列出typescript、lua、luau、scala、pascal、csharp等语言并以unknown收尾EXTRACTORS映射——位于 src/extraction/languages/index.ts。它把语言 token 映射到各自的 extractor注意tsx与typescript复用同一 extractorjsx复用javascriptc/cpp来自同一模块的两个导出。如果语言已支持例如再跑一次/add-lang typescript技能规定跳过 Step 2–6直接进入 Step 7–8 做基准测量来验证/度量它并在报告里注明“本次未改任何代码”。这个短路设计避免了重复接线的回归风险同时保证每次/add-lang调用都能产出一份有数据的验收报告。四、Step 2 — 找 grammar 并做健康检查ABI / 堆损坏4.1 先查tree-sitter-wasms里有没有现成的ls node_modules/tree-sitter-wasms/out/ | grep -i lang # csharp - c_sharp有大概率可以直接用tree-sitter-wasms包里的 wasmelixir、zig、ocaml、solidity、toml、yaml 等都属于这一类。grammars.ts会自动从该包解析见 src/extraction/grammars.ts 的resolveWasmPathvendored 语言读dist内wasm/目录否则走require.resolve(tree-sitter-wasms/out/...)没有需要把一个.wasmvendor 到src/extraction/wasm/仓库中已有tree-sitter-pascal.wasm、tree-sitter-scala.wasm、tree-sitter-lua.wasm等先例并在 Step 4 中把 token 加入 vendored 分支。从源码结构看vendored 语言清单集中在grammars.ts的VENDORED_WASM_LANGS集合中当前包含pascal、scala、lua、luau、csharp、r、cfml、cfscript、cfquery、cobol、vbnet、erlang、terraform、arkts、nix等见 grammars.ts。4.2 健康检查grammar 存在 ≠ 可用这是整个技能中最“踩坑经验驱动”的一步。SKILL.md 明确警告在写 extractor 之前必须健康检查因为一个“存在”的 grammar 仍然可能不可用node scripts/add-lang/check-grammar.mjs lang path/to/valid-sample.extscripts/add-lang/check-grammar.mjs 的实际行为源码注释写得很直白打印该 grammar 的ABI version在一个多 grammar 运行时上下文里反复解析同一份合法样本默认 20 次——它会先额外加载一个已知的健康 grammarpython来模拟真实索引时的多语法并存环境若合法样本解析出 ERROR 树RESULT: FAIL说明该 wasm 在 web-tree-sitter 下腐蚀共享 WASM 堆——其后果是“第一个文件之后的每个文件都静默丢失嵌套调用/import 节点”退出码0 健康1 堆损坏/解析错误2 无法运行。脚本注释里记录了一个真实案例tree-sitter-wasms里的Lua grammar 是 ABI 13在 web-tree-sitter 0.25 下每个文件第一次之后提取都退化修复方式是 vendor 上游 ABI 15 的 wasm。若健康检查 FAIL技能规定不要使用该 wasm而是获取新版本构建npm pack tree-sitter-grammars/tree-sitter-lang # 经常自带预编译 *.wasm # 或自行构建npx tree-sitter build --wasm需要 Docker/emscripten cp the.wasm src/extraction/wasm/tree-sitter-lang.wasm然后把 token 加入 Step 4 的 vendored 分支并对 vendored 路径重新跑 check-grammar 直到 PASS。如果实在拿不到健康的 wasm技能要求STOP 并告知用户——不交付半成品。另一个细节样本必须语法上完全合法否则“以错误的原因失败”。五、Step 3 — 用 dump-ast.mjs 发现 AST 节点类型写 extractor 之前必须先知道 grammar 产生的节点类型。技能的做法是准备一份代表性样本文件手工写一份覆盖函数、类/结构体、import、枚举的小样本或从已知仓库取一个真实文件然后node scripts/add-lang/dump-ast.mjs lang path/to/sample.ext # vendored grammar传 wasm 路径而不是 token node scripts/add-lang/dump-ast.mjs src/extraction/wasm/tree-sitter-lang.wasm sample.extscripts/add-lang/dump-ast.mjs 直接用 web-tree-sitter与 CodeGraph 相同运行时加载 wasm无需先注册语言。输出两部分缩进的 AST 树命名节点 字段名如name:、parameters:、body:、return_type:带行:列位置支持--depthN控制深度和--full打印匿名 token 节点节点类型频率表——脚本注释称之为“payoff”它直接告诉你哪些节点类型应该映射到functionTypes/classTypes/importTypes等字段。技能同时给出选型参考打开与目标语言范式最接近的现有 extractor 当模板——rust.ts/scala.ts函数式、trait、java.ts/csharp.ts面向对象、python.ts/ruby.ts脚本型、go.ts顶层方法 receiver。六、Step 4 — 四处接线有时是第五处核心改动技能把这一步定性为 “exact, fragile wiring —— 必须精确匹配现有风格”。以下每一处都可以对照仓库源码验证。6.1src/types.ts两处编辑在LANGUAGES常量中加入lang,位置在unknown之前参见 src/types.ts在DEFAULT_CONFIG.include中加入**/*.ext,。第二处绝不能跳过技能原文解释它是文件扫描的 allowlist——没有这条 glob即使检测和提取都已接通codegraph init也会发现0 个文件。6.2src/extraction/grammars.ts三个映射vendored 时加第四处WASM_GRAMMAR_FILESlang: tree-sitter-lang.wasm,该映射从 grammars.ts 起定义是 wasm 文件名的单一出处EXTENSION_MAP每个文件扩展名 →lang例如.lua: lua。值得注意的是isSourceFile直接由EXTENSION_MAP派生见 grammars.ts即“解析器支持”与“索引文件选择”共用同一张表不会漂移getLanguageDisplayNamelang: Display Name,仅 vendored 语言把lang加进VENDORED_WASM_LANGS的 wasm 路径分支grammars.ts使resolveWasmPath从本地wasm/目录读而不是去tree-sitter-wasms包里找。6.3 新建src/extraction/languages/lang.ts导出形如export const langExtractor: LanguageExtractor { … }的提取配置把 Step 3 发现的节点类型映射进来。对照 src/extraction/tree-sitter-types.ts 中的LanguageExtractor接口必填字段为字段含义functionTypes/classTypes/methodTypes函数 / 类 / 方法的 AST 节点类型interfaceTypes/structTypes/enumTypes接口或 protocol/trait/ 结构体 / 枚举typeAliasTypes/importTypes/callTypes/variableTypes类型别名 / import / 调用表达式 / 变量声明nameField/bodyField/paramsField名称、函数体、参数列表对应的 AST 字段名按需追加的可选 hook接口注释对每个都有说明getSignature、getVisibility、isExported、isConst、extractImport、extractVariables、visitNode、getReceiverTypeGo 式 receiver、interfaceKind如 Rust 归为trait、enumMemberTypes、packageTypes/extractPackageKotlin/Java 式包声明以及用于处理 grammar 特殊性的classifyClassNode、classifyMethodNode、resolveBody、synthesizeMembers等。6.4src/extraction/languages/index.ts注册到 EXTRACTORSimport { langExtractor } from ./lang; // 并在 EXTRACTORS 中加 lang: langExtractor,这与现有 30 余个注册项lua: luaExtractor、r: rExtractor等见 index.ts保持同构。6.5 有时需要第五处核心改动src/extraction/tree-sitter.ts技能的提示变量提取在extractVariable中有逐语言分支通用回退只能找到直接的identifier/variable_declarator子节点。如果 grammar 把声明名嵌套在更深的结构里例如 Lua 的variable_declaration → variable_list就要在 src/extraction/tree-sitter.ts 里镜像现有 ts/python/go 分支加一个} else if (this.language lang)分支。仓库中现成的 Lua/Luau 分支就是范例它处理variable_declaration → assignment_statement → variable_list支持local x, y 1, 2的多名声明且只对纯 identifier 建立 local 变量节点。另外“import 不是独立节点类型”的语言Lua/Ruby 的require在 AST 里是普通call不走importTypes而是在 extractor 的visitNodehook 里处理——这也是技能明确写出的分支策略。七、Step 5 — 构建 verify-extraction 循环直到 PASSnpm run build # tsc copy-assets把 vendored *.wasm 拷进 dist/package.json 中build脚本正是tsc npm run copy-assets …其中copy-assets会把src/extraction/wasm/下所有*.wasm复制进dist/extraction/wasm/——这就是技能 Notes 里强调“任何新*.wasm必须放在src/extraction/wasm/”的原因不放在这里就不会被打进dist/运行时加载不到。随后索引一个小型样本仓库并验证( cd sample-repo codegraph init -i ) node scripts/add-lang/verify-extraction.mjs sample-repo langscripts/add-lang/verify-extraction.mjs 的判定逻辑可直接读源码核对通过 PATH 上的codegraph status repo --json读取索引状态——因此它校验的是构建该索引的那个二进制保证“谁建的索引谁负责”维护一个SYMBOL_KINDS集合module、class、struct、interface、function、method、property、field、variable、constant、enum、enum_member、type_alias、namespace、route、component等——这些 kind 能证明 extractor 映射了 AST 节点而file/import是 CodeGraph 对任何语言结构性创建的不算数critical 检查任一失败即 FAILexit 1索引已初始化、目标语言被检测到、符号数 0soft 检查失败仅 WARNexit 0符号密度 ≥ 1/文件、边数 文件数退出码0 PASS 或软告警1 critical FAIL2 无法运行。FAIL 的典型症状是“只产出了file/import节点”——即节点类型名写错。循环动作是换更丰富的样本重跑dump-ast.mjs→ 修lang.ts映射 →npm run build→ 重新索引 → 重新 verify直到 PASS。八、Step 6 — 补提取测试并跑绿向tests/extraction.test.ts 添加测试以文件中的Rust Extraction块为模板在describe(Language Detection)中加一条detectLanguage断言验证扩展名 → 语言 token新建describe(Lang Extraction)块用内联源码字符串断言函数/类/import 被正确提取。npx vitest run __tests__/extraction.test.ts测试绿了才允许继续。这一步把“在某个样本仓库上碰巧能提取”固化为可回归的行为契约。九、Step 7 — 自动挑选 3 个仓库并登记语料技能要求不问用户、直接挑先找候选再人工筛出 3 个真正以lang为主的仓库每个规模档位一个gh search repos --languagelang --sortstars --limit 40 \ --json fullName,stargazerCount,description档位定义与 corpus.json 保持一致Small 约 150 文件 ·Medium约 150–1500 ·Large 约 1500。要跳过那些“标了lang标签但主体其实是另一种语言”的仓库。每个仓库再写一个跨文件架构问题必须需要跨文件追踪才能回答例如 corpus 里 Go 的 terraform 条目是 How does Terraform build and walk the resource dependency graph?。最后向.claude/skills/agent-eval/corpus.json添加一个Language块字段为name、repo、size、files、question这样/agent-eval技能以后可以直接复用这批语料——新语言的基准资产沉淀为团队的长期测试资产。十、Step 8 — 对 3 个仓库全量基准提取 A/B先一次性把开发构建放到 PATH 上npm run build ./scripts/local-install.sh scripts/add-lang/bench.sh lang name url question headless # ×3scripts/add-lang/bench.sh 的流程源码可逐行核对在共享语料目录默认/tmp/codegraph-corpus可用环境变量CORPUS覆盖与/agent-eval共用里 shallow clone 仓库已存在则复用删掉$REPO/.codegraph并用 PATH 上的 codegraph 重新codegraph init -i跑verify-extraction.mjs作为花钱前的廉价守门提取挂了就不跑 A/B避免在坏 extractor 上烧钱除非显式FORCE_AB1通过则调用 scripts/agent-eval/run-all.sh 执行 with/without 检索的 A/B脚本退出码直接反映提取结果0 pass/warn1 critical fail2 读不到 status。A/B 每臂产出的指标由parse-run.mjs汇总输出工具调用次数、文件Read次数、Grep/Bash 次数、codegraph 工具调用次数、耗时、花费——with与without两臂都要读。3 个仓库跑完后必要时再用./scripts/local-install.sh恢复 dev 链接。十一、Step 9 — 更新 README 与 CHANGELOGREADME.md把Lang加进语言特性条目并在Supported Languages表格README.md 附近加一行| Lang | \.ext | Full support (classes, methods, …) |。表格中已有先例可循例如 Lua 一行写着 Full support (functions, methods with receivers, local variables,require imports, call edges)见 README.mdCHANGELOG.md在最顶部最新版本块之上新增## [Unreleased]段落下挂### Added写一条用户视角的要点例如 CodeGraph now indexes (.ext) — functions, classes, imports, and call edges.若## [Unreleased]已存在则追加其下发布时会被折叠进下一个版本块。十二、Step 10 — 报告且绝不 commit最终交付给用户的审查报告应包含四块Files changed4 处接线 新 extractor 测试 README CHANGELOG corpus.json 如有 vendor 的.wasmExtraction每仓库files / nodes / edges /verify-extraction结果A/B每仓库withvswithout的工具调用数、文件 Read 数、花费加一句裁决——codegraph 是否降低了 effort两臂是否都到达了正确答案Gaps / follow-ups尚未映射的节点类型、缺失的 resolution 边、框架路由等。然后交接给用户不执行git commit/push或发布——发布统一走 GitHub Actions Release 工作流。十三、Notes四条必须记住的边界规则SKILL.md 结尾的 Notes 是整套流程的风险兜底A/B 是真实花钱的运行派生 2 臂 × 3 仓库的claude -popus带--max-budget-usd语料目录/tmp/codegraph-corpus与/agent-eval共享clone 跨运行复用新*.wasm必须放src/extraction/wasm/copy-assetsnpm run build的一部分负责把它带进dist/否则运行时加载不到索引必须由构建它的那个二进制来服务Step 8 先构建 链接 dev buildverify-extraction.mjs又读 PATH 上同一二进制的 status这一约束在整条链路里被刻意保持拿不到 grammar、或提取到不了 PASS就 STOP 并报告——不交付半接线的语言dont ship a half-wired language。结语这套流程为什么值得参考add-lang技能把“加一种语言支持”这个看似线性的任务拆解成了每一环都有机器判据的闭环grammar 健康检查用 ABI 版本 重复解析防堆损坏节点发现用 AST 频率表代替猜节点名接线点被精确限定为 4或 5个文件提取质量用status --json的符号密度做硬门槛检索收益用同仓库双臂 A/B 的真实花费来量化。对想给 CodeGraph 增加语言支持的开发者而言照 SKILL.md 的检查单执行、辅以 scripts/add-lang/ 下四个脚本即可在不触碰核心解析逻辑的前提下完成一次可验收、可回归、可复用的语言接入。【免费下载链接】codegraphPre-indexed code knowledge graph, auto syncs on code changes, for Claude Code, Codex, Gemini, Cursor, OpenCode, AntiGravity, Kiro, CoPilot, and Hermes Agent — fewer tokens, fewer tool calls, 100% local项目地址: https://gitcode.com/GitHub_Trending/co0degr/codegraph创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

最新新闻

Flutter高精度位置服务开发实战指南

Flutter高精度位置服务开发实战指南

1. 项目概述Flutter作为Google推出的跨平台开发框架,正在重塑移动应用开发的格局。在众多应用场景中,位置服务始终是移动开发的核心需求之一。从外卖配送、共享出行到社交签到,精准的位置获取与可视化呈现直接影响用户体验。本文将带你深入Fl…

2026/9/8 0:04:17
出入口匝道智慧管理:基于EasyCVR的视频汇聚与智能分析实践

出入口匝道智慧管理:基于EasyCVR的视频汇聚与智能分析实践

1. 项目背景与整体设计思路1.1 出入口匝道场景为什么难管跑过高速的朋友都有体会,出入口匝道是整条路网里最容易出状况的地方。汇入主路时要观察主路车流、寻找可插入的间隙,驶出匝道时要提前变道、减速,一旦遇到高峰时段车流密集&#xff0c…

2026/9/8 0:04:17
POE供电的实验室温湿度监控系统:从选型到部署全攻略

POE供电的实验室温湿度监控系统:从选型到部署全攻略

做科研实验室环境监控有些年头了,踩过的坑比写过的方案还多。其中一个印象最深的问题,就是供电。实验室墙面往往早就被仪器占满,220V插座比工位还紧张,而温湿度传感器这种东西偏偏分布得特别散:细胞房、样品室、精密仪…

2026/9/8 0:04:17
总线通信精髓:多脚一线与分时复用,从USB到CAN一次讲透

总线通信精髓:多脚一线与分时复用,从USB到CAN一次讲透

搞嵌入式这么多年,我越来越觉得,总线通信这件事,最怕的就是“知其然不知其所以然”。很多人调过I2C、用过SPI、看过USB枚举的log,但真被问一句“总线到底在解决什么问题”,往往就卡住了。我琢磨了很久,发现…

2026/9/8 0:04:17
Rust Cargo 完全指南:命令、依赖管理与构建实战

Rust Cargo 完全指南:命令、依赖管理与构建实战

Cargo 这个东西,我说它是 Rust 生态的灵魂,应该没人反对。写过 Rust 的人都知道,安装好工具链之后,你打交道最多的不是 rustc,而是 Cargo。拿新建项目来说, cargo new 帮你把目录结构、Git 仓库初始化一起…

2026/9/8 0:04:17
PDF去水印工具详解:区域删除与文字删除的原理与实操

PDF去水印工具详解:区域删除与文字删除的原理与实操

不知道你有没有遇到过这种情况:千辛万苦从网上下载了一份PDF学习资料,打开一看,页面中间斜着铺了一层“仅供学习交流使用”,或者在右下角压了个半透明的论坛Logo。内容本身完全没问题,但只要有这层水印,打印…

2026/9/7 23:59:17