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

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.

npm CI License: MIT

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 que memory://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, ou capture_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

QuandoCopyExtract (D→I)Integrate (I→K)
O servidor MCP Facthouse iniciasimsim (limite 50)sim
Uma ferramenta ou recurso Facthouse é chamadosim, se fontes nomeadas e JSONL cresceunãonão
O processo MCP Facthouse sainãonãosim

Chamável

ChamadaDeCopyExtract (D→I)Integrate (I→K)
consolidateFerramenta MCP ou CLI. O chamador espera.simsim (limite 50)sim
facthouse notify compactionOutro processo (recomendado PreCompact; não instalamos). Não espera.simsim (limite 50)sim
facthouse notify thresholdOutro processo. Não espera. Não é um hook de copy-store.nãosim, 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çõesO assistente grava
QuemClaude Code ou Cursor (logs de sessão no disco, sob o home do cliente)Qualquer cliente MCP (Grok, Desktop, …)
ComoNomeie uma fonte; Facthouse copia novas linhas desses logs para o armazenamentosources vazio; o assistente chama capture_fact
Primeira execuçãoPasso a passo no TTY, escolha copy, defina cwd; init pergunta se deseja copiar logs existentes e depois se deseja extrair e integrarPasso 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 que memory://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 com sources vazio, é 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.enabled em 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íveis
  • get_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
TarefaUso
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 PATHnpm install -g @facthouse/mcp@… (mesma fixação). Atualize-o quando você aumentar o trecho.
Alterar ajustes extras depoisfacthouse settings (ou settings --data <dir>). Não redefine o arquivo.
Um comando CLI, sem PATHnpx -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:

HostURL típica
Ollamahttp://localhost:11434/v1 (o padrão se você omitir a URL)
LM Studiohttp://localhost:1234/v1
vLLMhttp://localhost:8000/v1
llama.cpphttp://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 ganchoQuandoO que chamarPor quê
Início da sessãoA conversa começamemory://profile (automático), search_knowledgeO assistente sabe quem você é desde a primeira mensagem
CorreçãoUm fato durável está faltando no armazenamentocapture_factOpcional; conversas do Claude Code já estão em session_events via cópia
Pesquisa pré-respostaAntes de gerar uma respostasearch_knowledge, get_contextRespostas informadas pelo conhecimento armazenado
Pré-compactaçãoAntes da compressão da janela de contextofacthouse notify compactionO servidor copia novas linhas, extrai, integra
Pontos de interrupção naturaisMudança de tópico, conclusão de tarefaconsolidate (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:

  1. A extração já o leu. Qualquer coisa à frente do watermark de consolidação ainda é entrada.
  2. Nenhum fato cita sua proveniência.
  3. Ele caiu fora dos eventos extraction.working_memory_size mais 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, depois npm run test:semantic.
  • A avaliação ao vivo do primeiro fato precisa da CLI claude. Execute npm 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. Execute npm 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 em qwen2.5vl:7b). Execute npm 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.

Licença

MIT