Engram: memória persistente para agentes no Linux

Mascote do LinuxPro encaixando um cartucho de memória no SQLite, com o elefante do Engram na bancada

El agente de terminal es genial hasta que termina la sesión. En la siguiente, redescubre el mismo bug, vuelve a leer el mismo README y pregunta otra vez si la API usa JWT. Engram es un cerebro local para eso: un binario en Go, un SQLite con FTS5 en ~/.engram/engram.db, y la misma base de datos para Claude Code, Codex, Cursor, Grox y cualquier otro cliente MCP.

No es un cubo de transcripts. El agente decide qué vale la pena recordar: decisión, bug, convención, y lo guarda con mem_save. En la siguiente sesión, mem_search y mem_context devuelven el trozo adecuado. El mapa de alternativas (mnemo, Leteo, Subcog…) está en Alternativas a Claude-Mem en Go, Rust y C; el mapa de los agentes en terminal, en Asistentes de IA en el terminal Linux. Este post es el paso a paso de Engram en Linux: instalar, conectarlo a los agentes, ajustar el nombre del proyecto y dejar el daemon en el arranque.

O que é — e o que não é

Engram (/ˈen.ɡræm/, el rastro físico de un recuerdo en el cerebro) es un binario Go con SQLite integrado mediante modernc.org/sqlite: Go puro, sin CGO, sin Node, sin Python, sin Docker para el uso diario. Licencia MIT. La línea estable en julio de 2026 es la v1.20.0.

Quatro portas para o mesmo banco:

Porta Comando Para quê
MCP stdio engram mcp --tools=agent O agente fala com a memória (Claude, Grok, Codex…)
CLI engram search, save, context Você consulta e grava na mão
TUI engram tui Navegar sessões e observações no terminal
HTTP local engram serve (porta 7437) API JSON. No es una página de navegador

El dashboard HTML (/dashboard) es el Engram Cloud, otro proceso, Postgres, opcional. Sin Cloud, el visor local es el TUI.

A filosofia, explícita no README: o agente já tem o LLM e o contexto. Em vez de capturar cada tool call e comprimir depois (o modelo do claude-mem), o Engram pede que o agente grave só o que dura. Resultado: busca FTS5 limpa, zero chamada extra de API, um arquivo que você controla.

Instalar no Ubuntu/Linux

No existe paquete apt ni .deb en las releases. Lo que pide la documentación de producción es el binario. Un archivo, cero runtime: sin Node, sin Python, sin Docker. La línea estable en julio de 2026 es la v1.20.0.

Os releases oferecem binários Linux prontos para amd64 e arm64. O executável oficial é estaticamente ligado, sem dependências de runtime; escolha apenas o arquivo da arquitetura da máquina. Para compilar do código-fonte, o requisito é Go 1.24+.

Ubuntu amd64 e arm64

sudo apt-get update
sudo apt-get install -y curl ca-certificates

VER=1.20.0
case "$(dpkg --print-architecture)" in
  amd64) FILE=engram_${VER}_linux_amd64.tar.gz ;;
  arm64) FILE=engram_${VER}_linux_arm64.tar.gz ;;
  *) echo "sem binário pronto para $(dpkg --print-architecture)"; exit 1 ;;
esac

cd /tmp
curl -fsSL -O "https://github.com/Gentleman-Programming/engram/releases/download/v${VER}/${FILE}"
curl -fsSL -O "https://github.com/Gentleman-Programming/engram/releases/download/v${VER}/checksums.txt"
sha256sum -c checksums.txt --ignore-missing

mkdir -p ~/.local/bin
tar -xzf "$FILE" engram
install -m 755 engram ~/.local/bin/engram

# o ~/.profile do Ubuntu só acrescenta ~/.local/bin no próximo login,
# e só se o diretório já existir
export PATH="$HOME/.local/bin:$PATH"
hash -r
engram version

A saída esperada é engram 1.20.0. O tarball traz o executável na raiz, mais README, LICENSE e CHANGELOG. Banco padrão: ~/.engram/engram.db.

Para que el PATH quede permanente, abre una terminal nueva después de la instalación. El ~/.profile por defecto de Ubuntu ya trae el bloque if [ -d "$HOME/.local/bin" ] — por eso el mkdir va antes que el install.

go install

Si ya tienes Go 1.24+ (el de la documentación). El paquete golang-go de Ubuntu 24.04 es 1.22 y el de 22.04 es 1.18 — no se puede go install por ahí; usa el binario de la release o instala Go desde su web:

go install github.com/Gentleman-Programming/engram/cmd/engram@latest
# cai em $(go env GOPATH)/bin — em geral ~/go/bin/

go install carimba a versão como dev. Se quiser o git-describe no engram version, clone e passe -ldflags — um go install e um go build no mesmo PATH deixam dois binários e a versão “dev” ganha. Há uma linha v2 (github.com/Gentleman-Programming/engram/v2/cmd/engram) para release candidates; produção continua na v1.

Homebrew no Linux

brew install gentleman-programming/tap/engram

El tap cubre la línea estable v1.20.0. Actualización: brew update && brew upgrade engram. Cambiar el binario mata un engram serve suelto — por eso el servicio systemd, más abajo.

Primeiro contato

engram version
engram stats
engram projects list
engram tui

Banco padrão: ~/.engram/engram.db. Override: ENGRAM_DATA_DIR. No TUI, j/k navega, Enter abre, / busca, Esc volta. Tema Catppuccin Mocha.

A API local, se você subir o daemon:

engram serve          # 127.0.0.1:7437
curl -s http://127.0.0.1:7437/health
# {"service":"engram","status":"ok","version":"0.1.0"}

/ y /dashboard en ese puerto devuelven 404. Es JSON, no un sitio. GET /project/current usa el cwd del proceso serve — en systemd con WorkingDirectory=%h, eso se convierte en el basename del home, no el repo en el que estás editando.

Ligar nos agentes

engram setup escribe el MCP en el formato de cada cliente. No configura Cloud. Reinicia el agente después.

Agente Comando
Claude Code claude plugin marketplace add Gentleman-Programming/engram e claude plugin install engram — ou engram setup claude-code
Codex engram setup codex
OpenCode engram setup opencode
Cursor engram setup cursor
Gemini CLI engram setup gemini-cli
VS Code Copilot engram setup vscode-copilot
Windsurf, Qwen, Kiro, Kilo, Pi, Antigravity engram setup <nome> — lista em engram --help

Perfiles MCP: agent (el conjunto que usa el agente en el día a día), admin, o all. El valor por defecto de engram mcp sin flag es all. Para el agente, usa --tools=agent.

Grok Build (manual)

Não há engram setup grok. Em ~/.grok/config.toml:

[mcp_servers.engram]
command = "/home/SEU_USER/.local/bin/engram"
args = ["mcp", "--tools=agent"]
enabled = true

Confira com grok mcp doctor engram — handshake ok e as tools do perfil agent. Recarregue a sessão do Grok: o MCP só entra na que sobe depois da config. O banco é o mesmo do Claude. O nome do projeto, não: cada processo detecta pelo próprio cwd.

Qualquer cliente MCP

{
  "mcpServers": {
    "engram": {
      "command": "engram",
      "args": ["mcp", "--tools=agent"]
    }
  }
}

O cliente dispara um processo stdio por sessão. Isso não substitui o engram serve do systemd — são coisas diferentes. MCP lê e grava o SQLite direto; o serve é a API HTTP (e o autosync Cloud, se você ligar).

Como o Engram escolhe o projeto

Ele não indexa o path. Resolve um nome e filtra o SQLite por esse nome. Precedência:

  1. argumento explícito (mem_context con project, engram context teste);
  2. override de processo (engram mcp --project … o ENGRAM_PROJECT);
  3. detecção pelo cwd.

A detecção do diretório, em ordem:

# source O que usa
0 config .engram/config.json con project_name
1 git_remote repo com origin — nome do remote, gravado num binding privado do clone
2 git_root git sem origin — basename da raiz
3 git_child cwd tem exatamente um filho git — promove esse
4 ambiguous vários filhos git — não escolhe sozinho
5 dir_basename último recurso: filepath.Base(cwd)

Pasta sem git vira o basename. Claude gravando em /home/você/teste e Grok em …/site-linuxpro são dois projetos. A memória não aparece “do outro lado” até você buscar com o nome certo ou all_projects=true.

Lock estável na raiz do repo:

{
  "project_name": "site-linuxpro"
}

O Engram usa o config mais próximo abaixo da raiz git — dá para ter backend/.engram/config.json e frontend/.engram/config.json no monorepo. Fora de git, só vale o config do diretório atual: ~/.engram/config.json não vaza para os filhos. Primeira chamada útil de qualquer sessão: mem_current_project — devolve project, project_source e, se for o caso, available_projects.

Se a escrita voltar ambiguous_project, o agente não pode chutar. Você escolhe um nome da lista e a tool retenta com project_choice_reason=user_selected_after_ambiguous_project.

Subir o serve no boot

Esta seção é opcional. Claude Code, Codex e os demais clientes MCP via stdio usam engram mcp e não precisam de engram serve. Suba o serviço se precisar da API HTTP local, do autosync do Cloud ou de integrações HTTP, como OpenCode e Pi.

Quando ele for necessário, um supervisor evita que engram serve morra no reboot ou durante a troca do binário.

Unit de usuário, no template oficial:

# ~/.config/systemd/user/engram.service
[Unit]
Description=Engram Memory Server
After=network.target

[Service]
WorkingDirectory=%h
ExecStart=%h/.local/bin/engram serve
Restart=always
RestartSec=3
Environment=ENGRAM_DATA_DIR=%h/.engram
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target
mkdir -p ~/.engram ~/.config/systemd/user
systemctl --user daemon-reload
systemctl --user enable --now engram.service
curl -s http://127.0.0.1:7437/health
journalctl --user -u engram -f

enable amarra no login. Para subir no boot sem sessão gráfica, o usuário precisa de linger:

loginctl enable-linger "$USER"
loginctl show-user "$USER" -p Linger

Se a 7437 já estiver ocupada por um serve órfão, a unit falha no bind. Mate o processo antigo (ss -tlnp | grep 7437) e systemctl --user restart engram.

O contrato de memória

O README trata o Engram como memória curada, não como dump. O ciclo:

  1. Orientarmem_current_project, depois mem_context / mem_search.
  2. Buscar antes de repetir — decisão, bug, convenção que já podem estar no banco.
  3. Revelar por camadasmem_search devolve preview (~300 caracteres); mem_get_observation traz o texto inteiro; mem_timeline mostra o antes/depois na sessão.
  4. Gravar o que duramem_save com título curto, tipo (decision, bugfix, config, architecture…) e corpo What / Why / Where / Learned. Não grave saída crua de ferramenta.
  5. Assunto que evoluitopic_key estável (architecture/auth-model). Mesmo projeto + scope + topic vira upsert, não uma linha nova.
  6. Fechar a sessãomem_session_summary com Goal, Discoveries, Accomplished, Next Steps, Files.

Scope: project (default), personal ou global. Um personal no mesmo topic_key não sobrescreve o de projeto.

O que não vai para o SQLite: senha, token, dump de journalctl. O git continua sendo o registro — a história está em A história do Git. Tags <private> são removidas em duas camadas no Engram; mesmo assim, não grave o que não pode vazar.

Cloud e dashboard no navegador

O Cloud é replicação opcional + UI. SQLite local continua autoritativo. Caminho smoke com Docker, no clone do repositório:

docker compose -f docker-compose.cloud.yml up -d
engram cloud config --server http://127.0.0.1:18080
engram cloud enroll meu-projeto
engram sync --cloud --project meu-projeto

Dashboard local: http://127.0.0.1:18080/dashboard. No compose smoke, /dashboard/login redireciona sem pedir token. Rotas úteis: /dashboard/browser, /dashboard/projects, /dashboard/activity.

Para o dia a dia num laptop, Cloud é extra. TUI + MCP bastam.

Dicas que evitam dor

  • Um cérebro, nomes certos. Claude, Grok e Codex só compartilham memória se o project for o mesmo. Coloque .engram/config.json no repo no primeiro dia.
  • Não instale três servidores de memória no mesmo agente. Eles competem pelo contexto. Um de sessão (Engram) + o grafo do código (codebase-memory-mcp) já é o teto útil — o encaixe no fluxo está em Vibe coding no Linux.
  • MCP ≠ serve. O Grok/Claude sobe engram mcp via stdio. O systemd sobe engram serve na 7437. Os dois podem coexistir; um não substitui o outro.
  • Cwd do serve. Unit com WorkingDirectory=%h faz /project/current responder o basename da home. Para leitura de projeto, use o MCP do agente (cwd do repo) ou passe --project.
  • Busca FTS5 é AND por padrão. match_mode=any alarga. Preview não é o registro completo — abra o id.
  • Doctor. engram doctor (ou mem_doctor) checa lock do SQLite, mismatch de sessão e binding. Quatro checks ok é o estado saudável.
  • Linger. Sem loginctl enable-linger, a unit de usuário só vive enquanto houver sessão. Com linger, sobrevive ao reboot headless.
  • Upgrade do binário. Homebrew ou um install por cima mata o processo se não houver systemd com Restart=always.
  • Não misture autosync nativo e wrappers de cron. A documentação pede um modo só.
  • HTTP token. ENGRAM_HTTP_TOKEN protege delete/export/import na API local. Sem ele, essas rotas ficam abertas em 127.0.0.1 — ok no laptop, ruim se você publicar a 7437 na LAN.

Engram ou claude-mem?

O Engram nasceu inspirado no claude-mem, com decisões opostas: binário único, qualquer agente MCP, FTS5 em vez de worker + ChromaDB, o agente comprime na hora em vez de um pipeline à parte. Se a sua vida é só Claude Code e você já está no ecossistema de hooks dele, o original continua válido. Se Claude, Codex e Grok precisam lembrar a mesma decisão, comece pelo Engram. Comparação lado a lado e as outras opções em Go/Rust/C: Alternativas ao Claude-Mem.

Fechando

Instale o binário da release, trave o nome do projeto num .engram/config.json, ligue o MCP em cada agente e deixe o engram serve no systemd de usuário. O resto é disciplina: gravar o que dura, buscar antes de repetir, fechar a sessão com um resumo. O agente da manhã seguinte já sabe que a autenticação é JWT — e você não paga um segundo modelo só para lembrar disso.

Para continuar: asistentes de IA en el terminal, Ollama se a inferência também for local, e a história do Go — a língua em que o Engram é um arquivo só.

Links oficiais: github.com/Gentleman-Programming/engram · releases · engram.gentlemanprogramming.com · Installation · Agent Setup