sql-spider は何をしますか?
SQL データベースの決定論的な依存関係グラフを構築し、シードオブジェクトから外部へスパイダー探索して、閉じた状態(単一の連結コンポーネント、孤立ノードなし、架空のエッジなし)になるまで続けます。グラフエンジンは純粋でオフライン動作です。SQL テキストを AST に解析し、依存関係をツリーから直接読み取るため、同じ入力からは常に同じグラフが得られ、ヒューリスティックもライブ接続も不要です。
このスキルが存在する理由:sql-spider はデータベースに接続しません。 読み取り専用のクエリを出力し、CSV 結果を取り込みます。つまり、あなた、エージェントがデータベースアダプタとなります。 あなたは出力された各クエリを、データベースに到達可能な方法で実行し、結果をフィードバックしてループを駆動します。これこそがこのツールが構築された方法であり(直接接続できない読み取り専用ジョブ経由でのみ到達可能なデータベースをマッピングする)、任意の対象に対して安全に使用できる理由です。
いつ使用するか
- 「このデータベースをマッピングして」/「これらのストアドプロシージャ/テーブル/ビューの依存関係グラフを作成して」
- 「
Ordersを参照しているものは?」/「proc_xが実際に触っているものは?」 - 「このテーブルの完全なクロージャを見つけて」:推移的に依存しているすべてのもの、何もぶら下がらない状態まで。
- 「データベースに直接アクセスできないので、クエリを出力して実行します」または「DBA に送ってください」
- 誰も何が何に依存しているか分からなくなったレガシースキーマの文書化/理解。
使用すべきでない場面:アプリケーション SQL の作成、データやスキーマの変更(このスキルは読み取り専用です。ガードレールを参照)、データベースの変更が必要な処理。
動作の仕組み(契約)
エンジンはダイアレクトに依存しません。ダイアレクト固有の手順は、.sql を依存関係ファクトに解析することだけです(単一メソッドの IDialectExtractor の背後)。それ以外はすべてダイアレクトに依存しません:グラフアセンブリ、フロンティア、スパイダーループ、連結コンポーネントクロージャ監査、系統、viz。
ループは常に同じ形状で、ダイアレクトやデータベースに関係なく動作します:
- seed / round が読み取り専用の
.sqlクエリファイルを出力ディレクトリに出力します。 - あなたがそれらのクエリをデータベースに対して実行し(アダプタ手順)、各結果を CSV として保存します。
- absorb が CSV を
.sqlとしてコーパスに戻します。 - round が再抽出し、グラフと HTML ビジュアライゼーションを書き込み、次のプルクエリをステージングするか、クロージャを報告します。
- フロンティアが空になり、グラフが単一の連結コンポーネントになるまで繰り返します。
最初に:インストールしてください、単に実行するだけではダメ(初回のみ)
このファイルを raw フェッチ(ユーザーが "fetch .../SKILL.md and follow it" を貼り付けた)またはスキルディレクトリにないチェックアウトから入手した場合は、使用前にインストールし、リポジトリをスキルディレクトリにクローンして、インストールされたコピーから続行してください:
git clone https://github.com/royashbrook/sql-spider ~/.claude/skills/sql-spider # Claude Code
# 他のハーネス:スキルが自動検出される場所にクローンしてください
その後、ユーザーにインストールしたことを伝えてください。違いは重要です:その場での実行(または raw フェッチ)は今日は動作しますが、明日には忘れられます。インストールすれば、将来のすべてのセッションで自動的に機能を発見できます。「このツールを使用する」にはインストールも含めてください。
graphify のペアリングについても同じルールです(手順 6):graphify のインストールは2 つのコマンドが必要です(バイナリ用に uv tool install graphifyy、次に graphify 独自のスキルを登録するために graphify install --platform <あなたのハーネス>)。バイナリのみのインストールが最も一般的なミスなので、両方行ってください。
手順 0:一度ビルドする(初回使用時にビルド)
このスキルは .NET のソースコードを提供し、バイナリは含みません。最初の呼び出しでビルドされ、以降の呼び出しではビルドが再利用されます。.NET 10 SDK が必要です(dotnet --version;なければインストール:macOS では brew install dotnet、その他のディストリビューションではパッケージ、または https://dot.net)。
SKILL_DIR をこのファイルを含むディレクトリの絶対パスに解決し、次のコマンドを定義します:
SKILL_DIR="<このスキルディレクトリの絶対パス>"
spider() { dotnet run -c Release --project "$SKILL_DIR" -- "$@"; }
最初の spider ... 呼び出しでコンパイルが行われ(数秒、ScriptDom + SqlParserCS を復元)、以降の呼び出しは高速です。実際のデータベースに触れる前に、バンドルされている例で動作確認を行ってください:
spider extract "$SKILL_DIR/examples/northwind" # -> 36 ノード、66 エッジ、「単一コンポーネント、孤立ノードなし」
spider viz "$SKILL_DIR/examples/northwind/graph.json" && open "$SKILL_DIR/examples/northwind/graph.html"
OK: single connected component, no orphans と表示されれば、ツールは正常に動作しています。
手順 1:アダプタを選ぶ(データベースにどうやってアクセスするか?)
sql-spider はクエリを出力します。誰かがそれを実行する必要があります。シードを行う前に、あなたがどれに該当するかを決めてください(完全なレシピは references/adapters.md にあります):
- 接続された SQL ツール / MCP:クエリを実行して行を返すツールがあります。出力された各
.sqlを実行し、行を CSV として書き出します。最速。エージェントが DB にアクセスできる場合に最適。 - 読み取り専用クエリブリッジ:
.sqlファイルを置くと、それがデータベースに対して実行され、CSV が返ってくるジョブ/スキル(これが元の設定、読み取りアクセス権を持つ CI ジョブ)。出力された各クエリをそれを通じて送信し、CSV を収集します。 - ユーザーが実行:データベースにまったくアクセスできません。各クエリを表示し、ユーザーが自分のクライアント(SSMS、
sqlcmdなど)で実行し、CSV を貼り返してもらいます。最も遅いですが、どこでも動作し、ロックダウンされた本番データベースに対しては正しい方法です(ユーザーまたはその DBA がバッチで実行)。
いずれにしても、契約は同じです:出力された .sql が入力、CSV が出力。1 つ選び、実行中はそれを維持してください。
手順 2:作業ディレクトリを設定する
スキルディレクトリの外で作業し、スキルリポジトリをクリーンな状態に保ってください。ユーザーのプロジェクト(または任意のスクラッチディレクトリ)で:
mkdir -p work/corpus work/stage && cd work
corpus/ には蓄積された .sql(現在までのモデル)が保持され、stage/ は今回のラウンドのクエリとその CSV が配置されます。
手順 3:ルートオブジェクトからシードする
ユーザーが気にかけているルート、中央のテーブルやプロシージャを選んでください。そこからコールドスタートします:
spider seed Orders stage/ # 読み取り専用プルクエリを stage/ に書き込みます
seed は、ルート自体の定義、そのスキーマ(テーブルの場合)、およびそれを参照するすべてのものをプルするためのクエリを出力します。それらをアダプタ(手順 1)を通して実行し、各結果を CSV として stage/ に保存し、次にそれらを統合します:
spider absorb stage/*.csv --corpus corpus/
手順 4:クロージャまでラウンドを繰り返す(一度に 1 つのレビュー可能なラウンド)
spider round corpus/
各ラウンド:corpus/ を再抽出して corpus/graph.json に書き込み、corpus/graph.html(開いて確認)を書き込み、クロージャを報告するか、次のプルクエリを corpus/_next/ にステージングします。フロンティアが残っている場合:
# corpus/_next/*.sql をアダプタを通して実行し、CSV を corpus/_next/ に保存してから:
spider absorb corpus/_next/*.csv --corpus corpus/
spider round corpus/ # 再度実行
フロンティアはラウンドごとに縮小します。デフォルトでは一度に 1 ラウンドとし、人間がビジュアライゼーションを開いて、特に本番環境に対して、プルを続けるかどうかを判断できるようにしてください。round がフロンティアが空であると報告するまで続けてください。
手順 5:クロージャ
フロンティアが空かつグラフが単一の連結コンポーネントで孤立ノードがゼロになったら完了です。クロージャ監査がゲートとなります。extract はグラフがまだ閉じていない間は非ゼロの終了コードを返すため、CI に組み込むこともできます。
スコープに関する注意:ノード ID はデータベーススコープのベア名です(スキーマプレフィックスは削除されます)。したがって、1 回のスパイダー実行で 1 つのデータベースをマッピングします。ユーザーの質問がスキーマやデータベースにまたがる場合は、スコープごとにループを 1 回実行し、最初に閉じたグラフの境界エッジ(外側を指す参照)を次のスキャンのシードとして使用し、結果の graph.json ファイルをノード ID でマージします(graphify merge-graphs、または小さな JSON ユニオン)。そのシーケンス全体を自分で駆動できます。新しいツールは必要ありません。
すべてのオブジェクトがエッジで閉じるわけではなく、それは問題ありません。真に独立したオブジェクト(アプリ専用の関数、データベース外からのみ参照されるバージョン/アーカイブテーブル)は、エラーとしてではなく理由付きで報告されます。誠実な不変条件は「抽出ミスによる孤立ノードがゼロ」です:ノードが孤立している場合、監査はそれがプルすべき実際のギャップなのか、真の独立オブジェクトなのかを教えてくれます。
手順 6:表示する、および(オプション)graphify に引き渡す
インストール不要ですでにビューアがあります:spider viz <graph.json> はスタンドアロンのインタラクティブ HTML(力指向、ドラッグ可能、種類別に色分け)を書き出します。任意のブラウザで開いてください。ほとんどの用途ではこれで十分です。
graphify がインストールされている場合、閉じたグラフを引き渡すことを提案してください。 graphify (https://github.com/safishamsi/graphify) はグラフを、コミュニティ検出と query / path / explain 機能を備えたクエリ可能なナレッジグラフに変換します。エージェントとして、それが利用可能かどうかを確認し(PATH 上の graphify コマンド、graphify スキル、またはプロジェクト内の既存の graphify-out/ ディレクトリ)、利用可能な場合はユーザーに graphify ビューの出力と引き渡しを提案してください。利用できない場合は、インストールを提案し、ユーザーが同意した場合は、両方のコンポーネント(バイナリとスキル)をインストールしてください(uv tool install graphifyy、次に graphify install --platform <あなたのハーネス>)。2 番目のコマンドは、将来のセッションで graphify を検出可能にするためのものであり、バイナリのみのインストールが最も一般的なミスです。
--graphify を使用し、ネイティブの graph.json を graphify にコピーしないでください。 ネイティブグラフは有向マルチグラフです。そのまま graphify に渡すと過小解釈されます。--graphify フラグは、別の graphify 用のファイルを書き出し、ネイティブの graph.json はそのままにします:
spider extract corpus/ --graphify # ネイティブの graph.json と graphify-out/graph.json の両方を書き込みます
graphify cluster-only corpus/ # クラスタリングして報告する(または単に /graphify)
実際の実行から学んだ、知っておく価値のある 2 つのこと:
- 関係語彙(デフォルトではこちらを維持)。 デフォルトでは、プロジェクションは sql-spider 独自の関係を維持します(
fk/references/writes/calls/join_key)。graphify はこれらを問題なく取り込み、読み取り対書き込みの分割は「このテーブルを実際に更新しているものは何か」という最も有用なシグナルです。--graphify-standardを追加すると、代わりに graphify の定義済み列挙型(references/calls/shares_data_with)に統合できます。これは、複数のデータベースをマージしていて、1 つの統一語彙が必要な場合に便利です。 - テーブルがどのように使用されているかを尋ねる。
query Xではなくexplain Xに到達してください。参照されるテーブルはシンクです(エッジが内向き)。そのためquery(外向きの探索)はテーブル自体のみを返しますが、explainは質問に答える入ってくるエッジを表示します。 - コミュニティに名前を付ける。 クラスタリングではプレースホルダーラベル(「コミュニティ 7」)が生成され、50 以上の名前のないクラスターがあるグラフは、それを手渡された人間には読めません。メンバーから実際の名前をほぼ常に推測できます:支配的なテーブル名のプレフィックス、ハブオブジェクト、およびクラスター内のプロシージャが実際に行っていること(請求、ディスパッチ、給与評価、監査)。
cluster-onlyの後、各コミュニティのメンバーリストを読み、短いドメインに忠実なラベルに名前を変更してください(graphify のgraph.json/ レポート内のコミュニティラベルを編集)。10 分の名前付けは、所有者がナビゲートできるグラフと、あなただけがナビゲートできるグラフの違いです。提案してください。人間ははいと言うでしょう。
私たち自身の使用では、請求サブシステムを閉じたグラフにマッピングし、「これに依存しているものは何か」を直接グラフから回答し、グラフが指し示す 1 つのプロシージャだけを開きました。graphify の独自のドキュメントが、ナレッジグラフがもたらすその他の利点をカバーしています。graphify がインストールされていない場合は、これらすべてをスキップしてください。viz がすでにグラフを表示しており、sql-spider の仕事はクロージャが達成された時点で完了です。
ガードレール
- 常に読み取り専用。 出力されるすべてのクエリは、no-lock / deadlock-victim /
set nocount onの安全プリアンブルが付いたselectです。これを書き込みに編集しないでください。このスキルを通じてinsert/update/delete/merge/ DDL を実行しないでください。読み取り以外のものを構成している場合は、間違ったツールを使用しています。 - 本番環境に対してはペースを調整してください。 本番データベースにクエリのフラッドを自動で発射しないでください。一度に 1 つのレビュー可能なラウンドを実行するか、ステージングされたクエリをユーザー/DBA に渡してバッチで実行してもらってください。自動ループ(
roundが閉じるまで)は、アダプタが安全に無人実行でき、データベース所有者がそれで問題ない場合にのみ適切です。 - グラフは本文よりも安全な成果物です。 依存関係グラフ(オブジェクト名 + エッジ)が耐久性のある出力です。
corpus/内のプルされたプロシージャ本文は、対象組織の内部ロジックです。そのコーパスをプライベートとして扱い、グラフを公開し、本文は公開しないでください。
サブコマンド
| コマンド | 機能 |
|---|---|
| `extract [graph.json] [frontier.json] [--dialect tsql | sqlite] [--graphify[=out.json]] [--graphify-standard]` |
seed <root-object> <outdir> | 空のコーパス上で 1 つのルートに対するコールドスタートプルクエリを生成 |
generate <frontier.json> <outdir> | 現在のフロンティアに対する前方プルクエリを生成 |
reverse <referencers.csv> <outdir> [--roots a b] | ルートを参照するオブジェクトのモジュール定義をプル(1 レベルの逆方向) |
absorb <csv...> --corpus <dir> | プルされた CSV を .sql としてコーパスに統合 |
viz <graph.json> [out.html] | グラフを 1 つのスタンドアロンインタラクティブ HTML ファイルにレンダリング |
round <corpus-dir> [--dialect ...] | 1 回のレビュー可能なスパイダーパス:抽出 → グラフ + ビジュアライゼーション → 次のクエリをステージング(またはクロージャを報告) |
round がループドライバです。その他は、round が構成する部品(および seed によるコールドスタート、または generate / reverse による手動パスのために直接呼び出す部品)です。
ダイアレクト
--dialect tsql(デフォルト)は、Microsoft ScriptDom を使用して解析します(完全な T-SQL 忠実度)。--dialect sqlite は、SqlParserCS を使用して解析します(MySQL / Postgres などもカバー)。ダイアレクトの追加は、IDialectExtractor を実装する 1 つの小さなクラスを Extractor.Pick に登録するだけです。エンジンには触れません。
完全な設計と動作する Northwind の例については README.md を参照してください。
通常のユーザーフロー
最も一般的なフローは次のとおりです:
- ユーザーが「このデータベースをマッピングして」または「テーブル X が何に依存しているか教えて」と依頼します。
- あなた(エージェント)がルートオブジェクトを特定します。
seed、クエリを実行、absorb、roundのループをクロージャまで実行します。- ユーザーに
graph.htmlを表示します。 - (オプション)graphify が利用可能な場合は、ナレッジグラフのエクスポートとコミュニティの名前付けを提案します。
以上です。データベースへの書き込みはなく、ライブ接続もなく、すべての手順はレビュー可能です。
トラブルシューティング
- ビルドに失敗する: .NET 10 SDK がインストールされていることを確認してください(
dotnet --version)。インストールされていない場合は、brew install dotnet(macOS)または https://dot.net からインストールしてください。 - 解析エラー:
--dialectがデータベースタイプと一致していることを確認してください。T-SQL にはtsql、SQLite/MySQL/Postgres にはsqlite。 - 空のフロンティアだがクロージャではない:
extractの出力を確認してください。孤立ノードが報告されている可能性があります。次のプルラウンドのために手動でgenerateを使用する必要があるかもしれません。 - graphify が見つからない: バイナリ(
uv tool install graphifyy)とスキル(graphify install --platform <あなたのハーネス>)の両方をインストールしたことを確認してください。