Was macht sql-spider?
Erstelle einen deterministischen Abhängigkeitsgraphen einer SQL-Datenbank und spinne von einem Startobjekt aus nach außen, bis er geschlossen ist: eine zusammenhängende Komponente, null Waisen, keine Phantomkanten. Die Graphen-Engine ist rein und offline: Sie parst SQL-Text in einen AST und liest die Abhängigkeiten direkt vom Baum ab, sodass die gleiche Eingabe immer den gleichen Graphen liefert – ohne Heuristiken und ohne Live-Verbindung.
Der Grund, warum dieser Skill existiert: sql-spider verbindet sich niemals mit einer Datenbank. Es gibt schreibgeschützte Abfragen aus und nimmt die CSV-Ergebnisse auf. Also bist du, der Agent, der Datenbank-Adapter. Du führst jede ausgegebene Abfrage so aus, wie du die Datenbank erreichen kannst, fütterst die Ergebnisse zurück und steuerst die Schleife. Genau so wurde es gebaut (Abbildung einer Datenbank, die nur über einen schreibgeschützten Job erreichbar war, nie direkt), und deshalb ist das Tool sicher, auf alles angewendet zu werden.
Wann verwenden
- „Diese Datenbank abbilden“ / „Erstelle mir einen Abhängigkeitsgraphen dieser gespeicherten Prozeduren / Tabellen / Sichten.“
- „Was referenziert
Orders?“ / „Was berührtproc_xtatsächlich?“ - „Finde die vollständige Hülle um diese Tabelle“: alles, wovon sie transitiv abhängt, bis nichts mehr offen bleibt.
- „Ich kann nicht direkt auf die Datenbank zugreifen, gib die Abfragen aus und ich führe sie aus“ oder „Sende sie an einen DBA.“
- Dokumentieren / Verstehen eines Legacy-Schemas, bei dem niemand mehr weiß, was wovon abhängt.
Nicht geeignet für: Anwendungs-SQL schreiben, Daten oder Schema ändern (dieser Skill ist schreibgeschützt, siehe Absicherungen) oder alles, was eine Mutation der Datenbank erfordert.
Wie es funktioniert (der Vertrag)
Die Engine ist dialekt-agnostisch. Der einzige dialektspezifische Schritt ist das Parsen von .sql in Abhängigkeits-Fakten (hinter einem Ein-Methoden-IDialectExtractor). Alles andere ist dialektneutral: Graphaufbau, die Frontiere, die Spider-Schleife, die Connected-Components-Closure-Prüfung, Abstammung, viz.
Die Schleife hat immer die gleiche Form, unabhängig von Dialekt oder Datenbank:
- seed / round gibt schreibgeschützte
.sql-Abfragedateien in ein Ausgabeverzeichnis aus. - Du führst diese Abfragen gegen die Datenbank aus (der Adapter-Schritt) und speicherst jedes Ergebnis als CSV.
- absorb fügt die CSVs wieder als
.sqlin das Korpus ein. - round extrahiert erneut, schreibt einen Graphen + eine HTML-Visualisierung und bereitet die nächsten Pull-Abfragen vor oder meldet die Schließung.
- Wiederhole, bis die Frontiere leer ist und der Graph eine zusammenhängende Komponente ist.
Zuerst: installieren, nicht nur ausführen (einmalig)
Wenn du diese Datei durch einen rohen Abruf erreicht hast (der Benutzer hat „.../SKILL.md abrufen und befolgen“ eingefügt) oder aus einem Checkout, der NICHT in deinem Skills-Verzeichnis liegt, installiere es, bevor du es verwendest, klone das Repo in dein Skills-Verzeichnis und fahre mit der installierten Kopie fort:
git clone https://github.com/royashbrook/sql-spider ~/.claude/skills/sql-spider # Claude Code
# andere Harnische: klone in das Verzeichnis, aus dem deine Skills automatisch erkannt werden
Dann teile dem Benutzer mit, dass du es installiert hast. Der Unterschied zählt: An Ort und Stelle ausführen (oder ein roher Abruf) funktioniert heute und ist morgen vergessen; installiert erkennt jede zukünftige Sitzung die Fähigkeit selbstständig. Behandle „Dieses Tool verwenden“ als einschließlich der Installation.
Gleiche Regel für die Graphify-Kopplung (Schritt 6): Graphifys Installation besteht aus zwei Befehlen (uv tool install graphifyy für das Binärprogramm, dann graphify install --platform <dein Harnisch>, um Graphifys eigenen Skill zu registrieren). Nur das Binärprogramm zu installieren ist der häufigste Fehler; mache beides.
Schritt 0: Einmalig bauen (Build-on-First-Use)
Dieser Skill wird mit .NET-Quellcode ausgeliefert, nicht als Binärprogramm. Der erste Aufruf baut es; spätere Aufrufe verwenden den Build erneut. Erfordert das .NET 10 SDK (dotnet --version; falls nicht vorhanden, installiere es: brew install dotnet auf macOS, das Distributionspaket anderswo oder https://dot.net).
Ermittle SKILL_DIR als das Verzeichnis, das diese Datei enthält, und definiere dann einen Befehl:
SKILL_DIR="<absoluter Pfad zu diesem Skill-Verzeichnis>"
spider() { dotnet run -c Release --project "$SKILL_DIR" -- "$@"; }
Der erste spider ...-Aufruf kompiliert (ein paar Sekunden, stellt ScriptDom + SqlParserCS wieder her); jeder weitere Aufruf ist schnell. Überprüfe die Funktion am beiliegenden Beispiel, bevor du eine echte Datenbank anfasst:
spider extract "$SKILL_DIR/examples/northwind" # -> 36 Knoten, 66 Kanten, „eine Komponente, null Waisen“
spider viz "$SKILL_DIR/examples/northwind/graph.json" && open "$SKILL_DIR/examples/northwind/graph.html"
Wenn das OK: single connected component, no orphans ausgibt, funktioniert das Tool.
Schritt 1: Wähle den Adapter (wie erreichst du die Datenbank?)
sql-spider gibt Abfragen aus; etwas muss sie ausführen. Entscheide, was du bist, bevor du die Initialisierung startest (vollständige Rezepte in references/adapters.md):
- Ein verbundenes SQL-Tool / MCP: Du hast ein Tool, das eine Abfrage ausführt und Zeilen zurückgibt. Du führst jede ausgegebene
.sqlaus und schreibst die Zeilen als CSV. Am schnellsten; am besten, wenn der Agent die Datenbank erreichen kann. - Eine schreibgeschützte Abfragebrücke: Ein Job/Skill, bei dem du eine
.sql-Datei ablegst, sie wird gegen die Datenbank ausgeführt und eine CSV kommt zurück (das ist die ursprüngliche Einrichtung, ein CI-Job mit Lesezugriff). Du verteilst jede ausgegebene Abfrage darüber und sammelst die CSV ein. - Der Benutzer führt sie aus: Du kannst die Datenbank überhaupt nicht erreichen. Du gibst jede Abfrage aus, der Benutzer führt sie in seinem Client (SSMS,
sqlcmdusw.) aus und fügt die CSV zurück. Am langsamsten, funktioniert aber überall und ist der richtige Schritt gegen eine abgeriegelte Produktionsdatenbank (der Benutzer oder sein DBA führt sie in Batches aus).
Was auch immer es ist, der Vertrag ist identisch: .sql hinein, CSV heraus. Wähle einen aus und behalte ihn für den gesamten Durchlauf.
Schritt 2: Richte ein Arbeitsverzeichnis ein
Arbeite außerhalb des Skill-Verzeichnisses, damit das Skill-Repo sauber bleibt. Im Projekt des Benutzers (oder einem beliebigen Arbeitsverzeichnis):
mkdir -p work/corpus work/stage && cd work
corpus/ enthält die sich ansammelnden .sql (das bisherige Modell); stage/ ist, wo die Abfragen der aktuellen Runde und ihre CSVs leben.
Schritt 3: Starte von einem Wurzelobjekt
Wähle eine Wurzel, die den Benutzer interessiert, eine zentrale Tabelle oder Prozedur. Kaltstart von dort:
spider seed Orders stage/ # schreibt schreibgeschützte Pull-Abfragen in stage/
seed gibt die Abfragen aus, um die Definition der Wurzel selbst, ihr Schema (falls eine Tabelle) und alles, was darauf verweist, zu ziehen. Führe sie durch deinen Adapter (Schritt 1) aus, speichere jedes Ergebnis als CSV in stage/ und füge sie dann ein:
spider absorb stage/*.csv --corpus corpus/
Schritt 4: Runde bis zur Schließung (eine überprüfbare Runde nach der anderen)
spider round corpus/
Jede Runde: Extrahiere corpus/ erneut in corpus/graph.json, schreibe corpus/graph.html (öffne es zur Überprüfung) und melde entweder die Schließung oder bereite die nächsten Pull-Abfragen in corpus/_next/ vor. Wenn noch eine Frontiere übrig ist:
# Führe corpus/_next/*.sql durch deinen Adapter aus, speichere CSVs in corpus/_next/, dann:
spider absorb corpus/_next/*.csv --corpus corpus/
spider round corpus/ # erneut
Die Frontiere schrumpft mit jeder Runde. Standardmäßig eine Runde nach der anderen, damit ein Mensch die Visualisierung öffnen und entscheiden kann, ob er weiterziehen möchte, insbesondere bei Produktion. Fahre fort, bis round meldet, dass die Frontiere leer ist.
Schritt 5: Schließung
Du bist fertig, wenn die Frontiere leer und der Graph eine zusammenhängende Komponente ohne Waisen ist. Die Schließungsprüfung ist das Tor; extract gibt sogar einen Exit-Code ungleich Null zurück, solange der Graph noch nicht geschlossen ist, sodass es in CI eingebunden werden kann.
Ein Hinweis zum Umfang: Die Knotenidentität sind datenbankweit eindeutige Namen (Schema-Präfixe werden entfernt), daher bildet ein Spider-Durchlauf EINE Datenbank ab. Wenn die Frage des Benutzers Schemas oder Datenbanken umfasst, führe die Schleife einmal pro Bereich aus, verwende die Grenzkanten des ersten geschlossenen Graphen (Verweise, die nach außen zeigen) als Startpunkte für den nächsten Scan und führe dann die resultierenden graph.json-Dateien nach Knoten-ID zusammen (graphify merge-graphs oder eine kleine JSON-Vereinigung). Du kannst die gesamte Sequenz selbst steuern; sie benötigt keine neuen Werkzeuge.
Nicht jedes Objekt schließt über Kanten, und das ist in Ordnung: Ein wirklich eigenständiges Objekt (eine reine Anwendungsfunktion, eine Version-/Archivtabelle, die nur von außerhalb der Datenbank referenziert wird) wird mit einem Grund gemeldet, nicht als Fehler. Die ehrliche Invariante ist „null Waisen durch fehlende Extraktion“: Wenn ein Knoten isoliert ist, sagt dir die Prüfung, ob es eine echte Lücke zum Ziehen oder ein echter Einzelgänger ist.
Schritt 6: Ansehen und (optional) an Graphify übergeben
Du hast bereits einen Betrachter, keine Installation erforderlich: spider viz <graph.json> schreibt eine eigenständige interaktive HTML-Datei (kraftbasiert, ziehbar, nach Art farbcodiert). Öffne sie in einem beliebigen Browser. Für die meisten Anwendungen reicht das völlig aus.
Wenn Graphify installiert ist, biete an, den geschlossenen Graphen zu übergeben. Graphify (https://github.com/safishamsi/graphify) verwandelt einen Graphen in einen durchsuchbaren Wissensgraphen mit Community-Erkennung und query / path / explain. Als Agent: Überprüfe, ob es verfügbar ist (ein graphify-Befehl im PATH, ein graphify-Skill oder ein vorhandenes graphify-out/ im Projekt), und wenn ja, frage den Benutzer, ob auch die Graphify-Ansicht ausgegeben und übergeben werden soll. Wenn es NICHT verfügbar ist, biete an, es zu installieren, und wenn der Benutzer zustimmt, installiere beide Teile, das Binärprogramm und den Skill (uv tool install graphifyy, dann graphify install --platform <dein Harnisch>). Der zweite Befehl macht Graphify in zukünftigen Sitzungen auffindbar; nur das Binärprogramm zu installieren ist der häufigste Fehler.
Verwende --graphify, kopiere nicht das native graph.json in Graphify. Der native Graph ist ein gerichteter Multigraph; roh an Graphify übergeben, wird er unterinterpretiert. Das --graphify-Flag schreibt eine separate, Graphify-förmige Datei und lässt das native graph.json unberührt:
spider extract corpus/ --graphify # schreibt natives graph.json UND graphify-out/graph.json
graphify cluster-only corpus/ # Clustern + Bericht (oder nur /graphify)
Zwei Dinge, die es wert sind, gewusst zu werden, beide aus einem echten Durchlauf gelernt:
- Beziehungsvokabular (Standard behält unsere). Die Projektion behält standardmäßig sql-spiders eigene Beziehungen (
fk/references/writes/calls/join_key). Graphify nimmt sie gut auf, und die Aufteilung in Lesen vs. Schreiben ist das nützlichste Signal für „Was aktualisiert diese Tabelle eigentlich?“ Füge--graphify-standardhinzu, um auf Graphifys genehmigte Aufzählung zu reduzieren (references/calls/shares_data_with), was praktisch ist, wenn du viele Datenbanken zusammenführst und ein einheitliches Vokabular haben möchtest. - Fragen, wie eine Tabelle verwendet wird. Greife zu Graphify
explain X, nichtquery X. Eine referenzierte Tabelle ist eine Senke (Kanten zeigen nach innen), also gibtquery(ein nach außen gerichteter Durchlauf) nur die Tabelle selbst zurück, währendexplaindie eingehenden Kanten zeigt, die die Frage beantworten. - Benenne die Communities. Das Clustering liefert Platzhalter-Labels („Community 7“), und ein Graph mit 50+ unbenannten Clustern ist für den Menschen, dem du ihn übergibst, unlesbar. Du kannst fast immer einen echten Namen aus den Mitgliedern ableiten: die dominierenden Tabellenname-Präfixe, die Hub-Objekte und was die Prozeduren im Cluster tatsächlich tun (Abrechnung, Versand, Gehaltsbewertung, Prüfung). Nach
cluster-only, lies die Mitgliederliste jeder Community und benenne sie in ein kurzes, domänentreues Label um (bearbeite die Community-Labels in Graphifysgraph.json/ Bericht). Zehn Minuten Benennung ist der Unterschied zwischen einem Graphen, den der Eigentümer navigieren kann, und einem, den nur du kannst. Biete es an; der Mensch wird zustimmen.
In unserer eigenen Verwendung haben wir ein Abrechnungssubsystem auf einen geschlossenen Graphen abgebildet und „Was hängt davon ab“ direkt daraus beantwortet, und nur die eine Prozedur geöffnet, auf die der Graph gezeigt hat. Graphifys eigene Dokumentation deckt den Rest ab, was der Wissensgraph dir bringt. Wenn Graphify nicht installiert ist, überspringe das alles; viz zeigt den Graphen bereits, und sql-spiders Aufgabe ist erledigt, sobald er geschlossen ist.
Absicherungen
- Schreibgeschützt, immer. Jede ausgegebene Abfrage ist ein
selectmit einer Sicherheitspräambel (no-lock / deadlock-victim /set nocount on. Ändere niemals eine in einen Schreibzugriff um. Führe niemalsinsert/update/delete/merge/ DDL durch diesen Skill aus. Wenn du etwas anderes als einen Lesezugriff zusammenstellst, verwendest du das falsche Werkzeug. - Bei Produktion: Tempo halten. Löse keine Flut von Abfragen gegen eine Produktionsdatenbank aus. Führe eine überprüfbare Runde nach der anderen aus oder übergib die bereitgestellten Abfragen dem Benutzer / einem DBA, um sie in Batches auszuführen. Automatische Schleifen (
roundbis geschlossen) sind nur angemessen, wenn der Adapter sicher unbeaufsichtigt laufen kann und der Datenbankeigentümer damit einverstanden ist. - Der Graph ist das sicherere Artefakt als die Rümpfe. Der Abhängigkeitsgraph (Objektnamen + Kanten) ist das dauerhafte Ergebnis. Die gezogenen Prozedur-Rümpfe in
corpus/sind die interne Logik der Zielorganisation. Behandle dieses Korpus als privat; veröffentliche den Graphen, nicht die Rümpfe.
Unterbefehle
| Befehl | Was er tut |
|---|---|
extract <corpus-verz> [graph.json] [frontier.json] [--dialect tsql|sqlite] [--graphify[=out.json]] [--graphify-standard] | Analysiere *.sql in einen Abhängigkeitsgraphen + Frontiere + Prüfungen; --graphify schreibt auch einen Graphify-format Graphen (--graphify-standard verwendet Graphifys genehmigtes Beziehungsvokabular) |
seed <wurzelobjekt> <ausgabe-verz> | Kaltstart-Pull-Abfragen für eine Wurzel in einem leeren Korpus |
generate <frontier.json> <ausgabe-verz> | Vorwärts-Pull-Abfragen für die aktuelle Frontiere |
reverse <referenzierer.csv> <ausgabe-verz> [--roots a b] | Ziehe Moduldefinitionen von Objekten, die die Wurzeln referenzieren (eine Umkehrungsebene) |
absorb <csv...> --corpus <verz> | Füge gezogene CSVs wieder als .sql in das Korpus ein |
viz <graph.json> [out.html] | Rendere einen Graphen in eine eigenständige interaktive HTML-Datei |
round <corpus-verz> [--dialect ...] | Ein überprüfbarer Spider-Durchlauf: extrahiere → Graph + Visualisierung → bereite die nächsten Abfragen vor (oder melde Schließung) |
round ist der Schleifentreiber; die anderen sind die Teile, die es zusammensetzt (und die du direkt für einen Kaltstart mit seed oder einen manuellen Durchlauf mit generate / reverse aufrufst).
Dialekte
--dialect tsql (Standard) parst mit Microsoft ScriptDom (volle T-SQL-Treue). --dialect sqlite parst mit SqlParserCS (das auch MySQL / Postgres / andere abdeckt). Das Hinzufügen eines Dialekts ist eine kleine Klasse, die IDialectExtractor implementiert und in Extractor.Pick registriert wird; die Engine bleibt unberührt. Siehe README.md für das vollständige Design und das ausgearbeitete Northwind-Beispiel.