add-lang について
CodeGraphにtree-sitter言語を追加する自律型スキルです。文法の検証、抽出器の実装、テスト、リポジトリ評価、ドキュメント更新を行い、変更はコミットせずレビュー用に残します。
主な機能
- 01文法の健全性チェック
- 02抽出器の接続とテスト
- 03評価用リポジトリの選定
- 04抽出とAgentのA/B評価
- 05ドキュメント更新と変更報告
活用シーン
- 01CodeGraphに言語サポートを追加
- 02既存の対応言語を評価で検証
- 03リポジトリごとの検索効果を測定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ colbymchenry/ codegraph --skill add-langインストール後、Claude Code で/add-langを入力して読み込まれたか確認します。
詳細
CodeGraph に言語を追加する
新しい tree-sitter 言語を codegraph の抽出パイプラインに組み込み、人気リポジトリで実際のシンボルが抽出されることを確認し、エージェントにとって no-codegraph より優れていることを実証します。完全に自律して実行します。リポジトリを選び、ベンチマークを行い、ドキュメントを更新して、最後に報告します。コミット、プッシュ、公開、タグ付けは絶対にしないでください(チームのルール)。変更はすべてユーザーがレビューできるように残します。
引数には、Language ユニオンで使用されている言語トークンを指定します。例:lua、elixir、zig。指定がない場合は、どの言語かを尋ねてください。常に小文字の単一トークン形式を使用してください(c# ではなく csharp)。
前提条件
- codegraph リポジトリのルートから実行してください。
node、git、gh、ログイン済みのclaudeCLI が必要です(ベンチマークでは実際にclaude -pを実行します)。 - ベンチマークではローカルの開発ビルドを使用します。ステップ 8 でビルドし、PATH 上にリンクします。
ワークフロー
このチェックリストをコピーし、順番に進めてください。
- [ ] 1. Resolve language; bail early if already supported (just benchmark)
- [ ] 2. Find a grammar + health-check it (ABI / heap corruption)
- [ ] 3. Discover the grammar's 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
ステップ 1 — 解決と早期終了
言語がすでに組み込まれているか確認します。LANGUAGES 定数(src/types.ts)と EXTRACTORS マップ(src/extraction/languages/index.ts)でトークンを探してください。すでにサポートされている場合(例:typescript、rust)、ステップ 2〜6 をスキップし、そのままベンチマーク(ステップ 7〜8)に進んで検証・測定します。レポートにはコードを変更していないことを記載してください。
ステップ 2 — 文法を探し、ヘルスチェックする
ls node_modules/tree-sitter-wasms/out/ | grep -i <lang> # csharp -> c_sharp
- あり → 既成の文法である可能性が高く、
grammars.tsがtree-sitter-wasmsから自動的に解決します。(elixir、zig、ocaml、solidity、toml、yaml など、多くの言語が該当します。) - なし →
pascal/scala/luaと同様に、.wasmをsrc/extraction/wasm/にベンダーし、ステップ 4 でベンダー版の分岐にトークンを追加します。
エクストラクターを書く前に、必ずヘルスチェックをしてください。文法が存在していても使用できない場合があります。
node scripts/add-lang/check-grammar.mjs <lang> path/to/valid-sample.<ext>
文法の ABI バージョンを出力し、インデックス作成と同じ方法で実行します。インデックス作成用の V8 フラグを使い、ベンダー済み文法の隣で子プロセスを起動し、有効なサンプルを何度も解析した後、1 MiB のファイルサイズ上限でも一度解析します。失敗した場合(有効なコードで ERROR ツリーが発生する、または後続の解析で異なるツリーが返される場合。古い ABI が共有 WASM ヒープを破損させ、最初のファイル以降のすべてのファイルでネストされた呼び出しやインポートが気付かれないまま失われることがあります。例:tree-sitter-wasms の Lua 文法は ABI 13 であり、失敗します。また、すべての解析が完了した後でもプロセスがクラッシュまたはハングする場合)、その wasm は使用しないでください。代わりに、より新しい(ABI 14/15 の)ビルドをベンダーしてください。**
npm pack @tree-sitter-grammars/tree-sitter-<lang> # often ships a prebuilt *.wasm
# or build one: npx tree-sitter build --wasm (needs Docker/emscripten)
cp <the>.wasm src/extraction/wasm/tree-sitter-<lang>.wasm
次に、ステップ 4 のベンダー版の分岐にトークンを追加し、ベンダーしたパスで check-grammar を再実行して、PASS するまで確認します。正常な wasm を入手できない場合は、作業を中止してユーザーに伝えてください。
ステップ 3 — AST ノード型を調べる
代表的なソースファイルを用意します(関数、クラス/構造体、インポート、列挙型を網羅した小さなサンプルを書くか、既知のリポジトリから raw ファイルを curl します)。その後、次を実行します。
node scripts/add-lang/dump-ast.mjs <lang> path/to/sample.<ext>
# vendored grammar: pass the wasm path instead of the token
node scripts/add-lang/dump-ast.mjs src/extraction/wasm/tree-sitter-<lang>.wasm sample.<ext>
頻度テーブルとフィールド名(name:、parameters:、body:、return_type:)から、何をマッピングすべきかがわかります。その言語のパラダイムに最も近い既存のエクストラクターを開き、参考にしてください。関数型言語やトレイトなら rust.ts/scala.ts、オブジェクト指向なら java.ts/csharp.ts、スクリプト言語なら python.ts/ruby.ts、トップレベルメソッドやレシーバーがある場合は go.ts を参考にします。
ステップ 4 — 言語を接続する(4 ファイル)
以下は正確さが求められ、変更に弱い接続設定です。既存のスタイルに正確に合わせてください。
src/types.ts— 2 か所を編集します:LANGUAGES定数の'unknown'より前に'<lang>',を追加します。DEFAULT_CONFIG.includeに'**/*.<ext>',を追加します。ここを省略しないでください。これはファイルスキャンの許可リストです。この glob がないと、検出と抽出の接続設定が済んでいても、codegraph initで見つかるファイルは 0 件です。
src/extraction/grammars.ts— 3 つのマップを編集します:WASM_GRAMMAR_FILES:<lang>: 'tree-sitter-<lang>.wasm',EXTENSION_MAP:各ファイル拡張子を'<lang>'に対応付けます(例:'.lua': 'lua',)。getLanguageDisplayName:<lang>: '<Display Name>',- 同梱する場合のみ:wasm パスの分岐
(lang === 'pascal' || lang === 'scala' || …)に<lang>を追加します。
src/extraction/languages/<lang>.ts— 新しいファイルを作成し、export const <lang>Extractor: LanguageExtractor = { … }をエクスポートします。ステップ 3 で確認したノード型を対応付けてください。必須フィールド:functionTypes、classTypes、methodTypes、interfaceTypes、structTypes、enumTypes、typeAliasTypes、importTypes、callTypes、variableTypes、nameField、bodyField、paramsField。文法に応じてフックを追加します(getSignature、getVisibility、isExported、extractImport、visitNode、getReceiverType、interfaceKind、enumMemberTypesなど。src/extraction/tree-sitter-types.tsを参照してください)。src/extraction/languages/index.ts—import { <lang>Extractor } from './<lang>';を追加し、EXTRACTORSに<lang>: <lang>Extractor,を追加します。
場合によっては、src/extraction/tree-sitter.ts のコア部分も変更します。変数抽出には、extractVariable 内に言語ごとの分岐があります(汎用フォールバックで見つかるのは、直接の identifier/variable_declarator 子ノードのみです)。文法で宣言名が入れ子になっている場合(例:Lua の variable_declaration → variable_list)、既存の ts/python/go の分岐に合わせて、} else if (this.language === '<lang>') 分岐を追加してください。別個のノードではないインポート形式(Lua/Ruby の require は呼び出しです)は、エクストラクターの visitNode フックで処理します。
ステップ 5 — ビルドと検証の繰り返し
npm run build # tsc + copy-assets (copies any vendored *.wasm into dist/)
小規模なサンプルリポジトリにインデックスを作成し、抽出結果を確認します:
( cd <sample-repo> && codegraph init -i )
node scripts/add-lang/verify-extraction.mjs <sample-repo> <lang>
verify-extraction.mjs は、その言語が検出されない場合、または file/import ノードしか生成されない場合に失敗(終了コード 1)します。これは、ノード型名が間違っているときによく見られる症状です。失敗、または内容の乏しい警告が出た場合は、より大きなファイルで dump-ast.mjs を再実行し、<lang>.ts の対応付けを修正してから、npm run build を実行し、再度インデックスを作成して検証します。合格するまで繰り返してください。
ステップ 6 — テスト
Rust Extraction ブロックを参考に、__tests__/extraction.test.ts に追加します:
describe('Language Detection')にdetectLanguageのアサーションを追加します。- インラインのソース文字列から関数/クラス/インポートが抽出されることを検証する
describe('<Lang> Extraction')ブロックを追加します。
npx vitest run __tests__/extraction.test.ts
続行する前に、テストをすべて成功させてください。
ステップ 7 — リポジトリ 3 件を自動選定し、コーパスに追加する
確認を求めずに選定します。候補を見つけたうえで、実際に <lang> が主体のリポジトリをサイズ別に 1 件ずつ、合計 3 件選びます:
gh search repos --language=<lang> --sort=stars --limit 40 \
--json fullName,stargazerCount,description
サイズ区分(corpus.json に合わせます):小規模 <約150 ファイル · 中規模 約150~1500 ファイル · 大規模 >約1500 ファイル。<lang> タグが付いていても、実際には別の言語が主体のリポジトリは除外します。各リポジトリについて、ファイル間をたどる必要があるアーキテクチャに関する質問を 1 つ作成します。/agent-eval で再利用できるように、.claude/skills/agent-eval/corpus.json に "<Language>" ブロックを追加します(フィールド:name、repo、size、files、question)。
ステップ 8 — 3 つすべてをベンチマークする(抽出 + A/B)
開発ビルドで codegraph を PATH 上に一度だけビルドし、その後ループします:
npm run build && ./scripts/local-install.sh
scripts/add-lang/bench.sh <lang> <name> <url> "<question>" headless # ×3
bench.sh はクローンを作成し(/tmp/codegraph-corpus を共有)、データを消去してインデックスを作成し、verify-extraction.mjs を実行してから、scripts/agent-eval/run-all.sh でリトリーバルあり/なしの A/B テストを実行します(抽出に問題がある場合、有料の A/B テストはスキップされます)。
run-all.sh が出力する各 parse-run.mjs のサマリーを確認します。ツール呼び出し、ファイルの Read、Grep/Bash、codegraph-tool の呼び出し、所要時間、コストを、with と without の両方について確認します。ループの後、必要に応じて開発版へのリンクを復元します:
./scripts/local-install.sh。
ステップ 9 — ドキュメント + CHANGELOG
- README.md:「19+ Languages」機能項目に
<Lang>を追加し、Supported Languages テーブルに行を追加します:| <Lang> | \.ext` | Full support (classes, methods, …) |`。 - CHANGELOG.md:先頭(最新バージョンの上)に
## [Unreleased]セクションを追加し、### Addedの下にユーザー視点の項目を追加します。例: "CodeGraph now indexes (.ext) — functions, classes, imports, and call edges."。## [Unreleased]がすでにある場合は、その下に追記します。(リリース時に次のバージョン付きブロックにまとめられます。)
ステップ 10 — 報告(コミットしないこと)
レビュー用に次の内容をまとめます:
- 変更したファイル:4 つの配線編集 + 新しいエクストラクター + テスト + README + CHANGELOG + corpus.json(+ ベンダー提供の
.wasmがあればそのファイル)。 - 抽出(リポジトリごと):ファイル数 / ノード数 / エッジ数 /
verify-extractionの結果。 - A/B(リポジトリごと):
withとwithoutの比較(ツール呼び出し、ファイルの Read、コスト)と、1 行の判定 — codegraph により作業量が減ったか、両方のアームで正しい回答に到達したか。 - 不足点 / 今後の対応(まだマッピングされていないノードタイプ、不足している解決エッジ、フレームワークのルートなど)。
変更内容をユーザーに渡してください。git commit/push を実行したり、公開したりしないでください — リリースは GitHub Actions Release ワークフローを通じて行います。
注記
- A/B テストでは、実際に有料の
claude -p実行が行われます(opus、--max-budget-usd)。2 アーム × 3 リポジトリです。コーパスのディレクトリ/tmp/codegraph-corpusは/agent-evalと共有されるため、実行間でクローンが再利用されます。 - 新しい
*.wasmはすべてsrc/extraction/wasm/に置く必要があります。copy-assets(npm run buildで実行)がこれを同梱するため、そうしないとdist/に含まれません。 - インデックスは、それをビルドしたものと同じバイナリで提供する必要があります。ステップ 8 では先に開発ビルドを作成してリンクするため、この条件を満たします。
- 文法を取得できない場合、または抽出が PASS に到達できない場合は、停止して報告してください — 配線が不完全な言語を出荷しないでください。