ULTRON Control Center
Memoria persistente y gobernada para Claude Code — tu asistente recuerda decisiones, arquitectura y contexto entre sesiones, con auditoria de cada escritura.
¿Que es esto?
Tu asistente de IA olvida todo cada vez que cierras la ventana: las decisiones quetomasteis, los errores que ya resolvisteis, como esta montado tu proyecto. Al diasiguiente se lo vuelves a explicar todo.
ULTRON le da memoria. Mientras trabajas, guarda lo importante en tu propioordenador; cuando abres una conversacion nueva, se lo recuerda a la IAautomaticamente. Tu no haces nada: trabajas como siempre y tu asistente cada vezte conoce mejor. Tu decides que se guarda (todo pasa por una bandeja de aprobacion)y nada sale de tu maquina.
La version tecnica (click para abrir)Memoria local event-sourced (brain.db, SQLite) con indice semantico (Qdrant +E5 1024d), reinyectada en cada sesion mediante hooks — recall hibrido sub-segundocon un daemon residente. Ademas: AI Router multi-proveedor, orquestador deskills/agentes y cockpit de escritorio (Tauri 2 + React 19). Todo el estado sonficheros locales inspeccionables. Spec: docs/memory-spec.md.
Con y sin ULTRON
| Claude Code a secas | Con ULTRON | |
|---|---|---|
| Al abrir una sesion | Empieza de cero | Resume del proyecto: estado, tareas, decisiones |
| Contexto en cada prompt | El que tu escribas | + memorias relevantes recuperadas solas (~84% de prompts reales) |
| Errores ya resueltos | Se repiten | Se recuerdan ("eso ya lo intentamos, fallo por X") |
| Que se guarda | Nada | Lo que apruebes en la bandeja (con auditoria de cada cambio) |
| Donde viven tus datos | — | En tu disco, en ficheros que puedes abrir |
Frente a otros sistemas de memoria (servicios cloud tipo Mem0 y similares), lasdiferencias son de diseño, no de marketing: aqui la memoria es 100% local (sincuenta, sin suscripcion, sin enviar tu codigo a un tercero), gobernada (la IApropone, tu apruebas; cada escritura deja evento de auditoria), honesta (si nosabe, se abstiene en vez de inyectar relleno — medido) y abierta (SQLite +Markdown + un MCP server estandar que cualquier asistente puede consultar).
Tutorial de uso diario (humano + IA):
docs/TUTORIAL.md·Spec completa del sistema de memoria:docs/memory-spec.md·Instalacion por componentes:INSTALL.md· Licencia MIT.
Como fluye la memoria
flowchart LR
A[Prompt en Claude Code] -->|hook UserPromptSubmit| B[daemon ultron-memory<br/>E5 residente]
B --> C[(brain.db<br/>SQLite + FTS5)]
B --> D[(Qdrant<br/>E5 1024d)]
C -->|BM25| E[Fusion RRF + cross-encoder]
D -->|dense| E
E -->|pack de memorias| A
F[Fin de sesion] -->|hook Stop| G[Captura -> inbox de candidatos]
G -->|aprobacion| C
H[Cualquier cliente MCP<br/>Codex, Gemini CLI...] -->|MCP server| B
Numeros reales (medidos, no simulados)
Medidos sobre el corpus real del mantenedor (~3.300 memorias activas) con unoraculo de 29 queries etiquetadas a mano — tu instalacion arranca vacia y lascifras de recall dependen de tu corpus. Reproducibles con ultron-memory eval --golden y losscripts del repo.
| Metrica | Valor |
|---|---|
| Recall@8 (oraculo etiquetado a mano) | 0.82 |
| MRR (la memoria correcta, arriba) | 0.95 |
| Orchestrate con daemon caliente | ~0.5 s (vs ~3.5 s por proceso frio) |
| RAM en reposo (app / daemon) | 36 MB / ~40 MB (1.5-3.5 GB con modelos cargados) |
| Prompts reales servidos con memoria | 84% (gates calibrados sobre trafico real, no solo golden) |
Cuando el corpus no conoce la respuesta, el sistema se abstiene en vez deinyectar relleno — la honestidad del recall tambien esta medida (categoriaabstain del bench propio).
Quickstart
Sistema completo (app + skills + hooks + memoria semantica) — el caminorecomendado; es idempotente y pregunta antes de tocar nada:
git clone https://github.com/SkiTemplar/ultron-control-center.git $env:USERPROFILE\.ultron
cd $env:USERPROFILE\.ultron
powershell -ExecutionPolicy Bypass -File .\install.ps1 # Linux: ./install.sh
Instalacion por componentes (sin wizard, determinista; -DryRun lista elplan sin tocar nada):
.\install.ps1 -Core # app + memoria + hooks (el set por defecto)
.\install.ps1 -All # core + skills + tones + agents
.\install.ps1 -Skills -Tones # a la carta
.\install.ps1 -Core -DryRun # solo listar que haria
# Linux: ./install.sh --core | --all | --skills | --tones | --agents | --dry-run
Solo la app de escritorio (sin skills/hooks/sidecar de memoria):
git clone https://github.com/SkiTemplar/ultron-control-center.git ~/.ultron && cd ~/.ultron/control-center
cp ../.env.example ../.env # opcional: claves de proveedores LLM (todas vacias por defecto)
npm install
npm run build:app # = kill-app + tauri build -> ejecutable de escritorio
Guia completa (bootstrap one-liner desde release, flags, troubleshooting):INSTALL.md.
Qdrant es opcional (el recall degrada a sparse-only sin el); ver la seccionQdrant de docs/INSTALL-ADVANCED.md.Las rutas per-maquina se documentan enconfig/paths.example.toml.
Caracteristicas
- Memoria gobernada —
brain.db(SQLite) como unica fuente de verdad; todocambio pasa por un unico servicio que anexa un evento de auditoria. - Recall hibrido — denso (E5 1024d / Qdrant) + sparse (FTS5/BM25) fusionadoscon Reciprocal Rank Fusion; degrada a sparse-only sin Qdrant.
- Inbox de candidatos — las capturas automaticas proponen, el humano aprueba;nunca se auto-escribe memoria activa.
- Redaccion + dedupe en el write-path — secretos/PII fuera, duplicados por
content_hashfuera, antes de persistir o embeber. - AI Router — cadena primario -> fallbacks por zona, deteccion de claves ytelemetria de uso/ahorro; routing directo en Rust (sin sidecar LiteLLM).
- Orquestador por reglas — mapea prompt -> intent -> workflow -> agentes ->memorias; reserva el modelo grande solo para la cola ambigua.
- Tonos / personalidades — deteccion determinista del tono del chat(senales lexicas + peticion explicita) dentro del orchestrate; los tonos seeditan en Library -> Tones. La config real (
~/.ultron/personality.json) eslocal y gitignored; el repo publica solo los seeds compilados(orchestrator/personality.rs). El tono viste unicamente la conversacion:nunca commits, docs ni artefactos.
Que es
ULTRON Control Center no reemplaza a Claude Code: lo envuelve. Le da memoriapersistente y gobernada, enruta peticiones a varios proveedores LLM segun costey disponibilidad, y detecta automaticamente que skill/agente especialistaconviene para un prompt. Todo el estado vive en ficheros locales (SQLite +JSON + markdown) que puedes inspeccionar, versionar y editar a mano.
| Pilar | Que hace |
|---|---|
| Memoria gobernada | ~/.ultron/brain.db (SQLite) es la unica fuente de verdad. Toda escritura pasa por un unico servicio que ademas registra un evento de auditoria. Las capturas automaticas nunca escriben memoria activa directamente: proponen candidatos a un inbox que el humano aprueba o rechaza. |
| Recall hibrido | Fusion de dos fuentes con Reciprocal Rank Fusion (RRF): denso (vectores E5 1024d en Qdrant) + sparse (FTS5/BM25 sobre brain.db). Degrada a solo-sparse si Qdrant/E5 no estan disponibles. |
| AI Router | Catalogo de proveedores + zonas con cadena primario -> fallbacks, deteccion de claves, telemetria de uso/ahorro. Sin sidecar LiteLLM: routing directo en Rust. |
| Orquestador | Mapea un prompt (posiblemente vago) a intent -> workflow -> agentes a delegar -> memorias relevantes -> restricciones, mediante reglas (no usa el modelo grande para lo que resuelven reglas/triggers). |
Arquitectura del backend (real)
El backend Rust vive en control-center/src-tauri/src/. El modulo central dememoria esta en control-center/src-tauri/src/memory/.
Memoria: SQLite como fuente de verdad
~/.ultron/brain.db(SQLite, modo WAL) es la SoT canonica. El esquemacanonico vive enmemory/schema_v3.rs(memoria) +memory/schema_v4.rs(migracion historica v4: tablasedges/unresolved_refs, hoy inertes — elgrafo de codigo lo provee el MCP CodeGraph externo) /memory/migrations.rs, con modelos enmemory/model.rs(MemoryItem,MemoryCandidate,MemoryEvent, y los enums de gobernanzaStatus,Scope,Sensitivity,Source, etc.).MemoryService(memory/service.rs) es el unico escritor persistente.Invariante de gobernanza: toda mutacion pasa por aqui y anexa unMemoryEventde auditoria. Hooks y agentes nunca escribenmemory_itemsdirectamente; solo proponenMemoryCandidates que un humano (o una politicade auto-aprobacion) promueve.- En el camino de escritura se aplican guardas: redaccion de secretos/PII(
memory/redaction.rs) antes de persistir o embeber, dedupe exacto porcontent_hash(memory/texthash.rs) y dedupe lexico por FTS.
Qdrant: indice derivado (no fuente de verdad)
- La coleccion
ultron_memory(Qdrant) indexa los items ACTIVE conMultilingualE5Large, 1024 dimensiones (memory/qdrant_index.rs). Es unindice derivado: se puede reconstruir en cualquier momento conreindex_allybrain.dbsigue siendo la verdad. - Tras cada escritura aprobada/editada/restaurada,
sync_indexmantiene Qdranten paso con la SoT (best-effort; cualquier deriva es detectable/reparable viareconcile). - La coleccion antigua
ultron_sessions(384d BGE) esta retirada; Qdrant aquies siempre un indice, nunca la verdad.
Recall hibrido denso + sparse con RRF
- El comando unico
recall(commands/memory/recall_unified.rs) fusiona conReciprocal Rank Fusion (RRF_K = 60):- DENSO: vectores E5 en
ultron_memory(Qdrant). - SPARSE: FTS5/BM25 sobre
memory_items(solostatus=active).
- DENSO: vectores E5 en
- Devuelve un context pack compacto de resumenes bajo presupuesto de tokens(
TOKEN_BUDGET = 1500), con trazas de por que esta memoria (rangos porfuente, scores, descartes) para el Retrieval Inspector. - El unico camino de recall es el comando unificado
recallcon RRF; lasfuentes son Qdrant (denso) + SQLite/FTS5 (sparse). No usa servicios dememoria externos.
Captura automatica via Stop hook
- En
Stop, el hook pasa el transcript de la sesion amemory/capture.rs::capture_session. Este:- pide a un LLM (via
ai_router::route, zonachat) extraer unos pocoshechos/decisiones durables; - convierte cada hecho en un
MemoryCandidate(pasando por redaccion +dedupe) y lo deja en el inbox gobernado para aprobacion humana — nuncase auto-promueve a activo.
- pide a un LLM (via
- Fail-safe: si el router no tiene proveedor utilizable, degrada a unaheuristica local barata para que el Stop hook nunca falle.
- El inbox se gestiona desde
commands/memory/inbox.rs(memory_inbox_list,approve_candidate,reject_candidate).
AI Router: zonas, proveedores, fallback y telemetria
- Backend en el modulo
ai_router/(mod.rs + exec.rs + providers/ + seed.rs + store.rs). Estado en tres JSON bajo~/.ultron/cockpit/ai-router/:providers.json(catalogo),zones.json(zonas conprimary+fallbacks),metrics.json(contadores + ahorro). route(zone, prompt)recorre la cadena primario -> fallbacks, saltaproveedores sin clave API utilizable, registra latencia/tokens/ahorro en latelemetria y devuelveResult<String, String>(errores verbatim, nunca panic,cap de 10s).- Wrappers por proveedor: anthropic (claude-haiku), codex (OpenAI-compat),gemini, groq, ollama (local, sin clave), deepseek. Los healthchecks usan sondas baratas y no gastan tokens; las invocaciones de test si.
- Zonas por defecto incluyen
chat,code-edit,code-review,research-web,code-fast-local, entre otras.
Orquestador: deteccion automatica de skills/agentes
- El modulo
orchestrator/(rules.rs + ranking.rs + orchestrate.rs) mapeaprompt -> intent -> workflow -> agentes a delegar -> memorias -> restricciones. La clasificacion de intent es basada en reglas(bilingue es/en); el modelo grande se reserva para la cola ambigua. - Reutiliza (no duplica): el catalogo de agentes (
memory/catalog.rs), el recallunificado y los workflows integrados (agent_orchestration.rs). Nunca escribememoria persistente y delega a agentes reales en~/.claude/agents(los "ghost agents" inexistentes en disco se sanean).
Grafo de codigo: MCP CodeGraph (externo)
- El grafo de codigo (que simbolos existen, quien llama a quien, analisis deimpacto) lo provee CodeGraph (
@colbymchenry/codegraph, MIT), instaladocomo servidor MCP y consultado por los agentes viacodegraph_explore/codegraph_callers/codegraph_impact. Indexa el repo con tree-sitter (AST)en.codegraph/(SQLite local, incremental) — 20+ lenguajes.
Plugin Updates: chequeo de actualizaciones de plugins
- Sub-tab Updates dentro de Library (
src/components/library/PluginUpdates.tsx)que consume los comandos de backendplugin_check_updates_bulk(force)yplugin_changelog_summary(coordinate, installed_sha?). - Compara el SHA instalado contra el ultimo SHA del marketplace por cada plugin,marca cuales tienen actualizacion disponible y muestra el ultimo mensaje decommit / resumen de changelog.
Stack
| Capa | Tecnologia |
|---|---|
| Frontend (Control Center) | Tauri 2 + React 19 + TypeScript (control-center/src/) |
| Backend (Control Center) | Rust estable (control-center/src-tauri/src/) |
| Memoria (SoT) | SQLite (FTS5) en ~/.ultron/brain.db |
| Indice denso | Qdrant nativo (~/.ultron/qdrant-native/), coleccion ultron_memory, E5 1024d |
| Embeddings | E5 (denso) via crate::qdrant::embed_e5 dentro de ultron-memory |
| Sidecar CLI hooks | ultron-memory (logica canonica reusada por los hooks Node) |
| Scripting OS | PowerShell 5.1+ / scripts en cockpit/ |
| Runtimes LLM | Claude Code (principal); Codex CLI opcional. Gemini CLI retirado 2026-06-19 (Google corto el free-tier OAuth); Gemini queda solo como fallback cloud del AI Router |
Binarios sidecar declarados en control-center/src-tauri/Cargo.toml:ultron-memory (requiere la feature qdrant).
Build
# desde control-center/
npm install
npm run build:app # = kill-app + tauri build (genera el ejecutable de escritorio)
Otros scripts utiles (en control-center/package.json):
npm run dev # vite dev server (frontend)
npm run tauri # CLI de Tauri
npm test # vitest (frontend)
Nota Windows:
build:appejecuta primerokill-apppara cerrar cualquierinstancia en marcha; un binario obsoleto es la causa habitual de "no se haaplicado el cambio": cierra la app y recompila.
Estructura de carpetas
~/.ultron/
├── brain.db # SQLite — fuente de verdad de la memoria
├── qdrant-native/ # binario nativo de Qdrant (indice denso derivado)
├── qdrant_storage/ # datos persistidos por Qdrant
├── control-center/ # la app Tauri 2 + React 19
│ ├── src/ # frontend React/TS (componentes, tabs)
│ │ └── components/ # Dashboard, AIRouter, Library, Projects, ...
│ └── src-tauri/
│ └── src/
│ ├── memory/ # kernel de memoria (service, sqlite_store,
│ │ # qdrant_index, capture, redaction, texthash, ...)
│ ├── commands/ # comandos Tauri por dominio (memory, ai_router,
│ │ # projects, system_ops, ...)
│ ├── ai_router/ # AI Router (mod/exec/health/providers/seed/store/types)
│ ├── orchestrator/ # mod/orchestrate/ranking/rules/types_model
│ └── bin/ # sidecar ultron-memory
├── cockpit/ # config + estado en JSON/markdown
│ └── ai-router/ # providers.json, zones.json, metrics.json
├── personality.json # tonos del usuario (LOCAL, gitignored; se
│ # auto-siembra desde los seeds compilados)
├── hooks/ # hooks de ciclo de vida
├── skills/ # skills core (SKILL.md; catalogo curado no se publica)
├── plans/ projects/ # planes y proyectos
├── sessions/ # logs de sesion / telemetria de routing
└── docs/ # documentacion ampliada
Estado actual
- Memoria: kernel canonico activo. SoT =
brain.db; indice densoultron_memory(E5 1024d) sincronizado en escritura; recall unificado denso+sparse con RRFoperativo (degrada a sparse-only sin Qdrant). Write-path con redaccion desecretos y dedupe por content_hash cableados y testeados. - Captura automatica: Stop hook ->
capture_session-> candidatos al inboxgobernado; aprobacion/rechazo humano via comandos de inbox. - AI Router: routing real con cadena primario/fallback, deteccion de clavesy telemetria de uso/ahorro; sin sidecar LiteLLM.
- Tonos: deteccion determinista en el orchestrate (paridad JS/Rust deldetector verificada con gate 16/16); editor visual en Library -> Tones yplayground de deteccion.
personality.jsonlocal (gitignored) con seedspublicables compilados; limite duro: el tono solo aplica al chat, jamas aartefactos. - Detector de texto IA: hook PostToolUse que avisa cuando laprosa escrita "canta" a IA + Lab de patrones deterministas sobre el catalogode investigacion; matcher con CLI y banco de casos. Senala, no reescribe.
- UI (Control Center, v2.7.1): barra lateral con Dashboard, Usage, AI Router,System (con sub-tabs de Hooks/Schedules), MCPs,Library (sub-tabs Skills/Agents/Rules/Updates), Memory, Notes,Learn, Sessions, Projects, Finance (solo build local con
VITE_FINANCE=1),Settings y Notifications. La pestana Memoryesta viva (re-anadida 2026-06-04,Sidebar.tsx): expone el inbox decandidatos (aprobar/rechazar/editar) y la salud debrain.db; el kernel dememoria sigue siendo solo-backend, pero su gobierno human-in-the-loop se hacedesde esta pestana (ademas de los comandos).
Licencia
MIT — ver LICENSE. Copyright (c) 2026 Rodrigo Fernandez.