# Antes de que el modelo adivine: Galadriel y el contexto que necesitan los agentes de IA

**Un índice local que ayuda a Cursor, GitHub Copilot y otros agentes a entender cómo está conectado un proyecto antes de modificarlo.**

Cuando trabajamos con herramientas como Cursor o GitHub Copilot, solemos hacer preguntas como estas:

- ¿Dónde está implementada esta funcionalidad?
- ¿Qué clases dependen de este componente?
- Si modifico este contrato, ¿qué otros archivos podrían verse afectados?
- ¿Existe alguna dependencia circular?
- ¿Hay archivos que aparentemente no utiliza nadie?

Los modelos de IA pueden ayudarnos a responder estas preguntas. El problema es que no siempre tienen suficiente contexto sobre nuestro repositorio. Pueden encontrar archivos, interpretar fragmentos de código y proponer cambios, pero también pueden asumir relaciones que no existen, pasar por alto dependencias o sugerir modificaciones sin conocer todas sus consecuencias.

Y cuando eso ocurre, el problema no es necesariamente el modelo. Muchas veces, simplemente no tiene suficiente información sobre el proyecto.

**Antes de pedirle a un agente que modifique nuestro código, deberíamos darle una forma de entender cómo está construido.**

Esa es la idea detrás de **Galadriel**.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/6bb48180-ffed-4e7e-b0c0-b86d8a097dcf.png align="center")

## ¿Qué es Galadriel?

Galadriel es una herramienta de inteligencia estructural de código (*Local Code Intelligence*) que analiza un repositorio, construye un índice local y permite consultar las relaciones entre sus archivos.

Su objetivo es sencillo: proporcionar información verificable sobre la estructura de un proyecto para que los agentes de programación puedan trabajar con mayor contexto.

Galadriel no escribe código, no ejecuta modelos de lenguaje y tampoco necesita enviar nuestro repositorio a un servicio externo.

Construye un índice en nuestra propia máquina, dentro de `.galadriel/espejo.db`, y expone esa información mediante una interfaz que pueden consumir herramientas como Cursor y GitHub Copilot.

En lugar de pedirle al modelo que intente descubrir por sí solo cómo está organizado todo el proyecto, podemos darle acceso a información estructural previamente analizada.

Hay tres preguntas que resumen buena parte de lo que ofrece:

| Pregunta | Comando | Para qué sirve |
| --- | --- | --- |
| ¿Dónde está? | `galadriel search` | Buscar información en el repositorio. |
| ¿Qué relación tiene? | `galadriel relate` | Consultar las relaciones de un archivo. |
| ¿Qué podría verse afectado? | `galadriel impact` | Explorar dependencias e impacto de un cambio. |

Además, permite visualizar grafos, detectar ciclos, revisar posibles archivos sin referencias y consultar estadísticas del índice.

La diferencia importante es que Galadriel no pretende reemplazar el razonamiento del modelo. Le proporciona información sobre la cual puede razonar.

## Un índice, no otro modelo de IA

Es importante entender qué hace Galadriel y qué no hace.

No es un LLM. No utiliza embeddings ni necesita una base de datos vectorial para recuperar información. Tampoco intenta reemplazar las capacidades de los servidores de lenguaje de cada tecnología.

Su funcionamiento se puede entender en cuatro pasos:

1. **Analiza el repositorio.** Recorre los archivos que reconoce y extrae información relevante.
2. **Construye un índice.** Guarda fragmentos y relaciones en una base de datos SQLite local.
3. **Expone consultas.** Permite buscar archivos, consultar relaciones, explorar dependencias y analizar impactos.
4. **Entrega contexto al agente.** Mediante MCP, Cursor o GitHub Copilot pueden consultar esa información durante una conversación.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/e86a6b51-8e39-49b1-9f50-489daae9a1fd.png align="center")

El modelo sigue siendo responsable de interpretar la solicitud, razonar y proponer una solución. Galadriel aporta información estructural para reducir las suposiciones.

Por ejemplo, si le pedimos a un agente que modifique `Student.java`, puede consultar primero qué archivos están relacionados con esa clase y cuáles podrían verse afectados.

Así, la conversación deja de depender exclusivamente de lo que el modelo consiga inferir leyendo archivos individualmente.

## Cuatro proyectos reales, cuatro escenarios diferentes

Para probar Galadriel 1.0.0 utilicé cuatro repositorios de tecnologías y estructuras distintas.

Los siguientes resultados corresponden a índices generados localmente el 1 de noviembre de 2026.

| Proyecto | Archivos | Fragmentos | Relaciones |
| --- | --: | --: | --: |
| Ejemplos de módulos Java 25 | 70 | 79 | 43 |
| Destaka Android (Kotlin) | 93 | 374 | 295 |
| Microservicios Order/Product (.NET) | 95 | 511 | 131 |
| API de estudiantes (Quarkus) | 16 | 77 | 7 |

No se trata de ejemplos inventados para producir grafos atractivos. Son repositorios reales que permiten observar cómo Galadriel interpreta diferentes estructuras y relaciones.

Veamos algunos casos.

## 1\. Java 25: entender módulos y detectar ciclos

El primer escenario utiliza un proyecto con módulos de Java.

En este repositorio tenemos varios módulos relacionados con un servicio de pagos. Por ejemplo, los módulos de tarjeta, Yape y tienda dependen de una API común: `com.joedayz.pagos.api`.

Galadriel puede identificar estas relaciones y agruparlas mediante:

```bash
galadriel scan
galadriel graph --modules
```

El resultado permite visualizar las dependencias entre módulos, en lugar de limitarse a mostrar imports individuales.

También preparé un escenario didáctico con dos módulos que se requieren mutuamente:

```java
module com.joedayz.a {
    requires com.joedayz.b;
}
```

Y en el otro módulo:

```java
module com.joedayz.b {
    requires com.joedayz.a;
}
```

Esto genera una dependencia circular.

Podemos detectarla con:

```bash
galadriel cycles
```

El resultado identifica el ciclo:

```text
com.joedayz.a → com.joedayz.b → com.joedayz.a
```

También podemos consultar el impacto de modificar una clase compartida como `MedioPago.java`:

```bash
galadriel impact \
  04-servicios/src/com.joedayz.pagos.api/com/joedayz/pagos/api/MedioPago.java
```

Esto permite explorar qué archivos están relacionados con esa modificación.

Un detalle interesante es que Galadriel también contempla el análisis incremental. Si un archivo cambia o se mueve, el índice puede actualizar sus relaciones sin necesidad de reconstruir todo desde cero.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/82f420ab-d72b-4591-b6b5-191be854cbd4.png align="center")

```plaintext
cd ejemplos-modulos
galadriel scan
galadriel graph --modules
galadriel cycles
galadriel impact 04-servicios/src/com.joedayz.pagos.api/com/joedayz/pagos/api/MedioPago.java
```

## 2\. Kotlin: entender la estructura de una aplicación Android

El segundo escenario es Destaka Android, una aplicación desarrollada con Kotlin y Jetpack Compose.

Aquí no tenemos módulos Java definidos mediante `module-info.java`. La organización del proyecto gira alrededor de una Activity, componentes de interfaz, ViewModels, modelos y rutas.

Por eso, en este caso, el grafo de archivos resulta mucho más útil que el grafo de módulos.

Podemos consultar las relaciones de `MainActivity` y `DestakaApp`:

```bash
galadriel scan

galadriel relate \
  app/src/main/java/pe/joedayz/destaka/MainActivity.kt
```

Una de las cosas que podemos observar es cómo `MainActivity` utiliza `DestakaApp` y el tema visual de la aplicación.

A su vez, `DestakaApp` se relaciona con diferentes pantallas, sus ViewModels y otros componentes de la aplicación.

Esto permite entender mejor cómo se distribuye la responsabilidad entre los archivos.

También podemos consultar qué ocurriría si modificamos el tema visual:

```bash
galadriel impact \
  app/src/main/java/pe/joedayz/destaka/ui/theme/DestakaTheme.kt \
  --depth 2
```

El resultado permite explorar el impacto a más de un nivel de profundidad.

En este repositorio también se identificó un ciclo entre `AppResult.kt` y `AppError.kt`.

Y algo interesante: la consulta `unused` no encontró código huérfano en este escenario.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/42b38482-3022-426c-8ab4-90b5ef398179.png align="center")

```plaintext
cd destaka-android
galadriel scan
galadriel relate app/src/main/java/pe/joedayz/destaka/ui/theme/DestakaTheme.kt
galadriel impact app/src/main/java/pe/joedayz/destaka/ui/theme/DestakaTheme.kt --depth 2
galadriel unused
```

## 3\. .NET: seguir una dependencia entre microservicios a través de un contrato

El tercer escenario utiliza dos servicios desarrollados en C#: `OrderService` y `ProductService`.

Ambos se comunican mediante gRPC y comparten un contrato definido en un archivo Protocol Buffers:

`product.proto`

Este archivo declara, entre otras cosas:

```protobuf
option csharp_namespace = "ProductService.Grpc";

service ProductGrpc {
    // ...
}
```

El cliente de OrderService utiliza el cliente gRPC generado a partir de ese contrato.

Lo interesante es que Galadriel puede identificar la relación entre los proyectos a través del archivo `.proto`, sin depender de las clases C# generadas durante la compilación.

Al ejecutar:

```bash
galadriel scan
galadriel graph --modules
```

Podemos observar una relación entre ambos proyectos:

```text
OrderService ==> |2| ProductService
```

El peso representa las dos relaciones identificadas entre archivos de OrderService y el contrato de ProductService.

Ahora imaginemos que necesitamos modificar `product.proto`.

Podemos consultar el impacto:

```bash
galadriel impact \
  src/Services/ProductService/Protos/product.proto \
  --depth 2
```

La consulta permite encontrar los archivos relacionados con el contrato, incluyendo el cliente gRPC y los puntos de configuración de ambos servicios.

Esto resulta especialmente útil cuando trabajamos con arquitecturas distribuidas: un cambio puede comenzar en un contrato y terminar afectando componentes que viven en otro proyecto.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/c6644574-5b5f-46b0-8da7-0beaaaa26ef8.png align="center")

```plaintext
cd microservices-net-2026
galadriel scan
galadriel graph --modules
galadriel relate src/Services/OrderService/Clients/GrpcProductServiceClient.cs
galadriel impact src/Services/ProductService/Protos/product.proto --depth 2
```

## 4\. Quarkus: relaciones que no siempre aparecen en los imports

El último escenario utiliza una API de estudiantes desarrollada con Quarkus.

Es un proyecto pequeño, pero permite mostrar una característica interesante.

Tenemos dos clases dentro del mismo paquete:

- `Student.java`
- `Grade.java`

La clase `Student` contiene una colección de notas:

```java
List<Grade> grades;
```

Y `Grade` mantiene una referencia al estudiante:

```java
Student student;
```

No necesitamos que una clase importe explícitamente a la otra para que exista una relación entre ellas. Ambas están en el mismo paquete y se referencian mediante sus tipos.

Galadriel puede reconocer esta relación y representarla en el grafo.

Podemos consultar:

```bash
galadriel scan
galadriel graph
```

También podemos buscar información sobre estudiantes y notas:

```bash
galadriel search "estudiante nota"
```

Y consultar qué archivos podrían verse afectados al modificar `Student.java`:

```bash
galadriel impact \
  src/main/java/edu/utp/quarkus/student/Student.java
```

En este caso, el resultado identifica relaciones con `Grade`, `GradeResource` y `StudentResource`.

Es un ejemplo pequeño, pero ilustra algo importante: conocer las dependencias de un proyecto no siempre consiste en buscar instrucciones `import`. También hay relaciones que se pueden inferir a partir de los tipos y de la estructura del código.

![](https://cdn.hashnode.com/uploads/covers/64a79aba336591d2a1481aae/9db08fcd-4bbb-41f0-a48b-6892763c94ac.png align="center")

## Galadriel y los agentes de programación

Hasta aquí hemos visto cómo consultar Galadriel desde la terminal.

Pero su verdadero potencial aparece cuando lo conectamos con un agente de programación.

Para ello utiliza **MCP (Model Context Protocol)**.

MCP permite que aplicaciones como Cursor y GitHub Copilot accedan a herramientas externas. En este caso, Galadriel expone consultas sobre el repositorio para que el agente pueda utilizarlas durante una conversación.

### Integración con Cursor

En Cursor podemos registrar Galadriel mediante el archivo `.cursor/mcp.json`.

Una configuración básica sería:

```json
{
  "mcpServers": {
    "galadriel": {
      "command": "node",
      "args": [
        "/ruta/a/galadriel/dist/cli.js",
        "serve",
        "--workspace",
        "/ruta/al/repositorio"
      ]
    }
  }
}
```

Una vez configurado, Cursor podrá acceder a las herramientas expuestas por Galadriel:

- `search`
- `relate`
- `impact`
- `graph`
- `cycles`
- `unused`
- `advisories`
- `stats`

### Integración con GitHub Copilot

También podemos utilizarlo desde GitHub Copilot Chat en Visual Studio Code.

En este caso, la configuración del editor se realiza mediante `.vscode/mcp.json`:

```json
{
  "servers": {
    "galadriel": {
      "type": "stdio",
      "command": "node",
      "args": [
        "/ruta/a/galadriel/dist/cli.js",
        "serve",
        "--workspace",
        "/ruta/al/repositorio"
      ]
    }
  }
}
```

Después de guardar la configuración, podemos iniciar el servidor MCP y utilizar Copilot en modo Agent.

### Un ejemplo de uso antes de un refactor

Imaginemos que necesitamos modificar `Student.java`.

En lugar de pedirle directamente al agente que implemente el cambio, podemos comenzar con una instrucción como esta:

> Antes de editar Student.java, utiliza las herramientas impact y relate de Galadriel. No modifiques ningún archivo todavía. Identifica qué archivos están relacionados y cuáles podrían verse afectados por el cambio. Explícame los resultados antes de continuar.

El agente puede consultar el índice y utilizar esa información como parte de su análisis.

Si Galadriel identifica relaciones con `Grade`, `GradeResource` y `StudentResource`, el agente dispone de una referencia concreta para evaluar el cambio.

Esto no garantiza que el modelo tome siempre la decisión correcta, pero sí le proporciona información adicional para evitar algunas de las suposiciones habituales.

La idea es sencilla:

**El modelo razona. Galadriel aporta evidencia sobre la estructura del proyecto.**

## ¿Y qué pasa con LSP?

Galadriel también incorpora un servidor LSP (*Language Server Protocol*) que permite consultar relaciones a nivel de archivo.

Por ejemplo, podemos consultar qué archivos importa uno determinado y qué archivos lo referencian.

Sin embargo, es importante entender su alcance: el análisis de Galadriel trabaja a nivel de archivo, no llega al nivel de métodos o símbolos como lo hacen los servidores de lenguaje especializados.

Por eso, no pretende reemplazar el servidor de Java, Kotlin o C# que utilizamos habitualmente en nuestro IDE.

Ambos pueden complementarse.

Un servidor de lenguaje aporta información detallada sobre el código de una tecnología. Galadriel aporta una vista estructural del repositorio que también puede incluir otros elementos, como archivos `.proto` o enlaces relativos en documentación Markdown.

## Lo que Galadriel no pretende hacer

Prefiero dejar claros algunos límites de la herramienta.

Galadriel no es un asistente de programación autónomo. Tampoco es una solución que entienda cualquier lenguaje con el mismo nivel de profundidad.

Algunas consideraciones de la versión 1.0.0:

- No ejecuta modelos de lenguaje ni calcula embeddings.
- No envía información del repositorio a Internet.
- Los avisos de dependencias utilizan un catálogo local definido por el usuario; no consultan bases de vulnerabilidades en línea ni generan CVE por su cuenta.
- Go, Python, Ruby, Rust, PHP, SQL y shell pueden indexarse para búsquedas, pero no generan relaciones de import en esta versión.
- No indexa documentos PDF ni videos.
- La consulta `unused` debe interpretarse con criterio. Puede señalar scripts, migraciones u otros archivos que no tienen referencias directas, pero que siguen siendo necesarios para el proyecto.

El índice se almacena localmente en `.galadriel/`. Por esa razón, conviene agregar esa carpeta al `.gitignore` del repositorio.

La intención es mantener el análisis en nuestra máquina y no introducir información adicional en el control de versiones.

## ¿Cómo probar Galadriel?

Galadriel 1.0.0 requiere Node.js 22 o superior.

El proyecto utiliza TypeScript y SQLite con FTS5, mediante `better-sqlite3`.

Puedes obtener el código desde GitHub:

<https://github.com/joedayz/galadriel>

Para instalar la versión 1.0.0 desde el repositorio:

```bash
git clone https://github.com/joedayz/galadriel.git

cd galadriel

git checkout v1.0.0

npm install

npm run build

npm link
```

Después, desde el repositorio que quieras analizar:

```bash
galadriel scan
```

Y puedes comenzar explorando:

```bash
galadriel search "nombre de una funcionalidad"

galadriel graph

galadriel cycles

galadriel stats
```

El repositorio incluye más información sobre los comandos y las opciones disponibles.

## Una idea para trabajar mejor con IA

Estamos entrando en una etapa en la que los agentes de programación pueden leer, modificar, probar y hasta desplegar software.

Pero darles más autonomía no significa necesariamente darles más contexto.

Un agente puede generar código en segundos y, aun así, no entender completamente las consecuencias de modificar una clase, un contrato o una dependencia compartida.

Creo que una parte importante de la ingeniería de software en esta nueva etapa consiste precisamente en construir mecanismos que ayuden a los agentes a conocer el entorno en el que trabajan.

Galadriel nace de esa idea.

No busca reemplazar al desarrollador, al arquitecto ni al modelo de IA. Busca aportar una pieza que considero necesaria: **una representación consultable y verificable de cómo está conectado nuestro código.**

Porque antes de modificar un sistema, deberíamos entenderlo.

Y antes de dejar que un agente tome decisiones sobre nuestro código, deberíamos darle contexto suficiente para hacerlo.

---

**Galadriel 1.0.0**

Código fuente: <https://github.com/joedayz/galadriel>

Licencia: Apache 2.0

*Enjoy!*

*Joe*
