@cachly-dev/mcp-server 0.10.209 → 0.10.210

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ import{rootCertificates as a}from"node:tls";function p(t,e,o=process.env){const l=o.CACHLY_BRAINS_TLS!=="aus",r=Number(e?.tls_port??0),s=typeof e?.tls_ca=="string"?e.tls_ca:"";return l&&Number.isInteger(r)&&r>0&&s.includes("BEGIN CERTIFICATE")?{host:t.host,port:r,tls:{ca:[...a,s]},art:"tls-eigene-stelle"}:(e?e.tls_enabled!==!1:t.tls_enabled!==!1)?{host:t.host,port:t.port,tls:{},art:"tls-system"}:{host:t.host,port:t.port,art:"klartext"}}export{p as verbindungsWeg};
package/dist/src/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import{setzeClientKennung as Ht}from"./herkunft.js";import{jwtExpiryMs as Mt,checkJwt as Dt,handleApiError as Ut,diagnoseAuth as Se,planAuthHeal as Ue,readClientCredentialsFromEnv as zt,buildClientCredentialsBody as Jt,clientCredentialsTokenUrl as Ft}from"./auth.js";import{cachlyUrl as R}from"./cachly-url.js";import{nutzungsSchluessel as Wt}from"./werkzeug-nutzung.js";import{istLieferung as Yt,lieferSchluessel as Kt,tokenDerAntwort as qt,hatTreffer as Gt,trefferSchluessel as ze}from"./geliefert.js";import{notify as Je}from"./notifier.js";import{fileURLToPath as Fe}from"node:url";import{createRequire as Vt}from"node:module";import{execFile as Ae}from"node:child_process";const Zt=process.argv[1]!=null&&(process.argv[1]===Fe(import.meta.url)||process.argv[1].endsWith("/dist/index.js")||process.argv[1].endsWith("/src/index.ts"));import{Server as We}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Qt}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport as Xt}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as Ye,ErrorCode as ie,ListPromptsRequestSchema as Ke,ListResourceTemplatesRequestSchema as qe,ListResourcesRequestSchema as Ge,ListToolsRequestSchema as Ve,McpError as oe}from"@modelcontextprotocol/sdk/types.js";import{Redis as Ze}from"ioredis";let x=process.env.CACHLY_API_URL??"https://api.cachly.dev",y=Be()??"";le(y);const Ps=process.env.CACHLY_EMBED_MODEL??"",D=(()=>{try{const e=Vt(import.meta.url);for(const t of["../../package.json","../package.json"])try{const s=e(t);if(s.name==="@cachly-dev/mcp-server"&&s.version)return s.version}catch{}}catch{}return"0.10.100"})(),eo=Number(process.env.CACHLY_PROVISION_TIMEOUT_MS??9e4);let N=xe(process.env.CACHLY_BRAIN_INSTANCE_ID);function ne(){return y||Be()||""}function F(){return xe(process.env.CACHLY_BRAIN_INSTANCE_ID)||pt()||""}let Q=0,de=null,Qe=!1;async function to(){let e=[];try{V.getClientCapabilities()?.roots&&(e=(await V.listRoots(void 0,{timeout:3e3})).roots)}catch{}return Bn({wurzeln:e,env:process.env,cwd:process.cwd(),dateiPfad:Fe})}function re(){return Qe?ft(process.env):!1}function Ce(e,t,s){!e||!re()||En({instanzId:e,vomHook:s,verbindung:H,ausGit:n=>je("brain_from_git",n,H,P),projektOrdner:t?async()=>t:to,einbetten:n=>tt(n,{geduld:"lang"}),hatEinbettung:fo,einbettenZweit:n=>tt(n,{geduld:"lang",modell:ho}),melde:n=>S("brain_from_git",{...y?{api_key:y}:{},instance_id:e,total:n,auto:"startwissen"}),startvorrat:n=>Oe("brain_seed_starter",n,H,P),meldeStartvorrat:n=>S("brain_seed_starter",{...y?{api_key:y}:{},instance_id:e,auto:!0},{seeded_count:n,auto:!0})})}function Te(){return re()&&Ln()}const oo=7e3,no=12e3,so=18e4;let ve=null;function Ee(e){return ve||(ve=io(e).finally(()=>{ve=null})),ve}async function io(e){try{if(!y){const t=Date.now()+e;for(;!Le()&&kn({})&&Date.now()<t;)await new Promise(o=>setTimeout(o,xn));const s=Le();if(!s)return!1;y=s,le(s);const n=pt();n&&!N&&(N=n,Q=0),await ue(s),n&&await pe(n),S("instant_trial_started",{tool:"sessionstart-hook",...n?{instance_id:n}:{}})}if(re()&&gt()){const t=_n();t&&(Ne(t.instanzId,re(),Te()),Ce(t.instanzId,t.projekt||void 0,t.vomHook))}}catch{}return!!y}function ro(){if(!ft(process.env))return;const e=Date.now()+so,t=setInterval(()=>{if(Date.now()>e){clearInterval(t);return}y&&!gt()||Ee(0)},500);t.unref(),Ee(0)}async function ao(){if(!y)return"";try{const e=await fetch(`${x}/api/v1/instances/auto`,{method:"POST",headers:{Authorization:`Bearer ${y}`,"Content-Type":"application/json"},signal:AbortSignal.timeout(12e3)});if(e.ok){const t=await e.json(),s=t.instance?.id??t.instance_id;if(s)return s}else fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`},body:JSON.stringify({event:"auto_provision_failed",status:e.status,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}catch{fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"auto_provision_failed",status:0,reason:"network_error",version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}return""}async function Xe(){if(N)return N;if(!y)return"";if(de)return de;const e=Date.now();if(Q>0&&e-Q<3e4)return"";Q=e,de=(async()=>{try{const t=await fetch(`${x}/api/v1/instances`,{headers:{Authorization:`Bearer ${y}`,Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(t.ok){const n=(await t.json())?.data??[],o=n.find(r=>r.status==="running")??n.find(r=>r.status==="provisioning");if(o)return N=o.id,Q=0,N;const a=await ao();if(a)return N=a,Q=0,Ne(a,re(),Te()),pe(a),Ce(a),N}}catch{}return""})();try{return await de}finally{de=null}}let Ie=0;const co=6e4;let ae="";async function ue(e){try{const{writeFile:t,mkdir:s,readFile:n}=await import("node:fs/promises"),{existsSync:o}=await import("node:fs"),{resolve:a,dirname:r}=await import("node:path"),c=process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??"";if(!c)return;const u=a(c,".claude","mcp.json");let g={};if(o(u))try{g=JSON.parse(await n(u,"utf-8"))}catch{}g.mcpServers??={};const d=g.mcpServers.cachly;if(d)d.env??={},d.env.CACHLY_JWT=e;else{const v={};v.CACHLY_JWT=e,g.mcpServers.cachly={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:v}}await s(r(u),{recursive:!0}),await t(u,JSON.stringify(g,null,2),"utf-8");const m=[a(c,".cursor","mcp.json"),a(c,".codeium","windsurf","mcp_config.json")];await Promise.allSettled(m.map(async v=>{if(o(v))try{const w=await n(v,"utf-8"),b=JSON.parse(w),l=b?.mcpServers?.cachly;l?.env&&(l.env.CACHLY_JWT=e,await t(v,JSON.stringify(b,null,2),"utf-8"))}catch{}}))}catch{}}async function pe(e){if(e){ut(e,{apiKey:y});try{const{writeFile:t,readFile:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o}=await import("node:path"),a=process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??"";if(!a)return;const r=[o(a,".claude","mcp.json"),o(a,".cursor","mcp.json"),o(a,".codeium","windsurf","mcp_config.json")];await Promise.allSettled(r.map(async c=>{if(n(c))try{const u=JSON.parse(await s(c,"utf-8")),g=u?.mcpServers?.cachly;g?.env&&(g.env.CACHLY_BRAIN_INSTANCE_ID=e,await t(c,JSON.stringify(u,null,2),"utf-8"))}catch{}}))}catch{}}}async function lo(){try{const e=await fetch(`${x}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`},body:JSON.stringify({name:"cachly-mcp-selfheal",scope:"read_write"}),signal:AbortSignal.timeout(8e3)});if(!e.ok)return!1;const t=await e.json();return t.key?(y=t.key,le(t.key),ue(t.key),S("auth_self_healed",{reason:"near_expiry_refresh"}),!0):!1}catch{return!1}}async function Re(){const e=Se(y),t=Ue(e);if(t==="none")return ae="",!0;if(t==="refresh"){const s=Date.now();return s-Ie>=co&&(Ie=s,await lo())?(ae="",!0):(ae=e.message,e.usable)}return ae=e.message,!1}function ce(e,t){const s=(r,c)=>{try{t?.(r,c)}catch{}},n=r=>{r?s(!1,r.code??r.message):s(!0)},o=Wo(e);if(!o){s(!1,"keine-http-adresse");return}const a=Yo(o);try{process.platform==="win32"?Ae("cmd",["/c","start","",a],{windowsHide:!0},n):process.platform==="darwin"?Ae("open",[o],n):Ae("xdg-open",[o],n)}catch(r){s(!1,r instanceof Error?r.message:"unknown")}}let G=null;async function uo(){try{const e=await fetch(`${x}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(8e3)});if(e.ok){const t=await e.json(),s=t.verification_uri||R("/device","ambient-signin"),n=`${s}${s.includes("?")?"&":"?"}code=${encodeURIComponent(t.user_code)}`;return{deviceCode:t.device_code,userCode:t.user_code,verifyUrl:n,pollInterval:(t.interval??5)*1e3,deadline:Date.now()+600*1e3,polling:!1}}}catch{}try{const t=await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/auth/device",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"client_id=cachly-cli&scope=openid",signal:AbortSignal.timeout(8e3)});if(!t.ok)return null;const s=await t.json();return{deviceCode:s.device_code,userCode:s.user_code,verifyUrl:s.verification_uri_complete,pollInterval:(s.interval??5)*1e3,deadline:Date.now()+600*1e3,polling:!1}}catch{return null}}async function po(e){if(Date.now()>e.deadline)return"expired";const t=async()=>{const n=await fetch(`${x}/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:e.deviceCode}),signal:AbortSignal.timeout(8e3)});return n.ok?n.json():null},s=async()=>(await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`client_id=cachly-cli&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=${e.deviceCode}`,signal:AbortSignal.timeout(8e3)})).json();try{let n=await t().catch(()=>null);if(n||(n=await s().catch(()=>null)),!n)return"pending";if(n.access_token){let o=n.access_token;try{const a=await fetch(`${x}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({name:"cachly-mcp-smithery",scope:"read_write"}),signal:AbortSignal.timeout(8e3)});if(a.ok){const r=await a.json();r.key&&(o=r.key)}}catch{}return y=o,le(o),G=null,S("device_flow_completed"),ue(o),X(o),Q=0,await Xe(),N&&pe(N),"done"}return n.error==="slow_down"&&(e.pollInterval=Math.min(e.pollInterval+2e3,15e3)),"pending"}catch{return"pending"}}async function et(e){if(e.polling)return"pending";e.polling=!0;try{return await po(e)}finally{e.polling=!1}}function mo(e,t=et,s=o=>G===o,n=go){const o=async()=>{if(!s(e))return;let a="pending";try{a=await t(e)}catch{}if(a!=="done"){if(a==="expired"){s(e)&&(G=null);return}s(e)&&n(o,e.pollInterval)}};n(o,e.pollInterval)}function go(e,t){const s=setTimeout(e,t);typeof s.unref=="function"&&s.unref()}import{setEmbedJwt as le,computeEmbedding as tt,hasEmbedProvider as fo,EMBED_PROVIDER as ot}from"./embeddings.js";import{ZWEIT_MODELL as ho}from"./rangfolge-stellschrauben.js";import{tokenize as yo,splitMultiQuery as bo,levenshtein as vo,recencyBoost as wo,extractTimestamp as xo,STOPWORDS as _o,katakanaToRomaji as $o,arabicLightStem as ko,expandCrossLingual as So,CROSS_LINGUAL_MAP as Ao,ZERO_RESULTS_LOG as Co,zeroResultsTotal as To}from"./search.js";const se=new Map;function Eo(e){return e<=1?200:null}async function H(e){if(!e)throw new oe(ie.InvalidRequest,`\u23F3 Your Brain instance is still being set up.
2
+ import{setzeClientKennung as Mt}from"./herkunft.js";import{jwtExpiryMs as Dt,checkJwt as Ut,handleApiError as zt,diagnoseAuth as Se,planAuthHeal as Ue,readClientCredentialsFromEnv as Jt,buildClientCredentialsBody as Wt,clientCredentialsTokenUrl as Ft}from"./auth.js";import{cachlyUrl as R}from"./cachly-url.js";import{nutzungsSchluessel as Yt}from"./werkzeug-nutzung.js";import{istLieferung as Kt,lieferSchluessel as qt,tokenDerAntwort as Gt,hatTreffer as Vt,trefferSchluessel as ze}from"./geliefert.js";import{notify as Je}from"./notifier.js";import{fileURLToPath as We}from"node:url";import{createRequire as Zt}from"node:module";import{execFile as Ae}from"node:child_process";const Qt=process.argv[1]!=null&&(process.argv[1]===We(import.meta.url)||process.argv[1].endsWith("/dist/index.js")||process.argv[1].endsWith("/src/index.ts"));import{Server as Fe}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Xt}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport as eo}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as Ye,ErrorCode as ie,ListPromptsRequestSchema as Ke,ListResourceTemplatesRequestSchema as qe,ListResourcesRequestSchema as Ge,ListToolsRequestSchema as Ve,McpError as oe}from"@modelcontextprotocol/sdk/types.js";import{Redis as Ze}from"ioredis";let x=process.env.CACHLY_API_URL??"https://api.cachly.dev",y=Be()??"";le(y);const Hs=process.env.CACHLY_EMBED_MODEL??"",D=(()=>{try{const e=Zt(import.meta.url);for(const t of["../../package.json","../package.json"])try{const s=e(t);if(s.name==="@cachly-dev/mcp-server"&&s.version)return s.version}catch{}}catch{}return"0.10.100"})(),to=Number(process.env.CACHLY_PROVISION_TIMEOUT_MS??9e4);let N=xe(process.env.CACHLY_BRAIN_INSTANCE_ID);function ne(){return y||Be()||""}function W(){return xe(process.env.CACHLY_BRAIN_INSTANCE_ID)||pt()||""}let Q=0,de=null,Qe=!1;async function oo(){let e=[];try{V.getClientCapabilities()?.roots&&(e=(await V.listRoots(void 0,{timeout:3e3})).roots)}catch{}return Ln({wurzeln:e,env:process.env,cwd:process.cwd(),dateiPfad:We})}function re(){return Qe?ft(process.env):!1}function Ce(e,t,s){!e||!re()||In({instanzId:e,vomHook:s,verbindung:H,ausGit:n=>je("brain_from_git",n,H,P),projektOrdner:t?async()=>t:oo,einbetten:n=>tt(n,{geduld:"lang"}),hatEinbettung:ho,einbettenZweit:n=>tt(n,{geduld:"lang",modell:yo}),melde:n=>S("brain_from_git",{...y?{api_key:y}:{},instance_id:e,total:n,auto:"startwissen"}),startvorrat:n=>Oe("brain_seed_starter",n,H,P),meldeStartvorrat:n=>S("brain_seed_starter",{...y?{api_key:y}:{},instance_id:e,auto:!0},{seeded_count:n,auto:!0})})}function Te(){return re()&&Nn()}const no=7e3,so=12e3,io=18e4;let ve=null;function Ee(e){return ve||(ve=ro(e).finally(()=>{ve=null})),ve}async function ro(e){try{if(!y){const t=Date.now()+e;for(;!Le()&&Sn({})&&Date.now()<t;)await new Promise(o=>setTimeout(o,_n));const s=Le();if(!s)return!1;y=s,le(s);const n=pt();n&&!N&&(N=n,Q=0),await ue(s),n&&await pe(n),S("instant_trial_started",{tool:"sessionstart-hook",...n?{instance_id:n}:{}})}if(re()&&gt()){const t=$n();t&&(Ne(t.instanzId,re(),Te()),Ce(t.instanzId,t.projekt||void 0,t.vomHook))}}catch{}return!!y}function ao(){if(!ft(process.env))return;const e=Date.now()+io,t=setInterval(()=>{if(Date.now()>e){clearInterval(t);return}y&&!gt()||Ee(0)},500);t.unref(),Ee(0)}async function co(){if(!y)return"";try{const e=await fetch(`${x}/api/v1/instances/auto`,{method:"POST",headers:{Authorization:`Bearer ${y}`,"Content-Type":"application/json"},signal:AbortSignal.timeout(12e3)});if(e.ok){const t=await e.json(),s=t.instance?.id??t.instance_id;if(s)return s}else fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`},body:JSON.stringify({event:"auto_provision_failed",status:e.status,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}catch{fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"auto_provision_failed",status:0,reason:"network_error",version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}return""}async function Xe(){if(N)return N;if(!y)return"";if(de)return de;const e=Date.now();if(Q>0&&e-Q<3e4)return"";Q=e,de=(async()=>{try{const t=await fetch(`${x}/api/v1/instances`,{headers:{Authorization:`Bearer ${y}`,Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(t.ok){const n=(await t.json())?.data??[],o=n.find(c=>c.status==="running")??n.find(c=>c.status==="provisioning");if(o)return N=o.id,Q=0,N;const a=await co();if(a)return N=a,Q=0,Ne(a,re(),Te()),pe(a),Ce(a),N}}catch{}return""})();try{return await de}finally{de=null}}let Ie=0;const lo=6e4;let ae="";async function ue(e){try{const{writeFile:t,mkdir:s,readFile:n}=await import("node:fs/promises"),{existsSync:o}=await import("node:fs"),{resolve:a,dirname:c}=await import("node:path"),r=process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??"";if(!r)return;const d=a(r,".claude","mcp.json");let g={};if(o(d))try{g=JSON.parse(await n(d,"utf-8"))}catch{}g.mcpServers??={};const u=g.mcpServers.cachly;if(u)u.env??={},u.env.CACHLY_JWT=e;else{const v={};v.CACHLY_JWT=e,g.mcpServers.cachly={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:v}}await s(c(d),{recursive:!0}),await t(d,JSON.stringify(g,null,2),"utf-8");const m=[a(r,".cursor","mcp.json"),a(r,".codeium","windsurf","mcp_config.json")];await Promise.allSettled(m.map(async v=>{if(o(v))try{const w=await n(v,"utf-8"),b=JSON.parse(w),l=b?.mcpServers?.cachly;l?.env&&(l.env.CACHLY_JWT=e,await t(v,JSON.stringify(b,null,2),"utf-8"))}catch{}}))}catch{}}async function pe(e){if(e){ut(e,{apiKey:y});try{const{writeFile:t,readFile:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o}=await import("node:path"),a=process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??"";if(!a)return;const c=[o(a,".claude","mcp.json"),o(a,".cursor","mcp.json"),o(a,".codeium","windsurf","mcp_config.json")];await Promise.allSettled(c.map(async r=>{if(n(r))try{const d=JSON.parse(await s(r,"utf-8")),g=d?.mcpServers?.cachly;g?.env&&(g.env.CACHLY_BRAIN_INSTANCE_ID=e,await t(r,JSON.stringify(d,null,2),"utf-8"))}catch{}}))}catch{}}}async function uo(){try{const e=await fetch(`${x}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`},body:JSON.stringify({name:"cachly-mcp-selfheal",scope:"read_write"}),signal:AbortSignal.timeout(8e3)});if(!e.ok)return!1;const t=await e.json();return t.key?(y=t.key,le(t.key),ue(t.key),S("auth_self_healed",{reason:"near_expiry_refresh"}),!0):!1}catch{return!1}}async function Re(){const e=Se(y),t=Ue(e);if(t==="none")return ae="",!0;if(t==="refresh"){const s=Date.now();return s-Ie>=lo&&(Ie=s,await uo())?(ae="",!0):(ae=e.message,e.usable)}return ae=e.message,!1}function ce(e,t){const s=(c,r)=>{try{t?.(c,r)}catch{}},n=c=>{c?s(!1,c.code??c.message):s(!0)},o=Yo(e);if(!o){s(!1,"keine-http-adresse");return}const a=Ko(o);try{process.platform==="win32"?Ae("cmd",["/c","start","",a],{windowsHide:!0},n):process.platform==="darwin"?Ae("open",[o],n):Ae("xdg-open",[o],n)}catch(c){s(!1,c instanceof Error?c.message:"unknown")}}let G=null;async function po(){try{const e=await fetch(`${x}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(8e3)});if(e.ok){const t=await e.json(),s=t.verification_uri||R("/device","ambient-signin"),n=`${s}${s.includes("?")?"&":"?"}code=${encodeURIComponent(t.user_code)}`;return{deviceCode:t.device_code,userCode:t.user_code,verifyUrl:n,pollInterval:(t.interval??5)*1e3,deadline:Date.now()+600*1e3,polling:!1}}}catch{}try{const t=await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/auth/device",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"client_id=cachly-cli&scope=openid",signal:AbortSignal.timeout(8e3)});if(!t.ok)return null;const s=await t.json();return{deviceCode:s.device_code,userCode:s.user_code,verifyUrl:s.verification_uri_complete,pollInterval:(s.interval??5)*1e3,deadline:Date.now()+600*1e3,polling:!1}}catch{return null}}async function mo(e){if(Date.now()>e.deadline)return"expired";const t=async()=>{const n=await fetch(`${x}/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:e.deviceCode}),signal:AbortSignal.timeout(8e3)});return n.ok?n.json():null},s=async()=>(await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`client_id=cachly-cli&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=${e.deviceCode}`,signal:AbortSignal.timeout(8e3)})).json();try{let n=await t().catch(()=>null);if(n||(n=await s().catch(()=>null)),!n)return"pending";if(n.access_token){let o=n.access_token;try{const a=await fetch(`${x}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({name:"cachly-mcp-smithery",scope:"read_write"}),signal:AbortSignal.timeout(8e3)});if(a.ok){const c=await a.json();c.key&&(o=c.key)}}catch{}return y=o,le(o),G=null,S("device_flow_completed"),ue(o),X(o),Q=0,await Xe(),N&&pe(N),"done"}return n.error==="slow_down"&&(e.pollInterval=Math.min(e.pollInterval+2e3,15e3)),"pending"}catch{return"pending"}}async function et(e){if(e.polling)return"pending";e.polling=!0;try{return await mo(e)}finally{e.polling=!1}}function go(e,t=et,s=o=>G===o,n=fo){const o=async()=>{if(!s(e))return;let a="pending";try{a=await t(e)}catch{}if(a!=="done"){if(a==="expired"){s(e)&&(G=null);return}s(e)&&n(o,e.pollInterval)}};n(o,e.pollInterval)}function fo(e,t){const s=setTimeout(e,t);typeof s.unref=="function"&&s.unref()}import{setEmbedJwt as le,computeEmbedding as tt,hasEmbedProvider as ho,EMBED_PROVIDER as ot}from"./embeddings.js";import{ZWEIT_MODELL as yo}from"./rangfolge-stellschrauben.js";import{tokenize as bo,splitMultiQuery as vo,levenshtein as wo,recencyBoost as xo,extractTimestamp as _o,STOPWORDS as $o,katakanaToRomaji as ko,arabicLightStem as So,expandCrossLingual as Ao,CROSS_LINGUAL_MAP as Co,ZERO_RESULTS_LOG as To,zeroResultsTotal as Eo}from"./search.js";const se=new Map;function Io(e){return e<=1?200:null}async function H(e){if(!e)throw new oe(ie.InvalidRequest,`\u23F3 Your Brain instance is still being set up.
3
3
 
4
4
  This usually resolves in a few seconds \u2014 just call the tool again and it will connect automatically.
5
5
 
6
6
  If it keeps happening:
7
7
  \u2022 Run \`list_instances\` to check your instances, or
8
8
  \u2022 Set CACHLY_BRAIN_INSTANCE_ID in your MCP config, or
9
- \u2022 Reach us at support@cachly.dev.`);const t=se.get(e);return t||Cn(Io,e,()=>Ro(e))}const Io=new Map;async function Ro(e){W("verbindung: Instanz abfragen");let t=await P(`/api/v1/instances/${e}`);if(W(`verbindung: Instanz ${t.status}`),t=await An(t,()=>P(`/api/v1/instances/${e}`),{fristMs:eo,melde:r=>W(`verbindung: Instanz ${r.status}`)}),t.status!=="running"){fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",...y?{Authorization:`Bearer ${y}`}:{}},body:JSON.stringify({event:"instance_not_reachable",instance_id:e,status:t.status,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{});let r;throw t.status==="provisioning"?r=`\u23F3 Brain instance "${t.name}" is still starting up.
9
+ \u2022 Reach us at support@cachly.dev.`);const t=se.get(e);return t||Tn(Ro,e,()=>jo(e))}const Ro=new Map;async function jo(e){F("verbindung: Instanz abfragen");let t=await P(`/api/v1/instances/${e}`);if(F(`verbindung: Instanz ${t.status}`),t=await Cn(t,()=>P(`/api/v1/instances/${e}`),{fristMs:to,melde:r=>F(`verbindung: Instanz ${r.status}`)}),t.status!=="running"){fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",...y?{Authorization:`Bearer ${y}`}:{}},body:JSON.stringify({event:"instance_not_reachable",instance_id:e,status:t.status,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{});let r;throw t.status==="provisioning"?r=`\u23F3 Brain instance "${t.name}" is still starting up.
10
10
 
11
11
  First-time provisioning typically takes 1\u20133 minutes. Please retry in a moment \u2014 the instance will be ready soon.`:t.status==="failed"?r=`\u274C Brain instance "${t.name}" failed to start.
12
12
 
@@ -18,52 +18,52 @@ Update your payment method at: ${R("/billing","upgrade")}`:t.status==="pending_p
18
18
  Complete your checkout at: ${R("/instances","upgrade")}`:r=`Brain instance "${t.name}" is not reachable (status: ${t.status}).
19
19
 
20
20
  \u2022 View your instance at: ${R("/instances","instance-error")}
21
- \u2022 Run \`get_api_status\` for a full diagnostic.`,new oe(ie.InvalidRequest,r)}if(!t.host||!t.port)throw new oe(ie.InternalError,`Instance "${t.name}" is running but has no host/port \u2014 contact support@cachly.dev.`);let s,n=t.tls_enabled!==!1;try{const r=await P(`/api/v1/instances/${e}/connection`);s=r.password??void 0,n=r.tls_enabled!==!1,W("verbindung: Zugangsdaten da")}catch(r){const c=r instanceof Error?r.message:String(r);if(c.includes("401")||c.includes("403")||c.includes("Unauthorized"))throw new oe(ie.InvalidRequest,"API key rejected \u2014 run `cachly setup` to refresh your credentials.")}const o=new Ze({host:t.host,port:t.port,password:s||void 0,commandTimeout:8e3,...n?{tls:{}}:{},lazyConnect:!0,enableReadyCheck:!0,connectTimeout:8e3,retryStrategy:Eo,maxRetriesPerRequest:1,keepAlive:15e3}),a=()=>{se.delete(e),o.disconnect()};o.on("error",a),o.on("end",a);try{await o.connect()}catch(r){o.disconnect();const c=r instanceof Error?r.message:String(r);throw fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",...y?{Authorization:`Bearer ${y}`}:{}},body:JSON.stringify({event:"redis_connect_failed",instance_id:e,host:t.host,port:t.port,error:c,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{}),new oe(ie.InternalError,`Could not reach Brain instance "${t.name}" (${t.host}:${t.port}).
21
+ \u2022 Run \`get_api_status\` for a full diagnostic.`,new oe(ie.InvalidRequest,r)}if(!t.host||!t.port)throw new oe(ie.InternalError,`Instance "${t.name}" is running but has no host/port \u2014 contact support@cachly.dev.`);let s,n;try{const r=await P(`/api/v1/instances/${e}/connection`);s=r.password??void 0,n=r,F("verbindung: Zugangsdaten da")}catch(r){const d=r instanceof Error?r.message:String(r);if(d.includes("401")||d.includes("403")||d.includes("Unauthorized"))throw new oe(ie.InvalidRequest,"API key rejected \u2014 run `cachly setup` to refresh your credentials.")}const o=vt({host:t.host,port:t.port,tls_enabled:t.tls_enabled},n),a=new Ze({host:o.host,port:o.port,password:s||void 0,commandTimeout:8e3,...o.tls?{tls:o.tls}:{},lazyConnect:!0,enableReadyCheck:!0,connectTimeout:8e3,retryStrategy:Io,maxRetriesPerRequest:1,keepAlive:15e3}),c=()=>{se.delete(e),a.disconnect()};a.on("error",c),a.on("end",c);try{await a.connect()}catch(r){a.disconnect();const d=r instanceof Error?r.message:String(r);throw fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",...y?{Authorization:`Bearer ${y}`}:{}},body:JSON.stringify({event:"redis_connect_failed",instance_id:e,host:t.host,port:t.port,error:d,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{}),new oe(ie.InternalError,`Could not reach Brain instance "${t.name}" (${t.host}:${t.port}).
22
22
 
23
23
  \u2022 Check your network connection
24
24
  \u2022 Run \`get_api_status\` to verify instance status
25
- \u2022 Technical detail: ${c}`)}return se.set(e,o),W("verbindung: Valkey verbunden"),o}async function P(e,t={},s=!1){s||Ue(Se(y))!=="none"&&await Re(),Dt(y);const n=Number(process.env.CACHLY_API_TIMEOUT_MS??15e3),o=await fetch(`${x}${e}`,{...t,signal:AbortSignal.timeout(n),headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`,...t.headers}});if(!o.ok){if(o.status===401&&!s&&(Ie=0,await Re()))return P(e,t,!0);const r=(await o.json().catch(()=>({error:o.statusText}))).error??o.statusText;Ut(o.status,r)}if(o.status!==204)return o.json()}import{handleBrainTool as jo}from"./handlers/brain.js";import{handleContextTool as Bo}from"./handlers/context.js";import{handleInstanceTool as Lo}from"./handlers/instances.js";import{handleCacheTool as No}from"./handlers/cache.js";import{handleTeamTool as Oo}from"./handlers/team.js";import{handleRoadmapTool as Po}from"./handlers/roadmap.js";import{handleAdvancedTool as Ho}from"./handlers/advanced.js";import{handleSyndicateTool as Mo}from"./handlers/syndicate.js";import{handleFedbrainTool as je,_lastBrainFromGitCounts as we}from"./handlers/fedbrain.js";import{extractFirstRecallProof as Do,renderFirstRecallProof as Uo}from"./first-recall-proof.js";import{installClsPostCommitHook as nt,CLS_HOOK_VERSION as st}from"./cls-hook.js";import{CLAUDE_MD_MARKER_START as it,CLAUDE_MD_MARKER_END as rt,EDITOR_FILES as me,ANWEISUNGS_DATEIEN as zo,setzeAnweisungsblock as Jo}from"./projektdateien.js";import{uninstallBefehl as Fo}from"./uninstall.js";import{gitLesen as at}from"./git-ohne-shell.js";import{browserAdresse as Wo,fuerCmd as Yo}from"./browser-adresse.js";import{installAmbientHooks as ct,installCursorHooks as Ko,installCopilotHooks as qo,installCodexHooks as Go,installGeminiHooks as Vo,AMBIENT_HOOK_VERSION as lt,COPILOT_HOOKS_DATEI as Zo,CODEX_HOOKS_DATEI as Qo,GEMINI_SETTINGS_DATEI as Xo}from"./ambient-hooks.js";import{hookHauptlauf as en,auffrischenHauptlauf as tn,startwissenImportHauptlauf as on}from"./ambient-hook.js";import{STARTWISSEN_IMPORT as nn}from"./startwissen-hook.js";import{rahmeAntwort as sn}from"./antwort-rahmen.js";import{appendLedgerEntry as rn,readLedger as dt,defaultLedgerPath as an,reportLedgerEntry as cn,teileNachInstanz as ln}from"./ambient-ledger.js";import{installCodexMcp as dn,installGeminiMcp as un}from"./editor-mcp-eintrag.js";import{resolveApiKey as Be,saveApiKey as X,saveInstanceId as ut,readSavedApiKey as Le,readInstanceId as pt}from"./credentials.js";import{KEYCLOAK_BASIS as mt,istTestSchluessel as pn,waehleTestSchluessel as mn,starteKeycloakAnmeldung as gn,warteAufKeycloakAnmeldung as fn,uebernimm as hn,brainImKonto as yn,erfolgsText as bn,fehlerText as vn,ersetzeSchluessel as wn}from"./uebernahme.js";import{WARTE_TAKT_MS as xn,auftragLiegt as gt,nimmAuftrag as _n,sichereKonto as $n,sperreLiegt as kn,startwissenEingeschaltet as ft}from"./konto-anlegen.js";import{sichereZugang as Sn,echterWert as xe}from"./zugang.js";import{zeitpunkt as W}from"./zeitmessung.js";import{warteAufLaufendeInstanz as An,gemeinsamerAufbau as Cn}from"./instanz-warten.js";import{merkeNeuesBrain as Ne,startetLautLetztemBlick as Tn}from"./leeres-brain.js";import{starteStartwissen as En,startwissenGestartet as In,beanspruchStartwissen as Rn,holeStartwissenHinweis as jn,waehleProjektOrdner as Bn,startvorratErlaubt as Ln}from"./startwissen.js";import{eigeneFassung as Nn,pruefeNeueFassung as On,holeNeueFassungHinweis as Pn}from"./neue-fassung.js";import{beiStdinEnde as Hn}from"./stdin-ende.js";import{merkeWerkzeugAufruf as Mn,starteBrandWachhund as Dn}from"./brand-wachhund.js";import{sichtbareWerkzeuge as Un,VERTEILER as ht}from"./werkzeug-auswahl.js";import{buildLessonsMarkdown as zn,buildLessonsJsonl as Jn,vonRohLektion as Fn}from"./brain-export.js";import{detectEditor as Wn}from"./editor.js";import{milestoneSent as yt,markMilestoneSent as bt}from"./funnel-milestones.js";import{kostprobeUebrig as Yn,kostprobeVerbrauchen as Kn,kostprobeHinweis as qn,schrankeNachKostproben as Gn}from"./kostprobe.js";import{netBalance as Vn}from"./ambient-recall.js";import{handleShareTool as Oe}from"./handlers/share.js";import{handleVizTool as Zn}from"./handlers/viz.js";import{commitArt as Qn,istRueckbau as Xn,zaehleLektionen as es}from"./commit-art.js";import{TOOLS as ge}from"./tools.js";let vt=!1,wt=!1,_e=!1;function xt(){return Wn()}function ts(e){if(!e)return null;const t=e.match(/\*\*💡\s+([^*]+)\*\*/),s=e.match(/^>\s+(.+)$/m);if(!t||!s)return null;const n=t[1].trim(),o=s[1].trim();return!n||!o?null:{topic:n,what:o}}function os(e){try{const t=e.split(".");if(t.length!==3)return;const s=JSON.parse(Buffer.from(t[1],"base64url").toString("utf-8"));if(!s.sub)return;let n=2166136261;for(let o=0;o<s.sub.length;o++)n^=s.sub.charCodeAt(o),n=n*16777619>>>0;return n.toString(16).padStart(8,"0")+s.sub.length.toString(16).padStart(4,"0")}catch{return}}function S(e,t,s){if(process.env.CACHLY_NO_TELEMETRY==="1")return;const n=y?os(y):void 0;fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:e,version:D,editor:xt(),...y?{jwt:y}:{},...n?{user_fingerprint:n}:{},...s?{metrics:s}:{},...t}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}function ns(e,t){return cn({apiUrl:x,jwt:y,instanceId:e},t)}async function ss(e){if(!vt&&process.env.CACHLY_NO_TELEMETRY!=="1"){vt=!0;try{await fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"first_call_no_jwt",version:D,editor:xt(),tool:e}),signal:AbortSignal.timeout(3e3)})}catch{}}}const is=new Set(["causal_trace","brain_predict","brain_plan","brain_predict_failures","team_learn","team_confirm","team_recall","team_synthesize","team_crystallize","global_learn","global_recall"]),rs={causal_trace:"Causal root-cause tracing \u2014 follow the failure chain to the real cause, not just the symptom.",brain_predict:"Predictive risk \u2014 your Brain warns you what will break *before* you run it.",brain_plan:"Generative planning \u2014 turn a goal into an ordered, risk-aware plan from your own history.",brain_predict_failures:"Failure prediction \u2014 catch CI/build breakage before it happens.",team_learn:"Team Brain \u2014 one shared memory across your whole team.",team_confirm:"Team Brain \u2014 peer + senior review that raises lesson trust.",team_recall:"Team Brain \u2014 recall everything your teammates have already solved.",team_synthesize:"Team Brain \u2014 synthesize collective knowledge across authors.",team_crystallize:"Team Brain \u2014 compress your team's wisdom into a shareable crystal.",global_learn:"Team Brain \u2014 contribute to your organization's shared memory.",global_recall:"Team Brain \u2014 recall across your entire organization."},_t=R("/billing","upgrade"),$t=new Map;async function as(e){const t=$t.get(e);if(t&&t.expiresAt>Date.now())return t.info;try{const n=((await P(`/api/v1/instances/${e}`))?.tier??"free").toLowerCase(),o={tier:n,isFree:n==="free"||n===""};return $t.set(e,{info:o,expiresAt:Date.now()+6e4}),o}catch{return{tier:"unknown",isFree:!1}}}async function cs(e,t){if(!is.has(e)||!t)return null;const{isFree:s}=await as(t);if(!s)return null;const n=rs[e]??"A Premium intelligence feature.";if(Yn(e)){const o=Kn(e);return{kostprobe:qn(e,o,_t)}}return{sperre:Gn(e,n,_t)}}async function ls(e,t){try{await(await H(e)).hincrby(Wt(e),t,1)}catch{}}async function ds(e,t,s){if(Yt(t))try{const n=await H(e),o=Gt(s);await n.incrby(Kt(e),o?qt(s):0),await n.hincrby(ze(e),"abrufe",1),o&&await n.hincrby(ze(e),"treffer",1)}catch{}}async function us(e){const t=await uo();return t?(G=t,S("device_flow_started",{tool:e}),ce(t.verifyUrl,(s,n)=>{if(s){S("device_browser_opened",{stelle:"tool"});return}S("device_browser_failed",{reason:n??"unknown",stelle:"tool"}),process.stderr.write(`
25
+ \u2022 Technical detail: ${d}`)}return se.set(e,a),F("verbindung: Valkey verbunden"),a}async function P(e,t={},s=!1){s||Ue(Se(y))!=="none"&&await Re(),Ut(y);const n=Number(process.env.CACHLY_API_TIMEOUT_MS??15e3),o=await fetch(`${x}${e}`,{...t,signal:AbortSignal.timeout(n),headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`,...t.headers}});if(!o.ok){if(o.status===401&&!s&&(Ie=0,await Re()))return P(e,t,!0);const c=(await o.json().catch(()=>({error:o.statusText}))).error??o.statusText;zt(o.status,c)}if(o.status!==204)return o.json()}import{handleBrainTool as Bo}from"./handlers/brain.js";import{handleContextTool as Lo}from"./handlers/context.js";import{handleInstanceTool as No}from"./handlers/instances.js";import{handleCacheTool as Oo}from"./handlers/cache.js";import{handleTeamTool as Po}from"./handlers/team.js";import{handleRoadmapTool as Ho}from"./handlers/roadmap.js";import{handleAdvancedTool as Mo}from"./handlers/advanced.js";import{handleSyndicateTool as Do}from"./handlers/syndicate.js";import{handleFedbrainTool as je,_lastBrainFromGitCounts as we}from"./handlers/fedbrain.js";import{extractFirstRecallProof as Uo,renderFirstRecallProof as zo}from"./first-recall-proof.js";import{installClsPostCommitHook as nt,CLS_HOOK_VERSION as st}from"./cls-hook.js";import{CLAUDE_MD_MARKER_START as it,CLAUDE_MD_MARKER_END as rt,EDITOR_FILES as me,ANWEISUNGS_DATEIEN as Jo,setzeAnweisungsblock as Wo}from"./projektdateien.js";import{uninstallBefehl as Fo}from"./uninstall.js";import{gitLesen as at}from"./git-ohne-shell.js";import{browserAdresse as Yo,fuerCmd as Ko}from"./browser-adresse.js";import{installAmbientHooks as ct,installCursorHooks as qo,installCopilotHooks as Go,installCodexHooks as Vo,installGeminiHooks as Zo,AMBIENT_HOOK_VERSION as lt,COPILOT_HOOKS_DATEI as Qo,CODEX_HOOKS_DATEI as Xo,GEMINI_SETTINGS_DATEI as en}from"./ambient-hooks.js";import{hookHauptlauf as tn,auffrischenHauptlauf as on,startwissenImportHauptlauf as nn}from"./ambient-hook.js";import{STARTWISSEN_IMPORT as sn}from"./startwissen-hook.js";import{rahmeAntwort as rn}from"./antwort-rahmen.js";import{appendLedgerEntry as an,readLedger as dt,defaultLedgerPath as cn,reportLedgerEntry as ln,teileNachInstanz as dn}from"./ambient-ledger.js";import{installCodexMcp as un,installGeminiMcp as pn}from"./editor-mcp-eintrag.js";import{resolveApiKey as Be,saveApiKey as X,saveInstanceId as ut,readSavedApiKey as Le,readInstanceId as pt}from"./credentials.js";import{KEYCLOAK_BASIS as mt,istTestSchluessel as mn,waehleTestSchluessel as gn,starteKeycloakAnmeldung as fn,warteAufKeycloakAnmeldung as hn,uebernimm as yn,brainImKonto as bn,erfolgsText as vn,fehlerText as wn,ersetzeSchluessel as xn}from"./uebernahme.js";import{WARTE_TAKT_MS as _n,auftragLiegt as gt,nimmAuftrag as $n,sichereKonto as kn,sperreLiegt as Sn,startwissenEingeschaltet as ft}from"./konto-anlegen.js";import{sichereZugang as An,echterWert as xe}from"./zugang.js";import{zeitpunkt as F}from"./zeitmessung.js";import{warteAufLaufendeInstanz as Cn,gemeinsamerAufbau as Tn}from"./instanz-warten.js";import{merkeNeuesBrain as Ne,startetLautLetztemBlick as En}from"./leeres-brain.js";import{starteStartwissen as In,startwissenGestartet as Rn,beanspruchStartwissen as jn,holeStartwissenHinweis as Bn,waehleProjektOrdner as Ln,startvorratErlaubt as Nn}from"./startwissen.js";import{eigeneFassung as On,pruefeNeueFassung as Pn,holeNeueFassungHinweis as Hn}from"./neue-fassung.js";import{beiStdinEnde as Mn}from"./stdin-ende.js";import{merkeWerkzeugAufruf as Dn,starteBrandWachhund as Un}from"./brand-wachhund.js";import{sichtbareWerkzeuge as zn,VERTEILER as ht}from"./werkzeug-auswahl.js";import{buildLessonsMarkdown as Jn,buildLessonsJsonl as Wn,vonRohLektion as Fn}from"./brain-export.js";import{detectEditor as Yn}from"./editor.js";import{milestoneSent as yt,markMilestoneSent as bt}from"./funnel-milestones.js";import{kostprobeUebrig as Kn,kostprobeVerbrauchen as qn,kostprobeHinweis as Gn,schrankeNachKostproben as Vn}from"./kostprobe.js";import{netBalance as Zn}from"./ambient-recall.js";import{handleShareTool as Oe}from"./handlers/share.js";import{handleVizTool as Qn}from"./handlers/viz.js";import{commitArt as Xn,istRueckbau as es,zaehleLektionen as ts}from"./commit-art.js";import{TOOLS as ge}from"./tools.js";import{verbindungsWeg as vt}from"./brains-tls.js";let wt=!1,xt=!1,_e=!1;function _t(){return Yn()}function os(e){if(!e)return null;const t=e.match(/\*\*💡\s+([^*]+)\*\*/),s=e.match(/^>\s+(.+)$/m);if(!t||!s)return null;const n=t[1].trim(),o=s[1].trim();return!n||!o?null:{topic:n,what:o}}function ns(e){try{const t=e.split(".");if(t.length!==3)return;const s=JSON.parse(Buffer.from(t[1],"base64url").toString("utf-8"));if(!s.sub)return;let n=2166136261;for(let o=0;o<s.sub.length;o++)n^=s.sub.charCodeAt(o),n=n*16777619>>>0;return n.toString(16).padStart(8,"0")+s.sub.length.toString(16).padStart(4,"0")}catch{return}}function S(e,t,s){if(process.env.CACHLY_NO_TELEMETRY==="1")return;const n=y?ns(y):void 0;fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:e,version:D,editor:_t(),...y?{jwt:y}:{},...n?{user_fingerprint:n}:{},...s?{metrics:s}:{},...t}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}function ss(e,t){return ln({apiUrl:x,jwt:y,instanceId:e},t)}async function is(e){if(!wt&&process.env.CACHLY_NO_TELEMETRY!=="1"){wt=!0;try{await fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"first_call_no_jwt",version:D,editor:_t(),tool:e}),signal:AbortSignal.timeout(3e3)})}catch{}}}const rs=new Set(["causal_trace","brain_predict","brain_plan","brain_predict_failures","team_learn","team_confirm","team_recall","team_synthesize","team_crystallize","global_learn","global_recall"]),as={causal_trace:"Causal root-cause tracing \u2014 follow the failure chain to the real cause, not just the symptom.",brain_predict:"Predictive risk \u2014 your Brain warns you what will break *before* you run it.",brain_plan:"Generative planning \u2014 turn a goal into an ordered, risk-aware plan from your own history.",brain_predict_failures:"Failure prediction \u2014 catch CI/build breakage before it happens.",team_learn:"Team Brain \u2014 one shared memory across your whole team.",team_confirm:"Team Brain \u2014 peer + senior review that raises lesson trust.",team_recall:"Team Brain \u2014 recall everything your teammates have already solved.",team_synthesize:"Team Brain \u2014 synthesize collective knowledge across authors.",team_crystallize:"Team Brain \u2014 compress your team's wisdom into a shareable crystal.",global_learn:"Team Brain \u2014 contribute to your organization's shared memory.",global_recall:"Team Brain \u2014 recall across your entire organization."},$t=R("/billing","upgrade"),kt=new Map;async function cs(e){const t=kt.get(e);if(t&&t.expiresAt>Date.now())return t.info;try{const n=((await P(`/api/v1/instances/${e}`))?.tier??"free").toLowerCase(),o={tier:n,isFree:n==="free"||n===""};return kt.set(e,{info:o,expiresAt:Date.now()+6e4}),o}catch{return{tier:"unknown",isFree:!1}}}async function ls(e,t){if(!rs.has(e)||!t)return null;const{isFree:s}=await cs(t);if(!s)return null;const n=as[e]??"A Premium intelligence feature.";if(Kn(e)){const o=qn(e);return{kostprobe:Gn(e,o,$t)}}return{sperre:Vn(e,n,$t)}}async function ds(e,t){try{await(await H(e)).hincrby(Yt(e),t,1)}catch{}}async function us(e,t,s){if(Kt(t))try{const n=await H(e),o=Vt(s);await n.incrby(qt(e),o?Gt(s):0),await n.hincrby(ze(e),"abrufe",1),o&&await n.hincrby(ze(e),"treffer",1)}catch{}}async function ps(e){const t=await po();return t?(G=t,S("device_flow_started",{tool:e}),ce(t.verifyUrl,(s,n)=>{if(s){S("device_browser_opened",{stelle:"tool"});return}S("device_browser_failed",{reason:n??"unknown",stelle:"tool"}),process.stderr.write(`
26
26
  cachly: could not open a browser (${n??"unknown"}).
27
27
  cachly: open this yourself to finish signing in:
28
28
  cachly: ${t.verifyUrl}
29
29
  cachly: code ${t.userCode}
30
30
 
31
- `)}),mo(t),["\u{1F9E0} **cachly AI Brain \u2014 the user must sign in once.**","","**Show the following link and code to the user verbatim \u2014 they cannot","continue without them.**","",`\u{1F449} **${t.verifyUrl}**`,"",`Code: **${t.userCode}**`,"","A browser may have opened automatically with the code pre-filled. If it","did not, the link above is the whole step.","","Once signed in, the Brain activates on its own \u2014 no further action, no","restart. The next request arrives brain-powered.","",`\u2728 ${ge.length} MCP tools \xB7 GDPR \xB7 EU servers \xB7 free tier, no credit card`].join(`
31
+ `)}),go(t),["\u{1F9E0} **cachly AI Brain \u2014 the user must sign in once.**","","**Show the following link and code to the user verbatim \u2014 they cannot","continue without them.**","",`\u{1F449} **${t.verifyUrl}**`,"",`Code: **${t.userCode}**`,"","A browser may have opened automatically with the code pre-filled. If it","did not, the link above is the whole step.","","Once signed in, the Brain activates on its own \u2014 no further action, no","restart. The next request arrives brain-powered.","",`\u2728 ${ge.length} MCP tools \xB7 GDPR \xB7 EU servers \xB7 free tier, no credit card`].join(`
32
32
  `)):["\u{1F9E0} **cachly AI Brain \u2014 Setup required**","","Run the setup wizard once in your terminal:"," ```"," npx @cachly-dev/mcp-server@latest autopilot"," ```","",`Or get your API key at: ${R("/setup-ai","ambient-signin")}`,"","\u2728 Free tier includes: 1 Brain instance, persistent memory, semantic search."].join(`
33
- `)}async function ps(e){if(!e)return!0;if(In(e))return!1;try{return await Rn(await H(e),"sitzungsstart")}catch{return!0}}async function J(e,t){if(!y&&await Ee(oo))return J(e,t);if(!y){if(ss(e),G){const i=await et(G);return i==="done"?J(e,t):i==="expired"?(S("device_flow_failed",{reason:"timeout"}),G=null,"\u231B **Authentication timed out.** Please call any tool again to restart the sign-in flow."):["\u23F3 **Signing you in\u2026**","",`Finish in your browser: **${G.verifyUrl}**`,`Code: **${G.userCode}**`,"","This completes automatically once you sign in \u2014 no need to come back here."].join(`
34
- `)}return Sn({schluessel:y,konfigurierteInstanz:N,aufrufInstanz:t.instance_id,werkzeugName:e,holeSofortTest:async()=>{W("sofort-test: Anfang");const i=await $n({apiUrl:x,version:D,fristMs:no}),p=i.art==="angelegt"?i.test:i.art==="vorhanden"&&i.instanzId?{apiKey:i.apiKey,instanzId:i.instanzId}:null;return W(`sofort-test: ${p?"Brain angelegt":"kein Test"}`),p&&Ne(p.instanzId,re(),Te()),p},ablagen:{setzeSchluessel:i=>{y=i},setEmbedJwt:le,saveApiKey:i=>X(i),persistApiKeyToConfig:ue,merkeInstanz:i=>{N=i,Q=0},persistInstanceIdToConfig:pe},meldeEreignis:S,werkzeug:()=>J(e,t),anmelden:()=>us(e),neuesBrain:Ce})}if(!t.instance_id){const i=await Xe();i&&(t={...t,instance_id:i})}const s=await cs(e,t.instance_id);let n="";if(s!==null){if("sperre"in s)return S("premium_gate_hit",{tool:e,instance_id:t.instance_id??""}),s.sperre;n=s.kostprobe,S("premium_taste_used",{tool:e,instance_id:t.instance_id??""})}typeof t.instance_id=="string"&&t.instance_id&&ls(t.instance_id,e),W(`werkzeug ${e}: Zugang und Tarif geklaert`);const o=await jo(e,t,H,P);if(W(`werkzeug ${e}: Brain-Werkzeug fertig`),o!==null){typeof t.instance_id=="string"&&t.instance_id&&ds(t.instance_id,e,String(o??"")),!_e&&y&&(_e=!0,yt("first_call_success")||(bt("first_call_success"),S("first_call_success",{tool:e,instance_id:t.instance_id??N??""})));const i=t.instance_id??N??"",p=y?{api_key:y,instance_id:i}:{instance_id:i};if(e==="recall_best_solution")S("recall_best_solution",p);else if(e==="learn_from_attempts")S("learn_from_attempts",p);else if(e==="session_start"){S("session_start",p,{born_at:void 0,recalls_total:void 0,starter_seeded:!1});const h=typeof o=="object"&&o!==null&&"content"in o?JSON.stringify(o):String(o??""),E=h.includes("Welcome! Your AI Brain is live.");if(!Tn(i)){if(!E&&h.length>100)S("recall_best_solution",p);else if(E&&t.workspace_path&&await ps(i))try{const j=await je("brain_from_git",{instance_id:i,repo_path:t.workspace_path,limit:50},H,P);if(j!==null){S("brain_from_git",{...p,...we??{}}),S("recall_best_solution",p);let C="";if((we?.total??0)===0)try{const L=await Oe("brain_seed_starter",{instance_id:i},H,P);L&&(S("brain_seed_starter",{...p,auto:!0},{seeded_count:16,auto:!0}),C=`
33
+ `)}async function ms(e){if(!e)return!0;if(Rn(e))return!1;try{return await jn(await H(e),"sitzungsstart")}catch{return!0}}async function J(e,t){if(!y&&await Ee(no))return J(e,t);if(!y){if(is(e),G){const i=await et(G);return i==="done"?J(e,t):i==="expired"?(S("device_flow_failed",{reason:"timeout"}),G=null,"\u231B **Authentication timed out.** Please call any tool again to restart the sign-in flow."):["\u23F3 **Signing you in\u2026**","",`Finish in your browser: **${G.verifyUrl}**`,`Code: **${G.userCode}**`,"","This completes automatically once you sign in \u2014 no need to come back here."].join(`
34
+ `)}return An({schluessel:y,konfigurierteInstanz:N,aufrufInstanz:t.instance_id,werkzeugName:e,holeSofortTest:async()=>{F("sofort-test: Anfang");const i=await kn({apiUrl:x,version:D,fristMs:so}),p=i.art==="angelegt"?i.test:i.art==="vorhanden"&&i.instanzId?{apiKey:i.apiKey,instanzId:i.instanzId}:null;return F(`sofort-test: ${p?"Brain angelegt":"kein Test"}`),p&&Ne(p.instanzId,re(),Te()),p},ablagen:{setzeSchluessel:i=>{y=i},setEmbedJwt:le,saveApiKey:i=>X(i),persistApiKeyToConfig:ue,merkeInstanz:i=>{N=i,Q=0},persistInstanceIdToConfig:pe},meldeEreignis:S,werkzeug:()=>J(e,t),anmelden:()=>ps(e),neuesBrain:Ce})}if(!t.instance_id){const i=await Xe();i&&(t={...t,instance_id:i})}const s=await ls(e,t.instance_id);let n="";if(s!==null){if("sperre"in s)return S("premium_gate_hit",{tool:e,instance_id:t.instance_id??""}),s.sperre;n=s.kostprobe,S("premium_taste_used",{tool:e,instance_id:t.instance_id??""})}typeof t.instance_id=="string"&&t.instance_id&&ds(t.instance_id,e),F(`werkzeug ${e}: Zugang und Tarif geklaert`);const o=await Bo(e,t,H,P);if(F(`werkzeug ${e}: Brain-Werkzeug fertig`),o!==null){typeof t.instance_id=="string"&&t.instance_id&&us(t.instance_id,e,String(o??"")),!_e&&y&&(_e=!0,yt("first_call_success")||(bt("first_call_success"),S("first_call_success",{tool:e,instance_id:t.instance_id??N??""})));const i=t.instance_id??N??"",p=y?{api_key:y,instance_id:i}:{instance_id:i};if(e==="recall_best_solution")S("recall_best_solution",p);else if(e==="learn_from_attempts")S("learn_from_attempts",p);else if(e==="session_start"){S("session_start",p,{born_at:void 0,recalls_total:void 0,starter_seeded:!1});const h=typeof o=="object"&&o!==null&&"content"in o?JSON.stringify(o):String(o??""),T=h.includes("Welcome! Your AI Brain is live.");if(!En(i)){if(!T&&h.length>100)S("recall_best_solution",p);else if(T&&t.workspace_path&&await ms(i))try{const j=await je("brain_from_git",{instance_id:i,repo_path:t.workspace_path,limit:50},H,P);if(j!==null){S("brain_from_git",{...p,...we??{}}),S("recall_best_solution",p);let C="";if((we?.total??0)===0)try{const L=await Oe("brain_seed_starter",{instance_id:i},H,P);L&&(S("brain_seed_starter",{...p,auto:!0},{seeded_count:16,auto:!0}),C=`
35
35
  ---
36
- `+String(L))}catch{}const T=String(j),$=we?.total??0,k=$>0?`
37
- \u2705 **Brain bootstrapped from git \u2014 ${$} lesson${$===1?"":"s"} loaded.** Your AI already knows your history.`:"";if(T||C||k)return String(o)+k+`
36
+ `+String(L))}catch{}const E=String(j),$=we?.total??0,k=$>0?`
37
+ \u2705 **Brain bootstrapped from git \u2014 ${$} lesson${$===1?"":"s"} loaded.** Your AI already knows your history.`:"";if(E||C||k)return String(o)+k+`
38
38
  ---
39
- `+T+C}}catch(j){return S("brain_from_git_failed",{...p,reason:j instanceof Error?j.message.slice(0,120):"unknown"}),String(o)+`
39
+ `+E+C}}catch(j){return S("brain_from_git_failed",{...p,reason:j instanceof Error?j.message.slice(0,120):"unknown"}),String(o)+`
40
40
 
41
41
  > \u26A0\uFE0F **Auto-bootstrap from git history failed** \u2014 your Brain is live but starts empty.
42
- > Run \`brain_from_git(instance_id="`+i+'", repo_path="'+String(t.workspace_path)+'")` manually to seed it.\n> Or try `brain_seed_starter` to load 16 universal engineering lessons instantly.'}}}else if(e==="session_end")S("session_end",p);else if(e==="smart_recall"){const h=typeof o=="object"&&o!==null&&"content"in o?JSON.stringify(o):String(o??""),E=h.length>50&&!h.includes("No lessons found")&&!h.includes("no lessons")&&!h.includes("No matches found");if(S("smart_recall",p,{hit:E,topic:String(t.query??"").slice(0,80)}),E&&S("recall_best_solution",p),ae&&typeof o=="string")return`> \u26A0\uFE0F **Brain auth degraded** \u2014 ${ae.split(`
42
+ > Run \`brain_from_git(instance_id="`+i+'", repo_path="'+String(t.workspace_path)+'")` manually to seed it.\n> Or try `brain_seed_starter` to load 16 universal engineering lessons instantly.'}}}else if(e==="session_end")S("session_end",p);else if(e==="smart_recall"){const h=typeof o=="object"&&o!==null&&"content"in o?JSON.stringify(o):String(o??""),T=h.length>50&&!h.includes("No lessons found")&&!h.includes("no lessons")&&!h.includes("No matches found");if(S("smart_recall",p,{hit:T,topic:String(t.query??"").slice(0,80)}),T&&S("recall_best_solution",p),ae&&typeof o=="string")return`> \u26A0\uFE0F **Brain auth degraded** \u2014 ${ae.split(`
43
43
  `)[0]}
44
44
 
45
- ${o}`}return o}const a=await Bo(e,t,H,P);if(a!==null)return!_e&&y&&(_e=!0,yt("first_call_success")||(bt("first_call_success"),S("first_call_success",{tool:e,instance_id:t.instance_id??N??""}))),a;const r=await Lo(e,t,H,P);if(r!==null)return r;const c=await No(e,t,H,P);if(c!==null)return c;const u=i=>n?i+n:i,g=await Oo(e,t,H,P);if(g!==null)return u(g);const d=await Po(e,t,H,P);if(d!==null)return d;const m=await Ho(e,t,H,P);if(m!==null)return u(m);const v=await Mo(e,t,H,P);if(v!==null){if(e==="brain_predict"){const i=t.instance_id??N??"";S("brain_predict",y?{api_key:y,instance_id:i}:{instance_id:i})}return u(v)}const w=await Oe(e,t,H,P);if(w!==null)return w;const b=await Zn(e,t,H,P);if(b!==null)return b;const l=await je(e,t,H,P);if(l!==null){const i=t.instance_id??N??"",p=y?{api_key:y,instance_id:i}:{instance_id:i};if(e==="brain_from_git"){const h=we;S("brain_from_git",{...p,...h??{}},h?{fixes:h.fixes,features:h.features,refactors:h.refactors,total:h.total}:void 0)}else e==="brain_predict_failures"&&S("brain_predict_failures",p);return l}switch(e){case"get_api_status":{let i="unknown";try{const j=await fetch(`${x}/health`,{signal:AbortSignal.timeout(8e3)});if(j.ok){const A=await j.json();i=`${A.status??"ok"} (db: ${A.db??"?"})`}else i=`HTTP ${j.status}`}catch(j){i=`unreachable: ${j.message}`}if(!y)return["\u{1F4E1} **cachly API Status**","",` \u{1F310} API: ${x}`,` \u{1F493} Health: ${i}`," \u{1F511} Auth: \u274C CACHLY_JWT not set","",`\u{1F4A1} Get your API token at ${R("/instances","api-status")} \u2192 Settings \u2192 API Token`].join(`
46
- `);let p="\u274C invalid JWT format";try{const j=y.split(".");if(j.length===3){const A=JSON.parse(Buffer.from(j[1],"base64url").toString("utf-8")),C=A.sub??"(unknown)",T=A.iss??"(unknown)",$=T.includes("keycloak")?"Keycloak":"OIDC",k=A.exp?new Date(A.exp*1e3):null,L=k?k<new Date:!1;p=["\u2705 JWT decoded",` Sub (user ID): ${C}`,` Provider: ${$}`,` Issuer: ${T}`,` Expires: ${k?k.toISOString():"never"} ${L?"\u26A0\uFE0F EXPIRED \u2013 get a new token!":"\u2705"}`].join(`
45
+ ${o}`}return o}const a=await Lo(e,t,H,P);if(a!==null)return!_e&&y&&(_e=!0,yt("first_call_success")||(bt("first_call_success"),S("first_call_success",{tool:e,instance_id:t.instance_id??N??""}))),a;const c=await No(e,t,H,P);if(c!==null)return c;const r=await Oo(e,t,H,P);if(r!==null)return r;const d=i=>n?i+n:i,g=await Po(e,t,H,P);if(g!==null)return d(g);const u=await Ho(e,t,H,P);if(u!==null)return u;const m=await Mo(e,t,H,P);if(m!==null)return d(m);const v=await Do(e,t,H,P);if(v!==null){if(e==="brain_predict"){const i=t.instance_id??N??"";S("brain_predict",y?{api_key:y,instance_id:i}:{instance_id:i})}return d(v)}const w=await Oe(e,t,H,P);if(w!==null)return w;const b=await Qn(e,t,H,P);if(b!==null)return b;const l=await je(e,t,H,P);if(l!==null){const i=t.instance_id??N??"",p=y?{api_key:y,instance_id:i}:{instance_id:i};if(e==="brain_from_git"){const h=we;S("brain_from_git",{...p,...h??{}},h?{fixes:h.fixes,features:h.features,refactors:h.refactors,total:h.total}:void 0)}else e==="brain_predict_failures"&&S("brain_predict_failures",p);return l}switch(e){case"get_api_status":{let i="unknown";try{const j=await fetch(`${x}/health`,{signal:AbortSignal.timeout(8e3)});if(j.ok){const A=await j.json();i=`${A.status??"ok"} (db: ${A.db??"?"})`}else i=`HTTP ${j.status}`}catch(j){i=`unreachable: ${j.message}`}if(!y)return["\u{1F4E1} **cachly API Status**","",` \u{1F310} API: ${x}`,` \u{1F493} Health: ${i}`," \u{1F511} Auth: \u274C CACHLY_JWT not set","",`\u{1F4A1} Get your API token at ${R("/instances","api-status")} \u2192 Settings \u2192 API Token`].join(`
46
+ `);let p="\u274C invalid JWT format";try{const j=y.split(".");if(j.length===3){const A=JSON.parse(Buffer.from(j[1],"base64url").toString("utf-8")),C=A.sub??"(unknown)",E=A.iss??"(unknown)",$=E.includes("keycloak")?"Keycloak":"OIDC",k=A.exp?new Date(A.exp*1e3):null,L=k?k<new Date:!1;p=["\u2705 JWT decoded",` Sub (user ID): ${C}`,` Provider: ${$}`,` Issuer: ${E}`,` Expires: ${k?k.toISOString():"never"} ${L?"\u26A0\uFE0F EXPIRED \u2013 get a new token!":"\u2705"}`].join(`
47
47
  `)}}catch{p="\u274C JWT decode failed \u2013 check CACHLY_JWT format"}let h="";try{const A=(await P("/api/v1/instances")).data??[];if(A.length===0)h=`
48
48
 
49
49
  \u{1F9E0} **Brain Instances:** none \u2014 create one at ${R("/instances","api-status")}`;else{const C=[`
50
50
 
51
- \u{1F9E0} **Brain Instances:**`];for(const T of A){const $=T.status==="running"?"\u{1F7E2}":T.status==="provisioning"?"\u{1F7E1}":"\u{1F534}",k=T.id===N?" \u2190 active":"";if(C.push(` ${$} **${T.name}** (\`${T.id}\`) \xB7 ${T.status}${k}`),T.status==="running"&&T.host){const L=se.get(T.id);if(L)try{await L.ping(),C.push(" \u{1F493} Redis: connected")}catch{C.push(" \u26A0\uFE0F Redis: pooled but ping failed \u2014 will reconnect on next use")}else C.push(" \u{1F4A4} Redis: not connected yet (connects on first tool use)")}else T.status==="provisioning"?C.push(" \u23F3 Still provisioning \u2014 check back in ~30 s"):T.status!=="running"&&C.push(` \u274C Not reachable (status: ${T.status})`)}h=C.join(`
51
+ \u{1F9E0} **Brain Instances:**`];for(const E of A){const $=E.status==="running"?"\u{1F7E2}":E.status==="provisioning"?"\u{1F7E1}":"\u{1F534}",k=E.id===N?" \u2190 active":"";if(C.push(` ${$} **${E.name}** (\`${E.id}\`) \xB7 ${E.status}${k}`),E.status==="running"&&E.host){const L=se.get(E.id);if(L)try{await L.ping(),C.push(" \u{1F493} Redis: connected")}catch{C.push(" \u26A0\uFE0F Redis: pooled but ping failed \u2014 will reconnect on next use")}else C.push(" \u{1F4A4} Redis: not connected yet (connects on first tool use)")}else E.status==="provisioning"?C.push(" \u23F3 Still provisioning \u2014 check back in ~30 s"):E.status!=="running"&&C.push(` \u274C Not reachable (status: ${E.status})`)}h=C.join(`
52
52
  `)}}catch(j){h=`
53
53
 
54
- \u{1F9E0} **Brain Instances:** could not fetch \u2014 ${j.message}`}await Re();const E=Se(y),O=E.state==="long_lived"?"\u{1F6E1}\uFE0F Self-healing: \u2705 long-lived API key (won't expire silently)":E.state==="healthy"?`\u{1F6E1}\uFE0F Self-healing: \u2705 token valid${E.expiresInMs?` (${Math.round(E.expiresInMs/36e5)}h left)`:""}`:E.state==="near_expiry"?"\u{1F6E1}\uFE0F Self-healing: \u267B\uFE0F token near expiry \u2014 auto-refresh attempted":`\u{1F6E1}\uFE0F Self-healing: \u26A0\uFE0F ${E.message.split(`
54
+ \u{1F9E0} **Brain Instances:** could not fetch \u2014 ${j.message}`}await Re();const T=Se(y),O=T.state==="long_lived"?"\u{1F6E1}\uFE0F Self-healing: \u2705 long-lived API key (won't expire silently)":T.state==="healthy"?`\u{1F6E1}\uFE0F Self-healing: \u2705 token valid${T.expiresInMs?` (${Math.round(T.expiresInMs/36e5)}h left)`:""}`:T.state==="near_expiry"?"\u{1F6E1}\uFE0F Self-healing: \u267B\uFE0F token near expiry \u2014 auto-refresh attempted":`\u{1F6E1}\uFE0F Self-healing: \u26A0\uFE0F ${T.message.split(`
55
55
  `)[0]}`;return["\u{1F4E1} **cachly API Status**","",` \u{1F310} API: ${x}`,` \u{1F493} Health: ${i}`,` ${O}`,"","\u{1F511} **Auth:**",p,h].join(`
56
- `)}default:throw new kt(`Unknown tool: ${e}`)}}class kt extends Error{}const St=`This project has a Cachly AI Brain \u2014 persistent, cross-session memory of past fixes, decisions, and gotchas for THIS codebase. Use it proactively; it makes you faster and stops you repeating known mistakes.
56
+ `)}default:throw new St(`Unknown tool: ${e}`)}}class St extends Error{}const At=`This project has a Cachly AI Brain \u2014 persistent, cross-session memory of past fixes, decisions, and gotchas for THIS codebase. Use it proactively; it makes you faster and stops you repeating known mistakes.
57
57
 
58
58
  - At the START of every task, before reading files or editing: call smart_recall with one line about the task. If it returns lessons, apply them before researching from scratch.
59
59
  - WHEN debugging an error: call causal_trace with the exact error first \u2014 a known fix may already exist.
60
60
  - AFTER a fix, deploy, or discovery: call learn_from_attempts so the knowledge persists.
61
61
  - BEFORE a risky op (deploy, migration, dependency bump): call brain_predict.
62
62
 
63
- The Brain instance id comes from the CACHLY_BRAIN_INSTANCE_ID environment variable.`,At={tools:{},resources:{},prompts:{}},Ct=async()=>{const{katalog:e,unbekannteKernnamen:t}=Un(ge);return t.length>0&&console.error(`cachly: ${t.length} Kernwerkzeug(e) gibt es gar nicht: ${t.join(", ")}`),{tools:e}};async function Tt(){return{resources:[]}}async function Et(){return{resourceTemplates:[]}}async function It(){return{prompts:[]}}function ms(e){e.setRequestHandler(Ve,Ct),e.setRequestHandler(Ye,Bt),e.setRequestHandler(Ge,Tt),e.setRequestHandler(qe,Et),e.setRequestHandler(Ke,It)}function gs(){const e=new We({name:"cachly-mcp",version:D},{capabilities:At,instructions:St});return ms(e),Rt(e),e}function Rt(e){const t=e.oninitialized;e.oninitialized=()=>{let s;try{s=e.getClientVersion(),Ht(s?.name,s?.version)}catch{}wt||(wt=!0,S("mcp_verbunden",{client:String(s?.name??"unbekannt").slice(0,60),client_version:String(s?.version??"").slice(0,30)})),t?.()}}const V=new We({name:"cachly-mcp",version:D},{capabilities:At,instructions:St});Rt(V),V.setRequestHandler(Ve,Ct),V.setRequestHandler(Ge,Tt),V.setRequestHandler(qe,Et),V.setRequestHandler(Ke,It);let Pe=null,fe=!1,ee=null,jt=0;async function fs(e){if(!fe){if(ee){await ee;return}ee=(async()=>{fe=!0,Pe=e;try{await J("session_start",{instance_id:e,focus:"auto (MCP session)",workspace_path:process.cwd()})}catch{}finally{ee=null}})(),await ee,process.env.CACHLY_AUTO_INDEX!=="false"&&(async()=>{const t=await H(e),s=await t.get(`cachly:index:last_indexed:${e}`),n=1440*60*1e3;(!s||Date.now()-parseInt(s,10)>n)&&(await t.set(`cachly:index:last_indexed:${e}`,String(Date.now()),"EX",9e4),await J("index_project",{instance_id:e,dir:process.cwd(),max_files:150,ttl:86400*7,namespace:"cachly:sem:code",hintergrund:!0}))})().catch(()=>{})}}async function He(){if(!(!fe||!Pe)){fe=!1;try{await J("session_end",{instance_id:Pe,summary:`Auto-ended after ${jt} tool call(s). Session was started automatically.`,files_changed:[],lessons_learned:0})}catch{}}}const Bt=async e=>{let{name:t,arguments:s}=e.params;if(t===ht){const o=s??{},a=typeof o.tool=="string"?o.tool:"";if(!a)return{content:[{type:"text",text:'cachly_tool braucht das Feld "tool" \u2014 den Namen des Werkzeugs.'}],isError:!0};const r=ge.find(c=>c.name===a);if(!r)return{content:[{type:"text",text:`Kein Werkzeug namens "${a}". Die Liste steht in der Beschreibung von ${ht}.`}],isError:!0};if(o.describe===!0)return{content:[{type:"text",text:JSON.stringify({name:r.name,description:r.description,inputSchema:r.inputSchema},null,2)}]};t=a,s=o.arguments??{}}const n=new Set(["session_start","session_start_summary","session_end","auto_learn_session"]);if(!n.has(t)&&!fe&&!ee){const o=xe(s?.instance_id)||N||xe(process.env.CACHLY_BRAIN_INSTANCE_ID);o&&await fs(o).catch(()=>{})}else ee&&await ee.catch(()=>{});n.has(t)||jt++;try{Mn(),W(`werkzeug ${t}: Anfang`);const o=await J(t,s??{});return W(`werkzeug ${t}: Antwort fertig`),{content:[{type:"text",text:sn(t,o)+jn()+Pn(t)}]}}catch(o){if(o instanceof kt)return{content:[{type:"text",text:o.message}],isError:!0};if(o instanceof oe)throw o;const a=o.message??String(o);throw Je("cachly","tool_error",{tool:t,error:a}).catch(()=>{}),new oe(ie.InternalError,a)}};V.setRequestHandler(Ye,Bt),process.on("SIGTERM",async()=>{await He().catch(()=>{});for(const[,e]of se)await e.quit().catch(()=>{});process.exit(0)}),process.on("SIGINT",async()=>{await He().catch(()=>{});for(const[,e]of se)await e.quit().catch(()=>{});process.exit(0)}),process.on("unhandledRejection",e=>{const t=e instanceof Error?e.message:String(e);process.stderr.write(`[cachly-mcp] unhandledRejection: ${t}
63
+ The Brain instance id comes from the CACHLY_BRAIN_INSTANCE_ID environment variable.`,Ct={tools:{},resources:{},prompts:{}},Tt=async()=>{const{katalog:e,unbekannteKernnamen:t}=zn(ge);return t.length>0&&console.error(`cachly: ${t.length} Kernwerkzeug(e) gibt es gar nicht: ${t.join(", ")}`),{tools:e}};async function Et(){return{resources:[]}}async function It(){return{resourceTemplates:[]}}async function Rt(){return{prompts:[]}}function gs(e){e.setRequestHandler(Ve,Tt),e.setRequestHandler(Ye,Lt),e.setRequestHandler(Ge,Et),e.setRequestHandler(qe,It),e.setRequestHandler(Ke,Rt)}function fs(){const e=new Fe({name:"cachly-mcp",version:D},{capabilities:Ct,instructions:At});return gs(e),jt(e),e}function jt(e){const t=e.oninitialized;e.oninitialized=()=>{let s;try{s=e.getClientVersion(),Mt(s?.name,s?.version)}catch{}xt||(xt=!0,S("mcp_verbunden",{client:String(s?.name??"unbekannt").slice(0,60),client_version:String(s?.version??"").slice(0,30)})),t?.()}}const V=new Fe({name:"cachly-mcp",version:D},{capabilities:Ct,instructions:At});jt(V),V.setRequestHandler(Ve,Tt),V.setRequestHandler(Ge,Et),V.setRequestHandler(qe,It),V.setRequestHandler(Ke,Rt);let Pe=null,fe=!1,ee=null,Bt=0;async function hs(e){if(!fe){if(ee){await ee;return}ee=(async()=>{fe=!0,Pe=e;try{await J("session_start",{instance_id:e,focus:"auto (MCP session)",workspace_path:process.cwd()})}catch{}finally{ee=null}})(),await ee,process.env.CACHLY_AUTO_INDEX!=="false"&&(async()=>{const t=await H(e),s=await t.get(`cachly:index:last_indexed:${e}`),n=1440*60*1e3;(!s||Date.now()-parseInt(s,10)>n)&&(await t.set(`cachly:index:last_indexed:${e}`,String(Date.now()),"EX",9e4),await J("index_project",{instance_id:e,dir:process.cwd(),max_files:150,ttl:86400*7,namespace:"cachly:sem:code",hintergrund:!0}))})().catch(()=>{})}}async function He(){if(!(!fe||!Pe)){fe=!1;try{await J("session_end",{instance_id:Pe,summary:`Auto-ended after ${Bt} tool call(s). Session was started automatically.`,files_changed:[],lessons_learned:0})}catch{}}}const Lt=async e=>{let{name:t,arguments:s}=e.params;if(t===ht){const o=s??{},a=typeof o.tool=="string"?o.tool:"";if(!a)return{content:[{type:"text",text:'cachly_tool braucht das Feld "tool" \u2014 den Namen des Werkzeugs.'}],isError:!0};const c=ge.find(r=>r.name===a);if(!c)return{content:[{type:"text",text:`Kein Werkzeug namens "${a}". Die Liste steht in der Beschreibung von ${ht}.`}],isError:!0};if(o.describe===!0)return{content:[{type:"text",text:JSON.stringify({name:c.name,description:c.description,inputSchema:c.inputSchema},null,2)}]};t=a,s=o.arguments??{}}const n=new Set(["session_start","session_start_summary","session_end","auto_learn_session"]);if(!n.has(t)&&!fe&&!ee){const o=xe(s?.instance_id)||N||xe(process.env.CACHLY_BRAIN_INSTANCE_ID);o&&await hs(o).catch(()=>{})}else ee&&await ee.catch(()=>{});n.has(t)||Bt++;try{Dn(),F(`werkzeug ${t}: Anfang`);const o=await J(t,s??{});return F(`werkzeug ${t}: Antwort fertig`),{content:[{type:"text",text:rn(t,o)+Bn()+Hn(t)}]}}catch(o){if(o instanceof St)return{content:[{type:"text",text:o.message}],isError:!0};if(o instanceof oe)throw o;const a=o.message??String(o);throw Je("cachly","tool_error",{tool:t,error:a}).catch(()=>{}),new oe(ie.InternalError,a)}};V.setRequestHandler(Ye,Lt),process.on("SIGTERM",async()=>{await He().catch(()=>{});for(const[,e]of se)await e.quit().catch(()=>{});process.exit(0)}),process.on("SIGINT",async()=>{await He().catch(()=>{});for(const[,e]of se)await e.quit().catch(()=>{});process.exit(0)}),process.on("unhandledRejection",e=>{const t=e instanceof Error?e.message:String(e);process.stderr.write(`[cachly-mcp] unhandledRejection: ${t}
64
64
  `)}),process.on("uncaughtException",e=>{process.stderr.write(`[cachly-mcp] uncaughtException: ${e?.stack??String(e)}
65
- `)}),process.stdout.on("error",()=>{}),process.stdin.on("error",()=>{});function hs(e,t){const s=Object.entries(t).map(([n,o])=>`${n}=${o}`);return e==="codex"?{befehl:`codex mcp add cachly ${s.map(n=>`--env ${n}`).join(" ")} -- npx -y @cachly-dev/mcp-server@latest`,wo:"~/.codex/config.toml"}:e==="gemini"?{befehl:`gemini mcp add -s project ${s.map(n=>`-e ${n}`).join(" ")} cachly npx -- -y @cachly-dev/mcp-server@latest`,wo:".gemini/settings.json"}:null}const Lt="https://api.cachly.dev";function Z(e,t,s={}){const n={CACHLY_BRAIN_INSTANCE_ID:t};return s.includeApiKey&&(n.CACHLY_JWT=e),x&&x!==Lt&&(n.CACHLY_API_URL=x),n}function ys(e,t,s){return s==="continue"?JSON.stringify({experimental:{modelContextProtocolServers:[{transport:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"]},env:Z(e,t)}]}},null,2):s==="zed"?JSON.stringify({context_servers:{cachly:{command:{path:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(e,t)},settings:{}}}},null,2):Nt(s)?JSON.stringify({servers:{cachly:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(e,t)}}},null,2):JSON.stringify({mcpServers:{cachly:{command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(e,t)}}},null,2)}function Nt(e){return me[e]===".vscode/mcp.json"}function he(e,t){pn(e)||X(e,t)}async function Ot(e,t,s,n,o,a={}){const r={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(t,s)};if(!o.existsSync(e))return ys(t,s,n);let c={};try{c=JSON.parse(await o.readFile(e,"utf-8"))}catch{try{const{rename:m}=await import("node:fs/promises");await m(e,e+".bak"),process.stderr.write(`\u26A0\uFE0F ${e} was not valid JSON \u2014 backed up to ${e}.bak
66
- `)}catch{}}if(n==="continue"){const m=c.experimental??{},v=m.modelContextProtocolServers??[];let w;for(const l of v){const i=l.env??{};if(i.CACHLY_JWT){w=i.CACHLY_JWT;break}}w&&he(w,a);const b=v.filter(l=>{const i=l.env??{};return!i.CACHLY_JWT&&!i.CACHLY_BRAIN_INSTANCE_ID});return b.push({transport:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"]},env:r.env}),c.experimental={...m,modelContextProtocolServers:b},JSON.stringify(c,null,2)}if(n==="zed"){const m=c.context_servers??{},w=m.cachly?.command?.env?.CACHLY_JWT;return w&&he(w,a),m.cachly={command:{path:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:r.env},settings:{}},c.context_servers=m,JSON.stringify(c,null,2)}if(Nt(n)){const m=c.mcpServers??void 0,w=m?.cachly?.env?.CACHLY_JWT;w&&he(w,a),m&&"cachly"in m&&(delete m.cachly,Object.keys(m).length===0&&delete c.mcpServers);const b=c.servers??{},l=b.cachly,i=l?.env?.CACHLY_JWT;return i&&he(i,a),b.cachly=l?.envFile?{type:"stdio",...r,envFile:l.envFile}:{type:"stdio",...r},c.servers=b,JSON.stringify(c,null,2)}const u=c.mcpServers??{},d=u.cachly?.env?.CACHLY_JWT;return d&&he(d,a),u.cachly=r,c.mcpServers=u,JSON.stringify(c,null,2)}function bs(e){return`${it}
65
+ `)}),process.stdout.on("error",()=>{}),process.stdin.on("error",()=>{});function ys(e,t){const s=Object.entries(t).map(([n,o])=>`${n}=${o}`);return e==="codex"?{befehl:`codex mcp add cachly ${s.map(n=>`--env ${n}`).join(" ")} -- npx -y @cachly-dev/mcp-server@latest`,wo:"~/.codex/config.toml"}:e==="gemini"?{befehl:`gemini mcp add -s project ${s.map(n=>`-e ${n}`).join(" ")} cachly npx -- -y @cachly-dev/mcp-server@latest`,wo:".gemini/settings.json"}:null}const Nt="https://api.cachly.dev";function Z(e,t,s={}){const n={CACHLY_BRAIN_INSTANCE_ID:t};return s.includeApiKey&&(n.CACHLY_JWT=e),x&&x!==Nt&&(n.CACHLY_API_URL=x),n}function bs(e,t,s){return s==="continue"?JSON.stringify({experimental:{modelContextProtocolServers:[{transport:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"]},env:Z(e,t)}]}},null,2):s==="zed"?JSON.stringify({context_servers:{cachly:{command:{path:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(e,t)},settings:{}}}},null,2):Ot(s)?JSON.stringify({servers:{cachly:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(e,t)}}},null,2):JSON.stringify({mcpServers:{cachly:{command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(e,t)}}},null,2)}function Ot(e){return me[e]===".vscode/mcp.json"}function he(e,t){mn(e)||X(e,t)}async function Pt(e,t,s,n,o,a={}){const c={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(t,s)};if(!o.existsSync(e))return bs(t,s,n);let r={};try{r=JSON.parse(await o.readFile(e,"utf-8"))}catch{try{const{rename:m}=await import("node:fs/promises");await m(e,e+".bak"),process.stderr.write(`\u26A0\uFE0F ${e} was not valid JSON \u2014 backed up to ${e}.bak
66
+ `)}catch{}}if(n==="continue"){const m=r.experimental??{},v=m.modelContextProtocolServers??[];let w;for(const l of v){const i=l.env??{};if(i.CACHLY_JWT){w=i.CACHLY_JWT;break}}w&&he(w,a);const b=v.filter(l=>{const i=l.env??{};return!i.CACHLY_JWT&&!i.CACHLY_BRAIN_INSTANCE_ID});return b.push({transport:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"]},env:c.env}),r.experimental={...m,modelContextProtocolServers:b},JSON.stringify(r,null,2)}if(n==="zed"){const m=r.context_servers??{},w=m.cachly?.command?.env?.CACHLY_JWT;return w&&he(w,a),m.cachly={command:{path:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:c.env},settings:{}},r.context_servers=m,JSON.stringify(r,null,2)}if(Ot(n)){const m=r.mcpServers??void 0,w=m?.cachly?.env?.CACHLY_JWT;w&&he(w,a),m&&"cachly"in m&&(delete m.cachly,Object.keys(m).length===0&&delete r.mcpServers);const b=r.servers??{},l=b.cachly,i=l?.env?.CACHLY_JWT;return i&&he(i,a),b.cachly=l?.envFile?{type:"stdio",...c,envFile:l.envFile}:{type:"stdio",...c},r.servers=b,JSON.stringify(r,null,2)}const d=r.mcpServers??{},u=d.cachly?.env?.CACHLY_JWT;return u&&he(u,a),d.cachly=c,r.mcpServers=d,JSON.stringify(r,null,2)}function vs(e){return`${it}
67
67
  ## Cachly AI Brain \u2014 Always Active
68
68
 
69
69
  The Brain MCP server runs automatically. Instance: \`${e}\`
@@ -118,41 +118,41 @@ Report predicted failure risks to the user before proceeding.
118
118
 
119
119
  ### Half-finished code rule:
120
120
  Never commit code that does not compile. Run \`tsc --noEmit\` / \`go build ./...\` before every commit.
121
- ${rt}`}async function Pt(e,t){const{existsSync:s}=await import("node:fs"),{resolve:n}=await import("node:path"),o=zo.filter(c=>!c.nurMitIdea||s(n(e,".idea"))).map(c=>({path:n(e,...c.pfad),prefix:c.prefix})),a=bs(t),r={};for(const{path:c,prefix:u}of o)r[c]=await Jo(c,a,u);return r}if(process.argv[2]==="digest"){const e=ne(),t=F();(!e||!t)&&(console.log(`
121
+ ${rt}`}async function Ht(e,t){const{existsSync:s}=await import("node:fs"),{resolve:n}=await import("node:path"),o=Jo.filter(r=>!r.nurMitIdea||s(n(e,".idea"))).map(r=>({path:n(e,...r.pfad),prefix:r.prefix})),a=vs(t),c={};for(const{path:r,prefix:d}of o)c[r]=await Wo(r,a,d);return c}if(process.argv[2]==="digest"){const e=ne(),t=W();(!e||!t)&&(console.log(`
122
122
  \u26A0\uFE0F No cachly key or Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot
123
123
  `),process.exit(1)),process.stdout.write(`
124
124
  \u{1F9E0} Fetching your weekly Brain digest...
125
125
 
126
- `);try{const s=await fetch(`${x}/api/v1/instances/${t}/memory`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)});if(!s.ok)throw new Error(`stats HTTP ${s.status}`);const n=await s.json(),o=n.lesson_count??0,a=n.total_recall_count??0,r=Math.round(n.iq_boost_pct??0),c=(n.top_lessons??[]).slice(0,5),u=n.team_authors??[],g=a*1200,d=(g*3e-6).toFixed(2),m=o<10?"Junior Dev \u{1F527}":o<30?"Mid Dev \u26A1":o<60?"Senior Dev \u{1F9E0}":o<100?"Staff Eng \u{1F680}":"Principal Eng \u{1F3C6}",v=new Date,w=new Date(v);w.setDate(v.getDate()-7);const b=h=>h.toLocaleDateString("en-US",{month:"short",day:"numeric"});if(console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log(`\u2502 \x1B[1m\u{1F9E0} Brain Weekly Digest\x1B[0m \x1B[90m${b(w)} \u2013 ${b(v)}\x1B[0m \u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Total lessons : \x1B[33m${String(o).padEnd(8)}\x1B[0m Brain level : \x1B[32m${m.padEnd(18)}\x1B[0m\u2502`),console.log(`\u2502 Total recalls : \x1B[36m${String(a).padEnd(8)}\x1B[0m Quality score: \x1B[32m${String(r).padEnd(3)}%\x1B[0m \u2502`),console.log(`\u2502 Tokens saved : \x1B[32m${(Math.round(g/1e3)+"K").padEnd(8)}\x1B[0m Cost saved : \x1B[32m$${d.padEnd(20)}\x1B[0m\u2502`),u.length>0&&(console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 \x1B[36m\u{1F465} Team contributors:\x1B[0m ${u.slice(0,5).join(", ").slice(0,42).padEnd(42)} \u2502`)),c.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[33m\u{1F525} Most recalled lessons this week:\x1B[0m \u2502");for(const h of c){const E=`${h.topic}: ${h.what_worked}`.slice(0,57);console.log(`\u2502 \x1B[90m\u2022 ${E.padEnd(58)}\x1B[0m\u2502`)}}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log("");const l=c[0],i=[`\u{1F9E0} My AI Brain weekly digest (${b(w)} \u2013 ${b(v)}):`,"",` \u{1F4DA} ${o} lessons learned`,` \u{1F501} ${a} recalls \xB7 ~${Math.round(g/1e3)}K tokens saved`,` \u{1F3AF} Brain Level: ${m}`,l?` \u{1F525} Top lesson: "${l.topic}: ${l.what_worked.slice(0,60)}${l.what_worked.length>60?"\u2026":""}"`:"","","Built with @cachly_dev \u2014 AI that actually remembers \u{1F680}","cachly.dev"].filter(Boolean).join(`
126
+ `);try{const s=await fetch(`${x}/api/v1/instances/${t}/memory`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)});if(!s.ok)throw new Error(`stats HTTP ${s.status}`);const n=await s.json(),o=n.lesson_count??0,a=n.total_recall_count??0,c=Math.round(n.iq_boost_pct??0),r=(n.top_lessons??[]).slice(0,5),d=n.team_authors??[],g=a*1200,u=(g*3e-6).toFixed(2),m=o<10?"Junior Dev \u{1F527}":o<30?"Mid Dev \u26A1":o<60?"Senior Dev \u{1F9E0}":o<100?"Staff Eng \u{1F680}":"Principal Eng \u{1F3C6}",v=new Date,w=new Date(v);w.setDate(v.getDate()-7);const b=h=>h.toLocaleDateString("en-US",{month:"short",day:"numeric"});if(console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log(`\u2502 \x1B[1m\u{1F9E0} Brain Weekly Digest\x1B[0m \x1B[90m${b(w)} \u2013 ${b(v)}\x1B[0m \u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Total lessons : \x1B[33m${String(o).padEnd(8)}\x1B[0m Brain level : \x1B[32m${m.padEnd(18)}\x1B[0m\u2502`),console.log(`\u2502 Total recalls : \x1B[36m${String(a).padEnd(8)}\x1B[0m Quality score: \x1B[32m${String(c).padEnd(3)}%\x1B[0m \u2502`),console.log(`\u2502 Tokens saved : \x1B[32m${(Math.round(g/1e3)+"K").padEnd(8)}\x1B[0m Cost saved : \x1B[32m$${u.padEnd(20)}\x1B[0m\u2502`),d.length>0&&(console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 \x1B[36m\u{1F465} Team contributors:\x1B[0m ${d.slice(0,5).join(", ").slice(0,42).padEnd(42)} \u2502`)),r.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[33m\u{1F525} Most recalled lessons this week:\x1B[0m \u2502");for(const h of r){const T=`${h.topic}: ${h.what_worked}`.slice(0,57);console.log(`\u2502 \x1B[90m\u2022 ${T.padEnd(58)}\x1B[0m\u2502`)}}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log("");const l=r[0],i=[`\u{1F9E0} My AI Brain weekly digest (${b(w)} \u2013 ${b(v)}):`,"",` \u{1F4DA} ${o} lessons learned`,` \u{1F501} ${a} recalls \xB7 ~${Math.round(g/1e3)}K tokens saved`,` \u{1F3AF} Brain Level: ${m}`,l?` \u{1F525} Top lesson: "${l.topic}: ${l.what_worked.slice(0,60)}${l.what_worked.length>60?"\u2026":""}"`:"","","Built with @cachly_dev \u2014 AI that actually remembers \u{1F680}","cachly.dev"].filter(Boolean).join(`
127
127
  `),p="https://twitter.com/intent/tweet?text="+encodeURIComponent(i);console.log("\x1B[1m\u{1F4E3} Share your digest:\x1B[0m"),console.log(""),console.log("\x1B[90m"+"\u2500".repeat(63)+"\x1B[0m");for(const h of i.split(`
128
128
  `))console.log(` ${h}`);console.log("\x1B[90m"+"\u2500".repeat(63)+"\x1B[0m"),console.log(""),console.log(" \x1B[36m\u{1F426} Tweet this:\x1B[0m"),console.log(` \x1B[4m${p.slice(0,90)}...\x1B[0m`),console.log(""),console.log(" \x1B[2m\u{1F4A1} Invite your team: npx @cachly-dev/mcp-server@latest invite\x1B[0m"),console.log(" \x1B[2m Cron: 0 9 * * 1 npx @cachly-dev/mcp-server@latest digest\x1B[0m"),console.log("")}catch(s){console.log(`
129
129
  \u274C Could not fetch digest: ${s.message}
130
- `),process.exit(1)}process.exit(0)}if(process.argv[2]==="export"){const{writeFile:e,mkdir:t}=await import("node:fs/promises"),{resolve:s}=await import("node:path"),n=process.argv.slice(3),o=g=>{const d=n.indexOf(`--${g}`);return d!==-1?n[d+1]:void 0},a=o("format")??"both";a!=="md"&&a!=="jsonl"&&a!=="both"&&(console.log(`
130
+ `),process.exit(1)}process.exit(0)}if(process.argv[2]==="export"){const{writeFile:e,mkdir:t}=await import("node:fs/promises"),{resolve:s}=await import("node:path"),n=process.argv.slice(3),o=g=>{const u=n.indexOf(`--${g}`);return u!==-1?n[u+1]:void 0},a=o("format")??"both";a!=="md"&&a!=="jsonl"&&a!=="both"&&(console.log(`
131
131
  \u274C Unknown --format "${a}" \u2014 use md, jsonl, or both.
132
- `),process.exit(1));const r=s(o("out")??"."),c=y||Be()||"",u=F();(!c||!u)&&(console.log(`
132
+ `),process.exit(1));const c=s(o("out")??"."),r=y||Be()||"",d=W();(!r||!d)&&(console.log(`
133
133
  \u26A0\uFE0F No cachly key or Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot
134
134
  `),process.exit(1)),process.stdout.write(`
135
135
  \u{1F4E4} Exporting your Brain...
136
136
 
137
- `);try{let g=[],d="";const m=await fetch(`${x}/api/v1/instances/${u}/export`,{headers:{Authorization:`Bearer ${c}`},signal:AbortSignal.timeout(12e4)});if(m.ok){const w=await m.json();g=(w.lessons??[]).map(Fn).filter(b=>b!==null),w.complete===!1&&(d=w.note??"the server reported an incomplete read")}else if(m.status===404){const w=await fetch(`${x}/api/v1/instances/${u}/memory`,{headers:{Authorization:`Bearer ${c}`},signal:AbortSignal.timeout(8e3)});if(!w.ok)throw new Error(`memory HTTP ${w.status}`);g=((await w.json()).top_lessons??[]).map(l=>({topic:l.topic,outcome:l.outcome,severity:l.severity,tags:l.tags,whatWorked:l.what_worked,ts:l.ts,author:l.author,recallCount:l.recall_count})),d="this server has no /export endpoint yet, so this is the DASHBOARD SUMMARY: at most 50 lessons, each shortened to 120 characters. Update the server for a full export."}else throw new Error(`export HTTP ${m.status}`);g.length===0&&(console.log(` No lessons in this Brain yet \u2014 nothing to export.
138
- `),process.exit(0)),await t(r,{recursive:!0});const v=[];if(a==="md"||a==="both"){const w=s(r,"lessons.md");await e(w,zn(g),"utf-8"),v.push(`${g.length} lesson${g.length===1?"":"s"} \u2192 ${w}`)}if(a==="jsonl"||a==="both"){const w=s(r,"lessons.jsonl");await e(w,Jn(g),"utf-8"),v.push(`${g.length} lesson${g.length===1?"":"s"} \u2192 ${w}`)}d?(console.log("\u26A0\uFE0F Export INCOMPLETE \u2014 this is not your whole Brain:"),console.log(` ${d}`),console.log("")):console.log("\u2705 Export complete:");for(const w of v)console.log(` ${w}`);console.log("")}catch(g){console.log(`
137
+ `);try{let g=[],u="";const m=await fetch(`${x}/api/v1/instances/${d}/export`,{headers:{Authorization:`Bearer ${r}`},signal:AbortSignal.timeout(12e4)});if(m.ok){const w=await m.json();g=(w.lessons??[]).map(Fn).filter(b=>b!==null),w.complete===!1&&(u=w.note??"the server reported an incomplete read")}else if(m.status===404){const w=await fetch(`${x}/api/v1/instances/${d}/memory`,{headers:{Authorization:`Bearer ${r}`},signal:AbortSignal.timeout(8e3)});if(!w.ok)throw new Error(`memory HTTP ${w.status}`);g=((await w.json()).top_lessons??[]).map(l=>({topic:l.topic,outcome:l.outcome,severity:l.severity,tags:l.tags,whatWorked:l.what_worked,ts:l.ts,author:l.author,recallCount:l.recall_count})),u="this server has no /export endpoint yet, so this is the DASHBOARD SUMMARY: at most 50 lessons, each shortened to 120 characters. Update the server for a full export."}else throw new Error(`export HTTP ${m.status}`);g.length===0&&(console.log(` No lessons in this Brain yet \u2014 nothing to export.
138
+ `),process.exit(0)),await t(c,{recursive:!0});const v=[];if(a==="md"||a==="both"){const w=s(c,"lessons.md");await e(w,Jn(g),"utf-8"),v.push(`${g.length} lesson${g.length===1?"":"s"} \u2192 ${w}`)}if(a==="jsonl"||a==="both"){const w=s(c,"lessons.jsonl");await e(w,Wn(g),"utf-8"),v.push(`${g.length} lesson${g.length===1?"":"s"} \u2192 ${w}`)}u?(console.log("\u26A0\uFE0F Export INCOMPLETE \u2014 this is not your whole Brain:"),console.log(` ${u}`),console.log("")):console.log("\u2705 Export complete:");for(const w of v)console.log(` ${w}`);console.log("")}catch(g){console.log(`
139
139
  \u274C Could not export your Brain: ${g.message}
140
140
  `),process.exit(1)}process.exit(0)}if(process.argv[2]==="invite"){const e=ne();e||(console.log(`
141
141
  \u26A0\uFE0F No cachly key found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot
142
142
  `),process.exit(1));try{const t=await fetch(`${x}/api/v1/referral/me`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)});if(!t.ok)throw new Error(`HTTP ${t.status}`);const s=await t.json(),n=s.url??R(`/r/${s.code}`,"invite"),o=s.referral_count??0,a=`Hey, I've been using cachly to give my AI persistent memory across sessions \u2014 no more re-explaining my stack every morning.
143
143
 
144
- You get a free Brain: ${n}`,r=encodeURIComponent(`I gave my AI persistent memory. It remembers fixes, patterns, and context across every session \u2014 no more re-explaining.
144
+ You get a free Brain: ${n}`,c=encodeURIComponent(`I gave my AI persistent memory. It remembers fixes, patterns, and context across every session \u2014 no more re-explaining.
145
145
 
146
146
  Try it free: ${n}
147
147
 
148
- @cachlydev`);console.log(""),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F9E0} Your cachly Brain invite link \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 ${n.padEnd(61)}\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),o>0&&(console.log(`\u2502 \x1B[32m\u2713 ${o} developer${o===1?"":"s"} joined via your link so far\x1B[0m`.padEnd(72)+"\u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524")),console.log("\u2502 \x1B[33mSlack / DM message:\x1B[0m \u2502"),console.log("\u2502 \u2502");for(const c of a.split(`
149
- `))console.log(`\u2502 \x1B[90m${c.slice(0,58).padEnd(58)}\x1B[0m \u2502`);console.log("\u2502 \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 \x1B[36m\u{1D54F} Tweet:\x1B[0m https://twitter.com/intent/tweet?text=${r.slice(0,10)}... \u2502`),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log(""),console.log("\x1B[2m Each developer who signs up via your link earns you 1 month Pro.\x1B[0m"),console.log("")}catch(t){console.log(`
148
+ @cachlydev`);console.log(""),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F9E0} Your cachly Brain invite link \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 ${n.padEnd(61)}\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),o>0&&(console.log(`\u2502 \x1B[32m\u2713 ${o} developer${o===1?"":"s"} joined via your link so far\x1B[0m`.padEnd(72)+"\u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524")),console.log("\u2502 \x1B[33mSlack / DM message:\x1B[0m \u2502"),console.log("\u2502 \u2502");for(const r of a.split(`
149
+ `))console.log(`\u2502 \x1B[90m${r.slice(0,58).padEnd(58)}\x1B[0m \u2502`);console.log("\u2502 \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 \x1B[36m\u{1D54F} Tweet:\x1B[0m https://twitter.com/intent/tweet?text=${c.slice(0,10)}... \u2502`),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log(""),console.log("\x1B[2m Each developer who signs up via your link earns you 1 month Pro.\x1B[0m"),console.log("")}catch(t){console.log(`
150
150
  \u274C Could not fetch invite link: ${t.message}
151
- `),process.exit(1)}process.exit(0)}if(process.argv[2]==="join"){const{writeFile:e,readFile:t,mkdir:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o,dirname:a}=await import("node:path"),{homedir:r}=await import("node:os"),{createInterface:c}=await import("node:readline"),u=process.argv[3]??"";u||(console.log(`
151
+ `),process.exit(1)}process.exit(0)}if(process.argv[2]==="join"){const{writeFile:e,readFile:t,mkdir:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o,dirname:a}=await import("node:path"),{homedir:c}=await import("node:os"),{createInterface:r}=await import("node:readline"),d=process.argv[3]??"";d||(console.log(`
152
152
  \u274C Usage: npx @cachly-dev/mcp-server@latest join <token>
153
153
  `),console.log(` Get a token from a teammate: npx @cachly-dev/mcp-server@latest invite
154
154
  `),process.exit(1)),console.log(`
155
- \u23F3 Looking up invite...`);let g;try{const A=await fetch(`${x}/api/invite/${u}`,{signal:AbortSignal.timeout(8e3)});A.status===404&&(console.log(`
155
+ \u23F3 Looking up invite...`);let g;try{const A=await fetch(`${x}/api/invite/${d}`,{signal:AbortSignal.timeout(8e3)});A.status===404&&(console.log(`
156
156
  \u274C Invite not found \u2014 the link may be invalid.
157
157
  `),process.exit(1)),A.status===410&&(console.log(`
158
158
  \u274C This invite link has expired (7-day limit).
@@ -160,17 +160,17 @@ Try it free: ${n}
160
160
  \u274C Could not fetch invite: HTTP ${A.status}
161
161
  `),process.exit(1)),g=await A.json()}catch(A){console.log(`
162
162
  \u274C Network error: ${A.message}
163
- `),process.exit(1)}const{instance_id:d,instance_name:m,tier:v,label:w}=g,b=new Date(g.expires_at).toLocaleDateString();console.log(""),console.log(" \x1B[35m\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log(" \x1B[35m\u2551\x1B[0m \x1B[1m\u{1F9E0} Brain Invite\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log(" \x1B[35m\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(` Brain : \x1B[1m${m}\x1B[0m`),console.log(` Tier : ${v}`),w&&console.log(` Note : ${w}`),console.log(` Expires : ${b}`),console.log("");const l=c({input:process.stdin,output:process.stdout}),i=await new Promise(A=>{l.question(" Join this Brain? [Y/n] ",C=>{l.close(),A(C.trim().toLowerCase()||"y")})});i!=="y"&&i!=="yes"&&(console.log(`
163
+ `),process.exit(1)}const{instance_id:u,instance_name:m,tier:v,label:w}=g,b=new Date(g.expires_at).toLocaleDateString();console.log(""),console.log(" \x1B[35m\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log(" \x1B[35m\u2551\x1B[0m \x1B[1m\u{1F9E0} Brain Invite\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log(" \x1B[35m\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(` Brain : \x1B[1m${m}\x1B[0m`),console.log(` Tier : ${v}`),w&&console.log(` Note : ${w}`),console.log(` Expires : ${b}`),console.log("");const l=r({input:process.stdin,output:process.stdout}),i=await new Promise(A=>{l.question(" Join this Brain? [Y/n] ",C=>{l.close(),A(C.trim().toLowerCase()||"y")})});i!=="y"&&i!=="yes"&&(console.log(`
164
164
  Cancelled.
165
165
  `),process.exit(0));let p=y;if(!p){console.log(`
166
166
  No API key found \u2014 starting sign-in (10 seconds)...
167
167
  `);try{const A=await fetch(`${x}/api/v1/auth/device/code`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:"cachly-mcp-cli"}),signal:AbortSignal.timeout(1e4)});if(A.ok){const C=await A.json();console.log(` \u{1F449} Open: \x1B[36m${C.verification_uri}\x1B[0m`),console.log(` Code: \x1B[1m${C.user_code}\x1B[0m
168
- `);const T=(C.interval??5)*1e3;for(let $=0;$<24;$++){await new Promise(k=>setTimeout(k,T));try{const k=await fetch(`${x}/api/v1/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:C.device_code,client_id:"cachly-mcp-cli"}),signal:AbortSignal.timeout(8e3)});if(k.ok){const L=await k.json();if(L.access_token){p=L.access_token;break}}}catch{}}p||(console.log(`
168
+ `);const E=(C.interval??5)*1e3;for(let $=0;$<24;$++){await new Promise(k=>setTimeout(k,E));try{const k=await fetch(`${x}/api/v1/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:C.device_code,client_id:"cachly-mcp-cli"}),signal:AbortSignal.timeout(8e3)});if(k.ok){const L=await k.json();if(L.access_token){p=L.access_token;break}}}catch{}}p||(console.log(`
169
169
  \u274C Sign-in timed out. Run the command again.
170
170
  `),process.exit(1)),console.log(` \u2705 Signed in!
171
171
  `)}}catch(A){console.log(`
172
172
  \u26A0\uFE0F Could not start sign-in: ${A.message}`),console.log(` Set CACHLY_JWT manually from ${R("/setup-ai","join")}
173
- `),process.exit(1)}}p&&p!==y&&X(p);const h=process.cwd(),E=r(),O=[{label:".mcp.json (Claude Code project)",path:o(h,".mcp.json")},{label:".cursor/mcp.json",path:o(h,".cursor","mcp.json")},{label:".windsurf/mcp.json",path:o(h,".windsurf","mcp.json")},{label:".vscode/mcp.json (Copilot/Cline)",path:o(h,".vscode","mcp.json")},{label:"~/.claude/mcp.json (global)",path:o(E,".claude","mcp.json"),global:!0}];let j=0;for(const{label:A,path:C,global:T}of O){const $=a(C);if(!(!T&&!n($)&&!n(C)))try{await s($,{recursive:!0});let k={};if(n(C))try{k=JSON.parse(await t(C,"utf-8"))}catch{try{await(await import("node:fs/promises")).rename(C,C+".bak")}catch{}}const L=k.mcpServers??{},Y=L.cachly??{},K=Y.env??{};K.CACHLY_BRAIN_INSTANCE_ID=d,p&&T&&!K.CACHLY_JWT&&(K.CACHLY_JWT=p),x!==Lt&&(K.CACHLY_API_URL=x),L.cachly={...Y,command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:K},k.mcpServers=L,await e(C,JSON.stringify(k,null,2),"utf-8"),console.log(` \u2705 ${A}`),j++}catch(k){k.code!=="ENOENT"&&console.log(` \u26A0\uFE0F ${A}: ${k.message}`)}}console.log(""),j===0?console.log(" \u26A0\uFE0F No editor configs found \u2014 run `cachly setup` first.\n"):(console.log(` \u{1F9E0} You're now sharing Brain: \x1B[1m${m}\x1B[0m`),console.log(` Restart your editor \u2014 your AI arrives pre-briefed from the team Brain.
173
+ `),process.exit(1)}}p&&p!==y&&X(p);const h=process.cwd(),T=c(),O=[{label:".mcp.json (Claude Code project)",path:o(h,".mcp.json")},{label:".cursor/mcp.json",path:o(h,".cursor","mcp.json")},{label:".windsurf/mcp.json",path:o(h,".windsurf","mcp.json")},{label:".vscode/mcp.json (Copilot/Cline)",path:o(h,".vscode","mcp.json")},{label:"~/.claude/mcp.json (global)",path:o(T,".claude","mcp.json"),global:!0}];let j=0;for(const{label:A,path:C,global:E}of O){const $=a(C);if(!(!E&&!n($)&&!n(C)))try{await s($,{recursive:!0});let k={};if(n(C))try{k=JSON.parse(await t(C,"utf-8"))}catch{try{await(await import("node:fs/promises")).rename(C,C+".bak")}catch{}}const L=k.mcpServers??{},Y=L.cachly??{},K=Y.env??{};K.CACHLY_BRAIN_INSTANCE_ID=u,p&&E&&!K.CACHLY_JWT&&(K.CACHLY_JWT=p),x!==Nt&&(K.CACHLY_API_URL=x),L.cachly={...Y,command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:K},k.mcpServers=L,await e(C,JSON.stringify(k,null,2),"utf-8"),console.log(` \u2705 ${A}`),j++}catch(k){k.code!=="ENOENT"&&console.log(` \u26A0\uFE0F ${A}: ${k.message}`)}}console.log(""),j===0?console.log(" \u26A0\uFE0F No editor configs found \u2014 run `cachly setup` first.\n"):(console.log(` \u{1F9E0} You're now sharing Brain: \x1B[1m${m}\x1B[0m`),console.log(` Restart your editor \u2014 your AI arrives pre-briefed from the team Brain.
174
174
  `),console.log(" \u{1F4DB} Add the badge to your README:"),console.log(` npx @cachly-dev/mcp-server@latest badge
175
175
  `)),process.exit(0)}if(process.argv[2]==="upgrade"){process.stdout.write(`
176
176
  \u23F3 Checking for updates...
@@ -178,101 +178,101 @@ Try it free: ${n}
178
178
  \u2705 Already on the latest version: \x1B[32mv${D}\x1B[0m
179
179
  `):(console.log(""),console.log("\x1B[35m \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly update available\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(` Current : \x1B[31mv${D}\x1B[0m`),console.log(` Latest : \x1B[32mv${s}\x1B[0m`),console.log(""),console.log(" Update your editor configs to pick up the new version:"),console.log(""),console.log(" \x1B[32m npx @cachly-dev/mcp-server@latest autopilot\x1B[0m"),console.log(""),console.log(" \x1B[2m(npx always fetches the latest when @latest is specified)\x1B[0m"),console.log(""))}catch(e){console.log(`
180
180
  \u274C Could not check for updates: ${e.message}
181
- `),process.exit(1)}process.exit(0)}if(process.argv[2]==="bench"){const{fileURLToPath:e}=await import("node:url"),{dirname:t,resolve:s}=await import("node:path"),{loadExternalCorpus:n,runExternalBenchmark:o}=await import("./bench/external-corpus.js"),a=process.argv.includes("--json"),r=process.argv.slice(3).find(g=>!g.startsWith("--")),c=t(e(import.meta.url)),u=r?s(process.cwd(),r):s(c,"bench","external","sample-corpus.json");try{const g=await n(u),d=await o(g);a&&(console.log(JSON.stringify({corpus:g.name,lessons:d.corpusSize,queries:d.queryCount,cachly_p1:Math.round(d.cachly.precisionAt1*1e3)/10,flatfile_p1:Math.round(d.flatfile.precisionAt1*1e3)/10,cachly_mrr:Math.round(d.cachly.mrr*1e3)/10,flatfile_mrr:Math.round(d.flatfile.mrr*1e3)/10,p1_lift_vs_flatfile_pct:Math.round((d.cachly.precisionAt1-d.flatfile.precisionAt1)*1e3)/10,mrr_lift_vs_flatfile_pct:Math.round((d.cachly.mrr-d.flatfile.mrr)*1e3)/10},null,2)),process.exit(0));const m=((d.cachly.precisionAt1-d.flatfile.precisionAt1)*100).toFixed(1),v=((d.cachly.mrr-d.flatfile.mrr)*100).toFixed(1),w=((d.cachly.precisionAt1-d.baseline.precisionAt1)*100).toFixed(1),b=d.cachly.precisionAt1>=d.flatfile.precisionAt1?"\x1B[32m+":"\x1B[31m",l=d.cachly.mrr>=d.flatfile.mrr?"\x1B[32m+":"\x1B[31m";console.log(""),console.log("\x1B[35m \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly recall quality benchmark\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(` Corpus : ${g.name??u}`),console.log(` Dataset: ${d.corpusSize} lessons \xB7 ${d.queryCount} queries \xB7 10 engineering domains`),console.log(" (k8s, DB, auth, CI, frontend, API, payments, observability, Node.js, infra)"),console.log(""),console.log(" \x1B[1mPrecision@1\x1B[0m (finds the right lesson at rank #1):"),console.log(` flat-file memory : \x1B[33m${(d.flatfile.precisionAt1*100).toFixed(1)}%\x1B[0m (naive keyword overlap \u2014 no quality signal)`),console.log(` raw BM25 : \x1B[33m${(d.baseline.precisionAt1*100).toFixed(1)}%\x1B[0m (keyword ranking)`),console.log(` cachly : \x1B[1m\x1B[32m${(d.cachly.precisionAt1*100).toFixed(1)}%\x1B[0m (BM25 + quality reranking)`),console.log(""),console.log(" \x1B[1mMean Reciprocal Rank\x1B[0m (average rank of the right answer):"),console.log(` flat-file memory : \x1B[33m${(d.flatfile.mrr*100).toFixed(1)}%\x1B[0m`),console.log(` raw BM25 : \x1B[33m${(d.baseline.mrr*100).toFixed(1)}%\x1B[0m`),console.log(` cachly : \x1B[1m\x1B[32m${(d.cachly.mrr*100).toFixed(1)}%\x1B[0m`),console.log(""),console.log(" \x1B[1mLift vs flat-file memory\x1B[0m (what you get by switching from plain memory files):"),console.log(` Precision@1 : ${b}${m}%\x1B[0m`),console.log(` MRR : ${l}${v}%\x1B[0m`),console.log(` vs BM25 : \x1B[32m+${w}%\x1B[0m Precision@1 (quality reranking on top of keyword search)`),console.log(""),console.log(" \x1B[2mFlat-file = lexical overlap over raw text files (how Anthropic/Claude Memory works).\x1B[0m"),console.log(" \x1B[2mAdversarial distractors included \u2014 failure lessons that share the exact query vocabulary.\x1B[0m"),console.log(" \x1B[2mcachly ignores them because they have low confidence / failed outcome.\x1B[0m"),console.log(""),console.log(" Share your results:"),console.log(` \x1B[36m"My Brain: Precision@1 ${(d.cachly.precisionAt1*100).toFixed(1)}% (${b}${m}% vs flat-file memory, ${d.queryCount} queries)"\x1B[0m`),console.log(""),console.log(" Run on a custom corpus:"),console.log(" \x1B[2m npx @cachly-dev/mcp-server@latest bench my-incidents.json\x1B[0m"),console.log(" \x1B[2m npx @cachly-dev/mcp-server@latest bench --json # machine-readable\x1B[0m"),console.log(""),console.log(" \x1B[1m\u2192 Give your AI this recall quality on your own work (free, 1\u20135 min):\x1B[0m"),console.log(" \x1B[32m$ npx @cachly-dev/mcp-server@latest autopilot\x1B[0m"),console.log(" \x1B[90m Signs in, configures every editor, bootstraps from your git history.\x1B[0m"),console.log(` \x1B[90m Or create your Brain at: \x1B[36m${R("/setup-ai","bench")}\x1B[0m`),console.log("")}catch(g){console.error(`
181
+ `),process.exit(1)}process.exit(0)}if(process.argv[2]==="bench"){const{fileURLToPath:e}=await import("node:url"),{dirname:t,resolve:s}=await import("node:path"),{loadExternalCorpus:n,runExternalBenchmark:o}=await import("./bench/external-corpus.js"),a=process.argv.includes("--json"),c=process.argv.slice(3).find(g=>!g.startsWith("--")),r=t(e(import.meta.url)),d=c?s(process.cwd(),c):s(r,"bench","external","sample-corpus.json");try{const g=await n(d),u=await o(g);a&&(console.log(JSON.stringify({corpus:g.name,lessons:u.corpusSize,queries:u.queryCount,cachly_p1:Math.round(u.cachly.precisionAt1*1e3)/10,flatfile_p1:Math.round(u.flatfile.precisionAt1*1e3)/10,cachly_mrr:Math.round(u.cachly.mrr*1e3)/10,flatfile_mrr:Math.round(u.flatfile.mrr*1e3)/10,p1_lift_vs_flatfile_pct:Math.round((u.cachly.precisionAt1-u.flatfile.precisionAt1)*1e3)/10,mrr_lift_vs_flatfile_pct:Math.round((u.cachly.mrr-u.flatfile.mrr)*1e3)/10},null,2)),process.exit(0));const m=((u.cachly.precisionAt1-u.flatfile.precisionAt1)*100).toFixed(1),v=((u.cachly.mrr-u.flatfile.mrr)*100).toFixed(1),w=((u.cachly.precisionAt1-u.baseline.precisionAt1)*100).toFixed(1),b=u.cachly.precisionAt1>=u.flatfile.precisionAt1?"\x1B[32m+":"\x1B[31m",l=u.cachly.mrr>=u.flatfile.mrr?"\x1B[32m+":"\x1B[31m";console.log(""),console.log("\x1B[35m \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly recall quality benchmark\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(` Corpus : ${g.name??d}`),console.log(` Dataset: ${u.corpusSize} lessons \xB7 ${u.queryCount} queries \xB7 10 engineering domains`),console.log(" (k8s, DB, auth, CI, frontend, API, payments, observability, Node.js, infra)"),console.log(""),console.log(" \x1B[1mPrecision@1\x1B[0m (finds the right lesson at rank #1):"),console.log(` flat-file memory : \x1B[33m${(u.flatfile.precisionAt1*100).toFixed(1)}%\x1B[0m (naive keyword overlap \u2014 no quality signal)`),console.log(` raw BM25 : \x1B[33m${(u.baseline.precisionAt1*100).toFixed(1)}%\x1B[0m (keyword ranking)`),console.log(` cachly : \x1B[1m\x1B[32m${(u.cachly.precisionAt1*100).toFixed(1)}%\x1B[0m (BM25 + quality reranking)`),console.log(""),console.log(" \x1B[1mMean Reciprocal Rank\x1B[0m (average rank of the right answer):"),console.log(` flat-file memory : \x1B[33m${(u.flatfile.mrr*100).toFixed(1)}%\x1B[0m`),console.log(` raw BM25 : \x1B[33m${(u.baseline.mrr*100).toFixed(1)}%\x1B[0m`),console.log(` cachly : \x1B[1m\x1B[32m${(u.cachly.mrr*100).toFixed(1)}%\x1B[0m`),console.log(""),console.log(" \x1B[1mLift vs flat-file memory\x1B[0m (what you get by switching from plain memory files):"),console.log(` Precision@1 : ${b}${m}%\x1B[0m`),console.log(` MRR : ${l}${v}%\x1B[0m`),console.log(` vs BM25 : \x1B[32m+${w}%\x1B[0m Precision@1 (quality reranking on top of keyword search)`),console.log(""),console.log(" \x1B[2mFlat-file = lexical overlap over raw text files (how Anthropic/Claude Memory works).\x1B[0m"),console.log(" \x1B[2mAdversarial distractors included \u2014 failure lessons that share the exact query vocabulary.\x1B[0m"),console.log(" \x1B[2mcachly ignores them because they have low confidence / failed outcome.\x1B[0m"),console.log(""),console.log(" Share your results:"),console.log(` \x1B[36m"My Brain: Precision@1 ${(u.cachly.precisionAt1*100).toFixed(1)}% (${b}${m}% vs flat-file memory, ${u.queryCount} queries)"\x1B[0m`),console.log(""),console.log(" Run on a custom corpus:"),console.log(" \x1B[2m npx @cachly-dev/mcp-server@latest bench my-incidents.json\x1B[0m"),console.log(" \x1B[2m npx @cachly-dev/mcp-server@latest bench --json # machine-readable\x1B[0m"),console.log(""),console.log(" \x1B[1m\u2192 Give your AI this recall quality on your own work (free, 1\u20135 min):\x1B[0m"),console.log(" \x1B[32m$ npx @cachly-dev/mcp-server@latest autopilot\x1B[0m"),console.log(" \x1B[90m Signs in, configures every editor, bootstraps from your git history.\x1B[0m"),console.log(` \x1B[90m Or create your Brain at: \x1B[36m${R("/setup-ai","bench")}\x1B[0m`),console.log("")}catch(g){console.error(`
182
182
  \u274C bench failed: ${g.message}
183
183
  `),process.exit(1)}process.exit(0)}if(process.argv[2]==="demo"){const{existsSync:e,readFileSync:t}=await import("node:fs"),{resolve:s,basename:n}=await import("node:path"),o=process.cwd();console.log(`
184
184
  \x1B[35m\u{1F9E0} cachly Brain \u2014 Live Demo\x1B[0m`),console.log(`\x1B[90mNo account needed. Reading your git history...\x1B[0m
185
185
  `),e(s(o,".git"))||(console.log("\u26A0\uFE0F No git repository found here."),console.log(` Run this command inside a project directory with git history.
186
186
  `),console.log(` Example: cd ~/my-project && npx @cachly-dev/mcp-server@latest demo
187
- `),process.exit(0));let a="";try{a=at(o,["config","user.name"]).trim().split(" ")[0]??""}catch{}let r=n(o);try{const $=JSON.parse(t(s(o,"package.json"),"utf-8"));$.name&&(r=$.name.replace(/^@[^/]+\//,""))}catch{}let c="";try{c=at(o,["log","HEAD","--pretty=format:%H|||%s|||%ad|||%an","--date=short","--no-merges","-n","200"],{timeoutMs:3e4})}catch{console.log(`\u26A0\uFE0F Could not read git log. Make sure you have commits.
188
- `),process.exit(0)}const u=c.trim().split(`
189
- `).filter(Boolean).map($=>{const[k,L,Y,K]=$.split("|||");return{sha:(k??"").trim().slice(0,8),subject:(L??"").trim(),date:(Y??"").trim(),author:(K??"").trim()}});u.length===0&&(console.log(`\u26A0\uFE0F No commits found.
190
- `),process.exit(0));const g=new Map,d=[],m=[],v=[],w=new Set;let b=0;for(const $ of u){const k=Qn($.subject);g.set(k,(g.get(k)??0)+1),Xn($.subject)&&b++,k==="fix"&&d.length<5&&d.push($.subject.slice(0,72)),k==="feat"&&m.length<5&&m.push($.subject.slice(0,72)),k==="security"&&v.length<3&&v.push($.subject.slice(0,72)),$.author&&w.add($.author)}const l=es(u.map($=>$.subject)),i=`${u[u.length-1]?.date??"?"} \u2192 ${u[0]?.date??"?"}`,p=l>=501?"Oracle":l>=201?"Architect":l>=51?"Expert":l>=11?"Explorer":"Apprentice",E=`${a?`Hey ${a} \u2014 `:""}here's what your AI would know about ${r}`;process.stdout.write("\x1B[2K\r"),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log(`\u2502 \x1B[1m\u{1F9E0} ${E.slice(0,58).padEnd(58)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Commits analysed : \x1B[33m${String(u.length).padEnd(6)}\x1B[0m Date range: \x1B[90m${i.slice(0,23).padEnd(23)}\x1B[0m \u2502`),console.log(`\u2502 Lessons extracted: \x1B[32m${String(l).padEnd(6)}\x1B[0m Contributors: \x1B[36m${String(w.size).padEnd(20)}\x1B[0m\u2502`),console.log(`\u2502 Brain Level : \x1B[35m${p.padEnd(10)}\x1B[0m Reverts: \x1B[33m${String(b).padEnd(21)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");const O=[...g.entries()].filter(([$])=>$!=="chore").sort(($,k)=>k[1]-$[1]),j=($,k)=>"\u2588".repeat(Math.round($/k*20)).padEnd(20),A=Math.max(...O.map(([,$])=>$),1);console.log("\u2502 \x1B[90mCategory breakdown:\x1B[0m \u2502");for(const[$,k]of O){const L={fix:"\u{1F527}",feat:"\u2728",perf:"\u26A1",security:"\u{1F512}",deploy:"\u{1F680}",refactor:"\u{1F504}"}[$]??"\u2022";console.log(`\u2502 ${L} \x1B[36m${$.padEnd(10)}\x1B[0m \x1B[35m${j(k,A)}\x1B[0m \x1B[33m${String(k).padStart(3)}\x1B[0m \u2502`)}if(v.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[31m\u{1F512} Security fixes your AI would know:\x1B[0m \u2502");for(const $ of v)console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}if(d.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[33m\u{1F527} Bug fixes your AI would never repeat:\x1B[0m \u2502");for(const $ of d.slice(0,4))console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}if(m.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[32m\u2728 Features & decisions it would recall:\x1B[0m \u2502");for(const $ of m.slice(0,3))console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[32m\u{1F4A1} With cachly, your AI arrives pre-briefed every session.\x1B[0m \u2502"),console.log("\u2502 \x1B[32m No more re-explaining. No more repeated mistakes.\x1B[0m \u2502"),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log("");const C=new URLSearchParams({repo:r,commits:String(u.length),lessons:String(l),level:p,authors:String(w.size),reverts:String(b)}),T=R(`/preview?${C.toString()}`,"demo");console.log(" \x1B[1mMake this permanent (free, 1\u20135 minutes):\x1B[0m"),console.log(" \x1B[32m$ npx @cachly-dev/mcp-server@latest autopilot\x1B[0m"),console.log(""),console.log(` \x1B[90m\u{1F517} Shareable preview:\x1B[0m \x1B[36m${T}\x1B[0m`),console.log(""),console.log(" Works with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 Copilot \xB7 Cline \xB7 Zed"),console.log(" GDPR \xB7 German servers \xB7 free tier, no credit card"),console.log(""),process.exit(0)}if(process.argv[2]==="share"){const e=ne(),t=F();(!e||!t)&&(console.log(`
187
+ `),process.exit(0));let a="";try{a=at(o,["config","user.name"]).trim().split(" ")[0]??""}catch{}let c=n(o);try{const $=JSON.parse(t(s(o,"package.json"),"utf-8"));$.name&&(c=$.name.replace(/^@[^/]+\//,""))}catch{}let r="";try{r=at(o,["log","HEAD","--pretty=format:%H|||%s|||%ad|||%an","--date=short","--no-merges","-n","200"],{timeoutMs:3e4})}catch{console.log(`\u26A0\uFE0F Could not read git log. Make sure you have commits.
188
+ `),process.exit(0)}const d=r.trim().split(`
189
+ `).filter(Boolean).map($=>{const[k,L,Y,K]=$.split("|||");return{sha:(k??"").trim().slice(0,8),subject:(L??"").trim(),date:(Y??"").trim(),author:(K??"").trim()}});d.length===0&&(console.log(`\u26A0\uFE0F No commits found.
190
+ `),process.exit(0));const g=new Map,u=[],m=[],v=[],w=new Set;let b=0;for(const $ of d){const k=Xn($.subject);g.set(k,(g.get(k)??0)+1),es($.subject)&&b++,k==="fix"&&u.length<5&&u.push($.subject.slice(0,72)),k==="feat"&&m.length<5&&m.push($.subject.slice(0,72)),k==="security"&&v.length<3&&v.push($.subject.slice(0,72)),$.author&&w.add($.author)}const l=ts(d.map($=>$.subject)),i=`${d[d.length-1]?.date??"?"} \u2192 ${d[0]?.date??"?"}`,p=l>=501?"Oracle":l>=201?"Architect":l>=51?"Expert":l>=11?"Explorer":"Apprentice",T=`${a?`Hey ${a} \u2014 `:""}here's what your AI would know about ${c}`;process.stdout.write("\x1B[2K\r"),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log(`\u2502 \x1B[1m\u{1F9E0} ${T.slice(0,58).padEnd(58)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Commits analysed : \x1B[33m${String(d.length).padEnd(6)}\x1B[0m Date range: \x1B[90m${i.slice(0,23).padEnd(23)}\x1B[0m \u2502`),console.log(`\u2502 Lessons extracted: \x1B[32m${String(l).padEnd(6)}\x1B[0m Contributors: \x1B[36m${String(w.size).padEnd(20)}\x1B[0m\u2502`),console.log(`\u2502 Brain Level : \x1B[35m${p.padEnd(10)}\x1B[0m Reverts: \x1B[33m${String(b).padEnd(21)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");const O=[...g.entries()].filter(([$])=>$!=="chore").sort(($,k)=>k[1]-$[1]),j=($,k)=>"\u2588".repeat(Math.round($/k*20)).padEnd(20),A=Math.max(...O.map(([,$])=>$),1);console.log("\u2502 \x1B[90mCategory breakdown:\x1B[0m \u2502");for(const[$,k]of O){const L={fix:"\u{1F527}",feat:"\u2728",perf:"\u26A1",security:"\u{1F512}",deploy:"\u{1F680}",refactor:"\u{1F504}"}[$]??"\u2022";console.log(`\u2502 ${L} \x1B[36m${$.padEnd(10)}\x1B[0m \x1B[35m${j(k,A)}\x1B[0m \x1B[33m${String(k).padStart(3)}\x1B[0m \u2502`)}if(v.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[31m\u{1F512} Security fixes your AI would know:\x1B[0m \u2502");for(const $ of v)console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}if(u.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[33m\u{1F527} Bug fixes your AI would never repeat:\x1B[0m \u2502");for(const $ of u.slice(0,4))console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}if(m.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[32m\u2728 Features & decisions it would recall:\x1B[0m \u2502");for(const $ of m.slice(0,3))console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[32m\u{1F4A1} With cachly, your AI arrives pre-briefed every session.\x1B[0m \u2502"),console.log("\u2502 \x1B[32m No more re-explaining. No more repeated mistakes.\x1B[0m \u2502"),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log("");const C=new URLSearchParams({repo:c,commits:String(d.length),lessons:String(l),level:p,authors:String(w.size),reverts:String(b)}),E=R(`/preview?${C.toString()}`,"demo");console.log(" \x1B[1mMake this permanent (free, 1\u20135 minutes):\x1B[0m"),console.log(" \x1B[32m$ npx @cachly-dev/mcp-server@latest autopilot\x1B[0m"),console.log(""),console.log(` \x1B[90m\u{1F517} Shareable preview:\x1B[0m \x1B[36m${E}\x1B[0m`),console.log(""),console.log(" Works with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 Copilot \xB7 Cline \xB7 Zed"),console.log(" GDPR \xB7 German servers \xB7 free tier, no credit card"),console.log(""),process.exit(0)}if(process.argv[2]==="share"){const e=ne(),t=W();(!e||!t)&&(console.log(`
191
191
  \u26A0\uFE0F No cachly key or Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot (takes 1\u20135 minutes)
192
192
  `),process.exit(1)),process.stdout.write(`
193
193
  \u{1F9E0} Fetching your Brain stats...
194
- `);try{const s=await fetch(`${x}/api/v1/instances/${t}/memory`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)});if(!s.ok)throw new Error(`HTTP ${s.status}`);const n=await s.json(),o=n.lesson_count??0,a=n.total_recall_count??0,r=Math.round(n.iq_boost_pct??0),c=a*1200,u=(c*3e-6).toFixed(2),g=o===0?"Intern \u{1F331}":o<10?"Junior Dev \u{1F527}":o<30?"Mid Dev \u26A1":o<60?"Senior Dev \u{1F9E0}":o<100?"Staff Eng \u{1F680}":"Principal Eng \u{1F3C6}";console.log(""),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F9E0} My AI Brain \xB7 powered by \x1B[35mcachly.dev\x1B[0m \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Lessons stored : \x1B[33m${String(o).padEnd(8)}\x1B[0m Brain level: \x1B[32m${g.padEnd(18)}\x1B[0m\u2502`),console.log(`\u2502 Total recalls : \x1B[36m${String(a).padEnd(8)}\x1B[0m Quality score: \x1B[32m${String(r).padEnd(3)}%\x1B[0m \u2502`),console.log(`\u2502 Tokens saved : \x1B[32m${((c/1e3).toFixed(0)+"K").padEnd(8)}\x1B[0m Cost saved: \x1B[32m$${u.padEnd(20)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 Works with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 Copilot \u2502"),console.log("\u2502 Free \xB7 GDPR \xB7 German servers \u2502"),console.log("\u2502 \x1B[35mnpx @cachly-dev/mcp-server@latest autopilot\x1B[0m \u2502"),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log("");const d=R("/","share"),m=`\u{1F9E0} My AI coding assistant now has persistent memory.
194
+ `);try{const s=await fetch(`${x}/api/v1/instances/${t}/memory`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)});if(!s.ok)throw new Error(`HTTP ${s.status}`);const n=await s.json(),o=n.lesson_count??0,a=n.total_recall_count??0,c=Math.round(n.iq_boost_pct??0),r=a*1200,d=(r*3e-6).toFixed(2),g=o===0?"Intern \u{1F331}":o<10?"Junior Dev \u{1F527}":o<30?"Mid Dev \u26A1":o<60?"Senior Dev \u{1F9E0}":o<100?"Staff Eng \u{1F680}":"Principal Eng \u{1F3C6}";console.log(""),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F9E0} My AI Brain \xB7 powered by \x1B[35mcachly.dev\x1B[0m \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Lessons stored : \x1B[33m${String(o).padEnd(8)}\x1B[0m Brain level: \x1B[32m${g.padEnd(18)}\x1B[0m\u2502`),console.log(`\u2502 Total recalls : \x1B[36m${String(a).padEnd(8)}\x1B[0m Quality score: \x1B[32m${String(c).padEnd(3)}%\x1B[0m \u2502`),console.log(`\u2502 Tokens saved : \x1B[32m${((r/1e3).toFixed(0)+"K").padEnd(8)}\x1B[0m Cost saved: \x1B[32m$${d.padEnd(20)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 Works with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 Copilot \u2502"),console.log("\u2502 Free \xB7 GDPR \xB7 German servers \u2502"),console.log("\u2502 \x1B[35mnpx @cachly-dev/mcp-server@latest autopilot\x1B[0m \u2502"),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log("");const u=R("/","share"),m=`\u{1F9E0} My AI coding assistant now has persistent memory.
195
195
 
196
196
  ${o} lessons stored \xB7 ${a} recalls \xB7 ${g}
197
197
 
198
198
  Fix a bug once \u2192 AI remembers forever. Across Claude Code, Cursor, Windsurf, Copilot.
199
199
 
200
- ${d}
200
+ ${u}
201
201
 
202
202
  #AIMemory #ClaudeCode #Cursor #DeveloperTools`;console.log(" \x1B[1m\u{1F4CB} Share on Twitter/X (copy this):\x1B[0m"),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(m.split(`
203
203
  `).map(v=>` ${v}`).join(`
204
204
  `)),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(""),console.log(" \x1B[2mPro tip: add a screenshot of your Brain panel for 3x more engagement\x1B[0m"),console.log(" \x1B[2mAlso add a live badge to your README:\x1B[0m"),console.log(" \x1B[90m npx @cachly-dev/mcp-server@latest badge\x1B[0m"),console.log("")}catch(s){console.log(`
205
205
  \u274C Could not fetch stats: ${s.message}
206
- `),process.exit(1)}process.exit(0)}if(process.argv[2]==="publish"){const e=ne(),t=F();(!e||!t)&&(console.log(`
206
+ `),process.exit(1)}process.exit(0)}if(process.argv[2]==="publish"){const e=ne(),t=W();(!e||!t)&&(console.log(`
207
207
  \u26A0\uFE0F No cachly key or Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot
208
208
  `),process.exit(1));const s=process.argv.indexOf("--title"),n=s!==-1?process.argv[s+1]??"My Brain Snapshot":"My Brain Snapshot",o=process.argv.includes("--public");process.stdout.write(`
209
209
  \u{1F9E0} Publishing Brain snapshot...
210
- `);try{const a=await fetch(`${x}/api/v1/instances/${t}/memory`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)});let r=0,c=0;if(a.ok){const v=await a.json();r=v.lesson_count??0,c=v.total_recall_count??0}const u=await fetch(`${x}/api/v1/brains/share`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({title:n,visibility:o?"public":"unlisted",instance_id:t}),signal:AbortSignal.timeout(15e3)});if(!u.ok)throw new Error(`HTTP ${u.status}`);const d=(await u.json()).share_id??"unavailable",m=R(`/brain/share/${d}`,"publish");console.log(""),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F4E4} Brain Published \xB7 powered by \x1B[35mcachly.dev\x1B[0m \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Title : \x1B[33m${n.slice(0,44).padEnd(44)}\x1B[0m\u2502`),console.log(`\u2502 Lessons : \x1B[32m${String(r).padEnd(10)}\x1B[0m Recalls: \x1B[36m${String(c).padEnd(26)}\x1B[0m\u2502`),console.log(`\u2502 Visibility: \x1B[${o?"32":"33"}m${(o?"public (discoverable)":"unlisted (link only)").padEnd(44)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 \x1B[1mShare URL:\x1B[0m \x1B[36m${m.padEnd(51)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[2mAnyone can import with:\x1B[0m \u2502"),console.log(`\u2502 \x1B[90m brain_import(instance_id="...", share_id="${d.slice(0,17)}")\x1B[0m\u2502`),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log(""),console.log(" \x1B[1m\u{1F4CB} Share this with your team:\x1B[0m"),console.log(` ${m}`),console.log(""),console.log(` \x1B[2mTo list all your shares:\x1B[0m brain_share_list(instance_id="${t.slice(0,24)}...")`),console.log(` \x1B[2mTo revoke this share:\x1B[0m brain_unshare(share_id="${d.slice(0,24)}...")`),console.log("")}catch(a){console.log(`
210
+ `);try{const a=await fetch(`${x}/api/v1/instances/${t}/memory`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)});let c=0,r=0;if(a.ok){const v=await a.json();c=v.lesson_count??0,r=v.total_recall_count??0}const d=await fetch(`${x}/api/v1/brains/share`,{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({title:n,visibility:o?"public":"unlisted",instance_id:t}),signal:AbortSignal.timeout(15e3)});if(!d.ok)throw new Error(`HTTP ${d.status}`);const u=(await d.json()).share_id??"unavailable",m=R(`/brain/share/${u}`,"publish");console.log(""),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F4E4} Brain Published \xB7 powered by \x1B[35mcachly.dev\x1B[0m \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Title : \x1B[33m${n.slice(0,44).padEnd(44)}\x1B[0m\u2502`),console.log(`\u2502 Lessons : \x1B[32m${String(c).padEnd(10)}\x1B[0m Recalls: \x1B[36m${String(r).padEnd(26)}\x1B[0m\u2502`),console.log(`\u2502 Visibility: \x1B[${o?"32":"33"}m${(o?"public (discoverable)":"unlisted (link only)").padEnd(44)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 \x1B[1mShare URL:\x1B[0m \x1B[36m${m.padEnd(51)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[2mAnyone can import with:\x1B[0m \u2502"),console.log(`\u2502 \x1B[90m brain_import(instance_id="...", share_id="${u.slice(0,17)}")\x1B[0m\u2502`),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log(""),console.log(" \x1B[1m\u{1F4CB} Share this with your team:\x1B[0m"),console.log(` ${m}`),console.log(""),console.log(` \x1B[2mTo list all your shares:\x1B[0m brain_share_list(instance_id="${t.slice(0,24)}...")`),console.log(` \x1B[2mTo revoke this share:\x1B[0m brain_unshare(share_id="${u.slice(0,24)}...")`),console.log("")}catch(a){console.log(`
211
211
  \u274C Could not publish Brain: ${a.message}
212
212
  `),process.exit(1)}process.exit(0)}if(process.argv[2]==="tool-specs"||process.argv[2]==="openapi"){const{renderToolSpecs:e}=await import("./toolspecs.js");let t="openapi";if(process.argv[2]!=="openapi"){const n=process.argv.find(o=>o.startsWith("--format="));if(n)t=n.slice(9);else{const o=process.argv.indexOf("--format");o!==-1&&(t=process.argv[o+1]??"openapi")}}const s=["openapi","openai","anthropic","langchain"];s.includes(t)||(process.stderr.write(`
213
213
  \u274C Unknown format "${t}". Use one of: ${s.join(", ")}
214
214
 
215
215
  `),process.exit(1)),process.stdout.write(e(ge,t,D)+`
216
- `,()=>process.exit(0))}if(process.argv[2]==="badge"){const e=F();e||(console.log(`
216
+ `,()=>process.exit(0))}if(process.argv[2]==="badge"){const e=W();e||(console.log(`
217
217
  \u26A0\uFE0F No Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot (takes 1\u20135 minutes)
218
- `),process.exit(1));const t=`${x}/api/v1/badge/${e}`,s=R("/","badge"),n=`[![cachly Brain](${t})](${s})`,o=`<a href="${s}"><img src="${t}" alt="cachly Brain" /></a>`;console.log(""),console.log("\x1B[35m \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly Brain Badge\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(" Paste into your README.md:"),console.log(""),console.log(` \x1B[32m${n}\x1B[0m`),console.log(""),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Or paste into HTML:"),console.log(""),console.log(` \x1B[36m${o}\x1B[0m`),console.log(""),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Badge URL (live, updates every hour):"),console.log(` \x1B[90m${t}\x1B[0m`),console.log(""),console.log(" \x1B[2mThe badge shows your current lesson count \u2014 no auth required,"),console.log(" safe to embed in public repos. Updates hourly.\x1B[0m"),console.log(""),process.exit(0)}if(!process.argv[2]&&process.stdout.isTTY){console.log(""),console.log("\x1B[35m \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly \u2014 Persistent AI Memory for Developers\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(" Stop re-teaching your AI every morning."),console.log(" cachly gives it a permanent brain \u2014 pre-briefed every session."),console.log("");const e=(t,s)=>console.log(` \x1B[36m ${t.padEnd(22)}\x1B[0m ${s}`);console.log(" \x1B[1mStart:\x1B[0m \x1B[1m\x1B[32mnpx @cachly-dev/mcp-server@latest autopilot\x1B[0m \u2190 \x1B[1mOne command, fully ready\x1B[0m"),console.log(" Every command below runs as: npx @cachly-dev/mcp-server@latest <command>"),console.log(""),console.log(" \x1B[1mEvery day:\x1B[0m"),e("status","Lessons, recalls and team at a glance"),e("ambient-stats","Tokens injected vs saved \u2014 the honest net, even when negative"),e("doctor","Diagnose a broken or missing install"),e("health","Check key, API, editor configs and git hook"),e("digest","What your Brain learned this week"),console.log(" \x1B[1mSet up:\x1B[0m"),e("demo","Try it first (no account)"),e("setup","Interactive setup (pick editors)"),e("init","Write the config for one editor (flags)"),e("claim","Keep a test Brain in your own account"),e("upgrade","Check for updates"),e("uninstall","Take cachly out of this project (--dry-run first)"),console.log(" \x1B[1mYour data:\x1B[0m"),e("export","Write your lessons to disk (md / jsonl)"),e("index [dir]","Index a project into the Brain (CI)"),e("learn-git [repo]","Learn lessons from recent commits (CI)"),console.log(" \x1B[1mTeam & sharing:\x1B[0m"),e("invite","Invite a teammate"),e("join <token>","Accept a Brain invite"),e("share","Share your Brain stats"),e("publish","Publish an importable Brain snapshot"),e("badge","README badge for your Brain"),console.log(" \x1B[1mMore:\x1B[0m"),e("bench","Recall quality vs flat-file memory"),e("tool-specs | openapi","Tool definitions for other agent frameworks"),console.log(""),console.log(" \x1B[90mWorks with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 GitHub Copilot \xB7 Cline \xB7 Zed\x1B[0m"),console.log(` \x1B[90mGDPR \xB7 German servers \xB7 ${ge.length} MCP tools\x1B[0m`),console.log(""),process.exit(0)}const vs={cursor:{datei:".cursor/hooks.json",name:"Cursor",wie:"session briefing, per-prompt recall after the first tool call"},copilot:{datei:Zo,name:"VS Code / Copilot",wie:"session briefing, per-prompt recall"},codex:{datei:Qo,name:"Codex",wie:"session briefing, per-prompt recall; trust it once in /hooks"},gemini:{datei:Xo,name:"Gemini CLI",wie:"session briefing, per-prompt recall"}};function ws(e,t,s){if(!t)return;const{datei:n,name:o,wie:a}=vs[e];if(t.hooks==="skipped"){console.log(`\u26A0\uFE0F ${s}${n} ${t.grund??"is not valid JSON"} \u2014 left untouched, ${o} hooks not wired`);return}const r=t.hooks==="unchanged"?"\u2713 ":"\u2705 ",c=t.hooks==="written"?"Written":t.hooks==="merged"?"Merged":"Already wired";console.log(`${r}${s}${c}: ${n} (Ambient Recall for ${o} \u2014 ${a})`)}async function Me(e,t,s,n){const o=e==="codex"?"Codex":"Gemini CLI",a=await(e==="codex"?dn:un)(t,s).catch(()=>null);if(!a||a.status==="skipped"){const u=hs(e,s);console.log(`\u26A0\uFE0F ${n}${a?`${a.datei} ${a.grund??"could not be read"} \u2014 left untouched.`:`${o} MCP entry could not be written.`} Register cachly yourself:`),u&&console.log(` ${n}${u.befehl}`);return}const r=a.status==="unchanged"?"\u2713 ":"\u2705 ",c=a.status==="written"?"Written":a.status==="updated"?"Updated":"Already configured";console.log(`${r}${n}${c}: ${a.datei} (MCP server cachly for ${o} \u2014 it asks once to trust this folder; until then the server stays off)`)}async function ye(e,t,s,n){const o={cursor:Ko,copilot:qo,codex:Go,gemini:Vo}[e];ws(e,await o(t,s).catch(()=>null),n)}if(process.argv[2]==="init"){const e=Date.now(),{writeFile:t,mkdir:s,readFile:n}=await import("node:fs/promises"),{resolve:o,dirname:a}=await import("node:path"),r=process.argv.slice(3),c=l=>{const i=r.indexOf(`--${l}`);return i!==-1?r[i+1]:void 0};let u=c("instance-id")??process.env.CACHLY_BRAIN_INSTANCE_ID,g=c("api-key")??process.env.CACHLY_JWT;const d=(c("editor")??"claude").toLowerCase(),m=o(c("project-dir")??"."),v=c("api-url");if(v&&(x=v.replace(/\/+$/,"")),!u||!g)try{const{existsSync:l}=await import("node:fs"),i=process.env.HOME??process.env.USERPROFILE??"",p=i?o(i,".claude","mcp.json"):"";if(p&&l(p)){const E=JSON.parse(await n(p,"utf-8")).mcpServers?.cachly?.env??{};g??=E.CACHLY_JWT,u??=E.CACHLY_BRAIN_INSTANCE_ID,g&&u&&console.log("\u2713 Reusing credentials from ~/.claude/mcp.json (saved by a prior setup)")}}catch{}if((!u||!g)&&(console.error(`
218
+ `),process.exit(1));const t=`${x}/api/v1/badge/${e}`,s=R("/","badge"),n=`[![cachly Brain](${t})](${s})`,o=`<a href="${s}"><img src="${t}" alt="cachly Brain" /></a>`;console.log(""),console.log("\x1B[35m \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly Brain Badge\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(" Paste into your README.md:"),console.log(""),console.log(` \x1B[32m${n}\x1B[0m`),console.log(""),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Or paste into HTML:"),console.log(""),console.log(` \x1B[36m${o}\x1B[0m`),console.log(""),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Badge URL (live, updates every hour):"),console.log(` \x1B[90m${t}\x1B[0m`),console.log(""),console.log(" \x1B[2mThe badge shows your current lesson count \u2014 no auth required,"),console.log(" safe to embed in public repos. Updates hourly.\x1B[0m"),console.log(""),process.exit(0)}if(!process.argv[2]&&process.stdout.isTTY){console.log(""),console.log("\x1B[35m \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly \u2014 Persistent AI Memory for Developers\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\x1B[0m"),console.log(""),console.log(" Stop re-teaching your AI every morning."),console.log(" cachly gives it a permanent brain \u2014 pre-briefed every session."),console.log("");const e=(t,s)=>console.log(` \x1B[36m ${t.padEnd(22)}\x1B[0m ${s}`);console.log(" \x1B[1mStart:\x1B[0m \x1B[1m\x1B[32mnpx @cachly-dev/mcp-server@latest autopilot\x1B[0m \u2190 \x1B[1mOne command, fully ready\x1B[0m"),console.log(" Every command below runs as: npx @cachly-dev/mcp-server@latest <command>"),console.log(""),console.log(" \x1B[1mEvery day:\x1B[0m"),e("status","Lessons, recalls and team at a glance"),e("ambient-stats","Tokens injected vs saved \u2014 the honest net, even when negative"),e("doctor","Diagnose a broken or missing install"),e("health","Check key, API, editor configs and git hook"),e("digest","What your Brain learned this week"),console.log(" \x1B[1mSet up:\x1B[0m"),e("demo","Try it first (no account)"),e("setup","Interactive setup (pick editors)"),e("init","Write the config for one editor (flags)"),e("claim","Keep a test Brain in your own account"),e("upgrade","Check for updates"),e("uninstall","Take cachly out of this project (--dry-run first)"),console.log(" \x1B[1mYour data:\x1B[0m"),e("export","Write your lessons to disk (md / jsonl)"),e("index [dir]","Index a project into the Brain (CI)"),e("learn-git [repo]","Learn lessons from recent commits (CI)"),console.log(" \x1B[1mTeam & sharing:\x1B[0m"),e("invite","Invite a teammate"),e("join <token>","Accept a Brain invite"),e("share","Share your Brain stats"),e("publish","Publish an importable Brain snapshot"),e("badge","README badge for your Brain"),console.log(" \x1B[1mMore:\x1B[0m"),e("bench","Recall quality vs flat-file memory"),e("tool-specs | openapi","Tool definitions for other agent frameworks"),console.log(""),console.log(" \x1B[90mWorks with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 GitHub Copilot \xB7 Cline \xB7 Zed\x1B[0m"),console.log(` \x1B[90mGDPR \xB7 German servers \xB7 ${ge.length} MCP tools\x1B[0m`),console.log(""),process.exit(0)}const ws={cursor:{datei:".cursor/hooks.json",name:"Cursor",wie:"session briefing, per-prompt recall after the first tool call"},copilot:{datei:Qo,name:"VS Code / Copilot",wie:"session briefing, per-prompt recall"},codex:{datei:Xo,name:"Codex",wie:"session briefing, per-prompt recall; trust it once in /hooks"},gemini:{datei:en,name:"Gemini CLI",wie:"session briefing, per-prompt recall"}};function xs(e,t,s){if(!t)return;const{datei:n,name:o,wie:a}=ws[e];if(t.hooks==="skipped"){console.log(`\u26A0\uFE0F ${s}${n} ${t.grund??"is not valid JSON"} \u2014 left untouched, ${o} hooks not wired`);return}const c=t.hooks==="unchanged"?"\u2713 ":"\u2705 ",r=t.hooks==="written"?"Written":t.hooks==="merged"?"Merged":"Already wired";console.log(`${c}${s}${r}: ${n} (Ambient Recall for ${o} \u2014 ${a})`)}async function Me(e,t,s,n){const o=e==="codex"?"Codex":"Gemini CLI",a=await(e==="codex"?un:pn)(t,s).catch(()=>null);if(!a||a.status==="skipped"){const d=ys(e,s);console.log(`\u26A0\uFE0F ${n}${a?`${a.datei} ${a.grund??"could not be read"} \u2014 left untouched.`:`${o} MCP entry could not be written.`} Register cachly yourself:`),d&&console.log(` ${n}${d.befehl}`);return}const c=a.status==="unchanged"?"\u2713 ":"\u2705 ",r=a.status==="written"?"Written":a.status==="updated"?"Updated":"Already configured";console.log(`${c}${n}${r}: ${a.datei} (MCP server cachly for ${o} \u2014 it asks once to trust this folder; until then the server stays off)`)}async function ye(e,t,s,n){const o={cursor:qo,copilot:Go,codex:Vo,gemini:Zo}[e];xs(e,await o(t,s).catch(()=>null),n)}if(process.argv[2]==="init"){const e=Date.now(),{writeFile:t,mkdir:s,readFile:n}=await import("node:fs/promises"),{resolve:o,dirname:a}=await import("node:path"),c=process.argv.slice(3),r=l=>{const i=c.indexOf(`--${l}`);return i!==-1?c[i+1]:void 0};let d=r("instance-id")??process.env.CACHLY_BRAIN_INSTANCE_ID,g=r("api-key")??process.env.CACHLY_JWT;const u=(r("editor")??"claude").toLowerCase(),m=o(r("project-dir")??"."),v=r("api-url");if(v&&(x=v.replace(/\/+$/,"")),!d||!g)try{const{existsSync:l}=await import("node:fs"),i=process.env.HOME??process.env.USERPROFILE??"",p=i?o(i,".claude","mcp.json"):"";if(p&&l(p)){const T=JSON.parse(await n(p,"utf-8")).mcpServers?.cachly?.env??{};g??=T.CACHLY_JWT,d??=T.CACHLY_BRAIN_INSTANCE_ID,g&&d&&console.log("\u2713 Reusing credentials from ~/.claude/mcp.json (saved by a prior setup)")}}catch{}if((!d||!g)&&(console.error(`
219
219
  Usage: npx @cachly-dev/mcp-server@latest init --instance-id <uuid> --api-key <cky_live_...> [--editor claude|cursor|windsurf|copilot|continue|codex|gemini] [--project-dir /path] [--api-url https://your-self-hosted-backend]
220
220
  `),console.error(`First time? Run the zero-config wizard (signs you in, auto-provisions): npx @cachly-dev/mcp-server@latest autopilot
221
221
  `),console.error(`Get your credentials from: ${R("/setup-ai","init")}
222
- `),process.exit(1)),d==="codex"||d==="gemini")X(g),console.log(""),await Me(d,m,Z(g,u),"");else{const l=me[d]??".mcp.json",i=o(m,l);await s(a(i),{recursive:!0});const{existsSync:p}=await import("node:fs"),h=p(i),E=h?await n(i,"utf-8").catch(()=>""):"";X(g);const O=await Ot(i,g,u,d,{readFile:n,existsSync:p});O!==E?(await t(i,O,"utf-8"),console.log(`
222
+ `),process.exit(1)),u==="codex"||u==="gemini")X(g),console.log(""),await Me(u,m,Z(g,d),"");else{const l=me[u]??".mcp.json",i=o(m,l);await s(a(i),{recursive:!0});const{existsSync:p}=await import("node:fs"),h=p(i),T=h?await n(i,"utf-8").catch(()=>""):"";X(g);const O=await Pt(i,g,d,u,{readFile:n,existsSync:p});O!==T?(await t(i,O,"utf-8"),console.log(`
223
223
  \u2705 ${h?"Updated":"Written"}: ${l}`)):console.log(`
224
- \u2713 Already configured: ${l} (no change)`)}const w=await Pt(m,u);for(const[l,i]of Object.entries(w)){const p=i==="updated"?"\u2705 Updated":i==="appended"?"\u2705 Appended to":"\u2705 Written",h=l.split(/[\\/]/).pop()??l;console.log(`${p}: ${h}`)}try{const l=await nt(m,u);l==="written"?console.log("\u2705 Written: .git/hooks/post-commit (CLS hook)"):l==="upgraded"?console.log(`\u2705 Upgraded: .git/hooks/post-commit (CLS hook \u2192 ${st})`):l==="appended"?console.log("\u2705 Appended: .git/hooks/post-commit (CLS hook)"):l==="unchanged"&&console.log("\u2713 CLS hook already current in .git/hooks/post-commit")}catch{}if(d==="claude")try{const l=await ct(m,u);if(l.settings==="skipped")console.log(`\u26A0\uFE0F .claude/settings.json ${l.grund??"is not valid JSON"} \u2014 left untouched, Ambient Recall hooks not wired`);else{const i=l.scripts==="written"?"\u2705 Written":l.scripts==="upgraded"?`\u2705 Upgraded (\u2192 ${lt})`:"\u2713 Unchanged";console.log(`${i}: .claude/hooks/ (Ambient Recall \u2014 session briefing, per-prompt recall, file briefing, auto-learn)`),l.settings==="written"?console.log("\u2705 Written: .claude/settings.json (Ambient Recall hooks wired)"):l.settings==="merged"?console.log("\u2705 Merged: .claude/settings.json (Ambient Recall hooks wired)"):console.log("\u2713 Ambient Recall hooks already wired in .claude/settings.json")}}catch{}(d==="cursor"||d==="copilot"||d==="codex"||d==="gemini")&&await ye(d,m,u,"");const b=((Date.now()-e)/1e3).toFixed(1);console.log(`
225
- \u{1F9E0} Cachly AI Brain configured for ${d==="claude"?"Claude Code":d}! (${b}s)`),console.log(d==="codex"||d==="gemini"?` Start ${d} in this folder and trust it when asked \u2014 the \`cachly\` MCP tools will appear.`:" Restart your editor \u2014 the `cachly` MCP tools will appear."),console.log(" Re-run `init` anytime \u2014 it's idempotent (only writes what changed)."),console.log(`
224
+ \u2713 Already configured: ${l} (no change)`)}const w=await Ht(m,d);for(const[l,i]of Object.entries(w)){const p=i==="updated"?"\u2705 Updated":i==="appended"?"\u2705 Appended to":"\u2705 Written",h=l.split(/[\\/]/).pop()??l;console.log(`${p}: ${h}`)}try{const l=await nt(m,d);l==="written"?console.log("\u2705 Written: .git/hooks/post-commit (CLS hook)"):l==="upgraded"?console.log(`\u2705 Upgraded: .git/hooks/post-commit (CLS hook \u2192 ${st})`):l==="appended"?console.log("\u2705 Appended: .git/hooks/post-commit (CLS hook)"):l==="unchanged"&&console.log("\u2713 CLS hook already current in .git/hooks/post-commit")}catch{}if(u==="claude")try{const l=await ct(m,d);if(l.settings==="skipped")console.log(`\u26A0\uFE0F .claude/settings.json ${l.grund??"is not valid JSON"} \u2014 left untouched, Ambient Recall hooks not wired`);else{const i=l.scripts==="written"?"\u2705 Written":l.scripts==="upgraded"?`\u2705 Upgraded (\u2192 ${lt})`:"\u2713 Unchanged";console.log(`${i}: .claude/hooks/ (Ambient Recall \u2014 session briefing, per-prompt recall, file briefing, auto-learn)`),l.settings==="written"?console.log("\u2705 Written: .claude/settings.json (Ambient Recall hooks wired)"):l.settings==="merged"?console.log("\u2705 Merged: .claude/settings.json (Ambient Recall hooks wired)"):console.log("\u2713 Ambient Recall hooks already wired in .claude/settings.json")}}catch{}(u==="cursor"||u==="copilot"||u==="codex"||u==="gemini")&&await ye(u,m,d,"");const b=((Date.now()-e)/1e3).toFixed(1);console.log(`
225
+ \u{1F9E0} Cachly AI Brain configured for ${u==="claude"?"Claude Code":u}! (${b}s)`),console.log(u==="codex"||u==="gemini"?` Start ${u} in this folder and trust it when asked \u2014 the \`cachly\` MCP tools will appear.`:" Restart your editor \u2014 the `cachly` MCP tools will appear."),console.log(" Re-run `init` anytime \u2014 it's idempotent (only writes what changed)."),console.log(`
226
226
  \u{1F4DB} Add a live badge to your README:`),console.log(` npx @cachly-dev/mcp-server@latest badge
227
- `),process.exit(0)}if(process.argv[2]==="status"){const e=ne(),t=F();(!e||!t)&&(console.log(`
227
+ `),process.exit(0)}if(process.argv[2]==="status"){const e=ne(),t=W();(!e||!t)&&(console.log(`
228
228
  \u26A0\uFE0F No cachly key or Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot
229
- `),process.exit(1));try{const[s,n]=await Promise.all([fetch(`${x}/api/v1/instances/${t}/memory`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)}),fetch(`${x}/api/v1/referral/me`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)})]);if(!s.ok)throw new Error(`stats HTTP ${s.status}`);const o=await s.json(),a=n.ok?await n.json():null,r=o.lesson_count??0,c=o.total_recall_count??0,u=Math.round(o.iq_boost_pct??0),g=o.team_authors??[],d=a?.referral_count??0,m=a?.url??"",v=r===0?"Intern \u{1F331}":r<10?"Junior Dev \u{1F527}":r<30?"Mid Dev \u26A1":r<60?"Senior Dev \u{1F9E0}":r<100?"Staff Eng \u{1F680}":"Principal Eng \u{1F3C6}",w=r>0?"\x1B[32m\u25CF\x1B[0m":"\x1B[33m\u25CF\x1B[0m";if(console.log(""),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log(`\u2502 ${w} \x1B[1mBrain status\x1B[0m \xB7 instance ${t.slice(0,8)}... \u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Lessons : \x1B[33m${String(r).padEnd(8)}\x1B[0m Level : \x1B[32m${v.padEnd(18)}\x1B[0m\u2502`),console.log(`\u2502 Recalls : \x1B[36m${String(c).padEnd(8)}\x1B[0m Quality score: \x1B[32m${String(u).padEnd(3)}%\x1B[0m \u2502`),g.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");const b=g.slice(0,4).join(", ");console.log(`\u2502 \x1B[36m\u{1F465} Team Brain\x1B[0m \xB7 ${String(g.length).padEnd(2)} developer${g.length===1?" ":"s"} sharing lessons${" ".repeat(Math.max(0,19-b.length))} \u2502`),console.log(`\u2502 ${b.slice(0,56).padEnd(56)} \u2502`)}if(m){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");const b=`${m.slice(0,44)}${m.length>44?"\u2026":""}`;console.log(`\u2502 \x1B[35m\u{1F517} Invite link\x1B[0m \xB7 ${d>0?`\x1B[32m${d} joined\x1B[0m`:"share to grow your team"}${" ".repeat(Math.max(0,35-String(d).length))} \u2502`),console.log(`\u2502 \x1B[2m${b.padEnd(56)}\x1B[0m \u2502`)}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log(""),r===0&&(console.log(" \x1B[33m\u{1F4A1} No lessons yet.\x1B[0m Run a session with cachly connected to start learning."),console.log(""))}catch(s){console.log(`
229
+ `),process.exit(1));try{const[s,n]=await Promise.all([fetch(`${x}/api/v1/instances/${t}/memory`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)}),fetch(`${x}/api/v1/referral/me`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(8e3)})]);if(!s.ok)throw new Error(`stats HTTP ${s.status}`);const o=await s.json(),a=n.ok?await n.json():null,c=o.lesson_count??0,r=o.total_recall_count??0,d=Math.round(o.iq_boost_pct??0),g=o.team_authors??[],u=a?.referral_count??0,m=a?.url??"",v=c===0?"Intern \u{1F331}":c<10?"Junior Dev \u{1F527}":c<30?"Mid Dev \u26A1":c<60?"Senior Dev \u{1F9E0}":c<100?"Staff Eng \u{1F680}":"Principal Eng \u{1F3C6}",w=c>0?"\x1B[32m\u25CF\x1B[0m":"\x1B[33m\u25CF\x1B[0m";if(console.log(""),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log(`\u2502 ${w} \x1B[1mBrain status\x1B[0m \xB7 instance ${t.slice(0,8)}... \u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Lessons : \x1B[33m${String(c).padEnd(8)}\x1B[0m Level : \x1B[32m${v.padEnd(18)}\x1B[0m\u2502`),console.log(`\u2502 Recalls : \x1B[36m${String(r).padEnd(8)}\x1B[0m Quality score: \x1B[32m${String(d).padEnd(3)}%\x1B[0m \u2502`),g.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");const b=g.slice(0,4).join(", ");console.log(`\u2502 \x1B[36m\u{1F465} Team Brain\x1B[0m \xB7 ${String(g.length).padEnd(2)} developer${g.length===1?" ":"s"} sharing lessons${" ".repeat(Math.max(0,19-b.length))} \u2502`),console.log(`\u2502 ${b.slice(0,56).padEnd(56)} \u2502`)}if(m){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");const b=`${m.slice(0,44)}${m.length>44?"\u2026":""}`;console.log(`\u2502 \x1B[35m\u{1F517} Invite link\x1B[0m \xB7 ${u>0?`\x1B[32m${u} joined\x1B[0m`:"share to grow your team"}${" ".repeat(Math.max(0,35-String(u).length))} \u2502`),console.log(`\u2502 \x1B[2m${b.padEnd(56)}\x1B[0m \u2502`)}console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log(""),c===0&&(console.log(" \x1B[33m\u{1F4A1} No lessons yet.\x1B[0m Run a session with cachly connected to start learning."),console.log(""))}catch(s){console.log(`
230
230
  \u274C Could not fetch status: ${s.message}
231
- `),process.exit(1)}process.exit(0)}if(process.argv[2]==="health"){const{existsSync:e}=await import("node:fs"),{readFile:t}=await import("node:fs/promises"),{resolve:s}=await import("node:path"),n=process.cwd();let o=0,a=0;const r=l=>{console.log(` \u2705 ${l}`),o++},c=l=>{console.log(` \u26A0\uFE0F ${l}`)},u=l=>{console.log(` \u274C ${l}`),a++};console.log(`
231
+ `),process.exit(1)}process.exit(0)}if(process.argv[2]==="health"){const{existsSync:e}=await import("node:fs"),{readFile:t}=await import("node:fs/promises"),{resolve:s}=await import("node:path"),n=process.cwd();let o=0,a=0;const c=l=>{console.log(` \u2705 ${l}`),o++},r=l=>{console.log(` \u26A0\uFE0F ${l}`)},d=l=>{console.log(` \u274C ${l}`),a++};console.log(`
232
232
  \u{1F9E0} cachly health check
233
- `),console.log("\u{1F511} Auth token");const g=ne();if(!g)u("No cachly key found (environment or ~/.cachly/credentials.json) \u2014 run: npx @cachly-dev/mcp-server@latest autopilot");else if(g.startsWith("cky_"))r("Long-lived API key set (cky_\u2026) \u2014 no client-side expiry");else try{const l=g.split(".");if(l.length!==3)throw new Error("not a JWT");const i=JSON.parse(Buffer.from(l[1],"base64url").toString("utf-8")),p=i.exp?i.exp*1e3:null,h=p?Math.floor((p-Date.now())/6e4):null;p&&p<Date.now()?u(`JWT expired ${Math.abs(h)} minute(s) ago \u2014 get a new one: ${R("/setup-ai","health")}`):h!==null&&h<30?c(`JWT expires in ${h} minute(s) \u2014 refresh soon at ${R("/setup-ai","health")}`):r(`JWT valid${h!==null?` (expires in ${Math.floor(h/60)}h ${h%60}m)`:""}`)}catch{u("CACHLY_JWT format invalid (expected a cky_ API key or a 3-part JWT)")}console.log(`
234
- \u{1F310} Brain API`);const d=process.env.CACHLY_API_URL??"https://api.cachly.dev";try{const l=await fetch(`${d}/health`,{signal:AbortSignal.timeout(5e3)});if(l.ok){const i=await l.json();r(`${d} reachable (status: ${i.status??"ok"})`)}else l.status===401||l.status===403?r(`${d} reachable (auth required \u2014 expected)`):u(`${d}/health returned HTTP ${l.status}`)}catch(l){u(`${d} unreachable \u2014 ${l.message}`)}console.log(`
235
- \u{1F9E0} Brain instance`);const m=F();if(!m)c("No Brain instance found (environment or ~/.cachly/credentials.json) \u2014 will auto-resolve on first tool call");else if(g)try{const l=await fetch(`${d}/api/v1/instances/${m}`,{headers:{Authorization:`Bearer ${g}`,Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(l.ok){const i=await l.json();if(i.status==="running")if(r(`Instance "${i.name}" (${m.slice(0,8)}\u2026) is running`),console.log(`
236
- \u{1F50C} Redis connectivity`),i.host&&i.port)try{let p,h=i.tls_enabled!==!1;try{const j=await fetch(`${d}/api/v1/instances/${m}/connection`,{headers:{Authorization:`Bearer ${g}`,Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(j.ok){const A=await j.json();p=A.password,h=A.tls_enabled!==!1}}catch{}const E=new Ze({host:i.host,port:i.port,password:p,...h?{tls:{}}:{},lazyConnect:!0,connectTimeout:5e3,retryStrategy:()=>null});await E.connect();const O=await E.ping();E.disconnect(),O==="PONG"?r(`Redis PING \u2192 PONG (${i.host}:${i.port})`):c(`Redis responded but not PONG: ${O}`)}catch(p){u(`Redis unreachable \u2014 ${p.message}`)}else c("Instance has no host/port yet");else c(`Instance "${i.name}" status: ${i.status}`)}else u(`Instance ${m.slice(0,8)}\u2026 not found (HTTP ${l.status})`)}catch(l){u(`Could not check instance \u2014 ${l.message}`)}console.log(`
237
- \u{1F6E0} Editor configs (project dir)`);const v=[{editor:"Claude Code",path:".mcp.json"},{editor:"Cursor",path:".cursor/mcp.json"},{editor:"Windsurf",path:".windsurf/mcp.json"},{editor:"Copilot / Cline",path:".vscode/mcp.json"},{editor:"Zed",path:".zed/settings.json"},{editor:"Continue.dev",path:".continue/config.json"}];let w=0;for(const{editor:l,path:i}of v){const p=s(n,i);if(e(p))try{const h=await t(p,"utf-8");h.includes("@cachly-dev/mcp-server")||h.includes("cachly")?(r(`${l}: ${i}`),w++):c(`${l}: ${i} exists but cachly not found inside`)}catch{c(`${l}: ${i} exists but could not read`)}}w===0&&u("No editor MCP configs found \u2014 run: npx @cachly-dev/mcp-server@latest autopilot"),console.log(`
238
- \u{1FA9D} Git hook (ambient learning)`);const b=s(n,".git","hooks","post-commit");if(!e(s(n,".git")))c("Not in a git repository \u2014 skip");else if(e(b))try{(await t(b,"utf-8")).includes("cachly")?r(".git/hooks/post-commit (cachly CLS hook present)"):c(".git/hooks/post-commit exists but cachly hook not found \u2014 run setup to add it")}catch{c(".git/hooks/post-commit exists but could not read")}else c(".git/hooks/post-commit not found \u2014 run: npx @cachly-dev/mcp-server@latest autopilot");console.log(`
239
- \u{1F9EC} Embedding provider (semantic search)`);{const l=[["OPENAI_API_KEY","openai"],["GEMINI_API_KEY","gemini"],["MISTRAL_API_KEY","mistral"],["COHERE_API_KEY","cohere"],["OLLAMA_BASE_URL","ollama"]],i=(process.env.CACHLY_EMBED_PROVIDER??"").toLowerCase();if(i&&i!=="cachly"){const p=l.find(([,h])=>h===i)?.[0];p&&process.env[p]?r(`BYOK: ${i} (key present in ${p})`):c(`CACHLY_EMBED_PROVIDER=${i} but its key env var is not set \u2014 semantic search will fail`)}else{ot==="ollama"?r("Local Ollama (OLLAMA_BASE_URL) \u2014 text stays on your machine"):ot==="cachly"?r("Server-side embeddings (cachly, EU) \u2014 no key needed, uses your JWT"):c("No embedding provider active \u2014 sign in (CACHLY_JWT) for EU-hosted embeddings; search runs on words until then");for(const[p,h]of l)h!=="ollama"&&process.env[p]&&r(`${p} is set but not used \u2014 ${h} runs only if you name it with CACHLY_EMBED_PROVIDER=${h}`)}}console.log(`
233
+ `),console.log("\u{1F511} Auth token");const g=ne();if(!g)d("No cachly key found (environment or ~/.cachly/credentials.json) \u2014 run: npx @cachly-dev/mcp-server@latest autopilot");else if(g.startsWith("cky_"))c("Long-lived API key set (cky_\u2026) \u2014 no client-side expiry");else try{const l=g.split(".");if(l.length!==3)throw new Error("not a JWT");const i=JSON.parse(Buffer.from(l[1],"base64url").toString("utf-8")),p=i.exp?i.exp*1e3:null,h=p?Math.floor((p-Date.now())/6e4):null;p&&p<Date.now()?d(`JWT expired ${Math.abs(h)} minute(s) ago \u2014 get a new one: ${R("/setup-ai","health")}`):h!==null&&h<30?r(`JWT expires in ${h} minute(s) \u2014 refresh soon at ${R("/setup-ai","health")}`):c(`JWT valid${h!==null?` (expires in ${Math.floor(h/60)}h ${h%60}m)`:""}`)}catch{d("CACHLY_JWT format invalid (expected a cky_ API key or a 3-part JWT)")}console.log(`
234
+ \u{1F310} Brain API`);const u=process.env.CACHLY_API_URL??"https://api.cachly.dev";try{const l=await fetch(`${u}/health`,{signal:AbortSignal.timeout(5e3)});if(l.ok){const i=await l.json();c(`${u} reachable (status: ${i.status??"ok"})`)}else l.status===401||l.status===403?c(`${u} reachable (auth required \u2014 expected)`):d(`${u}/health returned HTTP ${l.status}`)}catch(l){d(`${u} unreachable \u2014 ${l.message}`)}console.log(`
235
+ \u{1F9E0} Brain instance`);const m=W();if(!m)r("No Brain instance found (environment or ~/.cachly/credentials.json) \u2014 will auto-resolve on first tool call");else if(g)try{const l=await fetch(`${u}/api/v1/instances/${m}`,{headers:{Authorization:`Bearer ${g}`,Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(l.ok){const i=await l.json();if(i.status==="running")if(c(`Instance "${i.name}" (${m.slice(0,8)}\u2026) is running`),console.log(`
236
+ \u{1F50C} Redis connectivity`),i.host&&i.port)try{let p,h;try{const A=await fetch(`${u}/api/v1/instances/${m}/connection`,{headers:{Authorization:`Bearer ${g}`,Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(A.ok){const C=await A.json();p=C.password,h=C}}catch{}const T=vt({host:i.host,port:i.port,tls_enabled:i.tls_enabled},h),O=new Ze({host:T.host,port:T.port,password:p,...T.tls?{tls:T.tls}:{},lazyConnect:!0,connectTimeout:5e3,retryStrategy:()=>null});await O.connect();const j=await O.ping();O.disconnect(),j==="PONG"?c(`Redis PING \u2192 PONG (${T.host}:${T.port}, ${T.art==="klartext"?"unencrypted":"TLS"})`):r(`Redis responded but not PONG: ${j}`)}catch(p){d(`Redis unreachable \u2014 ${p.message}`)}else r("Instance has no host/port yet");else r(`Instance "${i.name}" status: ${i.status}`)}else d(`Instance ${m.slice(0,8)}\u2026 not found (HTTP ${l.status})`)}catch(l){d(`Could not check instance \u2014 ${l.message}`)}console.log(`
237
+ \u{1F6E0} Editor configs (project dir)`);const v=[{editor:"Claude Code",path:".mcp.json"},{editor:"Cursor",path:".cursor/mcp.json"},{editor:"Windsurf",path:".windsurf/mcp.json"},{editor:"Copilot / Cline",path:".vscode/mcp.json"},{editor:"Zed",path:".zed/settings.json"},{editor:"Continue.dev",path:".continue/config.json"}];let w=0;for(const{editor:l,path:i}of v){const p=s(n,i);if(e(p))try{const h=await t(p,"utf-8");h.includes("@cachly-dev/mcp-server")||h.includes("cachly")?(c(`${l}: ${i}`),w++):r(`${l}: ${i} exists but cachly not found inside`)}catch{r(`${l}: ${i} exists but could not read`)}}w===0&&d("No editor MCP configs found \u2014 run: npx @cachly-dev/mcp-server@latest autopilot"),console.log(`
238
+ \u{1FA9D} Git hook (ambient learning)`);const b=s(n,".git","hooks","post-commit");if(!e(s(n,".git")))r("Not in a git repository \u2014 skip");else if(e(b))try{(await t(b,"utf-8")).includes("cachly")?c(".git/hooks/post-commit (cachly CLS hook present)"):r(".git/hooks/post-commit exists but cachly hook not found \u2014 run setup to add it")}catch{r(".git/hooks/post-commit exists but could not read")}else r(".git/hooks/post-commit not found \u2014 run: npx @cachly-dev/mcp-server@latest autopilot");console.log(`
239
+ \u{1F9EC} Embedding provider (semantic search)`);{const l=[["OPENAI_API_KEY","openai"],["GEMINI_API_KEY","gemini"],["MISTRAL_API_KEY","mistral"],["COHERE_API_KEY","cohere"],["OLLAMA_BASE_URL","ollama"]],i=(process.env.CACHLY_EMBED_PROVIDER??"").toLowerCase();if(i&&i!=="cachly"){const p=l.find(([,h])=>h===i)?.[0];p&&process.env[p]?c(`BYOK: ${i} (key present in ${p})`):r(`CACHLY_EMBED_PROVIDER=${i} but its key env var is not set \u2014 semantic search will fail`)}else{ot==="ollama"?c("Local Ollama (OLLAMA_BASE_URL) \u2014 text stays on your machine"):ot==="cachly"?c("Server-side embeddings (cachly, EU) \u2014 no key needed, uses your JWT"):r("No embedding provider active \u2014 sign in (CACHLY_JWT) for EU-hosted embeddings; search runs on words until then");for(const[p,h]of l)h!=="ollama"&&process.env[p]&&c(`${p} is set but not used \u2014 ${h} runs only if you name it with CACHLY_EMBED_PROVIDER=${h}`)}}console.log(`
240
240
  ${"\u2500".repeat(40)}`),a===0?console.log(`\u2705 All checks passed (${o} ok)
241
241
  `):(console.log(`\u274C ${a} check(s) failed, ${o} passed
242
242
  `),console.log(`\u{1F4A1} Fix issues with: npx @cachly-dev/mcp-server@latest autopilot
243
- `),process.exit(1)),process.exit(0)}if(process.argv[2]==="claim"){const{readFile:e,writeFile:t}=await import("node:fs/promises"),{existsSync:s}=await import("node:fs"),{resolve:n}=await import("node:path"),{homedir:o}=await import("node:os"),a=i=>{const p=process.argv.indexOf(`--${i}`);return p!==-1?process.argv[p+1]:void 0};x=(a("api-url")??"https://api.cachly.dev").replace(/\/+$/,"");const r=(a("auth-url")??mt).replace(/\/+$/,"");console.log(`
243
+ `),process.exit(1)),process.exit(0)}if(process.argv[2]==="claim"){const{readFile:e,writeFile:t}=await import("node:fs/promises"),{existsSync:s}=await import("node:fs"),{resolve:n}=await import("node:path"),{homedir:o}=await import("node:os"),a=i=>{const p=process.argv.indexOf(`--${i}`);return p!==-1?process.argv[p+1]:void 0};x=(a("api-url")??"https://api.cachly.dev").replace(/\/+$/,"");const c=(a("auth-url")??mt).replace(/\/+$/,"");console.log(`
244
244
  \u{1F9E0} cachly \u2014 keep your test Brain in your own account
245
- `),(x!=="https://api.cachly.dev"||r!==mt)&&console.log(`\u26A0\uFE0F Not the cachly servers: API ${x}, sign-in ${r}
246
- `);const c=mn({argument:a("key"),credentials:Le()});c||(console.log("No test key (cky_trial_\u2026) was found in ~/.cachly/credentials.json."),console.log("If you already use your own cachly account, there is nothing to claim."),console.log(`Otherwise pass the key: npx @cachly-dev/mcp-server@latest claim --key cky_trial_\u2026
247
- `),process.exit(1));const u=c.schluessel,g={argument:"--key",credentials:"~/.cachly/credentials.json"}[c.quelle];console.log(`Test key: ${u.slice(0,14)}\u2026 (from ${g})
248
- `);let d="";try{console.log(`Step 1: Sign in to your cachly account
249
- `);const i=await gn(fetch,r);console.log(` Code: \x1B[1;33m${i.userCode}\x1B[0m`),console.log(" Open this URL and confirm the code:"),console.log(`${i.adresse}
245
+ `),(x!=="https://api.cachly.dev"||c!==mt)&&console.log(`\u26A0\uFE0F Not the cachly servers: API ${x}, sign-in ${c}
246
+ `);const r=gn({argument:a("key"),credentials:Le()});r||(console.log("No test key (cky_trial_\u2026) was found in ~/.cachly/credentials.json."),console.log("If you already use your own cachly account, there is nothing to claim."),console.log(`Otherwise pass the key: npx @cachly-dev/mcp-server@latest claim --key cky_trial_\u2026
247
+ `),process.exit(1));const d=r.schluessel,g={argument:"--key",credentials:"~/.cachly/credentials.json"}[r.quelle];console.log(`Test key: ${d.slice(0,14)}\u2026 (from ${g})
248
+ `);let u="";try{console.log(`Step 1: Sign in to your cachly account
249
+ `);const i=await fn(fetch,c);console.log(` Code: \x1B[1;33m${i.userCode}\x1B[0m`),console.log(" Open this URL and confirm the code:"),console.log(`${i.adresse}
250
250
  `),ce(i.adresse,(p,h)=>{p||console.log(`
251
- \u2139\uFE0F No browser could be opened here (${h??"unknown"}) \u2014 please open the URL yourself.`)}),process.stdout.write(" Waiting for sign-in"),d=await fn(fetch,i,{basis:r,puls:()=>process.stdout.write(".")}),console.log(` \x1B[32m\u2713\x1B[0m
251
+ \u2139\uFE0F No browser could be opened here (${h??"unknown"}) \u2014 please open the URL yourself.`)}),process.stdout.write(" Waiting for sign-in"),u=await hn(fetch,i,{basis:c,puls:()=>process.stdout.write(".")}),console.log(` \x1B[32m\u2713\x1B[0m
252
252
  `)}catch(i){console.error(`
253
253
 
254
254
  ${i.message}. Nothing was changed.
255
- `),process.exit(1)}process.stdout.write("Step 2: Moving the test Brain into your account (it restarts once, up to a minute)\u2026");let m;try{m=await hn(fetch,x,d,u,"mcp",`cachly-mcp/${D}`),console.log(` \x1B[32m\u2713\x1B[0m
255
+ `),process.exit(1)}process.stdout.write("Step 2: Moving the test Brain into your account (it restarts once, up to a minute)\u2026");let m;try{m=await yn(fetch,x,u,d,"mcp",`cachly-mcp/${D}`),console.log(` \x1B[32m\u2713\x1B[0m
256
256
  `)}catch(i){console.error(`
257
257
 
258
- ${vn(i)}
259
- `),process.exit(1)}y=m.apiKey,X(m.apiKey),ut(m.instanceId,{apiKey:m.apiKey}),await ue(m.apiKey),await pe(m.instanceId);const v=o(),w=new Set([...Object.values(me).map(i=>n(process.cwd(),i)),n(v,".claude.json"),n(v,".claude","mcp.json"),n(v,".cursor","mcp.json"),n(v,".codeium","windsurf","mcp_config.json")]);let b=0;for(const i of w)if(s(i))try{const p=wn(await e(i,"utf-8"),u,m.apiKey);p.ersetzt&&(await t(i,p.text,"utf-8"),b++)}catch{}const l=await yn(fetch,x,m.apiKey,m.instanceId);console.log(bn(m,l)),console.log(`
258
+ ${wn(i)}
259
+ `),process.exit(1)}y=m.apiKey,X(m.apiKey),ut(m.instanceId,{apiKey:m.apiKey}),await ue(m.apiKey),await pe(m.instanceId);const v=o(),w=new Set([...Object.values(me).map(i=>n(process.cwd(),i)),n(v,".claude.json"),n(v,".claude","mcp.json"),n(v,".cursor","mcp.json"),n(v,".codeium","windsurf","mcp_config.json")]);let b=0;for(const i of w)if(s(i))try{const p=xn(await e(i,"utf-8"),d,m.apiKey);p.ersetzt&&(await t(i,p.text,"utf-8"),b++)}catch{}const l=await bn(fetch,x,m.apiKey,m.instanceId);console.log(vn(m,l)),console.log(`
260
260
  New key stored in ~/.cachly/credentials.json${b?` and in ${b} editor config file(s) that held the test key`:""}.`),console.log(`Restart your editor (or reload its MCP servers) so it uses the new key.
261
- `),process.exit(0)}const $e=process.argv[2]==="autopilot";if(process.argv[2]==="autosetup"||process.argv[2]==="setup"||$e){const{writeFile:e,mkdir:t,readFile:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o,dirname:a}=await import("node:path"),{createInterface:r}=await import("node:readline"),c=Date.now(),u=$e?"autopilot":"setup",g=process.argv.indexOf("--api-url");g!==-1&&process.argv[g+1]&&(x=process.argv[g+1].replace(/\/+$/,""),console.log(`\u2139\uFE0F Using self-hosted backend: ${x}
262
- `)),S("setup_started");const d=process.stdin.isTTY===!0,m=$e||process.argv.includes("--yes")||process.argv.includes("-y")||!d;$e?console.log(`\u{1F916} Autopilot \u2014 one-command setup (auth \u2192 instance \u2192 configs \u2192 Brain), zero prompts.
263
- `):!d&&!process.argv.includes("--yes")&&!process.argv.includes("-y")&&console.log(`\u2139\uFE0F Non-interactive terminal detected \u2014 running in automatic mode (no prompts).
264
- `);const v=r({input:process.stdin,output:process.stdout}),w=(f,_="")=>m?(console.log(`${f}${_}`),Promise.resolve(_)):new Promise(I=>v.question(f,U=>I(U.trim()||_)));console.log(`
261
+ `),process.exit(0)}const $e=process.argv[2]==="autopilot";if(process.argv[2]==="autosetup"||process.argv[2]==="setup"||$e){const{writeFile:e,mkdir:t,readFile:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o,dirname:a}=await import("node:path"),{createInterface:c}=await import("node:readline"),r=Date.now(),d=$e?"autopilot":"setup",g=process.argv.indexOf("--api-url");g!==-1&&process.argv[g+1]&&(x=process.argv[g+1].replace(/\/+$/,""),console.log(`\u2139\uFE0F Using self-hosted backend: ${x}
262
+ `)),S("setup_started");const u=process.stdin.isTTY===!0,m=$e||process.argv.includes("--yes")||process.argv.includes("-y")||!u;$e?console.log(`\u{1F916} Autopilot \u2014 one-command setup (auth \u2192 instance \u2192 configs \u2192 Brain), zero prompts.
263
+ `):!u&&!process.argv.includes("--yes")&&!process.argv.includes("-y")&&console.log(`\u2139\uFE0F Non-interactive terminal detected \u2014 running in automatic mode (no prompts).
264
+ `);const v=c({input:process.stdin,output:process.stdout}),w=(f,_="")=>m?(console.log(`${f}${_}`),Promise.resolve(_)):new Promise(I=>v.question(f,U=>I(U.trim()||_)));console.log(`
265
265
  \u{1F9E0} cachly AI Brain \u2014 Setup`),console.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
266
266
  `);let b=process.env.CACHLY_JWT??"";if(b)console.log(`\u2713 Using token from CACHLY_JWT env var
267
267
  `);else{console.log(`Step 1: Sign in to cachly (free, no credit card)
268
- `),S("setup_auth_started");let f="",_="",I="",U=5e3,z=!1,te="cachly";try{const q=await fetch(`${x}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(8e3)});if(q.ok){const B=await q.json();f=B.device_code,_=B.user_code;const M=B.verification_uri||R("/device",u);I=`${M}${M.includes("?")?"&":"?"}code=${encodeURIComponent(_)}`,U=(B.interval??5)*1e3,z=!!f}}catch{}if(!z)try{const B=await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/auth/device",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"client_id=cachly-cli&scope=openid",signal:AbortSignal.timeout(8e3)});if(B.ok){const M=await B.json();f=M.device_code,_=M.user_code,I=M.verification_uri_complete,U=(M.interval??5)*1e3,z=!0,te="keycloak"}}catch{}if(z&&f){console.log(` Code: \x1B[1;33m${_}\x1B[0m`),console.log(" Open this URL and confirm the code:"),console.log(`${I}
268
+ `),S("setup_auth_started");let f="",_="",I="",U=5e3,z=!1,te="cachly";try{const q=await fetch(`${x}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(8e3)});if(q.ok){const B=await q.json();f=B.device_code,_=B.user_code;const M=B.verification_uri||R("/device",d);I=`${M}${M.includes("?")?"&":"?"}code=${encodeURIComponent(_)}`,U=(B.interval??5)*1e3,z=!!f}}catch{}if(!z)try{const B=await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/auth/device",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"client_id=cachly-cli&scope=openid",signal:AbortSignal.timeout(8e3)});if(B.ok){const M=await B.json();f=M.device_code,_=M.user_code,I=M.verification_uri_complete,U=(M.interval??5)*1e3,z=!0,te="keycloak"}}catch{}if(z&&f){console.log(` Code: \x1B[1;33m${_}\x1B[0m`),console.log(" Open this URL and confirm the code:"),console.log(`${I}
269
269
  `),ce(I,(B,M)=>{if(B){S("device_browser_opened",{stelle:"setup"});return}S("device_browser_failed",{reason:M??"unknown",stelle:"setup"}),console.log(` \u2139\uFE0F No browser could be opened here (${M??"unknown"}) \u2014 please open the URL yourself.
270
270
  `)}),process.stdout.write(" Waiting for authorization");const q=Date.now()+600*1e3;for(;Date.now()<q;){await new Promise(B=>setTimeout(B,U)),process.stdout.write(".");try{let B=null;if(te==="cachly")try{const M=await fetch(`${x}/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:f}),signal:AbortSignal.timeout(8e3)});M.status<500&&(B=await M.json())}catch{}else{const M="https://auth.cachly.dev/realms/cachly/protocol/openid-connect";try{B=await(await fetch(`${M}/token`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`client_id=cachly-cli&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=${f}`,signal:AbortSignal.timeout(8e3)})).json()}catch{}}if(B?.access_token){b=B.access_token,console.log(` \x1B[32m\u2713 Authorized!\x1B[0m
271
271
  `),S("setup_auth_completed"),S("device_flow_completed");break}B?.error==="slow_down"?U=Math.min(U+2e3,15e3):B?.error&&B.error!=="authorization_pending"&&(S("device_flow_failed",{reason:B.error}),console.error(`
272
272
  Auth error: ${B.error}. Aborting.
273
273
  `),v.close(),process.exit(1))}catch{}}b||(S("device_flow_failed",{reason:"timeout"}),console.error(`
274
274
  Timed out waiting for authorization. Aborting.
275
- `),v.close(),process.exit(1)),console.log("")}else{S("device_flow_failed",{reason:"device_flow_unavailable"});const q=R("/setup-ai",u);console.log(` \u26A0\uFE0F Could not start automatic sign-in. Opening browser for web sign-in...
275
+ `),v.close(),process.exit(1)),console.log("")}else{S("device_flow_failed",{reason:"device_flow_unavailable"});const q=R("/setup-ai",d);console.log(` \u26A0\uFE0F Could not start automatic sign-in. Opening browser for web sign-in...
276
276
  `),console.log(` URL: \x1B[36m${q}\x1B[0m`),console.log(" 1. Sign up / log in at the URL above"),console.log(" 2. Go to Settings \u2192 API Keys \u2192 Create new key"),console.log(` 3. Copy the key (starts with cky_live_...)
277
277
  `),ce(q),m?(S("device_flow_failed",{reason:"non_interactive_no_key"}),console.error(`
278
278
  \u26A0\uFE0F This terminal is non-interactive, so the key cannot be pasted here.`),console.error(` Get your key at the URL above, then set it and re-run setup:
@@ -284,16 +284,16 @@ API key is required. Aborting.
284
284
  `)}catch{console.log(` (skipped)
285
285
  `)}}process.stdout.write("\u23F3 Fetching your instances...");let l=[];try{const f=await fetch(`${x}/api/v1/instances`,{headers:{Authorization:`Bearer ${b}`}});if(!f.ok)throw new Error(`HTTP ${f.status}`);l=((await f.json()).data??[]).filter(I=>I.status==="running")}catch(f){const _=f.message;console.error(`
286
286
 
287
- Failed to fetch instances: ${_}`),_.includes("401")&&(console.error(`Token rejected. Get a valid token at ${R("/setup-ai",u)}
288
- `),ce(R("/setup-ai",u))),v.close(),process.exit(1)}if(console.log(` found ${l.length}
287
+ Failed to fetch instances: ${_}`),_.includes("401")&&(console.error(`Token rejected. Get a valid token at ${R("/setup-ai",d)}
288
+ `),ce(R("/setup-ai",d))),v.close(),process.exit(1)}if(console.log(` found ${l.length}
289
289
  `),l.length===0){process.stdout.write("\u23F3 Creating your free Brain instance...");try{const f=await fetch(`${x}/api/v1/instances/auto`,{method:"POST",headers:{Authorization:`Bearer ${b}`,"Content-Type":"application/json"}});if(!f.ok)throw new Error(`HTTP ${f.status}`);const _=await f.json();if(_.instance)l=[_.instance];else if(_.instance_id){const I=_.instance_id;console.log(` \u2713 created (${I.slice(0,8)}\u2026)
290
290
  `),process.stdout.write("\u23F3 Waiting for instance to start");for(let U=0;U<45;U++){await new Promise(z=>setTimeout(z,3e3)),process.stdout.write(".");try{const z=await fetch(`${x}/api/v1/instances/${I}`,{headers:{Authorization:`Bearer ${b}`}});if(z.ok){const te=await z.json();if(te.status==="running"){l=[te];break}}}catch{}}console.log("")}}catch(f){console.log(` failed: ${f.message}
291
291
  `)}l.length===0&&(console.error(`
292
- Could not create an instance automatically. Opening ${R("/instances",u)} \u2026
293
- `),ce(R("/instances",u)),v.close(),process.exit(1))}const i=l[0];l.length>1&&(console.log(`\u2139\uFE0F Multiple instances found \u2014 using most recent: ${i.name}`),console.log(` (Run with --instance-id <id> to use a different one)
292
+ Could not create an instance automatically. Opening ${R("/instances",d)} \u2026
293
+ `),ce(R("/instances",d)),v.close(),process.exit(1))}const i=l[0];l.length>1&&(console.log(`\u2139\uFE0F Multiple instances found \u2014 using most recent: ${i.name}`),console.log(` (Run with --instance-id <id> to use a different one)
294
294
  `)),console.log(`\u2713 Instance: ${i.name} (${i.id.slice(0,8)}\u2026)
295
- `),S("setup_instance_ready",{instance_id:i.id});const p=process.cwd(),h=[],{homedir:E}=await import("node:os"),O=E();h.push("claude"),n(o(p,".cursor"))&&h.push("cursor"),n(o(p,".windsurf"))&&h.push("windsurf"),n(o(p,".vscode"))&&h.push("copilot"),n(o(p,".continue"))&&h.push("continue");const j=process.platform==="darwin"?o(O,"Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev"):o(O,".vscode/extensions");(n(j)&&!h.includes("copilot")||n(j))&&h.push("cline");const A=process.platform==="darwin"?o(O,"Library/Application Support/Zed"):o(O,".config/zed");n(A)&&h.push("zed");const C=f=>({claude:"Claude Code",cursor:"Cursor",windsurf:"Windsurf",copilot:"GitHub Copilot",continue:"Continue.dev",cline:"Cline (VSCode)",zed:"Zed"})[f]??f,T=h;console.log(`Step 3: Configuring for: ${T.map(C).join(", ")}
296
- `);const{existsSync:$}=await import("node:fs"),k=[];let L=0;X(b);for(const f of T){const _=me[f]??".mcp.json",I=o(p,_);try{await t(a(I),{recursive:!0});const U=$(I),z=await Ot(I,b,i.id,f,{readFile:s,existsSync:$});await e(I,z,"utf-8"),console.log(`\u2705 ${U?"Updated":"Written"}: ${_}`),L++}catch(U){const z=U.message;console.log(`\u26A0\uFE0F Could not write ${_}: ${z}`),console.log(" Fix permissions or run with sudo, then re-run setup."),k.push({file:_,reason:z})}}const Y=o(O,".claude","mcp.json");try{await t(a(Y),{recursive:!0});let f={};if(n(Y))try{f=JSON.parse(await s(Y,"utf-8"))}catch{}f.mcpServers??={},f.mcpServers.cachly={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(b,i.id,{includeApiKey:!0})},await e(Y,JSON.stringify(f,null,2),"utf-8"),console.log("\u2705 Written: ~/.claude/mcp.json (global \u2014 works in every project)"),L++}catch(f){const _=f.message;console.log(`\u26A0\uFE0F Could not write ~/.claude/mcp.json: ${_}`),k.push({file:"~/.claude/mcp.json",reason:_})}const K=await Pt(p,i.id);for(const[f,_]of Object.entries(K))console.log(`${_==="updated"?"\u2705 Updated":_==="appended"?"\u2705 Appended to":"\u2705 Written"}: ${f}`);y=b;let be=0;if(n(o(p,".git"))){process.stdout.write("\u23F3 Bootstrapping Brain from git history (~10s)...");try{const f=await J("brain_from_git",{instance_id:i.id,repo_path:p,limit:100}),_=f.match(/Ingested: \*\*(\d+)\*\*/);be=_?parseInt(_[1],10):0,console.log(` \u2713 ${be} lesson${be===1?"":"s"} extracted from git history`);const I=Do(f);I&&(console.log(""),console.log(I))}catch(f){console.log(` (skipped: ${f.message.slice(0,80)})`)}}if(be===0){process.stdout.write("\u{1F331} Seeding 16 universal engineering lessons (first recall works instantly)...");try{await J("brain_seed_starter",{instance_id:i.id}),console.log(" \u2713");try{const f=await J("smart_recall",{instance_id:i.id,query:"docker build slow"}),_=ts(f);_&&(console.log(""),console.log(Uo(_.topic,_.what)))}catch{}}catch(f){console.log(` (skipped: ${f.message.slice(0,60)})`)}}process.stdout.write(`
295
+ `),S("setup_instance_ready",{instance_id:i.id});const p=process.cwd(),h=[],{homedir:T}=await import("node:os"),O=T();h.push("claude"),n(o(p,".cursor"))&&h.push("cursor"),n(o(p,".windsurf"))&&h.push("windsurf"),n(o(p,".vscode"))&&h.push("copilot"),n(o(p,".continue"))&&h.push("continue");const j=process.platform==="darwin"?o(O,"Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev"):o(O,".vscode/extensions");(n(j)&&!h.includes("copilot")||n(j))&&h.push("cline");const A=process.platform==="darwin"?o(O,"Library/Application Support/Zed"):o(O,".config/zed");n(A)&&h.push("zed");const C=f=>({claude:"Claude Code",cursor:"Cursor",windsurf:"Windsurf",copilot:"GitHub Copilot",continue:"Continue.dev",cline:"Cline (VSCode)",zed:"Zed"})[f]??f,E=h;console.log(`Step 3: Configuring for: ${E.map(C).join(", ")}
296
+ `);const{existsSync:$}=await import("node:fs"),k=[];let L=0;X(b);for(const f of E){const _=me[f]??".mcp.json",I=o(p,_);try{await t(a(I),{recursive:!0});const U=$(I),z=await Pt(I,b,i.id,f,{readFile:s,existsSync:$});await e(I,z,"utf-8"),console.log(`\u2705 ${U?"Updated":"Written"}: ${_}`),L++}catch(U){const z=U.message;console.log(`\u26A0\uFE0F Could not write ${_}: ${z}`),console.log(" Fix permissions or run with sudo, then re-run setup."),k.push({file:_,reason:z})}}const Y=o(O,".claude","mcp.json");try{await t(a(Y),{recursive:!0});let f={};if(n(Y))try{f=JSON.parse(await s(Y,"utf-8"))}catch{}f.mcpServers??={},f.mcpServers.cachly={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:Z(b,i.id,{includeApiKey:!0})},await e(Y,JSON.stringify(f,null,2),"utf-8"),console.log("\u2705 Written: ~/.claude/mcp.json (global \u2014 works in every project)"),L++}catch(f){const _=f.message;console.log(`\u26A0\uFE0F Could not write ~/.claude/mcp.json: ${_}`),k.push({file:"~/.claude/mcp.json",reason:_})}const K=await Ht(p,i.id);for(const[f,_]of Object.entries(K))console.log(`${_==="updated"?"\u2705 Updated":_==="appended"?"\u2705 Appended to":"\u2705 Written"}: ${f}`);y=b;let be=0;if(n(o(p,".git"))){process.stdout.write("\u23F3 Bootstrapping Brain from git history (~10s)...");try{const f=await J("brain_from_git",{instance_id:i.id,repo_path:p,limit:100}),_=f.match(/Ingested: \*\*(\d+)\*\*/);be=_?parseInt(_[1],10):0,console.log(` \u2713 ${be} lesson${be===1?"":"s"} extracted from git history`);const I=Uo(f);I&&(console.log(""),console.log(I))}catch(f){console.log(` (skipped: ${f.message.slice(0,80)})`)}}if(be===0){process.stdout.write("\u{1F331} Seeding 16 universal engineering lessons (first recall works instantly)...");try{await J("brain_seed_starter",{instance_id:i.id}),console.log(" \u2713");try{const f=await J("smart_recall",{instance_id:i.id,query:"docker build slow"}),_=os(f);_&&(console.log(""),console.log(zo(_.topic,_.what)))}catch{}}catch(f){console.log(` (skipped: ${f.message.slice(0,60)})`)}}process.stdout.write(`
297
297
  \u23F3 Fetching your Brain health preview...`);try{const f=await fetch(`${x}/api/v1/instances/${i.id}/memory`,{headers:{Authorization:`Bearer ${b}`},signal:AbortSignal.timeout(6e3)});if(f.ok){const _=await f.json(),I=_.lesson_count??0,U=_.context_count??0,z=Math.round(_.iq_boost_pct??0),te=I===0?"Intern \u{1F331}":I<10?"Junior Dev \u{1F527}":I<30?"Mid Dev \u26A1":I<60?"Senior Dev \u{1F9E0}":I<100?"Staff Eng \u{1F680}":"Principal Eng \u{1F3C6}";if(console.log(` \u2713
298
298
  `),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F9E0} Brain Health Report \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Lessons stored : ${String(I).padEnd(6)} \u2502 Level: ${te.padEnd(20)}\u2502`),console.log(`\u2502 Context entries : ${String(U).padEnd(6)} \u2502 Quality score: ${String(z).padEnd(3)}% \u2502`),I===0&&(console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 Your Brain is empty and ready to learn. \u2502"),console.log("\u2502 After your first coding session it will contain: \u2502"),console.log("\u2502 \u2022 Lessons from every bug you fixed \u2502"),console.log("\u2502 \u2022 Your project's indexed files \u2502"),console.log("\u2502 \u2022 A session summary for next time \u2502")),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),I>=5){process.stdout.write(`
299
299
  \u23F3 Running predictive risk scan...`);try{const B=(await J("brain_predict",{instance_id:i.id,context:"starting a new development session"})).split(`
@@ -301,7 +301,7 @@ Could not create an instance automatically. Opening ${R("/instances",u)} \u2026
301
301
  `),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F52E} Brain Risk Preview (brain_predict) \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");for(const M of B)console.log(`\u2502 ${M.slice(0,51).padEnd(51)} \u2502`);console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")}else console.log(" (no risks found \u2014 clean slate!)")}catch{console.log(" (skipped)")}}}else console.log(" (skipped)")}catch{console.log(" (skipped)")}if(console.log(`
302
302
  \u{1F389} Your AI just got a permanent brain.`),console.log(` Restart your editor \u2014 from this session on, it arrives pre-briefed.
303
303
  `),console.log(` No more re-explaining your stack. No repeated mistakes.
304
- `),console.log(` Dashboard: ${R(`/instances/${i.id}`,u)}`),console.log(`
304
+ `),console.log(` Dashboard: ${R(`/instances/${i.id}`,d)}`),console.log(`
305
305
  \u{1F4DB} Add a live badge to your README:`),console.log(` npx @cachly-dev/mcp-server@latest badge
306
306
  `),!m)try{if(console.log(`
307
307
  \u{1F451} Governance (optional \u2014 role model: admin \xB7 reviewer \xB7 contributor \xB7 viewer)`),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),(await w(" Set yourself as the first admin? (y/N): ","N")).toLowerCase()==="y"){const _=await w(' Your handle (e.g. "alice"): ');_.trim()&&await J("team_assign_role",{instance_id:i.id,handle:_.trim(),role:"admin"}).catch(()=>"")&&(console.log(` \u2705 ${_.trim()} is now admin. Invite teammates:
@@ -311,38 +311,38 @@ Could not create an instance automatically. Opening ${R("/instances",u)} \u2026
311
311
  `)}catch{}}try{const f=await nt(process.cwd(),i.id);f==="written"?console.log(`
312
312
  \u2705 CLS git hook installed \u2014 your brain will learn from every commit.`):f==="upgraded"?console.log(`
313
313
  \u2705 CLS git hook upgraded to ${st}.`):f==="appended"&&console.log(`
314
- \u2705 CLS git hook appended to existing post-commit.`)}catch{}if(T.includes("claude"))try{const f=await ct(process.cwd(),i.id);if(f.settings==="skipped")console.log(`\u26A0\uFE0F .claude/settings.json ${f.grund??"is not valid JSON"} \u2014 left untouched, Ambient Recall hooks not wired`);else{const _=f.scripts==="written"?"\u2705 Written":f.scripts==="upgraded"?`\u2705 Upgraded (\u2192 ${lt})`:"\u2713 Unchanged";console.log(`${_}: .claude/hooks/ (Ambient Recall \u2014 session briefing, per-prompt recall, file briefing, auto-learn)`),f.settings==="written"?console.log("\u2705 Written: .claude/settings.json (Ambient Recall hooks wired)"):f.settings==="merged"?console.log("\u2705 Merged: .claude/settings.json (Ambient Recall hooks wired)"):console.log("\u2713 Ambient Recall hooks already wired in .claude/settings.json")}}catch{}T.includes("cursor")&&await ye("cursor",process.cwd(),i.id," "),T.includes("copilot")&&await ye("copilot",process.cwd(),i.id," "),(n(o(O,".codex"))||n(o(p,".codex")))&&(await ye("codex",process.cwd(),i.id," "),await Me("codex",process.cwd(),Z("",i.id)," ")),(n(o(O,".gemini"))||n(o(p,".gemini")))&&(await ye("gemini",process.cwd(),i.id," "),await Me("gemini",process.cwd(),Z("",i.id)," ")),y=b;const De=Math.round((Date.now()-c)/1e3);if(k.length>0&&S("setup_config_write_failed",{instance_id:i.id,failed:k.length,succeeded:L}),S("setup_completed",{instance_id:i.id,elapsed_s:De,config_failures:k.length}),k.length>0&&L===0){console.log(`
314
+ \u2705 CLS git hook appended to existing post-commit.`)}catch{}if(E.includes("claude"))try{const f=await ct(process.cwd(),i.id);if(f.settings==="skipped")console.log(`\u26A0\uFE0F .claude/settings.json ${f.grund??"is not valid JSON"} \u2014 left untouched, Ambient Recall hooks not wired`);else{const _=f.scripts==="written"?"\u2705 Written":f.scripts==="upgraded"?`\u2705 Upgraded (\u2192 ${lt})`:"\u2713 Unchanged";console.log(`${_}: .claude/hooks/ (Ambient Recall \u2014 session briefing, per-prompt recall, file briefing, auto-learn)`),f.settings==="written"?console.log("\u2705 Written: .claude/settings.json (Ambient Recall hooks wired)"):f.settings==="merged"?console.log("\u2705 Merged: .claude/settings.json (Ambient Recall hooks wired)"):console.log("\u2713 Ambient Recall hooks already wired in .claude/settings.json")}}catch{}E.includes("cursor")&&await ye("cursor",process.cwd(),i.id," "),E.includes("copilot")&&await ye("copilot",process.cwd(),i.id," "),(n(o(O,".codex"))||n(o(p,".codex")))&&(await ye("codex",process.cwd(),i.id," "),await Me("codex",process.cwd(),Z("",i.id)," ")),(n(o(O,".gemini"))||n(o(p,".gemini")))&&(await ye("gemini",process.cwd(),i.id," "),await Me("gemini",process.cwd(),Z("",i.id)," ")),y=b;const De=Math.round((Date.now()-r)/1e3);if(k.length>0&&S("setup_config_write_failed",{instance_id:i.id,failed:k.length,succeeded:L}),S("setup_completed",{instance_id:i.id,elapsed_s:De,config_failures:k.length}),k.length>0&&L===0){console.log(`
315
315
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557`),console.log("\u2551 \u26A0\uFE0F Setup incomplete \u2014 no editor config was written \u2551"),console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),console.log(`
316
316
  Your Brain instance exists, but no editor knows about it yet.`),console.log(" Failed writes:");for(const f of k)console.log(` \u2022 ${f.file} \u2014 ${f.reason}`);console.log(`
317
- Fix the permissions above and re-run, or configure manually:`),console.log(` CACHLY_JWT=${b.slice(0,12)}\u2026 CACHLY_BRAIN_INSTANCE_ID=${i.id}`),console.log(` Docs: ${R("/docs/mcp",u)}
317
+ Fix the permissions above and re-run, or configure manually:`),console.log(` CACHLY_JWT=${b.slice(0,12)}\u2026 CACHLY_BRAIN_INSTANCE_ID=${i.id}`),console.log(` Docs: ${R("/docs/mcp",d)}
318
318
  `),v.close(),await new Promise(f=>setTimeout(f,300)),process.exit(1)}if(console.log(`
319
319
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557`),console.log("\u2551 \u{1F680} Brain is ready. \u2551"),console.log(`\u2551 \u23F1\uFE0F Setup completed in ${(De+"s").padEnd(5)} \u2014 restart your editor \u2551`),console.log("\u2551 and your AI arrives pre-briefed every session. \u2551"),console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),k.length>0){console.log(`
320
- \u26A0\uFE0F Some editor configs could not be written (others succeeded):`);for(const f of k)console.log(` \u2022 ${f.file} \u2014 ${f.reason}`);console.log(" Fix the permissions above and re-run setup to configure them too.")}console.log(""),v.close(),await new Promise(f=>setTimeout(f,300)),process.exit(0)}if(process.argv[2]==="index"){const{resolve:e}=await import("node:path"),t=process.argv.slice(3),s=c=>{const u=t.indexOf(`--${c}`);return u!==-1?t[u+1]:void 0},n=e(s("dir")??t.find(c=>!c.startsWith("--"))??"."),o=s("instance-id")||F(),a=parseInt(s("max-files")??"500",10),r=s("namespace")??"cachly:sem:code";(!o||!y)&&(console.error(`
320
+ \u26A0\uFE0F Some editor configs could not be written (others succeeded):`);for(const f of k)console.log(` \u2022 ${f.file} \u2014 ${f.reason}`);console.log(" Fix the permissions above and re-run setup to configure them too.")}console.log(""),v.close(),await new Promise(f=>setTimeout(f,300)),process.exit(0)}if(process.argv[2]==="index"){const{resolve:e}=await import("node:path"),t=process.argv.slice(3),s=r=>{const d=t.indexOf(`--${r}`);return d!==-1?t[d+1]:void 0},n=e(s("dir")??t.find(r=>!r.startsWith("--"))??"."),o=s("instance-id")||W(),a=parseInt(s("max-files")??"500",10),c=s("namespace")??"cachly:sem:code";(!o||!y)&&(console.error(`
321
321
  \u274C No Brain instance or key found (flag, environment or ~/.cachly/credentials.json)
322
322
  `),console.error(" export CACHLY_BRAIN_INSTANCE_ID=<uuid>"),console.error(" export CACHLY_JWT=<cky_live_...>"),console.error(` npx @cachly-dev/mcp-server@latest index ./my-project
323
323
  `),process.exit(1)),console.log(`
324
324
  \u{1F4C2} Indexing: ${n}`),console.log(` Instance: ${o.slice(0,8)}\u2026 Max files: ${a}
325
- `);try{const c=await J("index_project",{instance_id:o,dir:n,max_files:a,ttl:604800,namespace:r});console.log(c),console.log(`
325
+ `);try{const r=await J("index_project",{instance_id:o,dir:n,max_files:a,ttl:604800,namespace:c});console.log(r),console.log(`
326
326
  \u2705 Indexing complete.
327
- `)}catch(c){console.error(`
328
- \u274C Indexing failed: ${c.message}
329
- `),process.exit(1)}process.exit(0)}if(process.argv[2]==="learn-git"){const{resolve:e}=await import("node:path"),t=process.argv.slice(3),s=r=>{const c=t.indexOf(`--${r}`);return c!==-1?t[c+1]:void 0},n=e(s("dir")??t.find(r=>!r.startsWith("--"))??"."),o=s("instance-id")||F(),a=parseInt(s("max-commits")??"50",10);(!o||!y)&&(console.error(`
327
+ `)}catch(r){console.error(`
328
+ \u274C Indexing failed: ${r.message}
329
+ `),process.exit(1)}process.exit(0)}if(process.argv[2]==="learn-git"){const{resolve:e}=await import("node:path"),t=process.argv.slice(3),s=c=>{const r=t.indexOf(`--${c}`);return r!==-1?t[r+1]:void 0},n=e(s("dir")??t.find(c=>!c.startsWith("--"))??"."),o=s("instance-id")||W(),a=parseInt(s("max-commits")??"50",10);(!o||!y)&&(console.error(`
330
330
  \u274C No Brain instance or key found (flag, environment or ~/.cachly/credentials.json)
331
331
  `),console.error(" export CACHLY_BRAIN_INSTANCE_ID=<uuid>"),console.error(" export CACHLY_JWT=<cky_live_...>"),console.error(` npx @cachly-dev/mcp-server@latest learn-git .
332
332
  `),process.exit(1)),console.log(`
333
333
  \u{1F9E0} Learning from git history: ${n}`),console.log(` Instance: ${o.slice(0,8)}\u2026 Max commits: ${a}
334
- `);try{const r=await J("brain_from_git",{instance_id:o,repo_path:n,limit:a});console.log(r),S("brain_from_git",{api_key:y,instance_id:o}),console.log(`
334
+ `);try{const c=await J("brain_from_git",{instance_id:o,repo_path:n,limit:a});console.log(c),S("brain_from_git",{api_key:y,instance_id:o}),console.log(`
335
335
  \u2705 Brain learned from your commits.
336
- `),await new Promise(c=>setTimeout(c,300))}catch(r){console.error(`
337
- \u274C learn-git failed: ${r.message}
338
- `),process.exit(1)}process.exit(0)}if(process.argv[2]==="ambient-recall"&&await en(process.argv.slice(3),process.argv[1]),process.argv[2]==="ambient-auffrischen"&&await tn(),process.argv[2]===nn&&await on(process.argv[3]??""),process.argv[2]==="ambient-credit"){try{const e=Math.round(Number(process.argv[3]));if(Number.isFinite(e)&&e>0){const t=Math.min(e,2e4),s=process.argv.slice(4).join(" ").slice(0,200)||void 0,n={ts:new Date().toISOString(),event:"credit",injected:0,prevented:t,note:s,instanz:F()||void 0};await rn(n),await ns(process.env.CACHLY_BRAIN_INSTANCE_ID??N,n),console.log(`\u2705 ambient credit recorded: ${t} tokens${s?` (${s})`:""}`)}else console.error("Usage: npx @cachly-dev/mcp-server@latest ambient-credit <tokens-saved> [note]")}catch{}process.exit(0)}if(process.argv[2]==="ambient-stats"){const e=F(),t=ln(await dt(),e||void 0),s=t.eigene,n=Vn(s),o=s.slice(-5);if(console.log(`
336
+ `),await new Promise(r=>setTimeout(r,300))}catch(c){console.error(`
337
+ \u274C learn-git failed: ${c.message}
338
+ `),process.exit(1)}process.exit(0)}if(process.argv[2]==="ambient-recall"&&await tn(process.argv.slice(3),process.argv[1]),process.argv[2]==="ambient-auffrischen"&&await on(),process.argv[2]===sn&&await nn(process.argv[3]??""),process.argv[2]==="ambient-credit"){try{const e=Math.round(Number(process.argv[3]));if(Number.isFinite(e)&&e>0){const t=Math.min(e,2e4),s=process.argv.slice(4).join(" ").slice(0,200)||void 0,n={ts:new Date().toISOString(),event:"credit",injected:0,prevented:t,note:s,instanz:W()||void 0};await an(n),await ss(process.env.CACHLY_BRAIN_INSTANCE_ID??N,n),console.log(`\u2705 ambient credit recorded: ${t} tokens${s?` (${s})`:""}`)}else console.error("Usage: npx @cachly-dev/mcp-server@latest ambient-credit <tokens-saved> [note]")}catch{}process.exit(0)}if(process.argv[2]==="ambient-stats"){const e=W(),t=dn(await dt(),e||void 0),s=t.eigene,n=Zn(s),o=s.slice(-5);if(console.log(`
339
339
  \u{1F9E0} Ambient Recall \u2014 net-token ledger
340
340
  `),console.log(` Instance: ${e?`${e.slice(0,8)}\u2026`:"(none set \u2014 showing every entry on this computer)"}`),console.log(` Turns recorded: ${s.length}`),console.log(` Injected tokens: ${n.injected}`),console.log(` Prevented tokens: ${n.prevented} (agent-reported via ambient-credit)`),console.log(` NET: ${n.net>=0?"+":""}${n.net} tokens`),o.length>0){console.log(`
341
- Last entries:`);for(const a of o){const r=a.prevented>0?`+${a.prevented} prevented`:`-${a.injected} injected`;console.log(` \u2022 ${a.ts.slice(0,19)} ${a.event}: ${r}${a.note?` (${a.note})`:""}`)}}(t.ohneInstanz>0||t.andereInstanzen>0)&&(console.log(`
342
- Not counted above:`),t.ohneInstanz>0&&console.log(` \u2022 ${t.ohneInstanz} older entries without an instance (before 0.10.207)`),t.andereInstanzen>0&&console.log(` \u2022 entries of ${t.andereInstanzen} other instance${t.andereInstanzen===1?"":"s"} on this computer`)),console.log(""),process.exit(0)}if(process.argv[2]==="uninstall"){const{homedir:e,tmpdir:t}=await import("node:os"),{resolve:s}=await import("node:path"),{createInterface:n}=await import("node:readline/promises"),o=process.argv.slice(3),r={projekt:s((c=>{const u=o.indexOf(`--${c}`);return u!==-1?o[u+1]:void 0})("project-dir")??"."),heim:process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??e(),tmp:t(),schluessel:ne(),instanz:F(),apiUrl:x,istTty:process.stdin.isTTY===!0&&process.stdout.isTTY===!0,ausgabe:c=>console.log(c),frage:async c=>{const u=n({input:process.stdin,output:process.stdout});try{return/^(y|yes|j|ja)$/i.test((await u.question(c)).trim())}finally{u.close()}}};process.exit(await Fo(o,r))}if(process.argv[2]==="doctor"){const{checkNodeVersion:e,checkCredential:t,checkApiReachable:s,checkAuthAccepted:n,checkInstance:o,checkVectorCoverage:a,inspectAmbientHooks:r,checkHooks:c,checkLedger:u,renderDoctorReport:g,doctorExitCode:d}=await import("./doctor.js"),m=[e(),t(y),await s(x),await n(x,y),o(F()||N),await a(x,y,F()||N),c(r(process.cwd())),u(await dt(),an())];console.log(g(m)),process.exit(d(m))}if(process.argv[2]==="cls-ingest"){try{const e=process.argv[3];(!e||!y)&&process.exit(0);let t;try{t=JSON.parse(e)}catch{process.exit(0)}const s=t.instance_id??N;(!s||!t.source)&&process.exit(0),await J("cls_ingest",{instance_id:s,source:t.source,payload:t.payload??{}})}catch{}process.exit(0)}if(!y){const e=zt();if(e)try{const t=await fetch(Ft(e),{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:Jt(e),signal:AbortSignal.timeout(8e3)});if(t.ok){const s=await t.json();s.access_token&&(y=s.access_token,le(s.access_token),S("m2m_auth_completed",{grant:"client_credentials",client_id:e.clientId}),process.stderr.write(`\u{1F916} cachly: authenticated via client_credentials (M2M, headless).
341
+ Last entries:`);for(const a of o){const c=a.prevented>0?`+${a.prevented} prevented`:`-${a.injected} injected`;console.log(` \u2022 ${a.ts.slice(0,19)} ${a.event}: ${c}${a.note?` (${a.note})`:""}`)}}(t.ohneInstanz>0||t.andereInstanzen>0)&&(console.log(`
342
+ Not counted above:`),t.ohneInstanz>0&&console.log(` \u2022 ${t.ohneInstanz} older entries without an instance (before 0.10.207)`),t.andereInstanzen>0&&console.log(` \u2022 entries of ${t.andereInstanzen} other instance${t.andereInstanzen===1?"":"s"} on this computer`)),console.log(""),process.exit(0)}if(process.argv[2]==="uninstall"){const{homedir:e,tmpdir:t}=await import("node:os"),{resolve:s}=await import("node:path"),{createInterface:n}=await import("node:readline/promises"),o=process.argv.slice(3),c={projekt:s((r=>{const d=o.indexOf(`--${r}`);return d!==-1?o[d+1]:void 0})("project-dir")??"."),heim:process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??e(),tmp:t(),schluessel:ne(),instanz:W(),apiUrl:x,istTty:process.stdin.isTTY===!0&&process.stdout.isTTY===!0,ausgabe:r=>console.log(r),frage:async r=>{const d=n({input:process.stdin,output:process.stdout});try{return/^(y|yes|j|ja)$/i.test((await d.question(r)).trim())}finally{d.close()}}};process.exit(await Fo(o,c))}if(process.argv[2]==="doctor"){const{checkNodeVersion:e,checkCredential:t,checkApiReachable:s,checkAuthAccepted:n,checkInstance:o,checkVectorCoverage:a,inspectAmbientHooks:c,checkHooks:r,checkLedger:d,renderDoctorReport:g,doctorExitCode:u}=await import("./doctor.js"),m=[e(),t(y),await s(x),await n(x,y),o(W()||N),await a(x,y,W()||N),r(c(process.cwd())),d(await dt(),cn())];console.log(g(m)),process.exit(u(m))}if(process.argv[2]==="cls-ingest"){try{const e=process.argv[3];(!e||!y)&&process.exit(0);let t;try{t=JSON.parse(e)}catch{process.exit(0)}const s=t.instance_id??N;(!s||!t.source)&&process.exit(0),await J("cls_ingest",{instance_id:s,source:t.source,payload:t.payload??{}})}catch{}process.exit(0)}if(!y){const e=Jt();if(e)try{const t=await fetch(Ft(e),{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:Wt(e),signal:AbortSignal.timeout(8e3)});if(t.ok){const s=await t.json();s.access_token&&(y=s.access_token,le(s.access_token),S("m2m_auth_completed",{grant:"client_credentials",client_id:e.clientId}),process.stderr.write(`\u{1F916} cachly: authenticated via client_credentials (M2M, headless).
343
343
  `))}else process.stderr.write(`\u26A0\uFE0F cachly: client_credentials auth failed (${t.status}). Check CACHLY_CLIENT_ID / CACHLY_CLIENT_SECRET.
344
344
  `),S("m2m_auth_failed",{status:t.status})}catch(t){process.stderr.write(`\u26A0\uFE0F cachly: client_credentials auth error: ${t.message}
345
- `),S("m2m_auth_failed",{reason:"network"})}}const xs=["demo","share","publish","health","autosetup","setup","autopilot","init","digest","invite","badge","join","upgrade","bench","tool-specs","openapi","ambient-credit","ambient-stats","doctor","uninstall"];if(!y&&!xs.includes(process.argv[2]??""))if(!process.argv[2]&&process.stdout.isTTY===!0&&Zt){const n=`
345
+ `),S("m2m_auth_failed",{reason:"network"})}}const _s=["demo","share","publish","health","autosetup","setup","autopilot","init","digest","invite","badge","join","upgrade","bench","tool-specs","openapi","ambient-credit","ambient-stats","doctor","uninstall"];if(!y&&!_s.includes(process.argv[2]??""))if(!process.argv[2]&&process.stdout.isTTY===!0&&Qt){const n=`
346
346
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
347
347
  \u2551 \u{1F9E0} cachly AI Brain \u2014 Setup required \u2551
348
348
  \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
@@ -362,7 +362,7 @@ Could not create an instance automatically. Opening ${R("/instances",u)} \u2026
362
362
  \u{1F9E0} cachly: no API key yet \u2014 the first cachly tool call creates a test Brain on EU servers, no sign-up.
363
363
  (Own account: npx @cachly-dev/mcp-server@latest autopilot)
364
364
 
365
- `);else{const e=Mt(y);if(e!==null){const t=Math.floor((e-Date.now())/6e4);t<=0?process.stderr.write(`
365
+ `);else{const e=Dt(y);if(e!==null){const t=Math.floor((e-Date.now())/6e4);t<=0?process.stderr.write(`
366
366
  \u26A0\uFE0F cachly: CACHLY_JWT expired ${Math.abs(t)} minute(s) ago.
367
367
  All tool calls will fail. Get a fresh token at ${R("/setup-ai","jwt-expiry")}
368
368
 
@@ -370,7 +370,7 @@ Could not create an instance automatically. Opening ${R("/instances",u)} \u2026
370
370
  \u26A0\uFE0F cachly: CACHLY_JWT expires in ${t} minute(s).
371
371
  Refresh it soon at ${R("/setup-ai","jwt-expiry")} to avoid interruptions.
372
372
 
373
- `)}}process.env.PORT||On({aktuelle:Nn(D)});const ke=process.env.PORT?parseInt(process.env.PORT,10):void 0;if(ke){const{createServer:e}=await import("node:http");e((s,n)=>{const o=new URL(s.url??"/",`http://localhost:${ke}`);if(o.pathname==="/health"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify({status:"ok",version:D,zeroResults:{total:To,last10:Co.slice(-10).map(a=>({query:a.query,ts:new Date(a.ts).toISOString()}))}}));return}if(o.pathname==="/mcp"||o.pathname==="/"){(async()=>{const a=gs(),r=new Xt({sessionIdGenerator:void 0});n.on("close",()=>{r.close().catch(()=>{}),a.close().catch(()=>{})});try{await a.connect(r),await r.handleRequest(s,n)}catch(c){process.stderr.write(`cachly-mcp HTTP: ${c.message}
374
- `),n.headersSent||(n.writeHead(500,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:c.message})))}})();return}n.writeHead(404),n.end("not found")}).listen(ke,()=>{process.stderr.write(`cachly-mcp HTTP server listening on :${ke}
375
- `)})}else{const e=new Qt;W("start: Module geladen, stdio verbinden"),await V.connect(e),typeof process.argv[2]=="string"&&!process.argv[2].startsWith("-")||(Qe=!0,ro(),Dn(),Hn(process.stdin,s=>{process.stderr.write(`[cachly-mcp] ${s} \u2014 Session zu Ende, Server geht mit
376
- `),(async()=>{await He().catch(()=>{});for(const[,n]of se)await n.quit().catch(()=>{});process.exit(0)})()}))}Je("cachly","startup",{version:D,mode:process.env.MCP_HTTP_PORT?"http":"stdio"}).catch(()=>{});export{rt as CLAUDE_MD_MARKER_END,it as CLAUDE_MD_MARKER_START,Ao as CROSS_LINGUAL_MAP,me as EDITOR_FILES,_o as STOPWORDS,ko as arabicLightStem,bs as buildClaudeMdBlock,ys as buildMcpConfig,Z as buildServerEnv,So as expandCrossLingual,xo as extractTimestamp,$o as katakanaToRomaji,vo as levenshtein,hs as mcpAddBefehl,Ot as mergeMcpConfig,wo as recencyBoost,Eo as reconnectOnce,bo as splitMultiQuery,mo as startBackgroundDevicePoll,yo as tokenize,Pt as writeInstructions};
373
+ `)}}process.env.PORT||Pn({aktuelle:On(D)});const ke=process.env.PORT?parseInt(process.env.PORT,10):void 0;if(ke){const{createServer:e}=await import("node:http");e((s,n)=>{const o=new URL(s.url??"/",`http://localhost:${ke}`);if(o.pathname==="/health"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify({status:"ok",version:D,zeroResults:{total:Eo,last10:To.slice(-10).map(a=>({query:a.query,ts:new Date(a.ts).toISOString()}))}}));return}if(o.pathname==="/mcp"||o.pathname==="/"){(async()=>{const a=fs(),c=new eo({sessionIdGenerator:void 0});n.on("close",()=>{c.close().catch(()=>{}),a.close().catch(()=>{})});try{await a.connect(c),await c.handleRequest(s,n)}catch(r){process.stderr.write(`cachly-mcp HTTP: ${r.message}
374
+ `),n.headersSent||(n.writeHead(500,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:r.message})))}})();return}n.writeHead(404),n.end("not found")}).listen(ke,()=>{process.stderr.write(`cachly-mcp HTTP server listening on :${ke}
375
+ `)})}else{const e=new Xt;F("start: Module geladen, stdio verbinden"),await V.connect(e),typeof process.argv[2]=="string"&&!process.argv[2].startsWith("-")||(Qe=!0,ao(),Un(),Mn(process.stdin,s=>{process.stderr.write(`[cachly-mcp] ${s} \u2014 Session zu Ende, Server geht mit
376
+ `),(async()=>{await He().catch(()=>{});for(const[,n]of se)await n.quit().catch(()=>{});process.exit(0)})()}))}Je("cachly","startup",{version:D,mode:process.env.MCP_HTTP_PORT?"http":"stdio"}).catch(()=>{});export{rt as CLAUDE_MD_MARKER_END,it as CLAUDE_MD_MARKER_START,Co as CROSS_LINGUAL_MAP,me as EDITOR_FILES,$o as STOPWORDS,So as arabicLightStem,vs as buildClaudeMdBlock,bs as buildMcpConfig,Z as buildServerEnv,Ao as expandCrossLingual,_o as extractTimestamp,ko as katakanaToRomaji,wo as levenshtein,ys as mcpAddBefehl,Pt as mergeMcpConfig,xo as recencyBoost,Io as reconnectOnce,vo as splitMultiQuery,go as startBackgroundDevicePoll,bo as tokenize,Ht as writeInstructions};
package/glama.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://glama.ai/mcp/schemas/server.json",
3
- "version": "0.10.209",
3
+ "version": "0.10.210",
4
4
  "maintainers": [
5
5
  "HeinrichNebula"
6
6
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cachly-dev/mcp-server",
3
- "version": "0.10.209",
3
+ "version": "0.10.210",
4
4
  "mcpName": "io.github.cachly-dev/mcp-server",
5
5
  "description": "Solve it once. From then on, your AI knows. Experience for coding agents, EU-hosted: an MCP server for Claude Code, Cursor, Copilot & Windsurf. Learns from every bug fix, commit and CI run.",
6
6
  "type": "module",
package/server.json CHANGED
@@ -6,13 +6,13 @@
6
6
  "url": "https://github.com/cachly-dev/cachly-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.10.209",
9
+ "version": "0.10.210",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "name": "@cachly-dev/mcp-server",
14
14
  "identifier": "@cachly-dev/mcp-server",
15
- "version": "0.10.209",
15
+ "version": "0.10.210",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }