Facthouse

Un motor de memoria local que cualquier herramienta de IA puede usar.

Documentación

Facthouse

Facthouse mascot

Facthouse es un motor de memoria local para herramientas de IA. La mayoría de los productos de "memoria" indexan registros de chat. Facthouse toma la actividad del agente (mensajes, uso de herramientas y otro tráfico MCP) y aplica consolidación inspirada en la neurociencia para que avance a través de Datos (lo que sucedió en la sesión) → Información (hechos extraídos) → Conocimiento (creencias integradas en un grafo de entidades). Durante este proceso, Facthouse vincula entidades, elimina duplicados, reconcilia conflictos y reemplaza lo que está desactualizado. Los embeddings vectoriales añaden búsqueda semántica opcional sobre ese grafo. El almacén es un archivo SQLite en tu disco.

npm CI License: MIT

Registra, almacena y recupera conocimiento estructurado. El enrutamiento por dominio, la extracción de entidades, la deduplicación y la sustitución se ejecutan en el servidor. Expuesto como un servidor MCP.

Inicio rápido

Requiere Node 22.5 o 24+.

npm install -g @facthouse/mcp@0.28.1
facthouse init

Si npm install -g falla porque ya existe un comando llamado mcp, elimina ese comando sobrante y reintenta.

facthouse init --web es la misma configuración que un formulario de navegador: imprime una URL 127.0.0.1 y no abre un navegador.

Pulsa Enter para aceptar cada valor predeterminado (copy = registros de sesión de Claude Code o Cursor en disco; elige record si el asistente debe guardar hechos). Si elegiste copy, init pregunta si copiar los registros existentes y luego si extraer e integrar. Init imprime un fragmento MCP: pégalo en el cliente y reinicia.

En el cliente, expresa algo duradero en conversación ordinaria: no hay comando de recordar.

Ese es el almacén. Archivo de transcripción (Claude Code o Cursor): siguiente sección. CLI: abajo.

Cómo entran las conversaciones

Dos formas. Elige una por almacén.

Copiar de transcripcionesEl asistente registra
QuiénClaude Code o Cursor (registros de sesión en disco, bajo el directorio del cliente)Cualquier cliente MCP (Grok, Desktop, …)
CómoNombra una fuente; Facthouse copia nuevas líneas de esos registros al almacénsources vacío; el asistente llama a capture_fact
Primera ejecuciónRecorrido por TTY, elige copy, establece cwd; init pregunta si copiar registros existentes y luego si extraer e integrarRecorrido por TTY, elige record

En un almacén de copia, capture_fact es una corrección para cada cliente MCP, no solo para el que escribe JSONL. Grok no tiene adaptador de transcripción: no pongas Claude Code en copy y Grok en el mismo almacén esperando que Grok registre.

facthouse init

Elige copy, establece cwd. Init pregunta si copiar registros existentes y luego si extraer e integrar (Enter = todas las líneas copiadas). Rechaza extraer para hacerlo más tarde con facthouse consolidate (--all toma todo el trabajo pendiente). Después de eso, el servidor copia nuevas líneas cuando maneja una llamada.

Compacto (opcional): facthouse notify compaction — no es un hook de Stop al final del turno.

Reproducción: facthouse.dev/demo.html.

Lo que obtienes

  • SQLite local. Postgres opcional. El aislamiento es el directorio, no una columna.
  • Grafo de entidades. Personas, organizaciones, proyectos, lugares, productos — extraídos, tipados y vinculados.
  • Búsqueda híbrida. BM25 + dominio estructurado + rutas del grafo de entidades, fusionados mediante Reciprocal Rank Fusion. Un proveedor de embeddings añade significado como cuarta lista; desactivado por defecto.
  • Memoria en sesión. get_session_context es el mismo informe que memory://briefing. Los clientes solo de herramientas deberían llamarlo al inicio de la sesión.
  • Historial inmutable. Los hechos nunca se eliminan, solo se reemplazan.

Cómo funciona

Una base de datos SQLite. Tres tablas en ella, no tres bases de datos:

  • D (session_events) — lo que se dijo (transcripciones copiadas, o lo que el asistente registra)
  • I (session_facts) — lo que se acaba de extraer, o capture_fact
  • K (facts) — conocimiento integrado

FTS5 (palabras) y embeddings opcionales (significado) son índices de K. No son un segundo almacén. La búsqueda semántica está desactivada a menos que la actives: search "shellfish" encuentra un hecho sobre mariscos, search "food" no, hasta que elijas un modelo de embeddings — un modelo es una opinión sobre lo que "similar" significa.

Dos velocidades. Extraer convierte nuevas líneas de transcripción en hechos autocontenidos. Integrar los ajusta a lo que el almacén ya sabe: dominios, entidades, duplicados, contradicciones, el grafo. consolidate ejecuta copia, extracción e integración juntos — en el servidor al inicio de la sesión y en la compactación, o manualmente desde la CLI. La extracción está limitada a 50 líneas por ejecución, así que un primer relleno nunca se gasta en todo; cada ejecución automática extrae hechos de las 50 líneas más antiguas. El servidor MCP copia el registro bruto en una llamada; no extrae entonces. La consolidación no inventa una frase que nadie dijo.

El almacenamiento necesita Node. La inteligencia necesita un modelo de lenguaje. Por defecto es la CLI de Claude Code en tu suscripción existente. Sin ella, la consolidación cae a una heurística integrada que no extrae hechos de transcripciones. capture_fact aún almacena hechos, sin entidades y sin enrutamiento por dominio.

MCP

Funciona con Claude Code, Claude Desktop y cualquier herramienta compatible con MCP. Los datos se almacenan en ~/.facthouse por defecto. Ese único directorio es toda la instalación. Para usar una ruta diferente, añade "env": { "FACTHOUSE_DATA": "/absolute/path" } al fragmento MCP. JSON acepta barras diagonales en Windows. FACTHOUSE_DATA en un fragmento MCP aplica solo a ese proceso de servidor. Un comando facthouse de terminal necesita --data, o FACTHOUSE_DATA en el entorno que esa shell hereda. Los hooks no ven el env de mcp.json.

Cursor consume herramientas pero no recursos hasta que exista un adaptador posterior — search_knowledge y get_entity aún funcionan allí; llama a get_session_context al inicio de la sesión.

Los recursos son contexto que el cliente carga automáticamente — sin llamada de herramienta. Las herramientas solo ayudan si el asistente recuerda usarlas; los recursos simplemente están presentes.

  • memory://briefing — Todo lo que vale la pena saber ahora mismo: perfil, lo aprendido en la última consolidación, hilos abiertos y conocimiento reciente. Markdown, mantenido aproximadamente a una pantalla.
  • memory://profile — Hechos de identidad central, los más importantes primero.

Ambos son vistas de solo lectura sobre la misma base de datos que consultan las herramientas. Los clientes que nunca cargan recursos (Cursor, Windsurf, Grok) obtienen el mismo informe llamando a get_session_context al inicio de una conversación. Sin segundo esquema de perfil.

Herramientas

Sesión

  • log_event — Registra eventos de conversación (mensajes, artefactos).
  • get_events — Recupera eventos de la sesión actual o anterior.
  • get_session_context — Informe de trabajo (el mismo markdown que memory://briefing) más hechos capturados en esta sesión. Llama al inicio de cada conversación si el cliente no carga recursos.

Lectura

  • get_entity — Todo lo conocido sobre cualquier sujeto nombrado — persona, organización, proyecto, lugar, producto — y cómo se conecta. Cuando varias filas comparten el nombre bajo diferentes tipos, los hechos de todas ellas regresan. Guiones, guiones bajos y puntuación suelta cuentan como las mismas letras solo cuando eso no une dos nombres ya almacenados como filas separadas. Si no hay entidad con ese nombre, los hechos que mencionan la redacción aún regresan en lugar de un fallo vacío.
  • get_context — Todo lo relevante para un tema (búsqueda + recorrido de entidades)
  • search_knowledge — Búsqueda híbrida en conocimiento integrado

Escritura

  • capture_fact — Almacena un hecho. En un almacén de copia esto es una corrección para algo que la extracción omitió; en un almacén con sources vacío es cómo entran los hechos. La descripción que ve el asistente se genera desde esa misma regla.
  • consolidate — Integra hechos pendientes en conocimiento a largo plazo. Extrae entidades, resuelve duplicados, detecta contradicciones, construye el grafo de conocimiento.
  • Herramientas de inferencia — Opt-in, desactivadas por defecto (inferences.enabled en config.json). Una hipótesis cita ids de hechos existentes y permanece pendiente hasta que se confirma. Esas herramientas no se registran hasta que actives la puerta. Consolidate nunca inventa una frase que nadie dijo.

Meta

  • get_schemas — Dominios disponibles y estructura
  • get_stats — Conteo de hechos, conteo de entidades, distribución de dominios, trabajo pendiente de extracción, gasto de inteligencia

CLI

El JSON de MCP inicia el servidor vía npx y no necesita instalación global. npm install -g pone facthouse en PATH para init, settings, stats e inspect. La misma CLI sin PATH es npx -y -p "@facthouse/mcp" -- facthouse — fija la versión; cita el paquete para que PowerShell no haga splat. -p y -- detienen que un binario global más antiguo gane. npx -y @facthouse/mcp sin -p / facthouse es el servidor; no lo ejecutes como comando de shell para init, settings o stats. El pegado de MCP inicia el servidor. No pone facthouse en PATH. Para inspeccionar el archivo desde una terminal, ver CLI abajo.

Estos comandos CLI funcionan en bash, zsh y PowerShell. Cita @facthouse/mcp en PowerShell. Las rutas Git Bash /c/... no son PowerShell; usa C:/... y pasa --data en lugar de cd o export. En Git Bash, cita una ruta con barra invertida o escribe C:/... — una \ sin citar es un escape. ~/ se expande en cada plataforma. WSL usa /mnt/c/.... FACTHOUSE_DATA en un fragmento MCP aplica solo a ese proceso de servidor. Un comando facthouse de terminal necesita --data, o FACTHOUSE_DATA en el entorno que esa shell hereda. Los hooks no ven el env de mcp.json.

npm install -g @facthouse/mcp@0.28.1
facthouse init --yes
npx -y -p "@facthouse/mcp@0.28.1" -- facthouse init --yes
npx -y -p "@facthouse/mcp@0.28.1" -- facthouse settings --json
npx -y -p "@facthouse/mcp@0.28.1" -- facthouse stats
npx -y -p "@facthouse/mcp@0.28.1" -- facthouse inspect
TareaUso
Servidor MCP (lo que el cliente inicia)El fragmento JSON: npx con args -y y un @facthouse/mcp@… fijado. Sin instalación global.
facthouse en PATHnpm install -g @facthouse/mcp@… (misma fijación). Actualízalo cuando subas el fragmento.
Cambiar ajustes extra despuésfacthouse settings (o settings --data <dir>). No restablece el archivo.
Un comando CLI, sin PATHnpx -y -p "@facthouse/mcp@…" -- facthouse …

facthouse init [dir]

El recorrido es cómo un humano en primera ejecución escribe config.json. Sáltalo y el servidor aún crea el directorio en el primer arranque MCP.

En una terminal, init pregunta directorio de datos, copiar transcripciones vs registros del asistente (predeterminado copy), búsqueda semántica y Más ajustes. --yes nunca pregunta y deja sources vacío. --web imprime una URL 127.0.0.1 y no abre un navegador; --yes rechaza --web. En una terminal, --force aún hace esas preguntas, luego reemplaza todo el archivo; --yes --force es el restablecimiento silencioso. --force no se fusiona con el archivo anterior.

facthouse init --yes
facthouse init --yes ~/my-memory
facthouse init --yes --force

El config.json generado es donde cambias el comportamiento de consolidación — más notablemente intelligence.provider (cli por defecto; heuristic para un respaldo regex sin dependencias, o FACTHOUSE_PROVIDER=heuristic en tiempo de ejecución). Init no pregunta ese campo.

facthouse settings

Cambia ajustes extra en un config.json existente (modelo CLI, tiempo de espera, extracción local opcional). No restablece el resto del archivo. Rechaza si no hay config.json (este comando no crea un almacén). --json / no una terminal imprime los ajustes actuales y no escribe. --web es los mismos ajustes en una página local (imprime URL, sin auto-apertura).

facthouse settings
facthouse settings --data ~/my-memory

facthouse record

Inserta eventos directamente en la base de datos (sin necesidad de servidor en ejecución). Compatible para demos y para almacenes que no tienen fuente nombrada. No es el predeterminado de Claude Code o Cursor — eso es sources más facthouse consolidate.

# From a hook (reads JSON payload from stdin):
echo '{"hook_event_name":"UserPromptSubmit","prompt":"hello"}' | facthouse record --role user

# With explicit content:
facthouse record --role user --event-type message --content "hello world"

# Options:
#   --role          user | assistant | system | tool (default: user)
#   --event-type    message | tool_call | tool_result | artifact (default: message)
#   --content-type  text | json | image | audio | binary (default: text)
#   --content       Event content (or pipe via stdin)
#   --speaker       Named participant when the transcript has one
#   --session-id    Target session (default: most recent)
#   --data          Data directory (default: ~/.facthouse or FACTHOUSE_DATA)

facthouse consolidate

Copia nuevas líneas de config.sources, extrae hechos candidatos de ellas e integra los hechos pendientes en conocimiento. El único comando que gasta llamadas de modelo:

facthouse consolidate
facthouse consolidate --copy            # copy only; spends nothing
facthouse consolidate --integrate       # pending facts to knowledge; no extract pass
facthouse consolidate --all             # extract the whole backlog now
facthouse consolidate --limit 200       # extract the oldest 200

# Steps — named steps run, in order; none named means all three:
#   -c, --copy       copy new transcript lines into the store
#   -e, --extract    turn new lines into candidate facts (the model call)
#   -i, --integrate  classify, link, dedupe, supersede, embed
# Extract is capped at 50 lines per run so a first backfill is never spent on
# the lot; the run says how many remain. --all lifts the cap, --limit N sets it.
#   --json           print the result object instead of the summary
#   --data           Data directory (default: ~/.facthouse or FACTHOUSE_DATA)

Respeta el proveedor configurado (por defecto claude -p). sources vacío hace que el paso de copia sea un no-op. Establece cwd en la fuente a menos que pretendas copiar cada grupo de proyectos. No ejecutes también hooks record en un almacén con fuentes nombradas.

facthouse notify <moment>

Dile al servidor MCP en ejecución que ocurrió un momento. El servidor decide qué ejecutar y lo hace en segundo plano, por lo que un hook regresa de inmediato:

facthouse notify compaction   # the client window is about to collapse: copy, extract, integrate now
facthouse notify threshold    # events arrived: extract if the threshold is due

# Options:
#   --data     Data directory (default: ~/.facthouse or FACTHOUSE_DATA)

Que no haya un servidor escuchando no es un error: el comando lo indica y sale con código 0, y el siguiente inicio de sesión lo cubre. Esto es lo que llama el hook PreCompact.

facthouse search <query>

facthouse search "coffee"
facthouse search "coffee" --domain preferences
facthouse search "coffee" --json

# Options:
#   --domain   Prioritise a domain. Biases ranking; does not filter
#   --limit    Maximum results (default: 20)
#   --json     Emit the raw search payload
#   --data     Data directory (default: ~/.facthouse or FACTHOUSE_DATA)

--domain sesga la clasificación en lugar de filtrar. Un filtro estricto ocultaría un hecho archivado bajo un casi-sinónimo.

facthouse stats

facthouse stats
facthouse stats --json

Los hechos son inmutables — los hechos superados se conservan — por lo que el recuento actual y el total difieren legítimamente una vez que algo ha sido superado. --json incluye la versión del paquete del binario que responde. El gasto de inteligencia son llamadas, tokens y tiempo transcurrido para extraer / clasificar / entidades / conciliar / superar / resumir, con proveedor y modelo por etapa. Los embeddings no son ese número.

facthouse inspect

Muestra D, I, K, entidades y el grafo. Escribe un archivo HTML local bajo el directorio de datos (no el directorio de trabajo actual). Imprime la ruta. No abre un navegador. El archivo es una exportación de memoria — trátalo como stats --json. La misma página también muestra el gasto de inteligencia (Graph / Spend).

facthouse inspect
facthouse inspect --graph
facthouse inspect --layer k
facthouse inspect --json
facthouse inspect --entity Helios --limit 20 --output ~/inspect.html

--layer health|d|i|k|entities|graph|all imprime tablas en terminal (más recientes primero, con límite). --graph (el predeterminado cuando no hay --layer / --json) escribe inspect.html. --limit es 10 para tablas y 50 para el lienzo. --all dibuja cada nodo — una maraña, explícito. La búsqueda y el filtro por tipo en la página aún pueden alcanzar un nodo que estaba fuera del límite.

Avanzado

Otro almacén

El almacén es este directorio. Los clientes lo comparten usando la misma ruta. Un segundo almacén es un segundo directorio, no una segunda instalación. El nombre predeterminado del servidor MCP es facthouse. Dividir no es un filtro sobre qué cliente escribió la fila. Trabajo y personal es una razón para dividir, no una configuración obligatoria.

Un directorio de datos no predeterminado imprime un nombre de servidor MCP distinto para que dos almacenes puedan compartir un solo mcp.json. Inicializar contra cada directorio adicional imprime ese fragmento. Ejemplo:

{
  "mcpServers": {
    "facthouse-personal": {
      "command": "npx",
      "args": ["-y", "@facthouse/mcp@0.28.1"],
      "env": { "FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-personal" }
    },
    "facthouse-work": {
      "command": "npx",
      "args": ["-y", "@facthouse/mcp@0.28.1"],
      "env": { "FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-work" }
    }
  }
}

Apunta el sources.cwd (o hook --data) de cada almacén solo a ese almacén. Dos directorios no aíslan nada si ambos copian el mismo home. FACTHOUSE_DATA en un fragmento MCP aplica solo a ese proceso de servidor. Un comando facthouse de terminal necesita --data, o FACTHOUSE_DATA en el entorno que hereda esa shell. Los hooks no ven el env de mcp.json.

Postgres (opcional)

SQLite es el predeterminado y no necesita software adicional. Para usar Postgres en su lugar, establece storage.provider a "postgres" en el config.json de ese almacén, o FACTHOUSE_STORAGE=postgres en la entrada MCP, y establece FACTHOUSE_POSTGRES_URL a una URL postgres:// (o postgresql://). La contraseña pertenece al entorno, no a config.json. Si la URL falta o no se puede alcanzar el servidor, Facthouse se detiene; no crea un archivo SQLite.

El directorio de datos sigue siendo la memoria: config.json y el socket del programador viven allí. Las tablas viven en la URL. Dos memorias necesitan dos directorios y dos bases de datos.

Init no pregunta qué motor usar. facthouse init --yes sigue escribiendo sqlite.

Ejemplo — solo marcadores de posición; no pongas una contraseña real en un archivo confirmado:

{
  "mcpServers": {
    "facthouse": {
      "command": "npx",
      "args": ["-y", "@facthouse/mcp@0.28.1"],
      "env": {
        "FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-work",
        "FACTHOUSE_STORAGE": "postgres",
        "FACTHOUSE_POSTGRES_URL": "postgres://USER:PASSWORD@localhost:5432/facthouse"
      }
    }
  }
}

Copiar versus registrar

Elige un mecanismo por almacén.

Recomendado — copiar. Nombra una fuente claude-code o cursor (establece cwd) y ejecuta facthouse consolidate desde la CLI primero. El servidor MCP también copia al inicio de sesión y cuando maneja una llamada. Grok y Codex son adaptadores posteriores. Los valores desconocidos de kind se rechazan.

{
  "sources": [
    {
      "kind": "claude-code",
      "home": "~/.claude",
      "cwd": "C:\\dev\\app"
    }
  ]
}

home es el directorio de configuración del cliente (~/.claude o ~/.cursor — ejemplos de ruta, no descubrimiento adicional). Cursor es "kind": "cursor" y home/projects/*/agent-transcripts/**/*.jsonl solamente — no Composer SQLite. Cursor codifica C:\\dev\\app como c-dev-app (Claude Code usa C--dev-app). Una primera carga inicial de más de 50 líneas toma varias ejecuciones, o una facthouse consolidate --all.

Alternativa — registrar, sin fuentes. Deja sources vacío. Canaliza un payload de hook de cliente hacia facthouse record si tienes uno. MCP log_event / capture_fact siguen funcionando.

No instales hooks de registro en este almacén — ambos escriben las mismas filas. Facthouse no detecta ni reescribe configuraciones de hooks existentes.

Modo solo registro MCP

Para omitir el asistente (solo registro — sin copia de transcripción), pega esto. El servidor crea ~/.facthouse en el primer arranque; no se te hacen esas preguntas.

{
  "mcpServers": {
    "facthouse": {
      "command": "npx",
      "args": ["-y", "@facthouse/mcp@0.28.1"]
    }
  }
}

Hooks (después de la primera consolidación)

mcp.json env no es visible para los hooks. Pasa el mismo --data (o establece FACTHOUSE_DATA en el entorno que el propio cliente hereda). El comando debe invocar la CLI (facthouse), nunca el binario del servidor. npx -y @facthouse/mcp sin -p / facthouse inicia el servidor MCP y cuelga un hook. Fija la versión del paquete, cítala si el hook ejecuta PowerShell, y pon -- antes de facthouse para que un binario más antiguo instalado globalmente en PATH no pueda ganar.

JSON del hook PreCompact
{
  "hooks": {
    "PreCompact": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "npx -y -p @facthouse/mcp@0.28.1 -- facthouse notify compaction --data /absolute/path/to/the-same-store"
          }
        ]
      }
    ]
  }
}

PreCompact notify compaction pide al servidor en ejecución que consolide: copiar las líneas JSONL más nuevas, extraer, integrar. El hook regresa de inmediato; el servidor hace el trabajo. No instalamos un hook Stop de fin de turno. En Windows, la ruta --data es el mismo directorio absoluto que pusiste en FACTHOUSE_DATA (por ejemplo C:\\Users\\alex\\AppData\\Local\\Temp\\facthouse-try).

La copia incremental frecuente intercala conversaciones en la secuencia global: un chat largo abierto se corta entre otros chats. El progreso de extracción es por conversación, por lo que un tiempo de espera agotado en un chat no descarta otro. Reducir extraction.batch_size significa más llamadas de extracción (más posibilidades de tiempo de espera agotado), no un retén general del almacén. facthouse stats informa eventos no extraídos contra esa marca de agua de extracción.

Si el servidor MCP no se inicia, o no lista herramientas, verifica la versión del paquete que el cliente realmente generó. Un facthouse global en PATH puede estar años detrás del pin en este README. Diagnostica con facthouse stats --data <dir> (la CLI imprime si el programador está escuchando) e inspeccionando serverInfo.version desde initialize más tools/list sobre stdio. 0.2.x responde initialize y luego lanza una excepción en tools/list.

Embeddings, modelo, tiempo de espera, bitemporal

Establece embedding.provider en config.json a "ollama" (local, sin clave API) o "voyage" (alojado), ejecuta facthouse consolidate, y search "food" comienza a devolver la alergia. Los hechos se incrustan cuando se consolidan. Voyage aplica un límite de 3 solicitudes/minuto hasta que haya un método de pago en la cuenta.

La búsqueda por significado es un escaneo exacto de los vectores almacenados cuando el conjunto es pequeño. Cuando ese conjunto es grande (32 MiB predeterminados del modelo actual), se usa un índice HNSW de esos vectores en su lugar: en proceso en SQLite, o un sidecar vector de Postgres cuando la extensión está habilitada. Los almacenes pequeños permanecen exactos. Un motor faltante mantiene la búsqueda exacta e imprime una advertencia; Facthouse no instala un addon nativo. embedding.ann es null (auto), false (nunca), o true (forzar cuando el motor lo permite). Esto no activa los embeddings.

intelligence.cli.model y intelligence.cli.timeout_ms son perillas adicionales. La configuración de Más en el primer arranque (Y) puede escribirlas; más tarde, facthouse settings. Init no pregunta intelligence.provider; FACTHOUSE_PROVIDER=heuristic es el interruptor de apagado. El respaldo heurístico no extrae hechos de transcripciones.

El habla de usuario sin nombre de canal se atribuye al propietario del almacén; un nombre para mostrar aún no crea una persona. El respaldo adicional (asentimiento, una observación de herramienta, un hablante diferente que reformula) se registra, no se puntúa, a menos que el almacén establezca pesos de clasificación interlocutor en config.json. El motor no incluye ninguno. Las claves de peso coinciden con la cadena del hablante tal como se almacena, por lo que dos personas con el mismo nombre comparten una clave.

Establece temporal.mode a bitemporal para registrar cuándo el sistema retractó una creencia, para que la búsqueda pueda responder qué creía el almacén en un instante.

Gasto de inteligencia

facthouse stats y get_stats informan llamadas de consolidación facturadas: tokens, tiempo transcurrido y el proveedor más el modelo en cada etapa (extraer, clasificar, entidades, conciliar, superar, resumir). Una ejecución que no informó tokens omite esos campos en lugar de mostrar cero. Los embeddings son una API diferente y no son este número.

El intelligence.token_budget opcional limita la extracción facturada por proveedor en ventanas móviles. Sin establecer es ilimitado. Por encima del límite, consolidar omite la extracción, mantiene la marca de agua y no recurre a la heurística. Las estadísticas e inspect Spend muestran lo usado y lo restante en cada límite, y cuándo el uso más antiguo en esa ventana caduca (resets).

"intelligence": {
  "token_budget": {
    "cli": { "week": "10M" }
  }
}

hour, day, week y month son móviles. Omite una escala para dejarla ilimitada. El espacio restante está en facthouse stats, get_stats e inspect Spend. Establece el límite en el config.json de este almacén — no hay comando de presupuesto.

La inteligencia local opcional es un interruptor diferente de los embeddings. Agrega intelligence.http en un host compatible con OpenAI. El protocolo es POST /v1/chat/completions; solo cambia el puerto:

HostURL típica
Ollamahttp://localhost:11434/v1 (el predeterminado si omites la URL)
LM Studiohttp://localhost:1234/v1
vLLMhttp://localhost:8000/v1
llama.cpphttp://localhost:8080/v1

La cadena del modelo es lo que ese host liste. GET {base_url}/models imprime los nombres. nomic-embed-text es solo de embeddings y no extraerá. Si el host está activo y sirve exactamente un modelo de chat, Facthouse lo usa para esta ejecución y te dice que fijes intelligence.http.model. Si se listan varios modelos de chat, establece ese campo; la extracción no adivinará.

Extraer y resumir usan entonces ese host; conciliar y superar permanecen en la CLI a menos que listes intelligence.stages. Cada etapa puede establecer on-fail a cli, http o none (ver el JSON a continuación). La extracción HTTP predeterminada reintenta en la CLI (cuenta contra el presupuesto de tokens de la CLI). La contradicción predeterminada es none — sin cambio de proveedor. none mantiene la marca de agua de extracción — no cae a la heurística. La configuración de Más en el primer arranque (Y, después de la ruta recomendada) puede establecer el host, el modelo y el on-fail de extracción. Más tarde, facthouse settings fusiona esas perillas en un archivo existente sin restablecerlo. facthouse inspect Spend muestra las mismas perillas y copia JSON; no guarda config.json.

El script en vivo npm run test:http-intelligence ha pasado en qwen2.5vl:7b.

"intelligence": {
  "http": {
    "base_url": "http://localhost:11434/v1",
    "model": "qwen2.5vl:7b"
  },
  "stages": {
    "extract": { "provider": "http", "on_fail": "cli" },
    "summarise": { "provider": "http", "on_fail": "cli" },
    "reconcile": { "provider": "cli", "on_fail": "none" },
    "supersede": { "provider": "cli", "on_fail": "none" }
  }
}

Demo CLI (sin fuente de transcripción)

Almacén desechable, no la ruta de captura para un home real de Claude Code o Cursor. Estas tres líneas se escriben.

export FACTHOUSE_DATA=/tmp/facthouse-demo
om() { npx -y -p "@facthouse/mcp@0.28.1" -- facthouse "$@"; }

om init --yes

om record --role user --content "I prefer dark mode in every editor, and I never want telemetry enabled."
om record --role user --content "I am allergic to shellfish, so avoid seafood restaurants when booking anything."
om record --role user --content "My colleague Robin at Acme is leading the Atlas migration project this quarter."

om consolidate
om search "Atlas"
om stats
$env:FACTHOUSE_DATA = Join-Path $env:TEMP "facthouse-demo"
function om { npx -y -p "@facthouse/mcp@0.28.1" -- facthouse @args }
om init --yes
om record --role user --content "I prefer dark mode in every editor, and I never want telemetry enabled."
om record --role user --content "I am allergic to shellfish, so avoid seafood restaurants when booking anything."
om record --role user --content "My colleague Robin at Acme is leading the Atlas migration project this quarter."
om consolidate
om search "Atlas"
om stats

allergies no es un dominio que Facthouse incluya. El motor no tiene vocabulario incorporado — leyó la conversación y decidió que ese hecho necesitaba un hogar. Un dominio sesga la clasificación en lugar de filtrar. Limpieza: rm -rf /tmp/facthouse-demo (Git Bash / macOS / Linux) o Remove-Item -Recurse -Force $env:TEMP\facthouse-demo (PowerShell).

Integración

Las descripciones de herramientas de Facthouse les dicen a los asistentes cuándo buscar y cuándo vale la pena preparar una corrección. No son cómo las conversaciones de Claude Code entran al almacén — eso es copia desde una fuente nombrada.

Sin configuración

Claude Code o Cursor: nombra una entrada sources (establece cwd) y ejecuta facthouse consolidate desde la CLI primero. El inicio de sesión MCP también copia. capture_fact está ahí si el asistente necesita corregir o agregar algo que la copia más la extracción no producirá.

Los clientes sin adaptador de copia aún dependen de log_event / capture_fact hasta que exista su adaptador.

Puntos de enganche

Punto de engancheCuándoQué llamarPor qué
Inicio de sesiónComienza la conversaciónmemory://profile (automático), search_knowledgeEl asistente sabe quién eres desde el primer mensaje
CorrecciónFalta un hecho duradero en el almacéncapture_factOpcional; las conversaciones de Claude Code ya están en session_events mediante copia
Búsqueda previa a la respuestaAntes de generar una respuestasearch_knowledge, get_contextRespuestas informadas por el conocimiento almacenado
Pre-compactaciónAntes de la compresión de la ventana de contextofacthouse notify compactionEl servidor copia nuevas líneas, extrae, integra
Puntos de ruptura naturalesCambio de tema, finalización de tareaconsolidate (opcional)Mantiene el grafo de conocimiento actualizado

Sobre la pre-compactación: facthouse notify compaction pide al servidor que consolide. No es un enganche de record.

Claude Code

Crea .claude/rules/facthouse.md en tu proyecto (o ~/.claude/rules/facthouse.md globalmente):

# Facthouse

- Conversations are copied from the named Claude Code source (first backfill: `facthouse consolidate` on the CLI)
- Do not install record hooks on this store
- Identity context loads automatically from the `memory://profile` resource — no tool call needed
- Before answering questions this store might already know, call `search_knowledge`
- Call `capture_fact` only to correct or add something that is not in the transcript
- When the conversation is getting long, call `consolidate` (or rely on PreCompact `facthouse notify compaction`)
- At natural breakpoints (topic change, task completion), call `consolidate` to keep the knowledge graph current

Para permitir las herramientas de Facthouse sin solicitudes de aprobación por llamada, añade al array permissions.allow en .claude/settings.json:

{
  "permissions": {
    "allow": [
      "mcp__facthouse__*"
    ]
  }
}

Cursor / Windsurf

Añade a .cursorrules (Cursor) o .windsurfrules (Windsurf) en la raíz de tu proyecto:

When the facthouse MCP server is available:
- Before answering questions this store might already know, call search_knowledge
- To find out everything known about a particular person, project, or thing, call get_entity
- Call capture_fact only to correct or add something copy or extraction missed
- When context is getting long, call consolidate to process pending facts before they are lost

Cursor y Windsurf consumen herramientas pero no recursos, por lo que memory://profile no se cargará por sí solo allí. Las conversaciones de Cursor se copian con kind: "cursor" (JSONL bajo ~/.cursor/projects/, no el almacén de compositor SQLite).

Claude Desktop / otros clientes MCP

Aún no hay adaptador de copia. Las descripciones de herramientas manejan la búsqueda y el capture_fact opcional; las conversaciones no se rastrean hasta que exista un adaptador posterior.

Recuperando espacio

Facthouse registra la conversación cruda y la salida de herramientas en session_events. En un almacén conectado a un cliente agéntico, esto se convierte en casi toda la base de datos. Un almacén medido en uso diario contenía 47,000 eventos y 493 MB frente a 21 hechos integrados.

facthouse stats informa la capa cruda junto con el conocimiento, incluyendo cuánto es recuperable. Para recuperarlo:

facthouse prune                    # report only — nothing is deleted
facthouse prune --apply --vacuum   # delete, then rebuild the file

Establece retention.disk_budget en config.json a un tamaño como "2GB" para limitar memory.db. Sin establecer, es ilimitado; init no escribe un límite. Cuando hay un límite y el archivo está lleno, los eventos crudos inalcanzables se podan automáticamente para que los nuevos registros puedan reutilizar ese espacio; si no queda nada sin usar, se rechazan más eventos crudos. Los hechos nunca se eliminan para cumplir el número. Compactar (--vacuum) sigue siendo un paso humano: copia todo el archivo para que el sistema operativo vea el tamaño más pequeño.

Si la mayor parte de ese volumen es salida de herramientas que consideras ruido, extraction.event_types y extraction.roles restringen lo que se examina, y extraction.min_content_length omite eventos triviales. Mide antes de actuar. Volumen y valor no son el mismo eje.

La regla es la alcanzabilidad, no la antigüedad. Un evento se elimina solo cuando se cumplen las tres condiciones:

  1. La extracción ya lo ha leído. Cualquier cosa por delante de la marca de agua de consolidación sigue siendo entrada.
  2. Ningún hecho cita su procedencia.
  3. Ha quedado fuera de los eventos extraction.working_memory_size más recientes de su propia sesión: un margen para que la consolidación aún pueda echar un vistazo a las notas crudas recientes. Esa ventana es evidencia del tema actual, no un diccionario de pronombres.

Ningún hecho, entidad, incrustación o resultado de búsqueda se ve afectado. Eliminar filas no reduce el archivo por sí solo: eso es --vacuum. Sin un límite, nada se poda automáticamente.

Desarrollo

git clone https://github.com/gordonkjlee/facthouse
cd facthouse
npm install
npm run build
npm test

npm test siempre ejecuta pipelines herméticos (JSONL de fixture → copia → extracción → búsqueda) con un extractor de grabación, y omite evaluaciones en vivo que necesitan un modelo real:

  • El recuerdo semántico necesita Ollama con nomic-embed-text. Inícialo, luego npm run test:semantic.
  • La evaluación en vivo del primer hecho necesita el CLI claude. Ejecuta npm run test:first-fact.
  • La evaluación en vivo del almacén de codificación (transcripciones de Cursor con forma de almacén) también necesita el CLI claude. Ejecuta npm run test:coding-store.
  • La extracción HTTP local necesita un modelo de chat en un host compatible con OpenAI y FACTHOUSE_HTTP_MODEL (verificado en qwen2.5vl:7b). Ejecuta npm run test:http-intelligence.

Cada uno de esos scripts falla en lugar de omitirse cuando falta su dependencia, así que una ejecución en verde significa que la afirmación se verificó realmente en lugar de pasarse por alto silenciosamente.

Contribuir

Las incidencias y solicitudes de extracción son bienvenidas. Abre una incidencia primero si el cambio es más que una errata.

Licencia

MIT