SSD Nodes Learn 8GB di RAM — $66/anno
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-02

Memmy: memoria locale condivisa per agenti AI su VPS

Scopri come compilare Memmy su Ubuntu, avviare il servizio sulla porta 18960 e mantenere in locale le note condivise da Claude Code, Codex e Cursor.

Che cos'è Memmy e cosa archivia

Memmy è un hub di memoria locale per agenti AI che viene eseguito sul proprio VPS (virtual private server). Mantiene un unico database SQLite di ciò che gli agenti hanno appreso, e ogni agente sul server legge e scrive nello stesso archivio. Il progetto è memmy-agent di MemTensor, distribuito con licenza MIT, alla versione 1.0.4 a luglio 2026.

Su un server è rilevante solo una parte del progetto. Memmy include un servizio di memoria in ascolto su http://127.0.0.1:18960, un'interfaccia a riga di comando (CLI) memmy-memory che comunica con il servizio e un ambiente di lavoro desktop. L'ambiente di lavoro è distribuito solo per macOS e Windows, quindi su un VPS Linux si eseguono il servizio e la CLI. Questo è sufficiente per fornire una memoria condivisa a Claude Code, Codex e Cursor.

Memmy organizza i dati archiviati in quattro livelli. L1 Trace è il turno grezzo: la richiesta, la risposta e le chiamate agli strumenti. L2 Policy è una procedura ricavata dalle tracce che si è dimostrata utile. L3 World Model è la conoscenza stabile di un progetto o di un ambiente. Skill è una procedura richiamabile derivata da una policy. Il servizio assegna un livello quando acquisisce un turno, quindi non è necessario crearli manualmente.

Cosa cambia un hub di memoria condivisa rispetto alla memoria specifica di ogni strumento

Oggi ogni agente distribuisce la propria memoria. Claude Code conserva i file di istruzioni nel repository. Cursor conserva le regole nel database del workspace. Codex conserva i log delle sessioni in ~/.codex. Ogni archivio appartiene a un solo strumento, quindi un'informazione insegnata lunedì in uno strumento non è disponibile martedì in un altro. Questo comporta un doppio costo: i token spesi per spiegare di nuovo lo stesso progetto e il lavoro errato causato da un agente che usa un presupposto già corretto altrove.

Un hub sposta l'archivio fuori dallo strumento. Memmy legge anche gli archivi esistenti, quindi non si parte da un database vuoto. Il relativo scanner conosce sei origini: Claude Code in ~/.claude/projects/**/*.jsonl, Codex in ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl, OpenCode in ~/.local/share/opencode/opencode.db, i file state.vscdb di Cursor, i database SQLite di OpenClaw in ~/.openclaw e Hermes in ~/.hermes. È possibile aggiungere manualmente un'origine specificandone il nome e un percorso locale.

I contatori dell'importazione non corrisponderanno, ed è previsto. Lo scanner raggruppa i messaggi per origine e conversazione, quindi scrive una memoria L1 per ogni turno completo. Un turno è completo quando contiene contenuto non vuoto dell'utente e termina con un messaggio non vuoto dell'assistente; una sessione interrotta non contribuisce quindi alcun dato. I messaggi vengono deduplicati tramite checkpoint delle conversazioni e ID stabili dei turni. Nella stessa esecuzione, il numero di elementi analizzati, il numero di messaggi importati e il numero di nuove memorie saranno diversi.

Questa è la parte che si abbina a come Claude Code gestisce il contesto all'interno di una singola sessione. La gestione del contesto decide cosa può rientrare in una singola finestra. Un hub di memoria decide cosa rimane disponibile dopo la chiusura della finestra.

Requisiti per il VPS

  • Node.js 22 o versione successiva. La documentazione di Memmy lo richiede e Ubuntu 24.04 include Node 18.
  • git e una toolchain di compilazione, perché better-sqlite3 è un modulo nativo che potrebbe essere compilato durante l'installazione.
  • Circa 2 GB di RAM. L'installazione nella directory root scarica un workspace di grandi dimensioni e una toolchain per la compilazione del frontend.
  • Alcuni GB di spazio libero su disco per node_modules e il database.
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 --version

node --version dovrebbe restituire v22 o una versione successiva. Un valore v18 in questo punto indica che il passaggio NodeSource non è stato eseguito correttamente e che l'installazione fallirà in seguito durante il controllo del motore del progetto.

Installare Memmy dai sorgenti su Ubuntu 24.04

git clone https://github.com/MemTensor/memmy-agent.git
cd memmy-agent
cp .env.example .env
npm install
npm run memory:build

npm run memory:build compila l'area di lavoro @memmy/memory in Memory/dist. Su un server headless non è necessario compilare altro nell'albero. Verificare che il modulo nativo sia stato caricato:

node -e "require('better-sqlite3'); console.log('better-sqlite3 loads')"

Se la riga genera un errore invece di stampare un risultato, il modulo nativo non è compatibile con la versione di Node in uso. Eseguire npm rebuild better-sqlite3, che corrisponde esattamente a ciò che fa lo script di avvio del progetto prima di avviare qualsiasi componente.

Il README documenta bash scripts/dev-start.sh come comando di avvio unico. Non eseguirlo su un VPS headless. Avvia la shell desktop Electron e un server di sviluppo Vite sulla porta 19000 insieme al servizio di memoria. Electron richiede un display, quindi su un server senza sessione grafica lo script si blocca o termina.

Avviare il servizio di memoria e verificare che risponda

npm run memory:serve:dev

Questo è il metodo documentato per eseguire il servizio di memoria dal codice sorgente. Si associa a 127.0.0.1:18960, mantiene il database in ~/.memmy/memory-service/memory.sqlite e legge la configurazione da ~/.memmy/config.yaml. Il README indica gli stessi valori in modo esplicito:

npm run memory:serve:dev -- \
  --host 127.0.0.1 --port 18960 \
  --db ~/.memmy/memory-service/memory.sqlite \
  --config ~/.memmy/config.yaml

Da una seconda shell, chiedere al servizio se è attivo:

curl -sS http://127.0.0.1:18960/api/v1/health

Health è l'unico endpoint che non richiede mai un token, quindi è il probe corretto. Se curl termina con il codice 7 e un messaggio Failed to connect to 127.0.0.1 port 18960, non c'è alcun processo in ascolto. Leggere il terminale in cui è in esecuzione il servizio, perché gli arresti anomali all'avvio vengono registrati lì. La causa abituale è il mancato caricamento del modulo SQLite nativo. ss -lntp | grep 18960 conferma il socket quando il servizio è attivo.

Il resto dell'API HTTP (interfaccia di programmazione delle applicazioni) è disponibile sotto /api/v1.

  • POST /api/v1/memory/add scrive una memoria e POST /api/v1/memory/search esegue query.
  • GET /api/v1/memory/:id e DELETE /api/v1/memory/:id leggono e rimuovono una voce.
  • POST /api/v1/sessions/open e POST /api/v1/sessions/:sessionId/close delimitano una sessione dell'agente.
  • POST /api/v1/turns/start e POST /api/v1/turns/:turnId/complete registrano un turno.
  • GET /api/v1/panel/overview, /api/v1/panel/analysis e /api/v1/panel/items alimentano il dashboard.

Memmy riserva un blocco di porte. In modalità headless si usa solo la prima: 18960 per la memoria, 18970 per lo stato del gateway, 18980 per l'interfaccia web e l'HTTP di amministrazione, 18990 per l'API compatibile con OpenAI avviata da memmy serve, quindi 19000 e 19010 per il server di sviluppo del frontend desktop. Se sul sistema una di queste porte è già occupata, questo è l'elenco da controllare.

Da dove proviene effettivamente il comando memmy-memory

È il punto in cui una prima installazione non riesce di solito. Leggi quindi il valore dal pacchetto invece di fare supposizioni. Il nome del comando non ha alcun rapporto con il nome del repository. Proviene dal campo bin del workspace che lo definisce:

node -p "JSON.stringify(require('./Memory/package.json').bin)"

Questo stampa {"memmy-memory":"./dist/src/cli/index.js"}. Il punto di ingresso compilato è quindi Memory/dist/src/cli/index.js. Esiste solo dopo npm run memory:build, perché la compilazione crea dist e contrassegna il file come eseguibile. Eseguilo direttamente:

node Memory/dist/src/cli/index.js health

Se vuoi il nome breve nel tuo PATH, crea un collegamento allo stesso file:

sudo ln -s "$PWD/Memory/dist/src/cli/index.js" /usr/local/bin/memmy-memory
memmy-memory health

Per impostazione predefinita, la CLI usa http://127.0.0.1:18960 e accetta --url, --token, --config, --source e --user-id. I relativi sottocomandi sono init, health, search, add, get e delete, oltre alle chiamate di sessione e di turno utilizzate dagli agenti anziché dalle persone. memmy-memory search "deploy steps" e memmy-memory add "staging migrates on deploy" sono le due operazioni eseguite più spesso da un agente.

Come si collega Claude Code a Memmy?

Claude Code non dispone di un'interfaccia per i plugin di memoria, quindi Memmy non si integra direttamente con esso. L'integrazione è più semplice. Claude Code esegue memmy-memory come un normale comando della shell e un file di istruzioni gli indica quando farlo. L'installer documentato di Memmy crea automaticamente questo file: memmy-memory init --agent inserisce un file di istruzioni per la memoria nella directory delle regole dell'agente di destinazione.

Scrivete manualmente l'istruzione una volta, così saprete esattamente cosa è stato comunicato all'agente. Claude Code legge CLAUDE.md dalla directory radice del progetto all'inizio di ogni sessione. Pertanto, una sezione come questa costituisce l'intera integrazione:

## 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.

È importante chiarire cosa comporta. Si tratta di un'integrazione a livello di istruzioni. Funziona quindi quando il modello decide di eseguire il comando, e non altrimenti. Nulla forza l'esecuzione. Se una sessione termina senza add, non viene salvato nulla. L'unico segnale è un risultato vuoto alla ricerca successiva. È lo stesso compromesso dei file di memoria propri di Claude Code, con una differenza: l'archivio è condiviso, quindi la nota è disponibile anche in Codex e Cursor sulla stessa macchina.

La direzione inversa non richiede alcuna configurazione. Lo scanner di Memmy legge già ~/.claude/projects/**/*.jsonl, che è il percorso in cui Claude Code scrive le trascrizioni delle sessioni. Eseguite Memmy sullo stesso server in cui eseguite Claude Code all'interno di una sessione tmux: il lavoro del giorno precedente diventerà memoria senza alcuna configurazione aggiuntiva.

Memmy funziona come server MCP per Claude Code?

No, e conoscere questa distinzione fa risparmiare tempo. MCP (model context protocol) prevede client e server. Memmy è un client. Si connette ai server MCP e rende disponibili i relativi strumenti al proprio runtime dell'agente. Non espone un endpoint MCP a cui claude mcp add possa connettersi. L'unico bridge MCP nel repository appartiene all'integrazione Composio all'interno dell'API locale desktop, e questa API si associa a una porta casuale su 127.0.0.1 dietro la propria intestazione x-memmy-mcp-token.

Il lato client è configurato in ~/.memmy/config.yaml, il file indicato da MEMMY_CONFIG, in tools.mcpServers:

tools:
  mcpServers:
    example:
      type: stdio
      command: npx
      args:
        - "-y"
        - "your-mcp-server"
      toolTimeout: 30
      enabledTools:
        - "*"

type accetta stdio, sse e streamableHttp. Un server stdio viene eseguito come processo figlio di Memmy. Il relativo comando deve quindi essere disponibile sullo stesso computer ed essere eseguito dallo stesso utente. Se mantieni già server MCP in esecuzione su un VPS, sono questi i server da elencare qui.

Mantenere privato l'archivio della memoria

Tutto ciò che Memmy gestisce risiede in ~/.memmy: config.yaml, l'area di lavoro, memory-service/memory.sqlite e i file di runtime. La scansione e l'acquisizione avvengono localmente e le memorie vengono scritte in quel file SQLite locale, quindi la configurazione predefinita è realmente locale.

Due percorsi accedono alla rete. MEMMY_CLOUD_SERVICE usa https://memmy-api.memtensor.cn come valore predefinito e supporta la modalità account con i relativi token di prova, quindi la modalità con chiave API non lo contatta. Il programma di miglioramento della memoria è un'opzione separata nelle impostazioni della privacy ed è disattivato finché non lo abiliti.

Un terzo percorso è più facile da non notare. Se configuri un provider di embedding ospitato, il testo di ogni memoria viene inviato a quel provider per essere convertito in un vettore. L'archiviazione locale non è sufficiente in questo caso. Un endpoint di embedding ospitato autonomamente è l'unico modo per impedire questo trasferimento.

Mantieni la porta 18960 sull'indirizzo di loopback. Non richiede una regola del firewall, perché un servizio associato a 127.0.0.1 non è raggiungibile dall'esterno del computer. Puoi raggiungerlo dal laptop tramite SSH:

ssh -N -L 18960:127.0.0.1:18960 you@your-vps

Se lo associ a un indirizzo più ampio, imposta prima un token. L'impostazione di storage.token nella configurazione oppure della variabile d'ambiente MEMMY_MEMORY_TOKEN o MEMORY_SERVICE_TOKEN richiede un bearer token per ogni endpoint, tranne quello di health. I valori di configurazione supportano i riferimenti ${ENV_NAME}, quindi il token e le chiavi API dei modelli restano fuori dal file stesso. È la stessa pratica di mantenere i segreti fuori dagli agenti AI usata altrove, mentre una policy ufw predefinita deny costituisce una protezione aggiuntiva se una versione futura modifica l'indirizzo di bind predefinito.

Esegui il backup di ~/.memmy prima di considerarlo affidabile

memory.sqlite è l'intero archivio. I vettori risiedono nello stesso file tramite l'estensione sqlite-vec, quindi il backup consiste in un unico file. Copiarlo con cp mentre il servizio sta scrivendo può produrre un database danneggiato. Usa il comando di backup integrato di SQLite:

mkdir -p ~/memmy-backup
sqlite3 ~/.memmy/memory-service/memory.sqlite ".backup '$HOME/memmy-backup/memory.sqlite'"

Questo crea una copia coerente mentre il servizio continua a funzionare. Trasferiscila fuori dal server secondo una pianificazione: è proprio lo scopo di restic per l'archiviazione esterna. La perdita di config.yaml comporta la perdita delle impostazioni del provider, che puoi reinserire. La perdita di memory.sqlite comporta la perdita di ogni memoria; nessun altro elemento del computer contiene una seconda copia.

Eseguire il servizio di memoria con systemd

npm run memory:serve:dev in una shell termina insieme alla shell. Un file unit mantiene il servizio attivo anche dopo i riavvii.

[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.target

Non inserire il token nella unit. Inseriscilo in /etc/memmy/memory.env, assegnato a root, con modalità 600:

MEMMY_CONFIG=/home/memmy/.memmy/config.yaml
MEMMY_MEMORY_TOKEN=replace-this-with-a-long-random-string
sudo 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/health

status=203/EXEC nell'output dello stato indica che systemd non ha potuto eseguire ExecStart. Controlla quindi which npm: in un'installazione NodeSource si trova in /usr/bin/npm, mentre con nvm si trova in un percorso nella home dell'utente, che systemd non individua. Una unit che si avvia e termina immediatamente ha invece riscontrato un errore interno a npm; journalctl -u memmy-memory -n 50 ne visualizza il motivo. Il funzionamento è lo stesso di qualsiasi altro servizio systemd su un VPS.

Cosa non fa ancora Memmy

  • Non esiste una build desktop per Linux. Gli script di packaging coprono macOS e Windows, quindi il workbench, la procedura guidata di onboarding e il dashboard della memoria non sono disponibili direttamente sul server.
  • memory:serve:dev esegue il punto di ingresso TypeScript tramite tsx, un percorso di sviluppo. Il repository include anche memory:serve per l'output compilato. Esegui npm run senza argomenti per verificare quali script sono effettivamente presenti nel tuo checkout.
  • Il recupero crea la finestra di ricerca a partire dalle 2,000 righe vettoriali più recenti, quindi applica la selezione Top-K all'interno di quella finestra. In uno store molto grande, una memoria meno recente può trovarsi al di fuori della finestra.
  • La generazione degli embedding avviene dopo l'acquisizione e un errore inserisce l'elemento in una coda di nuovi tentativi invece di bloccare il turno dell'agente. Una memoria aggiunta poco prima potrebbe non essere ancora ricercabile tramite la ricerca vettoriale.
  • Un singolo file SQLite corrisponde a un singolo nodo. Non esiste il clustering, quindi un secondo server costituisce una memoria separata.

La versione 1.0.4 e circa 329 stelle a luglio 2026 indicano un progetto giovane. Flag, percorsi e nomi degli script cambiano tra le release. Leggi il campo bin e l'output di npm run nel tuo checkout invece di affidarti a un comando copiato da una fonte qualsiasi, incluso questo testo.

FAQ

Perché il controllo dello stato restituisce «connessione rifiutata»?

Nessun processo è in ascolto sulla porta 18960. Un codice di uscita 7 di curl con Failed to connect to 127.0.0.1 port 18960 indica che il servizio di memoria non è in esecuzione oppure si è arrestato all'avvio; leggi quindi il terminale o il journal in cui è stato avviato. Le due cause più comuni sono un modulo nativo better-sqlite3 incompatibile con la versione di Node, risolvibile con npm rebuild better-sqlite3, e una versione di Node precedente alla 22. Conferma il socket con ss -lntp | grep 18960 quando il servizio è attivo.

Da dove proviene il comando memmy-memory dopo la compilazione dai sorgenti?

Dal campo bin del pacchetto workspace @memmy/memory, non dal nome del repository. Esegui node -p "JSON.stringify(require('./Memory/package.json').bin)" nella directory del checkout: il comando stampa {"memmy-memory":"./dist/src/cli/index.js"}. Quel file esiste solo dopo npm run memory:build, perché la compilazione crea dist e contrassegna il file come eseguibile. Eseguilo come node Memory/dist/src/cli/index.js health oppure crea un link simbolico in /usr/local/bin per usare il nome breve.

Posso aggiungere Memmy a Claude Code con claude mcp add?

No. Memmy è un client MCP, non un server MCP. Si connette ai server elencati in tools.mcpServers in ~/.memmy/config.yaml e rende disponibili i relativi strumenti al proprio runtime. Claude Code raggiunge Memmy nell'altro senso, eseguendo la CLI memmy-memory come comando shell, guidata da un file di istruzioni che memmy-memory init --agent scrive nella directory delle regole dell'agente.

L'esecuzione di Memmy invia le mie memorie a un servizio cloud?

L'analisi e l'acquisizione vengono eseguite localmente, e le memorie vengono scritte in ~/.memmy/memory-service/memory.sqlite sul disco locale. MEMMY_CLOUD_SERVICE usa https://memmy-api.memtensor.cn per la modalità account e i token di prova; il programma di miglioramento della memoria resta disattivato finché non lo abiliti. Il componente da controllare è il provider degli embedding: un modello di embedding ospitato riceve il testo di ogni memoria che converte in un vettore. Se questo aspetto è importante, usa un endpoint gestito autonomamente.