SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-26

Memmy : une mémoire locale partagée pour vos agents IA

Installez Memmy 1.0.4 depuis les sources sur Ubuntu, exposez son service sur le port 18960 et partagez une base SQLite locale entre Claude Code, Codex et Cursor.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 31, 2026.

Ce qu’est Memmy et ce qu’il stocke

Memmy est un hub de mémoire local pour les agents IA qui s’exécute sur votre propre VPS (virtual private server). Il conserve une base de données SQLite contenant ce que vos agents ont appris, et chaque agent présent sur le serveur lit et écrit dans ce même stockage. Le projet est memmy-agent de MemTensor, sous licence MIT, en version 1.0.4 en juillet 2026.

Seule une partie du projet est utile sur un serveur. Memmy fournit un service de mémoire qui écoute sur http://127.0.0.1:18960, une interface de ligne de commande (CLI) memmy-memory qui communique avec ce service, et un workbench de bureau. Le workbench est fourni uniquement pour macOS et Windows. Sur un VPS Linux, vous exécutez donc le service et la CLI. Cela suffit pour fournir une mémoire partagée à Claude Code, Codex et Cursor.

Memmy classe ce qu’il stocke en quatre couches. L1 Trace correspond au tour brut : la requête, la réponse et les appels d’outils. L2 Policy est une procédure déduite de traces qui se sont révélées utiles. L3 World Model contient les connaissances stables sur un projet ou un environnement. Skill est une procédure appelable cristallisée à partir d’une policy. Le service attribue une couche lors de l’ingestion d’un tour ; vous ne les créez donc pas manuellement. Si ces distinctions restent abstraites, la mémoire constitue l’une des étapes avancées de un parcours progressif pour apprendre à créer des agents, et les couches deviennent plus compréhensibles une fois que vous avez écrit vous-même une boucle d’agent simple et constaté qu’elle oublie tout entre deux exécutions.

Ce que change un hub de mémoire partagé par rapport à une mémoire propre à chaque outil

Aujourd’hui, chaque agent fournit sa propre mémoire. Claude Code conserve des fichiers d’instructions dans le dépôt. Cursor conserve ses règles dans la base de données de son espace de travail. Codex conserve les journaux de session sous ~/.codex. Chaque stockage appartient à un seul outil. Un fait que vous avez indiqué lundi dans un outil est donc inconnu mardi dans un autre. Vous le payez deux fois : d’abord en tokens pour réexpliquer le même projet, puis dans le travail incorrect produit lorsqu’un agent applique une hypothèse que vous avez déjà corrigée ailleurs.

Un hub sort le stockage de l’outil. Memmy lit également les stockages existants. Vous ne partez donc pas d’une base de données vide. Son scanner connaît six sources : Claude Code à ~/.claude/projects/**/*.jsonl, Codex à ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl, OpenCode à ~/.local/share/opencode/opencode.db, les fichiers state.vscdb de Cursor, les bases de données SQLite d’OpenClaw sous ~/.openclaw et Hermes sous ~/.hermes. Vous pouvez ajouter manuellement une source en indiquant un nom et un chemin local.

Les compteurs d’importation ne correspondront pas, et c’est normal. Le scanner regroupe les messages par source et par conversation, puis écrit une mémoire L1 par tour complet. Un tour est complet lorsqu’il contient un contenu utilisateur non vide et se termine par un message assistant non vide. Une session interrompue ne contribue donc à aucune mémoire. Les messages sont dédupliqués à l’aide de points de contrôle de conversation et d’identifiants de tour stables. Le nombre d’éléments analysés, le nombre de messages importés et le nombre de nouvelles mémoires diffèrent lors d’une même exécution.

Cette partie complète la façon dont Claude Code gère le contexte au sein d’une session. La gestion du contexte détermine ce qui tient dans une seule fenêtre. Un hub de mémoire détermine ce qui est conservé après la fermeture de cette fenêtre.

Ce qu’il vous faut sur le VPS

  • Node.js 22 ou une version ultérieure. La documentation de Memmy l’exige, et Ubuntu 24.04 fournit Node 18.
  • git et une toolchain de compilation, car better-sqlite3 est un module natif qui peut être compilé pendant l’installation.
  • Environ 2 GB de RAM. L’installation root télécharge un workspace volumineux et une toolchain de build frontend.
  • Quelques GB d’espace disque libre pour node_modules et la base de données.
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 doit afficher v22 ou une version ultérieure. La présence de v18 indique que l’étape NodeSource n’a pas abouti. L’installation échouera ensuite lors de la vérification du moteur du projet.

Installer Memmy depuis les sources sur 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 compile l’espace de travail @memmy/memory dans Memory/dist. Rien d’autre dans l’arborescence n’a besoin d’être compilé sur un serveur sans interface graphique. Vérifiez que le module natif est bien chargé :

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

Si cette ligne génère une erreur au lieu d’afficher le résultat, le module natif n’est pas compatible avec votre version de Node. Exécutez npm rebuild better-sqlite3. C’est exactement ce que fait le script de démarrage du projet avant de lancer quoi que ce soit.

Le README présente bash scripts/dev-start.sh comme une commande de démarrage unique. Ne l’exécutez pas sur un VPS sans interface graphique. Elle démarre l’interface de bureau Electron et un serveur de développement Vite sur le port 19000, en plus du service de mémoire. Electron a besoin d’un affichage. Sur un serveur sans session graphique, le script se bloque ou se termine.

Démarrer le service de mémoire et vérifier qu’il répond

npm run memory:serve:dev

C’est la méthode documentée pour exécuter le service de mémoire depuis les sources. Il écoute sur 127.0.0.1:18960, conserve la base de données dans ~/.memmy/memory-service/memory.sqlite et lit la configuration depuis ~/.memmy/config.yaml. Le README indique les mêmes valeurs lorsque vous voulez les définir explicitement :

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

Depuis un deuxième shell, demandez au service s’il est actif :

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

Health est le seul endpoint qui ne demande jamais de token. C’est pourquoi il constitue la bonne sonde. Si curl se termine avec le code 7 et un message Failed to connect to 127.0.0.1 port 18960, aucun processus n’écoute. Consultez le terminal qui exécute le service, car un crash au démarrage s’y affiche. La cause habituelle est l’échec du chargement du module SQLite natif. ss -lntp | grep 18960 confirme le socket une fois que le service est démarré.

Le reste de l’API HTTP (interface de programmation d’application) se trouve sous /api/v1.

  • POST /api/v1/memory/add écrit une mémoire et POST /api/v1/memory/search exécute des requêtes.
  • GET /api/v1/memory/:id et DELETE /api/v1/memory/:id lisent et suppriment une entrée.
  • POST /api/v1/sessions/open et POST /api/v1/sessions/:sessionId/close encadrent une session d’agent.
  • POST /api/v1/turns/start et POST /api/v1/turns/:turnId/complete enregistrent un tour.
  • GET /api/v1/panel/overview, /api/v1/panel/analysis et /api/v1/panel/items alimentent le dashboard.

Memmy réserve un bloc de ports. En mode headless, vous utilisez uniquement les premiers : 18960 pour la mémoire, 18970 pour l’état de santé de la gateway, 18980 pour l’interface web et l’admin HTTP, 18990 pour l’API compatible OpenAI démarrée par memmy serve, puis 19000 et 19010 pour le dev server du frontend desktop. Si quelque chose utilise déjà l’un de ces ports sur votre machine, consultez cette liste.

D’où vient réellement la commande memmy-memory

C’est généralement à cette étape qu’une première installation échoue. Lisez donc la définition dans le package au lieu de la déduire. Le nom de la commande n’a rien à voir avec le nom du dépôt. Il vient du champ bin de l’espace de travail qui la définit :

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

Cette commande affiche {"memmy-memory":"./dist/src/cli/index.js"}. Le point d’entrée compilé est donc Memory/dist/src/cli/index.js. Il n’existe qu’après npm run memory:build, car la compilation crée dist et rend le fichier exécutable. Exécutez-le directement :

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

Si vous voulez utiliser le nom court depuis votre PATH, créez un lien vers ce même fichier :

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

La CLI utilise http://127.0.0.1:18960 par défaut et accepte --url, --token, --config, --source et --user-id. Ses sous-commandes sont init, health, search, add, get et delete, ainsi que les appels de session et de tour utilisés par les agents plutôt que par les utilisateurs. memmy-memory search "deploy steps" et memmy-memory add "staging migrates on deploy" sont les deux commandes qu’un agent exécute le plus souvent.

Comment connecter Claude Code à Memmy ?

Claude Code ne dispose pas d’interface de plugin de mémoire. Memmy ne s’y branche donc pas. L’intégration est plus simple. Claude Code exécute memmy-memory comme une commande shell ordinaire. Un fichier d’instructions lui indique quand l’exécuter. L’installateur documenté de Memmy crée ce fichier pour vous : memmy-memory init --agent dépose un fichier d’instructions de mémoire dans le répertoire de règles de l’agent cible.

Écrivez l’instruction à la main une fois. Vous saurez ainsi exactement ce qui a été demandé à l’agent. Claude Code lit CLAUDE.md à la racine du projet au début de chaque session. Une section comme celle-ci suffit donc pour l’intégration :

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

Indiquez clairement ce que cette intégration permet. Il s’agit d’une intégration au niveau des instructions. Elle fonctionne donc lorsque le modèle décide d’exécuter la commande, et pas dans les autres cas. Rien ne force cet appel. Si une session se termine sans add, rien n’est enregistré. Le seul signal est un résultat vide lors de la recherche suivante. C’est le même compromis que pour les fichiers de mémoire intégrés de Claude Code, à une différence près : le stockage est partagé. La note est donc également accessible à Codex et à Cursor sur la même machine. Un harness qui expose une véritable interface de plugin comble cette lacune sans devoir le demander au modèle. C’est pourquoi la mémoire persistante figure aux côtés des plafonds de budget et des règles d’autorisation parmi les plugins DeepSeek Harness à installer.

L’autre sens ne nécessite aucune configuration. Le scanner de Memmy lit déjà ~/.claude/projects/**/*.jsonl, l’emplacement où Claude Code écrit les transcriptions de ses sessions. Exécutez Memmy sur le même serveur que celui où vous utilisez Claude Code dans une session tmux. Le travail de la veille devient alors de la mémoire sans configuration supplémentaire.

Memmy fonctionne-t-il comme serveur MCP pour Claude Code ?

Non. Le savoir permet d’éviter d’y passer l’après-midi. MCP (model context protocol) utilise des clients et des serveurs. Memmy est un client. Il se connecte aux serveurs MCP et met leurs outils à la disposition de son propre agent. Il n’expose pas de endpoint MCP auquel claude mcp add pourrait se connecter. Le seul bridge MCP du dépôt appartient à l’intégration Composio dans l’API locale desktop. Cette API écoute sur un port aléatoire de 127.0.0.1, protégé par son propre en-tête x-memmy-mcp-token.

Le client est configuré dans ~/.memmy/config.yaml, le fichier indiqué par MEMMY_CONFIG, sous tools.mcpServers :

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

type accepte stdio, sse et streamableHttp. Un serveur stdio s’exécute comme processus enfant de Memmy. Sa commande doit donc exister sur la même machine et s’exécuter avec le même utilisateur. Si vous avez déjà des serveurs MCP exécutés sur un VPS, ce sont ceux qu’il faut répertorier ici.

Conserver le magasin de mémoire privé

Tout ce que Memmy possède se trouve sous ~/.memmy : config.yaml, l’espace de travail, memory-service/memory.sqlite et les fichiers d’exécution. L’analyse et l’ingestion s’effectuent localement, et les mémoires sont écrites dans ce fichier SQLite local. Le fonctionnement par défaut est donc réellement local.

Deux chemins accèdent au réseau. MEMMY_CLOUD_SERVICE pointe par défaut vers https://memmy-api.memtensor.cn et prend en charge le mode compte avec ses jetons d’essai. Le mode clé d’API ne l’appelle donc jamais. Le programme d’amélioration de la mémoire est un réglage distinct dans les paramètres de confidentialité. Il est désactivé tant que vous ne l’activez pas.

Un troisième chemin est plus facile à manquer. Si vous configurez un fournisseur d’embeddings hébergé, le texte de chaque mémoire lui est envoyé pour être transformé en vecteur. Le stockage local ne change rien à ce point. Un endpoint d’embeddings que vous hébergez vous-même est le seul moyen de supprimer cette transmission.

Laissez le port 18960 lié à l’adresse loopback. Aucune règle de pare-feu n’est nécessaire, car un service lié à 127.0.0.1 n’est pas du tout accessible depuis l’extérieur de la machine. Accédez-y depuis votre ordinateur portable via SSH :

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

Si vous le liez un jour à une adresse plus large, définissez d’abord un token. La définition de storage.token dans la configuration, ou de la variable d’environnement MEMMY_MEMORY_TOKEN ou MEMORY_SERVICE_TOKEN, impose un bearer token à tous les endpoints, sauf celui de health. Les valeurs de configuration prennent en charge les références ${ENV_NAME}. Le token et vos clés d’API de modèles restent ainsi en dehors du fichier lui-même. C’est la même pratique que conserver les secrets hors des agents IA partout ailleurs, et une politique ufw default deny constitue votre protection de secours si une version ultérieure modifie son adresse bind par défaut.

Sauvegardez ~/.memmy avant de lui faire confiance

memory.sqlite est le store complet. Les vecteurs se trouvent dans ce même fichier grâce à l’extension sqlite-vec, donc un seul fichier constitue la sauvegarde. Le copier avec cp pendant que le service écrit peut produire une base de données incohérente. Utilisez la commande de sauvegarde native de SQLite :

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

Cette commande produit une copie cohérente pendant que le service continue de fonctionner. Envoyez-la régulièrement sur une autre machine, par exemple avec restic vers un stockage hors site. La perte de config.yaml vous oblige à ressaisir les paramètres du fournisseur. La perte de memory.sqlite vous fait perdre tous les souvenirs, car aucune autre copie ne se trouve sur la machine.

Exécuter le service de mémoire avec systemd

npm run memory:serve:dev lancé dans un shell s’arrête avec le shell. Un unit file maintient le service actif après les redémarrages.

[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

Ne mettez pas le token dans l’unit. Placez-le dans /etc/memmy/memory.env, avec root comme propriétaire et le mode 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 dans la sortie d’état signifie que systemd n’a pas pu exécuter ExecStart du tout. Vérifiez donc which npm : il se trouve dans /usr/bin/npm avec une installation NodeSource, et sous le répertoire personnel de l’utilisateur avec nvm ; systemd ne le trouvera pas. Une unit qui démarre puis s’arrête immédiatement a échoué dans npm. journalctl -u memmy-memory -n 50 en affiche la cause. Le fonctionnement est le même que pour n’importe quel autre service systemd sur un VPS.

Ce que Memmy ne fait pas encore

  • Il n’existe pas de build Linux pour le bureau. Les scripts de packaging couvrent macOS et Windows. Le workbench, son assistant d’onboarding et le tableau de bord de la mémoire ne sont donc pas disponibles directement sur le serveur.
  • memory:serve:dev exécute le point d’entrée TypeScript via tsx, qui correspond à un chemin de développement. Le dépôt fournit également memory:serve pour la sortie compilée. Exécutez npm run sans argument pour voir quels scripts sont réellement présents dans votre checkout.
  • La récupération construit sa fenêtre de recherche à partir des 2,000 dernières lignes de vecteurs, puis applique la sélection Top-K dans cette fenêtre. Dans un store très volumineux, une mémoire ancienne peut se trouver en dehors de cette fenêtre.
  • La génération des embeddings intervient après la capture. En cas d’échec, l’élément est placé dans une file de retry au lieu de bloquer le tour de l’agent. Une mémoire ajoutée il y a quelques instants peut donc ne pas être immédiatement trouvable par recherche vectorielle.
  • Un fichier SQLite correspond à un seul nœud. Il n’y a pas de clustering. Un deuxième serveur constitue donc une mémoire distincte.

La version 1.0.4 et environ 329 stars en juillet 2026 décrivent un projet encore jeune. Les flags, les chemins et les noms de scripts peuvent changer d’une release à l’autre. Consultez le champ bin et la sortie de npm run dans votre propre checkout, au lieu de faire confiance à une commande copiée n’importe où, y compris ici.

FAQ

Pourquoi le health check renvoie-t-il « connection refused » ?

Rien n’écoute sur le port 18960. Un code de sortie curl 7 avec Failed to connect to 127.0.0.1 port 18960 signifie que le service de mémoire ne fonctionne pas ou qu’il s’est arrêté au démarrage. Consultez donc le terminal ou le journal où il a été lancé. Les deux causes habituelles sont un module natif better-sqlite3 incompatible avec votre version de Node, problème corrigé avec npm rebuild better-sqlite3, et une version de Node antérieure à 22. Confirmez le socket avec ss -lntp | grep 18960 une fois le service démarré.

D’où vient la commande memmy-memory après une compilation depuis les sources ?

Elle provient du champ bin du package workspace @memmy/memory, et non du nom du dépôt. Exécutez node -p "JSON.stringify(require('./Memory/package.json').bin)" dans le checkout : la commande affiche {"memmy-memory":"./dist/src/cli/index.js"}. Ce fichier n’existe qu’après npm run memory:build, car la compilation crée dist et le rend exécutable. Exécutez-le avec node Memory/dist/src/cli/index.js health ou créez un lien symbolique vers /usr/local/bin pour utiliser le nom court.

Puis-je ajouter Memmy à Claude Code avec claude mcp add ?

Non. Memmy est un client MCP, pas un serveur MCP. Il se connecte aux serveurs répertoriés sous tools.mcpServers dans ~/.memmy/config.yaml et fournit leurs outils à son propre runtime. Claude Code accède à Memmy dans l’autre sens, en exécutant le CLI memmy-memory comme une commande shell, avec l’aide d’un fichier d’instructions que memmy-memory init --agent écrit dans le répertoire de règles de l’agent.

L’exécution de Memmy envoie-t-elle mes souvenirs vers un service cloud ?

L’analyse et l’ingestion s’exécutent localement, et les souvenirs sont écrits dans ~/.memmy/memory-service/memory.sqlite sur votre propre disque. MEMMY_CLOUD_SERVICE utilise https://memmy-api.memtensor.cn pour le mode compte et les tokens d’essai, et le programme d’amélioration de la mémoire reste désactivé tant que vous ne l’activez pas. Le point à surveiller est le fournisseur d’embeddings : un modèle d’embeddings hébergé reçoit le texte de chaque souvenir qu’il transforme en vecteur. Utilisez donc un endpoint que vous exécutez vous-même si ce point est important.