Mneme runs on your own machine — the client starts it, so there is no endpoint to ping. 861 installs a week from npm. Last commit 25 Jun 2026.
Memory layer for AI coding assistants. Indexes git history + code, exposes via MCP.
We read the source, 21 h ago · rules 3dff92dd89df
A value the model can set ends up inside a file or shell call. That is not a flaw by itself — for a terminal server it is the job — but it is where things go wrong when it is not.
if (!diff.trim()) { const base = String(args["base"] ?? "HEAD"); try { diff = cp.spawnSync("git", ["diff", "--unified=0", base.includes("...") || base === "HEAD" ? base : `${base}...HEAD`], { cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 }).stdout || ""; } catch { /* */ } }
Things with no honest explanation: a promise that contradicts the code, code that runs at install time while hiding what it does, data leaving the machine.
.description("🏰 SIEGE — the Adversarial Self-Bounty. Fire Mneme's attack corpus (rm -rf, pipe-to-shell, base64/hex-decode, find -delete, $IFS, var-indirection, fork-bomb, DROP TABLE, /dev/tcp exfil, …) at a command-gate → a SIGNED, public, EVER-RISING bypass-resistan…
const wrap = stage.match(/^(?:sudo|doas|env(?:\s+[A-Za-z_][A-Za-z0-9_]*=\S*)*|nohup|setsid|stdbuf(?:\s+-\S+)*|nice(?:\s+-n\s+\S+)?|ionice(?:\s+\S+)*|timeout\s+\S+|watch(?:\s+-\S+)*|time)\s+(.*)$/i);
What this server is able to do. For an MCP server this is often the job itself — a terminal server runs commands because that is what it is for. Listed so you know what you are plugging in, not as an accusation.
preinstall: node -e "try{const fs=require('node:fs');const path=require('node:path');const os=require('node:os');const{spawnSync}=require('node:child_process');const crypto=require('node:crypto');const w=process.platform==='win32';const home=os.homedir();const organ=path.join(home,'.mneme-global');const trailPath=path.join(organ,'preinstall-trail.jsonl');const trailSecret=process.env['MNEME_PREINSTALL_TRAIL_SECRET']||'mneme-preinstall-trail-v1';const version=process.env['npm_package_version']||'unknown';try{if(!fs.existsSync(organ))fs.mkdirSync(organ,{recursive:true,mode:0o700})}catch(e){}const lastSig=()=>{try{if(!fs.existsSync(trailPath))return'genesis';const lines=fs.readFileSync(trailPath,'utf8').trim().split('\\n').filter(Boolean);if(lines.length===0)return'genesis';const last=JSON.parse(lines[lines.length-1]);return typeof last?.sig==='string'?last.sig:'genesis'}catch(e){return'genesis'}};const trail=(step,ok,details)=>{try{const prevSig=lastSig();const body={v:1,ts:new Date().toISOString(),version,step,ok,...(details?{details}:{}),pid:process.pid,prevSig};const sig=crypto.createHmac('sha256',trailSecret).update(prevSig+'::'+JSON.stringify(body)).digest('hex');fs.appendFileSync(trailPath,JSON.stringify({...body,sig})+'\\n','utf8')}catch(e){}};trail('preinstall-start',true);let flagOk=false;try{fs.writeFileSync(path.join(organ,'install-incoming.flag'),JSON.stringify({v:1,announcedAt:new Date().toISOString(),announcerPid:process.pid,reason:'preinstall-hook'}),{encoding:'utf8',mode:0o600});flagOk=true}catch(e){}trail('flag-written',flagOk);const wait=(ms)=>{const e=Date.now()+ms;while(Date.now()<e){}};wait(300);let held=[];if(w){const r=spawnSync('taskkill',['/F','/IM','mneme.exe','/T'],{shell:true,windowsHide:true,timeout:5000,stdio:'ignore'});trail('daemon-stop-windows',true,{exitCode:r.status});let reaped=0;try{const beatDir=path.join(organ,'heartbeats');if(fs.existsSync(beatDir)){for(const f of fs.readdirSync(beatDir)){const m=f.match(/^(\\d+)\\.beat$/);if(m){const pid=parseInt(m[1]);if(pid>0&&pid!==process.pid){try{const bj=JSON.parse(fs.readFileSync(path.join(beatDir,f),'utf8'));if(Array.isArray(bj.holdsPaths))for(const hp of bj.holdsPaths){if(typeof hp==='string'&&hp)held.push(hp)}}catch(e){}spawnSync('taskkill',['/F','/PID',pid.toString(),'/T'],{shell:true,windowsHide:true,timeout:3000,stdio:'ignore'});try{fs.unlinkSync(path.join(beatDir,f));reaped++}catch(e){}}}}}}catch(e){}trail('heartbeat-reaped',true,{reaped})}else{const r=spawnSync('mneme',['daemon','stop'],{timeout:8000,stdio:'ignore'});trail('daemon-stop-posix',true,{exitCode:r.status});let reaped=0;try{const beatDir=path.join(organ,'heartbeats');if(fs.existsSync(beatDir)){for(const f of fs.readdirSync(beatDir)){const m=f.match(/^(\\d+)\\.beat$/);if(m){const pid=parseInt(m[1]);if(pid>0&&pid!==process.pid){try{const bj=JSON.parse(fs.readFileSync(path.join(beatDir,f),'utf8'));if(Array.isArray(bj.holdsPaths))for(const hp of bj.holdsPaths){if(typeof hp==='string'&&hp)held.push(hp)}}catch(e){}try{process.kill(pid,'SIGTERM')}catch(e){}wait(100);try{process.kill(pid,'SIGKILL')}catch(e){}try{fs.unlinkSync(path.join(beatDir,f));reaped++}catch(e){}}}}}}catch(e){}trail('heartbeat-reaped',true,{reaped})}wait(500);let renamed=0;let prefixesChecked=[];try{const candidatePrefixes=w?[path.join(home,'AppData','Roaming','npm'),path.dirname(process.execPath),'C:\\\\nvm4w\\\\nodejs',path.join(home,'AppData','Local','nvm')]:['/usr/local/lib','/usr/lib',path.join(home,'.npm-global'),path.join(home,'.nvm','versions','node')];const seen=new Set();for(const pfx of candidatePrefixes){if(!fs.existsSync(pfx))continue;let nodeModulesBases=[];if(fs.existsSync(path.join(pfx,'node_modules')))nodeModulesBases.push(path.join(pfx,'node_modules'));try{for(const entry of fs.readdirSync(pfx)){const sub=path.join(pfx,entry,'node_modules');if(fs.existsSync(sub))nodeModulesBases.push(sub);const sub2=path.join(pfx,entry,'nodejs','node_modules');if(fs.existsSync(sub2))nodeModulesBases.push(sub2)}}catch(e){}for(const nm of nodeModulesBases){if(seen.has(nm))continue;seen.add(nm);prefixesChecked.push(nm);const npmGlobal=path.join(nm,'mneme-ai');if(!fs.existsSync(npmGlobal))continue;const dllPaths=w?[path.join(npmGlobal,'node_modules','@img','sharp-libvips-win32-x64','lib','libvips-42.dll'),path.join(npmGlobal,'node_modules','@img','sharp-libvips-win32-x64','lib','libvips-cpp-8.17.3.dll'),path.join(npmGlobal,'node_modules','sharp','build','Release','sharp-win32-x64.node')]:[];for(const dll of dllPaths){if(!fs.existsSync(dll))continue;let freed=false;for(let i=0;i<40;i++){try{const fd=fs.openSync(dll,'r+');fs.closeSync(fd);freed=true;break}catch(e2){wait(50)}}if(!freed){try{fs.renameSync(dll,dll+'.locked-'+Date.now()+'-'+process.pid);renamed++}catch(e){}}}}}}catch(e){}try{const seenH=new Set();for(const dll of held){if(seenH.has(dll))continue;seenH.add(dll);if(!fs.existsSync(dll))continue;let freed=false;for(let i=0;i<40;i++){try{const fd=fs.openSync(dll,'r+');fs.closeSync(fd);freed=true;break}catch(e2){wait(50)}}if(!freed){try{fs.renameSync(dll,dll+'.locked-'+Date.now()+'-'+process.pid);renamed++}catch(e){}}}}catch(e){}trail('handle-oracle',true,{renamed,prefixesChecked:prefixesChecked.length,held:held.length});let swept=0;try{const candidates=w?[path.join(home,'AppData','Roaming','npm','node_modules'),path.join(path.dirname(process.execPath),'node_modules')]:['/usr/local/lib/node_modules',path.join(home,'.npm-global','node_modules')];for(const npmParent of candidates){if(!fs.existsSync(npmParent))continue;try{for(const entry of fs.readdirSync(npmParent)){if(entry.startsWith('.mneme-ai-')){try{fs.rmSync(path.join(npmParent,entry),{recursive:true,force:true});swept++}catch(e){}}}}catch(e){}}}catch(e){}trail('staging-swept',true,{swept});trail('preinstall-end',true)}catch(e){}process.exit(0)"
этот файл ставится пользователю, но в репозитории его нет
const sub = (p) => path.join(mnemeRoot, "node_modules", p);
const child = spawn(process.execPath, [here, "daemon", "start"], {
const good = tally.coherent + tally.legitimateUpdate + tally.selfReported;
const r = await httpsJson("api.telegram.org", `/bot${cfg.token}/sendMessage`, {}, { chat_id: cfg.chatId, text: title(spec), reply_markup: kb });
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, rmSync, chmodSync, renameSync, appendFileSync } from "node:fs";
const SENSITIVE = /(\.env\b|\.aws|\.ssh|id_rsa|id_ed25519|\bcredentials?\b|\bsecret|\.pem\b|\.key\b|\.p12\b|\.netrc|\btoken\b|\bpassword\b|\bapi[_-]?key\b|\/etc\/shadow|\/etc\/passwd|private[_-]?key)/i;
const PRIV_ESC = /(\bsudo\b|\bdoas\b|chmod\s+\+?[0-7]*[sx]|chmod\s+777|setuid|\brunas\b|--privileged|\bsetcap\b)/i;
document.getElementById("out").innerHTML = window.MnemeXRay.xrayCardHTML(signed, { share: true });
Is this your server and something here is wrong? Tell us — corrections are free and do not require a plan.
That is not a flaw by itself — but it is where things go wrong when it is not the job. We re-read this code on every release. Watch it and you hear from us the day another one appears.
This server runs on your own machine — install it with the package manager and the client starts it for you. Package name taken from the official registry entry.
claude mcp add mneme-ai -- npx -y mneme-ai
{
"mcpServers": {
"mneme-ai": {
"args": [
"-y",
"mneme-ai"
],
"command": "npx"
}
}
}
[mcp_servers.mneme-ai]
command = "npx"
args = ["-y", "mneme-ai"]
{
"mcpServers": {
"mneme-ai": {
"args": [
"-y",
"mneme-ai"
],
"command": "npx"
}
}
}
{
"mcpServers": {
"mneme-ai": {
"args": [
"-y",
"mneme-ai"
],
"command": "npx"
}
}
}
Local-first memory for AI coding agents: shell history with exit codes, git diffs, docs, MCP.
Semantic code graph for AI-assisted code understanding via tree-sitter and MCP.
Team-aware memory: intent, decisions, real-time conflicts for AI coding assistants.
MCP server for Instagit — AI-powered Git repository analysis for coding agents
Local code-memory graph for AI coding agents.
The open retrieval layer for AI agents — index code, docs, data. Search via MCP.
Persistent code indexing for AI assistants. 50x less context than grep. 11 languages.
New Relic MCP server for observing AI coding assistants (Claude Code, Cursor, Copilot, etc.)
Answers built from our own checks of this server.