0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Graphify入門 — コードをナレッジグラフ化するCLIをAPIキー無しで動かす

0
Last updated at Posted at 2026-07-22

はじめに

Claude Code や Codex にコードベース全体を理解させようとすると、コンテキスト window の消費と精度のトレードオフに必ず突き当たる。この課題に対して「コードをナレッジグラフ化し、AIエージェントがそこから必要な部分だけを辿れるようにする」というアプローチのOSSがここ数週間でGitHubトレンドを急伸している。GraphifyというPython製CLIで、README では「コード解析はローカルのtree-sitter処理だけで完結しAPIキーは不要」と謳われている。であればこのツールは何にAPIキーを使うのか。実際にインストールし、APIキーを与えない状態から始めてどこで機能が止まるかを確かめた。

この記事で分かること

  • Graphifyのインストール手順とAPIキーが実際に必要になる境界
  • graphify update で作ったグラフを god-nodes / explain / query / path で調べた結果
  • コンストラクタ注入されたクロスファイルの呼び出し関係が、どこまで拾われてどこから拾われないか
  • コミュニティ命名(cluster-only)がLLMバックエンドを要求する際の実際のエラーメッセージと解決手順

対象読者

  • Claude Code / Codex 等のAIコーディングエージェントにコードベース構造を把握させたい人
  • ローカル解析だけで完結するOSS開発ツールを探している人

前提環境

  • Python 3.10以上(今回の検証はクラウド実行環境上のPython 3系・pip)
  • graphifyy 0.9.22(2026-07-21時点のPyPI最新版)

TL;DR

  • コードのグラフ抽出はtree-sitterによるローカルAST処理のみで完結し、APIキーは不要
  • god-nodes / explain / query / path の4コマンドはAPIキーなしでも動き、抽出済みグラフの中身を正確に返す
  • ただし同一ファイル内の呼び出しは高精度に拾う一方、コンストラクタ注入されたクロスファイルの呼び出しは、今回の3ファイル構成のサンプルでは --mode deep(LLMセマンティック抽出)を使っても拾われなかった
  • コミュニティ命名(cluster-only)だけがLLMバックエンドを必須とし、未インストール時は何を pip install すべきかまで明示するエラーで止まる

Graphifyとは何か

READMEによれば、Graphifyはコード・SQLスキーマ・ドキュメント・画像・動画のフォルダをtree-sitterで解析し、クエリ可能なナレッジグラフに変換するOSSツールである。Claude Code・Codex・OpenCode・Cursor・Gemini CLI など複数のAIコーディングエージェントから /graphify スキルとして呼び出せる形で配布されており、2026年7月時点で9万2000★を超えている。ライセンスはMIT。対応言語はPython・TypeScript・Go・Rust・Java・C#・SQLなど36以上に及ぶ。

出力は3種類で、ブラウザで見られるインタラクティブな graph.html、要点とサジェスト質問をまとめた GRAPH_REPORT.md、クエリ可能な生データの graph.json になる。

実際にインストールしてグラフを作る

ステップ1: インストール

PyPI上のパッケージ名は graphifyyy が2つ)だが、CLIコマンド名は graphify になる。

pip install graphifyy

READMEでは隔離環境を作る uv tool install graphifyy が推奨されているが、pipでもCLIは同じように動く。インストール後、対応言語ぶんのtree-sitterパーサーが依存関係として一括で入る。

ステップ2: グラフを作る(APIキー不要)

コンストラクタ注入パターンを含む小さなPythonサンプル(UserService / OrderRepository / Notifier の3ファイル)を用意し、--no-cluster でLLMを介さない抽出だけを走らせた。

graphify update . --no-cluster
Re-extracting code files in . (no LLM needed)...
[graphify watch] Rebuilt (no clustering): 22 nodes, 22 edges
[graphify watch] graph.json updated in graphify-out

実行時間は0.28秒。ここまでAPIキーは一度も要求されなかった。出力メッセージの「no LLM needed」という文言どおり、コード抽出はローカルのAST処理だけで完結している。

ステップ3: 抽出済みグラフを調べる

god-nodes(最も接続の多いノード)・explain(特定ノードの接続関係)・query(BFSでのグラフ探索)・path(2ノード間の最短経路)の4コマンドを試した。いずれもAPIキーなしで動作する。

graphify god-nodes --top 5
God nodes (most connected):
  1. Notifier - 4 edges
  2. OrderRepository - 4 edges
  3. UserRepository - 4 edges
  4. UserService - 4 edges
  5. OrderService - 3 edges

explainOrderService を指定すると、そのクラスが持つメソッドと、どのファイルに属するかが返る。

graphify explain "OrderService"
Node: OrderService
  Source:    order_service.py L12
  Degree:    3
Connections (3):
  --> .place_order() [method] [EXTRACTED]
  <-- order_service.py [contains] [EXTRACTED]
  --> .__init__() [method] [EXTRACTED]

ここまではサンプルコードの構造どおりの結果が正確に返っている。

ハマりポイント

ポイント1: コンストラクタ注入されたクロスファイルの呼び出しが拾われない

用意したサンプルには、OrderService.place_order() がコンストラクタで受け取った self.user_serviceUserService のインスタンス)や self.notifierNotifier のインスタンス)のメソッドを呼び出す箇所がある。これは実務のコードでよく見る依存性注入のパターンだが、抽出後のグラフに含まれる calls エッジは3本のみで、いずれも同一ファイル内の呼び出しだった。

python3 -c "
import json
d = json.load(open('graphify-out/graph.json'))
calls = [e for e in d['links'] if e.get('relation')=='calls']
for e in calls:
    print(e['source'], '->', e['target'])
"
order_service_orderservice_place_order -> order_service_orderrepository_create
user_service_userservice_register -> user_service_userrepository_save
user_service_userservice_get_profile -> user_service_userrepository_find_by_id

OrderService.place_order() から self.user_service.get_profile()self.notifier.send_reminder() へのエッジは存在しない。生成された GRAPH_REPORT.md の「Surprising Connections」欄も「None detected - all connections are within the same source files.」と、ツール自身がクロスファイルの接続をゼロ件と報告していた。

--backend openai --mode deepextract サブコマンドの「aggressive INFERRED-edge semantic extraction」オプション)でLLMセマンティック抽出を試しても、.graphify_analysis.json のトークン使用量は入力・出力ともに0のままで、ノード数・エッジ数は22のまま変わらなかった。3ファイル・22ノードという今回の小さいサンプルでは、深いセマンティック抽出パスが発火する条件(読み込んだドキュメントの規模やASTだけでは曖昧なブリッジ候補の有無)に届かなかった可能性が高い。より大きなコードベースでの挙動は今回の検証範囲外だが、少なくとも「LLM不要でグラフが作れる」高速パスは、コンストラクタ注入によるクロスファイル依存を確実に拾う設計ではない、という制約は実測で確認できた。

ポイント2: コミュニティ命名だけがLLMバックエンドを要求する

グラフをコミュニティ(意味のまとまり)に分けて名前を付ける cluster-only を、LLM関連パッケージを何も入れていない状態で実行すると次のエラーで止まる。

graphify cluster-only . --no-viz
[graphify label] batch 1/1 (13 communities) failed: the 'openai' package is required
for this backend but is not installed. Install it with:
  uv tool install "graphifyy[openai]" --force  (uv tool), or
  pip install openai  (pip/venv install).
[graphify label] warning: community labeling failed; using Community N placeholders.

エラーメッセージ自体に修復コマンドが書かれている点は親切で、指示どおり pip install openai を実行すると、同じコマンドがエラーなく完了しコミュニティに名前が付いた。バックエンドは --backendgemini|kimi|claude|openai|deepseek|ollama から選べ、未指定時は設定されているAPIキーから自動判定される。

著者視点の発見ポイント

READMEの「コード解析にAPIキーは不要」という説明は、抽出コマンド単体を見る限り正確だった。一方で、抽出したグラフの「使い道」の側、つまりコミュニティ命名や意味的な深掘り(--mode deep)はLLMバックエンド前提で設計されている。この線引きは、GraphifyをCI/CDのようなAPIキーを渡しづらい環境に組み込む際の判断材料になる。「構造だけ機械的に把握したいならAPIキー不要、意味のあるラベルや深い依存解析まで欲しいならLLM必須」という切り分けは、READMEの文面だけでは読み取りにくく、実際にAPIキーなしの状態から段階的にコマンドを叩いてはじめて境界線が見えた。

まとめ

  • Graphifyのコード抽出はtree-sitterによるローカルAST処理のみで、APIキーなしで動く
  • god-nodes / explain / query / path はAPIキーなしで抽出済みグラフを正確に返す
  • 依存性注入パターンのクロスファイル呼び出しは、今回検証した小規模サンプルでは --mode deep を使っても拾われなかった。大規模コードベースでの挙動は要検証
  • コミュニティ命名(cluster-only)だけがLLMバックエンドを必須とし、パッケージ未導入時は具体的な pip install コマンドを提示するエラーで止まる

自分のリポジトリで依存性注入を多用している場合、--no-cluster の高速パスだけで依存関係の全体像を掴もうとすると見落としが出る可能性がある。クロスファイルの依存を正確に追いたい場合は、--mode deep を使ったうえで生成された calls エッジの本数が想定より少なくないか確認するとよい。

関連記事

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?