Desenvolvedores
Configuração avançada e infraestrutura
Para quando o servidor sai do seu laptop. Cada tópico traz um diagrama ou uma tabela, a menor config correta e um link para o documento completo no GitHub.
Quatro lugares onde ele roda
O binário é o mesmo nos quatro. Muda o endereço de bind e, com ele, quanto de autenticação e criptografia você fica devendo.

| Topologia | Bind | Autenticação | TLS | Roda como |
|---|---|---|---|---|
| Só o laptop | 127.0.0.1:49374 | Não precisa | Não | unit de usuário do systemd, agente do launchd ou um container |
| Máquina de homelab | 0.0.0.0:49374 | Bearer token e allowlist de hosts, os dois obrigatórios | Recomendado | Docker com healthcheck, ou o serviço de sistema do AUR |
| LAN com TLS | 0.0.0.0:49374 atrás de um proxy | Token root, mais um usuário e uma chave de API por pessoa | Sim. O Caddy com a CA interna funciona sem domínio | Docker Compose com um sidecar do Caddy |
| Túnel | Nenhuma porta no host | Igual ao servidor na LAN | Sim, na borda da Cloudflare | Docker Compose com um sidecar do cloudflared |
Um laptop pode dispensar o HTTP por completo com ai-memory serve --transport stdio. Para homelab, o repositório traz um script bin/deploy com templates de compose e de env. Siga o passo a passo de deploy em homelab.
TLS com um proxy reverso
O ai-memory não termina TLS, e isso é decisão de projeto. Um bearer token autentica a requisição. Ele não a criptografa.
Você pode dispensar o TLS quando
- o agente fala com ele por stdio
- o servidor só escuta em loopback, para um usuário, e ninguém abre
/webde outra máquina - é desenvolvimento local ou um experimento pontual
Você precisa de TLS quando
- existem contas, porque aí as chaves
aim_trafegam pela rede - o bind do servidor vai além do loopback
- você abre
/webde outra máquina - o servidor é acessível de fora da LAN

Para um domínio público com as portas 80 e 443 acessíveis. O Caddy emite e renova sozinho o certificado da Let’s Encrypt. O arquivo compose completo está no repositório como docker/compose.tls.caddy.yml.
memory.example.com {
reverse_proxy ai-memory:49374
}
Sem domínio e sem nada exposto. A CA interna do Caddy assina o certificado, e você instala o certificado raiz dela uma vez em cada máquina cliente. Se pular esse passo, os clientes recusam a conexão ou se acostumam a ignorar os avisos.
{
local_certs # manda o Caddy usar a CA interna em vez da LE
}
homelab.local, 192.168.1.50 {
reverse_proxy ai-memory:49374
}
docker compose exec caddy cat /data/caddy/pki/authorities/local/root.crt > caddy-root.crt
Para quem já roda nginx e tem os arquivos do certificado. HTTP/1.1 e o header Connection vazio são obrigatórios para o transporte streamable HTTP do MCP.
server {
listen 443 ssl http2;
server_name memory.example.com;
ssl_certificate /etc/nginx/certs/memory.crt;
ssl_certificate_key /etc/nginx/certs/memory.key;
location / {
proxy_pass http://ai-memory:49374;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
Um túnel só de saída, então nenhuma porta é aberta no seu roteador. Precisa de um domínio na Cloudflare, e o plano gratuito serve. No dashboard, aponte o hostname público para http://ai-memory:49374. O arquivo compose completo é o docker/compose.tls.cloudflared.yml.
cloudflared:
image: cloudflare/cloudflared:latest
container_name: ai-memory-tunnel
restart: unless-stopped
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
Depois avise o servidor
A allowlist precisa incluir o hostname público, senão a proteção contra DNS rebinding rejeita as requisições do proxy. A opção de cookie seguro é obrigatória assim que as pessoas fazem login por um listener fora do loopback.
AI_MEMORY_AUTH_TOKEN=...long-random-token-from-generate-auth-token...
AI_MEMORY_AUTH__SECURE_COOKIE=true
AI_MEMORY_ALLOWED_HOSTS=memory.example.com,localhost,127.0.0.1
AI_MEMORY_BIND=0.0.0.0:49374
E reaponte os clientes
A URL do MCP termina em /mcp. A URL dos hooks é só a origem.
ai-memory install-mcp --client claude-code --apply \
--server-url "https://memory.example.com/mcp" --auth-token "$AI_MEMORY_AUTH_TOKEN"
ai-memory install-hooks --agent claude-code --apply \
--server-url "https://memory.example.com" --auth-token "$AI_MEMORY_AUTH_TOKEN"
Leia o guia completo de HTTPS, com subpaths e timeouts de proxy para execuções longas de bootstrap
Mantenha o servidor no ar
O ai-memory não se reinicia sozinho. Quem faz isso é o gerenciador de serviços de cada sistema operacional.
Para uma workstation de um usuário só. Os pacotes do AUR instalam a unit. Não precisa de sudo e guarda o estado em ~/.local/share/ai-memory. Uma unit de usuário para no logout, a menos que você habilite o lingering.
systemctl --user daemon-reload
systemctl --user enable --now ai-memory.service
systemctl --user status ai-memory.service
journalctl --user -u ai-memory.service -f
# continua rodando depois do logout
loginctl enable-linger "$USER"
Para uma workstation compartilhada ou uma máquina na LAN. Os dados ficam em /var/lib/ai-memory, a config em /etc/ai-memory/config.toml e os segredos em /etc/ai-memory/env. Não rode as duas units no mesmo endereço de bind.
sudo systemd-sysusers /usr/lib/sysusers.d/ai-memory.conf
sudo systemd-tmpfiles --create /usr/lib/tmpfiles.d/ai-memory.conf
sudo -u ai-memory ai-memory \
--data-dir /var/lib/ai-memory \
--config /etc/ai-memory/config.toml \
init
sudo systemctl daemon-reload
sudo systemctl enable --now ai-memory.service
journalctl -u ai-memory.service -f
Os tarballs de macOS incluem um plist de LaunchAgent com dois placeholders. Rode isto a partir do tarball extraído. Um LaunchAgent para no logout, e o macOS não tem nada equivalente ao lingering. Nada rotaciona os dois arquivos de log dele.
mkdir -p ~/Library/Logs/ai-memory
AI_MEMORY_BIN=~/Applications/ai-memory/ai-memory
sed -e "s|__AI_MEMORY_BIN__|$AI_MEMORY_BIN|" \
-e "s|__HOME__|$HOME|" \
packaging/launchd/com.github.akitaonrails.ai-memory.plist \
> ~/Library/LaunchAgents/com.github.akitaonrails.ai-memory.plist
launchctl bootstrap gui/$(id -u) \
~/Library/LaunchAgents/com.github.akitaonrails.ai-memory.plist
O ai-memory não tem dispatcher de Windows Service, então sc create apontando para o exe não funciona, e uma Scheduled Task com Start-Process morre no próximo reboot. O WinSW faz esse papel. Use caminhos absolutos: um serviço roda como LocalSystem, e %LOCALAPPDATA% expandiria para o perfil errado.
<service>
<id>ai-memory</id>
<name>ai-memory MCP server</name>
<description>Long-term memory server for AI coding agents.</description>
<executable>C:\Users\you\AppData\Local\ai-memory\ai-memory.exe</executable>
<arguments>--data-dir "C:\Users\you\AppData\Local\ai-memory" serve --transport http --bind 127.0.0.1:49374</arguments>
<startmode>Automatic</startmode>
<onfailure action="restart" delay="5 sec"/>
<log mode="roll"/>
</service>
& "$Dest\ai-memory-service.exe" install
& "$Dest\ai-memory-service.exe" start
& "$Dest\ai-memory-service.exe" status
units do systemd no guia de instalaçãolaunchd no guia de macOSWinSW no guia de Windows
O diretório de dados e os backups
A wiki é a verdade. É markdown puro num repositório git, e o índice de busca é construído a partir dela.
O reindex reconstrói páginas, links e busca full-text a partir da wiki. Ele não traz de volta sessões, observações, handoffs, usuários, chaves, linhas de auditoria nem embeddings, então o banco continua tendo que entrar no seu backup.
| Diretório | O que guarda | Tipo | Faz backup? |
|---|---|---|---|
wiki/ | Todas as páginas em markdown, num repositório git só | Verdade | Sim. Ele entra no tarball de backup, e você também pode usar rsync ou git push |
raw/ | Segmentos de transcrição imutáveis e sanitizados das execuções gerenciadas | Verdade | Sim, se você usa ai-memory run. Copie à parte |
db/ | memory.sqlite: índice full-text, entidades, embeddings, sessões, usuários, linhas de auditoria | Quase todo derivado | Sim. Páginas, links e busca se reconstroem a partir da wiki. Sessões, handoffs, usuários e chaves só existem aqui |
models/ | O modelo local de embeddings, cerca de 87 MB | Reconstruível | Não. Ele é baixado de novo, ou você mesmo coloca os arquivos |
logs/ | Saída de trace com rotação | Descartável | Não |
Padrões: ~/.local/share/ai-memory no Linux, ~/Library/Application Support/ai-memory no macOS, %LOCALAPPDATA%\ai-memory no Windows, /data no container. Para mudar, use AI_MEMORY_DATA_DIR.
Backup e restore

Fazer backup
Ele usa a API de backup online do SQLite, então as escritas feitas durante o snapshot continuam coerentes. O tarball leva a árvore da wiki, o snapshot do banco e o config.toml.
# seguro com o servidor rodando
ai-memory backup --to /tmp/ai-memory-backup.tar.gz
Restaurar
--data-dir é o caminho do volume do lado do host. Os caminhos aqui são os do guia de deploy. Use os seus.
# Pare o servidor primeiro.
docker compose -f ~/deploy/ai-memory/docker-compose.yml down
# Restaure (o sysinfo recusa se o container ainda estiver rodando).
ai-memory restore --from /tmp/ai-memory-backup.tar.gz --data-dir /var/opt/docker/utils/ai-memory/data --force
# Suba de novo.
docker compose -f ~/deploy/ai-memory/docker-compose.yml up -d
Leia sobre as operações de ciclo de vida: purge, renomear, mover, restaurar uma página, reset
Roteamento e identidade
Um servidor compartilhado precisa responder duas perguntas: a qual projeto esta sessão pertence, e quem está pedindo.
O arquivo marcador
Por padrão, o projeto é o nome do diretório atual, num workspace chamado default. Para mudar isso, coloque um .ai-memory.toml em qualquer diretório ancestral. Os hooks sobem a partir do diretório de trabalho e usam o primeiro marcador que encontram.
Trabalho e pessoal
Um marcador por diretório pai. Todo repositório abaixo dele cai nesse workspace, com o nome do diretório como projeto.
# ~/projects/movvia/.ai-memory.toml
workspace = "movvia"
# ~/personal/.ai-memory.toml
workspace = "personal"
Mono-repo
Um marcador com project fixa todos os subdiretórios nesse único projeto. O marcador mais próximo vence.
# ~/projects/movvia/pe-portais/.ai-memory.toml
workspace = "movvia"
project = "pe-portais"
Git worktrees
Worktrees vinculados e subdiretórios resolvem para o repositório principal, mesmo quando o worktree fica fora dele.
# ~/projects/.ai-memory.toml
workspace = "oss"
project_strategy = "repo-root"
O mesmo arquivo guarda as regras de [capture] com ignore_paths, e ai-memory install-hooks --apply --capture-mode allowlist transforma o marcador em opt-in: um repositório sem ele não emite evento nenhum. Os hooks nativos aplicam as duas coisas. Os hooks de shell do wrapper Docker não. Leia a referência do arquivo marcador.
Modos de auto-scope
Uma chamada MCP sem projeto explícito é resolvida por um ponteiro de “projeto atual”. O modo decide quem compartilha esse ponteiro. O servidor loga o modo em uso na inicialização.
| Modo | Quando usar |
|---|---|
per_actor | O padrão. Isola harnesses em paralelo e pessoas diferentes no mesmo servidor. |
per_session | Para clientes session-aware, que repassam o session id do hook em toda requisição MCP. |
single | O comportamento anterior à v1.39. Um slot para o processo inteiro, a última escrita vence. Inseguro num servidor compartilhado. |
[auto_scope]
mode = "per_actor" # "per_actor" (padrão desde a v1.39) | "per_session" | "single"
session_ttl_secs = 3600 # TTL das entradas por chave (padrão 1 h)
max_entries = 4096 # limite rígido; as inserções mais antigas saem primeiro
Leia como funciona o isolamento do auto-scope
SSO e OIDC
Cada desenvolvedor faz login uma vez com um device flow de OIDC em qualquer emissor que siga o padrão, como Keycloak, Okta ou Entra ID. Daí em diante o token autentica os hooks nativos de ciclo de vida e os comandos da CLI quando não há um bearer token estático configurado.
ai-memory auth login oidc-device \
--issuer "https://issuer.example.com/realms/team" \
--client-id "ai-memory-cli"
Offline, limites e atualizações
O que uma revisão de segurança, um plano de capacidade e uma janela de manutenção precisam saber.
Instalação air-gapped (sem rede)
Binários
Todo asset de release tem um arquivo .sha256. Baixe numa máquina conectada, verifique e leve para dentro. As releases trazem só checksums, sem proveniência SLSA nem atestação de artefato.
Build a partir do código-fonte
O SQLite vai embutido e o libgit2 vai vendorizado, então o build precisa de um toolchain de C e do seu mirror de crates. cargo vendor funciona.
O modelo de embeddings
Uma instalação padrão baixa o modelo do Hugging Face na primeira inicialização. Para não fazer nenhuma requisição de saída, coloque antes model.safetensors, tokenizer.json e config.json em <data_dir>/models/all-MiniLM-L6-v2/. Os checksums estão fixados no código-fonte.
O binário não tem telemetria. O wrapper Docker consulta o Docker Hub atrás de uma imagem mais nova no máximo uma vez a cada 24 horas, e AI_MEMORY_NO_VERSION_CHECK=1 desliga isso. Num ambiente air-gapped as atualizações são manuais, do mesmo jeito que a instalação. Leia a página de instalação offline.
Capacidade
Toda escrita passa por um writer só. O projeto mediu onde isso bate no teto, com cargo test -p ai-memory-store --test writer_throughput -- --ignored --nocapture.
| Writers concorrentes | Throughput | Latência média |
|---|---|---|
| 1 | 42/s | 23,9 ms |
| 8 | 295/s | 3,4 ms |
| 32 | 698/s | 1,43 ms |
| 128 | 700/s | 1,43 ms |
- O teto fica em torno de 700 escritas por segundo, atingido perto de 32 writers.
- A fila de escrita é limitada a 1024. Passando disso, os produtores desaceleram e toda escrita ainda é gravada.
- Os hooks de shell desistem do servidor depois de 200 ms e guardam o evento num spool local, então um servidor lento não trava o seu agente.
AI_MEMORY_HOOK_RATE_PER_SECeAI_MEMORY_HOOK_RATE_BURSTadicionam um rate limit opcional por ator e por sessão. Vem desligado por padrão.
Atualização
ai-memory upgrade
- Com o wrapper Docker, isto verifica e substitui o wrapper, baixa a imagem e reinstala os scripts de hook. Um servidor em outro host é atualizado à parte.
- As migrações de schema e da wiki rodam na inicialização. Elas só andam para frente: um binário mais antigo se recusa a abrir um diretório migrado, então rode
ai-memory backupantes se existe chance de rollback.
Leia o guia de migração para a 2.0, incluindo como voltar atrás
Perguntas e respostas
O ai-memory precisa de TLS?
Não num laptop de um usuário só com bind em 127.0.0.1, e não por stdio. Coloque um proxy com TLS quando existirem contas, quando o bind do servidor for além do loopback, quando você abrir a interface web de outra máquina ou quando ele for acessível de fora da LAN. O ai-memory não termina TLS.
Do que eu preciso fazer backup?
Rode ai-memory backup, que é seguro com o servidor no ar. O tarball leva a árvore da wiki, um snapshot consistente do SQLite e o config.toml. A wiki é a fonte da verdade. Páginas, links e busca podem ser reconstruídos a partir dela com ai-memory reindex, mas sessões, handoffs, usuários e chaves só existem no banco.
O ai-memory tem suporte a SSO?
Ele suporta autenticação OIDC por device flow para os hooks de ciclo de vida e os comandos da CLI, com qualquer emissor que siga o padrão. O servidor não valida tokens OIDC, então colocar a API do servidor atrás do seu provedor de identidade exige um gateway que entenda OIDC na frente dele.
Dois servidores podem compartilhar um diretório de dados?
Não. Rode um servidor por diretório de dados. Desde a 2.0 o servidor pega um lock exclusivo em .serve.lock, e um segundo servidor se recusa a subir.
Rodando em algum lugar fora do comum?
Abra uma issue e descreva o seu setup. O código, a documentação e o tracker são todos públicos.