¿Qué hace sql-spider?
Construye un grafo de dependencias determinista de una base de datos SQL y "araña" hacia afuera desde un objeto semilla hasta que se cierra: un único componente conectado, cero huérfanos, sin aristas fantasma. El motor de grafos es puro y fuera de línea: analiza el texto SQL en un AST y lee las dependencias directamente del árbol, por lo que la misma entrada siempre produce el mismo grafo, sin heurísticas ni conexión en vivo.
Lo que este skill existe para resolver: sql-spider nunca se conecta a una base de datos. Emite consultas de solo lectura y consume los resultados CSV. Es decir, tú, el agente, eres el adaptador de base de datos. Tú ejecutas cada consulta emitida como puedas llegar a la base de datos, alimentas los resultados y conduces el bucle. Así es exactamente como se construyó (mapeando una base de datos accesible solo a través de un trabajo de solo lectura, nunca una conexión directa), y es por eso que la herramienta es segura para apuntar a cualquier cosa.
Cuándo usar esto
- "Mapea esta base de datos" / "construye un grafo de dependencias de estos procedimientos almacenados / tablas / vistas."
- "¿Qué referencia a
Orders?" / "¿qué toca realmenteproc_x?" - "Encuentra el cierre completo alrededor de esta tabla": todo de lo que depende, transitivamente, hasta que nada quede colgando.
- "No puedo acceder directamente a la base de datos, emite las consultas y yo las ejecutaré", o "envíalas a un DBA."
- Documentar / entender un esquema heredado donde nadie sabe qué depende de qué.
No para: escribir SQL de aplicación, modificar datos o esquemas (este skill es de solo lectura, ver Salvaguardas), ni nada que requiera mutar la base de datos.
Cómo funciona (el contrato)
El motor es independiente del dialecto. El único paso específico del dialecto es analizar .sql en hechos de dependencia
(detrás de un IDialectExtractor con un solo método). Todo lo demás es neutral al dialecto: montaje del grafo, la frontera, el bucle spider, la auditoría de cierre de componentes conectados, linaje, viz.
El bucle siempre tiene la misma forma, independientemente del dialecto o la base de datos:
- seed / round emite archivos de consulta
.sqlde solo lectura en un directorio de salida. - Tú ejecutas esas consultas contra la base de datos (el paso del adaptador) y guardas cada resultado como un CSV.
- absorb pliega los CSV de vuelta al corpus como
.sql. - round re-extrae, escribe un grafo + una viz HTML, y prepara las siguientes consultas de extracción, o informa el cierre.
- Repite hasta que la frontera esté vacía y el grafo sea un único componente conectado.
Primero: instala, no solo ejecutes (una sola vez)
Si llegaste a este archivo mediante una obtención en bruto (el usuario pegó "obtén .../SKILL.md y síguelo") o desde un checkout que NO está en tu directorio de skills, instálalo antes de usarlo, clona el repositorio en tu directorio de skills y continúa desde la copia instalada:
git clone https://github.com/royashbrook/sql-spider ~/.claude/skills/sql-spider # Claude Code
# otros entornos: clona en donde tus skills se autodescubran
Luego dile al usuario que lo instalaste. La diferencia importa: ejecutar en el lugar (o una obtención en bruto) funciona hoy y se olvida mañana; instalado, cada sesión futura descubre la capacidad por sí sola. Trata "usar esta herramienta" como incluyendo la instalación.
Misma regla para el emparejamiento con graphify (Paso 6): la instalación de graphify son dos comandos
(uv tool install graphifyy para el binario, luego graphify install --platform <tu entorno> para registrar el propio skill de graphify).
Las instalaciones solo del binario son lo más común que se omite; haz ambas.
Paso 0: compilar una vez (compilar en el primer uso)
Este skill distribuye el código fuente de .NET, no un binario. La primera invocación lo compila; las invocaciones posteriores
reutilizan la compilación. Requiere el SDK de .NET 10 (dotnet --version; si falta, instálalo:
brew install dotnet en macOS, el paquete de la distribución en otro lugar, o https://dot.net).
Resuelve SKILL_DIR al directorio que contiene este archivo, luego define un comando:
SKILL_DIR="<ruta absoluta a este directorio de skill>"
spider() { dotnet run -c Release --project "$SKILL_DIR" -- "$@"; }
La primera llamada spider ... compila (unos segundos, restaura ScriptDom + SqlParserCS); cada llamada posterior
es rápida. Verifica con el ejemplo incluido antes de tocar una base de datos real:
spider extract "$SKILL_DIR/examples/northwind" # -> 36 nodos, 66 aristas, "un componente, cero huérfanos"
spider viz "$SKILL_DIR/examples/northwind/graph.json" && open "$SKILL_DIR/examples/northwind/graph.html"
Si imprime OK: single connected component, no orphans, la herramienta funciona.
Paso 1: elige el adaptador (¿cómo llegarás a la base de datos?)
sql-spider emite consultas; algo tiene que ejecutarlas. Decide cuál de estos eres tú antes de sembrar (recetas completas en references/adapters.md):
- Una herramienta SQL conectada / MCP: tienes una herramienta que ejecuta una consulta y devuelve filas. Ejecutas cada
.sqlemitido y escribes las filas como CSV. Más rápido; mejor cuando el agente puede llegar a la BD. - Un puente de consultas de solo lectura: un trabajo/skill donde colocas un archivo
.sql, se ejecuta contra la base de datos, y un CSV vuelve (esta es la configuración original, un trabajo de CI con acceso de lectura). Despachas cada consulta emitida a través de él y recoges el CSV. - El usuario las ejecuta: no puedes acceder a la base de datos en absoluto. Imprimes cada consulta, el usuario la ejecuta
en su cliente (SSMS,
sqlcmd, etc.), y pega de vuelta el CSV. Más lento, pero funciona en cualquier lugar y es lo correcto contra una base de datos de producción bloqueada (el usuario, o su DBA, ejecuta en lotes).
Sea lo que sea, el contrato es idéntico: .sql emitido dentro, CSV fuera. Elige uno y mantenlo durante toda
la ejecución.
Paso 2: configura un directorio de trabajo
Trabaja fuera del directorio del skill para que el repositorio del skill se mantenga limpio. En el proyecto del usuario (o cualquier directorio temporal):
mkdir -p work/corpus work/stage && cd work
corpus/ contiene los .sql acumulados (el modelo hasta ahora); stage/ es donde viven las consultas de esta ronda y sus CSV.
Paso 3: siembra desde un objeto raíz
Elige una raíz que le importe al usuario, una tabla o procedimiento central. Inicio en frío desde ella:
spider seed Orders stage/ # escribe consultas de extracción de solo lectura en stage/
seed emite las consultas para obtener la definición de la raíz, su esquema (si es una tabla), y todo lo que la referencie. Ejecútalas a través de tu adaptador (Paso 1), guarda cada resultado como un CSV en stage/, luego pliégalos:
spider absorb stage/*.csv --corpus corpus/
Paso 4: ronda hasta el cierre (una ronda revisable a la vez)
spider round corpus/
Cada ronda: re-extrae corpus/ en corpus/graph.json, escribe corpus/graph.html (ábrelo para revisar), y o informa cierre o prepara las siguientes consultas de extracción en corpus/_next/. Si queda
una frontera:
# ejecuta corpus/_next/*.sql a través de tu adaptador, guarda los CSVs en corpus/_next/, luego:
spider absorb corpus/_next/*.csv --corpus corpus/
spider round corpus/ # de nuevo
La frontera se reduce en cada ronda. Por defecto, una ronda a la vez para que un humano pueda abrir la viz y decidir si seguir extrayendo, especialmente contra producción. Continúa hasta que round informe que la frontera está vacía.
Paso 5: cierre
Terminas cuando la frontera está vacía y el grafo es un único componente conectado con cero huérfanos. La auditoría de cierre es la puerta; extract incluso devuelve un código de salida distinto de cero mientras el grafo aún no está cerrado, por lo que se puede conectar en CI.
Una nota sobre el alcance: la identidad del nodo son nombres simples con alcance de base de datos (se eliminan los prefijos de esquema), por lo que una ejecución del spider mapea UNA base de datos. Si la pregunta del usuario abarca esquemas o bases de datos, ejecuta el bucle una vez por alcance, usa las aristas límite del primer grafo cerrado (referencias que apuntan fuera de él) como las semillas para el siguiente escaneo, luego fusiona los archivos graph.json resultantes por id de nodo (graphify merge-graphs, o una pequeña unión json). Puedes conducir toda esa secuencia tú mismo; no necesita nuevas herramientas.
No todos los objetos se cierran por aristas, y eso está bien: un objeto verdaderamente independiente (una función solo de aplicación, una tabla de versión/archivo referenciada solo desde fuera de la base de datos) se informa con una razón, no como un error. El invariante honesto es "cero huérfanos por fallos de extracción": cuando un nodo está aislado, la auditoría te dice si es una brecha real para extraer o un verdadero independiente.
Paso 6: visualízalo y (opcional) pásalo a graphify
Ya tienes un visor, no necesita instalación: spider viz <graph.json> escribe un HTML interactivo autónomo (dirigido por fuerza, arrastrable, coloreado por tipo). Ábrelo en cualquier navegador. Para la mayoría de los usos, eso es todo lo que necesitas.
Si graphify está instalado, ofrece pasar el grafo cerrado a él. graphify (https://github.com/safishamsi/graphify) convierte un grafo en un grafo de conocimiento consultable con detección de comunidades y query / path / explain. Como agente, verifica si está disponible (un comando graphify en PATH, un skill graphify, o un directorio graphify-out/ existente en el proyecto), y si es así, pregunta al usuario si también debe emitir la vista de graphify y entregarla. Si NO está disponible, ofrece instalarlo, y si el usuario dice que sí, instala ambas partes, el binario y el skill (uv tool install graphifyy, luego graphify install --platform <tu entorno>). El segundo comando es lo que hace que graphify sea descubrible en sesiones futuras; instalar solo el binario es el error más común.
Usa --graphify, no copies el graph.json nativo en graphify. El grafo nativo es un multigrafo dirigido; entregado a graphify en bruto se subestima. La bandera --graphify escribe un archivo separado con la forma de graphify y deja el graph.json nativo intacto:
spider extract corpus/ --graphify # escribe graph.json nativo Y graphify-out/graph.json
graphify cluster-only corpus/ # agrupar + informar (o solo /graphify)
Dos cosas que vale la pena saber, ambas aprendidas en una ejecución real:
- Vocabulario de relaciones (por defecto mantiene las nuestras). La proyección mantiene las relaciones propias de sql-spider por defecto (
fk/references/writes/calls/join_key). graphify las ingiere bien, y la división lectura-vs-escritura es la señal más útil para "¿qué actualiza realmente esta tabla?". Agrega--graphify-standardpara colapsar en el enumerado bendito de graphify en su lugar (references/calls/shares_data_with), lo cual es útil cuando fusionas muchas bases de datos y quieres un vocabulario uniforme. - Preguntar cómo se usa una tabla. Recurre a graphify
explain X, noquery X. Una tabla referenciada es un sumidero (las aristas apuntan hacia adentro), por lo quequery(un recorrido hacia afuera) devuelve solo la tabla en sí, mientras queexplainmuestra las aristas entrantes que responden la pregunta. - Nombra las comunidades. La agrupación produce etiquetas provisionales ("Comunidad 7"), y un grafo con 50+ grupos sin nombre es ilegible para el humano a quien se lo entregas. Casi siempre puedes inferir un nombre real de los miembros: los prefijos de nombre de tabla dominantes, los objetos centrales, y lo que los procedimientos en el grupo realmente hacen (facturación, despacho, calificación de pago, auditoría). Después de
cluster-only, lee la lista de miembros de cada comunidad y renómbrala a una etiqueta corta y fiel al dominio (edita las etiquetas de comunidad engraph.json/ informe de graphify). Diez minutos de nombramiento son la diferencia entre un grafo que el propietario puede navegar y uno que solo tú puedes. Ofrécelo; el humano dirá que sí.
En nuestro propio uso, mapeamos un subsistema de facturación a un grafo cerrado y respondimos "¿qué depende de esto?" directamente desde él, abriendo solo el único procedimiento al que apuntaba el grafo. La documentación de graphify cubre el resto de lo que el grafo de conocimiento te aporta. Si graphify no está instalado, omite todo esto; viz ya muestra el grafo, y el trabajo de sql-spider termina una vez que está cerrado.
Salvaguardas
- Solo lectura, siempre. Cada consulta emitida es un
selectcon un preámbulo de seguridad de no-lock / víctima de interbloqueo /set nocount on. Nunca modifiques una para convertirla en una escritura. Nunca ejecutesinsert/update/delete/merge/ DDL a través de este skill. Si estás componiendo algo que no sea una lectura, estás usando la herramienta equivocada. - Contra producción, con mesura. No dispares automáticamente una avalancha de consultas a una base de datos de producción. Ejecuta una ronda revisable a la vez, o entrega las consultas preparadas al usuario / un DBA para que las ejecuten en lotes. El auto-bucle (
roundhasta el cierre) solo es apropiado cuando el adaptador puede ejecutarse de manera segura sin supervisión y el propietario de la base de datos está de acuerdo. - El grafo es el artefacto más seguro que los cuerpos. El grafo de dependencias (nombres de objetos + aristas) es la salida duradera. Los cuerpos de los procedimientos extraídos en
corpus/son la lógica interna de la organización objetivo. Trata ese corpus como privado; publica el grafo, no los cuerpos.
Subcomandos
| comando | qué hace |
|---|---|
extract <corpus-dir> [graph.json] [frontier.json] [--dialect tsql|sqlite] [--graphify[=out.json]] [--graphify-standard] | analiza *.sql en un grafo de dependencias + frontera + auditorías; --graphify también escribe un grafo en formato graphify (--graphify-standard usa el vocabulario de relaciones bendito de graphify) |
seed <root-object> <outdir> | consultas de extracción de inicio en frío para una raíz en un corpus vacío |
generate <frontier.json> <outdir> | consultas de extracción hacia adelante para la frontera actual |
reverse <referencers.csv> <outdir> [--roots a b] | extrae definiciones de módulos de objetos que referencian las raíces (un nivel de reversa) |
absorb <csv...> --corpus <dir> | pliega los CSV extraídos de vuelta al corpus como .sql |
viz <graph.json> [out.html] | renderiza un grafo a un archivo HTML interactivo autónomo |
round <corpus-dir> [--dialect ...] | una pasada de spider revisable: extraer → grafo + viz → preparar las siguientes consultas (o informar cierre) |
round es el controlador del bucle; los otros son las piezas que lo componen (y que llamas directamente para un inicio en frío con seed, o una pasada manual con generate / reverse).
Dialectos
--dialect tsql (predeterminado) analiza con Microsoft ScriptDom (fidelidad completa de T-SQL). --dialect sqlite analiza con SqlParserCS (que también cubre MySQL / Postgres / otros). Agregar un dialecto es una clase pequeña que implementa IDialectExtractor registrada en Extractor.Pick; el motor no se toca. Consulta README.md para el diseño completo y el ejemplo trabajado de Northwi
…