Facthouse

Um mecanismo de memória local que qualquer ferramenta de IA pode usar.

Documentação

Facthouse

Facthouse mascot

Facthouse é um mecanismo de memória local para ferramentas de IA. A maioria dos produtos de "memória" indexa logs de chat. 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

Ele registra, armazena e recupera conhecimento estruturado. Roteamento de domínio, extração de entidades, deduplicação e substituição são executados no servidor. Exposto como um servidor MCP.

Início Rápido

Requer Node 22.5 ou 24+.

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

Se o npm install -g falhar porque um comando chamado mcp já existe, remova esse comando remanescente e tente novamente.

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; escolha 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 — cole-o no cliente e reinicie.

No cliente, declare algo durável em conversa comum — não há comando de lembrar.

Esse é o armazenamento. Arquivo de transcrição (Claude Code ou Cursor): próxima seção. CLI: abaixo.

Como as conversas entram

Duas maneiras. Escolha uma por armazenamento.

Copiar de transcriçõesO assistente registra
QuemClaude Code ou Cursor (logs de sessão no disco, sob o diretório inicial do cliente)Qualquer cliente MCP (Grok, Desktop, …)
ComoNomeie uma fonte; o 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; o init pergunta se deseja copiar logs existentes e depois se deseja extrair e integrarPasso a passo no TTY, escolha record

Em um armazenamento copy, capture_fact é uma correção para todos os clientes MCP, não apenas para aquele que escreve JSONL. O Grok não tem adaptador de transcrição — não coloque Claude Code em copy e Grok no mesmo armazenamento esperando que o Grok registre.

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). Recuse extrair para fazer isso depois com facthouse consolidate (--all pega todo o backlog). Depois disso, o servidor copia novas linhas quando ele lida com uma chamada.

Compact (opcional): facthouse notify compaction — não é um hook Stop de fim de turno.

Replay: facthouse.dev/demo.html.

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:

  • D (session_events) — o que foi dito (transcrições copiadas, ou o que o assistente registra)
  • I (session_facts) — o que foi extraído recentemente, 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 marisco, search "food" não encontra, até você escolher um modelo de embedding — um modelo é uma opinião sobre o que "semelhante" significa.

Duas velocidades. Extrair transforma novas linhas de transcrição em fatos autocontidos. Integrar os encaixa no que o armazenamento já sabe: domínios, entidades, duplicatas, contradições, o grafo. consolidate executa copy, extract e integrate juntos — no servidor no início da sessão e na compactação, ou manualmente pela CLI. A extração é limitada a 50 linhas por execução, então um primeiro backfill nunca é gasto de uma vez; cada execução automática extrai fatos das 50 linhas mais antigas. O servidor MCP copia o log bruto em uma chamada; ele não extrai naquele momento. A consolidação não inventa uma frase que ninguém disse.

Armazenamento precisa de Node. Inteligência precisa de um modelo de linguagem. Por padrão, esse é 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.

MCP

Funciona com Claude Code, Claude Desktop e qualquer ferramenta compatível com MCP. Os dados são armazenados em ~/.facthouse por padrão. Esse único diretório é toda a instalação. Para usar um caminho diferente, adicione "env": { "FACTHOUSE_DATA": "/absolute/path" } ao trecho MCP. JSON aceita barras normais no Windows. FACTHOUSE_DATA em um trecho MCP se aplica apenas àquele processo de servidor. Um comando facthouse no terminal precisa de --data, ou FACTHOUSE_DATA no ambiente que o shell herda. Hooks não veem o env do mcp.json.

O 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 carregar recursos.

Leitura

  • get_entity — Tudo que se sabe 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 houver 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 armazenamento copy, isso é uma correção para algo que a extração perdeu; em um armazenamento com sources vazio, é assim que os 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 no 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 disponíveis e estrutura
  • get_stats — Contagem de fatos, contagem de entidades, distribuição de domínios, backlog de extração, gasto de inteligência

CLI

O JSON do 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. A mesma CLI sem PATH é npx -y -p "@facthouse/mcp" -- facthouse — fixe a versão; cite o pacote para o PowerShell não fazer splat. -p e -- impedem que um binário global mais 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 do MCP inicia o servidor. Ele não coloca facthouse no PATH. Para inspecionar o arquivo de um terminal, veja a 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 se aplica apenas àquele processo de servidor. Um comando facthouse no terminal precisa de --data, ou FACTHOUSE_DATA no ambiente que o shell herda. Hooks não veem o env do 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
TarefaUso
Servidor MCP (o que o cliente inicia)O trecho JSON: npx com args -y e um @facthouse/mcp@… fixado. Sem instalação global.
facthouse no PATHnpm install -g @facthouse/mcp@… (mesma fixação). Atualize-o quando você alterar 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 do MCP.

Em um terminal, o init pergunta o diretório de dados, copiar transcrições vs registros do assistente (padrão copy), busca semântica e Configurações adicionais. --yes nunca solicita e deixa sources vazio. --web imprime uma URL 127.0.0.1 e não abre um navegador; --yes recusa --web. Em um terminal, --force ainda faz essas perguntas e depois substitui o arquivo inteiro; --yes --force é a redefinição silenciosa. --force não mescla 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 — mais notavelmente 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

Altere ajustes extras em um config.json existente (modelo CLI, timeout, extração local opcional). Não redefine o resto do arquivo. Recusa se não houver config.json (este comando não cria um armazenamento). --json / não em um terminal imprime os ajustes atuais e não grava. --web são os mesmos ajustes em uma página local (imprime URL, sem abertura automática).

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

facthouse record

Insere eventos diretamente no banco de dados (sem necessidade de servidor em execução). Suportado para demos e para armazenamentos que não têm 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 or FACTHOUSE_DATA)

facthouse consolidate

Copia novas linhas de config.sources, extrai fatos candidatos delas e integra os fatos pendentes no 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 or FACTHOUSE_DATA)

Respeita o provedor configurado (por padrão claude -p). sources vazio torna a etapa de cópia um no-op. Defina cwd na fonte, a menos que você pretenda copiar todos os grupos de projetos. Não execute também hooks record em um armazenamento com fontes nomeadas.

facthouse notify <moment>

Diga 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   # 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)

Nenhum servidor ouvindo não é um 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 or FACTHOUSE_DATA)

--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 uma vez que algo foi 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. Escreve um arquivo HTML local sob o diretório de dados (não o diretório de trabalho atual). Imprime o caminho. Não abre um 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 de terminal (mais recentes primeiro, limitadas). --graph (o padrão quando não há --layer / --json) escreve inspect.html. --limit é 10 para tabelas e 50 para o canvas. --all desenha cada nó — um emaranhado, explícito. Busca e filtro por tipo na página ainda podem alcançar um nó que estava fora do limite.

Avançado

Outro armazenamento

O armazenamento é este diretório. Clientes o compartilham usando o mesmo caminho. Um segundo armazenamento é 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 escreveu a linha. Trabalho e pessoal é uma razão 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 armazenamentos possam compartilhar um mcp.json. Init contra cada diretório extra imprime esse trecho. Exemplo:

{
  "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" }
    }
  }
}

Aponte o sources.cwd (ou hook --data) de cada armazenamento apenas para esse armazenamento. Dois diretórios não isolam nada se ambos copiarem o mesmo home. FACTHOUSE_DATA em um trecho MCP aplica-se apenas àquele processo de servidor. Um comando facthouse de terminal precisa de --data, ou FACTHOUSE_DATA no ambiente que o shell herda. Hooks não veem o env de mcp.json.

Postgres (opcional)

SQLite é o padrão e não precisa de software extra. Para usar Postgres em vez disso, defina storage.provider para "postgres" no config.json daquele armazenamento, 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 vivem lá. Tabelas vivem na URL. Duas memórias precisam de dois diretórios e dois bancos de dados.

Init não pergunta qual mecanismo usar. facthouse init --yes ainda escreve sqlite.

Exemplo — apenas placeholders; não coloque uma senha real em um arquivo commitado:

{
  "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

Escolha um mecanismo por armazenamento.

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 quando lida com uma chamada. Grok e Codex são adaptadores posteriores. Valores desconhecidos de kind 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 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 armazenamento — ambos escrevem as mesmas linhas. O Facthouse não detecta nem reescreve configurações de hook existentes.

Modo somente registro via 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 é perguntado sobre essas questões.

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

Hooks (após o primeiro consolidate)

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 mais antigo instalado globalmente no PATH não possa vencer.

JSON do 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 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 de 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 retentor geral do armazenamento. facthouse stats relata eventos não extraídos contra esse watermark de extração.

Se o servidor MCP não iniciar, ou não listar ferramentas, verifique a versão do pacote que o cliente realmente gerou. 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 em tools/list.

Embeddings, modelo, timeout, bitemporal

Defina embedding.provider em config.json para "ollama" (local, sem chave de API) ou "voyage" (hospedado), execute facthouse consolidate, e search "food" começa a retornar a alergia. Fatos são incorporados quando são consolidados. Voyage aplica um limite de 3 requisições/minuto até que um método de pagamento esteja na conta.

Busca por significado é uma varredura exata de vetores armazenados quando o conjunto é pequeno. Quando esse conjunto é grande (padrão 32 MiB do modelo atual), um índice HNSW desses vetores é usado em vez disso: em processo no SQLite, ou um sidecar vector do Postgres quando a extensão está habilitada. Armazenamentos 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 de primeira execução Mais (Y) podem escrevê-los; depois, facthouse settings. Init não pergunta intelligence.provider; FACTHOUSE_PROVIDER=heuristic é o interruptor de desligamento. O fallback heurístico não extrai fatos de transcrições.

Fala de usuário sem nome de canal é atribuída ao dono do armazenamento; um nome de exibição ainda não cria uma pessoa. Apoio extra (assentimento, uma observação de ferramenta, um reafirmação de outro falante) é registrado, não pontuado, a menos que o armazenamento defina pesos de classificação interlocutor em config.json. O mecanismo não envia nenhum. Chaves de peso correspondem à string do falante como armazenada, então duas pessoas com o mesmo nome compartilham uma chave.

Defina temporal.mode para bitemporal para registrar quando o sistema retratou uma crença, para que a busca possa responder o que o armazenamento 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 extração cobrada por provedor em janelas contínuas. Não definido é ilimitado. Acima do limite, consolidate pula 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 nessa 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. Espaço restante está em facthouse stats, get_stats e inspect Spend. Defina o limite no config.json deste armazenamento — 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 aquele host lista. GET {base_url}/models imprime os nomes. nomic-embed-text é somente embedding e não extrairá. Se o host estiver ativo e servir exatamente um modelo de chat, o Facthouse o usa para esta execução e diz para você fixar intelligence.http.model. Se vários modelos de chat forem listados, defina esse campo; extração não adivinhará.

Extração e resumo então usam esse host; reconciliar e substituir permanecem na CLI a menos que você liste intelligence.stages. Cada etapa pode definir on-fail para cli, http ou none (veja o JSON abaixo). Extração HTTP padrão tenta novamente na CLI (conta contra o orçamento de tokens da CLI). Contradição padrão é none — sem troca de provedor. none mantém o watermark de extração — não cai no heurístico. Configurações de primeira execução Mais (Y, após o caminho recomendado) podem definir o host, modelo e extração on-fail. Depois, facthouse settings mescla esses ajustes em um arquivo existente sem redefini-lo. facthouse inspect Spend mostra os mesmos ajustes 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 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.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 não é um domínio que o Facthouse envia. O mecanismo não tem vocabulário embutido — ele leu a conversa e decidiu que aquele 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 dizem aos assistentes quando buscar e quando uma correção vale a pena ser encenada. Elas não são como 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 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 integração (hook points)

Ponto de integraçãoQuandoO 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á ausente do armazenamentocapture_factOpcional; as conversas do Claude Code já estão em session_events via cópia
Busca 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 a pré-compactação: facthouse notify compaction pede ao servidor que consolide. Não é um hook de 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
- 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 as ferramentas do Facthouse sem solicitações de aprovação a cada chamada, adicione ao array permissions.allow em .claude/settings.json:

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

Cursor / Windsurf

Adicione a .cursorrules (Cursor) ou .windsurfrules (Windsurf) na raiz do seu projeto:

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 e Windsurf consomem ferramentas, mas não recursos, então memory://profile não será carregado sozinho neles. As conversas do Cursor são copiadas com kind: "cursor" (JSONL em ~/.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 das ferramentas lidam com busca e capture_fact opcional; as conversas não são monitoradas até que um adaptador posterior exista.

Recuperando espaço

O Facthouse registra a conversa bruta e a saída das 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; a inicialização não escreve um limite. Quando um limite é definido e o arquivo está cheio, eventos brutos inacessíveis são podados automaticamente para que novos registros possam reutilizar esse espaço; se nada não utilizado restar, mais eventos brutos são recusados. Fatos nunca são excluídos para atingir o número. A compactação (--vacuum) ainda é uma etapa humana — ela 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ê considera 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 estão no mesmo eixo.

A regra é acessibilidade, não idade. Um evento é removido somente quando todas as três condições se aplicam:

  1. A extração já o leu. Qualquer coisa à frente do marco de consolidação ainda é entrada.
  2. Nenhuma proveniência de fato o cita.
  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 para 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 busca é afetado. Excluir linhas não encolhe o arquivo por si só — isso é --vacuum. Sem um limite, nada é podado 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 → busca) com um extrator de gravação, e pula avaliações ao vivo que precisam de um modelo real:

  • Recuperação semântica precisa do Ollama com nomic-embed-text. Inicie-o, depois npm run test:semantic.
  • A avaliação ao vivo do primeiro fato precisa do CLI claude. Execute npm run test:first-fact.
  • A avaliação ao vivo do armazenamento de codificação (transcrições do Cursor em formato de warehouse) também precisa do CLI claude. Execute npm run test:coding-store.
  • A 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 erro de digitação.

Licença

MIT