🔍 AST-Digger
AI エージェントのためのピンポイント・コード解析 CLI
AST-Digger は、AIエージェントが大規模なコードベースを効率的に探索するための構文解析・コード抽出ツールです。本ツールはリポジトリルート直下(cmd/, internal/等)に実装されています。詳細な設計判断の経緯は SPECS/design.md・SPECS/tech.md・doc/adr/ 配下のADRを参照してください。
📎 全8サブコマンド(outline / symbol / locate / references / resolve-import / directory / feedback / agent-context)が実装済みで、CLIとして一通り機能します。
📚 目次
概要
大規模コードベースをAIエージェントが探索する際、ファイル全体を読み込むとコンテキストウィンドウが無駄に消費され、推論の精度も低下します。AST-Digger は tree-sitter を使って AST(抽象構文木)を高速にパースし、エージェントが必要な情報だけをピンポイントかつ構造的に取り出せる CLI ツールです。シングルバイナリとして動作し、ピンポイント抽出・差分キャッシュ・上限制御付き出力を提供します。
対応言語
| 言語 |
拡張子 |
| Python |
.py |
| TypeScript |
.ts, .tsx |
| Go |
.go |
| Java |
.java |
| JavaScript |
.js, .jsx |
| Rust |
.rs |
インストール / ビルド
必要環境
- Go 1.22 以上
- Cコンパイラ(gcc/clang 等)が必須です。tree-sitter バインディング(
github.com/tree-sitter/go-tree-sitter および各言語文法パッケージ)が CGO に依存しているため、CGO_ENABLED=1 でのビルドには C コンパイラが必要です。CGO依存に関する詳細は SPECS/tech.md および ADR-0005 を参照してください。
ビルド手順
リポジトリルートを作業ディレクトリとして、以下を実行します。共通のビルドコマンドは全プラットフォームで同一です。
go build ./cmd/ast-digger
カレントディレクトリに ast-digger(Windowsでは ast-digger.exe)という実行ファイルが生成されます。ただし、このgo buildが成功するには、各OSで以下のようにCコンパイラを用意しておく必要があります。
Windows
MinGW-w64 系のGCCツールチェインが必要です。以下のいずれかで導入してください。
- MSYS2 を導入し、
pacman -S mingw-w64-ucrt-x86_64-gcc 等で gcc をインストールする(MSYS2のUCRT64/MINGW64シェルのbinディレクトリをPATHに追加)。
- WinLibs が配布するビルド済みMinGW-w64一式を展開し、
binディレクトリをPATHに追加する。
- Chocolatey等のパッケージマネージャ経由で
mingw パッケージを導入する(choco install mingw)。
gcc --version がPowerShell/コマンドプロンプトから実行できることを確認してからビルドしてください。
macOS
Xcode Command Line Tools(clang)を導入します。
xcode-select --install
Linux
ディストリビューション標準のCコンパイラパッケージを導入します(Debian/Ubuntu系の例)。
sudo apt-get install build-essential
RHEL/Fedora系では sudo dnf groupinstall "Development Tools" 等、ディストリビューションの慣習に従ってください。
クロスコンパイルはスコープ外です
GOOS/GOARCH を切り替えたクロスコンパイル(例: Windows上で GOOS=linux go build を実行してLinux向けバイナリを生成する)は、本プロジェクトの方針として行いません。
CGOを有効にすると、ターゲットプラットフォーム向けのCクロスコンパイラの整備(zig cc 等)が別途必要になります。本プロジェクトはtree-sitterバインディングの利用(CGO依存)を優先し、クロスコンパイル対応の複雑化を避けるという方針決定を行いました。詳細は SPECS/tech.md および ADR-0005 を参照してください。
各プラットフォーム向けのバイナリは、そのプラットフォーム上でのネイティブビルドによって個別に生成する運用とします。
静的リンクについて
要件I-1(SPECS/requirements.md)により、Windows/Linuxでは生成バイナリが追加の共有ライブラリ配置なしに単独で動作することを必須とします。macOSはAppleのOS制約により完全な静的リンクができないため、システムライブラリへの動的リンクを許容し、可能な範囲での静的リンク(ベストエフォート)を目標とします。
静的リンクを促すビルドフラグの例(Windows):
CGO_ENABLED=1 go build -ldflags '-linkmode external -extldflags "-static"' -o ast-digger.exe ./cmd/ast-digger
⚠️ Windows環境では出力先ファイルに .\ast-digger.exe のように明示的に指定して実行することを推奨します。
バイナリサイズの削減(シンボル・デバッグ情報の削除)
配布用バイナリのファイルサイズを軽量化したい場合や、セキュリティソフトによる誤検知(False Positive)を回避したい場合は、-ldflags "-s -w" フラグを付与してビルドすることを推奨します。
go build -ldflags "-s -w" -o ast-digger.exe ./cmd/ast-digger
-s: 記号表(シンボルテーブル)を削除
-w: DWARF デバッグ情報を削除
💡 削減効果の実測値: 通常ビルド(約 22.8 MB)に対し、本フラグを付与することで 約 12.3 MB(約 46% 削減) までバイナリサイズを大幅に軽量化できます。
実行
ビルドせずに直接実行する場合:
go run ./cmd/ast-digger --version
ビルド済みバイナリを実行する場合:
./ast-digger --version
クイックスタート
以下は、実際にビルドしたバイナリを実行して得られた出力例です(対象は testdata/python/ 配下のテスト用フィクスチャ)。
ディレクトリ構造をシンボル付きで確認する
./ast-digger directory testdata/python/importproj
importproj/
bad_caller.py
main.py
mathutils.py
def add
def subtract
def multiply
def divide
__init__.py
def init_func
caller.py
utils.py
def util_func
ファイルのスケルトン(骨格コード)を取得する
./ast-digger outline testdata/python/importproj/mathutils.py
def add(a, b):
"""Add two numbers."""
...
def subtract(a, b):
"""Subtract b from a."""
...
def multiply(a, b):
"""Multiply two numbers."""
...
def divide(a, b):
"""Divide a by b."""
...
特定のシンボルを抽出する
./ast-digger symbol testdata/python/sample.py Greeter.shout
@staticmethod
def shout(message: str) -> str:
"""Shout a message."""
return message.upper()
コマンドリファレンス
共通フラグ --json / -j はすべてのコマンドに付与されており、指定するとJSON出力に切り替わります(agent-contextは常にJSON出力)。
directory — ディレクトリツリー + シンボル一覧
ast-digger directory [dir_path] [--recursive] [--no-recursive] [--limit N] [--json]
| オプション |
デフォルト |
説明 |
dir_path |
. |
スキャン対象ディレクトリ |
--recursive |
true(bool flag) |
サブディレクトリを再帰的にスキャンする |
--no-recursive |
false(bool flag) |
指定すると--recursiveの値に関わらずトップレベルのみをスキャンする |
--limit N |
50 |
表示するファイル数の上限 |
.workspace_cache/symbols.db(SQLite)を活用し、変更されたファイルのみを差分スキャンするため高速です。
多言語混在プロジェクトの例(testdata/mixed/references/、Python/TypeScript/Go/Java/JavaScript混在):
./ast-digger directory testdata/mixed/references
references/
caller.go
def useHelper
caller.java
class Caller
def callSite
caller.js
caller.py
caller.ts
target.go
def helperFn
target.java
class Target
def helperFn
target.js
def helperFn
target.py
def helperFn
target.ts
def helperFn
JSON出力時は、テキストツリー全体が {"result": "..."} の1文字列としてラップされます:
./ast-digger directory testdata/python/importproj --json
{
"result": "importproj/\n bad_caller.py\n main.py\n mathutils.py\n def add\n def subtract\n def multiply\n def divide\n __init__.py\n def init_func\n caller.py\n utils.py\n def util_func"
}
outline — スケルトンコード生成
ast-digger outline <file_path> [--json] [--no-truncate]
関数やメソッドの実装ボディを省略し、シグネチャ・docstring/doc comment・型情報だけを残したアウトラインコードを生成します。テキスト出力は300行を超えると自動的に切り詰められます(--no-truncateで無効化可能。--jsonは常に無切り詰め)。
# Python
./ast-digger outline testdata/python/importproj/mathutils.py
# TypeScript
./ast-digger outline testdata/typescript/sample.ts
# Go
./ast-digger outline testdata/go/sample.go
# Java
./ast-digger outline testdata/java/sample.java
# JavaScript(.jsxも同一文法でパース可能)
./ast-digger outline testdata/javascript/sample.jsx
# Rust
./ast-digger outline testdata/rust/sample.rs
# JSON 出力(シンボル構造データの配列)
./ast-digger outline testdata/python/importproj/mathutils.py --json
Go対象ファイルの出力例:
package sample
import "fmt"
// TopLevelFunction doubles x.
func TopLevelFunction(x int) int { /* ... */ }
// Greeter is a struct responsible for greetings.
type Greeter struct {
Prefix string
}
// Greet returns a greeting string using a pointer receiver.
func (g *Greeter) Greet(name string) string { /* ... */ }
// Shout returns an uppercased message using a value receiver.
func (g Greeter) Shout(message string) string { /* ... */ }
// Animal describes something that can speak.
type Animal interface {
// Speak returns the sound the animal makes.
Speak() string
}
// ... (以下、型エイリアス・named type・トップレベル関数が続く)
symbol — ピンポイントコード抽出
ast-digger symbol <file_path> <symbol_path> [--json] [--no-truncate]
symbol_path はドット区切りで指定します(例: ClassName.method_name。Goの場合は ReceiverType.MethodName)。抽出コードが300行を超える場合はテキスト・JSONいずれの出力でも自動的に切り詰められます(--no-truncateで無効化可能)。
# メソッドを抽出
./ast-digger symbol testdata/python/sample.py Greeter.shout
# レシーバメソッドを抽出(Go)
./ast-digger symbol testdata/go/sample.go Greeter.Greet
# クラスメソッドを抽出(TypeScript)
./ast-digger symbol testdata/typescript/sample.ts Greeter.shout
# メソッドを抽出(Java。コンストラクタも kind: "method" として同様に扱われる)
./ast-digger symbol testdata/java/sample.java SampleClass.greet
# クラスメソッドを抽出(JavaScript)
./ast-digger symbol testdata/javascript/sample.js Greeter.shout
# メソッド/関数を抽出(Rust)
./ast-digger symbol testdata/rust/sample.rs Greeter.greet
# JSON 出力(メタデータ付き)
./ast-digger symbol testdata/python/sample.py Greeter.shout --json
JSON出力例:
{
"name": "shout",
"kind": "method",
"parent": "Greeter",
"file_path": "testdata/python/sample.py",
"start_line": 16,
"end_line": 19,
"signature": "@staticmethod\ndef shout(message: str) -> str",
"docstring": "Shout a message.",
"code": "@staticmethod\n def shout(message: str) -> str:\n \"\"\"Shout a message.\"\"\"\n return message.upper()"
}
シンボルが見つからない場合は、類似するシンボル名候補が最大5件、終了コード4とともに提示されます:
./ast-digger symbol testdata/python/sample.py Greeter.shuot
Error: symbol not found: "Greeter.shuot" in testdata/python/sample.py
Did you mean?
- Greeter.shout
- Greeter
- Greeter.__init__
locate — シンボルの行範囲を特定
ast-digger locate <file_path> <symbol_path> [--json]
コードを読み込まずに、シンボルの開始行・終了行だけを高速に返します。巨大なシンボルをsymbolで取得する前に、あらかじめサイズを確認する用途に向いています。
./ast-digger locate testdata/python/sample.py Greeter.shout
# → testdata/python/sample.py:16-19
./ast-digger locate testdata/python/sample.py Greeter.shout --json
# → {"file": "testdata/python/sample.py", "symbol": "shout", "start_line": 16, "end_line": 19}
references — プロジェクト横断の参照探索
ast-digger references <symbol_name> [--project-root DIR] [--limit N] [--json]
--project-root(デフォルト.)配下の全対応ファイルから指定シンボルが参照・呼び出されている箇所を探索します。コメントや文字列リテラル内の出現は除外されます。件数が--limit(デフォルト50)を超えると切り詰められ、超過分を絞り込むためのヒントがstderrに出力されます(JSON出力時はtruncated/total_count/limit/hintキーとして返却)。
./ast-digger references target_func --project-root testdata/python/references
testdata/python/references/caller_a.py:2: target_func() # actual reference on this line
testdata/python/references/caller_b.py:6: value = target_func
上限超過時のヒント表示の例:
./ast-digger references bulk_symbol --project-root testdata/python/references_bulk --limit 5
testdata/python/references_bulk/callers.py:2: bulk_symbol() # call site 0
testdata/python/references_bulk/callers.py:3: bulk_symbol() # call site 1
testdata/python/references_bulk/callers.py:4: bulk_symbol() # call site 2
testdata/python/references_bulk/callers.py:5: bulk_symbol() # call site 3
testdata/python/references_bulk/callers.py:6: bulk_symbol() # call site 4
# ... (truncated: 5 of 60 results shown. Use --limit to increase or narrow down using --project-root)
注意(Go/Java対象コード固有の挙動): GoおよびJava版パーサーのFindReferencesInFileは、定義箇所自体を参照結果から除外しません。そのため、.go/.javaファイルを対象にreferencesを実行すると、呼び出し箇所に加えて定義行も含まれます(Python/TypeScript/JavaScriptの各パーサーは定義箇所を除外します)。
resolve-import — インポート定義元の解決
ast-digger resolve-import <file_path> <symbol_name> [--json]
対象ファイルのインポート文を解析し、指定シンボルの定義元ファイルと行番号を解決します。
インポートはカレントディレクトリをプロジェクトルート(Pythonでいうsys.path[0]相当)とみなして解決するため、モジュール参照を含むファイルを対象にする場合は、そのファイルが属するプロジェクトルート(例えばgo.modやパッケージの起点ディレクトリ)をカレントディレクトリにして実行してください。
Javaの場合、プロジェクトルート配下にsrc/main/java(Maven/Gradleの慣習的なソースルート)が存在すればそちらを優先し、なければプロジェクトルート自体をソースルートとして解決します。単一インポート(import com.example.Foo;)とワイルドカードインポート(import com.example.*;)の両方に対応します。
cd testdata/python/importproj
../../../ast-digger resolve-import main.py add
# → mathutils.py:1
../../../ast-digger resolve-import main.py add --json
# → {"file_path": "mathutils.py", "start_line": 1}
# Java(プロジェクトルート = testdata/java/importproj、src/main/java をソースルートとして解決)
cd testdata/java/importproj
../../../ast-digger resolve-import src/main/java/com/example/app/Main.java MathUtils
# → .../testdata/java/importproj/src/main/java/com/example/util/MathUtils.java:3
# JavaScript
cd ../../../testdata/javascript/importproj
../../../ast-digger resolve-import main.js add
# → mathutils.js:1
# Rust
cd ../../../testdata/rust/importproj
../../../ast-digger resolve-import main.rs add
# → utils.rs:1
feedback — フィードバックの記録
ast-digger feedback <message> [--json]
AI エージェントがツール利用中に発生した問題や摩擦を .workspace_cache/feedback.jsonl にタイムスタンプ付きで記録します。
./ast-digger feedback "outline command was helpful"
# → Feedback recorded successfully.
./ast-digger feedback "outline command was helpful" --json
{
"message": "Feedback recorded successfully."
}
agent-context — CLI スキーマの取得
ast-digger agent-context
登録済みの全コマンド・引数・オプションのスキーマを、常にJSONで出力します。AI エージェントがツール利用を開始する前に実行することで、正確な呼び出し方を自動学習できます。
出力の抜粋:
"directory": {
"description": "Print directory tree structure populated with incremental cached symbol outline.",
"arguments": [
{ "name": "dir_path", "type": "string", "required": false, "default": "." }
],
"options": [
{ "name": "--limit", "type": "integer", "default": "50", "description": "Max files to display in the output to avoid token bloating." },
{ "name": "--no-recursive", "type": "boolean", "default": "false", "description": "Scan only the top level of the directory tree; overrides --recursive." },
{ "name": "--recursive", "type": "boolean", "default": "true", "description": "Scan recursively down the directory tree (pass --recursive=false or --no-recursive to scan only the top level)." },
{ "name": "--json", "type": "boolean", "default": "false", "description": "Output structure in JSON format" }
]
}
AIエージェントの推奨ワークフロー
推奨される基本的な探索フロー(ルートの SKILL.md で定義済み)は以下の通りです:
1. directory → プロジェクト全体のシンボル構成を俯瞰(--json推奨)
2. outline → 対象ファイルのスケルトンで構造を把握(--json推奨)
3. locate → 目的のシンボルの行範囲・サイズを事前確認
4. symbol → サイズを確認した上でピンポイントに実装コードを抽出
5. references → 変更の影響範囲をプロジェクト横断で確認(--project-rootで絞り込み推奨)
避けるべきアンチパターン
- 巨大シンボルの無計画な全取得:
symbolコマンドを--no-truncate付きで無計画に読み込むと、LLMのコンテキストウィンドウを浪費し推論精度の低下を招きます。まずlocateでサイズを確認してください。
- 無制限の参照探索:
referencesコマンドは--project-rootで対象を絞り込まずに巨大プロジェクト全体をスキャンすると時間がかかります。
キャッシュと差分スキャン
directory コマンドはプロジェクトルートの .workspace_cache/symbols.db(SQLite)にシンボルインデックスをキャッシュし、feedback コマンドは同じく .workspace_cache/feedback.jsonl にフィードバックを追記します。
- 初回実行: 全ファイルをスキャンしてキャッシュを構築
- 2回目以降:
mtime と SHA-256 ハッシュで変更を検知し、変更ファイルのみ再スキャン
node_modules, .git, .venv, __pycache__ は自動的に除外
ライセンス
Apache License 2.0