FactMem
A local memory engine any AI tool can use. You own the SQLite file. Install with `npx -y @factmem/mcp`.
Documentação
Facthouse
Facthouse é um mecanismo de memória local para ferramentas de IA. A maioria dos produtos de "memória" indexa logs de conversas. O Facthouse pega a atividade do agente — mensagens, uso de ferramentas e outros tráfegos MCP — e aplica consolidação inspirada em neurociência para que ela avance por Dados (o que aconteceu na sessão) → Informações (fatos extraídos) → Conhecimento (crenças integradas em um grafo de entidades). Durante esse processo, o Facthouse vincula entidades, remove duplicatas, reconcilia conflitos e substitui o que está desatualizado. Embeddings vetoriais adicionam busca semântica opcional sobre esse grafo. O armazenamento é um arquivo SQLite no seu disco.
Início Rápido
Requer Node 22.5 ou 24+.
npx -y @facthouse/mcp
facthouse init
facthouse init --web é a mesma configuração de um formulário de navegador — ele imprime uma URL 127.0.0.1 e não abre um navegador.
Pressione Enter para aceitar cada padrão (copy = logs de sessão do Claude Code ou Cursor no disco; type record se o assistente deve salvar fatos). Se você escolheu copy, o init pergunta se deseja copiar logs existentes e depois se deseja extrair e integrar. O init imprime um trecho MCP assim que o armazenamento é gravado — adicione-o à configuração MCP do cliente enquanto copy/extract são executados. Reinicie o cliente quando o init terminar.
No cliente, declare algo duradouro em conversa comum — não há comando de lembrar.
Pergunte novamente na próxima sessão, ou facthouse search. Esse é o armazenamento.
Copie dos logs do Claude Code ou Cursor, ou grave de qualquer cliente MCP: Como as conversas entram. Replay: facthouse.dev/demo.html. CLI: abaixo.
O que você obtém
- SQLite local. Postgres opcional. O isolamento é o diretório, não uma coluna.
- Grafo de entidades. Pessoas, organizações, projetos, lugares, produtos — extraídos, tipados e vinculados.
- Busca híbrida. BM25 + domínio estruturado + caminhos de grafo de entidades, mesclados via Fusão de Classificação Recíproca. Um provedor de embeddings adiciona significado como uma quarta lista; desativado por padrão.
- Memória na sessão.
get_session_contexté o mesmo briefing quememory://briefing. Clientes somente com ferramentas devem chamá-lo no início da sessão. - Histórico imutável. Fatos nunca são excluídos, apenas substituídos.
Como funciona
Um banco de dados SQLite. Três tabelas nele, não três bancos de dados: Dados (o que aconteceu na sessão) → Informações (fatos extraídos) → Conhecimento (crenças integradas).
- D (
session_events) — o que foi dito (transcrições copiadas, ou o que o assistente grava) - I (
session_facts) — o que foi extraído, oucapture_fact - K (
facts) — conhecimento integrado
FTS5 (palavras) e embeddings opcionais (significado) são índices de K. Eles não são um segundo armazenamento. A busca semântica está desativada, a menos que você a ative: search "shellfish" encontra um fato sobre mariscos, search "food" não, até você escolher um modelo de embedding — um modelo é uma opinião sobre o que "semelhante" significa.
Duas velocidades. Copy segue transcrições nomeadas para Dados. Extract transforma novas linhas de transcrição em fatos autocontidos (D→I). Integrate os ajusta ao que o armazenamento já sabe: domínios, entidades, duplicatas, contradições, o grafo (I→K). consolidate é o guarda-chuva: copy, extract e integrate juntos. Extract é limitado a 50 linhas por execução, então um primeiro backfill nunca é gasto de uma vez; quando extract é executado, ele pega as 50 linhas mais antigas. A consolidação não inventa uma frase que ninguém disse.
Um hook não pode chamar ferramentas MCP — elas existem apenas na conexão do assistente — e não deve esperar por uma passagem de modelo. Portanto, ele não invoca consolidate. Ele executa facthouse notify …, que informa ao servidor já em execução que um momento aconteceu e retorna imediatamente. consolidate é o verbo do pipeline (ferramenta MCP ou CLI); o chamador espera. notify compaction é esse verbo solicitado ao servidor ativo, de forma assíncrona. notify threshold é uma política diferente (somente extract, se devido).
Automático
| Quando | Copy | Extract (D→I) | Integrate (I→K) |
|---|---|---|---|
| O servidor MCP Facthouse inicia | sim | sim (limite 50) | sim |
| Uma ferramenta ou recurso Facthouse é chamado | sim, se fontes nomeadas e JSONL cresceu | não | não |
| O processo MCP Facthouse sai | não | não | sim |
Chamável
| Chamada | De | Copy | Extract (D→I) | Integrate (I→K) |
|---|---|---|---|---|
consolidate | Ferramenta MCP ou CLI. O chamador espera. | sim | sim (limite 50) | sim |
facthouse notify compaction | Outro processo (recomendado PreCompact; não instalamos). Não espera. | sim | sim (limite 50) | sim |
facthouse notify threshold | Outro processo. Não espera. Não é um hook de copy-store. | não | sim, se devido (limite 50) | não |
Em um copy store padrão sem hooks extras, apenas a tabela automática é executada: Facthouse inicia (todos os três), copy em cada chamada de ferramenta ou recurso Facthouse se fontes nomeadas cresceram, e integrate em uma saída limpa do processo. Fechar uma janela de chat pode pular a linha de saída; o próximo início ainda consolida. Devido no limite significa pelo menos 10 linhas não examinadas e dois minutos desde a última execução controlada. consolidate --all remove o limite de extract. A compactação é recomendada PreCompact (notify compaction): os mesmos três passos que consolidate, no servidor em execução, sem esperar. Não instalamos o hook. Não é um hook Stop. record ativa extract por limite em um record store — não instale hooks de record em um copy store.
Armazenamento precisa de Node. Inteligência precisa de um modelo de linguagem. Por padrão, é o Claude Code CLI na sua assinatura existente. Sem ele, a consolidação recorre a uma heurística embutida que não extrai fatos de transcrições. capture_fact ainda armazena fatos, sem entidades e sem roteamento de domínio.
Como as conversas entram
Duas maneiras. Escolha uma por armazenamento.
| Copiar de transcrições | O assistente grava | |
|---|---|---|
| Quem | Claude Code ou Cursor (logs de sessão no disco, sob o home do cliente) | Qualquer cliente MCP (Grok, Desktop, …) |
| Como | Nomeie uma fonte; Facthouse copia novas linhas desses logs para o armazenamento | sources vazio; o assistente chama capture_fact |
| Primeira execução | Passo a passo no TTY, escolha copy, defina cwd; init pergunta se deseja copiar logs existentes e depois se deseja extrair e integrar | Passo a passo no TTY, escolha record |
Em um copy store, capture_fact é uma correção para todo cliente MCP, não apenas para aquele que escreve JSONL. Grok não tem adaptador de transcrição — não coloque Claude Code em copy e Grok no mesmo armazenamento esperando que Grok grave.
facthouse init
Escolha copy, defina cwd. O init pergunta se deseja copiar logs existentes e depois se deseja extrair e integrar (Enter = todas as linhas copiadas; uma seleção de 500 ou mais pede que você digite a escolha novamente). Recuse extract para fazer isso depois com facthouse consolidate (--all pega linhas não examinadas restantes, não aquelas puladas como fora de uma janela de 7 dias ou 30 dias). Depois disso, o servidor copia novas linhas quando lida com uma chamada Facthouse. Extract e integrate seguem a tabela em Como funciona.
Compact (recomendado): facthouse notify compaction — não instalamos o hook. Não é um hook Stop de fim de turno.
MCP
Funciona com qualquer ferramenta compatível com MCP. Armazenamento padrão: ~/.facthouse. Um caminho diferente é "env": { "FACTHOUSE_DATA": "/absolute/path" } no trecho MCP. JSON aceita barras normais no Windows.
Cursor consome ferramentas, mas não recursos, até que um adaptador posterior exista — search_knowledge e get_entity ainda funcionam lá; chame get_session_context no início da sessão.
Recursos são contexto que o cliente carrega automaticamente — sem chamada de ferramenta. Ferramentas só ajudam se o assistente lembrar de usá-las; recursos estão simplesmente presentes.
memory://briefing— Tudo que vale a pena saber agora: perfil, o que foi aprendido na última consolidação, tópicos abertos e conhecimento recente. Markdown, mantido em aproximadamente uma tela.memory://profile— Fatos centrais de identidade, mais importantes primeiro.
Ambos são visualizações somente leitura sobre o mesmo banco de dados que as ferramentas consultam. Clientes que nunca carregam recursos (Cursor, Windsurf, Grok) recebem o mesmo briefing chamando get_session_context no início de uma conversa. Sem segundo esquema de perfil.
Ferramentas
Sessão
log_event— Registra eventos de conversa (mensagens, artefatos).get_events— Recupera eventos da sessão atual ou anterior.get_session_context— Briefing de trabalho (o mesmo markdown quememory://briefing) mais fatos capturados nesta sessão. Chame no início de toda conversa se o cliente não carrega recursos.
Leitura
get_entity— Tudo conhecido sobre qualquer assunto nomeado — pessoa, organização, projeto, lugar, produto — e como ele se conecta. Quando várias linhas compartilham o nome sob tipos diferentes, fatos de todas elas retornam. Hífens, sublinhados e pontuação solta contam como as mesmas letras apenas quando isso não une dois nomes já armazenados como linhas separadas. Se não há entidade com esse nome, fatos que mencionam a redação ainda retornam em vez de um erro vazio.get_context— Tudo relevante para um tópico (busca + travessia de entidades)search_knowledge— Busca híbrida no conhecimento integrado
Escrita
capture_fact— Armazena um fato. Em um copy store, isso é uma correção para algo que a extração perdeu; em um armazenamento comsourcesvazio, é assim que fatos entram. A descrição que o assistente vê é gerada a partir dessa mesma regra.consolidate— Integra fatos pendentes no conhecimento de longo prazo. Extrai entidades, resolve duplicatas, detecta contradições, constrói o grafo de conhecimento.- Ferramentas de inferência — Opt-in, desativadas por padrão (
inferences.enabledem config.json). Uma hipótese cita ids de fatos existentes e permanece pendente até ser confirmada. Essas ferramentas não são registradas até você ativar o portão. Consolidate nunca inventa uma frase que ninguém disse.
Meta
get_schemas— Domínios e estrutura disponíveisget_stats— Contagem de fatos, contagem de entidades, distribuição de domínios, backlog de extração, gasto de inteligência
CLI
O JSON MCP inicia o servidor via npx e não precisa de instalação global. npm install -g coloca facthouse no PATH para init, settings, stats e inspect. O mesmo CLI sem PATH é npx -y -p "@facthouse/mcp" -- facthouse — fixe a versão; cite o pacote para o PowerShell não dividir. -p e -- impedem que um binário global antigo vença. npx -y @facthouse/mcp sem -p / facthouse é o servidor; não o execute como comando de shell para init, settings ou stats. O colar MCP inicia o servidor. Ele não coloca facthouse no PATH. Para inspecionar o arquivo de um terminal, veja CLI abaixo.
Esses comandos CLI funcionam em bash, zsh e PowerShell. Cite @facthouse/mcp no PowerShell. Caminhos Git Bash /c/... não são PowerShell; use C:/... e passe --data em vez de cd ou export. No Git Bash, cite um caminho com barra invertida ou escreva C:/... — \ sem aspas é um escape. ~/ é expandido em todas as plataformas. WSL usa /mnt/c/.... FACTHOUSE_DATA em um trecho MCP aplica-se apenas àquele processo de servidor. Um comando facthouse de terminal precisa de --data, FACTHOUSE_DATA no ambiente que o shell herda, ou um armazenamento .facthouse neste projeto. Hooks não veem env de mcp.json.
npm install -g @facthouse/mcp@0.31.0
facthouse init --yes
Se npm install -g falhar porque um comando chamado mcp já existe, remova esse comando remanescente e tente novamente.
npx -y -p "@facthouse/mcp@0.31.0" -- facthouse init --yes
npx -y -p "@facthouse/mcp@0.31.0" -- facthouse settings --json
npx -y -p "@facthouse/mcp@0.31.0" -- facthouse stats
npx -y -p "@facthouse/mcp@0.31.0" -- facthouse inspect
| Tarefa | Uso |
|---|---|
| Servidor MCP (o que o cliente inicia) | O trecho JSON: npx com args -y e uma versão fixada @facthouse/mcp@…. Sem instalação global. |
facthouse no PATH | npm install -g @facthouse/mcp@… (mesma fixação). Atualize-o quando você aumentar o trecho. |
| Alterar ajustes extras depois | facthouse settings (ou settings --data <dir>). Não redefine o arquivo. |
| Um comando CLI, sem PATH | npx -y -p "@facthouse/mcp@…" -- facthouse … |
facthouse init [dir]
O passo a passo é como um humano na primeira execução escreve config.json. Pule-o e o servidor ainda cria o diretório no primeiro boot MCP.
No terminal, o init pergunta o diretório de dados, copiar transcrições vs registros do assistente (padrão: copiar), busca semântica e configurações adicionais. --yes nunca pergunta e deixa sources vazio. --web imprime uma URL 127.0.0.1 e não abre o navegador; --yes recusa --web. No terminal, --force ainda faz essas perguntas e depois substitui o arquivo inteiro; --yes --force é o reset silencioso. --force não faz merge com o arquivo anterior.
facthouse init --yes
facthouse init --yes ~/my-memory
facthouse init --yes --force
O config.json gerado é onde você altera o comportamento de consolidação — principalmente intelligence.provider (cli por padrão; heuristic para um fallback de regex sem dependências, ou FACTHOUSE_PROVIDER=heuristic em tempo de execução). O init não pergunta esse campo.
facthouse settings
Altera opções extras em um config.json existente (modelo CLI, timeout, extração local opcional). Não redefine o restante do arquivo. Recusa se não houver config.json (este comando não cria um store). --json / não-terminal imprime os ajustes atuais e não grava. --web são os mesmos ajustes em uma página local (imprime URL, sem abrir automaticamente).
facthouse settings
facthouse settings --data ~/my-memory
facthouse record
Insere eventos diretamente no banco de dados (sem precisar de servidor em execução). Suportado para demonstrações e para stores sem fonte nomeada. Não é o padrão do Claude Code ou Cursor — esse é sources mais 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_DATA, a .facthouse store in this project, or ~/.facthouse)
facthouse consolidate
Copia novas linhas de config.sources, extrai fatos candidatos delas e integra os fatos pendentes ao conhecimento. O único comando que gasta chamadas 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_DATA, a .facthouse store in this project, or ~/.facthouse)
Respeita o provedor configurado (por padrão claude -p). sources vazio faz a etapa de cópia virar um no-op. Defina cwd na fonte, a menos que você pretenda copiar todos os grupos de projeto. Não execute também hooks record em um store com fontes nomeadas.
facthouse notify <moment>
Diz ao servidor MCP em execução que um momento aconteceu. O servidor decide o que executar e faz isso em segundo plano, então um hook retorna imediatamente:
facthouse notify compaction # client about to compact: copy new JSONL, extract, integrate (does not wait)
facthouse notify threshold # events arrived: extract if the threshold is due
# Options:
# --data Data directory (default: FACTHOUSE_DATA, a .facthouse store in this project, or ~/.facthouse)
Nenhum servidor ouvindo não é erro: o comando informa isso e sai com código 0, e o próximo início de sessão cobre isso. É isso que o hook PreCompact chama.
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_DATA, a .facthouse store in this project, or ~/.facthouse)
--domain enviesa a classificação em vez de filtrar. Um filtro rígido esconderia um fato arquivado sob um quase-sinônimo.
facthouse stats
facthouse stats
facthouse stats --json
Fatos são imutáveis — fatos substituídos são mantidos — então a contagem atual e o total legitimamente diferem depois que algo é substituído. --json inclui a versão do pacote do binário que responde. Gasto de inteligência são chamadas, tokens e tempo decorrido para extrair / classificar / entidades / reconciliar / substituir / resumir, com provedor e modelo por etapa. Embeddings não são esse número.
facthouse inspect
Amostra D, I, K, entidades e o grafo. Grava um arquivo HTML local no diretório de dados (não no diretório de trabalho atual). Imprime o caminho. Não abre o navegador. O arquivo é uma exportação de memória — trate-o como stats --json. A mesma página também mostra o gasto de inteligência (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 tabelas no terminal (mais recentes primeiro, limitadas). --graph (o padrão quando não há --layer / --json) grava inspect.html. --limit é 10 para tabelas e 50 para o canvas. --all desenha todos os nós — um emaranhado, explícito. Busca e filtro por tipo na página ainda podem alcançar um nó que ficou fora do limite.
Avançado
Outro store
O store é este diretório. Clientes o compartilham usando o mesmo caminho. Um segundo store é um segundo diretório, não uma segunda instalação. O nome padrão do servidor MCP é facthouse. Dividir não é um filtro sobre qual cliente gravou a linha. Trabalho e pessoal é um motivo para dividir, não uma configuração obrigatória.
Um diretório de dados não padrão imprime um nome de servidor MCP distinto para que dois stores possam compartilhar um mcp.json. O init contra cada diretório extra imprime esse trecho. Exemplo:
{
"mcpServers": {
"facthouse-personal": {
"command": "npx",
"args": ["-y", "@facthouse/mcp@0.31.0"],
"env": { "FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-personal" }
},
"facthouse-work": {
"command": "npx",
"args": ["-y", "@facthouse/mcp@0.31.0"],
"env": { "FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-work" }
}
}
}
Aponte o sources.cwd de cada store (ou hook --data) apenas para aquele store. Dois diretórios não isolam nada se ambos copiarem o mesmo home.
Postgres (opcional)
SQLite é o padrão e não precisa de software extra. Para usar Postgres, defina storage.provider como "postgres" no config.json daquele store, ou FACTHOUSE_STORAGE=postgres na entrada MCP, e defina FACTHOUSE_POSTGRES_URL para uma URL postgres:// (ou postgresql://). A senha pertence ao ambiente, não ao config.json. Se a URL estiver ausente ou o servidor não puder ser alcançado, o Facthouse para; ele não cria um arquivo SQLite.
O diretório de dados ainda é a memória: config.json e o socket do agendador ficam lá. As tabelas ficam na URL. Duas memórias precisam de dois diretórios e dois bancos de dados.
O init não pergunta qual mecanismo usar. facthouse init --yes ainda grava sqlite.
Exemplo — apenas placeholders; não coloque uma senha real em um arquivo versionado:
{
"mcpServers": {
"facthouse": {
"command": "npx",
"args": ["-y", "@facthouse/mcp@0.31.0"],
"env": {
"FACTHOUSE_DATA": "C:\\Users\\alex\\.facthouse-work",
"FACTHOUSE_STORAGE": "postgres",
"FACTHOUSE_POSTGRES_URL": "postgres://USER:PASSWORD@localhost:5432/facthouse"
}
}
}
}
Copiar versus registrar
Escolha um mecanismo por store.
Recomendado — copiar. Nomeie uma fonte claude-code ou cursor (defina cwd) e execute facthouse consolidate pela CLI primeiro. O servidor MCP também copia no início da sessão e ao lidar com uma chamada. Grok e Codex são adaptadores posteriores. Valores kind desconhecidos são rejeitados.
{
"sources": [
{
"kind": "claude-code",
"home": "~/.claude",
"cwd": "C:\\dev\\app"
}
]
}
home é o diretório de configuração do cliente (~/.claude ou ~/.cursor — exemplos de caminho, não descoberta extra). Cursor é "kind": "cursor" e home/projects/*/agent-transcripts/**/*.jsonl apenas — não Composer SQLite. Cursor codifica C:\\dev\\app como c-dev-app (Claude Code usa C--dev-app). Um primeiro backfill de mais de 50 linhas leva várias execuções, ou um único facthouse consolidate --all.
Alternativa — registrar, sem fontes. Deixe sources vazio. Envie um payload de hook do cliente para facthouse record se você tiver um. MCP log_event / capture_fact continuam funcionando.
Não instale hooks de registro neste store — ambos gravam as mesmas linhas. O Facthouse não detecta nem reescreve configurações de hook existentes.
Modo de registro somente MCP
Para pular o assistente (somente registro — sem cópia de transcrição), cole isto. O servidor cria ~/.facthouse no primeiro boot; você não é questionado sobre essas perguntas.
{
"mcpServers": {
"facthouse": {
"command": "npx",
"args": ["-y", "@facthouse/mcp@0.31.0"]
}
}
}
Hooks
PreCompact notify compaction é o útil: quando o cliente está prestes a compactar, um hook de curta duração informa o servidor em execução, e o hook retorna imediatamente. O servidor copia novas linhas JSONL, depois extrai e integra — a compactação não exclui a transcrição, e o hook não fotocopia a janela ativa. O init imprime este JSON com --data preenchido. Cole no .claude/settings.json do Claude Code (usuário ou projeto). Não o instalamos. Não instale um hook Stop. Não instale hooks de registro neste store — ambos gravam as mesmas linhas.
mcp.json env não é visível para hooks. Passe o mesmo --data (ou defina FACTHOUSE_DATA no ambiente que o próprio cliente herda). O comando deve invocar a CLI (facthouse), nunca o binário do servidor. npx -y @facthouse/mcp sem -p / facthouse inicia o servidor MCP e trava um hook. Fixe a versão do pacote, cite-a se o hook executar PowerShell e coloque -- antes de facthouse para que um binário global mais antigo no PATH não possa vencer.
JSON do hook PreCompact
{
"hooks": {
"PreCompact": [
{
"hooks": [
{
"type": "command",
"command": "npx -y -p @facthouse/mcp@0.31.0 -- facthouse notify compaction --data /absolute/path/to/the-same-store"
}
]
}
]
}
}
PreCompact notify compaction pede ao servidor em execução para consolidar: copiar as linhas JSONL mais recentes, extrair, integrar. O hook retorna imediatamente; o servidor faz o trabalho. Não instalamos um hook Stop de fim de turno. No Windows, o caminho --data é o mesmo diretório absoluto que você colocou em FACTHOUSE_DATA (por exemplo, C:\\Users\\alex\\AppData\\Local\\Temp\\facthouse-try).
Cópias incrementais frequentes intercalam conversas na sequência global: um chat longo mantido aberto é fatiado entre outros chats. O progresso da extração é por conversa, então um timeout em um chat não descarta outro. Reduzir extraction.batch_size significa mais chamadas de extração (mais chances de timeout), não um retém-tudo no store. facthouse stats relata eventos não extraídos contra esse watermark de extração.
Se o servidor MCP não iniciar, ou listar nenhuma ferramenta, verifique a versão do pacote que o cliente realmente iniciou. Um facthouse global no PATH pode estar anos atrás do pin neste README. Diagnostique com facthouse stats --data <dir> (a CLI imprime se o agendador está ouvindo) e inspecionando serverInfo.version de initialize mais tools/list via stdio. 0.2.x responde initialize e então lança erro em tools/list.
Embeddings, modelo, timeout, bitemporal
Defina embedding.provider em config.json como "ollama" (local, sem chave de API) ou "voyage" (hospedado), execute facthouse consolidate, e search "food" começa a retornar a alergia. Fatos são embedados quando são consolidados. Voyage aplica um limite de 3 solicitações/minuto até que um método de pagamento esteja na conta.
A busca por significado é uma varredura exata dos vetores armazenados quando o conjunto é pequeno. Quando esse conjunto é grande (padrão de 32 MiB do modelo atual), um índice HNSW desses vetores é usado: em processo no SQLite, ou um sidecar Postgres vector quando a extensão está habilitada. Stores pequenos permanecem exatos. Um mecanismo ausente mantém a busca exata e imprime um aviso; o Facthouse não instala um addon nativo. embedding.ann é null (auto), false (nunca) ou true (forçar quando o mecanismo permite). Isso não ativa embeddings.
intelligence.cli.model e intelligence.cli.timeout_ms são ajustes extras. Configurações adicionais de primeira execução (Y) podem gravá-los; depois, facthouse settings. O init não pergunta intelligence.provider; FACTHOUSE_PROVIDER=heuristic é o kill-switch. O fallback heurístico não extrai fatos de transcrições.
Fala de canal sem nome de usuário é atribuída ao dono do store; um nome de exibição ainda não cria uma pessoa. Apoio extra (assentimento, observação de ferramenta, outro falante reformulando) é registrado, não pontuado, a menos que o store defina pesos de classificação interlocutor em config.json. O mecanismo não traz nenhum. As chaves de peso correspondem à string do falante como armazenada, então duas pessoas com o mesmo nome compartilham uma chave.
Defina temporal.mode como bitemporal para registrar quando o sistema retratou uma crença, para que a busca possa responder o que o store acreditava em um instante.
Gasto de inteligência
facthouse stats e get_stats relatam chamadas de consolidação cobradas: tokens, tempo decorrido e o provedor mais modelo em cada etapa (extrair, classificar, entidades, reconciliar, substituir, resumir). Uma execução que não relatou tokens omite esses campos em vez de mostrar zero. Embeddings são uma API diferente e não são esse número.
intelligence.token_budget opcional limita a extração cobrada por provedor em janelas contínuas. Não definido é ilimitado. Acima do limite, a consolidação pula a extração, mantém o watermark e não cai no fallback heurístico. Stats e inspect Spend mostram usado e restante em cada limite, e quando o uso mais antigo naquela janela expira (resets).
"intelligence": {
"token_budget": {
"cli": { "week": "10M" }
}
}
hour, day, week e month são contínuos. Omita uma escala para deixá-la ilimitada. O espaço restante está em facthouse stats, get_stats e inspect Spend. Defina o limite no config.json deste store — não há comando de orçamento.
Inteligência local opcional é um interruptor diferente de embeddings. Adicione intelligence.http em um host compatível com OpenAI. O protocolo é POST /v1/chat/completions; apenas a porta muda:
| Host | URL típica |
|---|---|
| Ollama | http://localhost:11434/v1 (o padrão se você omitir a URL) |
| LM Studio | http://localhost:1234/v1 |
| vLLM | http://localhost:8000/v1 |
| llama.cpp | http://localhost:8080/v1 |
A string do modelo é o que esse host lista. GET {base_url}/models imprime os nomes. nomic-embed-text é somente para incorporação e não fará extração. Se o host estiver ativo e servir exatamente um modelo de chat, o Facthouse o usa para esta execução e informa para fixar intelligence.http.model. Se vários modelos de chat forem listados, defina esse campo; a extração não fará suposições.
Extraia e resuma, depois use esse host; reconciliação e substituição permanecem na CLI, a menos que você liste intelligence.stages. Cada etapa pode definir on-fail como cli, http ou none (veja o JSON abaixo). A extração HTTP por padrão tenta novamente na CLI (conta contra o orçamento de token da CLI). A contradição por padrão é none — sem troca de provedor. none mantém o watermark de extração — não cai para a heurística. As configurações de primeira execução (Y, após o caminho recomendado) podem definir o host, o modelo e o on-fail de extração. Depois, facthouse settings mescla esses controles em um arquivo existente sem redefini-lo. facthouse inspect Spend mostra os mesmos controles e copia JSON; não salva config.json.
O script ao vivo npm run test:http-intelligence passou em 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" }
}
}
Demonstração da CLI (sem fonte de transcrição)
Armazenamento descartável, não o caminho de captura para um home real de Claude Code ou Cursor. Estas três linhas são digitadas.
export FACTHOUSE_DATA=/tmp/facthouse-demo
om() { npx -y -p "@facthouse/mcp@0.31.0" -- 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.31.0" -- 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 não é um domínio que o Facthouse fornece. O mecanismo não tem vocabulário embutido — ele leu a conversa e decidiu que esse fato precisava de um lar. Um domínio enviesa a classificação em vez de filtrar. Limpeza: rm -rf /tmp/facthouse-demo (Git Bash / macOS / Linux) ou Remove-Item -Recurse -Force $env:TEMP\facthouse-demo (PowerShell).
Integração
As descrições de ferramentas do Facthouse informam aos assistentes quando pesquisar e quando uma correção vale a pena ser encenada. Elas não são como as conversas do Claude Code entram no armazenamento — isso é cópia de uma fonte nomeada.
Sem configuração
Claude Code ou Cursor: nomeie uma entrada sources (defina cwd) e execute facthouse consolidate pela CLI primeiro. O início da sessão MCP também copia. capture_fact está lá se o assistente precisar corrigir ou adicionar algo que a cópia mais extração não produzirá.
Clientes sem adaptador de cópia ainda dependem de log_event / capture_fact até que seu adaptador exista.
Pontos de gancho
| Ponto de gancho | Quando | O que chamar | Por quê |
|---|---|---|---|
| Início da sessão | A conversa começa | memory://profile (automático), search_knowledge | O assistente sabe quem você é desde a primeira mensagem |
| Correção | Um fato durável está faltando no armazenamento | capture_fact | Opcional; conversas do Claude Code já estão em session_events via cópia |
| Pesquisa pré-resposta | Antes de gerar uma resposta | search_knowledge, get_context | Respostas informadas pelo conhecimento armazenado |
| Pré-compactação | Antes da compressão da janela de contexto | facthouse notify compaction | O servidor copia novas linhas, extrai, integra |
| Pontos de interrupção naturais | Mudança de tópico, conclusão de tarefa | consolidate (opcional) | Mantém o grafo de conhecimento atualizado |
Sobre pré-compactação: facthouse notify compaction pede ao servidor para consolidar. Não é um gancho record.
Claude Code
Crie .claude/rules/facthouse.md no seu projeto (ou ~/.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 — both write the same rows.
- 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 ferramentas do Facthouse sem prompts de aprovação por chamada, adicione ao array permissions.allow em .claude/settings.json:
{
"permissions": {
"allow": [
"mcp__facthouse__*"
]
}
}
Cursor / Windsurf
No Cursor Directory, Add to Cursor é por componente: clique nele no servidor MCP e novamente na regra. Isso inicia um armazenamento de registros em ~/.facthouse — sem facthouse init. A aba Hooks é Copy into ~/.cursor/hooks.json, não Add to Cursor. Para copiar transcrições do Agent, execute facthouse init, escolha copy, tipo cursor.
Adicione a .cursorrules (Cursor) ou .windsurfrules (Windsurf) na raiz do seu projeto:
When the facthouse MCP server is available:
- At the start of every conversation, before answering, call get_session_context unless you already loaded the memory://briefing resource. That call returns the same working briefing the resource would have injected. Tools-only clients never fetch resources.
- 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
Cursor e Windsurf consomem ferramentas, mas não recursos, então memory://profile não carregará sozinho lá. As conversas do Cursor em si são copiadas com kind: "cursor" (JSONL sob ~/.cursor/projects/, não o armazenamento SQLite do composer).
Claude Desktop / outros clientes MCP
Ainda não há adaptador de cópia. As descrições de ferramentas lidam com pesquisa e capture_fact opcional; conversas não são rastreadas até que um adaptador posterior exista.
Recuperando espaço
O Facthouse registra conversa bruta e saída de ferramentas em session_events. Em um armazenamento conectado a um cliente agêntico, isso se torna quase todo o banco de dados. Um armazenamento medido em uso diário continha 47.000 eventos e 493 MB contra 21 fatos integrados.
facthouse stats relata a camada bruta junto com o conhecimento, incluindo quanto é recuperável. Para recuperá-lo:
facthouse prune # report only — nothing is deleted
facthouse prune --apply --vacuum # delete, then rebuild the file
Defina retention.disk_budget em config.json para um tamanho como "2GB" para limitar memory.db. Sem definição é ilimitado; init não escreve um limite. Quando um limite é definido e o arquivo está cheio, eventos brutos inalcançáveis são podados automaticamente para que novos logs possam reutilizar esse espaço; se nada não utilizado permanecer, mais eventos brutos são recusados. Fatos nunca são excluídos para atender ao número. Compactar (--vacuum) ainda é uma etapa humana — copia o arquivo inteiro para que o sistema operacional veja o tamanho menor.
Se a maior parte desse volume for saída de ferramentas que você julga ser ruído, extraction.event_types e extraction.roles restringem o que é examinado, e extraction.min_content_length pula eventos triviais. Meça antes de agir. Volume e valor não são o mesmo eixo.
A regra é alcançabilidade, não idade. Um evento é removido somente quando todas as três condições são verdadeiras:
- A extração já o leu. Qualquer coisa à frente do watermark de consolidação ainda é entrada.
- Nenhum fato cita sua proveniência.
- Ele caiu fora dos eventos
extraction.working_memory_sizemais recentes da própria sessão — uma margem para que a consolidação ainda possa olhar notas brutas recentes. Essa janela é evidência do tópico atual, não um dicionário de pronomes.
Nenhum fato, entidade, incorporação ou resultado de pesquisa é afetado. Excluir linhas não encolhe o arquivo por si só — isso é --vacuum. Sem um limite, nada poda automaticamente.
Desenvolvimento
git clone https://github.com/gordonkjlee/facthouse
cd facthouse
npm install
npm run build
npm test
npm test sempre executa pipelines herméticos (JSONL de fixture → cópia → extração →
pesquisa) com um extrator de gravação, e pula avaliações ao vivo que precisam de um modelo
real:
- Recall semântico precisa do Ollama com
nomic-embed-text. Inicie-o, depoisnpm run test:semantic. - A avaliação ao vivo do primeiro fato precisa da CLI
claude. Executenpm run test:first-fact. - A avaliação ao vivo do armazenamento de codificação (transcrições do Cursor em formato warehouse) também
precisa da CLI
claude. Executenpm run test:coding-store. - Extração HTTP local precisa de um modelo de chat em um host compatível com OpenAI e
FACTHOUSE_HTTP_MODEL(verificado emqwen2.5vl:7b). Executenpm run test:http-intelligence.
Cada um desses scripts falha em vez de pular quando sua dependência está ausente, então uma execução verde significa que a afirmação foi realmente verificada em vez de silenciosamente ignorada.
Contribua
Issues e pull requests são bem-vindos. Abra uma issue primeiro se a mudança for mais do que um typo.
- Perguntas: GitHub Discussions
- Como construir e testar: CONTRIBUTING.md
Licença
MIT