Compartment
Memória totalmente offline e criptografada em repouso para agentes de IA, com os vetores de embedding também criptografados, busca exata residente em RAM, exclusão por cripto-fragmentação e um log de auditoria encadeado por hash.
Documentação
Compartment
Memória criptografada e totalmente offline para agentes de IA. Um cofre no seu próprio computador, lido e escrito por Claude Code, Claude Desktop, Hermes Agent, OpenClaw, Cursor, Codex e qualquer outro cliente MCP. Sem chave de API, sem conta, sem rede, sem telemetria.
Instalação em um clique (após pip install compartment && compartment init):
Claude Code, Claude Desktop, Hermes Agent e OpenClaw são conectados por um único
comando: compartment integrate claude, hermes ou openclaw.
Compartment é memória persistente para agentes de IA, armazenada no seu próprio computador. O que um agente aprende em uma sessão fica disponível em todas as sessões posteriores, em todos os projetos, para todos os agentes na máquina, e nada sai da máquina.
Cada memória é uma única afirmação, registrada com sua fonte e a data em que foi
aprendida. Memórias podem expirar: defina expires e a memória é removida após
essa data. Quando uma preferência muda, a nova substitui a antiga.
A recuperação é uma busca híbrida por vetores e palavras-chave sobre um índice em memória. Ela
responde em cerca de 12 ms e retorna apenas o que é relevante.
O modelo de embeddings está incluído no pacote. Tudo no disco é criptografado, incluindo os vetores de embeddings, e apenas sua frase secreta abre o cofre. Um cofre novo vem com cerca de 6.700 fatos de referência sobre hardware, sistemas operacionais, portas, codificações e ferramentas de shell. Eles são memórias comuns, e um único interruptor os remove da busca.
Como se compara com outros servidores de memória
Onde cada servidor mantém a memória e o que a protege, conforme documentado por cada projeto em 2 de setembro de 2026. Fontes e a tabela completa estão em docs/COMPARISON.md; correções são bem-vindas como PR contra esse arquivo.
| Memória em repouso | Criptografada | Conta / chave de API | Rede em tempo de execução | |
|---|---|---|---|---|
| Compartment | um arquivo criptografado; índice na RAM | sim, vetores também | nenhuma | nenhuma, imposto por CI |
@modelcontextprotocol/server-memory | texto puro memory.jsonl, busca por substring | não | nenhuma | nenhuma |
| mem0 (código aberto) | armazenamento de vetores + fatos extraídos por LLM; seu servidor MCP é apenas hospedado | não documentado | chave de LLM | chamadas de LLM; telemetria ativada por padrão |
| Graphiti (Zep) / Letta | Neo4j / servidor + banco de dados | não documentado | chave de LLM | chamadas de LLM; telemetria ativada por padrão |
| claude-mem | SQLite local + Chroma | não documentado | login obrigatório | conta + chamadas ao provedor; telemetria ativada por padrão |
| basic-memory (AGPL) | Markdown + SQLite | não documentado | nenhuma | telemetria ativada por padrão |
| Hindsight (Vectorize) | um contêiner com PostgreSQL embutido | não documentado | chave de LLM (modelos locais configuráveis) | chamadas de LLM; fornecedor declara sem telemetria |
| Supermemory | serviço em nuvem, ou binário pré-compilado auto-hospedado | não documentado | conta (nuvem) ou chave de LLM (auto-hospedado) | chamadas em nuvem; auto-hospedado: fornecedor declara sem telemetria |
| Cognee | SQLite + LanceDB + Kuzu localmente, ou nuvem | não documentado | chave de LLM | chamadas de LLM; telemetria ativada por padrão |
| MemOS | Neo4j + Qdrant auto-hospedado, ou nuvem | não documentado | chave de LLM | chamadas de LLM; telemetria ativada por padrão |
A lógica da memória
Quase tudo é armazenado. Apenas turnos vazios são descartados. Um simples "OK" é uma decisão, não ruído: quando o agente pergunta "Quer que eu envie esta resposta ao cliente agora?" e o usuário responde "OK", Compartment armazena a decisão junto com a pergunta que ela respondeu. Conversa fiada é mantida, mas classificada por último.
A importância é atribuída por níveis fixos. Decisões e consentimento 0,90, fatos pessoais e preferências 0,80, a máquina e a configuração do usuário 0,75, outras declarações substantivas 0,55, conversa fiada 0,20. A importância multiplica uma pontuação de correspondência em vez de somar a ela, então ela desempata quase-empates a favor do que importa e nunca pode trazer à tona uma memória que não correspondeu à pergunta.
Uma afirmação por memória, imposta. O armazenamento rejeita qualquer coisa com mais de
200 caracteres (a configuração max_memory_chars), e qualquer coisa que contenha
listas, títulos ou parágrafos, com um erro que diz como dividi-la.
Instruções sozinhas não funcionaram: em um cofre real, a mediana de memória escrita
por um agente era de 1.938 caracteres de log de sessão com marcadores. memory_store_many
armazena um lote em uma única chamada. compartment atomize divide memórias acima do limite
em um cofre existente; cada parte mantém as datas do original, e o original
é marcado como substituído, mas permanece legível por id.
Cada memória registra sua fonte e data. source é obrigatório: "do
chat", "lido de pyproject.toml", "busca na web". discovered é a data em que o
fato foi aprendido, separada da data em que foi salvo. Ambos são anexados ao
texto como uma cláusula curta, por exemplo [web search, 2026-08-01].
Memórias podem expirar. Para um fato que deixa de ser verdadeiro em uma data
conhecida, como um preço promocional, uma reserva ou um código de porta, defina expires para essa data
(2026-09-03) ou para uma duração (14d, 2w, 3m, 1y). A memória é
removida após essa data. compartment expire executa a varredura manualmente;
expire_memories a desativa. A maioria dos fatos não deve expirar; uma expiração
errada exclui uma memória que o usuário queria.
Fatos se acumulam; opiniões se atualizam. Um novo fato é adicionado ao lado dos
outros: o código da porta mudou, um script vive em um caminho, uma versão foi
lançada. Uma opinião substitui outra. Quando uma preferência é armazenada com kind="opinion",
o cofre procura primeiro por uma opinião viva semelhante. Se encontrar uma, retorna
o registro antigo em vez de inserir, e o chamador reenvia com
supersedes=[old id] para substituí-lo, ou supersedes=[] para manter ambos.
Reafirmar uma opinião viva atualiza sua data em vez de armazenar uma cópia.
Registros substituídos são removidos da busca, mas mantidos na cadeia de auditoria e
legíveis por id, com um ponteiro para seu substituto. supersedes também funciona
em fatos, para correções. A classificação de opiniões carrega um bônus de recência que
a classificação de fatos não tem, então a opinião mais nova vence. compartment opinions audit encontra opiniões vivas sobrepostas em cofres mais antigos e mantém a
mais nova, ou as relata para mesclagem manual.
A captura não depende do modelo. Um host que declara sua própria
memória em seu prompt de sistema pode substituir qualquer instrução de ferramenta. Então
integrate claude instala um hook PostToolUse que escreve cada arquivo de memória
que Claude Code salva no cofre, quer o modelo chame a ferramenta ou não.
O hook deixa seus outros hooks intactos, faz backup de settings.json
primeiro, sempre sai com sucesso para nunca quebrar seu editor, e não faz
nada enquanto o cofre estiver bloqueado. compartment hook status | install | uninstall, or integrate claude --no-hooks. compartment import-claude
importa qualquer coisa que o hook perdeu.
A busca retorna o que é relevante, não um número fixo. Compartment retorna
toda memória cuja pontuação se sustenta contra o melhor resultado para a mesma
pergunta, até um limite generoso. O corte é relativo porque as pontuações não são
comparáveis entre perguntas: em um cofre real, a consulta sem sentido "como
assar pão de fermentação natural" pontuou mais alto do que a consulta real "o que Max decidiu
sobre Airtable". Uma pergunta sobre a qual o cofre não sabe nada retorna nada.
Passe top_k para obter exatamente essa quantidade.
As tags são mantidas atualizadas. Sobre o que uma memória trata nunca muda; a que
ela é relevante muda. Suponha que, enquanto trabalha em um projeto chamado Northwind,
você aprenda que o cliente quer números antes de conclusões. O agente marca
a memória com northwind. Dois anos depois, o mesmo cliente, agora chamado Harbour,
contrata você novamente, e o agente busca com a tag harbour. A memória
ainda é verdadeira, mas um filtro de tag não consegue encontrá-la. Então uma passagem em
segundo plano dá a cada memória as tags que seus vizinhos mais próximos no espaço de embeddings
carregam, ponderadas por similaridade: conforme memórias de Harbour se acumulam perto daquela antiga, ela
adquire a tag harbour. Dois outros sinais rodam em paralelo: tags que quase
sempre ocorrem juntas implicam uma na outra, e uma tag existente cuja frase
aparece no texto de uma memória é anexada. A passagem escreve apenas tags, nunca
texto, datas ou embeddings. Ela apenas adiciona tags, a menos que você passe --prune,
tags_origin preserva as tags originais, e compartment retag --dry-run
mostra o que mudaria.
Um grafo além de uma lista. memory_link registra uma relação: sujeito,
predicado, objeto, opcionalmente vinculada a uma memória e a uma janela de validade.
memory_relations responde por entidade, por predicado ou a partir de uma data.
Compartment armazena e corresponde relações deterministicamente; o modelo
host decide o que vincular.
Memórias são dados, não instruções. Memórias recuperadas são envolvidas com
um aviso de que são dados armazenados. Conteúdo de uma fonte não confiável pode ser marcado
como quarantined, o que adiciona um aviso a cada recuperação dele. O agente
host ainda deve tratar a memória como dados.
Um modelo de embeddings por cofre. O SHA-256 do modelo é registrado no
cofre e verificado na abertura, para que as pontuações de similaridade permaneçam comparáveis. Para mudar
o modelo, execute compartment reindex --re-embed.
Sem LLM interno. Os embeddings são executados localmente com um modelo ONNX int8 de 384 dimensões incluído, em um único processo compartilhado de cerca de 70 MB que todos os agentes na máquina usam. O modelo host decide o que armazenar e esquecer; Compartment captura, criptografa e recupera. Essa divisão mantém a garantia offline absoluta e cada decisão reproduzível. Com um LLM offline, todo o agente roda sem rede.
Veja o que ele aprendeu. compartment recent lista as memórias mais recentes,
ocultando os fatos de referência para que suas próprias memórias fiquem visíveis.
compartment status relata organic_records ao lado do total.
memory_recent é a mesma visão via MCP.
O aplicativo e o painel
O mesmo painel em cada sistema: a barra de menus no macOS, a área de notificação no Windows e uma janela comum no Linux, listada no menu de aplicativos. O Linux recebe uma janela de propósito: um ícone de bandeja pode nunca aparecer no GNOME ou Wayland, e o controle que desbloqueia suas memórias não deve falhar silenciosamente.
O painel mostra se o cofre está aberto, quantas memórias ele contém e quantas você armazenou, as três configurações que valem a pena mudar (hook de captura, se fatos de referência aparecem na busca, bloqueio automático), quais agentes estão conectados com botões para conectar Claude, Hermes Agent ou OpenClaw, e as últimas cinco memórias. Você pode desbloquear, bloquear e mudar sua frase secreta lá sem terminal. O painel abre instantaneamente com o que leu por último e atualiza em segundo plano, apenas quando algo realmente mudou. Enquanto você o usa, um processo auxiliar mantém o cofre aberto somente leitura e lê apenas as novas memórias conforme os agentes as adicionam; após dez minutos ociosos, ele sai, então um aplicativo ocioso não mantém cofre nem chave. Olhar nunca bloqueia, desbloqueia ou reescreve o cofre. Ele é feito para ser um dos muitos aplicativos no seu computador, não algo que você precisa aprender: cada função é um botão ou um interruptor, e os padrões foram escolhidos por medição.
O botão Painel abre o cofre inteiro no seu navegador: crescimento ao longo do tempo, o grafo de relações com cada entidade nomeada, tags, contagens por agente e busca ao vivo. Ele é servido da RAM apenas em 127.0.0.1, somente leitura, sem requisições de saída.
A matemática
Tudo abaixo está em um único arquivo,
src/compartment/ranking.py, usado pelo
vault, pelo dashboard e pelo benchmark. Uma pontuação de benchmark, portanto, mede
o próprio produto.
Armazenamento: memórias longas são incorporadas em janelas
O codificador lê 512 tokens. Texto além disso não é visto de forma alguma, então uma memória longa costumava ser pesquisável apenas pela sua abertura. Em um vault real com 6.705 memórias, 40% dos registros excediam a janela e 57,6% do texto era invisível para a busca semântica.
Então cada registro é incorporado como janelas sobrepostas de W = 448 tokens com um
passo de S = 384, dando 64 tokens de sobreposição para que nenhum fato seja cortado
pela metade, e o registro é pontuado pela sua melhor janela:
windows(d) = ceil( max(0, tokens(d) - W) / S ) + 1 capped at 64
s_vec(d) = max over windows w of d : cos(q, w)
Máximo, não média: uma memória é relevante se qualquer parte dela for, e uma média penalizaria uma memória longa pelas suas outras partes. Com uma janela por registro, isso é idêntico ao comportamento antigo, então memórias curtas não são afetadas. A maioria das memórias é curta: 6.705 registros produziram 6.785 janelas. As janelas são medidas em tokens do modelo, não em caracteres, porque um orçamento de caracteres erra por um fator de três entre prosa e um digest hexadecimal.
Recuperação: dois canais, combinados como evidência
Dois índices respondem a perguntas diferentes. O índice vetorial responde o que uma memória significa; o índice de palavras-chave responde o que ela diz. Suas pontuações não estão na mesma escala, e combiná-los é o problema central.
Até a versão 4.7, o Compartment os somava. Somar permite que uma correspondência semântica apenas razoável supere evidência literal conclusiva: buscar em um vault real por um SHA de commit que aparece em exatamente uma memória retornava essa memória abaixo de dez paráfrases dela, porque a soma enterrava um resultado de palavra-chave em primeiro lugar.
Os dois canais são alternativas, não adendos: qualquer um deles sozinho pode estabelecer relevância. Isso é um OR suave sobre evidências independentes,
P(relevant) = 1 - (1 - p_vec)(1 - p_lex)
e a pontuação é o seu logaritmo, que classifica de forma idêntica, mas mantém espalhando os resultados perto do topo em vez de saturar em 1:
score(d) = - w_vec · log(1 - p_vec(d)) - w_lex · log(1 - p_lex(d))
w_vec = 0.75 w_lex = 0.25
Qualquer canal próximo da certeza carrega a memória sozinho; nenhum pode vetar o outro.
Transformando um cosseno em uma probabilidade. Um codificador normalizado por L2 fornece cossenos que são comparáveis entre consultas, então limites fixos os mapeiam. A normalização min-max por consulta reescalaria o melhor resultado de uma consulta sem esperança para 1.0 e descartaria essa informação.
p_vec(d) = clamp( (cos(q, d) - 0.25) / (0.85 - 0.25), 0, 0.88 )
O teto de 0.88 importa. Um cosseno é uma similaridade, nunca uma identidade: um
codificador pode dizer isto é sobre a mesma coisa, nunca este é o registro que você
nomeou. Uma correspondência literal em uma string única para uma memória pode. Então o canal
semântico é limitado abaixo do que o canal literal pode alcançar, e o limite é
forçado pelos pesos: o canal literal atinge o máximo em
0.25 · -log(1 - 0.999) = 1.727, então 0.75 · -log(1 - cap) < 1.727, dando
cap < 0.90.
Transformando um resultado de palavra-chave em uma probabilidade, sem BM25. BM25 mede quão bem um documento corresponde, o que não resolve um confronto contra um resultado semântico. O que resolve é quão improvável a correspondência foi por acaso. Cada termo de consulta carrega sua auto-informação sobre o vault, e uma memória pontua a fração da informação da consulta que ela cobre:
I(t) = log( N / (1 + df(t)) ) N = records in the vault
p_lex(d) = ( Σ I(t) for query terms t present in d ) / ( Σ I(t) for all t )
Um termo único para uma memória é quase conclusivo; um termo em um décimo do vault é quase nada, seja qual for seu BM25. É isso que torna resultados literais e semânticos comparáveis.
O índice de palavras-chave é consultado como AND primeiro, porque uma frase exata é o sinal mais forte. O AND implícito do FTS5 exige que uma pergunta de nove palavras apareça palavra por palavra, então quando o AND não encontra nada, ele recai para OR sobre os termos informativos apenas: qualquer coisa em mais de 10% dos registros é descartada. Esse limiar é medido do vault, não retirado de uma lista de stopwords em inglês, então funciona da mesma forma para código, nomes ou outros idiomas.
Um pequeno termo de concordância de classificação é adicionado, a única coisa que a fusão de classificação recíproca faz bem, dimensionado para desempatar:
+ w_rrf · k · [ 1/(k + rank_vec) + 1/(k + rank_lex) ] w_rrf = 0.10, k = 20
Importância e recência reordenam a pontuação
evidence(d) = aged( vec term, q(d) ) + lex term + rank residue
final(d) = evidence(d) · ( 1 + w_imp · (2·importance(d) - 1) + w_op )
aged(s, q) = log( 1 + 2^( -q / half_life_share ) · (e^s - 1) )
q(d) = share of the vault's own memories written after this one
half_life_share = 0.5, so the median memory is worth half the odds
w_imp = 0.15, for facts and opinions alike
w_op = 0.30 · 2^( -age_days / 30 ) for an opinion, from the last
re-affirmation (`affirmed`); 0 for a fact
Multiplicativo, então um prior só pode reordenar memórias que já corresponderam. Um prior aditivo deixaria uma memória importante aparecer para uma pergunta não relacionada. Uma memória que não correspondeu a nada pontua zero e permanece assim.
Centrado no padrão 0.5, daí 2·importance - 1. Cada memória
sem peso carrega 0.5, incluindo os milhares de fatos de referência, então sem
centralização todos receberiam o mesmo impulso e a importância não faria nada.
Centrado, uma memória sem peso é neutra e apenas um peso deliberado a move.
A idade de uma memória é contada em memórias, não em dias. Um fato não fica menos verdadeiro em seis meses; o que torna uma memória antiga a resposta errada é que o vault avançou, e o quanto avançou é uma questão sobre quanto foi escrito. Então uma memória é tão antiga quanto a parcela do vault escrita depois dela. Duas memórias adicionadas em uma quinzena deixam uma memória de quinze dias intocada; quinhentas adicionadas na mesma quinzena reduzem pela metade as chances por trás de sua evidência semântica. A população contada são as memórias vivas do próprio vault nos namespaces sendo pesquisados: não os fatos de referência e não um pacote instalado, que chegam aos milhares em um instante e não têm idade nesse sentido.
A mudança é aplicada apenas ao canal semântico, e em chances, então uma correspondência
forte é ajustada e uma fraca é reduzida. Um identificador literal é deixado
sozinho: um SHA de commit que aparece em exatamente uma memória nomeia essa memória
quer tenha sido escrito ontem ou no ano passado. E os pisos de relevância leem
a pontuação sem idade, então a recência escolhe a ORDEM dos resultados e nunca
quais voltam. Uma consequência: o score relatado de uma memória retornada
é o envelhecido e pode ficar abaixo do piso absoluto que passou, então o piso
é um corte que o vault faz e não uma propriedade do número que ele devolve.
Uma opinião carrega um segundo prior além disso, e esse está no relógio: ele reduz pela metade a cada 30 dias desde quando foi reafirmada pela última vez, com peso suficiente para que a opinião mais recente sobre um assunto vença.
Ordem de recuperação
Filtros de namespace, tag, data e fatos de referência são executados após a classificação, então um pool dimensionado para o número solicitado de resultados pode ser esvaziado por eles enquanto memórias correspondentes ficam logo após o corte. O pool começa em 200 por canal e se amplia até três vezes quando a filtragem deixa poucos. Abaixo de 20.000 registros, a busca vetorial é exata (matemática de matriz SIMD, recall 1.0); acima disso, HNSW com cerca de 99% de recall.
Segurança e o modelo de bloqueio
Os primitivos: criptografia XChaCha20-Poly1305 em tudo em repouso,
incluindo vetores de incorporação, porque vetores podem ser invertidos de volta para texto · slots de chave Argon2id, estilo LUKS · uma chave por registro, então forget --shred
destrói a chave e o conteúdo é irrecuperável em vez de marcado como excluído
· um diário selado com fsync, compactação atômica e recuperação testada com kill -9 ·
um log de auditoria encadeado por hash (compartment audit verify) · manifests de vault assinados
e pacotes · transporte stdio sem portas abertas; o único socket local
é o socket Unix do processo de incorporação compartilhado, no mesmo diretório privado
que a credencial de desbloqueio, carregando texto para dentro e vetores para fora e
nunca uma chave · uma proteção em tempo de execução que aborta em qualquer tentativa de socket de rede
(--assert-offline), com CI executando toda a suíte sob ela no Linux,
macOS e Windows. O modelo de ameaça completo,
incluindo o que o Compartment não pode proteger, está em
SECURITY.md.
Pelo aplicativo
Tudo o que você faz no dia a dia é um botão. Desbloquear pede sua frase secreta; Bloquear fecha o vault e limpa toda credencial armazenada; Alterar senha recriptografa; Bloqueio automático escolhe 15, 30 ou 60 minutos ociosos, ou nunca. O Compartment nunca gera uma senha, semente ou frase de recuperação, e não guarda nenhuma credencial que você não tenha.
Após um desbloqueio, o vault permanece aberto entre processos, logouts e logins pelo tempo que você deixar, até um reinício ou perda de energia, até o timer de bloqueio automático disparar, ou até você bloqueá-lo. Um reinício ou perda de energia sempre o bloqueia: a credencial de desbloqueio é a chave mestra envolvida com um segredo aleatório por inicialização que vive apenas na memória do kernel e nunca é escrito em disco, então uma nova inicialização não pode abri-lo. Uma cópia do arquivo de credencial sozinha é inútil.
Pela linha de comando
Os mesmos controles, mais dois que só existem aqui:
compartment unlockecompartment lockfazem o que os botões fazem. Agentes podem bloquear com a ferramentamemory_lock. (Vaults de versões mais antigas que receberam uma frase de recuperação ainda a aceitam.)compartment 2fa enableadiciona um segundo fator: sua frase secreta mais um arquivo de chave, por exemplo em um pendrive USB. Ambos alimentam o Argon2id juntos, então o requisito é imposto pela criptografia, não por uma configuração; um arquivo de vault roubado mais sua frase secreta não abre nada sem o arquivo de chave. A localização do arquivo de chave é lembrada, então desbloquear parece o mesmo enquanto ele estiver presente.compartment unlock --keychainno macOS é uma adesão explícita que sobrevive a reinicializações.
A ferramenta MCP memory_unlock existe, mas está desativada por padrão, porque ativá-la
coloca a frase secreta no contexto do modelo.
Um vault, muitos agentes, qualquer máquina
Sem a linha de comando
Cada agente na máquina usa o mesmo vault, e nada disso precisa de configuração: os botões Conectar um agente do aplicativo conectam Claude, Hermes Agent e OpenClaw, e o que um agente armazena os outros recuperam. Claude, Hermes Agent, Cursor e a CLI podem usar o vault ao mesmo tempo: escritas são serializadas por um bloqueio de arquivo, cada processo percebe escritas de outros e recarrega, e cada agente tem sua própria identidade e namespace. Seus servidores compartilham um processo de incorporação também, então dez agentes custam um modelo em RAM, e ele sai alguns minutos depois que o último deles sai.
Um vault bloqueado é um arquivo, memory.vault na pasta .compartment do seu
diretório pessoal. Para mover para outra máquina, bloqueie o vault, copie o
arquivo para lá, instale o Compartment e desbloqueie-o no aplicativo com sua
frase secreta.
Pela linha de comando
O mesmo movimento, assinado para que o destinatário possa verificá-lo, mais as saídas de emergência:
compartment lock --sign
scp ~/.compartment/memory.vault other-machine:
compartment --vault memory.vault unlock # your passphrase (+ keyfile if 2FA)
lock --sign adiciona um manifest Ed25519 que o destinatário pode verificar com
compartment verify e nenhuma credencial. export --plaintext escreve o vault
como JSONL e import o lê de volta, então você nunca fica preso.
FORMAT.md especifica os arquivos .vault e .mpack byte por
byte. Namespaces por agente aceitam concessões rw, ro ou none no arquivo de
configurações, então um agente de rascunho pode ler sem escrever.
Pacotes de memória são pacotes assinados e somente leitura de memórias curadas
(compartment pack build | install | remove | list | export). Eles instalam
sob packs/<name>, somente leitura para todos os chamadores, e
include_packs_in_search os alterna. A assinatura de um pacote é verificada contra
uma chave que você confia, nunca contra a chave dentro do pacote. Os fatos de referência
são o único pacote que vive em main como memórias comuns.
PACKS.md cobre a autoria.
compartment setup airgap-bundle prepara uma instalação para uma máquina sem
rede; setup download-model e setup download-longmemeval buscam o que
os benchmarks opcionais precisam.
Medido, em um laptop básico de 8 GB
Cada número abaixo é reproduzível na sua máquina com compartment selftest and compartment bench (--longmemeval executa o benchmark de
recuperação); compartment embed-daemon status relata o tamanho do próprio processo
compartilhado.
| Métrica | Medido |
|---|---|
| Instalação limpa → abrir cofre, offline | segundos, zero rede |
| Busca vetorial, 20 mil registros (HNSW) | p95 0,68 ms |
| Busca híbrida completa (embed + janelas + palavras-chave + fusão de evidências) | mediana 11,6 ms, p95 14,7 ms |
| Processo de incorporação compartilhado, modelo carregado, uma vez por máquina | 68 MB residentes |
| O mesmo após dois lotes de 64 janelas de texto longo | 71 MB; antes da 4.9.6, o servidor de cada agente mantinha 1,5 GB, depois 3 GB |
| Um processo de servidor MCP com seu modelo no daemon compartilhado | 60 MB, mais seu cofre e índice |
| Armazenar uma memória (embed + criptografar + journal fsync) | ~40 ms |
| Tamanho do wheel, modelo incluído | ~30 MB |
| Suíte de testes (cripto, adulteração, falha, offline, concorrência, 2FA, grafo, painel, ranqueamento) | 800+ testes, guarda offline ativa |
Instalação
Nenhuma linha de comando necessária. Em um Mac, baixe o Compartment.pkg do último lançamento e abra-o. Python, o modelo de incorporação e todas as dependências estão dentro dele. Ele pede que você escolha uma frase secreta, cria o cofre e coloca o Compartment na sua barra de menus, onde os botões Conectar um agente fazem o resto.
Pela linha de comando, em qualquer sistema:
| pip (macOS, Linux, Windows) | pip install compartment && compartment init |
| pipx / uv | pipx install compartment ou uv tool install compartment, depois compartment init |
| Plugin Claude Code | após pip install compartment && compartment init: /plugin marketplace add MaxFreedomPollard/Compartment, depois /plugin install compartment@maxfreedompollard. O Codex lê o mesmo arquivo de marketplace |
| Docker | docker build -t compartment . a partir de um checkout; veja Conectando cada agente |
A rota pip precisa de Python 3.11 ou mais recente. O aplicativo roda no macOS 13 ou mais recente, no Windows com o runtime Microsoft Visual C++ instalado, e em qualquer desktop Linux.
init pede que você escolha uma frase secreta, cria o cofre, carrega os
fatos de referência, conecta o Claude Code, Hermes Agent ou OpenClaw se estiverem
instalados, e inicia o aplicativo: um item na barra de menus no macOS, um ícone na
bandeja no Windows, uma janela no Linux. Reinicie seu agente e ele terá uma memória.
Para conectar um agente depois, ou qualquer outro cliente:
compartment integrate claude # Claude Code + Claude Desktop
compartment integrate hermes # Hermes Agent
compartment integrate openclaw # OpenClaw
compartment integrate --list # the 28 MCP clients it can wire: Cursor, VS Code, Cline, Roo Code, Zed, OpenCode, Codex CLI, Gemini CLI, Oh My Pi, LM Studio, AnythingLLM, BoltAI ...
compartment integrate --all # every one of them that is installed here
claude, hermes e openclaw também recebem a habilidade /compartmentalize
instalada em seus diretórios de habilidades. Qualquer outro cliente MCP usa este bloco
(transporte stdio, sem variáveis de ambiente):
{ "mcpServers": { "compartment": { "command": "compartment", "args": ["serve"] } } }
Conectando cada agente
Nada disso precisa de terminal: os botões Conectar um agente no aplicativo
executam os mesmos passos para Claude, Hermes Agent e OpenClaw. Os comandos abaixo
são para quem os prefere, e para conectar um cliente que o aplicativo não
lista. No Windows, execute-os no PowerShell com py -m pip install compartment
no lugar de pip install compartment.
Claude (Code + Desktop)
pip install compartment && compartment init && compartment integrate claude
Registra o servidor MCP com a CLI do Claude Code (escopo do usuário, todos os
projetos), importa as memórias que o Claude Code já escreveu em seus
arquivos de memória (somente cópia e repetível; --no-import pula isso), instala o
hook de captura (--no-hooks pula isso), instala a habilidade /compartmentalize,
escreve um bloco gerenciado em CLAUDE.md e imprime o bloco de configuração do Claude Desktop.
O servidor também se descreve no handshake do MCP, dizendo ao
modelo para recordar antes de responder e para armazenar fatos duráveis, credenciais,
nomes e decisões, então o Claude usa o Compartment como sua memória sem nenhuma
instrução manual.
Hermes Agent
pip install compartment && compartment init && compartment integrate hermes
Instala o plugin de provedor no ambiente Hermes e executa
hermes memory setup compartment; verifique com hermes memory status.
Hermes Agent 0.20.0 e mais recentes também leem o formato portátil
Agent Plugins, e este repositório é
um deles. Essa rota instala o servidor MCP e a habilidade /compartmentalize
do GitHub:
pip install compartment && compartment init
hermes plugins install MaxFreedomPollard/Compartment
hermes plugins enable compartment
O provedor é a integração mais completa, porque recorda e armazena em cada turno; o pacote portátil funciona apenas quando o modelo chama suas ferramentas. No macOS e Windows, ambos instalam no mesmo nome de diretório de plugin, então use um ou outro.
OpenClaw
pip install compartment && compartment init && compartment integrate openclaw
Escreve a entrada mcpServers em ~/.openclaw/openclaw.json, com um
backup. Depois execute openclaw gateway restart e verifique com
openclaw mcp list.
Qualquer cliente MCP
compartment integrate <client> conecta qualquer um dos 28 clientes em --list.
Cada escrita de configuração faz um backup byte-exato primeiro, mescla em vez de
substituir, escreve atomicamente e se recusa a tocar em um arquivo que não consegue analisar (ele
imprime o bloco para colar em vez disso). Para fazer manualmente, use o bloco em
Instalação; VS Code usa a chave servers com "type": "stdio",
Zed usa context_servers, Codex usa TOML em
[mcp_servers.compartment]. --vault e --caller são opcionais; os
padrões são ~/.compartment/memory.vault e chamador user.
Passo a passo por cliente estão em
docs/INTEGRATIONS.md.
Docker
docker build -t compartment . a partir de um checkout constrói uma imagem headless:
somente stdio, sem porta, usuário sem privilégios, cofre em um bind mount em /data.
Crie o cofre no host primeiro com compartment init, porque esse
passo solicita a frase secreta.
Configuração
Nada aqui é obrigatório. O Compartment instala já configurado; esta é toda a superfície se você quiser mudar algo.
No aplicativo
O painel atrás do ícone: Desbloquear e Bloquear, Alterar senha, Criar memórias automaticamente (o hook de captura), Buscar fatos iniciais, Bloqueio automático (15, 30, 60 minutos ou nunca), os botões CONECTAR UM AGENTE para Claude, Hermes Agent e OpenClaw, Atualizar e Sair.
Comandos
Flags globais, antes do comando: --vault PATH, --caller NAME,
--keyfile PATH, --assert-offline, --version.
| Comando | O que faz |
|---|---|
init | cria o cofre. --passphrase, --creator, --keychain, --no-session, --no-app |
unlock / lock | abre ou fecha ele. --passphrase-stdin, --keyfile, --keychain, --once; lock --sign --identity |
status / verify / selftest | o que há nele, está intacto, funciona |
store / get / forget | uma memória. --source (obrigatório), --discovered, --expires, --namespace, --tag, --importance, --kind fact|opinion, --supersedes ID, --keep-both, --quarantined, --raw; forget --shred |
search / recent | encontra coisas. --namespace, --tag, --top-k, --limit, --all, --json |
expire | remove memórias expiradas |
atomize | lista memórias blob acima do limite como JSONL (--out + --plaintext), aplica um plano de divisão escrito por agente (--apply) |
opinions audit | preenche kind em registros com formato de opinião, agrupa opiniões ativas sobrepostas, resolve com --keep-newest. --threshold, --no-backfill, --json |
link / relations / unlink | o grafo de relações, com janelas de validade (--from, --to, --as-of) |
panel (menubar, tray) | o aplicativo. --show, --self-check, --render, --login |
integrate <agent> | conecta claude, hermes, openclaw ou qualquer cliente listado, e instala /compartmentalize. --list, --all, --no-import, --no-hooks; integrate --refresh atualiza as instruções que uma instalação anterior escreveu nos arquivos do agente e nada mais |
hook | o hook de captura do Claude Code: install --pin-vault, uninstall, status, capture |
import-claude | puxa o que o Claude Code já escreveu. --dir, --namespace, --dry-run |
serve | o servidor MCP, via stdio |
embed-daemon | o processo de incorporação compartilhado que todo agente usa: status, stop, run |
dash | lê o cofre em um navegador: 127.0.0.1, token de uso único, somente GET |
export / import | export --plaintext escreve sem criptografia; import lê de volta |
rekey | altera a frase secreta. --new-passphrase-stdin |
2fa | enable, disable, status: um arquivo de chave como segundo fator |
audit | verify, repair o histórico encadeado por hash |
retag | recalcula tags do cofre atual (--dry-run, --prune); nunca altera o texto da memória |
reindex | reconstrói o índice e dá aos registros longos as janelas de incorporação que estão faltando. --int8, --f32, --re-embed, --model |
pack | build, install, remove, list, export pacotes de memória assinados (--trusted-key) |
bench | --records, --longmemeval, --variant, --limit |
setup | download-model, download-longmemeval, airgap-bundle |
update | atualiza no lugar e depois atualiza as instruções nos arquivos do agente. --source pega o main do GitHub, --no-app pula o reinício |
uninstall | remove ele. O cofre é mantido a menos que você passe --purge |
compartment panel --login on | off | status controla iniciar no login (no
Linux, a entrada do menu de aplicativos). init --no-app pula o aplicativo em
máquinas headless e em CI.
compartment dash é o botão do Painel pelo terminal: o cofre inteiro
no seu navegador, crescimento ao longo do tempo, o grafo de relações com cada entidade
nomeada, tags, contagens por agente, busca ao vivo. Ele serve a partir da RAM em 127.0.0.1
apenas, atrás de um token de URL aleatório, somente leitura, sem requisições de saída e sem
configuração. Ctrl-C fecha ele.
A habilidade /compartmentalize
compartment integrate <agent> escreve um arquivo no diretório de habilidades do próprio
agente, e compartment uninstall o remove:
| Agente | Caminho |
|---|---|
| Claude Code | ~/.claude/skills/compartmentalize/SKILL.md |
| Hermes Agent | $HERMES_HOME ou ~/.hermes/skills/compartmentalize/SKILL.md |
| OpenClaw | $OPENCLAW_HOME ou ~/.openclaw/skills/compartmentalize/SKILL.md |
Todos os três usam o mesmo layout de Agent Skills, então é um único arquivo. Apenas o usuário
o executa. Digite antes de compactar, ou a qualquer momento, e o agente armazena a
conversa inteira no cofre: pessoas e contatos, credenciais e onde elas
vivem, URLs e hosts, decisões e as razões para elas, e um registro
da própria sessão. Ele faz muitas chamadas memory_store. Você pode editar sua
cópia; uma instalação posterior faz backup de uma cópia alterada em vez de sobrescrevê-la.
Arquivo de configurações
<vault>.config.json, ao lado do cofre, contendo permissões por chamador e:
| Configuração | Padrão | Significado |
|---|---|---|
auto_lock_minutes | 30 | tempo ocioso antes de bloquear. 0 nunca bloqueia |
search_starter_facts | true | se os fatos semeados entram nos resultados de busca |
include_packs_in_search | true | o mesmo, para pacotes instalados |
recency_half_life_share | 0.5 | o quanto do cofre precisa ser mais novo que uma memória antes que sua evidência semântica valha metade das probabilidades. 0 desativa o prior de recência |
expire_memories | true | remover memórias expiradas automaticamente |
duplicate_threshold | 0.97 | similaridade de cosseno na qual um armazenamento é duplicado |
max_memory_chars | 200 | o limite de comprimento de uma única afirmação para memórias autorais. 0 desativa as verificações de comprimento e layout |
opinion_update_threshold | 0.80 | similaridade na qual uma nova opinião é uma atualização de uma ativa e precisa de uma decisão de substituição |
opinion_reaffirm_threshold | 0.97 | similaridade na qual uma opinião reformulada reafirma o registro ativo em vez de armazenar |
retag_interval_hours | 6 | com que frequência a passagem em segundo plano recalcula tags. 0 desativa isso |
retag_prune | false | se essa passagem também pode remover tags |
index_precision | "f32" | "int8" usa um quarto da RAM |
embed_daemon | true | pedir ao processo de incorporação compartilhado da máquina por vetores em vez de carregar o modelo neste processo |
unlock_tool_enabled | false | permite que um agente desbloqueie o cofre. Desativado porque a frase secreta cruzaria o contexto do modelo |
Ambiente
COMPARTMENT_VAULT qual cofre usar, COMPARTMENT_PASSPHRASE para scripts
e CI, COMPARTMENT_SESSION_DIR onde a credencial de desbloqueio vive,
COMPARTMENT_UI_SCALE escala do painel, COMPARTMENT_ASSERT_OFFLINE abortar em qualquer
tentativa de rede. COMPARTMENT_EMBED_DAEMON=0 mantém o modelo de incorporação
dentro de cada processo em vez do compartilhado, COMPARTMENT_EMBED_SOCKET
move o socket desse processo, COMPARTMENT_EMBED_IDLE é quantos segundos ele
sobrevive ao seu último cliente (300). HERMES_HOME, OPENCLAW_HOME e XDG_DATA_HOME são lidos
onde se aplicam. Qualquer coisa exportada como ENGRAM_* ainda funciona.
Ferramentas MCP
Cada ferramenta tem um título e uma anotação somente leitura ou destrutiva, para que um
cliente possa distinguir as sete ferramentas somente leitura das que escrevem antes de
chamar qualquer coisa. memory_search, memory_store, memory_store_many,
memory_get, memory_recent, memory_forget, memory_link,
memory_relations, memory_unlink, memory_list_namespaces,
memory_status, memory_lock, memory_selftest. memory_unlock existe, mas
está desativado, a menos que você o ative acima.
Documentação
| docs/MEMORY.md | como a memória é armazenada, o que é lembrado e o design de classificação |
| docs/INTEGRATIONS.md | selecionando Compartment no Hermes Agent, OpenClaw, Claude, e todo o resto |
| docs/COMPARISON.md | outros servidores de memória, com fontes |
| SECURITY.md | o modelo de ameaça completo e seus limites |
| FORMAT.md | especificações de .vault e .mpack em nível de byte (agnósticas de linguagem) |
| PACKS.md | criação e envio de pacotes de memória assinados |
| CONTRIBUTING.md | configuração, boas issues e as garantias a manter |
| RELEASING.md | como um lançamento é feito |
Política de Privacidade
O Compartment não coleta dados: sem telemetria, sem análises, sem conta e sem rede em tempo de execução. As memórias são armazenadas apenas na sua máquina, criptografadas com AEAD em repouso com uma frase secreta que nunca a deixa, e nada é compartilhado com ninguém. A política completa, cobrindo coleta, armazenamento, acesso à rede, compartilhamento com terceiros, retenção e contato, está em https://maxfreedompollard.github.io/Compartment/privacy.
Onde encontrá-lo
O Compartment está listado no PyPI, no registro oficial de MCP, no Cursor Directory, Glama, LobeHub, MCP Toplist, MCP Market, mcpservers.org, TensorBlock, no registro toolsdk.ai, Libraries.io, Snyk Advisor e deps.dev, e nas listas curadas abordage/awesome-mcp, TensorBlock/awesome-mcp-servers e Jenqyang/Awesome-AI-Agents.
Bugs e solicitações de recursos: Issues. Suporte e perguntas: Discussions; relatórios de segurança: SECURITY.md. Perguntas e ideias: Discussions.
mcp-name: io.github.MaxFreedomPollard/compartment