Skip to main content
Glama

ContextForge

Pipeline determinista que convierte cualquier repo en un índice consultable por agentes IA. 94.4 % menos tokens por sesión, 17.9× compresión, ÷28× costo SDD con prompt caching — sin LLM en el pipeline, sin lock-in de agente.

214 600 tokens (todo el repo)  →  11 988 tokens (lo que importa a la tarea)

tests savings npm docker


El problema que resuelve

Cada vez que un agente IA (Claude Code, Cursor, OpenCode) abría el repo tenía que:

  1. Leer TODO para entender qué existe

  2. Recordar correr pnpm forge context manualmente antes de cada tarea

  3. Adivinar qué archivos tocar sin contexto del grafo

  4. No había gate pre-commit — specs y guardrails se saltaban fácil

Ahora todo eso es automático vía MCP + hooks.


Cómo encaja cada pieza

Dev / Agente (Claude Code · Cursor · OpenCode) escribe tarea
        │
        ▼
[Hook UserPromptSubmit]  ← automático, sin hacer nada
  → MCP: select_agent_context(task)
  → Agente recibe: skills relevantes + domains tocados
        │
        ▼
Agente llama forge_context(task)  ← MCP tool, sin pnpm, sin disco
  → ~20 archivos rankeados por PageRank + BFS
  → sabe exactamente qué leer, no el repo entero
        │
        ▼
Agente llama forge_spec("mi-feature")  ← MCP tool
  → escribe openspec/changes/mi-feature/
      ├── proposal.md        ← motivación y alcance
      ├── design.md          ← decisiones técnicas
      ├── tasks.md           ← lista de tareas
      ├── specs/             ← Requirements + Scenarios (Given/When/Then)
      ├── graph.subset.json  ← subgrafo FROZEN de los archivos relevantes
      ├── context.md         ← mapa de lectura para el agente
      └── agent-manifest.json ← skills filtradas SOLO para este change
        │
        ▼
Agente/Dev llena proposal.md + specs/*.md
  openspec validate mi-feature  ← verifica formato Requirement + Scenario
        │
        ▼
Agente llama forge_implement("mi-feature")  ← MCP tool
  → .contextforge/implement-plan.json
      allowedFiles: [solo los del context-pack]
      maxLocDelta: estimado del pack
        │
        ▼
Agente implementa código
        │
        ▼
Agente intenta  git commit
        │
        ▼
[Hook PreToolUse]  ← automático, bloquea si hay violaciones
  → node .claude/hooks/forge-pre-commit.mjs
  → forge implement --check valida git diff vs guardrails
  → archivo fuera de allowedFiles → exit 2 → COMMIT BLOQUEADO
  → Agente recibe lista de violaciones y corrige antes de reintentar
        │
        ▼
Commit pasa → merge
        │
        ▼
Agente corre  openspec archive mi-feature
        │
        ▼
[Hook PostToolUse(openspec)]  ← automático, en background
  → forge_rebuild_graph async
  → grafo fresco para la próxima tarea

ContextForge no reemplaza OpenSpec — lo alimenta

OpenSpec es el framework de specs. Claude Code / Cursor / OpenCode son los agentes IA que lo usan. ContextForge le da a los agentes el contexto correcto para que OpenSpec reciba datos reales del código, no inventados.

OpenSpec hace

ContextForge aporta

Valida formato Requirement: + Scenario:

El contexto correcto para escribir la spec

Archiva y mueve specs a openspec/specs/

El subgrafo frozen que dice qué archivos aplican

openspec validate chequea Given/When/Then

forge_check chequea que el código respete los guardrails

Historial de specs por feature

forge_status muestra qué changes tienen subgrafo activo


Antes vs ahora

Sin hooks ni MCP — el dev recordaba (o no) cada paso:

pnpm forge scan
pnpm forge graph
pnpm forge context "mi tarea"
pnpm forge spec mi-feature
# llenar docs...
pnpm forge implement mi-feature
# codear...
pnpm forge implement --check  # se olvidaba frecuentemente
git commit
openspec archive mi-feature
pnpm forge scan && pnpm forge graph  # se olvidaba siempre

Ahora — los hooks y MCP tools hacen el trabajo:

# Agente recibe contexto automático al escribir el prompt (hook)
# Llama forge_context → forge_spec → forge_implement via MCP (sin pnpm)
# Dev/agente llena las specs → openspec validate confirma formato
# Agente codea
git commit              # → hook bloquea si hay violaciones, las explica
openspec archive mi-feature  # → hook reconstruye grafo en background

pnpm forge manual solo para bootstrap (forge init) o forzar reconstrucción (forge graph --force).


Instalación

npm — público, sin token:

# CLI (uso diario)
pnpm add -g @anai-raia-alex/contextforge-cli         # global
# o
pnpm add -D @anai-raia-alex/contextforge-cli         # por proyecto

# MCP server (para agentes vía Node)
pnpm add -D @anai-raia-alex/contextforge-mcp

# OpenSpec CLI (recomendado, activa el modo handoff)
npm i -g @fission-ai/openspec

Docker — sin instalar Node, multi-arch (amd64+arm64):

docker pull ghcr.io/alejandro-cedeno-10/contextforge-mcp:latest

Desde fuente (desarrollo):

git clone https://github.com/alejandro-cedeno-10/contextforge-cli.git
cd contextforge-cli
pnpm install && pnpm build

Quick start (5 comandos para empezar)

# 1. Inicializar (corre 'openspec init' si está en PATH; instala instrucciones del agente)
pnpm forge init

# 2. Indexar el repo (incremental; cache por hash)
pnpm forge scan
pnpm forge graph

# 3. Por cada tarea
pnpm forge context "fix race en tokenLedger writer"

# 4. SDD opcional (con OpenSpec)
pnpm forge spec mi-feature-id    # spec-input + handoff/fallback
openspec validate mi-feature-id

# 5. Implementar con guardrails
pnpm forge implement mi-feature-id
# (trabajas con el agente)
pnpm forge implement --check     # gate pre-commit

Las tres capas

Capa 1 — Grafos para ahorrar tokens

En lugar de "leer todo el repo", rankeamos los archivos por relevancia a tu tarea con el grafo de dependencias real del código + Personalized PageRank.

Pipeline:

pnpm forge scan       # Indexa con BLAKE3 (incremental)
pnpm forge graph      # Grafo file + symbol con tree-sitter
pnpm forge context "<tarea>"   # PageRank + BFS + budget

Algoritmo:

1. resolve_seeds(task)        → archivos semilla por keywords
2. personalized_pagerank()    → ranking de relevancia (alpha=0.85, 50 iter)
3. bfs_expand(depth=2)        → captura deps directas + transitivas
4. score_nodes()              → pagerank × (1/bfs_dist) × edge_multiplier
5. greedy_pack(budget=12000)  → llena hasta 12k tokens (full → excerpt → summary)

Edge multipliers: tests=1.2 · defines=1.0 · calls=1.0 · imports=0.8 · references=0.6

Ahorro medido en este repo:

Sin ContextForge

Con context-pack

214 600 tokens

11 988 tokens

~$0.64 / sesión (Claude Sonnet 4.6)

~$0.036 / sesión

128 archivos enviados

50 archivos seleccionados

Compresión: 17.9× · Ahorro: 94.4 %

Capa 2 — SDD apoyando a OpenSpec (no compitiendo con él)

v0.3.0+ — forge spec ya no genera el spec final. Genera la entrada (spec-input.json + spec-prompt.md) para que OpenSpec o un agente IA lo escriban con todo el contexto correcto.

Tres roles separados, cada uno hace lo suyo:

       ┌─────────────────────┐    ┌─────────────────────┐    ┌────────────────┐
       │   ContextForge      │    │     OpenSpec        │    │   Agente IA    │
       ├─────────────────────┤    ├─────────────────────┤    ├────────────────┤
ROL    │  Selección de       │    │  Estructura +       │    │  Redacción     │
       │  contexto           │    │  validación         │    │                │
       ├─────────────────────┤    ├─────────────────────┤    ├────────────────┤
TÉC.   │  PageRank + BFS +   │    │  Schemas RFC 2119   │    │  LLM           │
       │  budget tokens      │    │  Given/When/Then    │    │                │
       ├─────────────────────┤    ├─────────────────────┤    ├────────────────┤
INPUT  │  scan + graph +     │    │  spec-input.json    │    │  spec-prompt.md│
       │  task               │    │                     │    │  + context-pack│
       ├─────────────────────┤    ├─────────────────────┤    ├────────────────┤
OUTPUT │  context-pack +     │    │  proposal/design/   │    │  .md llenos    │
       │  spec-input + prompt│    │  tasks/spec.md      │    │  + commits     │
       └─────────────────────┘    └─────────────────────┘    └────────────────┘

Pipeline SDD completo:

pnpm forge context "<tarea>"          # context-pack + agent-manifest
pnpm forge spec mi-feature-id         # spec-input + handoff/fallback
openspec list                          # ver changes activos
openspec validate mi-feature-id        # validación oficial
pnpm forge implement mi-feature-id     # plan con guardrails
# (trabajas con el agente)
pnpm forge implement --check           # gate pre-commit
openspec archive mi-feature-id -y      # al mergear: mueve a specs/

Modo handoff vs modo fallback:

Modo

Cuándo

Qué pasa

Handoff (default si OpenSpec CLI está)

openspec --version resuelve

forge spec ejecuta openspec new change + emite .contextforge/spec-prompt.md con instrucciones canónicas + contexto del grafo. El dev pega ese prompt en su agente

Fallback (sin OpenSpec CLI o --no-openspec)

CLI ausente, CI sin instalación

ContextForge emite el scaffold con formato moderno (### Requirement: + #### Scenario:). Cuando se instale el CLI después, openspec validate pasa sin retoque

Mismo contrato (spec-input.json), dos formas de consumirlo. Portable Mac/Linux/Windows.

Forma de cada Requirement (RFC 2119 + Given/When/Then):

### Requirement: System produces fix-token-race within budget

The system MUST implement the change `fix-token-race` while respecting
`guardrails.allowedFiles` and not exceeding `guardrails.maxLocDelta`.

#### Scenario: change is implemented within scope

- **Given** a valid `.contextforge/context-pack.json` for the task
- **When** the developer runs `pnpm forge implement fix-token-race`
- **Then** `pnpm forge implement --check` exits with code 0

Guardrails de implementación (derivados del grafo):

forge implement produce implement-plan.json cuyos campos vienen del context-pack:

  • allowedFiles[] ← exactamente los archivos del pack

  • forbiddenPaths[] — nunca tocar

  • maxLocDelta — derivado del tamaño del pack

  • maxFilesChangedallowedFiles.length + 2

forge implement --check valida tu git diff antes del commit. Si te saliste del scope, te lo dice exactamente y el commit no pasa.

Capa 3 — Solo cargar las skills/rules que aplican a la tarea

forge context ya emite 5 artefactos sin paso extra:

.contextforge/context-pack.json              ← archivos relevantes
.contextforge/token-ledger.json              ← métricas
.contextforge/agent-manifest.json            ← NEUTRAL (validado por schema)
.claude/agent-manifest.md                    ← renderer Claude Code
.cursor/rules/contextforge-active.mdc        ← renderer Cursor (Auto-Attached)
.contextforge/manifests/opencode-readme.md   ← renderer OpenCode

Reglas de matching (priorizadas):

  1. alwaysApply: true → siempre incluida.

  2. frontmatter domains: [..] ∩ dominios tocados → match domain.

  3. nombre contextforge-domain-<slug> del dominio tocado → match explicit (legacy ctx-<slug> aún soportado).

  4. nada matchea → skipped (con razón).

Frontmatter mal formado nunca crashea: cae en skipped con frontmatter parse error.

Activación por agente (sin pasos manuales después de setup):

Agente

Cómo se carga

Setup

Claude Code

Hook UserPromptSubmit regenera el manifest en cada prompt

Pegar snippet en .claude/settings.json (ver docs/integrations/claude-code-hook.md)

OpenCode

El agente llama tool MCP select_agent_context({task}) al inicio. Live, sin disco

opencode.json ya configurado

Cursor

Rule Auto-Attached con globs: por dominio. Se activa al abrir un archivo del dominio

Sin setup; forge context regenera la rule


El grafo en detalle

Esta sección explica qué genera forge graph, cómo lo genera, cómo lo visualiza, y cómo el agente lo consume. Si vienes de Understand-Anything, vas a reconocer la idea: convertir un repo en un mapa navegable. La diferencia es que aquí el pipeline es 100 % determinista (sin LLM en el loop, sin coste por correrlo), cacheable por archivo, y los outputs son JSON portables que cualquier agente puede consumir sin la app.

Pipeline de generación (qué pasa cuando corres forge graph)

┌──────────────┐       ┌─────────────┐       ┌──────────────┐       ┌──────────────┐
│  scan.json   │  →    │  per-file   │  →    │  graph passes│  →    │  graph.json  │
│  (BLAKE3)    │       │  cache hit? │       │  (4 etapas)  │       │  + cache.json│
└──────────────┘       └─────────────┘       └──────────────┘       └──────────────┘
       │                      │                      │
       │                      │                      ├─ Pass 0: file nodes
       │                      │                      ├─ Pass 1: parse code/test (paralelo, n=cpus)
       │                      │                      ├─ Pass 2: defines + imports + tests
       │                      │                      ├─ Pass 3: extends / implements
       │                      │                      ├─ Pass 3.5 (--with-calls): calls
       │                      │                      └─ Pass 4: folder + contains
       │                      │
       │                      └─ Si `file.hash` coincide con cache, reusa el fragment parseado
       │                         y solo recomputa las aristas cross-file (imports/extends/calls).
       │
       └─ Hash global del scan: si no cambió, `forge graph` ni siquiera arranca (skip).

Output canónico.contextforge/graph.json cumple docs/schemas/graph.schema.json:

{
  "schemaVersion": "0.2.0",
  "project": { "name": "contextforge-cli", "root": "." },
  "generatedAt": "2026-05-08T...Z",
  "scanRef": { "path": ".contextforge/scan.json", "scanHash": "..." },
  "parser": { "engine": "heuristic" },
  "stats": {
    "nodesByType": { "file": 287, "folder": 117, "symbol": 3104 },
    "edgesByType": { "imports": 71, "defines": 2256, "contains": 376 }
  },
  "nodes": [
    /* ordenados por id, JSON byte-estable */
  ],
  "edges": [
    /* ordenadas por (from,to,type) */
  ]
}

Tipos de nodo y arista que produce

Nodo

Cuándo aparece

file

Uno por cada archivo del scan (code/test/doc/config/asset)

symbol

Por cada función/clase/interface/type/var/enum exportada o interna

folder

Sintético, derivado de los paths (anidación completa)

package

Por cada import externo único (react, node:path, @anthropic-ai/sdk, …)

Arista

De qué

Cuándo se emite

defines

file → symbol

Siempre que el archivo contiene un símbolo

imports

file → file o file → package

Relativos · alias workspace (pnpm) · alias tsconfig.paths · externos

tests

file:test → file:impl

Convención *.test.ts*.ts

extends

symbol → symbol

Clase/interface extiende un símbolo del mismo file o de un import

implements

symbol → symbol

class A implements B resuelto

contains

folder → folder y folder → file

Estructura de carpetas

calls

file → symbol

(heurística regex, ruido aceptado)

references

file → symbol

(PascalCase, fuera de imports/defines)

Lenguajes parseables hoy (heurística regex, no tree-sitter WASM): TypeScript, TSX, JavaScript, JSX, Python, Go, Rust, Java. El resto se incluye como file pero sin símbolos.

Incrementalidad y reproducibilidad

pnpm forge graph              # 1ª vez en este repo: 112 archivos parseados
# editas un archivo
pnpm forge scan               # actualiza hashes
pnpm forge graph              # → "cache: 111 reutilizados, 1 reparseados"

pnpm forge graph --force      # ignora ambos caches; reconstruye todo
pnpm forge graph --with-calls # añade aristas calls (heurística, opt-in)
pnpm forge graph --with-refs  # añade aristas references PascalCase (opt-in)

# resolución de imports
#   1. workspace pnpm  (packages/<name>)
#   2. tsconfig.paths  (compilerOptions.paths con baseUrl)
#   3. relativos       (./foo, ../bar)
#   4. externos        → nodo type=package (react, node:fs, @scope/lib)

# export a otros formatos
pnpm forge graph --export=dot     > graph.dot
pnpm forge graph --export=graphml > graph.graphml
# Render con Graphviz: dot -Tsvg graph.dot -o graph.svg
# O abrir graph.graphml directamente en Gephi.

# enriquecimiento opcional con LLM (Anthropic)
ANTHROPIC_API_KEY=sk-... pnpm forge graph --enrich
# Agrega summary / tags / complexity a los símbolos exportados.
# El default sigue siendo determinista; --enrich es la única excepción opt-in.
  • Cache global por hash del scan: si scan.json no cambió, forge graph no arranca.

  • Cache por archivo (.contextforge/graph.cache.json): solo se reparsean los archivos cuyo hash BLAKE3 cambió.

  • Output byte-idéntico entre dos corridas (excluyendo generatedAt): los nodos y aristas se ordenan al final por id / (from,to,type), así que git diff del JSON es revisable y el prompt cache de Claude no se invalida innecesariamente.

Visualización: forge viz

pnpm forge graph
pnpm forge viz                # genera .contextforge/graph.html
# abre el archivo en cualquier navegador, no necesita servidor ni Node

El HTML viewer es standalone (un solo archivo, Cytoscape vía CDN) y trae:

┌──────────────────────────────────────────────────────────────────────┐
│ ContextForge      [Grafo] [Dominios]   287 nodos · 2703 edges · 50 pack│
├──────────────┬───────────────────────────────────────────────────────┤
│ Estadísticas │                                                        │
│  287 archivos │              ●─────●                                  │
│  3104 símbolos│            ╱       ╲       ●  ←  archivo en pack      │
│  2703 edges   │           ●─────●───●      ◇  ←  símbolo exportado    │
│  50 en pack   │            ╲   ╱            ◇  ← dashed = interno     │
│               │             ●─●            ▢  ←  carpeta              │
│ Tour ◀ ▶ ✕   │                                                        │
│  3 / 50       │                                                        │
│               │                                                        │
│ Leyenda nodos │           ┌──────────────┐                            │
│  ● Código 128 │           │   src/       │  ←  agrupación por dominio │
│  ● Test  24   │           │  ┌────┐ ┌──┐ │      (toggle "Agrupar")    │
│  ● Doc   17   │           │  │a.ts│ │b │ │                            │
│  ▢ Carpeta 117│           │  └────┘ └──┘ │                            │
│  ◇ Interno 218│           └──────────────┘                            │
│  ● En pack 50 │                                                        │
│               │                                                        │
│ Leyenda edges │                                                        │
│ ─ imports     │                                                        │
│ ─ defines     │                                                        │
│ ─ tests       │                                                        │
│ ─ extends     │                                                        │
│ ─ contains    │                                                        │
│               │                                                        │
│ Filtros       │                                                        │
│ [Solo pack] [+Sím] [+Carpetas] [Agrupar]                               │
│ [⊕ Centrar]  [⟳ Layout]                                               │
│               │                                                        │
│ 🔍 Buscar...  │                                                        │
│               │                                                        │
│ Nodo selec.   │                                                        │
│  src/main.ts  │                                                        │
│  [code][ts]   │                                                        │
│  Define 4 sím │                                                        │
│  → importa: 3 │                                                        │
│  ← usado por:5│                                                        │
└───────────────┴────────────────────────────────────────────────────────┘

Capacidades del viewer:

  • Dos vistas: grafo file/symbol/folder + vista de dominios (agregación por carpeta top-level, edges = imports cruzados entre dominios).

  • Tour por context-pack: recorre uno por uno los archivos seleccionados por PageRank para tu tarea, centrándose y mostrando vecinos.

  • Filtros incrementales: solo pack (default), añadir símbolos, añadir carpetas, agrupar por dominio.

  • Estilos diferenciados para exported:false (símbolos internos en dashed) y nodos folder.

  • Búsqueda por nombre o ruta con resaltado.

  • Panel de nodo: kind, lang, contadores de edges entrantes/salientes, lista navegable de vecinos.

Cómo lo usa el agente

El agente nunca lee el repo a ciegas. Lee artefactos derivados, en este orden:

1. .contextforge/agent-context.md   ← qué hay disponible y en qué orden leerlo
2. .contextforge/context-pack.json  ← solo los archivos relevantes a la tarea
3. .contextforge/agent-manifest.json ← qué skills/rules aplican (con razón)
4. .contextforge/graph.json          ← solo si necesita ver vecinos / cross-deps

El grafo no se inyecta entero al prompt. El agente lo consulta puntualmente:

Pregunta del agente

Cómo responde el grafo

"¿Qué archivos tocan a Foo?"

Edges defines/imports entrantes del símbolo

"¿Quién testea esto?"

Edges tests entrantes del file

"¿De qué hereda Bar?"

Edge extends saliente del símbolo

"¿En qué carpeta vive este archivo?"

Edge contains entrante del file

"Dame el subgrafo de mi tarea"

Lo entrega forge context ya filtrado (PageRank + BFS + budget)

"Que nada se salga del scope"

implement-plan.json::allowedFiles[] derivado del pack

Vía MCP — los agentes que hablen MCP pueden llamar tools sin tocar disco:

{ "tool": "forge_neighbors", "arguments": { "path": "src/foo.ts" } }
// → { incoming: [...], outgoing: [...], symbols: [...] }

{ "tool": "forge_context", "arguments": { "task": "fix race in writer" } }
// → { files: [...], packTokens: 11988, tokenLedger: {...} }

Vs. Understand-Anything (qué tomamos, qué no)

Aspecto

Understand-Anything

ContextForge

Pipeline

Tree-sitter + LLM agents (híbrido)

Regex/tree-sitter, 0 LLM en el pipeline

Lenguajes soportados

10+ con WASM

8 con heurística (TS/JS/Py/Go/Rust/Java/TSX/JSX)

Schema de nodo

21 tipos (con dominio + knowledge)

4 tipos canónicos (file/symbol/folder/package)

Schema de arista

35 tipos

8 tipos (los que un agente usa de verdad)

Enriquecimiento (summary)

LLM agents enriquecen cada nodo

Determinista: contadores derivados del grafo

Coste de regenerar

API key + tiempo + ruido

CPU-only · cache por archivo · idempotente

Visualización

Dashboard rico, tours guiados

HTML standalone con tour + dominios + filtros

Persistencia

knowledge-graph.json + embeddings

graph.json + graph.cache.json (BLAKE3)

Roadmap LLM enrich

Es la base

Opt-in futuro (--enrich), nunca el default

La filosofía: el grafo de ContextForge no intenta entender el código, intenta darte un índice rápido y barato. La inteligencia semántica vive en el agente, no en el pipeline. Por eso es reproducible y por eso el output sirve de input al prompt cache de Claude (descuento del 90 % en iteraciones 2+ del SDD).


Cómo el grafo le da superpoderes a OpenSpec

El bloque clave de v0.3.0+. Sin grafo, OpenSpec hace su trabajo bien pero el agente trabaja a ciegas. Con grafo, el spec se vuelve trazable, validable y barato.

1. El spec-input.json deriva del grafo, no del repo.

Campo

Lo aporta el grafo

affectedFiles

El context-pack ya filtró por PageRank → spec apunta a archivos reales

crossDomainDeps

El grafo de imports → design.md menciona dependencias correctas

domain

Inferencia por mayoría de paths del pack

evidence

Referencias trazables a los artefactos JSON validados

purpose

Inferencia determinista del nombre del archivo

2. El agente recibe el spec-prompt, NO el repo.

forge spec genera .contextforge/spec-prompt.md con 4 secciones:

1. Contexto del repo (de ContextForge)
   - Tarea, dominio inferido, archivos afectados, cross-domain deps, evidencia
2. Instrucciones canónicas de OpenSpec
   - Lo que devuelve `openspec instructions proposal --change <id> --json`
3. Restricciones para tu salida
   - Token budget, allowed files, formato moderno
4. Output esperado
   - Editar openspec/changes/<id>/{proposal,design,tasks,specs}.md

El agente no abre el repo. Solo lee este prompt + el context-pack si necesita más detalle.

3. El multiplicador escondido — prompt caching.

Claude descuenta 90 % del precio de tokens cacheados. ContextForge mete un boost porque su output es determinista:

  • Mismo forge context → mismo context-pack.json byte-a-byte.

  • Mismo forge spec → mismo spec-prompt.md byte-a-byte.

Entre las iteraciones 2, 3, N del SDD, el agente cachea todo el prompt. Solo paga full por el delta.

4. Ahorro doble medido.

Por iteración SDD:
  Sin ContextForge   217 600 tokens   $0.65
  Con ContextForge    18 988 tokens   $0.057   (-91%)

3 iteraciones de un feature normal:
  Sin caching         3 × $0.65 = $1.96
  Con caching activo  $0.07     (÷28×)

5. Trazabilidad auditable.

Cada path en design.md apunta a un archivo del context-pack.json. Cada commit puede verificarse con forge implement --check contra allowedFiles[] derivado del pack.

6. Subgrafo congelado dentro del change (v0.3.7+).

forge spec <id> ahora también escribe openspec/changes/<id>/graph.subset.json — un subgrafo limitado al context-pack del change + 1 hop por aristas. Eso significa:

  • Las skills/prompts del agente que leen openspec/changes/<id>/ tienen el grafo del momento exacto en que se autorizó el spec, sin necesidad de reabrir .contextforge/graph.json (que pudo haber mutado).

  • design.md incluye una sección "Context graph (subset)" con stats y la referencia al adjunto.

  • Vía MCP: forge_change_subgraph({ change_id: "mi-feature" }) lo devuelve directo, ideal para que un agente lo cargue al inicio de una sesión de implementación.

openspec/changes/mi-feature/
  ├── proposal.md
  ├── design.md           ← incluye tabla con stats del subset
  ├── tasks.md
  ├── specs/<domain>/spec.md
  ├── graph.subset.json   ← subgrafo self-contained · validado por JSON Schema
  └── graph.subset.html   ← viewer interactivo standalone (Cytoscape, sin servidor)

Trazabilidad real: el subgrafo es byte-stable (orden determinista), validado por JSON Schema (docs/schemas/graph-subset.schema.json), y queda commiteado con el resto del change. Si seis meses después el grafo global cambió, puedes comparar este subset con el subgrafo equivalente de hoy y ver el drift.

Tabla — qué aporta cada herramienta:

Aporte

ContextForge

OpenSpec

Agente IA

Ranking de archivos por relevancia

Grafo de dependencias

Token budget + selección por presupuesto

Trazabilidad (cada archivo viene del pack)

Schemas estables (Requirement+Scenario)

Validación estructural (openspec validate)

Templates canónicos por artefacto

Instalación de instrucciones por agente (openspec init)

Redacción de prosa

Decisiones de diseño contextual

Determinismo + cacheabilidad


Documentación generada para agentes (forge init)

forge init genera .contextforge/agent-context.md — un archivo derivado que cualquier agente puede leer al iniciar sesión y entender:

  • Qué artefactos hay disponibles y en qué orden leerlos.

  • Cómo consumirlos (no leer el repo a ciegas).

  • La receta SDD completa (ContextForge ⊕ OpenSpec).

  • Política para agentes (no specs a mano, no bullets, gate pre-commit).

  • Tabla de comandos clave por intención.

Adicionalmente, forge init detecta si openspec CLI está en PATH y, si el directorio openspec/ no existe, ejecuta:

openspec init . --tools=claude,cursor,opencode --force

Eso instala las instrucciones canónicas de OpenSpec para los 3 agentes (las que aparecen en .claude/, .cursor/rules/, opencode.json). Idempotente: si el directorio openspec/ ya existe, salta.


Comandos completos

Comando

Qué hace

LLM

forge init

.contextforge/ + agent-context.md + openspec init (si está)

No

forge scan

Indexa con BLAKE3 (incremental)

No

forge graph [--force] [--with-calls] [--with-refs] [--enrich] [--export=<dot|graphml>]

Grafo file/symbol/folder/package con cache por archivo (BLAKE3)

No (¹)

forge context "<tarea>" [--no-manifest] [--force]

PageRank + BFS + budget · auto-emite manifest

No

forge spec <id> [--no-openspec]

spec-input.json + handoff/fallback OpenSpec

No

forge implement <id>

Plan con guardrails derivados del pack

No

forge implement --check

Valida diff vs guardrails

No

forge skills [--force]

Auto-genera skills por dominio (contextforge-domain-<slug>.md)

No

forge manifest [--agents=...] [--force]

Re-genera manifest sin re-rankear

No

forge sync [--since X] [--rebuild]

Reporta delta desde un ref de git

No

forge impact

Health check de artefactos + cobertura

No

forge viz

Visualización HTML interactiva del grafo

No

forge docs [--force]

Scaffold Diátaxis (tutorials/how-to/reference/explanation/adr/architecture)

No

Política: ningún comando llama a un LLM por defecto. Todo es derivable, reproducible, auditable.

(¹) forge graph --enrich es la única excepción opt-in — agrega summary/tags/complexity a símbolos exportados vía Anthropic API. Requiere ANTHROPIC_API_KEY. Sin la flag, el pipeline sigue 100 % determinista.


Servidor MCP

packages/mcp expone 10 tools consumibles por cualquier cliente MCP (Claude Code, OpenCode, etc.).

Tool

Propósito

forge_status

Estado de los artefactos (frescura, conteos, savings)

forge_domain_map

Mapa de dominios + dependencias cruzadas

forge_neighbors

Vecinos directos de un archivo en el grafo

forge_context

Selección PageRank para una tarea (con o sin contenido)

forge_check

Valida git diff contra guardrails del implement-plan

forge_change_subgraph

Subgrafo congelado de un OpenSpec change (openspec/changes/<id>/graph.subset.json)

forge_change_context

Mapa de lectura del change (openspec/changes/<id>/context.md)

forge_archive_change

Cierra un change: openspec archive + rebuild graph padre + refresh subgrafos

select_agent_context

Runtime: computa agent-manifest en memoria para una tarea (cache mtime)

get_agent_manifest

Offline: lee .contextforge/agent-manifest.json precomputado

Wiring (Docker, recomendado):

{
  "mcpServers": {
    "contextforge": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "-v",
        "${PWD}:/project",
        "-e",
        "PROJECT_ROOT=/project",
        "ghcr.io/alejandro-cedeno-10/contextforge-mcp:latest"
      ]
    }
  }
}

Wiring (npm):

{
  "mcpServers": {
    "contextforge": {
      "command": "node",
      "args": ["./node_modules/@anai-raia-alex/contextforge-mcp/dist/index.js"],
      "env": { "PROJECT_ROOT": "." }
    }
  }
}

Artefactos generados

Todos los JSON validados con JSON Schema 2020-12 antes de escribirse.

.contextforge/
  scan.json                  # archivos con hashes BLAKE3
  graph.json                 # 368 nodos, 267 edges
  context-pack.json          # archivos seleccionados dentro del presupuesto
  token-ledger.json          # métricas auditables del ahorro
  agent-manifest.json        # skills/rules relevantes a la tarea (neutral)
  spec-input.json            # entrada determinista para OpenSpec / agente
  spec-prompt.md             # prompt copy-paste (modo handoff)
  implement-plan.json        # guardrails: allowedFiles, maxLocDelta, etc.
  agent-context.md           # documentación del repo para agentes IA
  graph.html                 # visualización interactiva (Cytoscape.js)
  manifests/opencode-readme.md   # instrucciones MCP para OpenCode

.claude/agent-manifest.md           # manifest renderer Claude Code
.cursor/rules/contextforge-active.mdc  # rule auto-attached por dominios tocados

openspec/changes/<id>/
  proposal.md          # intent, scope, why, alternatives
  design.md            # decisiones técnicas con archivos del grafo
  tasks.md             # T1, T1.1, T2... checklist
  specs/<dominio>/spec.md   # ## ADDED Requirements + ### Requirement: + #### Scenario:

Schemas

Artefacto

Schema

scan.json

docs/schemas/scan.schema.json

graph.json

docs/schemas/graph.schema.json

context-pack.json

docs/schemas/context-pack.schema.json

implement-plan.json

docs/schemas/implement-plan.schema.json

token-ledger.json

docs/schemas/token-ledger.schema.json

agent-manifest.json

docs/schemas/agent-manifest.schema.json

spec-input.json

docs/schemas/spec-input.schema.json


Métricas reales (este repo, hoy)

Métrica

Valor

Tests

270 / 270 verde (26 archivos)

Coverage

≥ 80 % global · módulos manifest/ y spec/ ≥ 95 %

Token savings

94.4 % vs baseline

Compresión

17.9× por sesión · ÷28× SDD con caching

Archivos del repo

128

Archivos en context-pack

50

Tokens del context-pack

11 988

Tokens baseline

214 606

Grafo

368 nodos, 267 edges

Comandos forge

13

Tools MCP

7


Distribución

Canal

Identificador

npmjs.com (público, sin token)

@anai-raia-alex/contextforge-{core,cli,mcp}

GitHub Container Registry

ghcr.io/alejandro-cedeno-10/contextforge-mcp:latest (multi-arch amd64+arm64)

Repo público

https://github.com/alejandro-cedeno-10/contextforge-cli


Integración con agentes — matriz

Agente

Configuración

Selección por tarea

Estado

Claude Code

.claude/skills/ (3 task-oriented + N auto-generadas) · hook UserPromptSubmit

Hook inyecta manifest live + JSON precomputado

Listo

Cursor

.cursor/rules/contextforge.mdc (alwaysApply) + contextforge-active.mdc (Auto-Attached)

Rule por glob regenerada por forge context (Cursor no tiene hooks reactivos)

Listo

OpenCode

opencode.json con MCP server registrado

Tool MCP select_agent_context({task}) live

Listo

Codex / otros

Leen .contextforge/*.json directamente

Lectura directa de agent-manifest.json

Compatible

Los .contextforge/*.json son portables. Cualquier agente futuro los puede consumir sin modificación.


Principios

  • Determinismo primero: ningún comando llama a un LLM. Reproducible, auditable, cacheable.

  • OpenSpec por defecto: forge spec delega a OpenSpec CLI cuando está, fallback determinista cuando no.

  • Cache por hash: si scan.json no cambió, forge graph salta el rebuild.

  • Presupuesto explícito: cada context-pack tiene maxInputTokens trazable en token-ledger.json.

  • JSON validado: ningún artefacto se escribe sin pasar JSON Schema.

  • Portable: cualquier agente puede consumir .contextforge/*.json sin modificación.

  • Sin lock-in: si mañana sale otra herramienta SDD, lee los mismos JSON.


Para la exposición — los 5 puntos memorables

  1. 94 % menos tokens por sesión — verificado con token-ledger.json, no estimado.

  2. ÷28× costo SDD con prompt caching — porque el output es determinista byte-a-byte.

  3. No competimos con OpenSpec, lo apoyamos. Tres roles separados (CF / OpenSpec / agente). Si OpenSpec evoluciona, no nos pisamos.

  4. El agente solo carga lo de tu tarea actual — context-pack + manifest. Las 100 skills viejas no entran al contexto.

  5. Sin lock-in. Los .contextforge/*.json son neutrales. Si mañana sale otra herramienta, los puede consumir igual.


Estructura del monorepo

packages/
  core/   → scanner, parser tree-sitter, graph builder, selector PageRank,
            packer, schema validator, skill builder, agent-manifest, spec-input,
            spec promptRenderer
  cli/    → comandos forge (init, scan, graph, context, spec, implement, manifest,
            skills, sync, impact, viz, docs)
  mcp/    → servidor MCP con 7 tools

.claude/skills/    → 3 skills task-oriented (contextforge-*) +
                     N auto-generadas (contextforge-domain-*) +
                     agent-manifest.md (per-task)
.cursor/rules/     → contextforge.mdc (alwaysApply) +
                     contextforge-active.mdc (Auto-Attached, regenerada por tarea)
opencode.json      → configuración MCP para OpenCode
docs/integrations/ → guías de wiring por agente
docs/explanation/  → contextforge-and-openspec.md (lectura clave)

Tests

pnpm test               # todos los tests
pnpm test:coverage      # con cobertura
pnpm typecheck          # tsc -b --force (project references)

Suite actual: 270/270 tests pasando (26 archivos), coverage global ≥ 80 % · módulos manifest/ y spec/ ≥ 95 %.


Documentación

Documento

Descripción

docs/explanation/contextforge-and-openspec.md

Lectura clave: 3 roles (CF / OpenSpec / agente), ahorro medido, prompt caching ÷28×

docs/how-to/use-contextforge.md

Guía paso a paso: instalación, pipeline, integración por agente

docs/integrations/claude-code-hook.md

Snippet copy-paste para activar manifest en runtime en Claude Code

docs/integrations/cursor-rules.md

Los 3 modos de rules en Cursor + estrategia recomendada

docs/integrations/opencode-mcp.md

Ejemplo de select_agent_context desde OpenCode

docs/token-savings-architecture.md

Análisis de ahorro de tokens por capas con tabla de costos

docs/EXAMPLES/end-to-end-flow.md

Walkthrough completo del pipeline con outputs reales

docs/IMPLEMENTATION_TASKS.md

Backlog de sprints con criterios verificables

docs/CHANGELOG-schemas.md

Historial de cambios de schemas

openspec/changes/forge-spec-as-prepare-step/

OpenSpec change del re-arquitectura v0.3.0

openspec/changes/agent-manifest/

OpenSpec change del manifest por tarea

openspec/changes/auto-domain-skills/

OpenSpec change de las skills auto-generadas

CONTEXTFORGE_SOURCE_OF_TRUTH.md

Decisiones de diseño, arquitectura, roadmap


Licencia

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
0dRelease cycle
23Releases (12mo)

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alejandro-cedeno-10/contextforge-cli'

If you have feedback or need assistance with the MCP directory API, please join our Discord server