ULTRON Control Center
An MCP server that provides persistent, governed memory for Claude Code, enabling local storage and retrieval of decisions, architecture, and context across sessions with audit trails and hybrid semantic recall.
README
<p align="center"> <img src="control-center/src-tauri/icons/128x128@2x.png" width="110" alt="ULTRON"> </p>
<h1 align="center">ULTRON Control Center</h1>
<p align="center"> <strong>Memoria persistente y gobernada para <a href="https://claude.com/claude-code">Claude Code</a></strong> — <em>tu asistente recuerda decisiones, arquitectura y contexto entre sesiones, con auditoria de cada escritura.</em> </p>
<p align="center"> <img alt="version" src="https://img.shields.io/badge/version-2.7.1-6e40c9?style=for-the-badge"> <img alt="memoria" src="https://img.shields.io/badge/memoria-SQLite_+Qdrant-2da44e?style=for-the-badge"> <img alt="recall" src="https://img.shields.io/badge/recall-BM25+E5+_reranker-1f6feb?style=for-the-badge"> <img alt="mcp" src="https://img.shields.io/badge/MCP-server_incluido-d29922?style=for-the-badge"> </p>
<p align="center"> <img alt="stack" src="https://img.shields.io/badge/Tauri_2-React_19-24292f?logo=tauri"> <img alt="backend" src="https://img.shields.io/badge/Rust-2021-f74c00?logo=rust&logoColor=white"> <img alt="plataforma" src="https://img.shields.io/badge/Windows_11-principal-0078d4?logo=windows"> <img alt="licencia" src="https://img.shields.io/badge/MIT-licencia-3fb950"> </p>
¿Que es esto?
Tu asistente de IA olvida todo cada vez que cierras la ventana: las decisiones que tomasteis, los errores que ya resolvisteis, como esta montado tu proyecto. Al dia siguiente se lo vuelves a explicar todo.
ULTRON le da memoria. Mientras trabajas, guarda lo importante en tu propio ordenador; cuando abres una conversacion nueva, se lo recuerda a la IA automaticamente. Tu no haces nada: trabajas como siempre y tu asistente cada vez te conoce mejor. Tu decides que se guarda (todo pasa por una bandeja de aprobacion) y nada sale de tu maquina.
<details> <summary><strong>La version tecnica</strong> (click para abrir)</summary>
Memoria local event-sourced (brain.db, SQLite) con indice semantico (Qdrant +
E5 1024d), reinyectada en cada sesion mediante hooks — recall hibrido sub-segundo
con un daemon residente. Ademas: AI Router multi-proveedor, orquestador de
skills/agentes y cockpit de escritorio (Tauri 2 + React 19). Todo el estado son
ficheros locales inspeccionables. Spec: docs/memory-spec.md.
</details>
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), las diferencias son de diseño, no de marketing: aqui la memoria es 100% local (sin cuenta, sin suscripcion, sin enviar tu codigo a un tercero), gobernada (la IA propone, tu apruebas; cada escritura deja evento de auditoria), honesta (si no sabe, 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 un
oraculo de 29 queries etiquetadas a mano — tu instalacion arranca vacia y las
cifras de recall dependen de tu corpus. Reproducibles con ultron-memory eval --golden y los
scripts 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 de inyectar relleno — la honestidad del recall tambien esta medida (categoria abstain del bench propio).
Quickstart
Sistema completo (app + skills + hooks + memoria semantica) — el camino recomendado; 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 el
plan 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 seccion
Qdrant de docs/INSTALL-ADVANCED.md.
Las rutas per-maquina se documentan en
config/paths.example.toml.
Caracteristicas
- Memoria gobernada —
brain.db(SQLite) como unica fuente de verdad; todo cambio pasa por un unico servicio que anexa un evento de auditoria. - Recall hibrido — denso (E5 1024d / Qdrant) + sparse (FTS5/BM25) fusionados con 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 y telemetria 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 se
editan en Library -> Tones. La config real (
~/.ultron/personality.json) es local 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 memoria persistente y gobernada, enruta peticiones a varios proveedores LLM segun coste y disponibilidad, y detecta automaticamente que skill/agente especialista conviene 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 de
memoria 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 esquema canonico vive enmemory/schema_v3.rs(memoria) +memory/schema_v4.rs(migracion historica v4: tablasedges/unresolved_refs, hoy inertes — el grafo 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 politica de 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 con MultilingualE5Large, 1024 dimensiones (memory/qdrant_index.rs). Es un indice derivado: se puede reconstruir en cualquier momento conreindex_allybrain.dbsigue siendo la verdad. - Tras cada escritura aprobada/editada/restaurada,
sync_indexmantiene Qdrant en paso con la SoT (best-effort; cualquier deriva es detectable/reparable viareconcile). - La coleccion antigua
ultron_sessions(384d BGE) esta retirada; Qdrant aqui es siempre un indice, nunca la verdad.
Recall hibrido denso + sparse con RRF
- El comando unico
recall(commands/memory/recall_unified.rs) fusiona con Reciprocal 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 por fuente, scores, descartes) para el Retrieval Inspector. - El unico camino de recall es el comando unificado
recallcon RRF; las fuentes son Qdrant (denso) + SQLite/FTS5 (sparse). No usa servicios de memoria 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 pocos hechos/decisiones durables; - convierte cada hecho en un
MemoryCandidate(pasando por redaccion + dedupe) y lo deja en el inbox gobernado para aprobacion humana — nunca se auto-promueve a activo.
- pide a un LLM (via
- Fail-safe: si el router no tiene proveedor utilizable, degrada a una heuristica 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, salta proveedores sin clave API utilizable, registra latencia/tokens/ahorro en la telemetria 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 health checks 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 recall unificado y los workflows integrados (agent_orchestration.rs). Nunca escribe memoria 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 de
impacto) lo provee CodeGraph (
@colbymchenry/codegraph, MIT), instalado como 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 de commit / 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 cualquier instancia en marcha; un binario obsoleto es la causa habitual de "no se ha aplicado 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 RRF operativo (degrada a sparse-only sin Qdrant). Write-path con redaccion de secretos y dedupe por content_hash cableados y testeados. - Captura automatica: Stop hook ->
capture_session-> candidatos al inbox gobernado; aprobacion/rechazo humano via comandos de inbox. - AI Router: routing real con cadena primario/fallback, deteccion de claves y telemetria de uso/ahorro; sin sidecar LiteLLM.
- Tonos: deteccion determinista en el orchestrate (paridad JS/Rust del
detector verificada con gate 16/16); editor visual en Library -> Tones y
playground de deteccion.
personality.jsonlocal (gitignored) con seeds publicables compilados; limite duro: el tono solo aplica al chat, jamas a artefactos. - Detector de texto IA: hook PostToolUse que avisa cuando la prosa escrita "canta" a IA + Lab de patrones deterministas sobre el catalogo de 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 Memory esta viva (re-anadida 2026-06-04,Sidebar.tsx): expone el inbox de candidatos (aprobar/rechazar/editar) y la salud debrain.db; el kernel de memoria sigue siendo solo-backend, pero su gobierno human-in-the-loop se hace desde esta pestana (ademas de los comandos).
Licencia
MIT — ver LICENSE. Copyright (c) 2026 Rodrigo Fernandez.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。