Memmy: memória local para agentes no VPS
Veja como compilar o Memmy 1.0.4 no Ubuntu, iniciar o serviço na porta 18960 e manter em um único SQLite as memórias dos agentes, sem sair do VPS.
O que é o Memmy e o que ele armazena
O Memmy é um hub de memória local para agentes de IA que é executado no seu próprio VPS (servidor virtual privado). Ele mantém um único banco de dados SQLite com o que seus agentes aprenderam, e todos os agentes no servidor leem e gravam nesse mesmo armazenamento. O projeto é memmy-agent da MemTensor, licenciado sob a MIT, na versão 1.0.4 em julho de 2026.
Apenas parte dele é relevante em um servidor. O Memmy fornece um serviço de memória que escuta em http://127.0.0.1:18960, uma interface de linha de comando (CLI) memmy-memory que se comunica com esse serviço e uma bancada de trabalho para desktop. A bancada de trabalho é distribuída somente para macOS e Windows. Portanto, em um VPS Linux, você executa o serviço e a CLI. Isso é suficiente para fornecer uma memória compartilhada ao Claude Code, ao Codex e ao Cursor.
O Memmy organiza o que armazena em quatro camadas. L1 Trace é o turno bruto: a solicitação, a resposta e as chamadas de ferramentas. L2 Policy é um procedimento derivado de traces que se mostrou útil. L3 World Model é o conhecimento estável sobre um projeto ou ambiente. Skill é um procedimento chamável cristalizado a partir de uma policy. O serviço atribui uma camada ao ingerir um turno. Portanto, você não precisa criá-las manualmente.
O que um hub de memória compartilhada muda em comparação com a memória por ferramenta
Atualmente, cada agente distribui sua própria memória. O Claude Code mantém arquivos de instruções no repositório. O Cursor mantém regras no banco de dados do workspace. O Codex mantém logs de sessão em ~/.codex. Cada armazenamento pertence a uma ferramenta, portanto um fato que você ensinou na segunda-feira em uma ferramenta é desconhecido na terça-feira em outra. Você paga duas vezes por isso: uma vez nos tokens gastos para explicar novamente o mesmo projeto e outra vez no trabalho incorreto quando um agente age com base em uma suposição que você já corrigiu em outro lugar.
Um hub move o armazenamento para fora da ferramenta. O Memmy também lê os armazenamentos existentes, portanto você não começa com um banco de dados vazio. O scanner conhece seis fontes: Claude Code em ~/.claude/projects/**/*.jsonl, Codex em ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl, OpenCode em ~/.local/share/opencode/opencode.db, os arquivos state.vscdb do Cursor, os bancos de dados SQLite do OpenClaw em ~/.openclaw e o Hermes em ~/.hermes. Você pode adicionar uma fonte manualmente, informando um nome e um caminho local.
Os contadores de importação não serão iguais, e isso é esperado. O scanner agrupa as mensagens por fonte e conversa e, em seguida, grava uma memória L1 por turno completo. Um turno é considerado completo quando tem conteúdo de usuário não vazio e termina com uma mensagem do assistant não vazia; portanto, uma sessão interrompida não contribui com nada. As mensagens são deduplicadas usando checkpoints de conversa e IDs de turno estáveis. A contagem verificada, a contagem de mensagens importadas e a contagem de novas memórias serão diferentes na mesma execução.
Esta é a parte que complementa como o Claude Code gerencia o contexto em uma única sessão. O gerenciamento de contexto decide o que cabe em uma única janela. Um hub de memória decide o que permanece depois que essa janela é fechada.
O que você precisa na VPS
- Node.js 22 ou mais recente. A documentação do Memmy exige essa versão, e o Ubuntu 24.04 inclui o Node 18.
gite uma cadeia de ferramentas de compilação, porquebetter-sqlite3é um módulo nativo que pode ser compilado durante a instalação.- Cerca de 2 GB de RAM. A instalação na conta root baixa um workspace grande e uma cadeia de compilação de frontend.
- Alguns GB de espaço livre em disco para
node_modulese o banco de dados.
sudo apt update
sudo apt install -y git build-essential python3 curl ca-certificates sqlite3
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node --versionnode --version deve exibir v22 ou mais recente. Um valor v18 aqui indica que a etapa do NodeSource não foi aplicada, e a instalação falhará posteriormente na verificação do engine do projeto.
Instalar o Memmy a partir do código-fonte no Ubuntu 24.04
git clone https://github.com/MemTensor/memmy-agent.git
cd memmy-agent
cp .env.example .env
npm install
npm run memory:buildnpm run memory:build compila o workspace do @memmy/memory em Memory/dist. Nada mais na árvore precisa ser compilado em um servidor headless. Verifique se o módulo nativo foi carregado:
node -e "require('better-sqlite3'); console.log('better-sqlite3 loads')"Se essa linha gerar um erro em vez de imprimir a saída, o módulo nativo não é compatível com sua versão do Node. Execute npm rebuild better-sqlite3, que é exatamente o que o script de inicialização do próprio projeto faz antes de iniciar qualquer coisa.
O README documenta bash scripts/dev-start.sh como um comando de inicialização. Não o execute em um VPS headless. Ele inicia o shell de desktop do Electron e um servidor de desenvolvimento Vite na porta 19000, junto ao serviço de memória. O Electron precisa de um display. Portanto, em um servidor sem uma sessão gráfica, o script fica travado ou é encerrado.
Inicie o serviço de memória e verifique se ele responde
npm run memory:serve:devEssa é a forma documentada de executar o serviço de memória a partir do código-fonte. Ele faz bind em 127.0.0.1:18960, mantém o banco de dados em ~/.memmy/memory-service/memory.sqlite e lê a configuração de ~/.memmy/config.yaml. O README especifica os mesmos valores quando você precisa informá-los explicitamente:
npm run memory:serve:dev -- \
--host 127.0.0.1 --port 18960 \
--db ~/.memmy/memory-service/memory.sqlite \
--config ~/.memmy/config.yamlEm um segundo shell, verifique se o serviço está ativo:
curl -sS http://127.0.0.1:18960/api/v1/healthHealth é o único endpoint que nunca solicita um token, por isso é a sonda adequada. Se curl sair com o código 7 e uma mensagem Failed to connect to 127.0.0.1 port 18960, nada está escutando. Leia o terminal que executa o serviço, porque uma falha na inicialização é exibida nele. A causa mais comum é a falha ao carregar o módulo nativo do SQLite. ss -lntp | grep 18960 confirma o socket quando o serviço está ativo.
O restante da API HTTP (interface de programação de aplicações) fica em /api/v1.
POST /api/v1/memory/addgrava uma memória ePOST /api/v1/memory/searchfaz consultas.GET /api/v1/memory/:ideDELETE /api/v1/memory/:idleem e removem uma entrada.POST /api/v1/sessions/openePOST /api/v1/sessions/:sessionId/closedelimitam uma sessão do agente.POST /api/v1/turns/startePOST /api/v1/turns/:turnId/completeregistram um turno.GET /api/v1/panel/overview,/api/v1/panel/analysise/api/v1/panel/itemsalimentam o dashboard.
O Memmy reserva um bloco de portas. Em uma execução sem interface gráfica, você usa apenas a primeira: 18960 para a memória, 18970 para a verificação de integridade do gateway, 18980 para a interface web e o HTTP administrativo, 18990 para a API compatível com OpenAI iniciada por memmy serve, e 19000 e 19010 para o servidor de desenvolvimento do frontend para desktop. Se algum processo no seu host já usar uma delas, essa é a lista que você deve verificar.
De onde realmente vem o comando memmy-memory
É aqui que uma primeira instalação costuma dar errado. Leia essas informações a partir do pacote, em vez de fazer suposições. O nome do comando não tem relação com o nome do repositório. Ele vem do campo bin do workspace que o define:
node -p "JSON.stringify(require('./Memory/package.json').bin)"Isso exibe {"memmy-memory":"./dist/src/cli/index.js"}. Portanto, o entry point compilado é Memory/dist/src/cli/index.js. Ele só existe depois de npm run memory:build, porque o build cria dist e marca o arquivo como executável. Execute-o diretamente:
node Memory/dist/src/cli/index.js healthSe quiser o nome curto no PATH, crie um link para o mesmo arquivo:
sudo ln -s "$PWD/Memory/dist/src/cli/index.js" /usr/local/bin/memmy-memory
memmy-memory healthA CLI usa http://127.0.0.1:18960 por padrão e aceita --url, --token, --config, --source e --user-id. Seus subcomandos são init, health, search, add, get e delete, além de chamadas de sessão e de turno que os agentes usam, e não as pessoas. memmy-memory search "deploy steps" e memmy-memory add "staging migrates on deploy" são os dois que um agente executa com mais frequência.
Como conectar o Claude Code ao Memmy?
O Claude Code não tem uma interface de plugin de memória, portanto o Memmy não se conecta diretamente a ele. A integração é mais simples. O Claude Code executa memmy-memory como um comando shell comum, e um arquivo de instruções informa quando fazer isso. O instalador documentado do Memmy cria esse arquivo para você: memmy-memory init --agent grava um arquivo de instruções de memória no diretório de regras do agente de destino.
Escreva a instrução manualmente uma vez. Assim, você sabe exatamente o que foi informado ao agente. O Claude Code lê CLAUDE.md a partir da raiz do projeto no início de cada sessão. Portanto, uma seção como esta é toda a integração:
## Memory
Before starting a task, run `memmy-memory search "<topic>"` and read what comes back.
When a task is done, run `memmy-memory add "<what you learned>"` for anything that will matter next session.Defina claramente o que isso oferece. Trata-se de uma integração no nível das instruções. Ela funciona quando o modelo decide executar o comando, e não funciona caso contrário. Nada força a chamada. Se uma sessão terminar sem add, nada será salvo. O único sinal será um resultado vazio na próxima pesquisa. Essa é a mesma limitação dos próprios arquivos de memória do Claude Code, com uma diferença: o armazenamento é compartilhado. Assim, a anotação também fica disponível para o Codex e o Cursor na mesma máquina.
A outra direção não exige nenhuma configuração. O scanner do Memmy já lê ~/.claude/projects/**/*.jsonl, que é onde o Claude Code grava as transcrições das sessões. Execute o Memmy no mesmo servidor em que você executa o Claude Code dentro de uma sessão tmux para que o trabalho de ontem se torne memória sem nenhuma configuração adicional.
O Memmy funciona como um servidor MCP para o Claude Code?
Não. Saber disso evita perder uma tarde. O MCP (model context protocol) tem clientes e servidores. O Memmy é um cliente. Ele se conecta a servidores MCP e disponibiliza as ferramentas deles para seu próprio ambiente de execução do agente. Ele não publica um endpoint MCP ao qual claude mcp add possa se conectar. A única ponte MCP no repositório pertence à integração do Composio dentro da API local da área de trabalho, e essa API escuta em uma porta aleatória em 127.0.0.1, protegida pelo próprio cabeçalho x-memmy-mcp-token.
O lado cliente é configurado em ~/.memmy/config.yaml, o arquivo indicado por MEMMY_CONFIG, em tools.mcpServers:
tools:
mcpServers:
example:
type: stdio
command: npx
args:
- "-y"
- "your-mcp-server"
toolTimeout: 30
enabledTools:
- "*"type aceita stdio, sse e streamableHttp. Um servidor stdio é executado como um processo filho do Memmy. Portanto, o comando precisa existir no mesmo host e ser executado pelo mesmo usuário. Se você já mantém servidores MCP em execução em um VPS, são esses servidores que devem ser listados aqui.
Mantendo o armazenamento de memória privado
Tudo o que o Memmy possui fica em ~/.memmy: config.yaml, o workspace, memory-service/memory.sqlite e os arquivos de runtime. A varredura e a ingestão ocorrem localmente, e as memórias são gravadas nesse arquivo SQLite local. Portanto, a postura padrão é realmente local.
Dois caminhos acessam a rede. MEMMY_CLOUD_SERVICE usa https://memmy-api.memtensor.cn por padrão e oferece o modo de conta com seus tokens de avaliação. Por isso, o modo de chave de API nunca o chama. O programa de melhoria de memória é uma opção separada nas configurações de privacidade e permanece desativado até que você o ative.
Um terceiro caminho é mais fácil de ignorar. Se você configurar um provedor de embeddings hospedado, o texto de cada memória será enviado a esse provedor para ser transformado em um vetor. O armazenamento local não impede esse envio. Um endpoint de embeddings hospedado por você é a única forma de eliminá-lo.
Mantenha a porta 18960 no endereço de loopback. Ela não precisa de uma regra de firewall, porque um serviço vinculado a 127.0.0.1 não pode ser acessado de fora do host. Acesse-o do seu laptop por SSH:
ssh -N -L 18960:127.0.0.1:18960 you@your-vpsSe você vincular o serviço a um endereço mais amplo, defina um token primeiro. Definir storage.token na configuração, ou a variável de ambiente MEMMY_MEMORY_TOKEN ou MEMORY_SERVICE_TOKEN, faz com que todos os endpoints, exceto o de health, exijam um bearer token. Os valores de configuração aceitam referências ${ENV_NAME}. Assim, o token e suas chaves de API dos modelos permanecem fora do próprio arquivo. Esse é o mesmo procedimento usado para manter segredos fora dos agentes de IA em outros contextos, e uma política ufw de negação padrão funciona como proteção adicional caso uma versão futura altere o endereço de bind padrão.
Faça backup de ~/.memmy antes de confiar nele
memory.sqlite é todo o armazenamento. Os vetores ficam nesse mesmo arquivo por meio da extensão sqlite-vec, portanto um único arquivo é suficiente para o backup. Copiá-lo com cp enquanto o serviço está gravando pode produzir um banco de dados inconsistente. Use o comando de backup do próprio SQLite:
mkdir -p ~/memmy-backup
sqlite3 ~/.memmy/memory-service/memory.sqlite ".backup '$HOME/memmy-backup/memory.sqlite'"Isso produz uma cópia consistente enquanto o serviço continua em execução. Envie essa cópia para fora do servidor regularmente, usando restic para armazenamento externo. Perder config.yaml custa as configurações do provedor, que podem ser digitadas novamente. Perder memory.sqlite custa todas as memórias, e nenhum outro local na máquina mantém uma segunda cópia.
Execute o serviço de memória no systemd
npm run memory:serve:dev em um shell é encerrado junto com o shell. Um arquivo de unidade mantém o serviço em execução após reinicializações.
[Unit]
Description=Memmy memory service
After=network-online.target
[Service]
Type=simple
User=memmy
WorkingDirectory=/opt/memmy/memmy-agent
EnvironmentFile=/etc/memmy/memory.env
ExecStart=/usr/bin/npm run memory:serve:dev
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetMantenha o token fora da unidade. Coloque-o em /etc/memmy/memory.env, pertencente a root, com modo 600:
MEMMY_CONFIG=/home/memmy/.memmy/config.yaml
MEMMY_MEMORY_TOKEN=replace-this-with-a-long-random-stringsudo systemctl daemon-reload
sudo systemctl enable --now memmy-memory
systemctl status memmy-memory --no-pager
curl -sS http://127.0.0.1:18960/api/v1/healthstatus=203/EXEC na saída de status significa que o systemd não conseguiu executar ExecStart de forma alguma. Portanto, verifique which npm: ele fica em /usr/bin/npm em uma instalação do NodeSource e em algum local dentro do diretório inicial do usuário no nvm, que o systemd não encontrará. Uma unidade que inicia e encerra imediatamente falhou dentro do npm. journalctl -u memmy-memory -n 50 exibe o motivo. O funcionamento é igual ao de qualquer outro serviço systemd em um VPS.
O que o Memmy ainda não faz
- Não há uma compilação para desktop Linux. Os scripts de empacotamento abrangem macOS e Windows, portanto o workbench, o assistente de onboarding e o painel de memória não estão disponíveis no próprio servidor.
memory:serve:devexecuta o ponto de entrada TypeScript por meio detsx, um caminho de desenvolvimento. O repositório também incluimemory:servepara a saída compilada. Executenpm runsem argumentos para ver quais scripts o seu checkout realmente possui.- A recuperação cria a janela de pesquisa a partir das 2,000 linhas de vetores mais recentes e, em seguida, aplica a seleção Top-K dentro dessa janela. Em um armazenamento muito grande, uma memória antiga pode ficar fora dela.
- A geração de embeddings ocorre depois da captura, e uma falha vai para uma fila de novas tentativas em vez de bloquear o turno do agente. Uma memória adicionada há pouco pode ainda não estar disponível para a pesquisa vetorial.
- Um único arquivo SQLite corresponde a um único nó. Não há clustering, portanto um segundo servidor representa uma memória separada.
A versão 1.0.4 e aproximadamente 329 estrelas em julho de 2026 descrevem um projeto recente. Flags, caminhos e nomes de scripts mudam entre as versões. Leia o campo bin e a saída de npm run no seu próprio checkout, em vez de confiar em um comando copiado de qualquer lugar, inclusive daqui.
FAQ
Por que a verificação de integridade retorna conexão recusada?
Nada está escutando na porta 18960. Um código de saída 7 do curl com Failed to connect to 127.0.0.1 port 18960 significa que o serviço de memória não está em execução ou falhou na inicialização. Leia o terminal ou o journal onde ele foi iniciado. As duas causas mais comuns são um módulo nativo better-sqlite3 incompatível com sua versão do Node, corrigido com npm rebuild better-sqlite3, e uma versão do Node inferior a 22. Confirme o socket com ss -lntp | grep 18960 quando o serviço estiver em execução.
De onde vem o comando memmy-memory após a compilação a partir do código-fonte?
Do campo bin do pacote de workspace @memmy/memory, não do nome do repositório. Execute node -p "JSON.stringify(require('./Memory/package.json').bin)" dentro do checkout para exibir {"memmy-memory":"./dist/src/cli/index.js"}. Esse arquivo só existe após npm run memory:build, porque a compilação cria dist e marca o arquivo como executável. Execute-o como node Memory/dist/src/cli/index.js health ou crie um link simbólico para ele em /usr/local/bin para usar o nome curto.
Posso adicionar o Memmy ao Claude Code com claude mcp add?
Não. O Memmy é um cliente MCP, não um servidor MCP. Ele se conecta aos servidores listados em tools.mcpServers no arquivo ~/.memmy/config.yaml e disponibiliza as ferramentas deles para o próprio runtime. O Claude Code acessa o Memmy no sentido inverso, executando a CLI memmy-memory como um comando de shell, orientado por um arquivo de instruções que memmy-memory init --agent grava no diretório de regras do agente.
Executar o Memmy envia minhas memórias para um serviço de nuvem?
A análise e a ingestão são executadas localmente, e as memórias são gravadas em ~/.memmy/memory-service/memory.sqlite no seu próprio disco. MEMMY_CLOUD_SERVICE aponta para https://memmy-api.memtensor.cn no modo de conta e para tokens de avaliação, e o programa de melhoria da memória permanece desativado até que você o habilite. O ponto a monitorar é o provedor de embeddings: um modelo de embeddings hospedado recebe o texto de cada memória que transforma em um vetor. Use um endpoint executado por você mesmo se isso for importante.