@clauderecallhq/cli 0.65.11 → 0.66.0

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.
package/dist/cli.js CHANGED
@@ -618,13 +618,13 @@ CREATE INDEX IF NOT EXISTS idx_synth_results_target
618
618
  ON bug_synthesis_results(scope, target_id, created_at DESC);
619
619
  CREATE INDEX IF NOT EXISTS idx_synth_results_created
620
620
  ON bug_synthesis_results(created_at DESC);
621
- `});import*as vo from"sqlite-vec";function _(){if(ae)return ae;P(),ae=new rs(te),vo.load(ae),ae.pragma("cache_size = -64000"),ae.pragma("mmap_size = 268435456"),ae.pragma("temp_store = MEMORY"),ae.pragma("busy_timeout = 5000"),ae.pragma("journal_size_limit = 67108864"),ae.pragma("wal_autocheckpoint = 1000"),ae.exec(Oo),Ao(ae);try{ae.exec("PRAGMA optimize")}catch{}return ae}var ae,T=N(()=>{"use strict";En();j();Io();ae=null});import Ne from"chalk";import{formatDistanceToNowStrict as pp,parseISO as mp}from"date-fns";function Y(e,t){if(!e)return"";let s=e.replace(/\s+/g," ").trim();return s.length<=t?s:s.slice(0,t-1)+"\u2026"}function W(e){if(!e)return"";try{return pp(mp(e),{addSuffix:!0})}catch{return""}}function H(e){return e.slice(0,8)}function $o(e,t){if(!t)return e;let s=t.split(/\s+/).filter(r=>r.length>1).map(r=>r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));if(s.length===0)return e;let n=new RegExp(`(${s.join("|")})`,"gi");return e.replace(n,r=>Ne.bgYellow.black(r))}var d,I=N(()=>{"use strict";d={dim:Ne.gray,bold:Ne.bold,project:Ne.cyan,user:Ne.blue,assistant:Ne.green,tool:Ne.magenta,warn:Ne.yellow,err:Ne.red,ok:Ne.green,accent:Ne.hex("#f97316")}});import{existsSync as si,readFileSync as dm,writeFileSync as um,unlinkSync as pm}from"node:fs";import{join as mm}from"node:path";function jt(){if(!si(pt))return null;try{let e=dm(pt,"utf8"),t=JSON.parse(e);return typeof t.license_jwt!="string"||t.license_jwt.length===0?null:t}catch{return null}}function ni(e){P(),um(pt,JSON.stringify(e,null,2)+`
621
+ `});import*as vo from"sqlite-vec";function _(){if(ae)return ae;P(),ae=new rs(te),vo.load(ae),ae.pragma("cache_size = -64000"),ae.pragma("mmap_size = 268435456"),ae.pragma("temp_store = MEMORY"),ae.pragma("busy_timeout = 5000"),ae.pragma("journal_size_limit = 67108864"),ae.pragma("wal_autocheckpoint = 1000"),ae.exec(Oo),Ao(ae);try{ae.exec("PRAGMA optimize")}catch{}return ae}var ae,T=N(()=>{"use strict";En();j();Io();ae=null});import Ne from"chalk";import{formatDistanceToNowStrict as pp,parseISO as mp}from"date-fns";function Y(e,t){if(!e)return"";let s=e.replace(/\s+/g," ").trim();return s.length<=t?s:s.slice(0,t-1)+"\u2026"}function W(e){if(!e)return"";try{return pp(mp(e),{addSuffix:!0})}catch{return""}}function H(e){return e.slice(0,8)}function Do(e,t){if(!t)return e;let s=t.split(/\s+/).filter(r=>r.length>1).map(r=>r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));if(s.length===0)return e;let n=new RegExp(`(${s.join("|")})`,"gi");return e.replace(n,r=>Ne.bgYellow.black(r))}var d,I=N(()=>{"use strict";d={dim:Ne.gray,bold:Ne.bold,project:Ne.cyan,user:Ne.blue,assistant:Ne.green,tool:Ne.magenta,warn:Ne.yellow,err:Ne.red,ok:Ne.green,accent:Ne.hex("#f97316")}});import{existsSync as si,readFileSync as dm,writeFileSync as um,unlinkSync as pm}from"node:fs";import{join as mm}from"node:path";function jt(){if(!si(pt))return null;try{let e=dm(pt,"utf8"),t=JSON.parse(e);return typeof t.license_jwt!="string"||t.license_jwt.length===0?null:t}catch{return null}}function ni(e){P(),um(pt,JSON.stringify(e,null,2)+`
622
622
  `,{mode:384})}function ri(){si(pt)&&pm(pt)}var pt,Pt=N(()=>{"use strict";j();pt=mm(x,"license.json")});var oi,An,ii,ai,ci=N(()=>{"use strict";oi=`-----BEGIN PUBLIC KEY-----
623
623
  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZysO2FffTLdyxQnTmnt78/ayvqz9
624
624
  kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
625
625
  -----END PUBLIC KEY-----
626
626
  `,An="ES256",ii="clauderecall.com",ai="clauderecall-cli"});import{jwtVerify as gm,importSPKI as fm}from"jose";async function _m(){return ls||(ls=await fm(oi,An),ls)}async function ds(e){try{let t=await _m(),{payload:s}=await gm(e,t,{issuer:ii,audience:ai,algorithms:[An]});return{valid:!0,claims:s}}catch(t){return{valid:!1,reason:t instanceof Error?t.message:"verification failed"}}}var ls,In=N(()=>{"use strict";ci();ls=null});import{createHash as hm}from"node:crypto";import{hostname as Em,userInfo as bm,platform as Sm,arch as ym}from"node:os";function us(){let e="unknown";try{e=bm().username}catch{}let t=[Em(),e,Sm(),ym()];return hm("sha256").update(t.join("\0")).digest("hex")}var vn=N(()=>{"use strict"});function xt(){let e=process.env.RECALL_API_BASE;if(e&&e.length>0){let t=e.replace(/\/$/,""),s;try{s=new URL(t)}catch{throw new Error(`RECALL_API_BASE is not a valid URL: ${t}`)}let n=s.hostname==="127.0.0.1"||s.hostname==="localhost"||s.hostname==="::1";if(s.protocol==="https:"||s.protocol==="http:"&&n)return t;throw new Error(`RECALL_API_BASE must be HTTPS, or HTTP with loopback hostname. Got: ${t}`)}return"https://clauderecall.com"}var ps=N(()=>{"use strict"});import{existsSync as Tm,readFileSync as wm,writeFileSync as xm}from"node:fs";import{join as Rm}from"node:path";function ms(){if(!Tm(Mn))return null;try{let e=JSON.parse(wm(Mn,"utf8"));return typeof e.license_key!="string"||typeof e.last_checked_at!="string"||typeof e.revoked!="boolean"?null:e}catch{return null}}function Lm(e){P(),xm(Mn,JSON.stringify(e,null,2)+`
627
- `,{mode:384})}async function Om(e,t){let s=null,n=null;try{s=new AbortController,n=setTimeout(()=>s?.abort(),Cm);let r=await fetch(t,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({license_key:e}),signal:s.signal});if(!r.ok)return null;let o=await r.json();return typeof o?.revoked!="boolean"?null:o}catch{return null}finally{n&&clearTimeout(n)}}async function li(e,t={}){let s=ms(),n=t.apiUrl??`${xt()}/api/license/check`,r=s?.license_key===e,o=!s||!r||Date.now()-new Date(s.last_checked_at).getTime()>=km;if(!t.force&&!o)return s;let i=await Om(e,n);if(!i)return r?s:null;let a={license_key:e,last_checked_at:new Date().toISOString(),revoked:i.revoked,reason:i.reason??null};return Lm(a),a}function di(e){let t=ms();return!t||t.license_key!==e?null:t.revoked?{revoked:!0,reason:t.reason?`license revoked: ${t.reason}`:"license revoked by issuer"}:Date.now()-new Date(t.last_checked_at).getTime()>Nm?{revoked:!0,reason:"license has not been validated with the server in 30+ days. Reconnect to the internet and run `recall license check`"}:null}var Mn,km,Nm,Cm,Dn=N(()=>{"use strict";j();ps();Mn=Rm(x,"license-check.json"),km=1440*60*1e3,Nm=720*60*60*1e3,Cm=1e4});function Im(e=Date.now()){return e<$n}function pi(e=Date.now()){return Im(e)?`(one-time purchase, $${Am} through May 2026 Founder pricing, $${ui} from June, lifetime updates either way)`:`(one-time purchase, $${ui}, lifetime updates)`}var $n,Am,ui,jn=N(()=>{"use strict";$n=Date.UTC(2026,5,1,7,0,0),Am="29.69",ui="49.69"});function Un(e){let t=e.now??Date.now(),s=e.status.expires_at??null,n=s?new Date(s).getTime():null,r=n!==null&&n-t<vm;if(e.status.tier==="pro"&&r&&n!==null){let o=Math.max(0,Math.floor((n-t)/36e5));if(o<=24)return{kind:"trial-near-expiry",message:`Your Pro trial ends in ${o} hours. Lock in Founder pricing ($29.69 lifetime, ends May 31): ${Pn}`}}if(e.status.tier==="free"&&r&&n!==null&&n<t&&Math.floor((t-n)/36e5)<720)return{kind:"trial-expired",message:`Your Pro trial ended. Your data is intact; only Pro features are gated. Founder pricing ($29.69 lifetime, ends May 31): ${Pn}`};if(e.status.tier==="free"){let o=$n-t;if(o>0&&o<=3*Fn){let i=Math.max(1,Math.ceil(o/Fn));return{kind:"founder-near-deadline",message:`Founder pricing ($29.69 lifetime) ends in ${i} day${i===1?"":"s"}. After May 31, lifetime is $49.69: ${Pn}`}}}return null}var Pn,Fn,vm,mi=N(()=>{"use strict";jn();Pn="https://clauderecall.com/pricing",Fn=1440*60*1e3,vm=60*Fn});var gs={};fe(gs,{getLicenseStatus:()=>ye,isPro:()=>Dm,performRevocationCheck:()=>Bn,printTrialBannerIfAny:()=>$m,requireProOrExit:()=>Ce});async function ye(){let e=jt();if(!e)return{tier:"free"};let t=await ds(e.license_jwt);if(!t.valid||!t.claims)return{tier:"free",invalid_reason:t.reason};if(t.claims.machine_fp&&t.claims.machine_fp!==us())return{tier:"free",invalid_reason:"machine fingerprint mismatch \u2014 re-activate on this device"};let s=di(e.license_key);return s?.revoked?{tier:"free",invalid_reason:s.reason}:Mm(e,t.claims)}async function Bn(e){let t=jt();if(!t)return{ran:!1,revoked:!1,reason:null,last_checked_at:null};let s=await li(t.license_key,{force:e?.force??!1});return s?{ran:!0,revoked:s.revoked,reason:s.reason,last_checked_at:s.last_checked_at}:{ran:!0,revoked:!1,reason:null,last_checked_at:null}}function Mm(e,t){let s=t.test_mode===!0&&process.env.NODE_ENV==="production";return{tier:s?"free":"pro",key_short:e.key_short,customer_email:e.customer_email,activated_at:e.activated_at,test_mode:e.test_mode,...s?{test_mode_blocked:!0}:{},expires_at:typeof t.exp=="number"?new Date(t.exp*1e3).toISOString():null}}async function Dm(){return(await ye()).tier==="pro"}async function Ce(e){let t=await ye();if(t.tier==="pro")return;let s=Un({status:t});s&&process.stderr.write(`
627
+ `,{mode:384})}async function Om(e,t){let s=null,n=null;try{s=new AbortController,n=setTimeout(()=>s?.abort(),Cm);let r=await fetch(t,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({license_key:e}),signal:s.signal});if(!r.ok)return null;let o=await r.json();return typeof o?.revoked!="boolean"?null:o}catch{return null}finally{n&&clearTimeout(n)}}async function li(e,t={}){let s=ms(),n=t.apiUrl??`${xt()}/api/license/check`,r=s?.license_key===e,o=!s||!r||Date.now()-new Date(s.last_checked_at).getTime()>=km;if(!t.force&&!o)return s;let i=await Om(e,n);if(!i)return r?s:null;let a={license_key:e,last_checked_at:new Date().toISOString(),revoked:i.revoked,reason:i.reason??null};return Lm(a),a}function di(e){let t=ms();return!t||t.license_key!==e?null:t.revoked?{revoked:!0,reason:t.reason?`license revoked: ${t.reason}`:"license revoked by issuer"}:Date.now()-new Date(t.last_checked_at).getTime()>Nm?{revoked:!0,reason:"license has not been validated with the server in 30+ days. Reconnect to the internet and run `recall license check`"}:null}var Mn,km,Nm,Cm,$n=N(()=>{"use strict";j();ps();Mn=Rm(x,"license-check.json"),km=1440*60*1e3,Nm=720*60*60*1e3,Cm=1e4});function Im(e=Date.now()){return e<Dn}function pi(e=Date.now()){return Im(e)?`(one-time purchase, $${Am} through May 2026 Founder pricing, $${ui} from June, lifetime updates either way)`:`(one-time purchase, $${ui}, lifetime updates)`}var Dn,Am,ui,jn=N(()=>{"use strict";Dn=Date.UTC(2026,5,1,7,0,0),Am="29.69",ui="49.69"});function Un(e){let t=e.now??Date.now(),s=e.status.expires_at??null,n=s?new Date(s).getTime():null,r=n!==null&&n-t<vm;if(e.status.tier==="pro"&&r&&n!==null){let o=Math.max(0,Math.floor((n-t)/36e5));if(o<=24)return{kind:"trial-near-expiry",message:`Your Pro trial ends in ${o} hours. Lock in Founder pricing ($29.69 lifetime, ends May 31): ${Pn}`}}if(e.status.tier==="free"&&r&&n!==null&&n<t&&Math.floor((t-n)/36e5)<720)return{kind:"trial-expired",message:`Your Pro trial ended. Your data is intact; only Pro features are gated. Founder pricing ($29.69 lifetime, ends May 31): ${Pn}`};if(e.status.tier==="free"){let o=Dn-t;if(o>0&&o<=3*Fn){let i=Math.max(1,Math.ceil(o/Fn));return{kind:"founder-near-deadline",message:`Founder pricing ($29.69 lifetime) ends in ${i} day${i===1?"":"s"}. After May 31, lifetime is $49.69: ${Pn}`}}}return null}var Pn,Fn,vm,mi=N(()=>{"use strict";jn();Pn="https://clauderecall.com/pricing",Fn=1440*60*1e3,vm=60*Fn});var gs={};fe(gs,{getLicenseStatus:()=>ye,isPro:()=>$m,performRevocationCheck:()=>Bn,printTrialBannerIfAny:()=>Dm,requireProOrExit:()=>Ce});async function ye(){let e=jt();if(!e)return{tier:"free"};let t=await ds(e.license_jwt);if(!t.valid||!t.claims)return{tier:"free",invalid_reason:t.reason};if(t.claims.machine_fp&&t.claims.machine_fp!==us())return{tier:"free",invalid_reason:"machine fingerprint mismatch \u2014 re-activate on this device"};let s=di(e.license_key);return s?.revoked?{tier:"free",invalid_reason:s.reason}:Mm(e,t.claims)}async function Bn(e){let t=jt();if(!t)return{ran:!1,revoked:!1,reason:null,last_checked_at:null};let s=await li(t.license_key,{force:e?.force??!1});return s?{ran:!0,revoked:s.revoked,reason:s.reason,last_checked_at:s.last_checked_at}:{ran:!0,revoked:!1,reason:null,last_checked_at:null}}function Mm(e,t){let s=t.test_mode===!0&&process.env.NODE_ENV==="production";return{tier:s?"free":"pro",key_short:e.key_short,customer_email:e.customer_email,activated_at:e.activated_at,test_mode:e.test_mode,...s?{test_mode_blocked:!0}:{},expires_at:typeof t.exp=="number"?new Date(t.exp*1e3).toISOString():null}}async function $m(){return(await ye()).tier==="pro"}async function Ce(e){let t=await ye();if(t.tier==="pro")return;let s=Un({status:t});s&&process.stderr.write(`
628
628
  ${s.message}
629
629
  `),process.stderr.write(`
630
630
  ${e} is a Pro feature.
@@ -635,10 +635,10 @@ Then run: recall activate <license-key>
635
635
 
636
636
  `),t.invalid_reason&&process.stderr.write(`(stored license is invalid: ${t.invalid_reason})
637
637
 
638
- `),process.exit(1)}async function $m(){let e=await ye(),t=Un({status:e});return t?(process.stderr.write(`
638
+ `),process.exit(1)}async function Dm(){let e=await ye(),t=Un({status:e});return t?(process.stderr.write(`
639
639
  ${t.message}
640
640
 
641
- `),!0):!1}var _e=N(()=>{"use strict";Pt();In();vn();Dn();jn();mi()});import{writeFileSync as hR,readFileSync as Pm,existsSync as Fm}from"node:fs";import{join as Um}from"node:path";function fi(){if(!Fm(fs))return null;try{return Pm(fs,"utf8").trim()}catch{return null}}var fs,Hn=N(()=>{"use strict";j();fs=Um(x,"daemon.token")});import{existsSync as _i,readFileSync as Bm,writeFileSync as TR,unlinkSync as Hm}from"node:fs";import{join as Xn}from"node:path";function Xm(){if(!_i(Wn))return null;try{let e=JSON.parse(Bm(Wn,"utf8"));return typeof e.pid!="number"||typeof e.port!="number"?null:e}catch{return null}}function Jn(){for(let e of[Wn,Wm,fs])if(_i(e))try{Hm(e)}catch{}}function Jm(e){try{return process.kill(e,0),!0}catch{return!1}}function K(){let e=Xm();return e?Jm(e.pid)?e:(Jn(),null):null}var Wn,Wm,_s,We=N(()=>{"use strict";j();Hn();Wn=Xn(x,"daemon.pid"),Wm=Xn(x,"daemon.port"),_s=Xn(x,"daemon.log")});import{writeFileSync as Og}from"node:fs";import{join as Ag}from"node:path";function Kn(e){try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return[]}function Ki(e){return _().prepare("SELECT alias FROM session_aliases WHERE session_id = ?").get(e)?.alias??null}function vg(){return _().prepare("SELECT session_id, alias, updated_at, previous_aliases FROM session_aliases").all().map(t=>({session_id:t.session_id,alias:t.alias,updated_at:t.updated_at,previous_aliases:Kn(t.previous_aliases)}))}function ys(e,t){let s=t.trim();if(!s)throw new Error("alias must be non-empty");let n=_(),r=new Date().toISOString(),o=n.prepare("SELECT alias, previous_aliases FROM session_aliases WHERE session_id = ?").get(e),i=[];return o&&(i=Kn(o.previous_aliases),o.alias!==s&&i.push({alias:o.alias,replaced_at:r})),n.prepare(`INSERT INTO session_aliases (session_id, alias, updated_at, previous_aliases)
641
+ `),!0):!1}var _e=N(()=>{"use strict";Pt();In();vn();$n();jn();mi()});import{writeFileSync as bR,readFileSync as Pm,existsSync as Fm}from"node:fs";import{join as Um}from"node:path";function fi(){if(!Fm(fs))return null;try{return Pm(fs,"utf8").trim()}catch{return null}}var fs,Hn=N(()=>{"use strict";j();fs=Um(x,"daemon.token")});import{existsSync as _i,readFileSync as Bm,writeFileSync as xR,unlinkSync as Hm}from"node:fs";import{join as Xn}from"node:path";function Xm(){if(!_i(Wn))return null;try{let e=JSON.parse(Bm(Wn,"utf8"));return typeof e.pid!="number"||typeof e.port!="number"?null:e}catch{return null}}function Jn(){for(let e of[Wn,Wm,fs])if(_i(e))try{Hm(e)}catch{}}function Jm(e){try{return process.kill(e,0),!0}catch{return!1}}function K(){let e=Xm();return e?Jm(e.pid)?e:(Jn(),null):null}var Wn,Wm,_s,We=N(()=>{"use strict";j();Hn();Wn=Xn(x,"daemon.pid"),Wm=Xn(x,"daemon.port"),_s=Xn(x,"daemon.log")});import{writeFileSync as Og}from"node:fs";import{join as Ag}from"node:path";function Kn(e){try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return[]}function Ki(e){return _().prepare("SELECT alias FROM session_aliases WHERE session_id = ?").get(e)?.alias??null}function vg(){return _().prepare("SELECT session_id, alias, updated_at, previous_aliases FROM session_aliases").all().map(t=>({session_id:t.session_id,alias:t.alias,updated_at:t.updated_at,previous_aliases:Kn(t.previous_aliases)}))}function ys(e,t){let s=t.trim();if(!s)throw new Error("alias must be non-empty");let n=_(),r=new Date().toISOString(),o=n.prepare("SELECT alias, previous_aliases FROM session_aliases WHERE session_id = ?").get(e),i=[];return o&&(i=Kn(o.previous_aliases),o.alias!==s&&i.push({alias:o.alias,replaced_at:r})),n.prepare(`INSERT INTO session_aliases (session_id, alias, updated_at, previous_aliases)
642
642
  VALUES (?, ?, ?, ?)
643
643
  ON CONFLICT(session_id) DO UPDATE SET
644
644
  alias = excluded.alias,
@@ -657,10 +657,10 @@ ${t.message}
657
657
  ORDER BY COALESCE(timestamp, ''), rowid`).all(i.id),c=lf(a,5).map(u=>`${u.role}: ${u.content_text.slice(0,400)}`).join(`
658
658
  ---
659
659
  `);return{id:i.id,project:i.project,git_branch:i.git_branch,alias:i.alias,first_user_message:i.first_user_message,message_sample:c,current_tags:da(i.id)}})}var pa=N(()=>{"use strict";T();Zn()});import{z as we}from"zod";function ma(e){let t=e.minTags??2,s=e.maxTags??4,n=e.untaggedOnly??!e.sessionId,r=["Auto-tag my Claude Recall sessions using the MCP tools available to you.","","1. Call `list_tags` first to see which tags I already use (prefer those for consistency over inventing new ones).","2. Call `list_sessions_to_tag` with these filters:"],o=[];return e.sessionId?(o.push("limit: 1"),r.push(` ${o.join(", ")}`),r.push(` Then match the session id ${e.sessionId} from the returned list.`)):(n&&o.push("untaggedOnly: true"),e.project&&o.push(`project: "${e.project}"`),e.collectionId&&o.push(`collectionId: "${e.collectionId}"`),o.push(`limit: ${e.limit??100}`),r.push(` ${o.join(", ")}`)),r.push(""),r.push(`3. For each session returned, look at the alias, first user message, git branch, and sampled messages. Pick ${t}-${s} concise, lowercase, hyphen-separated tags describing:`),r.push(" - domain/subsystem (auth, db, frontend, billing, etc.)"),r.push(" - kind of work (bugfix, feature, refactor, research)"),r.push(" - prominent tools or libraries if relevant"),r.push(""),r.push("4. Call `apply_tags` once per session to write the tags."),r.push(""),r.push("Work through EVERY session returned \u2014 do not stop partway. When done, reply with a short summary of how many sessions were tagged. Do not ask clarifying questions; just do the work."),r.join(`
660
- `)}var Nk,Ck,Lk,Ok,ga=N(()=>{"use strict";Nk={project:we.string().optional().describe("Exact project name match (optional)."),collectionId:we.string().optional().describe("Restrict to sessions in this collection (optional)."),sessionId:we.string().optional().describe("Full session UUID to tag just one session (optional)."),untaggedOnly:we.boolean().optional().describe("Skip sessions that already have any tag (default: true)."),limit:we.number().int().min(1).max(500).optional().describe("Max sessions to process (default: 100)."),minTags:we.number().int().min(1).max(10).optional().describe("Minimum tags per session (default: 2)."),maxTags:we.number().int().min(1).max(10).optional().describe("Maximum tags per session (default: 4).")};Ck={sessionId:we.string().describe("Session UUID (or 8+-char prefix) to summarize."),mode:we.enum(["brief","detailed"]).optional().describe("brief = 3-5 bullets; detailed = paragraph + bullets. Default: brief.")},Lk={sessionId:we.string().describe("Session UUID (or 8+-char prefix) to extract decisions from.")},Ok={sessionId:we.string().describe("Session UUID (or 8+-char prefix) to find similar sessions to."),limit:we.number().int().min(1).max(20).optional().describe("How many similar sessions to surface (default: 5).")}});function fa(e,t){let s=df.get(e);if(!(!s||s.size===0))for(let n of s)try{n(t)}catch{}}var df,_a=N(()=>{"use strict";df=new Map});var Qn={};fe(Qn,{buildScanPrompt:()=>ha,isClaudeCliAvailable:()=>ce,runClaudeCliScan:()=>Sf,spawnClaudePrompt:()=>mt});import{execFileSync as uf,execSync as pf,spawn as mf}from"node:child_process";function ff(){if(Bt)return Bt;try{Bt=pf("which claude",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{Bt="claude"}return Bt}function ce(){try{return uf("command",["-v","claude"],{stdio:"ignore"}),!0}catch{return!1}}function ha(e){return ma({project:e.project,collectionId:e.collectionId,sessionId:e.sessionIds&&e.sessionIds.length===1?e.sessionIds[0]:void 0,untaggedOnly:e.untaggedOnly,limit:e.limit})}function _f(e,t){let s=t.get(e);return s||e.slice(0,8)}function hf(e){try{return ua(e).map(s=>({id:s.id,label:s.alias&&s.alias.trim().length>0?s.alias:s.first_user_message&&s.first_user_message.trim().length>0?s.first_user_message.slice(0,60):s.id.slice(0,8)}))}catch{return[]}}function Ef(e){let{scanId:t,total:s,labelTable:n}=e,r=new Set;return o=>{let i=o.trim();if(!i.startsWith("{"))return;let a;try{a=JSON.parse(i)}catch{return}if(!a||typeof a!="object")return;let l=a;if(!(l.type!=="assistant"||!l.message?.content))for(let c of l.message.content){if(c?.type!=="tool_use"||c.name!=="mcp__recall__apply_tags")continue;let u=c.input,p=typeof u?.sessionId=="string"?u.sessionId:null;!p||r.has(p)||(r.add(p),fa(t,{type:"progress",current:r.size,total:s,sessionId:p,sessionLabel:_f(p,n)}))}}}function bf(e){let t="";return s=>{t+=s.toString("utf8");let n=t.indexOf(`
660
+ `)}var Lk,Ok,Ak,Ik,ga=N(()=>{"use strict";Lk={project:we.string().optional().describe("Exact project name match (optional)."),collectionId:we.string().optional().describe("Restrict to sessions in this collection (optional)."),sessionId:we.string().optional().describe("Full session UUID to tag just one session (optional)."),untaggedOnly:we.boolean().optional().describe("Skip sessions that already have any tag (default: true)."),limit:we.number().int().min(1).max(500).optional().describe("Max sessions to process (default: 100)."),minTags:we.number().int().min(1).max(10).optional().describe("Minimum tags per session (default: 2)."),maxTags:we.number().int().min(1).max(10).optional().describe("Maximum tags per session (default: 4).")};Ok={sessionId:we.string().describe("Session UUID (or 8+-char prefix) to summarize."),mode:we.enum(["brief","detailed"]).optional().describe("brief = 3-5 bullets; detailed = paragraph + bullets. Default: brief.")},Ak={sessionId:we.string().describe("Session UUID (or 8+-char prefix) to extract decisions from.")},Ik={sessionId:we.string().describe("Session UUID (or 8+-char prefix) to find similar sessions to."),limit:we.number().int().min(1).max(20).optional().describe("How many similar sessions to surface (default: 5).")}});function fa(e,t){let s=df.get(e);if(!(!s||s.size===0))for(let n of s)try{n(t)}catch{}}var df,_a=N(()=>{"use strict";df=new Map});var Qn={};fe(Qn,{buildScanPrompt:()=>ha,isClaudeCliAvailable:()=>ce,runClaudeCliScan:()=>Sf,spawnClaudePrompt:()=>mt});import{execFileSync as uf,execSync as pf,spawn as mf}from"node:child_process";function ff(){if(Bt)return Bt;try{Bt=pf("which claude",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{Bt="claude"}return Bt}function ce(){try{return uf("command",["-v","claude"],{stdio:"ignore"}),!0}catch{return!1}}function ha(e){return ma({project:e.project,collectionId:e.collectionId,sessionId:e.sessionIds&&e.sessionIds.length===1?e.sessionIds[0]:void 0,untaggedOnly:e.untaggedOnly,limit:e.limit})}function _f(e,t){let s=t.get(e);return s||e.slice(0,8)}function hf(e){try{return ua(e).map(s=>({id:s.id,label:s.alias&&s.alias.trim().length>0?s.alias:s.first_user_message&&s.first_user_message.trim().length>0?s.first_user_message.slice(0,60):s.id.slice(0,8)}))}catch{return[]}}function Ef(e){let{scanId:t,total:s,labelTable:n}=e,r=new Set;return o=>{let i=o.trim();if(!i.startsWith("{"))return;let a;try{a=JSON.parse(i)}catch{return}if(!a||typeof a!="object")return;let l=a;if(!(l.type!=="assistant"||!l.message?.content))for(let c of l.message.content){if(c?.type!=="tool_use"||c.name!=="mcp__recall__apply_tags")continue;let u=c.input,p=typeof u?.sessionId=="string"?u.sessionId:null;!p||r.has(p)||(r.add(p),fa(t,{type:"progress",current:r.size,total:s,sessionId:p,sessionLabel:_f(p,n)}))}}}function bf(e){let t="";return s=>{t+=s.toString("utf8");let n=t.indexOf(`
661
661
  `);for(;n!==-1;){let r=t.slice(0,n);t=t.slice(n+1),r.length>0&&e(r),n=t.indexOf(`
662
662
  `)}}}async function Sf(e,t={},s){let n=!!t.scanId,r=n?hf(e):[],o=new Map(r.map(l=>[l.id,l.label])),i=r.length,a;return n&&t.scanId&&(a=Ef({scanId:t.scanId,total:i,labelTable:o})),Ea({prompt:ha(e),allowedTools:gf.split(","),opts:t,onProgress:s,onStdoutLine:a,outputFormat:n?"stream-json":"json"})}async function mt(e,t,s={},n){return Ea({prompt:e,allowedTools:t,opts:s,onProgress:n,outputFormat:"json"})}function Ea(e){let{prompt:t,allowedTools:s,opts:n,onProgress:r,onStdoutLine:o,outputFormat:i}=e,a=["-p",t,"--output-format",i,"--allowedTools",s.join(","),"--permission-mode","bypassPermissions"];return i==="stream-json"&&a.push("--verbose"),n.model&&a.push("--model",n.model),new Promise(l=>{let c=mf(ff(),a,{stdio:["ignore","pipe","pipe"]}),u=[],p=[],m=o?bf(o):void 0;c.stdout.on("data",g=>{u.push(g),m&&m(g)}),c.stderr.on("data",g=>{if(p.push(g),r){let h=g.toString("utf8").trim();h&&r(h)}});let f=setTimeout(()=>{c.kill("SIGKILL")},1800*1e3);c.on("close",g=>{clearTimeout(f),l({success:g===0,stdout:Buffer.concat(u).toString("utf8"),stderr:Buffer.concat(p).toString("utf8"),exitCode:g})}),c.on("error",g=>{clearTimeout(f),l({success:!1,stdout:"",stderr:String(g),exitCode:null})})})}var gf,Bt,Je=N(()=>{"use strict";pa();ga();_a();gf=["mcp__recall__list_tags","mcp__recall__list_sessions_to_tag","mcp__recall__apply_tags"].join(",")});var wa={};fe(wa,{downloadModel:()=>nr,getModelDir:()=>Ns,isModelInstalled:()=>gt,uninstallModel:()=>rr});import{existsSync as sr,mkdirSync as ya,rmSync as tr,createWriteStream as Ff,statSync as Uf}from"node:fs";import{join as ks}from"node:path";import{createHash as Bf}from"node:crypto";import{readFile as Hf}from"node:fs/promises";function Ns(){return ks(x,"models","BAAI","bge-base-en-v1.5")}function gt(){let e=Ns();return Ta.every(t=>sr(ks(e,t.path)))}async function nr(e){let t=Ns();ya(t,{recursive:!0}),ya(ks(t,"onnx"),{recursive:!0});for(let s of Ta){let n=ks(t,s.path),r=Wf+s.path,o=0;sr(n)&&(o=Uf(n).size);let i={};o>0&&(i.Range=`bytes=${o}-`);let a=await fetch(r,{headers:i});if(!a.ok&&a.status!==206)throw new Error(`Failed to download ${s.path}: HTTP ${a.status}`);let l=a.headers.get("content-length"),c=l?o+Number(l):0,u=a.body;if(!u)throw new Error(`No response body for ${s.path}`);let p=Ff(n,{flags:o>0?"a":"w"}),m=u.getReader(),f=o;for(;;){let{done:E,value:b}=await m.read();if(E)break;p.write(Buffer.from(b)),f+=b.byteLength,e?.(s.path,f,c)}if(p.end(),await new Promise((E,b)=>{p.on("finish",E),p.on("error",b)}),s.sha256==="TODO_PLACEHOLDER")throw tr(n),new Error(`Refusing to install: SHA-256 not pinned for ${s.path}. Update model-download.ts.`);let g=await Hf(n);if(Bf("sha256").update(g).digest("hex")!==s.sha256)throw tr(n),new Error(`SHA-256 mismatch for ${s.path}`)}}function rr(){let e=Ns();sr(e)&&tr(e,{recursive:!0,force:!0})}var Wf,Ta,Cs=N(()=>{"use strict";j();Wf="https://huggingface.co/BAAI/bge-base-en-v1.5/resolve/main/",Ta=[{path:"config.json",sha256:"bc00af31a4a31b74040d73370aa83b62da34c90b75eb77bfa7db039d90abd591"},{path:"tokenizer.json",sha256:"d241a60d5e8f04cc1b2b3e9ef7a4921b27bf526d9f6050ab90f9267a1f9e5c66"},{path:"tokenizer_config.json",sha256:"9261e7d79b44c8195c1cada2b453e55b00aeb81e907a6664974b4d7776172ab3"},{path:"onnx/model.onnx",sha256:"9bc579acdba21c253c62a9bf866891355a63ffa3442b52c8a37d75b2ccb91848"}]});var ir={};fe(ir,{EmbedderUnavailableError:()=>Wt,embed:()=>ft,embedQuery:()=>or,getEmbedderStatus:()=>Ge,loadEmbedder:()=>Ke,unloadEmbedder:()=>zf});import{join as Ra}from"node:path";function Gf(){return Ra(x,"models","bge-base-en-v1.5")}async function Ke(){if(Ls&&Ht)return;let e;try{e=await import("@huggingface/transformers")}catch(n){throw new Wt(n)}let{pipeline:t,env:s}=e;s.localModelPath=Ra(x,"models"),s.allowRemoteModels=!1;try{Ht=await t("feature-extraction",ka,{local_files_only:!0,cache_dir:Gf()}),Ls=!0}catch(n){throw n instanceof Error&&/Cannot find module|onnxruntime_binding/.test(n.message)?new Wt(n):n}}function Ge(){return{loaded:Ls,modelId:ka,dim:Xf}}async function ft(e){if(!Ht)throw new Error("[embedder] Model not loaded. Call loadEmbedder() before embedding.");let t=[];for(let s=0;s<e.length;s+=xa){let n=e.slice(s,s+xa),o=(await Ht(n,{pooling:"cls",normalize:!0})).tolist();for(let i=0;i<n.length;i++){let a=o[i],l=Array.isArray(a[0])?a[0]:a;t.push(new Float32Array(l))}}return t}async function or(e){let t=Jf+e,[s]=await ft([t]);return s}function zf(){Ht=null,Ls=!1}var ka,Xf,xa,Jf,Ht,Ls,Wt,Ve=N(()=>{"use strict";j();ka="BAAI/bge-base-en-v1.5",Xf=768,xa=16,Jf="Represent this sentence for searching relevant passages: ",Ht=null,Ls=!1;Wt=class extends Error{cause;constructor(t){let s=t instanceof Error?t.message:String(t);super(["Semantic search is unavailable on this platform.","",`Reason: ${s}`,"",`Platform: ${process.platform}/${process.arch}, Node ${process.version}`,"","Claude Recall supports macOS (arm64/x64), Linux (x64/arm64), and Windows (x64).","Core CLI features (search, list, context, daemon) work everywhere.","Only `recall semantic *` requires the on-device embedder.","","See: https://clauderecall.com/docs (Supported platforms) \u2014 or file an issue at","https://gitlab.com/clauderecallhq/clauderecallhq/-/issues with the platform line above."].join(`
663
- `)),this.name="EmbedderUnavailableError",this.cause=t}}});var La={};fe(La,{ensureTransformersInstalled:()=>a_});import{spawn as Zf}from"node:child_process";import{existsSync as Qf}from"node:fs";import{dirname as e_,resolve as t_}from"node:path";import{fileURLToPath as s_}from"node:url";function r_(){let e=e_(s_(import.meta.url));return t_(e,"..","..")}async function o_(){try{return await import("@huggingface/transformers"),!0}catch{return!1}}function i_(e){return new Promise(t=>{let s=["install","--no-save","--no-audit","--no-fund","--prefix",e,`@huggingface/transformers@${n_}`],n=Zf("npm",s,{stdio:["ignore","inherit","inherit"],cwd:e});n.on("error",r=>{t({ok:!1,error:`npm spawn failed: ${r instanceof Error?r.message:String(r)}`})}),n.on("exit",r=>{t(r===0?{ok:!0,action:"installed"}:{ok:!1,error:`npm install exited with code ${r}`})})})}async function a_(){if(await o_())return{ok:!0,action:"already-installed"};let e=r_();return Qf(e)?(console.log(`Installing @huggingface/transformers into ${e} ...`),i_(e)):{ok:!1,error:`package root not found at ${e}`}}var n_,Oa=N(()=>{"use strict";n_="^3.4.1"});import{writeFileSync as Xa,readFileSync as qN,existsSync as Ja,mkdirSync as Ga,readdirSync as KN}from"node:fs";import{join as Is}from"node:path";function z_(){P(),Ja(mr)||Ga(mr,{recursive:!0})}function Y_(){P(),Ja(gr)||Ga(gr,{recursive:!0})}function za(e){try{return JSON.parse(e)}catch{return e}}function fr(e){return{id:e.id,source_session_id:e.source_session_id,target_session_id:e.target_session_id,link_type:e.link_type,confidence:e.confidence,source:e.source,evidence:za(e.evidence),approved:e.approved===1,created_at:e.created_at,updated_at:e.updated_at}}function _r(e){return{id:e.id,source_session_id:e.source_session_id,target_session_id:e.target_session_id,link_type:e.link_type,confidence:e.confidence,evidence:za(e.evidence),status:e.status,inferred_by:e.inferred_by,created_at:e.created_at,decided_at:e.decided_at}}function q_(e){if(!Number.isFinite(e)||e<0||e>1)throw new Error("confidence must be a number in [0, 1]")}function Ya(e){if(!H_.has(e))throw new Error(`invalid link_type: ${e}`)}function qa(e){if(!J_.has(e))throw new Error(`invalid inferred_by: ${e}`)}function K_(e,t){if(!e||!t)throw new Error("source_session_id and target_session_id are required");if(e===t)throw new Error("a session cannot link to itself")}function V_(e={}){let t=_(),s=[],n=[];e.sourceSessionId&&(s.push("source_session_id = ?"),n.push(e.sourceSessionId)),e.targetSessionId&&(s.push("target_session_id = ?"),n.push(e.targetSessionId)),e.linkType&&(Ya(e.linkType),s.push("link_type = ?"),n.push(e.linkType)),e.approvedOnly&&s.push("approved = 1");let r=s.length?`WHERE ${s.join(" AND ")}`:"",o=Math.max(1,Math.min(5e3,e.limit??1e3));return t.prepare(`SELECT * FROM session_links ${r}
663
+ `)),this.name="EmbedderUnavailableError",this.cause=t}}});var La={};fe(La,{ensureTransformersInstalled:()=>a_});import{spawn as Zf}from"node:child_process";import{existsSync as Qf}from"node:fs";import{dirname as e_,resolve as t_}from"node:path";import{fileURLToPath as s_}from"node:url";function r_(){let e=e_(s_(import.meta.url));return t_(e,"..","..")}async function o_(){try{return await import("@huggingface/transformers"),!0}catch{return!1}}function i_(e){return new Promise(t=>{let s=["install","--no-save","--no-audit","--no-fund","--prefix",e,`@huggingface/transformers@${n_}`],n=Zf("npm",s,{stdio:["ignore","inherit","inherit"],cwd:e});n.on("error",r=>{t({ok:!1,error:`npm spawn failed: ${r instanceof Error?r.message:String(r)}`})}),n.on("exit",r=>{t(r===0?{ok:!0,action:"installed"}:{ok:!1,error:`npm install exited with code ${r}`})})})}async function a_(){if(await o_())return{ok:!0,action:"already-installed"};let e=r_();return Qf(e)?(console.log(`Installing @huggingface/transformers into ${e} ...`),i_(e)):{ok:!1,error:`package root not found at ${e}`}}var n_,Oa=N(()=>{"use strict";n_="^3.4.1"});import{writeFileSync as Xa,readFileSync as VN,existsSync as Ja,mkdirSync as Ga,readdirSync as ZN}from"node:fs";import{join as Is}from"node:path";function z_(){P(),Ja(mr)||Ga(mr,{recursive:!0})}function Y_(){P(),Ja(gr)||Ga(gr,{recursive:!0})}function za(e){try{return JSON.parse(e)}catch{return e}}function fr(e){return{id:e.id,source_session_id:e.source_session_id,target_session_id:e.target_session_id,link_type:e.link_type,confidence:e.confidence,source:e.source,evidence:za(e.evidence),approved:e.approved===1,created_at:e.created_at,updated_at:e.updated_at}}function _r(e){return{id:e.id,source_session_id:e.source_session_id,target_session_id:e.target_session_id,link_type:e.link_type,confidence:e.confidence,evidence:za(e.evidence),status:e.status,inferred_by:e.inferred_by,created_at:e.created_at,decided_at:e.decided_at}}function q_(e){if(!Number.isFinite(e)||e<0||e>1)throw new Error("confidence must be a number in [0, 1]")}function Ya(e){if(!H_.has(e))throw new Error(`invalid link_type: ${e}`)}function qa(e){if(!J_.has(e))throw new Error(`invalid inferred_by: ${e}`)}function K_(e,t){if(!e||!t)throw new Error("source_session_id and target_session_id are required");if(e===t)throw new Error("a session cannot link to itself")}function V_(e={}){let t=_(),s=[],n=[];e.sourceSessionId&&(s.push("source_session_id = ?"),n.push(e.sourceSessionId)),e.targetSessionId&&(s.push("target_session_id = ?"),n.push(e.targetSessionId)),e.linkType&&(Ya(e.linkType),s.push("link_type = ?"),n.push(e.linkType)),e.approvedOnly&&s.push("approved = 1");let r=s.length?`WHERE ${s.join(" AND ")}`:"",o=Math.max(1,Math.min(5e3,e.limit??1e3));return t.prepare(`SELECT * FROM session_links ${r}
664
664
  ORDER BY confidence DESC, updated_at DESC
665
665
  LIMIT ?`).all(...n,o).map(fr)}function hr(e){return _().prepare(`SELECT * FROM session_links
666
666
  WHERE source_session_id = ? OR target_session_id = ?
@@ -734,15 +734,15 @@ ${t.message}
734
734
  COUNT(DISTINCT st.session_id) AS tagged
735
735
  FROM sessions s
736
736
  LEFT JOIN session_tags st ON st.session_id = s.id
737
- WHERE s.project_id = ?`).get(e),h=g.total>0?g.tagged/g.total:0,E=qt(h),b=Math.round((o*.2+a*.25+u*.15+f*.2+E*.2)*100);return{projectId:e,projectName:s.name,score:b,breakdown:{sessionCount:{raw:r,score:o,weight:.2},recency:{daysSinceLastSession:Math.round(i),score:a,weight:.25},fragmentation:{avgMessages:Math.round(c*10)/10,score:u,weight:.15},searchCoverage:{ratio:Math.round(m*100)/100,score:f,weight:.2},tagCoverage:{ratio:Math.round(h*100)/100,score:E,weight:.2}}}}function Ur(e){let s=_().prepare("SELECT id FROM projects WHERE name = ?").get(e);return s?Fr(s.id):null}function Br(){let t=_().prepare("SELECT id FROM projects ORDER BY name").all(),s=[];for(let n of t){let r=Fr(n.id);r&&s.push(r)}return s}var Hr=N(()=>{"use strict";T()});function vd(e,t){return{type:"svg",props:{width:e,height:e,viewBox:"0 0 64 64",style:{display:"flex"},children:[{type:"line",props:{x1:14,y1:16,x2:46,y2:16,stroke:t,strokeWidth:3,strokeLinecap:"round"}},{type:"line",props:{x1:14,y1:24,x2:38,y2:24,stroke:t,strokeWidth:3,strokeLinecap:"round"}},{type:"line",props:{x1:10,y1:32,x2:54,y2:32,stroke:yt,strokeWidth:5,strokeLinecap:"round"}},{type:"line",props:{x1:14,y1:40,x2:42,y2:40,stroke:t,strokeWidth:3,strokeLinecap:"round"}},{type:"line",props:{x1:14,y1:48,x2:36,y2:48,stroke:t,strokeWidth:3,strokeLinecap:"round"}}]}}}function st(e,t){return{type:"div",props:{style:{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%"},children:[{type:"div",props:{style:{display:"flex",alignItems:"center",gap:"18px"},children:[vd(72,e.markStroke),{type:"span",props:{style:{fontSize:"36px",fontWeight:700,color:e.wordmarkFg,letterSpacing:"-0.01em"},children:"Claude Recall"}}]}},{type:"span",props:{style:{fontSize:"17px",color:e.wordmarkFg,opacity:.6,textTransform:"uppercase",letterSpacing:"0.18em",fontWeight:600},children:t}}]}}}function nt(e){return{type:"div",props:{style:{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%"},children:[{type:"div",props:{style:{display:"flex",alignItems:"center",gap:"14px"},children:[vd(52,e.markStroke),{type:"span",props:{style:{fontSize:"24px",fontWeight:700,color:e.wordmarkFg},children:"clauderecall.com"}}]}},{type:"span",props:{style:{fontSize:"20px",color:e.wordmarkFg,opacity:.7,fontWeight:500},children:"local memory for Claude Code"}}]}}}function jy(e){return e>=1e9?`${(e/1e9).toFixed(2).replace(/\.?0+$/,"")}B`:e>=1e6?`${(e/1e6).toFixed(2).replace(/\.?0+$/,"")}M`:e>=1e3?`${(e/1e3).toFixed(1).replace(/\.0$/,"")}k`:String(e)}function Py(e){return e.toLocaleString("en-US")}function rt(e){return e<1e3?String(e):`${jy(e)} (${Py(e)})`}function ot(e){return new Date(e).toLocaleDateString("en-US",{month:"long",day:"numeric",year:"numeric"})}var yt,Vt=N(()=>{"use strict";yt="#f97316"});var Dd={};fe(Dd,{render:()=>By});function Qs(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[{type:"span",props:{style:{fontSize:"34px",fontWeight:700,color:Zt,fontFamily:"JetBrains Mono"},children:e}},{type:"span",props:{style:{fontSize:"14px",color:en,textTransform:"uppercase",letterSpacing:"0.16em"},children:t}}]}}}function By(e){let s=[ot(e.sessionDate)];e.durationLabel&&s.push(e.durationLabel);let n=s.join(" \xB7 "),r=e.costDollars??"$\u2014",o=typeof e.cachedTokens=="number"&&e.cachedTokens>=1e5?`+ ${rt(e.cachedTokens)} cached`:null,i=[st(Md,"session receipt"),{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[{type:"div",props:{style:{fontSize:"44px",fontWeight:700,color:Zt,lineHeight:1.15,wordBreak:"break-word"},children:e.sessionTitle}},{type:"div",props:{style:{fontSize:"20px",color:en},children:n}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"32px 0"},children:[{type:"span",props:{style:{fontSize:"180px",fontWeight:700,color:yt,fontFamily:"JetBrains Mono",lineHeight:1,letterSpacing:"-0.04em"},children:r}},{type:"span",props:{style:{marginTop:"16px",fontSize:"16px",color:en,textTransform:"uppercase",letterSpacing:"0.24em",fontWeight:600},children:"session cost"}}]}},{type:"div",props:{style:{display:"flex",width:"100%",height:"1px",backgroundColor:Uy}}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",gap:"24px"},children:[Qs(String(e.messageCount),"msgs"),Qs(String(e.filesReferenced),"files"),Qs(String(e.toolCallCount),"tools"),Qs(e.model??"\u2014","model")]}}];return o&&i.push({type:"div",props:{style:{fontSize:"14px",color:en,fontFamily:"JetBrains Mono",opacity:.7},children:o}}),e.verdict&&i.push({type:"div",props:{style:{display:"flex",fontSize:"24px",fontStyle:"italic",color:Zt,borderLeft:`3px solid ${yt}`,paddingLeft:"20px",marginTop:"8px"},children:`"${e.verdict}"`}}),i.push({type:"div",props:{style:{display:"flex",flex:1}}}),i.push(nt(Md)),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundColor:Fy,padding:"64px 72px",fontFamily:"Inter",gap:"28px"},children:i}}}var Fy,Zt,en,Uy,Md,$d=N(()=>{"use strict";Vt();Fy="#1a1b1e",Zt="#e7e9ee",en="#8b9098",Uy="#2a2c33",Md={markStroke:Zt,wordmarkFg:Zt}});var Pd={};fe(Pd,{render:()=>Xy});function tn(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[{type:"span",props:{style:{fontSize:"34px",fontWeight:700,color:Qt,fontFamily:"JetBrains Mono"},children:e}},{type:"span",props:{style:{fontSize:"14px",color:sn,fontFamily:"JetBrains Mono",textTransform:"lowercase"},children:`// ${t}`}}]}}}function Xy(e){let t=[ot(e.sessionDate),e.durationLabel].filter(Boolean).join(" \xB7 "),s=e.costDollars??"$\u2014",n=typeof e.cachedTokens=="number"&&e.cachedTokens>=1e5?`# ${rt(e.cachedTokens)} tokens cache-replayed (free)`:null,r=[st(jd,"recall.cli/share"),{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"6px"},children:[{type:"div",props:{style:{fontSize:"18px",color:eo,fontFamily:"JetBrains Mono"},children:"$ recall share --session"}},{type:"div",props:{style:{fontSize:"40px",fontWeight:700,color:Qt,lineHeight:1.15,wordBreak:"break-word",fontFamily:"JetBrains Mono"},children:e.sessionTitle}},{type:"div",props:{style:{fontSize:"18px",color:sn,fontFamily:"JetBrains Mono"},children:t}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"flex-start",padding:"12px 0"},children:[{type:"span",props:{style:{fontSize:"20px",color:sn,fontFamily:"JetBrains Mono"},children:"> total_cost:"}},{type:"span",props:{style:{fontSize:"180px",fontWeight:700,color:eo,fontFamily:"JetBrains Mono",lineHeight:1,letterSpacing:"-0.04em"},children:s}}]}},{type:"div",props:{style:{display:"flex",width:"100%",height:"1px",backgroundColor:Wy}}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",gap:"24px"},children:[tn(String(e.messageCount),"msgs"),tn(String(e.filesReferenced),"files"),tn(String(e.toolCallCount),"tools"),tn(e.model??"\u2014","model")]}}];return n&&r.push({type:"div",props:{style:{fontSize:"14px",color:sn,fontFamily:"JetBrains Mono",opacity:.7},children:n}}),e.verdict&&r.push({type:"div",props:{style:{display:"flex",fontSize:"22px",color:Qt,fontFamily:"JetBrains Mono",borderLeft:`3px solid ${eo}`,paddingLeft:"20px",marginTop:"8px"},children:`// ${e.verdict}`}}),r.push({type:"div",props:{style:{display:"flex",flex:1}}}),r.push(nt(jd)),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundColor:Hy,padding:"64px 72px",fontFamily:"Inter",gap:"28px"},children:r}}}var Hy,Qt,sn,Wy,eo,jd,Fd=N(()=>{"use strict";Vt();Hy="#0d0d0f",Qt="#e1e7ee",sn="#6b7480",Wy="#1f2229",eo="#7ee787",jd={markStroke:Qt,wordmarkFg:Qt}});var Bd={};fe(Bd,{render:()=>Gy});function nn(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[{type:"span",props:{style:{fontSize:"34px",fontWeight:700,color:Tt,fontFamily:"JetBrains Mono"},children:e}},{type:"span",props:{style:{fontSize:"14px",color:rn,textTransform:"uppercase",letterSpacing:"0.16em",fontWeight:600},children:t}}]}}}function Gy(e){let t=[ot(e.sessionDate),e.durationLabel].filter(Boolean).join(" \xB7 "),s=e.costDollars??"$\u2014",n=typeof e.cachedTokens=="number"&&e.cachedTokens>=1e5?`+ ${rt(e.cachedTokens)} cached`:null,r=[st(Ud,"session receipt"),{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[{type:"div",props:{style:{fontSize:"44px",fontWeight:700,color:Tt,lineHeight:1.15,wordBreak:"break-word"},children:e.sessionTitle}},{type:"div",props:{style:{fontSize:"20px",color:rn},children:t}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"32px 0"},children:[{type:"span",props:{style:{fontSize:"180px",fontWeight:700,color:Tt,fontFamily:"JetBrains Mono",lineHeight:1,letterSpacing:"-0.04em"},children:s}},{type:"span",props:{style:{marginTop:"16px",fontSize:"16px",color:rn,textTransform:"uppercase",letterSpacing:"0.24em",fontWeight:600},children:"session cost"}}]}},{type:"div",props:{style:{display:"flex",width:"100%",height:"1px",backgroundColor:Jy}}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",gap:"24px"},children:[nn(String(e.messageCount),"msgs"),nn(String(e.filesReferenced),"files"),nn(String(e.toolCallCount),"tools"),nn(e.model??"\u2014","model")]}}];return n&&r.push({type:"div",props:{style:{fontSize:"14px",color:rn,fontFamily:"JetBrains Mono",opacity:.85},children:n}}),e.verdict&&r.push({type:"div",props:{style:{display:"flex",fontSize:"24px",fontStyle:"italic",color:Tt,borderLeft:`3px solid ${Tt}`,paddingLeft:"20px",marginTop:"8px"},children:`"${e.verdict}"`}}),r.push({type:"div",props:{style:{display:"flex",flex:1}}}),r.push(nt(Ud)),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundImage:"linear-gradient(135deg, #b1370f 0%, #f97316 55%, #fbbf24 100%)",padding:"64px 72px",fontFamily:"Inter",gap:"28px"},children:r}}}var Tt,rn,Jy,Ud,Hd=N(()=>{"use strict";Vt();Tt="#ffffff",rn="rgba(255,255,255,0.7)",Jy="rgba(255,255,255,0.18)",Ud={markStroke:Tt,wordmarkFg:Tt}});var Xd={};fe(Xd,{render:()=>Vy});function on(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[{type:"span",props:{style:{fontSize:"34px",fontWeight:800,color:Lt,fontFamily:"JetBrains Mono"},children:e}},{type:"span",props:{style:{fontSize:"14px",color:es,textTransform:"uppercase",letterSpacing:"0.16em",fontWeight:600},children:t}}]}}}function Ky(e){let t=e.reduce((s,n)=>s+n.value,0)||1;return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[{type:"div",props:{style:{display:"flex",width:"100%",height:"10px",borderRadius:"5px",backgroundColor:qy,overflow:"hidden"},children:e.map(s=>({type:"div",props:{style:{display:"flex",width:`${s.value/t*100}%`,height:"100%",backgroundColor:s.color}}}))}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",fontSize:"12px",color:es,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.14em"},children:e.map(s=>({type:"span",props:{style:{display:"flex"},children:`${s.label} \xB7 ${s.value}`}}))}}]}}}function Vy(e){let t=[ot(e.sessionDate),e.durationLabel].filter(Boolean).join(" \xB7 "),s=e.costDollars??"$\u2014",n=typeof e.cachedTokens=="number"&&e.cachedTokens>=1e5?`+ ${rt(e.cachedTokens)} cached`:null,r=[st(Wd,"session receipt"),{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[{type:"div",props:{style:{fontSize:"40px",fontWeight:700,color:Lt,lineHeight:1.15,wordBreak:"break-word"},children:e.sessionTitle}},{type:"div",props:{style:{fontSize:"18px",color:es},children:t}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"flex-start",padding:"8px 0"},children:[{type:"span",props:{style:{fontSize:"14px",color:es,textTransform:"uppercase",letterSpacing:"0.24em",fontWeight:700},children:"session cost"}},{type:"span",props:{style:{fontSize:"180px",fontWeight:800,color:Lt,fontFamily:"JetBrains Mono",lineHeight:1,letterSpacing:"-0.04em"},children:s}}]}},{type:"div",props:{style:{display:"flex",width:"100%",height:"1px",backgroundColor:Yy}}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",gap:"24px"},children:[on(String(e.messageCount),"msgs"),on(String(e.filesReferenced),"files"),on(String(e.toolCallCount),"tools"),on(e.model??"\u2014","model")]}},Ky([{value:e.messageCount,color:yt,label:"msgs"},{value:e.filesReferenced,color:"#0a0a0a",label:"files"},{value:e.toolCallCount,color:"#5a6068",label:"tools"}])];return n&&r.push({type:"div",props:{style:{fontSize:"14px",color:es,fontFamily:"JetBrains Mono",opacity:.85},children:n}}),e.verdict&&r.push({type:"div",props:{style:{display:"flex",fontSize:"22px",fontStyle:"italic",color:Lt,borderLeft:`3px solid ${yt}`,paddingLeft:"20px",marginTop:"8px"},children:`"${e.verdict}"`}}),r.push({type:"div",props:{style:{display:"flex",flex:1}}}),r.push(nt(Wd)),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundColor:zy,padding:"64px 72px",fontFamily:"Inter",gap:"24px"},children:r}}}var zy,Lt,es,Yy,qy,Wd,Jd=N(()=>{"use strict";Vt();zy="#f6f7f9",Lt="#0a0a0a",es="#5a6068",Yy="#e3e6eb",qy="#dde1e7",Wd={markStroke:Lt,wordmarkFg:Lt}});var Gd={};fe(Gd,{render:()=>eT});function to(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"8px",flex:1},children:[{type:"div",props:{style:{fontSize:"52px",fontWeight:700,color:an},children:t}},{type:"div",props:{style:{fontSize:"16px",color:At,textTransform:"uppercase",letterSpacing:"2px"},children:e}}]}}}function so(e,t){return{type:"div",props:{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"16px 24px",backgroundColor:no,borderRadius:"12px"},children:[{type:"span",props:{style:{fontSize:"18px",color:At},children:e}},{type:"span",props:{style:{fontSize:"20px",fontWeight:700,color:an},children:t}}]}}}function eT(e){let t=Math.round(e.healthScore),s=[{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"8px"},children:[{type:"div",props:{style:{fontSize:"16px",color:At,textTransform:"uppercase",letterSpacing:"6px"},children:"YOUR MONTH IN CODE"}},{type:"div",props:{style:{fontSize:"44px",fontWeight:700,color:an},children:e.month}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"12px",backgroundColor:no,borderRadius:"16px",padding:"28px",border:`1px solid ${Ot}40`},children:[{type:"div",props:{style:{fontSize:"16px",color:Qy,textTransform:"uppercase",letterSpacing:"2px"},children:"You are a"}},{type:"div",props:{style:{fontSize:"36px",fontWeight:700,color:Ot},children:e.archetype}}]}},{type:"div",props:{style:{display:"flex",gap:"16px",width:"100%"},children:[to("Recalls",String(e.totalRecalls)),to("Tokens piped",e.totalTokensPiped>999999?`${(e.totalTokensPiped/1e6).toFixed(1)}M`:e.totalTokensPiped.toLocaleString()),to("Sessions",String(e.sessionsIndexed))]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px",width:"100%"},children:[{type:"div",props:{style:{fontSize:"14px",color:At,textTransform:"uppercase",letterSpacing:"2px",marginBottom:"4px"},children:"Highlights"}},so("Most recalled",e.mostRecalledSession),so("Biggest recall",`${e.biggestRecallTokens.toLocaleString()} tokens`),so("Peak hours",e.mostActiveHours)]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"12px"},children:[{type:"div",props:{style:{width:"100px",height:"100px",borderRadius:"50%",border:`6px solid ${Ot}`,display:"flex",alignItems:"center",justifyContent:"center"},children:{type:"span",props:{style:{fontSize:"32px",fontWeight:700,color:Ot},children:`${t}`}}}},{type:"div",props:{style:{fontSize:"14px",color:At,textTransform:"uppercase",letterSpacing:"2px"},children:"Memory health"}}]}}];return e.verdict&&s.push({type:"div",props:{style:{backgroundColor:no,borderLeft:`3px solid ${Ot}`,borderRadius:"8px",padding:"20px 24px",fontSize:"20px",color:an,fontStyle:"italic"},children:`"${e.verdict}"`}}),s.push({type:"div",props:{style:{display:"flex",alignItems:"center",justifyContent:"center",gap:"12px",marginTop:"auto"},children:[{type:"span",props:{style:{fontSize:"22px",fontWeight:700,color:Ot},children:"Claude Recall"}},{type:"span",props:{style:{fontSize:"18px",color:At},children:"clauderecall.com"}}]}}),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundColor:Zy,padding:"72px 64px",fontFamily:"Inter",gap:"36px"},children:s}}}var Zy,no,an,At,Ot,Qy,zd=N(()=>{"use strict";Zy="#0b0c0f",no="#15171c",an="#e7e9ee",At="#8b9098",Ot="#f97316",Qy="#fb923c"});var co,au,G,w,Z,Me,cu,lu,du,uu,lo,uo,it=N(()=>{"use strict";co=[String.raw` ___ _ _ _ _ ___ ___ ___ ___ ___ _ _ _ `,String.raw` / __| | /_\ | | | | \| __| | _ \ __/ __| /_\ | | | | `,String.raw`| (__| |__ / _ \| |_| | |) | _| | / _| (__ / _ \| |__| |__ `,String.raw` \___|____/_/ \_\\___/|___/|___| |_|_\___\___/_/ \_\____|____|`],au=co[0]?.length??64,G="#f97316",w="#8b9098",Z="#10b981",Me="#f59e0b",cu="#60a5fa",lu="#34d399",du="#c084fc",uu="CLAUDE RECALL",lo=100,uo=30});import{useEffect as AT,useState as IT}from"react";import{Box as pu,Text as pe}from"ink";import{createRequire as vT}from"node:module";import{existsSync as MT}from"node:fs";import{jsx as re,jsxs as gu}from"react/jsx-runtime";function mu({cols:e}){let[t,s]=IT(jT);AT(()=>{let r=!1,o=K(),i=0,a=0;if(MT(te))try{let c=_().prepare(`SELECT
737
+ WHERE s.project_id = ?`).get(e),h=g.total>0?g.tagged/g.total:0,E=qt(h),b=Math.round((o*.2+a*.25+u*.15+f*.2+E*.2)*100);return{projectId:e,projectName:s.name,score:b,breakdown:{sessionCount:{raw:r,score:o,weight:.2},recency:{daysSinceLastSession:Math.round(i),score:a,weight:.25},fragmentation:{avgMessages:Math.round(c*10)/10,score:u,weight:.15},searchCoverage:{ratio:Math.round(m*100)/100,score:f,weight:.2},tagCoverage:{ratio:Math.round(h*100)/100,score:E,weight:.2}}}}function Ur(e){let s=_().prepare("SELECT id FROM projects WHERE name = ?").get(e);return s?Fr(s.id):null}function Br(){let t=_().prepare("SELECT id FROM projects ORDER BY name").all(),s=[];for(let n of t){let r=Fr(n.id);r&&s.push(r)}return s}var Hr=N(()=>{"use strict";T()});function vd(e,t){return{type:"svg",props:{width:e,height:e,viewBox:"0 0 64 64",style:{display:"flex"},children:[{type:"line",props:{x1:14,y1:16,x2:46,y2:16,stroke:t,strokeWidth:3,strokeLinecap:"round"}},{type:"line",props:{x1:14,y1:24,x2:38,y2:24,stroke:t,strokeWidth:3,strokeLinecap:"round"}},{type:"line",props:{x1:10,y1:32,x2:54,y2:32,stroke:yt,strokeWidth:5,strokeLinecap:"round"}},{type:"line",props:{x1:14,y1:40,x2:42,y2:40,stroke:t,strokeWidth:3,strokeLinecap:"round"}},{type:"line",props:{x1:14,y1:48,x2:36,y2:48,stroke:t,strokeWidth:3,strokeLinecap:"round"}}]}}}function st(e,t){return{type:"div",props:{style:{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%"},children:[{type:"div",props:{style:{display:"flex",alignItems:"center",gap:"18px"},children:[vd(72,e.markStroke),{type:"span",props:{style:{fontSize:"36px",fontWeight:700,color:e.wordmarkFg,letterSpacing:"-0.01em"},children:"Claude Recall"}}]}},{type:"span",props:{style:{fontSize:"17px",color:e.wordmarkFg,opacity:.6,textTransform:"uppercase",letterSpacing:"0.18em",fontWeight:600},children:t}}]}}}function nt(e){return{type:"div",props:{style:{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%"},children:[{type:"div",props:{style:{display:"flex",alignItems:"center",gap:"14px"},children:[vd(52,e.markStroke),{type:"span",props:{style:{fontSize:"24px",fontWeight:700,color:e.wordmarkFg},children:"clauderecall.com"}}]}},{type:"span",props:{style:{fontSize:"20px",color:e.wordmarkFg,opacity:.7,fontWeight:500},children:"local memory for Claude Code"}}]}}}function Fy(e){return e>=1e9?`${(e/1e9).toFixed(2).replace(/\.?0+$/,"")}B`:e>=1e6?`${(e/1e6).toFixed(2).replace(/\.?0+$/,"")}M`:e>=1e3?`${(e/1e3).toFixed(1).replace(/\.0$/,"")}k`:String(e)}function Uy(e){return e.toLocaleString("en-US")}function rt(e){return e<1e3?String(e):`${Fy(e)} (${Uy(e)})`}function ot(e){return new Date(e).toLocaleDateString("en-US",{month:"long",day:"numeric",year:"numeric"})}var yt,Vt=N(()=>{"use strict";yt="#f97316"});var $d={};fe($d,{render:()=>Wy});function Qs(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[{type:"span",props:{style:{fontSize:"34px",fontWeight:700,color:Zt,fontFamily:"JetBrains Mono"},children:e}},{type:"span",props:{style:{fontSize:"14px",color:en,textTransform:"uppercase",letterSpacing:"0.16em"},children:t}}]}}}function Wy(e){let s=[ot(e.sessionDate)];e.durationLabel&&s.push(e.durationLabel);let n=s.join(" \xB7 "),r=e.costDollars??"$\u2014",o=typeof e.cachedTokens=="number"&&e.cachedTokens>=1e5?`+ ${rt(e.cachedTokens)} cached`:null,i=[st(Md,"session receipt"),{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[{type:"div",props:{style:{fontSize:"44px",fontWeight:700,color:Zt,lineHeight:1.15,wordBreak:"break-word"},children:e.sessionTitle}},{type:"div",props:{style:{fontSize:"20px",color:en},children:n}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"32px 0"},children:[{type:"span",props:{style:{fontSize:"180px",fontWeight:700,color:yt,fontFamily:"JetBrains Mono",lineHeight:1,letterSpacing:"-0.04em"},children:r}},{type:"span",props:{style:{marginTop:"16px",fontSize:"16px",color:en,textTransform:"uppercase",letterSpacing:"0.24em",fontWeight:600},children:"session cost"}}]}},{type:"div",props:{style:{display:"flex",width:"100%",height:"1px",backgroundColor:Hy}}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",gap:"24px"},children:[Qs(String(e.messageCount),"msgs"),Qs(String(e.filesReferenced),"files"),Qs(String(e.toolCallCount),"tools"),Qs(e.model??"\u2014","model")]}}];return o&&i.push({type:"div",props:{style:{fontSize:"14px",color:en,fontFamily:"JetBrains Mono",opacity:.7},children:o}}),e.verdict&&i.push({type:"div",props:{style:{display:"flex",fontSize:"24px",fontStyle:"italic",color:Zt,borderLeft:`3px solid ${yt}`,paddingLeft:"20px",marginTop:"8px"},children:`"${e.verdict}"`}}),i.push({type:"div",props:{style:{display:"flex",flex:1}}}),i.push(nt(Md)),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundColor:By,padding:"64px 72px",fontFamily:"Inter",gap:"28px"},children:i}}}var By,Zt,en,Hy,Md,Dd=N(()=>{"use strict";Vt();By="#1a1b1e",Zt="#e7e9ee",en="#8b9098",Hy="#2a2c33",Md={markStroke:Zt,wordmarkFg:Zt}});var Pd={};fe(Pd,{render:()=>Gy});function tn(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[{type:"span",props:{style:{fontSize:"34px",fontWeight:700,color:Qt,fontFamily:"JetBrains Mono"},children:e}},{type:"span",props:{style:{fontSize:"14px",color:sn,fontFamily:"JetBrains Mono",textTransform:"lowercase"},children:`// ${t}`}}]}}}function Gy(e){let t=[ot(e.sessionDate),e.durationLabel].filter(Boolean).join(" \xB7 "),s=e.costDollars??"$\u2014",n=typeof e.cachedTokens=="number"&&e.cachedTokens>=1e5?`# ${rt(e.cachedTokens)} tokens cache-replayed (free)`:null,r=[st(jd,"recall.cli/share"),{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"6px"},children:[{type:"div",props:{style:{fontSize:"18px",color:eo,fontFamily:"JetBrains Mono"},children:"$ recall share --session"}},{type:"div",props:{style:{fontSize:"40px",fontWeight:700,color:Qt,lineHeight:1.15,wordBreak:"break-word",fontFamily:"JetBrains Mono"},children:e.sessionTitle}},{type:"div",props:{style:{fontSize:"18px",color:sn,fontFamily:"JetBrains Mono"},children:t}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"flex-start",padding:"12px 0"},children:[{type:"span",props:{style:{fontSize:"20px",color:sn,fontFamily:"JetBrains Mono"},children:"> total_cost:"}},{type:"span",props:{style:{fontSize:"180px",fontWeight:700,color:eo,fontFamily:"JetBrains Mono",lineHeight:1,letterSpacing:"-0.04em"},children:s}}]}},{type:"div",props:{style:{display:"flex",width:"100%",height:"1px",backgroundColor:Jy}}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",gap:"24px"},children:[tn(String(e.messageCount),"msgs"),tn(String(e.filesReferenced),"files"),tn(String(e.toolCallCount),"tools"),tn(e.model??"\u2014","model")]}}];return n&&r.push({type:"div",props:{style:{fontSize:"14px",color:sn,fontFamily:"JetBrains Mono",opacity:.7},children:n}}),e.verdict&&r.push({type:"div",props:{style:{display:"flex",fontSize:"22px",color:Qt,fontFamily:"JetBrains Mono",borderLeft:`3px solid ${eo}`,paddingLeft:"20px",marginTop:"8px"},children:`// ${e.verdict}`}}),r.push({type:"div",props:{style:{display:"flex",flex:1}}}),r.push(nt(jd)),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundColor:Xy,padding:"64px 72px",fontFamily:"Inter",gap:"28px"},children:r}}}var Xy,Qt,sn,Jy,eo,jd,Fd=N(()=>{"use strict";Vt();Xy="#0d0d0f",Qt="#e1e7ee",sn="#6b7480",Jy="#1f2229",eo="#7ee787",jd={markStroke:Qt,wordmarkFg:Qt}});var Bd={};fe(Bd,{render:()=>Yy});function nn(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[{type:"span",props:{style:{fontSize:"34px",fontWeight:700,color:Tt,fontFamily:"JetBrains Mono"},children:e}},{type:"span",props:{style:{fontSize:"14px",color:rn,textTransform:"uppercase",letterSpacing:"0.16em",fontWeight:600},children:t}}]}}}function Yy(e){let t=[ot(e.sessionDate),e.durationLabel].filter(Boolean).join(" \xB7 "),s=e.costDollars??"$\u2014",n=typeof e.cachedTokens=="number"&&e.cachedTokens>=1e5?`+ ${rt(e.cachedTokens)} cached`:null,r=[st(Ud,"session receipt"),{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[{type:"div",props:{style:{fontSize:"44px",fontWeight:700,color:Tt,lineHeight:1.15,wordBreak:"break-word"},children:e.sessionTitle}},{type:"div",props:{style:{fontSize:"20px",color:rn},children:t}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"32px 0"},children:[{type:"span",props:{style:{fontSize:"180px",fontWeight:700,color:Tt,fontFamily:"JetBrains Mono",lineHeight:1,letterSpacing:"-0.04em"},children:s}},{type:"span",props:{style:{marginTop:"16px",fontSize:"16px",color:rn,textTransform:"uppercase",letterSpacing:"0.24em",fontWeight:600},children:"session cost"}}]}},{type:"div",props:{style:{display:"flex",width:"100%",height:"1px",backgroundColor:zy}}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",gap:"24px"},children:[nn(String(e.messageCount),"msgs"),nn(String(e.filesReferenced),"files"),nn(String(e.toolCallCount),"tools"),nn(e.model??"\u2014","model")]}}];return n&&r.push({type:"div",props:{style:{fontSize:"14px",color:rn,fontFamily:"JetBrains Mono",opacity:.85},children:n}}),e.verdict&&r.push({type:"div",props:{style:{display:"flex",fontSize:"24px",fontStyle:"italic",color:Tt,borderLeft:`3px solid ${Tt}`,paddingLeft:"20px",marginTop:"8px"},children:`"${e.verdict}"`}}),r.push({type:"div",props:{style:{display:"flex",flex:1}}}),r.push(nt(Ud)),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundImage:"linear-gradient(135deg, #b1370f 0%, #f97316 55%, #fbbf24 100%)",padding:"64px 72px",fontFamily:"Inter",gap:"28px"},children:r}}}var Tt,rn,zy,Ud,Hd=N(()=>{"use strict";Vt();Tt="#ffffff",rn="rgba(255,255,255,0.7)",zy="rgba(255,255,255,0.18)",Ud={markStroke:Tt,wordmarkFg:Tt}});var Xd={};fe(Xd,{render:()=>Qy});function on(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"4px"},children:[{type:"span",props:{style:{fontSize:"34px",fontWeight:800,color:Lt,fontFamily:"JetBrains Mono"},children:e}},{type:"span",props:{style:{fontSize:"14px",color:es,textTransform:"uppercase",letterSpacing:"0.16em",fontWeight:600},children:t}}]}}}function Zy(e){let t=e.reduce((s,n)=>s+n.value,0)||1;return{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[{type:"div",props:{style:{display:"flex",width:"100%",height:"10px",borderRadius:"5px",backgroundColor:Vy,overflow:"hidden"},children:e.map(s=>({type:"div",props:{style:{display:"flex",width:`${s.value/t*100}%`,height:"100%",backgroundColor:s.color}}}))}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",fontSize:"12px",color:es,fontWeight:600,textTransform:"uppercase",letterSpacing:"0.14em"},children:e.map(s=>({type:"span",props:{style:{display:"flex"},children:`${s.label} \xB7 ${s.value}`}}))}}]}}}function Qy(e){let t=[ot(e.sessionDate),e.durationLabel].filter(Boolean).join(" \xB7 "),s=e.costDollars??"$\u2014",n=typeof e.cachedTokens=="number"&&e.cachedTokens>=1e5?`+ ${rt(e.cachedTokens)} cached`:null,r=[st(Wd,"session receipt"),{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[{type:"div",props:{style:{fontSize:"40px",fontWeight:700,color:Lt,lineHeight:1.15,wordBreak:"break-word"},children:e.sessionTitle}},{type:"div",props:{style:{fontSize:"18px",color:es},children:t}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"flex-start",padding:"8px 0"},children:[{type:"span",props:{style:{fontSize:"14px",color:es,textTransform:"uppercase",letterSpacing:"0.24em",fontWeight:700},children:"session cost"}},{type:"span",props:{style:{fontSize:"180px",fontWeight:800,color:Lt,fontFamily:"JetBrains Mono",lineHeight:1,letterSpacing:"-0.04em"},children:s}}]}},{type:"div",props:{style:{display:"flex",width:"100%",height:"1px",backgroundColor:Ky}}},{type:"div",props:{style:{display:"flex",justifyContent:"space-between",gap:"24px"},children:[on(String(e.messageCount),"msgs"),on(String(e.filesReferenced),"files"),on(String(e.toolCallCount),"tools"),on(e.model??"\u2014","model")]}},Zy([{value:e.messageCount,color:yt,label:"msgs"},{value:e.filesReferenced,color:"#0a0a0a",label:"files"},{value:e.toolCallCount,color:"#5a6068",label:"tools"}])];return n&&r.push({type:"div",props:{style:{fontSize:"14px",color:es,fontFamily:"JetBrains Mono",opacity:.85},children:n}}),e.verdict&&r.push({type:"div",props:{style:{display:"flex",fontSize:"22px",fontStyle:"italic",color:Lt,borderLeft:`3px solid ${yt}`,paddingLeft:"20px",marginTop:"8px"},children:`"${e.verdict}"`}}),r.push({type:"div",props:{style:{display:"flex",flex:1}}}),r.push(nt(Wd)),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundColor:qy,padding:"64px 72px",fontFamily:"Inter",gap:"24px"},children:r}}}var qy,Lt,es,Ky,Vy,Wd,Jd=N(()=>{"use strict";Vt();qy="#f6f7f9",Lt="#0a0a0a",es="#5a6068",Ky="#e3e6eb",Vy="#dde1e7",Wd={markStroke:Lt,wordmarkFg:Lt}});var Gd={};fe(Gd,{render:()=>sT});function to(e,t){return{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"8px",flex:1},children:[{type:"div",props:{style:{fontSize:"52px",fontWeight:700,color:an},children:t}},{type:"div",props:{style:{fontSize:"16px",color:At,textTransform:"uppercase",letterSpacing:"2px"},children:e}}]}}}function so(e,t){return{type:"div",props:{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"16px 24px",backgroundColor:no,borderRadius:"12px"},children:[{type:"span",props:{style:{fontSize:"18px",color:At},children:e}},{type:"span",props:{style:{fontSize:"20px",fontWeight:700,color:an},children:t}}]}}}function sT(e){let t=Math.round(e.healthScore),s=[{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"8px"},children:[{type:"div",props:{style:{fontSize:"16px",color:At,textTransform:"uppercase",letterSpacing:"6px"},children:"YOUR MONTH IN CODE"}},{type:"div",props:{style:{fontSize:"44px",fontWeight:700,color:an},children:e.month}}]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"12px",backgroundColor:no,borderRadius:"16px",padding:"28px",border:`1px solid ${Ot}40`},children:[{type:"div",props:{style:{fontSize:"16px",color:tT,textTransform:"uppercase",letterSpacing:"2px"},children:"You are a"}},{type:"div",props:{style:{fontSize:"36px",fontWeight:700,color:Ot},children:e.archetype}}]}},{type:"div",props:{style:{display:"flex",gap:"16px",width:"100%"},children:[to("Recalls",String(e.totalRecalls)),to("Tokens piped",e.totalTokensPiped>999999?`${(e.totalTokensPiped/1e6).toFixed(1)}M`:e.totalTokensPiped.toLocaleString()),to("Sessions",String(e.sessionsIndexed))]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",gap:"8px",width:"100%"},children:[{type:"div",props:{style:{fontSize:"14px",color:At,textTransform:"uppercase",letterSpacing:"2px",marginBottom:"4px"},children:"Highlights"}},so("Most recalled",e.mostRecalledSession),so("Biggest recall",`${e.biggestRecallTokens.toLocaleString()} tokens`),so("Peak hours",e.mostActiveHours)]}},{type:"div",props:{style:{display:"flex",flexDirection:"column",alignItems:"center",gap:"12px"},children:[{type:"div",props:{style:{width:"100px",height:"100px",borderRadius:"50%",border:`6px solid ${Ot}`,display:"flex",alignItems:"center",justifyContent:"center"},children:{type:"span",props:{style:{fontSize:"32px",fontWeight:700,color:Ot},children:`${t}`}}}},{type:"div",props:{style:{fontSize:"14px",color:At,textTransform:"uppercase",letterSpacing:"2px"},children:"Memory health"}}]}}];return e.verdict&&s.push({type:"div",props:{style:{backgroundColor:no,borderLeft:`3px solid ${Ot}`,borderRadius:"8px",padding:"20px 24px",fontSize:"20px",color:an,fontStyle:"italic"},children:`"${e.verdict}"`}}),s.push({type:"div",props:{style:{display:"flex",alignItems:"center",justifyContent:"center",gap:"12px",marginTop:"auto"},children:[{type:"span",props:{style:{fontSize:"22px",fontWeight:700,color:Ot},children:"Claude Recall"}},{type:"span",props:{style:{fontSize:"18px",color:At},children:"clauderecall.com"}}]}}),{type:"div",props:{style:{display:"flex",flexDirection:"column",width:"100%",height:"100%",backgroundColor:eT,padding:"72px 64px",fontFamily:"Inter",gap:"36px"},children:s}}}var eT,no,an,At,Ot,tT,zd=N(()=>{"use strict";eT="#0b0c0f",no="#15171c",an="#e7e9ee",At="#8b9098",Ot="#f97316",tT="#fb923c"});var co,au,G,w,Z,Me,cu,lu,du,uu,lo,uo,it=N(()=>{"use strict";co=[String.raw` ___ _ _ _ _ ___ ___ ___ ___ ___ _ _ _ `,String.raw` / __| | /_\ | | | | \| __| | _ \ __/ __| /_\ | | | | `,String.raw`| (__| |__ / _ \| |_| | |) | _| | / _| (__ / _ \| |__| |__ `,String.raw` \___|____/_/ \_\\___/|___/|___| |_|_\___\___/_/ \_\____|____|`],au=co[0]?.length??64,G="#f97316",w="#8b9098",Z="#10b981",Me="#f59e0b",cu="#60a5fa",lu="#34d399",du="#c084fc",uu="CLAUDE RECALL",lo=100,uo=30});import{useEffect as vT,useState as MT}from"react";import{Box as pu,Text as pe}from"ink";import{createRequire as $T}from"node:module";import{existsSync as DT}from"node:fs";import{jsx as re,jsxs as gu}from"react/jsx-runtime";function mu({cols:e}){let[t,s]=MT(FT);vT(()=>{let r=!1,o=K(),i=0,a=0;if(DT(te))try{let c=_().prepare(`SELECT
738
738
  (SELECT COUNT(*) FROM sessions) AS sessions,
739
- (SELECT COUNT(*) FROM projects) AS projects`).get();i=c.sessions,a=c.projects}catch{}return s(l=>({...l,daemon:o,sessions:i,projects:a})),ye().then(l=>{r||s(c=>({...c,tier:l.tier}))}).catch(()=>{}),()=>{r=!0}},[]);let n=e>=au+2;return gu(pu,{flexDirection:"column",children:[n?co.map((r,o)=>re(pe,{color:G,bold:!0,children:r},o)):re(pe,{color:G,bold:!0,children:uu}),re(PT,{state:t})]})}function PT({state:e}){let t=re(pe,{color:w,children:" \xB7 "});return gu(pu,{children:[re(pe,{color:w,children:"v"}),re(pe,{color:G,children:$T}),t,re(pe,{color:w,children:"daemon: "}),e.daemon?re(pe,{color:Z,children:`running 127.0.0.1:${e.daemon.port}`}):re(pe,{color:Me,children:"stopped"}),t,re(pe,{color:w,children:"sessions: "}),re(pe,{color:G,children:e.sessions}),e.projects>0?re(pe,{color:w,children:` across ${e.projects} ${e.projects===1?"project":"projects"}`}):null,t,re(pe,{color:w,children:"license: "}),e.tier==="pro"?re(pe,{color:Z,children:"Pro"}):re(pe,{color:w,children:"Free"})]})}var DT,$T,jT,fu=N(()=>{"use strict";We();j();T();_e();it();DT=vT(import.meta.url),$T=DT("../../../package.json").version,jT={daemon:null,sessions:0,projects:0,tier:"free"}});import{Box as Ye,Text as oe}from"ink";import{jsx as z,jsxs as dn}from"react/jsx-runtime";function UT(e,t,s){if(t<=s)return{start:0,end:t};let n=e-Math.floor(s/2);return n<0&&(n=0),n+s>t&&(n=t-s),{start:n,end:n+s}}function at(e,t){if(t<=0)return"";let s=e.replace(/\s+/g," ").trim();return s.length<=t?s:s.slice(0,Math.max(0,t-1))+"\u2026"}function _u({sessions:e,total:t,selected:s,width:n,height:r,loading:o,dbExists:i,filter:a,sortMode:l,groupByProject:c}){let u=Math.max(20,n-2),f=Math.max(1,r-1-1-2),g=UT(s,e.length,f),h=e.slice(g.start,g.end);if(!i)return dn(Ye,{flexDirection:"column",width:n,height:r,borderStyle:"round",borderColor:w,children:[z(oe,{color:G,bold:!0,children:" Sessions "}),z(Ye,{paddingX:1,paddingY:1,children:z(oe,{color:w,wrap:"wrap",children:"No sessions indexed yet. Quit (q) and run `recall index` first."})})]});let S=[FT[l],c?"grouped":""].filter(Boolean).join(" \xB7 "),C=o?" Sessions \xB7 loading\u2026 ":a?` Sessions \xB7 ${e.length} of ${t} match "${at(a,18)}" \xB7 ${S} `:` Sessions \xB7 ${e.length} of ${t} \xB7 ${S} `,R=null;return c&&g.start>0&&(R=e[g.start-1]?.project_name??null),dn(Ye,{flexDirection:"column",width:n,height:r,borderStyle:"round",borderColor:w,children:[z(Ye,{width:u+2,paddingLeft:1,children:z(oe,{color:G,bold:!0,children:at(C,u)})}),z(Ye,{flexDirection:"column",flexGrow:1,paddingX:1,children:h.length===0?z(oe,{color:w,children:a?"no matches.":"no sessions."}):h.flatMap((L,Q)=>{let v=g.start+Q,ee=v===s,B=[];return c&&L.project_name!==R&&(B.push(z(HT,{project:L.project_name,width:u},`hdr-${L.project_name}-${v}`)),R=L.project_name),B.push(z(BT,{session:L,width:u,isSelected:ee,indented:c},L.id)),B})}),z(Ye,{width:u+2,paddingLeft:1,children:z(oe,{color:w,children:e.length>0?at(` ${s+1} / ${e.length}${g.end<e.length?" \xB7 scroll for more":""} `,u):""})})]})}function BT({session:e,width:t,isSelected:s,indented:n}){let r=W(e.started_at)||"",o=n?" ":"",i=s?"\u258C ":" ";if(n){let f=e.alias||e.auto_title||e.first_user_message||"(no title)",g=Math.min(14,Math.max(6,Math.floor(t*.25))),h=Math.max(10,t-i.length-o.length-g-1),E=at(f,h),b=at(r,g),S=Math.max(1,t-i.length-o.length-E.length-b.length);return dn(Ye,{children:[z(oe,{children:o}),z(oe,{color:s?G:w,bold:s,children:i}),z(oe,{color:s?G:"#fefce8",bold:s,children:E}),z(oe,{children:" ".repeat(S)}),z(oe,{color:w,children:b})]})}let a=e.project_name||"?",l=Math.min(28,Math.floor(t*.7)),c=Math.min(14,t-l-i.length-1),u=at(a,l),p=at(r,c),m=Math.max(1,t-i.length-u.length-p.length);return dn(Ye,{children:[z(oe,{color:s?G:w,bold:s,children:i}),z(oe,{color:s?G:"#67e8f9",bold:s,children:u}),z(oe,{children:" ".repeat(m)}),z(oe,{color:w,children:p})]})}function HT({project:e,width:t}){return z(Ye,{children:z(oe,{color:"#67e8f9",bold:!0,children:at(`\u25BE ${e}`,t)})})}var FT,hu=N(()=>{"use strict";I();it();FT={recent:"recent",longest:"longest",busiest:"busiest project"}});import{useEffect as WT,useState as po}from"react";function Eu(e,t,s){let n=s?"":"AND is_sidechain = 0";return e.prepare(`SELECT uuid, role, type, timestamp, content_text
739
+ (SELECT COUNT(*) FROM projects) AS projects`).get();i=c.sessions,a=c.projects}catch{}return s(l=>({...l,daemon:o,sessions:i,projects:a})),ye().then(l=>{r||s(c=>({...c,tier:l.tier}))}).catch(()=>{}),()=>{r=!0}},[]);let n=e>=au+2;return gu(pu,{flexDirection:"column",children:[n?co.map((r,o)=>re(pe,{color:G,bold:!0,children:r},o)):re(pe,{color:G,bold:!0,children:uu}),re(UT,{state:t})]})}function UT({state:e}){let t=re(pe,{color:w,children:" \xB7 "});return gu(pu,{children:[re(pe,{color:w,children:"v"}),re(pe,{color:G,children:PT}),t,re(pe,{color:w,children:"daemon: "}),e.daemon?re(pe,{color:Z,children:`running 127.0.0.1:${e.daemon.port}`}):re(pe,{color:Me,children:"stopped"}),t,re(pe,{color:w,children:"sessions: "}),re(pe,{color:G,children:e.sessions}),e.projects>0?re(pe,{color:w,children:` across ${e.projects} ${e.projects===1?"project":"projects"}`}):null,t,re(pe,{color:w,children:"license: "}),e.tier==="pro"?re(pe,{color:Z,children:"Pro"}):re(pe,{color:w,children:"Free"})]})}var jT,PT,FT,fu=N(()=>{"use strict";We();j();T();_e();it();jT=$T(import.meta.url),PT=jT("../../../package.json").version,FT={daemon:null,sessions:0,projects:0,tier:"free"}});import{Box as Ye,Text as oe}from"ink";import{jsx as z,jsxs as dn}from"react/jsx-runtime";function HT(e,t,s){if(t<=s)return{start:0,end:t};let n=e-Math.floor(s/2);return n<0&&(n=0),n+s>t&&(n=t-s),{start:n,end:n+s}}function at(e,t){if(t<=0)return"";let s=e.replace(/\s+/g," ").trim();return s.length<=t?s:s.slice(0,Math.max(0,t-1))+"\u2026"}function _u({sessions:e,total:t,selected:s,width:n,height:r,loading:o,dbExists:i,filter:a,sortMode:l,groupByProject:c}){let u=Math.max(20,n-2),f=Math.max(1,r-1-1-2),g=HT(s,e.length,f),h=e.slice(g.start,g.end);if(!i)return dn(Ye,{flexDirection:"column",width:n,height:r,borderStyle:"round",borderColor:w,children:[z(oe,{color:G,bold:!0,children:" Sessions "}),z(Ye,{paddingX:1,paddingY:1,children:z(oe,{color:w,wrap:"wrap",children:"No sessions indexed yet. Quit (q) and run `recall index` first."})})]});let S=[BT[l],c?"grouped":""].filter(Boolean).join(" \xB7 "),C=o?" Sessions \xB7 loading\u2026 ":a?` Sessions \xB7 ${e.length} of ${t} match "${at(a,18)}" \xB7 ${S} `:` Sessions \xB7 ${e.length} of ${t} \xB7 ${S} `,R=null;return c&&g.start>0&&(R=e[g.start-1]?.project_name??null),dn(Ye,{flexDirection:"column",width:n,height:r,borderStyle:"round",borderColor:w,children:[z(Ye,{width:u+2,paddingLeft:1,children:z(oe,{color:G,bold:!0,children:at(C,u)})}),z(Ye,{flexDirection:"column",flexGrow:1,paddingX:1,children:h.length===0?z(oe,{color:w,children:a?"no matches.":"no sessions."}):h.flatMap((L,Q)=>{let v=g.start+Q,ee=v===s,B=[];return c&&L.project_name!==R&&(B.push(z(XT,{project:L.project_name,width:u},`hdr-${L.project_name}-${v}`)),R=L.project_name),B.push(z(WT,{session:L,width:u,isSelected:ee,indented:c},L.id)),B})}),z(Ye,{width:u+2,paddingLeft:1,children:z(oe,{color:w,children:e.length>0?at(` ${s+1} / ${e.length}${g.end<e.length?" \xB7 scroll for more":""} `,u):""})})]})}function WT({session:e,width:t,isSelected:s,indented:n}){let r=W(e.started_at)||"",o=n?" ":"",i=s?"\u258C ":" ";if(n){let f=e.alias||e.auto_title||e.first_user_message||"(no title)",g=Math.min(14,Math.max(6,Math.floor(t*.25))),h=Math.max(10,t-i.length-o.length-g-1),E=at(f,h),b=at(r,g),S=Math.max(1,t-i.length-o.length-E.length-b.length);return dn(Ye,{children:[z(oe,{children:o}),z(oe,{color:s?G:w,bold:s,children:i}),z(oe,{color:s?G:"#fefce8",bold:s,children:E}),z(oe,{children:" ".repeat(S)}),z(oe,{color:w,children:b})]})}let a=e.project_name||"?",l=Math.min(28,Math.floor(t*.7)),c=Math.min(14,t-l-i.length-1),u=at(a,l),p=at(r,c),m=Math.max(1,t-i.length-u.length-p.length);return dn(Ye,{children:[z(oe,{color:s?G:w,bold:s,children:i}),z(oe,{color:s?G:"#67e8f9",bold:s,children:u}),z(oe,{children:" ".repeat(m)}),z(oe,{color:w,children:p})]})}function XT({project:e,width:t}){return z(Ye,{children:z(oe,{color:"#67e8f9",bold:!0,children:at(`\u25BE ${e}`,t)})})}var BT,hu=N(()=>{"use strict";I();it();BT={recent:"recent",longest:"longest",busiest:"busiest project"}});import{useEffect as JT,useState as po}from"react";function Eu(e,t,s){let n=s?"":"AND is_sidechain = 0";return e.prepare(`SELECT uuid, role, type, timestamp, content_text
740
740
  FROM messages
741
741
  WHERE session_id = @id
742
742
  ${n}
743
743
  ORDER BY timestamp DESC
744
- LIMIT @limit`).all({id:t,limit:XT})}function bu(e){let[t,s]=po([]),[n,r]=po(!1),[o,i]=po(!1);return WT(()=>{if(!e){s([]),i(!1);return}r(!0);try{let a=_(),l=Eu(a,e,!1),c=!1;l.length===0&&(l=Eu(a,e,!0),c=l.length>0),s([...l].reverse()),i(c)}catch{s([]),i(!1)}finally{r(!1)}},[e]),{messages:t,loading:n,fallbackToSidechain:o}}var XT,Su=N(()=>{"use strict";T();XT=6});import{Box as De,Text as Fe}from"ink";import{Fragment as YT,jsx as V,jsxs as vt}from"react/jsx-runtime";function JT(e){let t=(e.role??"").toLowerCase();return t==="user"?{label:"user",color:cu}:t==="assistant"?{label:"asst",color:lu}:t==="tool"?{label:"tool",color:du}:t==="system"?{label:"sys ",color:w}:e.type==="summary"?{label:"sum ",color:w}:{label:"----",color:w}}function GT(e,t){return e?e.replace(/\s+/g," ").trim().slice(0,t+1).replace(/.{1}$/,s=>e.length>t?"\u2026":s):"(empty)"}function yu({session:e,width:t,height:s}){let n=e?.id??null,{messages:r,loading:o,fallbackToSidechain:i}=bu(n),a=Math.max(20,t-2),c=Math.max(4,s-2-2),u=Math.max(2,Math.floor(c/Math.max(1,r.length)));return e?vt(De,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:w,children:[vt(De,{paddingX:1,flexDirection:"column",children:[V(De,{width:a,children:V(Fe,{color:G,bold:!0,wrap:"truncate-end",children:e.alias||e.auto_title||e.first_user_message||"(no title)"})}),V(De,{width:a,children:V(Fe,{color:w,wrap:"truncate-end",children:`${e.id.slice(0,8)} \xB7 ${e.message_count} msgs \xB7 ${W(e.started_at)}`})})]}),V(De,{flexDirection:"column",paddingX:1,flexGrow:1,children:o?V(Fe,{color:w,children:"loading messages\u2026"}):r.length===0?V(Fe,{color:w,children:"no messages indexed for this session."}):vt(YT,{children:[i?V(Fe,{color:w,children:"(showing sidechain / subagent messages)"}):null,r.map(p=>V(zT,{message:p,width:a,perMessageLines:u},p.uuid))]})})]}):vt(De,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:w,children:[V(De,{paddingX:1,children:V(Fe,{color:G,bold:!0,children:"Preview"})}),V(De,{paddingX:1,paddingY:1,children:V(Fe,{color:w,children:"Select a session on the left to preview."})})]})}function zT({message:e,width:t,perMessageLines:s}){let n=JT(e),r=Math.max(1,s-1),o=Math.max(20,t-2),i=r*o,a=GT(e.content_text,i);return vt(De,{flexDirection:"column",marginBottom:0,children:[vt(De,{children:[V(Fe,{color:n.color,bold:!0,children:n.label}),V(Fe,{color:w,children:` ${e.timestamp?W(e.timestamp):""}`})]}),V(De,{width:t,children:V(Fe,{wrap:"truncate-end",children:a})})]})}var Tu=N(()=>{"use strict";I();Su();it()});import{useMemo as qT}from"react";import{Box as $e,Text as ct}from"ink";import{jsx as me,jsxs as ts}from"react/jsx-runtime";function KT(e,t){try{return{ok:!0,result:Us(e,{budget:t})}}catch(s){return{ok:!1,error:s instanceof Error?s.message:String(s)}}}function wu({session:e,width:t,height:s,budget:n}){let r=qT(()=>e?KT(e.id,n):null,[e?.id,n]),o=Math.max(20,t-2),a=Math.max(4,s-2-2);if(!e)return ts($e,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:w,children:[me($e,{paddingX:1,children:me(ct,{color:G,bold:!0,children:"Neighborhood"})}),me($e,{paddingX:1,paddingY:1,children:me(ct,{color:w,children:"Select a session and press `n` to assemble its neighborhood."})})]});if(!r)return null;if(!r.ok)return ts($e,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:Me,children:[me($e,{paddingX:1,children:me(ct,{color:Me,bold:!0,children:"Neighborhood error"})}),me($e,{paddingX:1,paddingY:1,children:me(ct,{color:Me,children:r.error})})]});let{result:l}=r,c=l.bundle.replace(/\n+$/,"").split(`
745
- `),u=c.slice(0,Math.max(1,a-1)),p=c.length-u.length;return ts($e,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:Z,children:[ts($e,{paddingX:1,flexDirection:"column",children:[me($e,{width:o,children:me(ct,{color:Z,bold:!0,wrap:"truncate-end",children:"Neighborhood"})}),me($e,{width:o,children:me(ct,{color:w,wrap:"truncate-end",children:`budget=${n} used=${l.budgetUsed} remaining=${l.budgetRemaining} truncated=${l.truncated.length}`})})]}),ts($e,{flexDirection:"column",paddingX:1,flexGrow:1,children:[u.map((m,f)=>me(ct,{wrap:"truncate-end",children:m||" "},f)),p>0?me(ct,{color:w,children:`\u2026 ${p} more line${p===1?"":"s"} (resize the terminal or use \`recall neighborhood ${e.id.slice(0,8)}\` for the full bundle)`}):null]})]})}var xu=N(()=>{"use strict";Rr();it()});import{useEffect as VT,useState as Ru}from"react";import{Box as ss,Text as lt}from"ink";import mo from"ink-text-input";import{jsx as be,jsxs as go}from"react/jsx-runtime";function ku({mode:e,query:t,onQueryChange:s,onSearchSubmit:n,onAliasSubmit:r,onTagSubmit:o,aliasInitial:i,toast:a}){let[l,c]=Ru(""),[u,p]=Ru("");return VT(()=>{e==="alias"&&c(i),e==="tag"&&p("")},[e,i]),a&&e==="normal"?be(ss,{children:be(lt,{color:Me,children:`\u25B6 ${a}`})}):e==="search"?go(ss,{children:[be(lt,{color:G,bold:!0,children:"/ "}),be(mo,{value:t,onChange:s,onSubmit:n,placeholder:"filter sessions by project, alias, or opening message..."}),be(lt,{color:w,children:" esc clear \xB7 enter confirm"})]}):e==="alias"?go(ss,{children:[be(lt,{color:Z,bold:!0,children:"alias \u203A "}),be(mo,{value:l,onChange:c,onSubmit:m=>r(m),placeholder:"terminal-tab name for this session"}),be(lt,{color:w,children:" esc cancel \xB7 enter save"})]}):e==="tag"?go(ss,{children:[be(lt,{color:Z,bold:!0,children:"tag \u203A "}),be(mo,{value:u,onChange:p,onSubmit:m=>o(m),placeholder:"add a tag to this session"}),be(lt,{color:w,children:" esc cancel \xB7 enter save"})]}):be(ss,{children:be(lt,{color:w,children:"\u2191\u2193 nav \xB7 / filter \xB7 enter view \xB7 a alias \xB7 t tag \xB7 s sort \xB7 g group \xB7 n bundle \xB7 o browser \xB7 ? help \xB7 q quit"})})}var Nu=N(()=>{"use strict";it()});import{Box as ge,Text as F}from"ink";import{jsx as D,jsxs as Se}from"react/jsx-runtime";function Cu({width:e,height:t}){return Se(ge,{flexDirection:"column",width:e,height:t,borderStyle:"round",borderColor:G,paddingX:2,paddingY:1,children:[Se(ge,{children:[D(F,{color:G,bold:!0,children:"Claude Recall TUI \u2014 Help"}),D(F,{color:w,children:" \xB7 press ? or esc to close"})]}),Se(ge,{marginTop:1,flexDirection:"column",children:[D(F,{color:Z,bold:!0,children:"Navigation"}),ZT.map(s=>D(fo,{row:s},s.key))]}),Se(ge,{marginTop:1,flexDirection:"column",children:[D(F,{color:Z,bold:!0,children:"Actions on the selected session"}),QT.map(s=>D(fo,{row:s},s.key))]}),Se(ge,{marginTop:1,flexDirection:"column",children:[D(F,{color:Z,bold:!0,children:"Right-pane views"}),ew.map(s=>D(fo,{row:s},s.key))]}),Se(ge,{marginTop:1,flexDirection:"column",children:[D(F,{color:Z,bold:!0,children:"What is Neighborhood?"}),D(F,{color:w,wrap:"wrap",children:"Neighborhood assembles a ranked, token-budgeted bundle of context around the selected session: its parent and child sessions, citations (sessions it referenced), similar sessions (by embedding), and any related bug-pattern matches. Press `n` in the TUI to preview it on the right."})]}),Se(ge,{marginTop:1,flexDirection:"column",children:[D(F,{color:Z,bold:!0,children:"Maintenance & diagnostics"}),D(F,{color:w,wrap:"wrap",children:"Two commands cover everything. Quit the TUI with `q` first, then:"}),Se(ge,{marginTop:1,children:[D(F,{color:w,children:" \u2022 "}),D(F,{children:"recall doctor"})]}),D(F,{color:w,wrap:"wrap",children:" Health report: DB size, WAL, FTS fragmentation, integrity, disk free."}),D(F,{color:w,wrap:"wrap",children:" Run this first if anything feels slow or wrong. Add --json for machine output."}),Se(ge,{marginTop:1,children:[D(F,{color:w,children:" \u2022 "}),D(F,{children:"recall optimize"})]}),D(F,{color:w,wrap:"wrap",children:" Maintenance: WAL truncate + FTS5 merge + planner stats. Safe while daemon is running."}),D(F,{color:w,wrap:"wrap",children:" Add --vacuum (with daemon stopped) to also reclaim disk pages from deleted rows."})]}),Se(ge,{marginTop:1,flexDirection:"column",children:[D(F,{color:Z,bold:!0,children:"How to pipe a session into Claude"}),D(F,{color:w,wrap:"wrap",children:"Two recipes. Both work in any shell \u2014 exit this TUI with `q` first, then run them."}),Se(ge,{marginTop:1,children:[D(F,{color:w,children:" 1. "}),D(F,{children:"recall context <id> | claude"})]}),D(F,{color:w,wrap:"wrap",children:" Pipes one session's full transcript as markdown into a fresh `claude` chat."}),D(F,{color:w,wrap:"wrap",children:" Use when you want to continue exactly where one session left off."}),Se(ge,{marginTop:1,children:[D(F,{color:w,children:" 2. "}),D(F,{children:"recall neighborhood <id> | claude"})]}),D(F,{color:w,wrap:"wrap",children:" Pipes the bundle (parents + children + citations + similar + bug matches)."}),D(F,{color:w,wrap:"wrap",children:" Use when you want broader context, not just one transcript."})]})]})}function fo({row:e}){return Se(ge,{children:[D(ge,{width:16,children:D(F,{color:G,children:e.key})}),D(F,{color:w,wrap:"truncate-end",children:e.description})]})}var ZT,QT,ew,Lu=N(()=>{"use strict";it();ZT=[{key:"\u2191 / k",description:"move selection up"},{key:"\u2193 / j",description:"move selection down"},{key:"PgUp / PgDn",description:"jump 10 sessions"},{key:"/",description:"filter by project, alias, or first user message"},{key:"g",description:"toggle project-grouped view"},{key:"s",description:"cycle sort order: recent \u2192 longest \u2192 most-active"}],QT=[{key:"enter",description:"open the full transcript (`recall show <id>`) and exit the TUI"},{key:"a",description:"set or update the alias for the selected session"},{key:"t",description:"add a tag to the selected session"},{key:"o",description:"open the selected session in your browser (daemon required)"}],ew=[{key:"n",description:"toggle the right pane between Preview and Neighborhood"},{key:"?",description:"open this help screen"},{key:"esc",description:"dismiss filter or this help screen"},{key:"q / Ctrl-C",description:"quit the TUI"}]});import{useEffect as tw,useMemo as sw,useState as un}from"react";import{existsSync as nw}from"node:fs";function Ou(e){let[t,s]=un([]),[n,r]=un(!0),[o,i]=un(null),[a,l]=un(!0);return tw(()=>{if(!nw(te)){l(!1),r(!1);return}try{let p=_().prepare(`SELECT s.id, p.name AS project_name, s.started_at,
744
+ LIMIT @limit`).all({id:t,limit:GT})}function bu(e){let[t,s]=po([]),[n,r]=po(!1),[o,i]=po(!1);return JT(()=>{if(!e){s([]),i(!1);return}r(!0);try{let a=_(),l=Eu(a,e,!1),c=!1;l.length===0&&(l=Eu(a,e,!0),c=l.length>0),s([...l].reverse()),i(c)}catch{s([]),i(!1)}finally{r(!1)}},[e]),{messages:t,loading:n,fallbackToSidechain:o}}var GT,Su=N(()=>{"use strict";T();GT=6});import{Box as $e,Text as Fe}from"ink";import{Fragment as KT,jsx as V,jsxs as vt}from"react/jsx-runtime";function zT(e){let t=(e.role??"").toLowerCase();return t==="user"?{label:"user",color:cu}:t==="assistant"?{label:"asst",color:lu}:t==="tool"?{label:"tool",color:du}:t==="system"?{label:"sys ",color:w}:e.type==="summary"?{label:"sum ",color:w}:{label:"----",color:w}}function YT(e,t){return e?e.replace(/\s+/g," ").trim().slice(0,t+1).replace(/.{1}$/,s=>e.length>t?"\u2026":s):"(empty)"}function yu({session:e,width:t,height:s}){let n=e?.id??null,{messages:r,loading:o,fallbackToSidechain:i}=bu(n),a=Math.max(20,t-2),c=Math.max(4,s-2-2),u=Math.max(2,Math.floor(c/Math.max(1,r.length)));return e?vt($e,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:w,children:[vt($e,{paddingX:1,flexDirection:"column",children:[V($e,{width:a,children:V(Fe,{color:G,bold:!0,wrap:"truncate-end",children:e.alias||e.auto_title||e.first_user_message||"(no title)"})}),V($e,{width:a,children:V(Fe,{color:w,wrap:"truncate-end",children:`${e.id.slice(0,8)} \xB7 ${e.message_count} msgs \xB7 ${W(e.started_at)}`})})]}),V($e,{flexDirection:"column",paddingX:1,flexGrow:1,children:o?V(Fe,{color:w,children:"loading messages\u2026"}):r.length===0?V(Fe,{color:w,children:"no messages indexed for this session."}):vt(KT,{children:[i?V(Fe,{color:w,children:"(showing sidechain / subagent messages)"}):null,r.map(p=>V(qT,{message:p,width:a,perMessageLines:u},p.uuid))]})})]}):vt($e,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:w,children:[V($e,{paddingX:1,children:V(Fe,{color:G,bold:!0,children:"Preview"})}),V($e,{paddingX:1,paddingY:1,children:V(Fe,{color:w,children:"Select a session on the left to preview."})})]})}function qT({message:e,width:t,perMessageLines:s}){let n=zT(e),r=Math.max(1,s-1),o=Math.max(20,t-2),i=r*o,a=YT(e.content_text,i);return vt($e,{flexDirection:"column",marginBottom:0,children:[vt($e,{children:[V(Fe,{color:n.color,bold:!0,children:n.label}),V(Fe,{color:w,children:` ${e.timestamp?W(e.timestamp):""}`})]}),V($e,{width:t,children:V(Fe,{wrap:"truncate-end",children:a})})]})}var Tu=N(()=>{"use strict";I();Su();it()});import{useMemo as VT}from"react";import{Box as De,Text as ct}from"ink";import{jsx as me,jsxs as ts}from"react/jsx-runtime";function ZT(e,t){try{return{ok:!0,result:Us(e,{budget:t})}}catch(s){return{ok:!1,error:s instanceof Error?s.message:String(s)}}}function wu({session:e,width:t,height:s,budget:n}){let r=VT(()=>e?ZT(e.id,n):null,[e?.id,n]),o=Math.max(20,t-2),a=Math.max(4,s-2-2);if(!e)return ts(De,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:w,children:[me(De,{paddingX:1,children:me(ct,{color:G,bold:!0,children:"Neighborhood"})}),me(De,{paddingX:1,paddingY:1,children:me(ct,{color:w,children:"Select a session and press `n` to assemble its neighborhood."})})]});if(!r)return null;if(!r.ok)return ts(De,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:Me,children:[me(De,{paddingX:1,children:me(ct,{color:Me,bold:!0,children:"Neighborhood error"})}),me(De,{paddingX:1,paddingY:1,children:me(ct,{color:Me,children:r.error})})]});let{result:l}=r,c=l.bundle.replace(/\n+$/,"").split(`
745
+ `),u=c.slice(0,Math.max(1,a-1)),p=c.length-u.length;return ts(De,{flexDirection:"column",width:t,height:s,borderStyle:"round",borderColor:Z,children:[ts(De,{paddingX:1,flexDirection:"column",children:[me(De,{width:o,children:me(ct,{color:Z,bold:!0,wrap:"truncate-end",children:"Neighborhood"})}),me(De,{width:o,children:me(ct,{color:w,wrap:"truncate-end",children:`budget=${n} used=${l.budgetUsed} remaining=${l.budgetRemaining} truncated=${l.truncated.length}`})})]}),ts(De,{flexDirection:"column",paddingX:1,flexGrow:1,children:[u.map((m,f)=>me(ct,{wrap:"truncate-end",children:m||" "},f)),p>0?me(ct,{color:w,children:`\u2026 ${p} more line${p===1?"":"s"} (resize the terminal or use \`recall neighborhood ${e.id.slice(0,8)}\` for the full bundle)`}):null]})]})}var xu=N(()=>{"use strict";Rr();it()});import{useEffect as QT,useState as Ru}from"react";import{Box as ss,Text as lt}from"ink";import mo from"ink-text-input";import{jsx as be,jsxs as go}from"react/jsx-runtime";function ku({mode:e,query:t,onQueryChange:s,onSearchSubmit:n,onAliasSubmit:r,onTagSubmit:o,aliasInitial:i,toast:a}){let[l,c]=Ru(""),[u,p]=Ru("");return QT(()=>{e==="alias"&&c(i),e==="tag"&&p("")},[e,i]),a&&e==="normal"?be(ss,{children:be(lt,{color:Me,children:`\u25B6 ${a}`})}):e==="search"?go(ss,{children:[be(lt,{color:G,bold:!0,children:"/ "}),be(mo,{value:t,onChange:s,onSubmit:n,placeholder:"filter sessions by project, alias, or opening message..."}),be(lt,{color:w,children:" esc clear \xB7 enter confirm"})]}):e==="alias"?go(ss,{children:[be(lt,{color:Z,bold:!0,children:"alias \u203A "}),be(mo,{value:l,onChange:c,onSubmit:m=>r(m),placeholder:"terminal-tab name for this session"}),be(lt,{color:w,children:" esc cancel \xB7 enter save"})]}):e==="tag"?go(ss,{children:[be(lt,{color:Z,bold:!0,children:"tag \u203A "}),be(mo,{value:u,onChange:p,onSubmit:m=>o(m),placeholder:"add a tag to this session"}),be(lt,{color:w,children:" esc cancel \xB7 enter save"})]}):be(ss,{children:be(lt,{color:w,children:"\u2191\u2193 nav \xB7 / filter \xB7 enter view \xB7 a alias \xB7 t tag \xB7 s sort \xB7 g group \xB7 n bundle \xB7 o browser \xB7 ? help \xB7 q quit"})})}var Nu=N(()=>{"use strict";it()});import{Box as ge,Text as F}from"ink";import{jsx as $,jsxs as Se}from"react/jsx-runtime";function Cu({width:e,height:t}){return Se(ge,{flexDirection:"column",width:e,height:t,borderStyle:"round",borderColor:G,paddingX:2,paddingY:1,children:[Se(ge,{children:[$(F,{color:G,bold:!0,children:"Claude Recall TUI \u2014 Help"}),$(F,{color:w,children:" \xB7 press ? or esc to close"})]}),Se(ge,{marginTop:1,flexDirection:"column",children:[$(F,{color:Z,bold:!0,children:"Navigation"}),ew.map(s=>$(fo,{row:s},s.key))]}),Se(ge,{marginTop:1,flexDirection:"column",children:[$(F,{color:Z,bold:!0,children:"Actions on the selected session"}),tw.map(s=>$(fo,{row:s},s.key))]}),Se(ge,{marginTop:1,flexDirection:"column",children:[$(F,{color:Z,bold:!0,children:"Right-pane views"}),sw.map(s=>$(fo,{row:s},s.key))]}),Se(ge,{marginTop:1,flexDirection:"column",children:[$(F,{color:Z,bold:!0,children:"What is Neighborhood?"}),$(F,{color:w,wrap:"wrap",children:"Neighborhood assembles a ranked, token-budgeted bundle of context around the selected session: its parent and child sessions, citations (sessions it referenced), similar sessions (by embedding), and any related bug-pattern matches. Press `n` in the TUI to preview it on the right."})]}),Se(ge,{marginTop:1,flexDirection:"column",children:[$(F,{color:Z,bold:!0,children:"Maintenance & diagnostics"}),$(F,{color:w,wrap:"wrap",children:"Two commands cover everything. Quit the TUI with `q` first, then:"}),Se(ge,{marginTop:1,children:[$(F,{color:w,children:" \u2022 "}),$(F,{children:"recall doctor"})]}),$(F,{color:w,wrap:"wrap",children:" Health report: DB size, WAL, FTS fragmentation, integrity, disk free."}),$(F,{color:w,wrap:"wrap",children:" Run this first if anything feels slow or wrong. Add --json for machine output."}),Se(ge,{marginTop:1,children:[$(F,{color:w,children:" \u2022 "}),$(F,{children:"recall optimize"})]}),$(F,{color:w,wrap:"wrap",children:" Maintenance: WAL truncate + FTS5 merge + planner stats. Safe while daemon is running."}),$(F,{color:w,wrap:"wrap",children:" Add --vacuum (with daemon stopped) to also reclaim disk pages from deleted rows."})]}),Se(ge,{marginTop:1,flexDirection:"column",children:[$(F,{color:Z,bold:!0,children:"How to pipe a session into Claude"}),$(F,{color:w,wrap:"wrap",children:"Two recipes. Both work in any shell \u2014 exit this TUI with `q` first, then run them."}),Se(ge,{marginTop:1,children:[$(F,{color:w,children:" 1. "}),$(F,{children:"recall context <id> | claude"})]}),$(F,{color:w,wrap:"wrap",children:" Pipes one session's full transcript as markdown into a fresh `claude` chat."}),$(F,{color:w,wrap:"wrap",children:" Use when you want to continue exactly where one session left off."}),Se(ge,{marginTop:1,children:[$(F,{color:w,children:" 2. "}),$(F,{children:"recall neighborhood <id> | claude"})]}),$(F,{color:w,wrap:"wrap",children:" Pipes the bundle (parents + children + citations + similar + bug matches)."}),$(F,{color:w,wrap:"wrap",children:" Use when you want broader context, not just one transcript."})]})]})}function fo({row:e}){return Se(ge,{children:[$(ge,{width:16,children:$(F,{color:G,children:e.key})}),$(F,{color:w,wrap:"truncate-end",children:e.description})]})}var ew,tw,sw,Lu=N(()=>{"use strict";it();ew=[{key:"\u2191 / k",description:"move selection up"},{key:"\u2193 / j",description:"move selection down"},{key:"PgUp / PgDn",description:"jump 10 sessions"},{key:"/",description:"filter by project, alias, or first user message"},{key:"g",description:"toggle project-grouped view"},{key:"s",description:"cycle sort order: recent \u2192 longest \u2192 most-active"}],tw=[{key:"enter",description:"open the full transcript (`recall show <id>`) and exit the TUI"},{key:"a",description:"set or update the alias for the selected session"},{key:"t",description:"add a tag to the selected session"},{key:"o",description:"open the selected session in your browser (daemon required)"}],sw=[{key:"n",description:"toggle the right pane between Preview and Neighborhood"},{key:"?",description:"open this help screen"},{key:"esc",description:"dismiss filter or this help screen"},{key:"q / Ctrl-C",description:"quit the TUI"}]});import{useEffect as nw,useMemo as rw,useState as un}from"react";import{existsSync as ow}from"node:fs";function Ou(e){let[t,s]=un([]),[n,r]=un(!0),[o,i]=un(null),[a,l]=un(!0);return nw(()=>{if(!ow(te)){l(!1),r(!1);return}try{let p=_().prepare(`SELECT s.id, p.name AS project_name, s.started_at,
746
746
  s.message_count, s.first_user_message,
747
747
  NULLIF(sa.alias, '') AS alias,
748
748
  s.auto_title
@@ -754,10 +754,10 @@ ${t.message}
754
754
  AND COALESCE(s.auto_title, '') NOT LIKE '[output-index]%'
755
755
  AND COALESCE(s.auto_title, '') NOT LIKE '[skill]%'
756
756
  ORDER BY COALESCE(s.started_at, '') DESC
757
- LIMIT @limit`).all({limit:rw});s(p)}catch(u){i(u instanceof Error?u.message:String(u))}finally{r(!1)}},[]),{sessions:sw(()=>{let u=e.trim().toLowerCase();return u?t.filter(p=>{let m=p.project_name?.toLowerCase()??"",f=p.first_user_message?.toLowerCase()??"";return m.includes(u)||f.includes(u)}):t},[t,e]),total:t.length,loading:n,error:o,dbExists:a}}var rw,Au=N(()=>{"use strict";T();j();rw=200});import{useEffect as _o,useMemo as ow,useState as Ue}from"react";import{Box as dt,Text as pn,useApp as iw,useInput as aw}from"ink";import{spawn as cw}from"node:child_process";import{platform as mn}from"node:os";import{jsx as ie,jsxs as Eo}from"react/jsx-runtime";function vu(){return{cols:process.stdout.columns??100,rows:process.stdout.rows??30}}function mw(e){let t=mn()==="darwin"?"open":mn()==="win32"?"start":"xdg-open",s=mn()==="win32"?["",e]:[e];cw(t,s,{detached:!0,stdio:"ignore",shell:mn()==="win32"}).unref()}function Mu({onShowSession:e}){let{exit:t}=iw(),s=vu(),[n,r]=Ue(s.cols),[o,i]=Ue(s.rows),[a,l]=Ue(0),[c,u]=Ue(""),[p,m]=Ue("normal"),[f,g]=Ue(null),[h,E]=Ue("preview"),[b,S]=Ue("recent"),[C,R]=Ue(!1),[L,Q]=Ue(!1),{sessions:v,total:ee,loading:B,error:y,dbExists:U}=Ou(c),M=ow(()=>{if(v.length===0)return v;let $=new Map;if(b==="busiest"||C)for(let O of v)$.set(O.project_name,($.get(O.project_name)??0)+1);let X=[...v];if(b==="longest"?X.sort((O,J)=>(J.message_count??0)-(O.message_count??0)):b==="busiest"&&X.sort((O,J)=>{let Re=$.get(O.project_name)??0,ke=$.get(J.project_name)??0;return ke!==Re?ke-Re:(J.started_at??"").localeCompare(O.started_at??"")}),C){let O=new Map;for(let ke of X){let He=O.get(ke.project_name);He||(He=[],O.set(ke.project_name,He)),He.push(ke)}let J=Array.from(O.keys()).sort((ke,He)=>{if(b==="busiest"){let wo=$.get(ke)??0,xo=$.get(He)??0;if(xo!==wo)return xo-wo}return ke.localeCompare(He)}),Re=[];for(let ke of J)for(let He of O.get(ke)??[])Re.push(He);return Re}return X},[v,b,C]);_o(()=>{let $=()=>{let X=vu();r(X.cols),i(X.rows)};return process.stdout.on("resize",$),()=>{process.stdout.off("resize",$)}},[]),_o(()=>{if(M.length===0){a!==0&&l(0);return}a>=M.length&&l(M.length-1)},[M.length,a]),_o(()=>{if(!f)return;let $=setTimeout(()=>g(null),2500);return()=>clearTimeout($)},[f]),aw(($,X)=>{if(p==="search"){X.escape&&(m("normal"),u(""));return}if(p==="alias"||p==="tag"){X.escape&&m("normal");return}if(L){($==="?"||X.escape||$==="q")&&Q(!1);return}if($==="q"||X.ctrl&&$==="c"){t();return}if($==="?"){Q(!0);return}if(!(M.length===0&&$!=="/")){if(X.upArrow||$==="k"){l(O=>Math.max(0,O-1));return}if(X.downArrow||$==="j"){l(O=>Math.min(M.length-1,O+1));return}if(X.pageUp){l(O=>Math.max(0,O-10));return}if(X.pageDown){l(O=>Math.min(M.length-1,O+10));return}if(X.return){let O=M[a];O&&(e(O.id),t());return}if($==="o"){let O=M[a];if(!O)return;let J=K();if(!J){g("start the daemon first (`recall start`)");return}let Re=`http://127.0.0.1:${J.port}/sessions/${O.id}`;mw(Re),g(`opened ${Re}`);return}if($==="n"){E(J=>J==="neighborhood"?"preview":"neighborhood");let O=M[a];O&&g(h==="neighborhood"?"preview view":`neighborhood for ${O.id.slice(0,8)}`);return}if($==="/"){m("search");return}if($==="a"){M[a]&&m("alias");return}if($==="t"){M[a]&&m("tag");return}if($==="s"){S(O=>{let J=ho.indexOf(O),Re=ho[(J+1)%ho.length];return g(`sort: ${gw[Re]}`),Re});return}if($==="g"){R(O=>(g(O?"flat view":"grouped by project"),!O));return}}});function q($){m("normal");let X=M[a];if(!X)return;let O=$.trim();if(!O){g("alias unchanged (empty input)");return}try{ys(X.id,O),g(`alias set: ${O}`)}catch(J){g(`alias failed: ${J instanceof Error?J.message:"unknown"}`)}}function Be($){m("normal");let X=M[a];if(!X)return;let O=$.trim();if(!O){g("tag unchanged (empty input)");return}try{let J=la(X.id,O);g(J.added?`tag added: ${J.tag}`:`tag exists: ${J.tag}`)}catch(J){g(`tag failed: ${J instanceof Error?J.message:"unknown"}`)}}if(n<lo||o<uo)return Eo(dt,{flexDirection:"column",padding:1,children:[ie(pn,{color:Me,children:"Terminal too small."}),ie(pn,{color:w,children:`Resize to at least ${lo} cols x ${uo} rows. Current: ${n} x ${o}.`}),ie(pn,{color:w,children:"Press q to quit."})]});let je=Math.max(10,o-pw-Iu),ut=Math.max(36,Math.floor(n*.4)),To=n-ut-1,fn=M[a]??null;return Eo(dt,{flexDirection:"column",width:n,height:o,children:[ie(mu,{cols:n}),ie(dt,{height:1}),y?ie(dt,{paddingX:1,children:ie(pn,{color:Me,children:`Error loading sessions: ${y}`})}):L?ie(dt,{height:je,children:ie(Cu,{width:n,height:je})}):Eo(dt,{flexDirection:"row",height:je,children:[ie(_u,{sessions:M,total:ee,selected:a,width:ut,height:je,loading:B,dbExists:U,filter:c,sortMode:b,groupByProject:C}),ie(dt,{width:1,height:je}),h==="neighborhood"?ie(wu,{session:fn,width:To,height:je,budget:4e3}):ie(yu,{session:fn,width:To,height:je})]}),ie(dt,{height:Iu,width:n,paddingX:1,children:ie(ku,{mode:p,query:c,onQueryChange:u,onSearchSubmit:()=>m("normal"),onAliasSubmit:q,onTagSubmit:Be,aliasInitial:fn?.alias??"",toast:f})})]})}var lw,dw,uw,Iu,pw,ho,gw,Du=N(()=>{"use strict";fu();hu();Tu();xu();Nu();Lu();Au();We();Ft();Zn();it();lw=4,dw=1,uw=1,Iu=1,pw=lw+dw+uw,ho=["recent","longest","busiest"];gw={recent:"most recent first",longest:"longest sessions first",busiest:"busiest project first"}});import{render as fw}from"ink";import{jsx as _w}from"react/jsx-runtime";async function $u(){let e={showSessionId:null};return await fw(_w(Mu,{onShowSession:n=>{e.showSessionId=n}})).waitUntilExit(),e}var ju=N(()=>{"use strict";Du()});var Pu={};fe(Pu,{runTui:()=>Ew});import{spawn as hw}from"node:child_process";async function Ew(){if(!process.stdin.isTTY||!process.stdout.isTTY){console.error("recall tui requires an interactive terminal. Run it directly (no pipes)."),process.exitCode=1;return}let e=await $u();if(!e.showSessionId)return;let t=process.argv[1];t&&await new Promise(s=>{let n=hw(process.execPath,[t,"show",e.showSessionId],{stdio:"inherit"});n.on("exit",()=>s()),n.on("error",()=>s())})}var Fu=N(()=>{"use strict";ju()});var Uu={};fe(Uu,{findSimilarSessions:()=>Sw,vectorSearch:()=>bw});async function bw(e,t=50){let s=await or(e),n=_(),r=Buffer.from(s.buffer,s.byteOffset,s.byteLength);return n.prepare(`SELECT v.rowid, v.distance, cm.session_id, cm.text, cm.message_uuids
757
+ LIMIT @limit`).all({limit:iw});s(p)}catch(u){i(u instanceof Error?u.message:String(u))}finally{r(!1)}},[]),{sessions:rw(()=>{let u=e.trim().toLowerCase();return u?t.filter(p=>{let m=p.project_name?.toLowerCase()??"",f=p.first_user_message?.toLowerCase()??"";return m.includes(u)||f.includes(u)}):t},[t,e]),total:t.length,loading:n,error:o,dbExists:a}}var iw,Au=N(()=>{"use strict";T();j();iw=200});import{useEffect as _o,useMemo as aw,useState as Ue}from"react";import{Box as dt,Text as pn,useApp as cw,useInput as lw}from"ink";import{spawn as dw}from"node:child_process";import{platform as mn}from"node:os";import{jsx as ie,jsxs as Eo}from"react/jsx-runtime";function vu(){return{cols:process.stdout.columns??100,rows:process.stdout.rows??30}}function fw(e){let t=mn()==="darwin"?"open":mn()==="win32"?"start":"xdg-open",s=mn()==="win32"?["",e]:[e];dw(t,s,{detached:!0,stdio:"ignore",shell:mn()==="win32"}).unref()}function Mu({onShowSession:e}){let{exit:t}=cw(),s=vu(),[n,r]=Ue(s.cols),[o,i]=Ue(s.rows),[a,l]=Ue(0),[c,u]=Ue(""),[p,m]=Ue("normal"),[f,g]=Ue(null),[h,E]=Ue("preview"),[b,S]=Ue("recent"),[C,R]=Ue(!1),[L,Q]=Ue(!1),{sessions:v,total:ee,loading:B,error:y,dbExists:U}=Ou(c),M=aw(()=>{if(v.length===0)return v;let D=new Map;if(b==="busiest"||C)for(let O of v)D.set(O.project_name,(D.get(O.project_name)??0)+1);let X=[...v];if(b==="longest"?X.sort((O,J)=>(J.message_count??0)-(O.message_count??0)):b==="busiest"&&X.sort((O,J)=>{let Re=D.get(O.project_name)??0,ke=D.get(J.project_name)??0;return ke!==Re?ke-Re:(J.started_at??"").localeCompare(O.started_at??"")}),C){let O=new Map;for(let ke of X){let He=O.get(ke.project_name);He||(He=[],O.set(ke.project_name,He)),He.push(ke)}let J=Array.from(O.keys()).sort((ke,He)=>{if(b==="busiest"){let wo=D.get(ke)??0,xo=D.get(He)??0;if(xo!==wo)return xo-wo}return ke.localeCompare(He)}),Re=[];for(let ke of J)for(let He of O.get(ke)??[])Re.push(He);return Re}return X},[v,b,C]);_o(()=>{let D=()=>{let X=vu();r(X.cols),i(X.rows)};return process.stdout.on("resize",D),()=>{process.stdout.off("resize",D)}},[]),_o(()=>{if(M.length===0){a!==0&&l(0);return}a>=M.length&&l(M.length-1)},[M.length,a]),_o(()=>{if(!f)return;let D=setTimeout(()=>g(null),2500);return()=>clearTimeout(D)},[f]),lw((D,X)=>{if(p==="search"){X.escape&&(m("normal"),u(""));return}if(p==="alias"||p==="tag"){X.escape&&m("normal");return}if(L){(D==="?"||X.escape||D==="q")&&Q(!1);return}if(D==="q"||X.ctrl&&D==="c"){t();return}if(D==="?"){Q(!0);return}if(!(M.length===0&&D!=="/")){if(X.upArrow||D==="k"){l(O=>Math.max(0,O-1));return}if(X.downArrow||D==="j"){l(O=>Math.min(M.length-1,O+1));return}if(X.pageUp){l(O=>Math.max(0,O-10));return}if(X.pageDown){l(O=>Math.min(M.length-1,O+10));return}if(X.return){let O=M[a];O&&(e(O.id),t());return}if(D==="o"){let O=M[a];if(!O)return;let J=K();if(!J){g("start the daemon first (`recall start`)");return}let Re=`http://127.0.0.1:${J.port}/sessions/${O.id}`;fw(Re),g(`opened ${Re}`);return}if(D==="n"){E(J=>J==="neighborhood"?"preview":"neighborhood");let O=M[a];O&&g(h==="neighborhood"?"preview view":`neighborhood for ${O.id.slice(0,8)}`);return}if(D==="/"){m("search");return}if(D==="a"){M[a]&&m("alias");return}if(D==="t"){M[a]&&m("tag");return}if(D==="s"){S(O=>{let J=ho.indexOf(O),Re=ho[(J+1)%ho.length];return g(`sort: ${_w[Re]}`),Re});return}if(D==="g"){R(O=>(g(O?"flat view":"grouped by project"),!O));return}}});function q(D){m("normal");let X=M[a];if(!X)return;let O=D.trim();if(!O){g("alias unchanged (empty input)");return}try{ys(X.id,O),g(`alias set: ${O}`)}catch(J){g(`alias failed: ${J instanceof Error?J.message:"unknown"}`)}}function Be(D){m("normal");let X=M[a];if(!X)return;let O=D.trim();if(!O){g("tag unchanged (empty input)");return}try{let J=la(X.id,O);g(J.added?`tag added: ${J.tag}`:`tag exists: ${J.tag}`)}catch(J){g(`tag failed: ${J instanceof Error?J.message:"unknown"}`)}}if(n<lo||o<uo)return Eo(dt,{flexDirection:"column",padding:1,children:[ie(pn,{color:Me,children:"Terminal too small."}),ie(pn,{color:w,children:`Resize to at least ${lo} cols x ${uo} rows. Current: ${n} x ${o}.`}),ie(pn,{color:w,children:"Press q to quit."})]});let je=Math.max(10,o-gw-Iu),ut=Math.max(36,Math.floor(n*.4)),To=n-ut-1,fn=M[a]??null;return Eo(dt,{flexDirection:"column",width:n,height:o,children:[ie(mu,{cols:n}),ie(dt,{height:1}),y?ie(dt,{paddingX:1,children:ie(pn,{color:Me,children:`Error loading sessions: ${y}`})}):L?ie(dt,{height:je,children:ie(Cu,{width:n,height:je})}):Eo(dt,{flexDirection:"row",height:je,children:[ie(_u,{sessions:M,total:ee,selected:a,width:ut,height:je,loading:B,dbExists:U,filter:c,sortMode:b,groupByProject:C}),ie(dt,{width:1,height:je}),h==="neighborhood"?ie(wu,{session:fn,width:To,height:je,budget:4e3}):ie(yu,{session:fn,width:To,height:je})]}),ie(dt,{height:Iu,width:n,paddingX:1,children:ie(ku,{mode:p,query:c,onQueryChange:u,onSearchSubmit:()=>m("normal"),onAliasSubmit:q,onTagSubmit:Be,aliasInitial:fn?.alias??"",toast:f})})]})}var uw,pw,mw,Iu,gw,ho,_w,$u=N(()=>{"use strict";fu();hu();Tu();xu();Nu();Lu();Au();We();Ft();Zn();it();uw=4,pw=1,mw=1,Iu=1,gw=uw+pw+mw,ho=["recent","longest","busiest"];_w={recent:"most recent first",longest:"longest sessions first",busiest:"busiest project first"}});import{render as hw}from"ink";import{jsx as Ew}from"react/jsx-runtime";async function Du(){let e={showSessionId:null};return await hw(Ew(Mu,{onShowSession:n=>{e.showSessionId=n}})).waitUntilExit(),e}var ju=N(()=>{"use strict";$u()});var Pu={};fe(Pu,{runTui:()=>Sw});import{spawn as bw}from"node:child_process";async function Sw(){if(!process.stdin.isTTY||!process.stdout.isTTY){console.error("recall tui requires an interactive terminal. Run it directly (no pipes)."),process.exitCode=1;return}let e=await Du();if(!e.showSessionId)return;let t=process.argv[1];t&&await new Promise(s=>{let n=bw(process.execPath,[t,"show",e.showSessionId],{stdio:"inherit"});n.on("exit",()=>s()),n.on("error",()=>s())})}var Fu=N(()=>{"use strict";ju()});var Uu={};fe(Uu,{findSimilarSessions:()=>Tw,vectorSearch:()=>yw});async function yw(e,t=50){let s=await or(e),n=_(),r=Buffer.from(s.buffer,s.byteOffset,s.byteLength);return n.prepare(`SELECT v.rowid, v.distance, cm.session_id, cm.text, cm.message_uuids
758
758
  FROM vec_chunks v JOIN chunk_meta cm ON cm.rowid = v.rowid
759
- WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(r,t).map(i=>({sessionId:i.session_id,chunkRowid:i.rowid,distance:i.distance,text:i.text,messageUuids:JSON.parse(i.message_uuids)}))}async function Sw(e,t=10,s=.65){let n=_(),r=n.prepare("SELECT rowid FROM chunk_meta WHERE session_id = ? ORDER BY rowid LIMIT 1").get(e);if(!r)return[];let o=n.prepare("SELECT embedding FROM vec_chunks WHERE rowid = ?").get(r.rowid);if(!o)return[];let i=n.prepare(`SELECT v.rowid, v.distance, cm.session_id FROM vec_chunks v JOIN chunk_meta cm ON cm.rowid = v.rowid
760
- WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(o.embedding,t*5),a=new Map;for(let c of i){if(c.session_id===e)continue;let u=a.get(c.session_id);(u===void 0||c.distance<u)&&a.set(c.session_id,c.distance)}let l=[];for(let[c,u]of a){let p=1-u;p>=s&&l.push({sessionId:c,similarity:p})}return l.sort((c,u)=>u.similarity-c.similarity),l.slice(0,t)}var Bu=N(()=>{"use strict";T();Ve()});import{createRequire as yw}from"module";import{Command as Tw}from"commander";T();j();import{basename as Wp}from"node:path";import{createReadStream as ip}from"node:fs";import{createInterface as ap}from"node:readline";function os(e){return typeof e=="number"&&Number.isFinite(e)?e:0}function wn(e){let t=e?.usage;if(!t||typeof t!="object")return null;let s={inputTokens:os(t.input_tokens),outputTokens:os(t.output_tokens),cacheCreateTokens:os(t.cache_creation_input_tokens),cacheReadTokens:os(t.cache_read_input_tokens)};return s.inputTokens===0&&s.outputTokens===0&&s.cacheCreateTokens===0&&s.cacheReadTokens===0?null:s}var cp=/\x1B\[[0-9;]*[a-zA-Z]/g;function yn(e){return e.replace(cp,"")}var Tn=12e3;function Mo(e,t){if(e.length<=Tn)return e;let s=e.slice(0,Tn),n=e.length-Tn;return`${s}
759
+ WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(r,t).map(i=>({sessionId:i.session_id,chunkRowid:i.rowid,distance:i.distance,text:i.text,messageUuids:JSON.parse(i.message_uuids)}))}async function Tw(e,t=10,s=.65){let n=_(),r=n.prepare("SELECT rowid FROM chunk_meta WHERE session_id = ? ORDER BY rowid LIMIT 1").get(e);if(!r)return[];let o=n.prepare("SELECT embedding FROM vec_chunks WHERE rowid = ?").get(r.rowid);if(!o)return[];let i=n.prepare(`SELECT v.rowid, v.distance, cm.session_id FROM vec_chunks v JOIN chunk_meta cm ON cm.rowid = v.rowid
760
+ WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(o.embedding,t*5),a=new Map;for(let c of i){if(c.session_id===e)continue;let u=a.get(c.session_id);(u===void 0||c.distance<u)&&a.set(c.session_id,c.distance)}let l=[];for(let[c,u]of a){let p=1-u;p>=s&&l.push({sessionId:c,similarity:p})}return l.sort((c,u)=>u.similarity-c.similarity),l.slice(0,t)}var Bu=N(()=>{"use strict";T();Ve()});import{createRequire as ww}from"module";import{Command as xw}from"commander";T();j();import{basename as Wp}from"node:path";import{createReadStream as ip}from"node:fs";import{createInterface as ap}from"node:readline";function os(e){return typeof e=="number"&&Number.isFinite(e)?e:0}function wn(e){let t=e?.usage;if(!t||typeof t!="object")return null;let s={inputTokens:os(t.input_tokens),outputTokens:os(t.output_tokens),cacheCreateTokens:os(t.cache_creation_input_tokens),cacheReadTokens:os(t.cache_read_input_tokens)};return s.inputTokens===0&&s.outputTokens===0&&s.cacheCreateTokens===0&&s.cacheReadTokens===0?null:s}var cp=/\x1B\[[0-9;]*[a-zA-Z]/g;function yn(e){return e.replace(cp,"")}var Tn=12e3;function Mo(e,t){if(e.length<=Tn)return e;let s=e.slice(0,Tn),n=e.length-Tn;return`${s}
761
761
 
762
762
  \u27E8\u2026 ${n.toLocaleString()} more chars in ${t}; see raw JSONL for full content \u27E9`}function lp(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function dp(e){if(typeof e.content=="string")return e.content;if(Array.isArray(e.content)){let t=[];for(let s of e.content)if(s&&typeof s=="object"){let n=s;n.type==="text"&&typeof n.text=="string"?t.push(n.text):n.type==="image"&&t.push("[image]")}return t.join(`
763
763
  `)}return""}function up(e){if(!e)return{text:"",toolNames:[]};if(typeof e.content=="string")return{text:yn(e.content),toolNames:[]};if(!Array.isArray(e.content))return{text:"",toolNames:[]};let t=[],s=[];for(let n of e.content)if(!(!n||typeof n!="object")){if(n.type==="text"&&typeof n.text=="string"){t.push(yn(n.text));continue}if(n.type==="tool_use"&&typeof n.name=="string"){s.push(n.name);let r=n.input!=null?lp(n.input):"",o=Mo(r,"tool input");t.push(`\u26A1 **Tool call \xB7 \`${n.name}\`**
@@ -770,7 +770,7 @@ ${o}
770
770
  ${o}
771
771
  \`\`\``)}else t.push("_(tool result was empty or image-only)_");continue}if(n.type==="image"){t.push("_(image)_");continue}t.push(`_(unknown block: ${n.type})_`)}return{text:t.join(`
772
772
 
773
- `),toolNames:s}}async function*Do(e){let t=ip(e,{encoding:"utf8"}),s=ap({input:t,crlfDelay:1/0});for await(let n of s){if(!n.trim())continue;let r;try{r=JSON.parse(n)}catch{continue}if(!r.uuid||!r.sessionId)continue;let{text:o,toolNames:i}=up(r.message);yield{uuid:r.uuid,parentUuid:r.parentUuid??null,sessionId:r.sessionId,type:r.type??"unknown",role:r.message?.role??null,timestamp:r.timestamp??null,isSidechain:r.isSidechain===!0,cwd:r.cwd??null,gitBranch:r.gitBranch??null,version:r.version??null,contentText:o,toolNames:i,raw:n,usage:wn(r.message),model:r.message?.model??null}}}I();var jo=[{name:"Anthropic API key",regex:/sk-ant-[a-zA-Z0-9_\-]{40,}/g,severity:"high"},{name:"OpenAI API key",regex:/sk-(?:proj-)?[a-zA-Z0-9]{32,}/g,severity:"high"},{name:"AWS access key ID",regex:/AKIA[0-9A-Z]{16}/g,severity:"high"},{name:"GitHub PAT",regex:/gh[pousr]_[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Stripe live/test key",regex:/(?:sk|rk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}/g,severity:"high"},{name:"Slack token",regex:/xox[abprs]-[A-Za-z0-9\-]{10,}/g,severity:"high"},{name:"Google API key",regex:/AIza[0-9A-Za-z_\-]{35}/g,severity:"high"},{name:"Private key block",regex:/-----BEGIN (?:RSA |DSA |EC |OPENSSH |ENCRYPTED )?PRIVATE KEY-----/g,severity:"high"},{name:"Apify token",regex:/apify_api_[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Notion integration",regex:/(?:secret_|ntn_)[A-Za-z0-9]{40,}/g,severity:"high"},{name:"Vercel token",regex:/vercel_[A-Za-z0-9]{24,}/g,severity:"high"},{name:"Supabase service key",regex:/sbp_[A-Za-z0-9]{40,}/g,severity:"high"},{name:"SendGrid key",regex:/SG\.[A-Za-z0-9_\-]{20,}\.[A-Za-z0-9_\-]{20,}/g,severity:"high"},{name:"Mailgun key",regex:/key-[a-f0-9]{32}/g,severity:"high"},{name:"Twilio SID",regex:/AC[a-f0-9]{32}/g,severity:"high"},{name:"Discord bot token",regex:/[MN][A-Za-z\d]{23}\.[\w-]{6}\.[\w-]{27,38}/g,severity:"high"},{name:"npm token",regex:/npm_[A-Za-z0-9]{36}/g,severity:"high"},{name:"HuggingFace token",regex:/hf_[A-Za-z0-9]{30,}/g,severity:"high"},{name:"Replicate token",regex:/r8_[A-Za-z0-9]{32,}/g,severity:"high"},{name:"Figma token",regex:/figd_[A-Za-z0-9_\-]{30,}/g,severity:"high"},{name:"Linear key",regex:/lin_api_[A-Za-z0-9]{30,}/g,severity:"high"},{name:"DigitalOcean token",regex:/dop_v1_[a-f0-9]{64}/g,severity:"high"},{name:"Generic provider token",regex:/\b[a-z][a-z0-9]{2,20}_(?:api|pat|token|sk|pk|key|auth)_(?=[A-Za-z0-9_\-]*\d)[A-Za-z0-9_\-]{20,}\b/g,severity:"high"},{name:"Bearer token",regex:/\b[Bb]earer\s+[A-Za-z0-9_\-\.=]{24,}\b/g,severity:"medium"},{name:"Slack webhook URL",regex:/https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Discord webhook URL",regex:/https:\/\/(?:ptb\.|canary\.)?discord(?:app)?\.com\/api\/webhooks\/\d+\/[A-Za-z0-9_\-]{40,}/g,severity:"high"},{name:"Teams webhook URL",regex:/https:\/\/[a-zA-Z0-9.\-]+\.webhook\.office\.com\/webhookb2\/[A-Za-z0-9@_\-\/]{30,}/g,severity:"high"},{name:"Secret near keyword",regex:/\b(?:webhook[_\s\-]?secret|signing[_\s\-]?secret|webhook[_\s\-]?signing[_\s\-]?secret|api[_\s\-]?secret|client[_\s\-]?secret|private[_\s\-]?key|access[_\s\-]?token|auth[_\s\-]?token|api[_\s\-]?key)\b[\s\S]{0,200}?\b(?:[a-fA-F0-9]{32,}|[A-Za-z0-9+/_\-]{20,}(?:\.[A-Za-z0-9+/_\-]{10,}){1,2}|[A-Za-z0-9+/_\-]{40,}={0,2})\b/gi,severity:"high"},{name:"JWT",regex:/eyJ[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}/g,severity:"medium"},{name:"URL with password",regex:/https?:\/\/[^:\s/@]+:[^@\s]{6,}@[^\s/]+/g,severity:"high"},{name:"Password assignment",regex:/(?<![A-Za-z])(?:password|passwd|pwd|secret|token|api[_\-]?key|access[_\-]?key|auth[_\-]?token|webhook[_\-]?secret|client[_\-]?secret|private[_\-]?key)\b\s*[:=]\s*["']?[A-Za-z0-9_\-+/=]{16,}/gi,severity:"high"}];function Po(e){if(e.length<=8)return e.slice(0,2)+"\u2022".repeat(Math.max(0,e.length-4))+e.slice(-2);let t=e.slice(0,Math.min(6,Math.floor(e.length/3))),s=e.slice(-Math.min(4,Math.floor(e.length/4)));return`${t}${"\u2022".repeat(Math.max(3,e.length-t.length-s.length))}${s}`}function Dt(e){if(!e)return[];let t=new Set,s=[];for(let n of jo){n.regex.lastIndex=0;for(let r of e.matchAll(n.regex)){let o=r[0],i=`${n.name}::${Fo(o)}`;t.has(i)||(t.add(i),s.push({pattern:n.name,maskedPreview:Po(o),offset:r.index??0,severity:n.severity}))}}return s}function Fo(e){let t=5381;for(let s=0;s<e.length;s++)t=(t<<5)+t+e.charCodeAt(s)|0;return(t>>>0).toString(36)}function qe(e){if(!e)return{redacted:e,count:0};let t=e,s=0,n=new Set;for(let r of jo)r.regex.lastIndex=0,t=t.replace(r.regex,o=>{let i=`${r.name}::${Fo(o)}`;return n.has(i)||(n.add(i),s+=1),`[REDACTED ${r.name}: ${Po(o)}]`});return{redacted:t,count:s}}function Uo(e,t,s){e.prepare("DELETE FROM message_usage WHERE session_id = ?").run(t);let n=e.prepare(`
773
+ `),toolNames:s}}async function*$o(e){let t=ip(e,{encoding:"utf8"}),s=ap({input:t,crlfDelay:1/0});for await(let n of s){if(!n.trim())continue;let r;try{r=JSON.parse(n)}catch{continue}if(!r.uuid||!r.sessionId)continue;let{text:o,toolNames:i}=up(r.message);yield{uuid:r.uuid,parentUuid:r.parentUuid??null,sessionId:r.sessionId,type:r.type??"unknown",role:r.message?.role??null,timestamp:r.timestamp??null,isSidechain:r.isSidechain===!0,cwd:r.cwd??null,gitBranch:r.gitBranch??null,version:r.version??null,contentText:o,toolNames:i,raw:n,usage:wn(r.message),model:r.message?.model??null}}}I();var jo=[{name:"Anthropic API key",regex:/sk-ant-[a-zA-Z0-9_\-]{40,}/g,severity:"high"},{name:"OpenAI API key",regex:/sk-(?:proj-)?[a-zA-Z0-9]{32,}/g,severity:"high"},{name:"AWS access key ID",regex:/AKIA[0-9A-Z]{16}/g,severity:"high"},{name:"GitHub PAT",regex:/gh[pousr]_[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Stripe live/test key",regex:/(?:sk|rk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}/g,severity:"high"},{name:"Slack token",regex:/xox[abprs]-[A-Za-z0-9\-]{10,}/g,severity:"high"},{name:"Google API key",regex:/AIza[0-9A-Za-z_\-]{35}/g,severity:"high"},{name:"Private key block",regex:/-----BEGIN (?:RSA |DSA |EC |OPENSSH |ENCRYPTED )?PRIVATE KEY-----/g,severity:"high"},{name:"Apify token",regex:/apify_api_[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Notion integration",regex:/(?:secret_|ntn_)[A-Za-z0-9]{40,}/g,severity:"high"},{name:"Vercel token",regex:/vercel_[A-Za-z0-9]{24,}/g,severity:"high"},{name:"Supabase service key",regex:/sbp_[A-Za-z0-9]{40,}/g,severity:"high"},{name:"SendGrid key",regex:/SG\.[A-Za-z0-9_\-]{20,}\.[A-Za-z0-9_\-]{20,}/g,severity:"high"},{name:"Mailgun key",regex:/key-[a-f0-9]{32}/g,severity:"high"},{name:"Twilio SID",regex:/AC[a-f0-9]{32}/g,severity:"high"},{name:"Discord bot token",regex:/[MN][A-Za-z\d]{23}\.[\w-]{6}\.[\w-]{27,38}/g,severity:"high"},{name:"npm token",regex:/npm_[A-Za-z0-9]{36}/g,severity:"high"},{name:"HuggingFace token",regex:/hf_[A-Za-z0-9]{30,}/g,severity:"high"},{name:"Replicate token",regex:/r8_[A-Za-z0-9]{32,}/g,severity:"high"},{name:"Figma token",regex:/figd_[A-Za-z0-9_\-]{30,}/g,severity:"high"},{name:"Linear key",regex:/lin_api_[A-Za-z0-9]{30,}/g,severity:"high"},{name:"DigitalOcean token",regex:/dop_v1_[a-f0-9]{64}/g,severity:"high"},{name:"Generic provider token",regex:/\b[a-z][a-z0-9]{2,20}_(?:api|pat|token|sk|pk|key|auth)_(?=[A-Za-z0-9_\-]*\d)[A-Za-z0-9_\-]{20,}\b/g,severity:"high"},{name:"Bearer token",regex:/\b[Bb]earer\s+[A-Za-z0-9_\-\.=]{24,}\b/g,severity:"medium"},{name:"Slack webhook URL",regex:/https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Discord webhook URL",regex:/https:\/\/(?:ptb\.|canary\.)?discord(?:app)?\.com\/api\/webhooks\/\d+\/[A-Za-z0-9_\-]{40,}/g,severity:"high"},{name:"Teams webhook URL",regex:/https:\/\/[a-zA-Z0-9.\-]+\.webhook\.office\.com\/webhookb2\/[A-Za-z0-9@_\-\/]{30,}/g,severity:"high"},{name:"Secret near keyword",regex:/\b(?:webhook[_\s\-]?secret|signing[_\s\-]?secret|webhook[_\s\-]?signing[_\s\-]?secret|api[_\s\-]?secret|client[_\s\-]?secret|private[_\s\-]?key|access[_\s\-]?token|auth[_\s\-]?token|api[_\s\-]?key)\b[\s\S]{0,200}?\b(?:[a-fA-F0-9]{32,}|[A-Za-z0-9+/_\-]{20,}(?:\.[A-Za-z0-9+/_\-]{10,}){1,2}|[A-Za-z0-9+/_\-]{40,}={0,2})\b/gi,severity:"high"},{name:"JWT",regex:/eyJ[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}/g,severity:"medium"},{name:"URL with password",regex:/https?:\/\/[^:\s/@]+:[^@\s]{6,}@[^\s/]+/g,severity:"high"},{name:"Password assignment",regex:/(?<![A-Za-z])(?:password|passwd|pwd|secret|token|api[_\-]?key|access[_\-]?key|auth[_\-]?token|webhook[_\-]?secret|client[_\-]?secret|private[_\-]?key)\b\s*[:=]\s*["']?[A-Za-z0-9_\-+/=]{16,}/gi,severity:"high"}];function Po(e){if(e.length<=8)return e.slice(0,2)+"\u2022".repeat(Math.max(0,e.length-4))+e.slice(-2);let t=e.slice(0,Math.min(6,Math.floor(e.length/3))),s=e.slice(-Math.min(4,Math.floor(e.length/4)));return`${t}${"\u2022".repeat(Math.max(3,e.length-t.length-s.length))}${s}`}function $t(e){if(!e)return[];let t=new Set,s=[];for(let n of jo){n.regex.lastIndex=0;for(let r of e.matchAll(n.regex)){let o=r[0],i=`${n.name}::${Fo(o)}`;t.has(i)||(t.add(i),s.push({pattern:n.name,maskedPreview:Po(o),offset:r.index??0,severity:n.severity}))}}return s}function Fo(e){let t=5381;for(let s=0;s<e.length;s++)t=(t<<5)+t+e.charCodeAt(s)|0;return(t>>>0).toString(36)}function qe(e){if(!e)return{redacted:e,count:0};let t=e,s=0,n=new Set;for(let r of jo)r.regex.lastIndex=0,t=t.replace(r.regex,o=>{let i=`${r.name}::${Fo(o)}`;return n.has(i)||(n.add(i),s+=1),`[REDACTED ${r.name}: ${Po(o)}]`});return{redacted:t,count:s}}function Uo(e,t,s){e.prepare("DELETE FROM message_usage WHERE session_id = ?").run(t);let n=e.prepare(`
774
774
  INSERT INTO message_usage (
775
775
  message_uuid, session_id, model,
776
776
  input_tokens, output_tokens, cache_create_tokens, cache_read_tokens,
@@ -802,7 +802,7 @@ ${o}
802
802
  total_cache_create_tokens = @cc,
803
803
  total_cache_read_tokens = @cr,
804
804
  primary_model = @model
805
- WHERE id = @id`).run({id:t,input:s.input_tokens,output:s.output_tokens,cc:s.cache_create_tokens,cr:s.cache_read_tokens,model:n?.model??null})}T();j();import{writeFileSync as Ep,mkdirSync as bp,existsSync as Sp}from"node:fs";import{join as Wo}from"node:path";T();var gp=[/^You will receive a sample of user messages from a Claude Cod/i,/^You will receive the first \d+ user messages from a Claude/i,/^Base directory for this skill:/i,/^You are Claude Code in a fresh terminal/i,/^You are extracting a structured Output Index from a Claude/i];var fp=[/^Score this person'?s relevance/i,/^You are a [^\n.]{1,60}co-pilot/i,/^Return ONLY valid JSON/i],_p=[/^Draft (a|an|marketing) [a-z]/i,/^Read the file at /i,/^Read this and then begin/i,/^read this and then begin/i],hp=20;function Bo(e){if(e.auto_title_source==="agent"&&e.auto_title)return"agent";if(e.has_alias)return"manual_alias";if(e.auto_title&&e.auto_title.includes(" \xB7 "))return"fixed_v0.16.1";if(!e.auto_title||e.auto_title.length<hp)return"low_signal";for(let t of gp)if(t.test(e.auto_title))return"recursive_meta";for(let t of fp)if(t.test(e.auto_title))return"programmatic";for(let t of _p)if(t.test(e.auto_title))return"template_pending";return"clean"}function xn(e){if(!e)return"";let t=e.split("|")[0];return t=t.replace(/\s*\([^)]*\)\s*$/,""),t=t.replace(/\s+/g," ").trim(),t}var kn=Wo(x,"titles"),yp=80,Tp=60,wp=100;function xp(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(s=>!!s&&typeof s=="object"&&typeof s.title=="string"&&typeof s.replaced_at=="string")}catch{}return[]}function Xo(e){if(!e)return null;let t=e;if(t=t.replace(/```[\s\S]*?```/g," "),t=t.replace(/`[^`]+`/g," "),t=t.replace(/https?:\/\/\S+/g,"[url]"),t=t.replace(/\s+/g," ").trim(),!t)return null;let s=Rp(t,e);if(s)return s;let n=t.match(/^[^.!?\n]{8,}?[.!?]/)?.[0]?.trim();return(n&&n.length<=yp?n:t.slice(0,Tp)).trim()||null}function Rp(e,t){let s=e.match(/^\/([A-Za-z0-9][A-Za-z0-9_-]*)\s+([\s\S]*)$/);if(s){let n=`/${s[1]}`,r=t.replace(/^\s*\/[A-Za-z0-9][A-Za-z0-9_-]*\s+/,""),o=Nn(r);return o?$t(`${n} \xB7 ${o}`):n}for(let n of kp){if(!e.match(n.match))continue;let o=n.prefix,i=n.extract?n.extract(e,t):Nn(t);return i?n.completeFromExtract?$t(i):$t(`${o} \xB7 ${i}`):o}for(let n of Lp){if(!e.match(n.match))continue;let o=n.extract?n.extract(e,t):as(t);return o?n.completeFromExtract?$t(o):$t(`${n.prefix} \xB7 ${o}`):n.prefix}return null}var kp=[{match:/^Draft (?:a|an) brand brief\b/i,prefix:"Draft brand brief"},{match:/^Draft (?:a|an) sales brief\b/i,prefix:"Draft sales brief"},{match:/^Draft (?:a|an) leave-behind\b/i,prefix:"Draft leave-behind"},{match:/^Draft (?:a|an) audio identity brief\b/i,prefix:"Draft audio identity brief"},{match:/^Draft marketing ideas\b/i,prefix:"Draft marketing ideas"},{match:/^Draft (?:a|an) ([a-z]{3,30}(?:\s+[a-z]{3,30}){0,2})\b/i,prefix:"Draft",extract:(e,t)=>{let n=e.match(/^Draft (?:a|an) ([a-z]{3,30}(?:\s+[a-z]{3,30}){0,2})\b/i)?.[1]?.trim(),r=Nn(t);return n&&r?`${n} \xB7 ${r}`:n||r}},{match:/^Read the file at /i,prefix:"Read",extract:e=>{let s=e.match(/^Read the file at\s+([^\s]+)/i)?.[1];return s?s.split("/").filter(Boolean).slice(-2).join("/")||s:null}},{match:/^(?:read|inspect) this and then begin\b/i,prefix:"Begin from preamble",completeFromExtract:!0,extract:(e,t)=>Cp(t)},{match:/^Base directory for this skill:/i,prefix:"[skill]",completeFromExtract:!0,extract:(e,t)=>{let s=t.match(/\.claude\/skills\/([^/\s]+)/);return s?.[1]?`[skill] ${s[1]}`:null}},{match:/^You are extracting a structured Output Index/i,prefix:"[output-index]",completeFromExtract:!0,extract:(e,t)=>Np(t)},{match:/^You will receive a sample of user messages from a Claude Code session:/i,prefix:"[meta]",completeFromExtract:!0,extract:(e,t)=>Ho(t,"[meta] auto-title (full-arc)")},{match:/^You will receive the first \d+ user messages from a Claude Code session/i,prefix:"[meta]",completeFromExtract:!0,extract:(e,t)=>Ho(t,"[meta] auto-title (initial)")},{match:/^You are implementing v\d+\.\d+/i,prefix:"Implementing",completeFromExtract:!0,extract:e=>{let t=e.match(/^You are implementing (v\d+\.\d+\w*)\s*(?:\(([^)]+)\))?/i);if(!t)return null;let s=t[1],n=t[2]?.trim();return n?`Implementing ${s} \xB7 ${n}`:`Implementing ${s}`}}];function Np(e){if(!e)return"[output-index] extractor";let t=e.match(/^Session:\s*([0-9a-f]{8})\b/im),s=e.match(/^Opening prompt:\s*([^\n]{1,140})/im),n=t?.[1]?.trim(),r=s?.[1]?.trim().replace(/\s+/g," "),o=r&&r.length>70?r.slice(0,67)+"\u2026":r;return n&&o?`[output-index] \xB7 ${n} \xB7 ${o}`:n?`[output-index] \xB7 ${n}`:o?`[output-index] \xB7 ${o}`:"[output-index] extractor"}function Ho(e,t){if(!e)return t;let s=e.indexOf("Messages:");if(s===-1)return t;let n=e.slice(s+9),r=/^\s*\d+\.\s*([^\n]+)/gm;for(let o of n.matchAll(r)){let i=o[1]?.trim()??"";if(!i)continue;let a=i.replace(/^<[^>]+>[\s\S]*?<\/[^>]+>\s*/g,"").replace(/^\[Pasted text[^\]]*\]\s*/i,"").trim();if(!a||/^<local-command-/.test(a))continue;let l=a.length>60?a.slice(0,57)+"\u2026":a;return`${t} \xB7 ${l}`}return t}function Cp(e){if(!e)return null;let t=e.match(/([\/\w.\-]+\.(?:md|markdown|txt|json|yaml|yml|toml|ts|tsx|js|jsx|py|sql))(?=[\s,;:)\]"'`]|$)/i);if(!t)return null;let s=t[1].split("/").filter(Boolean);return(s[s.length-1]??"").replace(/\.[^.]+$/,"")||null}var Lp=[{match:/^Score this person'?s relevance/i,prefix:"Score relevance",extract:(e,t)=>as(t)},{match:/^You are a [^\n.]{1,60}co-pilot/i,prefix:"co-pilot",completeFromExtract:!0,extract:(e,t)=>{let n=e.match(/^You are a ([^\n.]{1,60}?)co-pilot/i)?.[1]?.trim(),r=n?`${n} co-pilot`:"co-pilot",o=as(t);return o?`${r} \xB7 ${o}`:r}},{match:/^Return ONLY valid JSON/i,prefix:"JSON-only",extract:(e,t)=>as(t)}];function as(e){let t=/^\s*(Name|Company|Prospect|Author|Brand|Client)\s*:\s*([^\n]+)/gim,s;for(;(s=t.exec(e))!==null;){let n=s[2].trim();if(!n||/^(null|none|n\/a|—|-)$/i.test(n))continue;let r=n.replace(/\s+/g," ");return xn(r)||r}return null}function $t(e){return e.slice(0,wp).trim()}var Op=[/^deep research$/i,/^reference(?: spec)?$/i,/^canonical spec/i,/^product context/i,/^services?(?: overview)?$/i,/^overview$/i,/^(?:introduction|template|instructions|context)$/i],Ap=[/^(?:brand|brand brief|brand summary)$/i,/^(?:known facts?|facts)$/i,/^(?:client|prospect|customer|account)$/i,/^(?:topic|subject|brief|task)$/i,/^(?:about|for|re)$/i];function Rn(e){let t=e.trim();return t.length<3?!0:Op.some(s=>s.test(t))}function Ip(e){let t=e.trim().replace(/\s*\([^)]*\)\s*$/,"").trim();return Ap.some(s=>s.test(t))}function Nn(e){let t=vp(e);return t===null?null:xn(t)||t}function vp(e){if(/^\s*Skill smoke test\b/i.test(e))return"smoke test";let t=/(^|\n)#{1,3}\s+([^\n]+?)\s+(?:—|–|-|:)\s+([^\n]{2,80})/g,s,n=[];for(;(s=t.exec(e))!==null;){let l=s[2].trim(),c=s[3].trim().replace(/\s+/g," ");if(!Rn(c)){if(Ip(l))return c;n.push(c)}}if(n.length>0)return n[0];let r=e.match(/\b(?:Topic|Subject|Brand|About|Client|For|Re)\s*:\s*([^\n]{2,80})/i);if(r?.[1]&&!Rn(r[1]))return r[1].trim().replace(/\s+/g," ");let o=/===\s*([^=\n]{2,120}?)\s*===/g;for(;(s=o.exec(e))!==null;){let l=s[1].trim().replace(/\.(md|txt|json)$/i,""),c=l.replace(/\s*\([^)]*\)\s*$/,"").trim();if(c&&!Rn(c)&&!/product context|reference/i.test(l))return c}let i=e.replace(/^Context for this run[^:]*:\s*/i,"");if(i!==e){let l=i.split(`
805
+ WHERE id = @id`).run({id:t,input:s.input_tokens,output:s.output_tokens,cc:s.cache_create_tokens,cr:s.cache_read_tokens,model:n?.model??null})}T();j();import{writeFileSync as Ep,mkdirSync as bp,existsSync as Sp}from"node:fs";import{join as Wo}from"node:path";T();var gp=[/^You will receive a sample of user messages from a Claude Cod/i,/^You will receive the first \d+ user messages from a Claude/i,/^Base directory for this skill:/i,/^You are Claude Code in a fresh terminal/i,/^You are extracting a structured Output Index from a Claude/i];var fp=[/^Score this person'?s relevance/i,/^You are a [^\n.]{1,60}co-pilot/i,/^Return ONLY valid JSON/i],_p=[/^Draft (a|an|marketing) [a-z]/i,/^Read the file at /i,/^Read this and then begin/i,/^read this and then begin/i],hp=20;function Bo(e){if(e.auto_title_source==="agent"&&e.auto_title)return"agent";if(e.has_alias)return"manual_alias";if(e.auto_title&&e.auto_title.includes(" \xB7 "))return"fixed_v0.16.1";if(!e.auto_title||e.auto_title.length<hp)return"low_signal";for(let t of gp)if(t.test(e.auto_title))return"recursive_meta";for(let t of fp)if(t.test(e.auto_title))return"programmatic";for(let t of _p)if(t.test(e.auto_title))return"template_pending";return"clean"}function xn(e){if(!e)return"";let t=e.split("|")[0];return t=t.replace(/\s*\([^)]*\)\s*$/,""),t=t.replace(/\s+/g," ").trim(),t}var kn=Wo(x,"titles"),yp=80,Tp=60,wp=100;function xp(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(s=>!!s&&typeof s=="object"&&typeof s.title=="string"&&typeof s.replaced_at=="string")}catch{}return[]}function Xo(e){if(!e)return null;let t=e;if(t=t.replace(/```[\s\S]*?```/g," "),t=t.replace(/`[^`]+`/g," "),t=t.replace(/https?:\/\/\S+/g,"[url]"),t=t.replace(/\s+/g," ").trim(),!t)return null;let s=Rp(t,e);if(s)return s;let n=t.match(/^[^.!?\n]{8,}?[.!?]/)?.[0]?.trim();return(n&&n.length<=yp?n:t.slice(0,Tp)).trim()||null}function Rp(e,t){let s=e.match(/^\/([A-Za-z0-9][A-Za-z0-9_-]*)\s+([\s\S]*)$/);if(s){let n=`/${s[1]}`,r=t.replace(/^\s*\/[A-Za-z0-9][A-Za-z0-9_-]*\s+/,""),o=Nn(r);return o?Dt(`${n} \xB7 ${o}`):n}for(let n of kp){if(!e.match(n.match))continue;let o=n.prefix,i=n.extract?n.extract(e,t):Nn(t);return i?n.completeFromExtract?Dt(i):Dt(`${o} \xB7 ${i}`):o}for(let n of Lp){if(!e.match(n.match))continue;let o=n.extract?n.extract(e,t):as(t);return o?n.completeFromExtract?Dt(o):Dt(`${n.prefix} \xB7 ${o}`):n.prefix}return null}var kp=[{match:/^Draft (?:a|an) brand brief\b/i,prefix:"Draft brand brief"},{match:/^Draft (?:a|an) sales brief\b/i,prefix:"Draft sales brief"},{match:/^Draft (?:a|an) leave-behind\b/i,prefix:"Draft leave-behind"},{match:/^Draft (?:a|an) audio identity brief\b/i,prefix:"Draft audio identity brief"},{match:/^Draft marketing ideas\b/i,prefix:"Draft marketing ideas"},{match:/^Draft (?:a|an) ([a-z]{3,30}(?:\s+[a-z]{3,30}){0,2})\b/i,prefix:"Draft",extract:(e,t)=>{let n=e.match(/^Draft (?:a|an) ([a-z]{3,30}(?:\s+[a-z]{3,30}){0,2})\b/i)?.[1]?.trim(),r=Nn(t);return n&&r?`${n} \xB7 ${r}`:n||r}},{match:/^Read the file at /i,prefix:"Read",extract:e=>{let s=e.match(/^Read the file at\s+([^\s]+)/i)?.[1];return s?s.split("/").filter(Boolean).slice(-2).join("/")||s:null}},{match:/^(?:read|inspect) this and then begin\b/i,prefix:"Begin from preamble",completeFromExtract:!0,extract:(e,t)=>Cp(t)},{match:/^Base directory for this skill:/i,prefix:"[skill]",completeFromExtract:!0,extract:(e,t)=>{let s=t.match(/\.claude\/skills\/([^/\s]+)/);return s?.[1]?`[skill] ${s[1]}`:null}},{match:/^You are extracting a structured Output Index/i,prefix:"[output-index]",completeFromExtract:!0,extract:(e,t)=>Np(t)},{match:/^You will receive a sample of user messages from a Claude Code session:/i,prefix:"[meta]",completeFromExtract:!0,extract:(e,t)=>Ho(t,"[meta] auto-title (full-arc)")},{match:/^You will receive the first \d+ user messages from a Claude Code session/i,prefix:"[meta]",completeFromExtract:!0,extract:(e,t)=>Ho(t,"[meta] auto-title (initial)")},{match:/^You are implementing v\d+\.\d+/i,prefix:"Implementing",completeFromExtract:!0,extract:e=>{let t=e.match(/^You are implementing (v\d+\.\d+\w*)\s*(?:\(([^)]+)\))?/i);if(!t)return null;let s=t[1],n=t[2]?.trim();return n?`Implementing ${s} \xB7 ${n}`:`Implementing ${s}`}}];function Np(e){if(!e)return"[output-index] extractor";let t=e.match(/^Session:\s*([0-9a-f]{8})\b/im),s=e.match(/^Opening prompt:\s*([^\n]{1,140})/im),n=t?.[1]?.trim(),r=s?.[1]?.trim().replace(/\s+/g," "),o=r&&r.length>70?r.slice(0,67)+"\u2026":r;return n&&o?`[output-index] \xB7 ${n} \xB7 ${o}`:n?`[output-index] \xB7 ${n}`:o?`[output-index] \xB7 ${o}`:"[output-index] extractor"}function Ho(e,t){if(!e)return t;let s=e.indexOf("Messages:");if(s===-1)return t;let n=e.slice(s+9),r=/^\s*\d+\.\s*([^\n]+)/gm;for(let o of n.matchAll(r)){let i=o[1]?.trim()??"";if(!i)continue;let a=i.replace(/^<[^>]+>[\s\S]*?<\/[^>]+>\s*/g,"").replace(/^\[Pasted text[^\]]*\]\s*/i,"").trim();if(!a||/^<local-command-/.test(a))continue;let l=a.length>60?a.slice(0,57)+"\u2026":a;return`${t} \xB7 ${l}`}return t}function Cp(e){if(!e)return null;let t=e.match(/([\/\w.\-]+\.(?:md|markdown|txt|json|yaml|yml|toml|ts|tsx|js|jsx|py|sql))(?=[\s,;:)\]"'`]|$)/i);if(!t)return null;let s=t[1].split("/").filter(Boolean);return(s[s.length-1]??"").replace(/\.[^.]+$/,"")||null}var Lp=[{match:/^Score this person'?s relevance/i,prefix:"Score relevance",extract:(e,t)=>as(t)},{match:/^You are a [^\n.]{1,60}co-pilot/i,prefix:"co-pilot",completeFromExtract:!0,extract:(e,t)=>{let n=e.match(/^You are a ([^\n.]{1,60}?)co-pilot/i)?.[1]?.trim(),r=n?`${n} co-pilot`:"co-pilot",o=as(t);return o?`${r} \xB7 ${o}`:r}},{match:/^Return ONLY valid JSON/i,prefix:"JSON-only",extract:(e,t)=>as(t)}];function as(e){let t=/^\s*(Name|Company|Prospect|Author|Brand|Client)\s*:\s*([^\n]+)/gim,s;for(;(s=t.exec(e))!==null;){let n=s[2].trim();if(!n||/^(null|none|n\/a|—|-)$/i.test(n))continue;let r=n.replace(/\s+/g," ");return xn(r)||r}return null}function Dt(e){return e.slice(0,wp).trim()}var Op=[/^deep research$/i,/^reference(?: spec)?$/i,/^canonical spec/i,/^product context/i,/^services?(?: overview)?$/i,/^overview$/i,/^(?:introduction|template|instructions|context)$/i],Ap=[/^(?:brand|brand brief|brand summary)$/i,/^(?:known facts?|facts)$/i,/^(?:client|prospect|customer|account)$/i,/^(?:topic|subject|brief|task)$/i,/^(?:about|for|re)$/i];function Rn(e){let t=e.trim();return t.length<3?!0:Op.some(s=>s.test(t))}function Ip(e){let t=e.trim().replace(/\s*\([^)]*\)\s*$/,"").trim();return Ap.some(s=>s.test(t))}function Nn(e){let t=vp(e);return t===null?null:xn(t)||t}function vp(e){if(/^\s*Skill smoke test\b/i.test(e))return"smoke test";let t=/(^|\n)#{1,3}\s+([^\n]+?)\s+(?:—|–|-|:)\s+([^\n]{2,80})/g,s,n=[];for(;(s=t.exec(e))!==null;){let l=s[2].trim(),c=s[3].trim().replace(/\s+/g," ");if(!Rn(c)){if(Ip(l))return c;n.push(c)}}if(n.length>0)return n[0];let r=e.match(/\b(?:Topic|Subject|Brand|About|Client|For|Re)\s*:\s*([^\n]{2,80})/i);if(r?.[1]&&!Rn(r[1]))return r[1].trim().replace(/\s+/g," ");let o=/===\s*([^=\n]{2,120}?)\s*===/g;for(;(s=o.exec(e))!==null;){let l=s[1].trim().replace(/\.(md|txt|json)$/i,""),c=l.replace(/\s*\([^)]*\)\s*$/,"").trim();if(c&&!Rn(c)&&!/product context|reference/i.test(l))return c}let i=e.replace(/^Context for this run[^:]*:\s*/i,"");if(i!==e){let l=i.split(`
806
806
  `).map(c=>c.trim()).find(c=>c.length>=4);if(l)return l.slice(0,60)}let a=e.split(`
807
807
  `).map(l=>l.trim()).find(l=>l.length>=4);return a?a.slice(0,60):null}function Jo(e,t,s){let n=t.trim();if(!n)return;let r=_(),o=r.prepare(`SELECT auto_title, auto_title_source, auto_title_generated_at, auto_title_history
808
808
  FROM sessions WHERE id = ?`).get(e);if(!o||s==="heuristic"&&o.auto_title_source==="agent"&&o.auto_title||o.auto_title===n&&o.auto_title_source===s)return;let i=xp(o.auto_title_history),a=new Date().toISOString();o.auto_title&&o.auto_title_source&&i.push({title:o.auto_title,source:o.auto_title_source,replaced_at:a}),r.prepare(`UPDATE sessions
@@ -810,9 +810,9 @@ ${o}
810
810
  auto_title_source = ?,
811
811
  auto_title_generated_at = ?,
812
812
  auto_title_history = ?
813
- WHERE id = ?`).run(n,s,Date.now(),JSON.stringify(i),e),Dp(e,n,s,a)}function Mp(){P(),Sp(kn)||bp(kn,{recursive:!0})}function Dp(e,t,s,n){try{Mp();let r=Wo(kn,`${e}.txt`),o=`# Claude Recall auto-title \xB7 session ${e} \xB7 source ${s} \xB7 updated ${n}
813
+ WHERE id = ?`).run(n,s,Date.now(),JSON.stringify(i),e),$p(e,n,s,a)}function Mp(){P(),Sp(kn)||bp(kn,{recursive:!0})}function $p(e,t,s,n){try{Mp();let r=Wo(kn,`${e}.txt`),o=`# Claude Recall auto-title \xB7 session ${e} \xB7 source ${s} \xB7 updated ${n}
814
814
  `;Ep(r,o+t+`
815
- `)}catch(r){console.error("[autoTitle] mirror write failed:",r)}}import{existsSync as $p,mkdirSync as cx,readFileSync as jp,writeFileSync as lx}from"node:fs";import{homedir as Pp}from"node:os";import{join as Go}from"node:path";import{z as Cn}from"zod";function Fp(){return process.env.RECALL_HOME??Go(Pp(),".recall")}function Up(){return Go(Fp(),"config.json")}var Bp=Cn.object({heuristicEnabled:Cn.boolean().default(!0),agentEnabled:Cn.boolean().default(!1)}),Ln={heuristicEnabled:!0,agentEnabled:!1};function Hp(){let e=Up();if(!$p(e))return{};try{return JSON.parse(jp(e,"utf8"))}catch(t){return console.error("[auto-title-config] failed to parse config.json, using defaults:",t),{}}}function zo(){let e=Hp().autoTitle;if(!e)return{...Ln};let t=Bp.safeParse({...Ln,...e});return t.success?t.data:{...Ln}}var Xp=[/^<local-command-caveat>/,/^<command-name>/,/^<command-message>/,/^<system-reminder>/,/^<user-prompt-submit-hook>/,/^Caveat: The messages below were generated/i];function Jp(e){let t=e.trim();return t?Xp.some(s=>s.test(t)):!0}function Gp(e){let t=e;return t=t.replace(/^(?:<[^>]+>[\s\S]*?<\/[^>]+>\s*)+/,"").trim(),t=t.replace(/^<command-[^>]+>[^<]*<\/command-[^>]+>\s*/gm,"").trim(),!t||Jp(t)?null:t}function zp(e,t,s){let n=Sn(t),r=s??n,o=s?Wp(s)||s:Co(t),i=e.prepare("SELECT id, decoded_path FROM projects WHERE encoded_path = ?").get(t);if(i)return s&&i.decoded_path!==s&&e.prepare("UPDATE projects SET decoded_path = ?, name = ? WHERE id = ?").run(s,o,i.id),i.id;let a=e.prepare("INSERT INTO projects (encoded_path, decoded_path, name) VALUES (?, ?, ?)").run(t,r,o);return Number(a.lastInsertRowid)}async function Yp(e,t,s){let n=e.prepare("SELECT id, file_mtime FROM sessions WHERE file_path = ? LIMIT 1").get(t.sessionFile);if(!s&&n&&n.file_mtime>=t.mtime)return{inserted:!1,sessionCount:0,messageCount:0};let r=new Map,o=null;for await(let g of Do(t.sessionFile)){let h=r.get(g.sessionId);if(h||(h={sessionId:g.sessionId,entries:[],earliestTimestamp:null,latestTimestamp:null,firstUserMessage:null,userCount:0,assistantCount:0,cwd:null,gitBranch:null,version:null},r.set(g.sessionId,h)),h.entries.push(g),g.timestamp&&((!h.earliestTimestamp||g.timestamp<h.earliestTimestamp)&&(h.earliestTimestamp=g.timestamp),(!h.latestTimestamp||g.timestamp>h.latestTimestamp)&&(h.latestTimestamp=g.timestamp)),g.role==="user"&&!g.isSidechain){if(h.userCount+=1,!h.firstUserMessage&&g.contentText){let E=Gp(g.contentText);E&&(h.firstUserMessage=Y(qe(E).redacted,200))}}else g.role==="assistant"&&!g.isSidechain&&(h.assistantCount+=1);!h.cwd&&g.cwd&&(h.cwd=g.cwd),!h.gitBranch&&g.gitBranch&&(h.gitBranch=g.gitBranch),!h.version&&g.version&&(h.version=g.version),!o&&g.cwd&&(o=g.cwd)}let i=zp(e,t.encodedProject,o),a=new Date().toISOString(),l=e.prepare(`
815
+ `)}catch(r){console.error("[autoTitle] mirror write failed:",r)}}import{existsSync as Dp,mkdirSync as dx,readFileSync as jp,writeFileSync as ux}from"node:fs";import{homedir as Pp}from"node:os";import{join as Go}from"node:path";import{z as Cn}from"zod";function Fp(){return process.env.RECALL_HOME??Go(Pp(),".recall")}function Up(){return Go(Fp(),"config.json")}var Bp=Cn.object({heuristicEnabled:Cn.boolean().default(!0),agentEnabled:Cn.boolean().default(!1)}),Ln={heuristicEnabled:!0,agentEnabled:!1};function Hp(){let e=Up();if(!Dp(e))return{};try{return JSON.parse(jp(e,"utf8"))}catch(t){return console.error("[auto-title-config] failed to parse config.json, using defaults:",t),{}}}function zo(){let e=Hp().autoTitle;if(!e)return{...Ln};let t=Bp.safeParse({...Ln,...e});return t.success?t.data:{...Ln}}var Xp=[/^<local-command-caveat>/,/^<command-name>/,/^<command-message>/,/^<system-reminder>/,/^<user-prompt-submit-hook>/,/^Caveat: The messages below were generated/i];function Jp(e){let t=e.trim();return t?Xp.some(s=>s.test(t)):!0}function Gp(e){let t=e;return t=t.replace(/^(?:<[^>]+>[\s\S]*?<\/[^>]+>\s*)+/,"").trim(),t=t.replace(/^<command-[^>]+>[^<]*<\/command-[^>]+>\s*/gm,"").trim(),!t||Jp(t)?null:t}function zp(e,t,s){let n=Sn(t),r=s??n,o=s?Wp(s)||s:Co(t),i=e.prepare("SELECT id, decoded_path FROM projects WHERE encoded_path = ?").get(t);if(i)return s&&i.decoded_path!==s&&e.prepare("UPDATE projects SET decoded_path = ?, name = ? WHERE id = ?").run(s,o,i.id),i.id;let a=e.prepare("INSERT INTO projects (encoded_path, decoded_path, name) VALUES (?, ?, ?)").run(t,r,o);return Number(a.lastInsertRowid)}async function Yp(e,t,s){let n=e.prepare("SELECT id, file_mtime FROM sessions WHERE file_path = ? LIMIT 1").get(t.sessionFile);if(!s&&n&&n.file_mtime>=t.mtime)return{inserted:!1,sessionCount:0,messageCount:0};let r=new Map,o=null;for await(let g of $o(t.sessionFile)){let h=r.get(g.sessionId);if(h||(h={sessionId:g.sessionId,entries:[],earliestTimestamp:null,latestTimestamp:null,firstUserMessage:null,userCount:0,assistantCount:0,cwd:null,gitBranch:null,version:null},r.set(g.sessionId,h)),h.entries.push(g),g.timestamp&&((!h.earliestTimestamp||g.timestamp<h.earliestTimestamp)&&(h.earliestTimestamp=g.timestamp),(!h.latestTimestamp||g.timestamp>h.latestTimestamp)&&(h.latestTimestamp=g.timestamp)),g.role==="user"&&!g.isSidechain){if(h.userCount+=1,!h.firstUserMessage&&g.contentText){let E=Gp(g.contentText);E&&(h.firstUserMessage=Y(qe(E).redacted,200))}}else g.role==="assistant"&&!g.isSidechain&&(h.assistantCount+=1);!h.cwd&&g.cwd&&(h.cwd=g.cwd),!h.gitBranch&&g.gitBranch&&(h.gitBranch=g.gitBranch),!h.version&&g.version&&(h.version=g.version),!o&&g.cwd&&(o=g.cwd)}let i=zp(e,t.encodedProject,o),a=new Date().toISOString(),l=e.prepare(`
816
816
  INSERT INTO sessions (
817
817
  id, project_id, file_path, file_mtime,
818
818
  started_at, ended_at, message_count,
@@ -883,7 +883,7 @@ ${o}
883
883
  WHERE messages_fts MATCH @q
884
884
  ${i}
885
885
  ORDER BY bm25(messages_fts)
886
- LIMIT @limit`).all(o);if(a.length===0){console.log(d.dim(`no matches for "${e}"`));return}console.log(d.dim(`${a.length} match${a.length===1?"":"es"} for "${e}"`)),console.log("");for(let l of a){let c=l.snippet.replace(/<<([\s\S]*?)>>/g,(p,m)=>$o(m,m).replace(/\n/g," ")).replace(/\n/g," "),u=l.role==="user"?d.user("user"):l.role==="assistant"?d.assistant("asst"):d.dim("----");console.log(`${d.accent(H(l.session_id))} ${d.project(Y(l.project_name,20))} ${d.dim(W(l.started_at))} ${u}`),console.log(` ${Y(c,200)}`),console.log("")}console.log(d.dim("`recall show <id>` to read any session."))}T();j();We();I();import{statSync as Gm,existsSync as zm}from"node:fs";function hi(){if(console.log(""),console.log(d.bold("Claude Recall status")),console.log(d.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),!zm(te)){console.log(d.dim(" no database yet. run `recall index`."));return}let t=_().prepare(`SELECT
886
+ LIMIT @limit`).all(o);if(a.length===0){console.log(d.dim(`no matches for "${e}"`));return}console.log(d.dim(`${a.length} match${a.length===1?"":"es"} for "${e}"`)),console.log("");for(let l of a){let c=l.snippet.replace(/<<([\s\S]*?)>>/g,(p,m)=>Do(m,m).replace(/\n/g," ")).replace(/\n/g," "),u=l.role==="user"?d.user("user"):l.role==="assistant"?d.assistant("asst"):d.dim("----");console.log(`${d.accent(H(l.session_id))} ${d.project(Y(l.project_name,20))} ${d.dim(W(l.started_at))} ${u}`),console.log(` ${Y(c,200)}`),console.log("")}console.log(d.dim("`recall show <id>` to read any session."))}T();j();We();I();import{statSync as Gm,existsSync as zm}from"node:fs";function hi(){if(console.log(""),console.log(d.bold("Claude Recall status")),console.log(d.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),!zm(te)){console.log(d.dim(" no database yet. run `recall index`."));return}let t=_().prepare(`SELECT
887
887
  (SELECT COUNT(*) FROM projects) AS projects,
888
888
  (SELECT COUNT(*) FROM sessions) AS sessions,
889
889
  (SELECT COUNT(*) FROM messages) AS messages,
@@ -900,7 +900,7 @@ ${o}
900
900
  ORDER BY MAX(COALESCE(s.started_at, '')) DESC`).all();if(t.length===0){console.log(d.dim("no projects indexed yet."));return}let s=new Ym({head:[d.bold("project"),d.bold("sessions"),d.bold("msgs"),d.bold("latest"),d.bold("path")],style:{head:[],border:["grey"]}});for(let n of t)s.push([d.project(Y(n.name,30)),String(n.session_count),String(n.message_count),d.dim(W(n.latest)),d.dim(Y(n.decoded_path,50))]);console.log(s.toString())}We();We();j();I();import{spawn as Vm}from"node:child_process";import{openSync as Zm}from"node:fs";import{join as Qm}from"node:path";import{existsSync as qm}from"node:fs";import{dirname as bi}from"node:path";import{fileURLToPath as Km}from"node:url";var hs=null;function Te(){if(hs)return hs;let e=bi(Km(import.meta.url));for(;!qm(`${e}/package.json`);){let t=bi(e);if(t===e)throw new Error(`package.json not found walking up from ${import.meta.url}`);e=t}return hs=e,hs}function eg(){return Qm(Te(),"dist","daemon","entrypoint.js")}async function Es(){let e=K();if(e){console.log(`${d.ok("already running")} pid ${e.pid} \xB7 http://127.0.0.1:${e.port}`);return}P();let t=Zm(_s,"a"),s=eg();Vm(process.execPath,[s],{detached:!0,stdio:["ignore",t,t],env:{...process.env}}).unref();let r=Date.now();for(;Date.now()-r<5e3;){await new Promise(i=>setTimeout(i,150));let o=K();if(o){console.log(`${d.ok("daemon started")} pid ${o.pid} \xB7 http://127.0.0.1:${o.port}`),console.log(d.dim(`logs: ${_s}`));return}}console.error(d.err("daemon did not come up within 5s \u2014 check the log file")),console.error(d.dim(` ${_s}`)),process.exitCode=1}We();I();async function Si(){let e=K();if(!e){console.log(d.dim("no daemon running.")),Jn();return}try{process.kill(e.pid,"SIGTERM")}catch(s){console.error(d.err(`failed to signal pid ${e.pid}: ${s.message}`)),process.exitCode=1;return}let t=Date.now();for(;Date.now()-t<5e3;)if(await new Promise(s=>setTimeout(s,100)),!K()){console.log(d.ok(`stopped daemon pid ${e.pid}`));return}console.error(d.err(`pid ${e.pid} did not exit within 5s \u2014 you may need to kill it manually`)),process.exitCode=1}We();import{spawn as tg}from"node:child_process";import{platform as bs}from"node:os";I();function sg(e){let t=bs()==="darwin"?"open":bs()==="win32"?"start":"xdg-open",s=bs()==="win32"?["",e]:[e];tg(t,s,{detached:!0,stdio:"ignore",shell:bs()==="win32"}).unref()}async function yi(){let e=K();if(!e&&(console.log(d.dim("daemon not running \u2014 starting it\u2026")),await Es(),e=K(),!e)){console.error(d.err("could not start the daemon. run `recall start` manually and check logs.")),process.exitCode=1;return}let t=`http://127.0.0.1:${e.port}`;console.log(`${d.ok("opening")} ${t}`),sg(t)}T();var ng=/<(local-command-caveat|local-command-stdout|command-name|command-message|command-args|system-reminder|user-prompt-submit-hook|task-notification)[\s\S]*?<\/\1>/gi,rg=/⚡ \*\*Tool call · `[^`]+`\*\*\s*\n+```json\n[\s\S]*?\n```/g,og=/\*\*Tool result\*\*\s*\n+```\n[\s\S]*?\n```/g;function ig(e){return e.replace(ng,"").trim()}function ag(e){let t=e.replace(rg,"[tool call]");return t=t.replace(og,"[tool result]"),t=t.replace(/_\(unknown block: thinking\)_/g,""),t=t.replace(/(?:\[tool call\]|\[tool result\])(?:\s*(?:\[tool call\]|\[tool result\]))+/g,"[tool activity]"),t=t.replace(/\n{3,}/g,`
901
901
 
902
902
  `),t.trim()}function cg(e){return e.role??e.type??"message"}function Ti(e,t,s={}){let n=s.mode??"condensed",r=s.includeSidechain===!0,o=s.since?Date.parse(s.since):0,i=t.filter(u=>!(!r&&u.is_sidechain===1||o&&u.timestamp&&Date.parse(u.timestamp)<o)),a=[];s.prelude&&(a.push(s.prelude.trim()),a.push("")),a.push(`# Claude Recall, past session context (${n})`),a.push(""),a.push(`- **Project**: ${e.project_name}`),e.decoded_path&&a.push(`- **Path**: \`${e.decoded_path}\``),a.push(`- **Session ID**: \`${e.id}\``),e.started_at&&a.push(`- **Started**: ${e.started_at}`),e.ended_at&&a.push(`- **Ended**: ${e.ended_at}`),e.git_branch&&a.push(`- **Branch**: \`${e.git_branch}\``),a.push(`- **Messages**: ${i.length}`),a.push(""),a.push("> This is a transcript of a previous Claude Code session, included for context. Refer back to it when the user asks about past decisions, code written, or problems debugged in this work."),a.push(""),a.push("---"),a.push("");let l=0,c=0;for(let u of i){let p=u.content_text??"",m=ig(p);n==="condensed"&&(m=ag(m));let f=m.length>0,g=!!u.tool_names&&u.tool_names.length>0;if(!f&&!g){c+=1;continue}let h=cg(u),E=u.timestamp?` \`${u.timestamp}\``:"";a.push(`## ${h}${E}`),a.push(""),g&&n==="condensed"&&(a.push(`_tools used: ${u.tool_names}_`),a.push("")),f&&(a.push(m),a.push("")),l+=1}return a.push("---"),a.push(""),a.push(`_${l} messages included_`+(c?`, ${c} empty skipped`:"")+(r?"":", subagent/sidechain hidden")+"."),a.join(`
903
- `)}T();j();import{randomUUID as wi}from"node:crypto";import{writeFileSync as xi,readFileSync as c0,existsSync as lg,mkdirSync as dg}from"node:fs";import{join as Gn}from"node:path";var Ss=Gn(x,"threads"),ug=Gn(Ss,"index.json");function Ri(){P(),lg(Ss)||dg(Ss,{recursive:!0})}function ki(e,t,s){return{id:e.id,name:e.name,summary:e.summary,created_at:e.created_at,closed_at:e.closed_at,archived:e.archived===1,session_count:t.session_count,origin_count:t.origin_count,project:s?.project??null,project_count:s?.project_count??0,folder_id:e.folder_id??null}}function Ni(e){let t=new Map;if(e.length===0)return t;let s=_(),n=e.map(()=>"?").join(","),r=s.prepare(`SELECT te.thread_id AS thread_id,
903
+ `)}T();j();import{randomUUID as wi}from"node:crypto";import{writeFileSync as xi,readFileSync as d0,existsSync as lg,mkdirSync as dg}from"node:fs";import{join as Gn}from"node:path";var Ss=Gn(x,"threads"),ug=Gn(Ss,"index.json");function Ri(){P(),lg(Ss)||dg(Ss,{recursive:!0})}function ki(e,t,s){return{id:e.id,name:e.name,summary:e.summary,created_at:e.created_at,closed_at:e.closed_at,archived:e.archived===1,session_count:t.session_count,origin_count:t.origin_count,project:s?.project??null,project_count:s?.project_count??0,folder_id:e.folder_id??null}}function Ni(e){let t=new Map;if(e.length===0)return t;let s=_(),n=e.map(()=>"?").join(","),r=s.prepare(`SELECT te.thread_id AS thread_id,
904
904
  p.name AS project,
905
905
  COUNT(*) AS n,
906
906
  SUM(CASE WHEN te.role = 'origin' THEN 1 ELSE 0 END) AS origin_n
@@ -939,9 +939,9 @@ ${o}
939
939
  role = excluded.role,
940
940
  confidence = excluded.confidence,
941
941
  source = excluded.source,
942
- added_at = excluded.added_at`).run(e.threadId,e.sessionId,r,o,i,a,n),Le(e.threadId);let l=Li(e.sessionId);return{thread_id:e.threadId,session_id:e.sessionId,parent_session_id:r,role:o,confidence:i,source:a,added_at:n,alias:l.alias,auto_title:l.auto_title,auto_title_source:l.auto_title_source,alias_source:l.alias?"manual":null,first_user_message:l.first_user_message,project:l.project}}function Mi(e,t){let n=_().prepare("DELETE FROM thread_edges WHERE thread_id = ? AND session_id = ?").run(e,t);return n.changes>0&&Le(e),{removed:n.changes}}function Di(e,t,s){let n=_(),r=n.prepare("SELECT * FROM thread_edges WHERE thread_id = ? AND session_id = ?").get(e,t);if(!r)throw new Error("edge not found; add the session first");if(s!==null){if(s===t)throw new Error("cycle detected: session cannot be its own parent");let a=n.prepare("SELECT parent_session_id FROM thread_edges WHERE thread_id = ? AND session_id = ?"),l=s,c=new Set;for(;l!==null;){if(l===t)throw new Error(`cycle detected: setting parent of ${t} to ${s} would create a loop`);if(c.has(l))break;c.add(l),l=a.get(e,l)?.parent_session_id??null}}let o=s?"child":"origin";n.prepare(`UPDATE thread_edges
942
+ added_at = excluded.added_at`).run(e.threadId,e.sessionId,r,o,i,a,n),Le(e.threadId);let l=Li(e.sessionId);return{thread_id:e.threadId,session_id:e.sessionId,parent_session_id:r,role:o,confidence:i,source:a,added_at:n,alias:l.alias,auto_title:l.auto_title,auto_title_source:l.auto_title_source,alias_source:l.alias?"manual":null,first_user_message:l.first_user_message,project:l.project}}function Mi(e,t){let n=_().prepare("DELETE FROM thread_edges WHERE thread_id = ? AND session_id = ?").run(e,t);return n.changes>0&&Le(e),{removed:n.changes}}function $i(e,t,s){let n=_(),r=n.prepare("SELECT * FROM thread_edges WHERE thread_id = ? AND session_id = ?").get(e,t);if(!r)throw new Error("edge not found; add the session first");if(s!==null){if(s===t)throw new Error("cycle detected: session cannot be its own parent");let a=n.prepare("SELECT parent_session_id FROM thread_edges WHERE thread_id = ? AND session_id = ?"),l=s,c=new Set;for(;l!==null;){if(l===t)throw new Error(`cycle detected: setting parent of ${t} to ${s} would create a loop`);if(c.has(l))break;c.add(l),l=a.get(e,l)?.parent_session_id??null}}let o=s?"child":"origin";n.prepare(`UPDATE thread_edges
943
943
  SET parent_session_id = ?, role = ?, added_at = ?
944
- WHERE thread_id = ? AND session_id = ?`).run(s,o,new Date().toISOString(),e,t),Le(e);let i=Li(t);return Ci({...r,parent_session_id:s,role:o,added_at:new Date().toISOString(),alias:i.alias,auto_title:i.auto_title,auto_title_source:i.auto_title_source,first_user_message:i.first_user_message,project:i.project})}function $i(e,t){let s=t.trim();if(!s)throw new Error("name cannot be empty");_().prepare("UPDATE threads SET name = ? WHERE id = ?").run(s,e),Le(e);let r=Oe(e);if(!r)throw new Error(`thread ${e} not found`);return r}function ji(e){_().prepare("UPDATE threads SET closed_at = ? WHERE id = ?").run(new Date().toISOString(),e),Le(e);let s=Oe(e);if(!s)throw new Error(`thread ${e} not found`);return s}function Pi(e){_().prepare("UPDATE threads SET closed_at = NULL WHERE id = ?").run(e),Le(e);let s=Oe(e);if(!s)throw new Error(`thread ${e} not found`);return s}function Fi(e){_().prepare("UPDATE threads SET archived = 1 WHERE id = ?").run(e),Le(e);let s=Oe(e);if(!s)throw new Error(`thread ${e} not found`);return s}function Ui(e,t){if(e===t)throw new Error("cannot merge a thread into itself");let s=_(),n=new Date().toISOString();s.transaction(()=>{let o=s.prepare("SELECT * FROM thread_edges WHERE thread_id = ?").all(e);for(let i of o)s.prepare(`INSERT INTO thread_edges
944
+ WHERE thread_id = ? AND session_id = ?`).run(s,o,new Date().toISOString(),e,t),Le(e);let i=Li(t);return Ci({...r,parent_session_id:s,role:o,added_at:new Date().toISOString(),alias:i.alias,auto_title:i.auto_title,auto_title_source:i.auto_title_source,first_user_message:i.first_user_message,project:i.project})}function Di(e,t){let s=t.trim();if(!s)throw new Error("name cannot be empty");_().prepare("UPDATE threads SET name = ? WHERE id = ?").run(s,e),Le(e);let r=Oe(e);if(!r)throw new Error(`thread ${e} not found`);return r}function ji(e){_().prepare("UPDATE threads SET closed_at = ? WHERE id = ?").run(new Date().toISOString(),e),Le(e);let s=Oe(e);if(!s)throw new Error(`thread ${e} not found`);return s}function Pi(e){_().prepare("UPDATE threads SET closed_at = NULL WHERE id = ?").run(e),Le(e);let s=Oe(e);if(!s)throw new Error(`thread ${e} not found`);return s}function Fi(e){_().prepare("UPDATE threads SET archived = 1 WHERE id = ?").run(e),Le(e);let s=Oe(e);if(!s)throw new Error(`thread ${e} not found`);return s}function Ui(e,t){if(e===t)throw new Error("cannot merge a thread into itself");let s=_(),n=new Date().toISOString();s.transaction(()=>{let o=s.prepare("SELECT * FROM thread_edges WHERE thread_id = ?").all(e);for(let i of o)s.prepare(`INSERT INTO thread_edges
945
945
  (thread_id, session_id, parent_session_id, role, confidence, source, added_at)
946
946
  VALUES (?, ?, ?, ?, ?, ?, ?)
947
947
  ON CONFLICT(thread_id, session_id) DO UPDATE SET
@@ -977,7 +977,7 @@ ${o}
977
977
  `)||process.stdout.write(`
978
978
  `);let o=t.since?"since":t.full?"full":"condensed";Yn(n,Math.ceil(r.length/4),o,"cli"),process.stderr.isTTY&&process.stderr.write(`\x1B[2mShare this recall? \u2192 recall share\x1B[0m
979
979
  `)}_e();import{join as bg}from"node:path";import{spawn as Sg}from"node:child_process";async function Ji(e={}){await Ce("MCP server");let t=bg(Te(),"dist","mcp-server.js"),s={...process.env};e.allowWrites&&(s.RECALL_MCP_ALLOW_WRITES="1");let n=Sg(process.execPath,[t],{stdio:"inherit",env:s});return new Promise((r,o)=>{n.on("error",o),n.on("exit",(i,a)=>{if(a){process.kill(process.pid,a);return}process.exitCode=i??0,r()})})}T();import{execSync as qn}from"node:child_process";import{randomUUID as yg}from"node:crypto";import Tg from"node:readline/promises";I();async function Gi(e){if(e.list){wg();return}if(e.purge){xg(e.purge);return}let t=await Rg();t||(process.stderr.write(d.err(`clipboard empty / nothing on stdin
980
- `)),process.exit(1));let s=Dt(t);if(s.length>0&&!e.force){process.stderr.write(d.warn(`\u26A0 detected ${s.length} possible secret${s.length===1?"":"s"} in content:
980
+ `)),process.exit(1));let s=$t(t);if(s.length>0&&!e.force){process.stderr.write(d.warn(`\u26A0 detected ${s.length} possible secret${s.length===1?"":"s"} in content:
981
981
  `));for(let a of s.slice(0,8))process.stderr.write(` ${d.err(a.pattern)} ${d.dim("\u2192")} ${a.maskedPreview}
982
982
  `);s.length>8&&process.stderr.write(d.dim(` \u2026 ${s.length-8} more
983
983
  `)),e.dryRun&&(process.stderr.write(d.dim(`
@@ -1007,10 +1007,10 @@ show full content: recall paste --show <id>
1007
1007
  `)),process.exit(1)),t.prepare("DELETE FROM paste_archives WHERE id = ?").run(s[0].id),process.stderr.write(d.ok(`\u2713 purged ${s[0].id.slice(0,8)} \u2014 content permanently destroyed
1008
1008
  `))}async function Rg(){if(!process.stdin.isTTY)return await kg();try{return qn("pbpaste",{encoding:"utf8",maxBuffer:16*1024*1024})}catch{}try{return qn("xclip -o -selection clipboard",{encoding:"utf8",maxBuffer:16*1024*1024})}catch{}try{return qn("powershell.exe -command Get-Clipboard",{encoding:"utf8",maxBuffer:16*1024*1024})}catch{}throw new Error("Could not read clipboard. On macOS pbpaste should be built in; on Linux install xclip; on Windows pipe into this command instead.")}async function kg(){let e=[];for await(let t of process.stdin)e.push(Buffer.isBuffer(t)?t:Buffer.from(t));return Buffer.concat(e).toString("utf8")}T();I();async function zi(e){let t=_(),s=new Map,n=0,r=0,o=0,i=new Set,a=t.prepare(`SELECT uuid, session_id, content_text, raw_json
1009
1009
  FROM messages
1010
- WHERE content_text IS NOT NULL`).all(),l=t.prepare("UPDATE messages SET content_text = ?, raw_json = ? WHERE uuid = ?"),c=(g,h)=>{let E=Dt(g);if(E.length===0)return!1;for(let b of E){let S=s.get(b.pattern)??{pattern:b.pattern,severity:b.severity,hits:0,sessions:new Set};S.hits+=1,S.sessions.add(h),s.set(b.pattern,S)}return!0};process.stdout.write(d.dim(`Scanning ${a.length.toLocaleString()} messages\u2026
1010
+ WHERE content_text IS NOT NULL`).all(),l=t.prepare("UPDATE messages SET content_text = ?, raw_json = ? WHERE uuid = ?"),c=(g,h)=>{let E=$t(g);if(E.length===0)return!1;for(let b of E){let S=s.get(b.pattern)??{pattern:b.pattern,severity:b.severity,hits:0,sessions:new Set};S.hits+=1,S.sessions.add(h),s.set(b.pattern,S)}return!0};process.stdout.write(d.dim(`Scanning ${a.length.toLocaleString()} messages\u2026
1011
1011
  `));for(let g of a)if(n+=1,(c(g.content_text??"",g.session_id)||c(g.raw_json??"",g.session_id))&&(r+=1,i.add(g.session_id),e.verbose&&process.stderr.write(d.dim(` hit in session ${g.session_id.slice(0,8)} message ${g.uuid.slice(0,8)}
1012
1012
  `)),e.redact)){let E=qe(g.content_text??"").redacted,b=g.raw_json?qe(g.raw_json).redacted:null;l.run(E,b,g.uuid),o+=1}let u=t.prepare(`SELECT id, first_user_message FROM sessions
1013
- WHERE first_user_message IS NOT NULL`).all(),p=t.prepare("UPDATE sessions SET first_user_message = ? WHERE id = ?"),m=0;for(let g of u)Dt(g.first_user_message).length>0&&(i.add(g.id),e.redact&&(p.run(qe(g.first_user_message).redacted,g.id),m+=1));if(process.stdout.write(`
1013
+ WHERE first_user_message IS NOT NULL`).all(),p=t.prepare("UPDATE sessions SET first_user_message = ? WHERE id = ?"),m=0;for(let g of u)$t(g.first_user_message).length>0&&(i.add(g.id),e.redact&&(p.run(qe(g.first_user_message).redacted,g.id),m+=1));if(process.stdout.write(`
1014
1014
  `),s.size===0){process.stdout.write(d.ok(`\u2713 clean \u2014 no secrets detected across ${n.toLocaleString()} messages.
1015
1015
  `));return}let f=[...s.values()].sort((g,h)=>h.hits-g.hits);process.stdout.write(d.warn(`\u26A0 ${r.toLocaleString()} message${r===1?"":"s"} across ${i.size.toLocaleString()} session${i.size===1?"":"s"} contain detected secrets.
1016
1016
 
@@ -1030,11 +1030,11 @@ show full content: recall paste --show <id>
1030
1030
  ORDER BY s.started_at`).all(s.id);if(n.length===0){console.error(d.warn(`Project "${s.name}" has 0 sessions.`));return}let r={clean:0,"fixed_v0.16.1":0,agent:0,manual_alias:0,template_pending:0,programmatic:0,recursive_meta:0,low_signal:0},o=[];for(let u of n){let p={auto_title:u.auto_title,auto_title_source:u.auto_title_source??null,has_alias:u.has_alias===1},m=Bo(p);r[m]+=1,o.push({id:u.id,quality:m})}if(!e.dryRun){let u=t.prepare(`UPDATE sessions
1031
1031
  SET title_quality = ?,
1032
1032
  title_quality_computed_at = ?
1033
- WHERE id = ?`),p=Date.now();t.transaction(f=>{for(let g of f)u.run(g.quality,p,g.id)})(o)}if(e.json){console.log(JSON.stringify({project:s.name,project_id:s.id,total_sessions:n.length,dry_run:!!e.dryRun,counts:r},null,2));return}let i=n.length;console.log(""),console.log(d.project(`Title quality audit \u2014 project ${d.bold(s.name)}`)),s.decoded_path&&console.log(d.dim(` ${s.decoded_path}`)),console.log(d.dim(` ${i} sessions${e.dryRun?" (DRY RUN \u2014 no DB writes)":""}`)),console.log("");let a=["clean","fixed_v0.16.1","agent","manual_alias","template_pending","programmatic","recursive_meta","low_signal"],l=Math.max(...a.map(u=>u.length));for(let u of a){let p=r[u];if(p===0)continue;let m=(p/i*100).toFixed(1).padStart(5),f=Lg(p,i);console.log(` ${u.padEnd(l)} ${d.bold(String(p).padStart(5))} ${m}% ${f}`)}console.log("");let c=r.template_pending+r.programmatic+r.recursive_meta+r.low_signal;if(c>0){let u=(c/i*100).toFixed(1);console.log(d.dim(` ${c} sessions (${u}%) eligible for cleanup phases L1/L3/L4.`))}else console.log(d.ok(" No cleanup-eligible sessions remain in this project. \u2713"));console.log("")}async function Cg(e,t){if(t){let o=e.prepare("SELECT id, name, decoded_path FROM projects WHERE name = ?").get(t);if(o)return o;let i=e.prepare("SELECT id, name, decoded_path FROM projects WHERE name LIKE ? ORDER BY name LIMIT 1").get(`%${t}%`);return i||null}let s=process.cwd(),n=e.prepare("SELECT id, name, decoded_path FROM projects WHERE decoded_path = ?").get(s);if(n)return n;let r=e.prepare("SELECT id, name, decoded_path FROM projects WHERE name = ? LIMIT 1").get(Ng(s));return r||null}var Yi=28;function Lg(e,t){let s=Math.round(e/t*Yi);return d.dim("\u2588".repeat(s)+"\xB7".repeat(Yi-s))}Ft();I();T();En();T();Ft();import{readFileSync as Mg,existsSync as Vn,statSync as Dg,readdirSync as $g}from"node:fs";import{join as Ts}from"node:path";import{homedir as jg}from"node:os";var Ut=["vscode","cursor","windsurf"],Pg={vscode:"Code",cursor:"Cursor",windsurf:"Windsurf"};var Fg=.7,Ug=300*1e3;function Bg(e){let t=e?.homeDir??jg(),s=e?.sources??Ut,n=[];for(let r of s){let o=Ts(t,"Library","Application Support",Pg[r],"User","workspaceStorage");Vn(o)&&n.push({source:r,root:o})}return n}function Hg(e,t){let s=Ts(e,"workspace.json"),n=Ts(e,"state.vscdb");if(!Vn(s)||!Vn(n))return[];let r;try{let l=JSON.parse(Mg(s,"utf8"));if(!l.folder||!l.folder.startsWith("file://"))return[];r=decodeURIComponent(l.folder.replace(/^file:\/\//,""))}catch{return[]}let o;try{o=Dg(n).mtime.toISOString()}catch{return[]}let i;try{i=new rs(n,{readonly:!0})}catch{return[]}let a=[];try{let l=i.prepare("SELECT value FROM ItemTable WHERE key = 'terminal.integrated.bufferState' LIMIT 1").get(),c={};if(l?.value)try{c=JSON.parse(l.value)}catch{}let u=c.state??[];if(u.length===0)a.push({workspace_path:r,workspace_storage_dir:e,tab_name:null,cwd_hint:null,last_seen_at:o,source:t});else for(let p of u){let m=p.shellLaunchConfig??{},f=typeof m.name=="string"?m.name.trim():"";a.push({workspace_path:r,workspace_storage_dir:e,tab_name:f||null,cwd_hint:typeof m.cwd=="string"?m.cwd:null,last_seen_at:o,source:t})}}finally{i.close()}return a}function Wg(e,t){let s=[],n=0;if(e.cwd&&t.workspace_path){let r=e.cwd,o=t.workspace_path;(r===o||r.startsWith(o+"/")||o.startsWith(r+"/"))&&(n+=.5,s.push("cwd_prefix"))}if(e.started_at&&t.last_seen_at){let r=Date.parse(e.started_at),o=Date.parse(t.last_seen_at);Number.isFinite(r)&&Number.isFinite(o)&&Math.abs(r-o)<=Ug&&(n+=.4,s.push("time_window"))}return e.cwd&&t.cwd_hint&&e.cwd===t.cwd_hint&&(n+=.1,s.push("cwd_exact")),t.tab_name&&(n+=.2,s.push("has_name")),n>1&&(n=1),{score:n,matchedOn:s}}var Xg=new Set(["zsh","bash","fish","sh","dash","ksh","tcsh","csh","pwsh","powershell","cmd","nu","node","deno","bun","python","python3","ruby","ts-node","tsx","go","cargo","java","php","irb","pry","iex","task","tasks","terminal","copilot","cascade","composer","claude","claude code"]);function Jg(e){return Xg.has(e.trim().toLowerCase())}function Gg(e){let t=e.tab_name?.trim();return!t||Jg(t)?null:t}function Qi(e){let t=e?.minScore??Fg,s=e?.limit,n=_(),r=e?.projectId?" AND s.project_id = ?":"",o=e?.projectId?[e.projectId]:[],i=n.prepare(`SELECT s.id, p.decoded_path AS cwd, s.started_at
1033
+ WHERE id = ?`),p=Date.now();t.transaction(f=>{for(let g of f)u.run(g.quality,p,g.id)})(o)}if(e.json){console.log(JSON.stringify({project:s.name,project_id:s.id,total_sessions:n.length,dry_run:!!e.dryRun,counts:r},null,2));return}let i=n.length;console.log(""),console.log(d.project(`Title quality audit \u2014 project ${d.bold(s.name)}`)),s.decoded_path&&console.log(d.dim(` ${s.decoded_path}`)),console.log(d.dim(` ${i} sessions${e.dryRun?" (DRY RUN \u2014 no DB writes)":""}`)),console.log("");let a=["clean","fixed_v0.16.1","agent","manual_alias","template_pending","programmatic","recursive_meta","low_signal"],l=Math.max(...a.map(u=>u.length));for(let u of a){let p=r[u];if(p===0)continue;let m=(p/i*100).toFixed(1).padStart(5),f=Lg(p,i);console.log(` ${u.padEnd(l)} ${d.bold(String(p).padStart(5))} ${m}% ${f}`)}console.log("");let c=r.template_pending+r.programmatic+r.recursive_meta+r.low_signal;if(c>0){let u=(c/i*100).toFixed(1);console.log(d.dim(` ${c} sessions (${u}%) eligible for cleanup phases L1/L3/L4.`))}else console.log(d.ok(" No cleanup-eligible sessions remain in this project. \u2713"));console.log("")}async function Cg(e,t){if(t){let o=e.prepare("SELECT id, name, decoded_path FROM projects WHERE name = ?").get(t);if(o)return o;let i=e.prepare("SELECT id, name, decoded_path FROM projects WHERE name LIKE ? ORDER BY name LIMIT 1").get(`%${t}%`);return i||null}let s=process.cwd(),n=e.prepare("SELECT id, name, decoded_path FROM projects WHERE decoded_path = ?").get(s);if(n)return n;let r=e.prepare("SELECT id, name, decoded_path FROM projects WHERE name = ? LIMIT 1").get(Ng(s));return r||null}var Yi=28;function Lg(e,t){let s=Math.round(e/t*Yi);return d.dim("\u2588".repeat(s)+"\xB7".repeat(Yi-s))}Ft();I();T();En();T();Ft();import{readFileSync as Mg,existsSync as Vn,statSync as $g,readdirSync as Dg}from"node:fs";import{join as Ts}from"node:path";import{homedir as jg}from"node:os";var Ut=["vscode","cursor","windsurf"],Pg={vscode:"Code",cursor:"Cursor",windsurf:"Windsurf"};var Fg=.7,Ug=300*1e3;function Bg(e){let t=e?.homeDir??jg(),s=e?.sources??Ut,n=[];for(let r of s){let o=Ts(t,"Library","Application Support",Pg[r],"User","workspaceStorage");Vn(o)&&n.push({source:r,root:o})}return n}function Hg(e,t){let s=Ts(e,"workspace.json"),n=Ts(e,"state.vscdb");if(!Vn(s)||!Vn(n))return[];let r;try{let l=JSON.parse(Mg(s,"utf8"));if(!l.folder||!l.folder.startsWith("file://"))return[];r=decodeURIComponent(l.folder.replace(/^file:\/\//,""))}catch{return[]}let o;try{o=$g(n).mtime.toISOString()}catch{return[]}let i;try{i=new rs(n,{readonly:!0})}catch{return[]}let a=[];try{let l=i.prepare("SELECT value FROM ItemTable WHERE key = 'terminal.integrated.bufferState' LIMIT 1").get(),c={};if(l?.value)try{c=JSON.parse(l.value)}catch{}let u=c.state??[];if(u.length===0)a.push({workspace_path:r,workspace_storage_dir:e,tab_name:null,cwd_hint:null,last_seen_at:o,source:t});else for(let p of u){let m=p.shellLaunchConfig??{},f=typeof m.name=="string"?m.name.trim():"";a.push({workspace_path:r,workspace_storage_dir:e,tab_name:f||null,cwd_hint:typeof m.cwd=="string"?m.cwd:null,last_seen_at:o,source:t})}}finally{i.close()}return a}function Wg(e,t){let s=[],n=0;if(e.cwd&&t.workspace_path){let r=e.cwd,o=t.workspace_path;(r===o||r.startsWith(o+"/")||o.startsWith(r+"/"))&&(n+=.5,s.push("cwd_prefix"))}if(e.started_at&&t.last_seen_at){let r=Date.parse(e.started_at),o=Date.parse(t.last_seen_at);Number.isFinite(r)&&Number.isFinite(o)&&Math.abs(r-o)<=Ug&&(n+=.4,s.push("time_window"))}return e.cwd&&t.cwd_hint&&e.cwd===t.cwd_hint&&(n+=.1,s.push("cwd_exact")),t.tab_name&&(n+=.2,s.push("has_name")),n>1&&(n=1),{score:n,matchedOn:s}}var Xg=new Set(["zsh","bash","fish","sh","dash","ksh","tcsh","csh","pwsh","powershell","cmd","nu","node","deno","bun","python","python3","ruby","ts-node","tsx","go","cargo","java","php","irb","pry","iex","task","tasks","terminal","copilot","cascade","composer","claude","claude code"]);function Jg(e){return Xg.has(e.trim().toLowerCase())}function Gg(e){let t=e.tab_name?.trim();return!t||Jg(t)?null:t}function Qi(e){let t=e?.minScore??Fg,s=e?.limit,n=_(),r=e?.projectId?" AND s.project_id = ?":"",o=e?.projectId?[e.projectId]:[],i=n.prepare(`SELECT s.id, p.decoded_path AS cwd, s.started_at
1034
1034
  FROM sessions s
1035
1035
  JOIN projects p ON p.id = s.project_id
1036
1036
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1037
- WHERE (sa.alias IS NULL OR sa.alias = '')${r}`).all(...o),a=e?.sources??Ut,l=Bg({sources:a,homeDir:e?.homeDir}),c=[];for(let{source:p,root:m}of l){let f;try{f=$g(m)}catch{continue}for(let g of f){let h=Ts(m,g);c.push(...Hg(h,p))}}if(c.length===0)return[];let u=[];for(let p of i){let m=null;for(let g of c){let{score:h,matchedOn:E}=Wg(p,g);h<t||(!m||h>m.score)&&(m={entry:g,score:h,matched:E})}if(!m)continue;let f=Gg(m.entry);f&&u.push({session_id:p.id,proposed_alias:f,score:m.score,evidence:{source:m.entry.source,workspace_path:m.entry.workspace_path,workspace_storage_dir:m.entry.workspace_storage_dir,tab_name:m.entry.tab_name,cwd_hint:m.entry.cwd_hint,last_seen_at:m.entry.last_seen_at,matched_on:m.matched}})}return u.sort((p,m)=>m.score-p.score||p.session_id.localeCompare(m.session_id)),typeof s=="number"&&s>=0&&u.length>s?u.slice(0,s):u}function ea(e){let t=[],s=[];for(let n of e){let r=Ki(n.session_id);if(r&&r.trim()!==""){s.push(n);continue}t.push(n)}return{applicable:t,skipped:s}}import{basename as zg}from"node:path";async function sa(e){let t=qg(e.source);if(!t){console.error(d.err("Invalid --source. Allowed: vscode | cursor | windsurf | all (default).")),process.exitCode=1;return}let s=Kg(e.minScore,.7);if(s===null||s<0||s>1){console.error(d.err("Invalid --min-score. Must be a number in [0, 1].")),process.exitCode=1;return}let n=e.limit?parseInt(e.limit,10):void 0;if(n!==void 0&&(!Number.isFinite(n)||n<0)){console.error(d.err("Invalid --limit. Must be a non-negative integer.")),process.exitCode=1;return}let r=e.project?Vg(e.project):void 0;if(e.project&&r===null){console.error(d.err(`No project found matching "${e.project}". Run \`recall projects\`.`)),process.exitCode=1;return}let o=Qi({projectId:r??void 0,sources:t,minScore:s,limit:n}),{applicable:i,skipped:a}=ea(o);if(e.apply){let l=0;for(let c of i)try{ys(c.session_id,c.proposed_alias),l+=1}catch(u){console.error(d.err(`apply failed for ${c.session_id.slice(0,8)}: ${u.message}`))}if(e.json){console.log(JSON.stringify({mode:"apply",sources:t,min_score:s,project_id:r??null,applied:l,skipped:a.length,proposals:i.map(ta)},null,2));return}console.log(""),console.log(d.ok(`Applied ${l} alias backfill${l===1?"":"s"}`+(a.length?` \xB7 skipped ${a.length} (alias appeared since proposal)`:""))),console.log("");return}if(e.json){console.log(JSON.stringify({mode:"dry-run",sources:t,min_score:s,project_id:r??null,proposals:i.map(ta),skipped_due_to_existing_alias:a.length},null,2));return}Yg(i,t,s,a.length)}function Yg(e,t,s,n){if(console.log(""),console.log(d.project(`recall import-vscode-state \xB7 sources=${t.join("+")} min-score=${s.toFixed(2)} \xB7 DRY RUN`)),console.log(d.dim(" Pass --apply to write proposals via setAlias().")),console.log(""),e.length===0){console.log(d.warn(" No proposals \u2014 either no matching workspaces or every candidate session already has an alias.")),n>0&&console.log(d.dim(` ${n} sessions were skipped because they already have aliases.`)),console.log("");return}for(let r of e){let o=d.bold(r.session_id.slice(0,8)),i=d.bold(r.score.toFixed(2)),a=d.dim(`[${r.evidence.source}]`),l=r.evidence.matched_on.join("+");console.log(` ${o} score=${i} ${a} matched=${l}`),console.log(` proposed alias: ${d.bold(r.proposed_alias)}`),console.log(` workspace: ${d.dim(Y(r.evidence.workspace_path,70))}`),r.evidence.tab_name&&console.log(` tab name: ${r.evidence.tab_name}`),r.evidence.cwd_hint&&console.log(` cwd hint: ${d.dim(Y(r.evidence.cwd_hint,70))}`),console.log(` last seen: ${d.dim(r.evidence.last_seen_at)}`),console.log("")}console.log(d.dim(` ${e.length} proposal${e.length===1?"":"s"}`+(n>0?` \xB7 ${n} skipped (existing alias)`:"")+" \xB7 pass --apply to write via setAlias()")),console.log("")}function ta(e){return e}function qg(e){if(!e||e==="all")return Ut;let t=e.split(",").map(n=>n.trim().toLowerCase()).filter(Boolean),s=[];for(let n of t)if(Ut.includes(n))s.push(n);else return null;return s.length>0?s:null}function Kg(e,t){if(e===void 0)return t;let s=Number.parseFloat(e);return Number.isFinite(s)?s:null}function Vg(e){let t=_(),s=t.prepare("SELECT id FROM projects WHERE name = ? LIMIT 1").get(e);if(s)return s.id;let n=t.prepare("SELECT id FROM projects WHERE name LIKE ? ORDER BY name LIMIT 1").get(`%${e}%`);if(n)return n.id;let r=zg(e);if(r&&r!==e){let o=t.prepare("SELECT id FROM projects WHERE name = ? LIMIT 1").get(r);if(o)return o.id}return null}import{existsSync as na,mkdirSync as Zg,readFileSync as Qg,writeFileSync as ef}from"node:fs";import{homedir as tf}from"node:os";import{join as ra}from"node:path";import{z as Xe}from"zod";function oa(){return process.env.RECALL_HOME??ra(tf(),".recall")}function sf(){let e=oa();na(e)||Zg(e,{recursive:!0})}function ia(){return ra(oa(),"config.json")}var aa=Xe.object({enabled:Xe.boolean().default(!1),model:Xe.string().optional(),ratePerMinute:Xe.number().int().min(1).max(600).default(30),lastProcessedSessionId:Xe.string().nullable().default(null),backfillPaused:Xe.boolean().default(!1),autoExtractEnabled:Xe.boolean().default(!1),autoExtractIntervalMinutes:Xe.number().int().min(5).max(720).default(60),autoExtractBatchSize:Xe.number().int().min(1).max(20).default(1)}),ws={enabled:!1,ratePerMinute:30,lastProcessedSessionId:null,backfillPaused:!1,autoExtractEnabled:!1,autoExtractIntervalMinutes:60,autoExtractBatchSize:1};function ca(){let e=ia();if(!na(e))return{};try{return JSON.parse(Qg(e,"utf8"))}catch(t){return console.error("[semantic-config] failed to parse config.json, using defaults:",t),{}}}function Ae(){let e=ca().semantic;if(!e)return{...ws};let t=aa.safeParse({...ws,...e});return t.success?t.data:{...ws}}function Pe(e){sf();let t=ca(),s=aa.parse({...ws,...t.semantic??{},...e}),n={...t,semantic:s};return ef(ia(),JSON.stringify(n,null,2)),s}T();Je();import{existsSync as yf,mkdirSync as Tf,writeFileSync as wf}from"node:fs";import{homedir as xf}from"node:os";import{join as er}from"node:path";var Rf=1,kf=12e3,Nf=3,Cf=[];function Lf(){return process.env.RECALL_HOME??er(xf(),".recall")}function ba(){return er(Lf(),"semantic")}function Of(){let e=ba();yf(e)||Tf(e,{recursive:!0})}function Af(e){let t=_(),s=t.prepare(`SELECT s.id, s.message_count, s.first_user_message,
1037
+ WHERE (sa.alias IS NULL OR sa.alias = '')${r}`).all(...o),a=e?.sources??Ut,l=Bg({sources:a,homeDir:e?.homeDir}),c=[];for(let{source:p,root:m}of l){let f;try{f=Dg(m)}catch{continue}for(let g of f){let h=Ts(m,g);c.push(...Hg(h,p))}}if(c.length===0)return[];let u=[];for(let p of i){let m=null;for(let g of c){let{score:h,matchedOn:E}=Wg(p,g);h<t||(!m||h>m.score)&&(m={entry:g,score:h,matched:E})}if(!m)continue;let f=Gg(m.entry);f&&u.push({session_id:p.id,proposed_alias:f,score:m.score,evidence:{source:m.entry.source,workspace_path:m.entry.workspace_path,workspace_storage_dir:m.entry.workspace_storage_dir,tab_name:m.entry.tab_name,cwd_hint:m.entry.cwd_hint,last_seen_at:m.entry.last_seen_at,matched_on:m.matched}})}return u.sort((p,m)=>m.score-p.score||p.session_id.localeCompare(m.session_id)),typeof s=="number"&&s>=0&&u.length>s?u.slice(0,s):u}function ea(e){let t=[],s=[];for(let n of e){let r=Ki(n.session_id);if(r&&r.trim()!==""){s.push(n);continue}t.push(n)}return{applicable:t,skipped:s}}import{basename as zg}from"node:path";async function sa(e){let t=qg(e.source);if(!t){console.error(d.err("Invalid --source. Allowed: vscode | cursor | windsurf | all (default).")),process.exitCode=1;return}let s=Kg(e.minScore,.7);if(s===null||s<0||s>1){console.error(d.err("Invalid --min-score. Must be a number in [0, 1].")),process.exitCode=1;return}let n=e.limit?parseInt(e.limit,10):void 0;if(n!==void 0&&(!Number.isFinite(n)||n<0)){console.error(d.err("Invalid --limit. Must be a non-negative integer.")),process.exitCode=1;return}let r=e.project?Vg(e.project):void 0;if(e.project&&r===null){console.error(d.err(`No project found matching "${e.project}". Run \`recall projects\`.`)),process.exitCode=1;return}let o=Qi({projectId:r??void 0,sources:t,minScore:s,limit:n}),{applicable:i,skipped:a}=ea(o);if(e.apply){let l=0;for(let c of i)try{ys(c.session_id,c.proposed_alias),l+=1}catch(u){console.error(d.err(`apply failed for ${c.session_id.slice(0,8)}: ${u.message}`))}if(e.json){console.log(JSON.stringify({mode:"apply",sources:t,min_score:s,project_id:r??null,applied:l,skipped:a.length,proposals:i.map(ta)},null,2));return}console.log(""),console.log(d.ok(`Applied ${l} alias backfill${l===1?"":"s"}`+(a.length?` \xB7 skipped ${a.length} (alias appeared since proposal)`:""))),console.log("");return}if(e.json){console.log(JSON.stringify({mode:"dry-run",sources:t,min_score:s,project_id:r??null,proposals:i.map(ta),skipped_due_to_existing_alias:a.length},null,2));return}Yg(i,t,s,a.length)}function Yg(e,t,s,n){if(console.log(""),console.log(d.project(`recall import-vscode-state \xB7 sources=${t.join("+")} min-score=${s.toFixed(2)} \xB7 DRY RUN`)),console.log(d.dim(" Pass --apply to write proposals via setAlias().")),console.log(""),e.length===0){console.log(d.warn(" No proposals \u2014 either no matching workspaces or every candidate session already has an alias.")),n>0&&console.log(d.dim(` ${n} sessions were skipped because they already have aliases.`)),console.log("");return}for(let r of e){let o=d.bold(r.session_id.slice(0,8)),i=d.bold(r.score.toFixed(2)),a=d.dim(`[${r.evidence.source}]`),l=r.evidence.matched_on.join("+");console.log(` ${o} score=${i} ${a} matched=${l}`),console.log(` proposed alias: ${d.bold(r.proposed_alias)}`),console.log(` workspace: ${d.dim(Y(r.evidence.workspace_path,70))}`),r.evidence.tab_name&&console.log(` tab name: ${r.evidence.tab_name}`),r.evidence.cwd_hint&&console.log(` cwd hint: ${d.dim(Y(r.evidence.cwd_hint,70))}`),console.log(` last seen: ${d.dim(r.evidence.last_seen_at)}`),console.log("")}console.log(d.dim(` ${e.length} proposal${e.length===1?"":"s"}`+(n>0?` \xB7 ${n} skipped (existing alias)`:"")+" \xB7 pass --apply to write via setAlias()")),console.log("")}function ta(e){return e}function qg(e){if(!e||e==="all")return Ut;let t=e.split(",").map(n=>n.trim().toLowerCase()).filter(Boolean),s=[];for(let n of t)if(Ut.includes(n))s.push(n);else return null;return s.length>0?s:null}function Kg(e,t){if(e===void 0)return t;let s=Number.parseFloat(e);return Number.isFinite(s)?s:null}function Vg(e){let t=_(),s=t.prepare("SELECT id FROM projects WHERE name = ? LIMIT 1").get(e);if(s)return s.id;let n=t.prepare("SELECT id FROM projects WHERE name LIKE ? ORDER BY name LIMIT 1").get(`%${e}%`);if(n)return n.id;let r=zg(e);if(r&&r!==e){let o=t.prepare("SELECT id FROM projects WHERE name = ? LIMIT 1").get(r);if(o)return o.id}return null}import{existsSync as na,mkdirSync as Zg,readFileSync as Qg,writeFileSync as ef}from"node:fs";import{homedir as tf}from"node:os";import{join as ra}from"node:path";import{z as Xe}from"zod";function oa(){return process.env.RECALL_HOME??ra(tf(),".recall")}function sf(){let e=oa();na(e)||Zg(e,{recursive:!0})}function ia(){return ra(oa(),"config.json")}var aa=Xe.object({enabled:Xe.boolean().default(!1),model:Xe.string().optional(),ratePerMinute:Xe.number().int().min(1).max(600).default(30),lastProcessedSessionId:Xe.string().nullable().default(null),backfillPaused:Xe.boolean().default(!1),autoExtractEnabled:Xe.boolean().default(!1),autoExtractIntervalMinutes:Xe.number().int().min(5).max(720).default(60),autoExtractBatchSize:Xe.number().int().min(1).max(20).default(1)}),ws={enabled:!1,ratePerMinute:30,lastProcessedSessionId:null,backfillPaused:!1,autoExtractEnabled:!1,autoExtractIntervalMinutes:60,autoExtractBatchSize:1};function ca(){let e=ia();if(!na(e))return{};try{return JSON.parse(Qg(e,"utf8"))}catch(t){return console.error("[semantic-config] failed to parse config.json, using defaults:",t),{}}}function Ae(){let e=ca().semantic;if(!e)return{...ws};let t=aa.safeParse({...ws,...e});return t.success?t.data:{...ws}}function Pe(e){sf();let t=ca(),s=aa.parse({...ws,...t.semantic??{},...e}),n={...t,semantic:s};return ef(ia(),JSON.stringify(n,null,2)),s}T();Je();import{existsSync as yf,mkdirSync as Tf,writeFileSync as wf}from"node:fs";import{homedir as xf}from"node:os";import{join as er}from"node:path";var Rf=1,kf=12e3,Nf=3,Cf=[];function Lf(){return process.env.RECALL_HOME??er(xf(),".recall")}function ba(){return er(Lf(),"semantic")}function Of(){let e=ba();yf(e)||Tf(e,{recursive:!0})}function Af(e){let t=_(),s=t.prepare(`SELECT s.id, s.message_count, s.first_user_message,
1038
1038
  p.name AS project,
1039
1039
  NULLIF(sa.alias, '') AS alias
1040
1040
  FROM sessions s
@@ -1054,7 +1054,7 @@ show full content: recall paste --show <id>
1054
1054
  keywords = excluded.keywords,
1055
1055
  model = excluded.model,
1056
1056
  source_message_count = excluded.source_message_count,
1057
- generated_at = excluded.generated_at`).run({session_id:e.sessionId,summary:e.summary,keywords:s,model:e.model,source_message_count:e.sourceMessageCount,generated_at:e.generatedAt}),Of();let n=er(ba(),`${e.sessionId}.json`);wf(n,JSON.stringify({version:Rf,session_id:e.sessionId,summary:e.summary,keywords:e.keywords,model:e.model,source_message_count:e.sourceMessageCount,generated_at:e.generatedAt},null,2))}var xs=null;function Df(){let t=Ae().ratePerMinute,s=t/6e4;return(!xs||xs.capacity!==t)&&(xs={tokens:t,capacity:t,refillPerMs:s,lastRefill:Date.now()}),xs}function $f(e){let t=Date.now(),s=t-e.lastRefill;s>0&&(e.tokens=Math.min(e.capacity,e.tokens+s*e.refillPerMs),e.lastRefill=t)}async function jf(e){for(;;){if(e?.aborted)throw new Error("aborted");let t=Df();if($f(t),t.tokens>=1){t.tokens-=1;return}let s=1-t.tokens,n=Math.max(50,Math.ceil(s/t.refillPerMs));await new Promise(r=>setTimeout(r,Math.min(n,5e3)))}}async function Pf(e,t={}){let s=Ae();if(!s.enabled)return{sessionId:e,ok:!1,reason:"disabled"};if(!ce())return{sessionId:e,ok:!1,reason:"claude-cli-missing"};let n=Af(e);if(!n)return{sessionId:e,ok:!1,reason:"session-not-found"};if(n.messageCount<Nf)return{sessionId:e,ok:!1,reason:"too-short"};if(!n.excerpt.trim())return{sessionId:e,ok:!1,reason:"empty-excerpt"};await jf(t.signal);let r=If(n),o=await mt(r,Cf,{model:s.model});if(!o.success)return{sessionId:e,ok:!1,reason:`claude-cli-exit-${o.exitCode??"null"}`,model:s.model??null};let i=vf(o.stdout);return i?(Mf({sessionId:n.id,summary:i.summary,keywords:i.keywords,model:s.model??null,sourceMessageCount:n.messageCount,generatedAt:new Date().toISOString()}),{sessionId:e,ok:!0,model:s.model??null}):{sessionId:e,ok:!1,reason:"parse-failed",model:s.model??null}}async function Rs(e={}){let t=Ae();if(!t.enabled)return{total:0,processed:0,ok:0,failed:0,currentSessionId:null};let s=_(),r={limit:e.limit??1e3},o="s.message_count >= 3";e.force||(o+=" AND ss.session_id IS NULL"),typeof e.projectId=="number"&&(o+=" AND s.project_id = @projectId",r.projectId=e.projectId),t.lastProcessedSessionId&&e.force;let i=s.prepare(`SELECT s.id
1057
+ generated_at = excluded.generated_at`).run({session_id:e.sessionId,summary:e.summary,keywords:s,model:e.model,source_message_count:e.sourceMessageCount,generated_at:e.generatedAt}),Of();let n=er(ba(),`${e.sessionId}.json`);wf(n,JSON.stringify({version:Rf,session_id:e.sessionId,summary:e.summary,keywords:e.keywords,model:e.model,source_message_count:e.sourceMessageCount,generated_at:e.generatedAt},null,2))}var xs=null;function $f(){let t=Ae().ratePerMinute,s=t/6e4;return(!xs||xs.capacity!==t)&&(xs={tokens:t,capacity:t,refillPerMs:s,lastRefill:Date.now()}),xs}function Df(e){let t=Date.now(),s=t-e.lastRefill;s>0&&(e.tokens=Math.min(e.capacity,e.tokens+s*e.refillPerMs),e.lastRefill=t)}async function jf(e){for(;;){if(e?.aborted)throw new Error("aborted");let t=$f();if(Df(t),t.tokens>=1){t.tokens-=1;return}let s=1-t.tokens,n=Math.max(50,Math.ceil(s/t.refillPerMs));await new Promise(r=>setTimeout(r,Math.min(n,5e3)))}}async function Pf(e,t={}){let s=Ae();if(!s.enabled)return{sessionId:e,ok:!1,reason:"disabled"};if(!ce())return{sessionId:e,ok:!1,reason:"claude-cli-missing"};let n=Af(e);if(!n)return{sessionId:e,ok:!1,reason:"session-not-found"};if(n.messageCount<Nf)return{sessionId:e,ok:!1,reason:"too-short"};if(!n.excerpt.trim())return{sessionId:e,ok:!1,reason:"empty-excerpt"};await jf(t.signal);let r=If(n),o=await mt(r,Cf,{model:s.model});if(!o.success)return{sessionId:e,ok:!1,reason:`claude-cli-exit-${o.exitCode??"null"}`,model:s.model??null};let i=vf(o.stdout);return i?(Mf({sessionId:n.id,summary:i.summary,keywords:i.keywords,model:s.model??null,sourceMessageCount:n.messageCount,generatedAt:new Date().toISOString()}),{sessionId:e,ok:!0,model:s.model??null}):{sessionId:e,ok:!1,reason:"parse-failed",model:s.model??null}}async function Rs(e={}){let t=Ae();if(!t.enabled)return{total:0,processed:0,ok:0,failed:0,currentSessionId:null};let s=_(),r={limit:e.limit??1e3},o="s.message_count >= 3";e.force||(o+=" AND ss.session_id IS NULL"),typeof e.projectId=="number"&&(o+=" AND s.project_id = @projectId",r.projectId=e.projectId),t.lastProcessedSessionId&&e.force;let i=s.prepare(`SELECT s.id
1058
1058
  FROM sessions s
1059
1059
  LEFT JOIN session_semantic ss ON ss.session_id = s.id
1060
1060
  WHERE ${o}
@@ -1123,7 +1123,7 @@ show full content: recall paste --show <id>
1123
1123
  FROM chunk_meta cm
1124
1124
  ${g}`).get(...r),E=s?" JOIN sessions s ON s.id = cq.session_id WHERE s.project_id = ?":"",b=t.prepare(`SELECT COUNT(*) AS n
1125
1125
  FROM chunk_queue cq
1126
- ${E}`).get(...r);return{project:s,sessions:{total:i,with_semantic:a,with_semantic_pct:As(a,i),with_chunks:l,with_chunks_pct:As(l,i),with_message_embeddings:c,with_message_embeddings_pct:As(c,i)},messages:{total:p.total??0,eligible:p.eligible??0,embedded:f.embedded,embedded_pct:As(f.embedded,p.eligible??0),threshold_chars:Ze},chunks:{chunk_meta_rows:h.n,chunk_queue_pending:b.n},generated_at:new Date().toISOString()}}function Da(e){let s=e.sessions.with_semantic_pct,n=e.sessions.total-e.sessions.with_semantic,r=e.sessions.total>0&&s>=95,o=r?`${s}% session_semantic coverage (${e.sessions.with_semantic} of ${e.sessions.total})`:e.sessions.total===0?"no sessions in scope":`${s}% session_semantic coverage (need \u226595%); ${n} sessions missing summaries`;return{passes:r,required_pct:95,actual_pct:s,missing_sessions:n,reason:o}}_e();Cs();Ve();async function $a(e,t){let s=(e??"audit").toLowerCase();if(s==="audit")return g_(t);if(s==="backfill-summaries")return __(t);if(s==="backfill-messages")return h_(t);console.error(`Unknown embeddings action: ${e}. Supported: audit | backfill-summaries | backfill-messages`),process.exitCode=1}function cr(e){if(!e)return null;let t=he(e);return t||"not-found"}async function g_(e){let t=cr(e.project);if(t==="not-found"){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}let s=Ma({projectId:t?t.id:void 0}),n=Da(s);if(e.json){console.log(JSON.stringify({report:s,verdict:n},null,2));return}f_(s,n),n.passes||(process.exitCode=1)}function f_(e,t){let s=e.project?`project "${e.project.name}"`:"all projects";console.log(`Embeddings coverage \u2014 ${s}`),console.log(""),console.log(` Sessions: ${e.sessions.total} total`),console.log(` session_semantic: ${e.sessions.with_semantic}/${e.sessions.total} (${e.sessions.with_semantic_pct}%)`),console.log(` chunk_meta (any): ${e.sessions.with_chunks}/${e.sessions.total} (${e.sessions.with_chunks_pct}%)`),console.log(` message_embeddings: ${e.sessions.with_message_embeddings}/${e.sessions.total} (${e.sessions.with_message_embeddings_pct}%)`),console.log(""),console.log(` Messages: ${e.messages.total} total`),console.log(` eligible (>${e.messages.threshold_chars} chars): ${e.messages.eligible}`),console.log(` embedded: ${e.messages.embedded}${e.messages.eligible>0?` (${e.messages.embedded_pct}% of eligible)`:""}`),console.log(""),console.log(" Chunks (Pro tier):"),console.log(` chunk_meta rows: ${e.chunks.chunk_meta_rows}`),console.log(` chunk_queue pending: ${e.chunks.chunk_queue_pending}`),e.chunks.chunk_queue_pending>1e3&&e.chunks.chunk_meta_rows===0&&(console.log(""),console.log(" \u26A0 chunk_queue is backed up but no chunks have been processed."),console.log(" Activate Pro and run `recall semantic install` to drain the queue.")),console.log(""),t.passes?console.log(` \u2705 Acceptance: ${t.reason}`):(console.log(` \u274C Acceptance: ${t.reason}`),console.log(` Run \`recall embeddings backfill-summaries${e.project?` --project ${e.project.name}`:""}\` to close the gap.`))}async function __(e){if(!Ae().enabled){console.error("Semantic search is disabled. Run `recall semantic on` first."),process.exitCode=1;return}let s=cr(e.project);if(s==="not-found"){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}let n=e.limit?Math.max(1,Number(e.limit)):1e3,r=s?`project "${s.name}"`:"all projects";console.log(`Backfilling session_semantic \u2014 ${r} \u2014 up to ${n} sessions\u2026`);let o=Date.now(),i=0,a=await Rs({limit:n,projectId:s?s.id:void 0,onProgress:c=>{if(e.json||c.processed===i)return;i=c.processed;let u=c.total>0?` (${Math.round(c.processed/c.total*100)}%)`:"";process.stdout.write(`\r ${c.processed}/${c.total}${u} ok=${c.ok} failed=${c.failed} `)}});e.json||process.stdout.write(`
1126
+ ${E}`).get(...r);return{project:s,sessions:{total:i,with_semantic:a,with_semantic_pct:As(a,i),with_chunks:l,with_chunks_pct:As(l,i),with_message_embeddings:c,with_message_embeddings_pct:As(c,i)},messages:{total:p.total??0,eligible:p.eligible??0,embedded:f.embedded,embedded_pct:As(f.embedded,p.eligible??0),threshold_chars:Ze},chunks:{chunk_meta_rows:h.n,chunk_queue_pending:b.n},generated_at:new Date().toISOString()}}function $a(e){let s=e.sessions.with_semantic_pct,n=e.sessions.total-e.sessions.with_semantic,r=e.sessions.total>0&&s>=95,o=r?`${s}% session_semantic coverage (${e.sessions.with_semantic} of ${e.sessions.total})`:e.sessions.total===0?"no sessions in scope":`${s}% session_semantic coverage (need \u226595%); ${n} sessions missing summaries`;return{passes:r,required_pct:95,actual_pct:s,missing_sessions:n,reason:o}}_e();Cs();Ve();async function Da(e,t){let s=(e??"audit").toLowerCase();if(s==="audit")return g_(t);if(s==="backfill-summaries")return __(t);if(s==="backfill-messages")return h_(t);console.error(`Unknown embeddings action: ${e}. Supported: audit | backfill-summaries | backfill-messages`),process.exitCode=1}function cr(e){if(!e)return null;let t=he(e);return t||"not-found"}async function g_(e){let t=cr(e.project);if(t==="not-found"){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}let s=Ma({projectId:t?t.id:void 0}),n=$a(s);if(e.json){console.log(JSON.stringify({report:s,verdict:n},null,2));return}f_(s,n),n.passes||(process.exitCode=1)}function f_(e,t){let s=e.project?`project "${e.project.name}"`:"all projects";console.log(`Embeddings coverage \u2014 ${s}`),console.log(""),console.log(` Sessions: ${e.sessions.total} total`),console.log(` session_semantic: ${e.sessions.with_semantic}/${e.sessions.total} (${e.sessions.with_semantic_pct}%)`),console.log(` chunk_meta (any): ${e.sessions.with_chunks}/${e.sessions.total} (${e.sessions.with_chunks_pct}%)`),console.log(` message_embeddings: ${e.sessions.with_message_embeddings}/${e.sessions.total} (${e.sessions.with_message_embeddings_pct}%)`),console.log(""),console.log(` Messages: ${e.messages.total} total`),console.log(` eligible (>${e.messages.threshold_chars} chars): ${e.messages.eligible}`),console.log(` embedded: ${e.messages.embedded}${e.messages.eligible>0?` (${e.messages.embedded_pct}% of eligible)`:""}`),console.log(""),console.log(" Chunks (Pro tier):"),console.log(` chunk_meta rows: ${e.chunks.chunk_meta_rows}`),console.log(` chunk_queue pending: ${e.chunks.chunk_queue_pending}`),e.chunks.chunk_queue_pending>1e3&&e.chunks.chunk_meta_rows===0&&(console.log(""),console.log(" \u26A0 chunk_queue is backed up but no chunks have been processed."),console.log(" Activate Pro and run `recall semantic install` to drain the queue.")),console.log(""),t.passes?console.log(` \u2705 Acceptance: ${t.reason}`):(console.log(` \u274C Acceptance: ${t.reason}`),console.log(` Run \`recall embeddings backfill-summaries${e.project?` --project ${e.project.name}`:""}\` to close the gap.`))}async function __(e){if(!Ae().enabled){console.error("Semantic search is disabled. Run `recall semantic on` first."),process.exitCode=1;return}let s=cr(e.project);if(s==="not-found"){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}let n=e.limit?Math.max(1,Number(e.limit)):1e3,r=s?`project "${s.name}"`:"all projects";console.log(`Backfilling session_semantic \u2014 ${r} \u2014 up to ${n} sessions\u2026`);let o=Date.now(),i=0,a=await Rs({limit:n,projectId:s?s.id:void 0,onProgress:c=>{if(e.json||c.processed===i)return;i=c.processed;let u=c.total>0?` (${Math.round(c.processed/c.total*100)}%)`:"";process.stdout.write(`\r ${c.processed}/${c.total}${u} ok=${c.ok} failed=${c.failed} `)}});e.json||process.stdout.write(`
1127
1127
  `);let l=((Date.now()-o)/1e3).toFixed(1);e.json?console.log(JSON.stringify({...a,elapsed_seconds:Number(l)},null,2)):console.log(`Done in ${l}s \u2014 processed=${a.processed} ok=${a.ok} failed=${a.failed}`)}async function h_(e){if(await Ce("Per-message embeddings"),!gt()){console.error("Model not installed. Run `recall semantic install` first."),process.exitCode=1;return}Ge().loaded||await Ke();let t=cr(e.project);if(t==="not-found"){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}let s=e.limit?Math.max(1,Number(e.limit)):200,n=t?`project "${t.name}"`:"all projects";console.log(`Embedding messages > ${Ze} chars \u2014 ${n} \u2014 up to ${s} sessions\u2026`);let r=Date.now(),o=0,i=await va({projectId:t?t.id:void 0,limitSessions:s,onProgress:m=>{if(e.json||m.processed_sessions===o)return;o=m.processed_sessions;let f=m.total_sessions>0?` (${Math.round(m.processed_sessions/m.total_sessions*100)}%)`:"";process.stdout.write(`\r ${m.processed_sessions}/${m.total_sessions} sessions${f} embedded=${m.embedded_messages} failed=${m.failed_messages} `)}});e.json||process.stdout.write(`
1128
1128
  `);let a=((Date.now()-r)/1e3).toFixed(1);e.json?console.log(JSON.stringify({...i,elapsed_seconds:Number(a)},null,2)):console.log(`Done in ${a}s \u2014 sessions=${i.processed_sessions}/${i.total_sessions} embedded=${i.embedded_messages} failed=${i.failed_messages}`);let l=_(),c=t?" AND s.project_id = ?":"",u=t?[t.id]:[],p=l.prepare(`SELECT COUNT(DISTINCT s.id) AS n
1129
1129
  FROM sessions s
@@ -1133,7 +1133,7 @@ show full content: recall paste --show <id>
1133
1133
  AND m.content_text IS NOT NULL
1134
1134
  AND length(m.content_text) > ?
1135
1135
  AND me.message_uuid IS NULL
1136
- ${c}`).get(Ze,...u);p.n>0&&console.log(` ${p.n} session(s) still have unembedded eligible messages. Re-run to continue.`)}T();Je();import{createHash as x_}from"node:crypto";T();j();import{writeFileSync as E_,readFileSync as vN,existsSync as b_,mkdirSync as S_,readdirSync as MN}from"node:fs";import{join as ja}from"node:path";var lr=ja(x,"output-index");function y_(){P(),b_(lr)||S_(lr,{recursive:!0})}function Xt(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function T_(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}function Pa(e){return{session_id:e.session_id,files_written:Xt(e.files_written),brands_mentioned:Xt(e.brands_mentioned),terms_introduced:Xt(e.terms_introduced),plan_ids_referenced:Xt(e.plan_ids_referenced),bug_signatures:Xt(e.bug_signatures),raw_extraction:T_(e.raw_extraction),extracted_at:e.extracted_at,extractor_version:e.extractor_version}}function Fa(e){if(!e.session_id)throw new Error("session_id is required");let t=_(),s=new Date().toISOString(),n=JSON.stringify(e.files_written??[]),r=JSON.stringify(e.brands_mentioned??[]),o=JSON.stringify(e.terms_introduced??[]),i=JSON.stringify(e.plan_ids_referenced??[]),a=JSON.stringify(e.bug_signatures??[]),l=e.raw_extraction===void 0?null:JSON.stringify(e.raw_extraction),c=Math.max(1,Math.floor(e.extractor_version??1));t.prepare(`INSERT INTO session_output_index
1136
+ ${c}`).get(Ze,...u);p.n>0&&console.log(` ${p.n} session(s) still have unembedded eligible messages. Re-run to continue.`)}T();Je();import{createHash as x_}from"node:crypto";T();j();import{writeFileSync as E_,readFileSync as $N,existsSync as b_,mkdirSync as S_,readdirSync as DN}from"node:fs";import{join as ja}from"node:path";var lr=ja(x,"output-index");function y_(){P(),b_(lr)||S_(lr,{recursive:!0})}function Xt(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function T_(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}function Pa(e){return{session_id:e.session_id,files_written:Xt(e.files_written),brands_mentioned:Xt(e.brands_mentioned),terms_introduced:Xt(e.terms_introduced),plan_ids_referenced:Xt(e.plan_ids_referenced),bug_signatures:Xt(e.bug_signatures),raw_extraction:T_(e.raw_extraction),extracted_at:e.extracted_at,extractor_version:e.extractor_version}}function Fa(e){if(!e.session_id)throw new Error("session_id is required");let t=_(),s=new Date().toISOString(),n=JSON.stringify(e.files_written??[]),r=JSON.stringify(e.brands_mentioned??[]),o=JSON.stringify(e.terms_introduced??[]),i=JSON.stringify(e.plan_ids_referenced??[]),a=JSON.stringify(e.bug_signatures??[]),l=e.raw_extraction===void 0?null:JSON.stringify(e.raw_extraction),c=Math.max(1,Math.floor(e.extractor_version??1));t.prepare(`INSERT INTO session_output_index
1137
1137
  (session_id, files_written, brands_mentioned, terms_introduced,
1138
1138
  plan_ids_referenced, bug_signatures, raw_extraction,
1139
1139
  extracted_at, extractor_version)
@@ -1165,7 +1165,7 @@ show full content: recall paste --show <id>
1165
1165
  ORDER BY COALESCE(timestamp, ''), rowid`).all(e),r=[],o=0;for(let i of n){let a=i.role??"system",l=i.content_text.trim();if(!l)continue;let c=l.length>Ua?l.slice(0,Ua)+"\u2026":l,u=`${a}: ${c}`;if(o+u.length>k_)break;r.push(u),o+=u.length}return{meta:t,excerpt:r.join(`
1166
1166
 
1167
1167
  `)}}function v_(e){let{meta:t}=e;return["You are extracting a structured Output Index from a Claude Code session for a local knowledge graph.","","Read the transcript and produce a single JSON object with EXACTLY these fields. Output JSON only \u2014 no Markdown fences, no commentary, no explanation.","","Fields (every field MUST appear; use [] for empty):","- files_written: array of strings. Relative or absolute file paths the assistant created, edited, or extensively discussed (Write/Edit tool calls or paths quoted verbatim).",'- brands_mentioned: array of strings. Distinct proper-noun company / product / brand names mentioned. Examples of valid: "Glaser Group", "Apollo", "TikTok", "Cloudflare R2". NOT generic terms like "the company" or "users".','- terms_introduced: array of objects { "term": "<lowercase phrase>", "freq": <int> }. Distinctive multi-word noun phrases the session introduced or extensively discussed. Skip generic words. Cap at 30 entries.','- plan_ids_referenced: array of strings. Planning identifiers like "v0.18.A", "Phase D", "L3", "MASTER-PLAN-cognitive-graph". Empty array if none.','- bug_signatures: array of objects { "error_type": "<class or null>", "snippet": "<first line of the error>", "file": "<path or null>" }. Errors actually encountered in the session (not hypothetical). The error_type is the exception class (e.g. "TypeError", "ReferenceError") or null if unspecified.',"","Hard constraints:","- Do NOT fabricate. If a field has no concrete content from the transcript, output an empty array.","- Output JSON ONLY. No backticks, no markdown, no preamble.","- terms_introduced \u2264 30 entries; brands_mentioned \u2264 30 distinct entries; plan_ids_referenced \u2264 30; bug_signatures \u2264 30.","",`Session: ${t.alias??t.id.slice(0,8)}`,`Project: ${t.project??"unknown"}`,t.first_user_message?`Opening prompt: ${t.first_user_message.slice(0,500)}`:"","","Transcript excerpt (may be truncated):","---",e.excerpt,"---"].filter(Boolean).join(`
1168
- `)}function M_(e){return Array.isArray(e)&&e.every(t=>typeof t=="string")}function dr(e,t,s=!1){if(!Array.isArray(e))return[];let n=new Set,r=[];for(let o of e){if(typeof o!="string")continue;let i=s?o.trim().toLowerCase():o.trim();if(!(!i||i.length>256)&&!n.has(i)&&(n.add(i),r.push(i),r.length>=t))break}return r}function D_(e,t){if(!Array.isArray(e))return[];let s=new Set,n=[];for(let r of e){if(!r||typeof r!="object")continue;let o=r.term,i=r.freq;if(typeof o!="string")continue;let a=o.trim().toLowerCase();if(!a||a.length>128||s.has(a))continue;s.add(a);let l=typeof i=="number"&&Number.isFinite(i)&&i>0?Math.floor(i):1;if(n.push({term:a,frequency:l}),n.length>=t)break}return n}function $_(e,t){if(!Array.isArray(e))return[];let s=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n.error_type,o=n.snippet,i=n.file,a=typeof r=="string"&&r.trim().length>0?r.trim().slice(0,64):"unknown",l=typeof o=="string"?o.trim().replace(/\s+/g," ").slice(0,256):"";if(!l)continue;let c=typeof i=="string"&&i.trim().length>0?i.trim().slice(0,256):null,u=x_("sha256").update(`${a}::${l}`).digest("hex").slice(0,12);if(s.push({error_type:a,message_hash:u,snippet:l,file:c}),s.length>=t)break}return s}function j_(e){let t=e.trim();try{let m=JSON.parse(t);typeof m.result=="string"&&(t=m.result.trim())}catch{}t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let s=t.indexOf("{"),n=t.lastIndexOf("}");if(s===-1||n===-1||n<=s)return null;let r=t.slice(s,n+1),o;try{o=JSON.parse(r)}catch{return null}let i=dr(o.files_written,200),a=dr(o.brands_mentioned,C_),l=D_(o.terms_introduced,N_),c=dr(o.plan_ids_referenced,L_),u=$_(o.bug_signatures,O_);return i.length===0&&a.length===0&&l.length===0&&c.length===0&&u.length===0&&!M_(o.files_written)?null:{files_written:i,brands_mentioned:a,terms_introduced:l,plan_ids_referenced:c,bug_signatures:u}}var ur=null;async function P_(e,t){return ur?ur(e,t):mt(e,[],{model:t})}async function F_(e,t={}){if(t.signal?.aborted)return{session_id:e,ok:!1,failed:"aborted"};let s=I_(e);if(!s)return{session_id:e,ok:!1,skipped:"session-not-found"};let n=Ba(s.meta,{force:t.force});if(!n.eligible)return{session_id:e,ok:!1,skipped:n.reason};if(!ur&&!ce())return{session_id:e,ok:!1,failed:"claude-cli-missing"};let r=v_(s),o=t.model??pr,i=await P_(r,o);if(!i.success)return{session_id:e,ok:!1,failed:"claude-cli-error",exit_code:i.exitCode};let a=j_(i.stdout);if(!a)return{session_id:e,ok:!1,failed:"parse-failed",exit_code:i.exitCode};let l=U_(i.stdout),c=Fa({session_id:e,files_written:a.files_written,brands_mentioned:a.brands_mentioned,terms_introduced:a.terms_introduced,plan_ids_referenced:a.plan_ids_referenced,bug_signatures:a.bug_signatures,raw_extraction:{model:o,usage:l,raw_response_excerpt:i.stdout.slice(0,4e3)},extractor_version:Gt});return{session_id:e,ok:!0,index:c,usage:l}}function U_(e){try{let t=JSON.parse(e.trim());if(t&&typeof t=="object"&&t.usage){let s=t.usage,n={};return typeof s.input_tokens=="number"&&(n.input_tokens=s.input_tokens),typeof s.output_tokens=="number"&&(n.output_tokens=s.output_tokens),n}}catch{}return null}function B_(e={}){let t=_(),s=[],n=[];typeof e.projectId=="number"&&(s.push("s.project_id = ?"),n.push(e.projectId));let r=Math.max(1,Math.min(1e4,e.limit??1e3)),o=s.length?`WHERE ${s.join(" AND ")}`:"",i=t.prepare(`SELECT s.id,
1168
+ `)}function M_(e){return Array.isArray(e)&&e.every(t=>typeof t=="string")}function dr(e,t,s=!1){if(!Array.isArray(e))return[];let n=new Set,r=[];for(let o of e){if(typeof o!="string")continue;let i=s?o.trim().toLowerCase():o.trim();if(!(!i||i.length>256)&&!n.has(i)&&(n.add(i),r.push(i),r.length>=t))break}return r}function $_(e,t){if(!Array.isArray(e))return[];let s=new Set,n=[];for(let r of e){if(!r||typeof r!="object")continue;let o=r.term,i=r.freq;if(typeof o!="string")continue;let a=o.trim().toLowerCase();if(!a||a.length>128||s.has(a))continue;s.add(a);let l=typeof i=="number"&&Number.isFinite(i)&&i>0?Math.floor(i):1;if(n.push({term:a,frequency:l}),n.length>=t)break}return n}function D_(e,t){if(!Array.isArray(e))return[];let s=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n.error_type,o=n.snippet,i=n.file,a=typeof r=="string"&&r.trim().length>0?r.trim().slice(0,64):"unknown",l=typeof o=="string"?o.trim().replace(/\s+/g," ").slice(0,256):"";if(!l)continue;let c=typeof i=="string"&&i.trim().length>0?i.trim().slice(0,256):null,u=x_("sha256").update(`${a}::${l}`).digest("hex").slice(0,12);if(s.push({error_type:a,message_hash:u,snippet:l,file:c}),s.length>=t)break}return s}function j_(e){let t=e.trim();try{let m=JSON.parse(t);typeof m.result=="string"&&(t=m.result.trim())}catch{}t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let s=t.indexOf("{"),n=t.lastIndexOf("}");if(s===-1||n===-1||n<=s)return null;let r=t.slice(s,n+1),o;try{o=JSON.parse(r)}catch{return null}let i=dr(o.files_written,200),a=dr(o.brands_mentioned,C_),l=$_(o.terms_introduced,N_),c=dr(o.plan_ids_referenced,L_),u=D_(o.bug_signatures,O_);return i.length===0&&a.length===0&&l.length===0&&c.length===0&&u.length===0&&!M_(o.files_written)?null:{files_written:i,brands_mentioned:a,terms_introduced:l,plan_ids_referenced:c,bug_signatures:u}}var ur=null;async function P_(e,t){return ur?ur(e,t):mt(e,[],{model:t})}async function F_(e,t={}){if(t.signal?.aborted)return{session_id:e,ok:!1,failed:"aborted"};let s=I_(e);if(!s)return{session_id:e,ok:!1,skipped:"session-not-found"};let n=Ba(s.meta,{force:t.force});if(!n.eligible)return{session_id:e,ok:!1,skipped:n.reason};if(!ur&&!ce())return{session_id:e,ok:!1,failed:"claude-cli-missing"};let r=v_(s),o=t.model??pr,i=await P_(r,o);if(!i.success)return{session_id:e,ok:!1,failed:"claude-cli-error",exit_code:i.exitCode};let a=j_(i.stdout);if(!a)return{session_id:e,ok:!1,failed:"parse-failed",exit_code:i.exitCode};let l=U_(i.stdout),c=Fa({session_id:e,files_written:a.files_written,brands_mentioned:a.brands_mentioned,terms_introduced:a.terms_introduced,plan_ids_referenced:a.plan_ids_referenced,bug_signatures:a.bug_signatures,raw_extraction:{model:o,usage:l,raw_response_excerpt:i.stdout.slice(0,4e3)},extractor_version:Gt});return{session_id:e,ok:!0,index:c,usage:l}}function U_(e){try{let t=JSON.parse(e.trim());if(t&&typeof t=="object"&&t.usage){let s=t.usage,n={};return typeof s.input_tokens=="number"&&(n.input_tokens=s.input_tokens),typeof s.output_tokens=="number"&&(n.output_tokens=s.output_tokens),n}}catch{}return null}function B_(e={}){let t=_(),s=[],n=[];typeof e.projectId=="number"&&(s.push("s.project_id = ?"),n.push(e.projectId));let r=Math.max(1,Math.min(1e4,e.limit??1e3)),o=s.length?`WHERE ${s.join(" AND ")}`:"",i=t.prepare(`SELECT s.id,
1169
1169
  NULLIF(sa.alias, '') AS alias,
1170
1170
  s.auto_title,
1171
1171
  s.auto_title_source,
@@ -1178,11 +1178,11 @@ show full content: recall paste --show <id>
1178
1178
  LEFT JOIN projects p ON p.id = s.project_id
1179
1179
  ${o}
1180
1180
  ORDER BY COALESCE(s.started_at, ''), s.id`).all(...n),a=[],l=new Map;for(let c of i){let u={...c,alias_source:c.alias?"manual":null},p=Ba(u,{force:e.force});if(!p.eligible){let m=p.reason??"session-not-found";l.set(m,(l.get(m)??0)+1);continue}if(a.push(u),a.length>=r)break}return{eligible:a,skipped:l}}async function Ha(e={}){let t=B_({projectId:e.projectId,limit:e.limit,force:e.force}),s={total:t.eligible.length,processed:0,ok:0,failed:0,skipped:0,current_session_id:null,total_input_tokens:0,total_output_tokens:0};for(let r of t.skipped.values())s.skipped+=r;e.onProgress?.({...s});let n=[];for(let r of t.eligible){if(e.signal?.aborted)break;s.current_session_id=r.id,e.onProgress?.({...s});let o=await F_(r.id,{model:e.model,force:e.force,signal:e.signal});n.push(o),e.onResult?.(o),o.ok?s.ok+=1:o.skipped?s.skipped+=1:s.failed+=1,o.usage?.input_tokens&&(s.total_input_tokens+=o.usage.input_tokens),o.usage?.output_tokens&&(s.total_output_tokens+=o.usage.output_tokens),s.processed+=1,e.onProgress?.({...s})}return s.current_session_id=null,e.onProgress?.({...s}),{progress:s,results:n}}Je();async function Wa(e){if(!e.project){console.error("--project <name> is required."),process.exitCode=1;return}let t=he(e.project);if(!t){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}if(!ce()){console.error("claude CLI not found on PATH. Install Claude Code first, then re-run."),process.exitCode=1;return}let s=e.limit?Math.max(1,Number(e.limit)):200,n=e.model??pr;e.json||console.log(`Extracting Output Index \u2014 project "${t.name}" \u2014 extractor v${Gt} \u2014 model ${n} \u2014 up to ${s} sessions\u2026`);let r=Date.now(),o=-1,{progress:i,results:a}=await Ha({projectId:t.id,limit:s,force:e.force,model:n,onProgress:u=>{if(e.json||u.processed===o)return;o=u.processed;let p=u.total>0?` (${Math.round(u.processed/u.total*100)}%)`:"";process.stdout.write(`\r ${u.processed}/${u.total}${p} ok=${u.ok} failed=${u.failed} skipped=${u.skipped} in=${u.total_input_tokens} out=${u.total_output_tokens} `)}});e.json||process.stdout.write(`
1181
- `);let l=Number(((Date.now()-r)/1e3).toFixed(1)),c=i.total>0?Math.round(i.ok/i.total*1e3)/10:0;if(e.json){let u=a.filter(p=>!p.ok&&p.failed).map(p=>({session_id:p.session_id,failed:p.failed,exit_code:p.exit_code??null}));console.log(JSON.stringify({project:t.name,extractor_version:Gt,model:n,progress:i,acceptance_pct:c,failures:u.slice(0,20),elapsed_seconds:l},null,2))}else console.log(`Done in ${l}s \u2014 ok=${i.ok}/${i.total} (${c}%) failed=${i.failed} skipped=${i.skipped}`),console.log(`Token spend: input=${i.total_input_tokens} output=${i.total_output_tokens}`),i.total>0&&c<90?(console.log(` \u26A0 Phase D acceptance bar is 90% non-empty Output Index; actual ${c}%. Inspect failures and re-run.`),process.exitCode=1):i.total===0&&console.log(" \u24D8 No eligible sessions (all sessions were skipped or already extracted).")}T();zt();var Ds={citation:"same-project",similar:"same-project",skill_track:"same-project",bug_pattern:"cross-project",wiki_link:"cross-project",temporal_proximity:"same-project"},Q_=2,eh=.25,th=5,sh=60,nh=25;function Ms(e){return e.trim().toLowerCase()}function rh(e){let t=new Set;for(let s of e.files_written)t.add(`file:${Ms(s)}`);for(let s of e.brands_mentioned)t.add(`brand:${Ms(s)}`);for(let s of e.terms_introduced)t.add(`term:${Ms(s)}`);for(let s of e.plan_ids_referenced)t.add(`plan:${Ms(s)}`);return t}function oh(e){if(!Number.isFinite(e)||e<0)return 1;let t=Math.exp(-e/sh);return Math.max(.2,t)}function ih(e,t){if(!e||!t)return 0;let s=Date.parse(e),n=Date.parse(t);return!Number.isFinite(s)||!Number.isFinite(n)?0:Math.abs(n-s)/(1e3*60*60*24)}function ah(e){let t=Jt(e);return t?{session_id:t.session_id,files_written:t.files_written,brands_mentioned:t.brands_mentioned,terms_introduced:t.terms_introduced.map(s=>s.term),plan_ids_referenced:t.plan_ids_referenced}:null}function ch(e){return _().prepare(`SELECT s.id AS id, s.project_id AS project_id, s.started_at AS started_at
1181
+ `);let l=Number(((Date.now()-r)/1e3).toFixed(1)),c=i.total>0?Math.round(i.ok/i.total*1e3)/10:0;if(e.json){let u=a.filter(p=>!p.ok&&p.failed).map(p=>({session_id:p.session_id,failed:p.failed,exit_code:p.exit_code??null}));console.log(JSON.stringify({project:t.name,extractor_version:Gt,model:n,progress:i,acceptance_pct:c,failures:u.slice(0,20),elapsed_seconds:l},null,2))}else console.log(`Done in ${l}s \u2014 ok=${i.ok}/${i.total} (${c}%) failed=${i.failed} skipped=${i.skipped}`),console.log(`Token spend: input=${i.total_input_tokens} output=${i.total_output_tokens}`),i.total>0&&c<90?(console.log(` \u26A0 Phase D acceptance bar is 90% non-empty Output Index; actual ${c}%. Inspect failures and re-run.`),process.exitCode=1):i.total===0&&console.log(" \u24D8 No eligible sessions (all sessions were skipped or already extracted).")}T();zt();var $s={citation:"same-project",similar:"same-project",skill_track:"same-project",bug_pattern:"cross-project",wiki_link:"cross-project",temporal_proximity:"same-project"},Q_=2,eh=.25,th=5,sh=60,nh=25;function Ms(e){return e.trim().toLowerCase()}function rh(e){let t=new Set;for(let s of e.files_written)t.add(`file:${Ms(s)}`);for(let s of e.brands_mentioned)t.add(`brand:${Ms(s)}`);for(let s of e.terms_introduced)t.add(`term:${Ms(s)}`);for(let s of e.plan_ids_referenced)t.add(`plan:${Ms(s)}`);return t}function oh(e){if(!Number.isFinite(e)||e<0)return 1;let t=Math.exp(-e/sh);return Math.max(.2,t)}function ih(e,t){if(!e||!t)return 0;let s=Date.parse(e),n=Date.parse(t);return!Number.isFinite(s)||!Number.isFinite(n)?0:Math.abs(n-s)/(1e3*60*60*24)}function ah(e){let t=Jt(e);return t?{session_id:t.session_id,files_written:t.files_written,brands_mentioned:t.brands_mentioned,terms_introduced:t.terms_introduced.map(s=>s.term),plan_ids_referenced:t.plan_ids_referenced}:null}function ch(e){return _().prepare(`SELECT s.id AS id, s.project_id AS project_id, s.started_at AS started_at
1182
1182
  FROM sessions s
1183
1183
  JOIN session_output_index oi ON oi.session_id = s.id
1184
1184
  WHERE s.project_id = ?
1185
- ORDER BY COALESCE(s.started_at, ''), s.id`).all(e)}function lh(e,t){let s=new Map,n=new Map,r=new Map;for(let o of e){r.set(o.id,o.started_at);let i=t.get(o.id);if(!i)continue;let a=rh(i);if(a.size!==0){n.set(o.id,a);for(let l of a){let c=s.get(l);c?c.push(o.id):s.set(l,[o.id])}}}return{posting:s,vocab:n,startedAt:r}}function dh(e,t){let s=t.vocab.get(e),n=t.startedAt.get(e)??null;if(!s||!n)return[];let r=new Map;for(let i of s){let a=t.posting.get(i);if(a)for(let l of a){if(l===e)continue;let c=t.startedAt.get(l);if(!c||c>=n)continue;let u=r.get(l);u?u.push(i):r.set(l,[i])}}let o=[];for(let[i,a]of r){let l=a.length;if(l<Q_)continue;let c=t.startedAt.get(i)??null,u=ih(n,c),p=oh(u),m=Math.min(1,l/th*p);if(m<eh)continue;let f=a.slice(0,12);o.push({target_session_id:i,matched_terms:f,overlap:l,days_apart:Math.round(u*10)/10,recency:Math.round(p*1e3)/1e3,confidence:Math.round(m*1e3)/1e3})}return o.sort((i,a)=>a.confidence-i.confidence),o.slice(0,nh)}async function Za(e){if(Ds.citation!=="same-project")throw new Error("citation policy unexpectedly not same-project \u2014 refusing to run inference");let t=ch(e.projectId),s=new Map;for(let i of t){let a=ah(i.id);a&&s.set(i.id,a)}let n=lh(t,s),r={total_sessions:t.length,processed_sessions:0,suggestions_created:0,suggestions_skipped_existing:0,current_session_id:null};e.onProgress?.({...r});let o=[];for(let i of t){if(e.signal?.aborted)break;r.current_session_id=i.id,e.onProgress?.({...r});let a=dh(i.id,n);for(let l of a)try{let c=Qe({source_session_id:i.id,target_session_id:l.target_session_id,link_type:"citation",confidence:l.confidence,evidence:{matched_terms:l.matched_terms,overlap_count:l.overlap,recency:l.recency,days_apart:l.days_apart},inferred_by:"L2"});o.push(c.id),r.suggestions_created+=1}catch(c){console.error("[citation-inference] createSuggestion failed:",c)}r.processed_sessions+=1,e.onProgress?.({...r})}return r.current_session_id=null,e.onProgress?.({...r}),{progress:r,suggestion_ids:o}}async function Qa(e){if(!e.project){console.error("--project <name> is required."),process.exitCode=1;return}let t=he(e.project);if(!t){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}e.json||console.log(`Inferring citation suggestions \u2014 project "${t.name}"\u2026`);let s=Date.now(),n=-1,r=await Za({projectId:t.id,onProgress:i=>{if(e.json||i.processed_sessions===n)return;n=i.processed_sessions;let a=i.total_sessions>0?` (${Math.round(i.processed_sessions/i.total_sessions*100)}%)`:"";process.stdout.write(`\r ${i.processed_sessions}/${i.total_sessions} sessions${a} suggestions=${i.suggestions_created} `)}});e.json||process.stdout.write(`
1185
+ ORDER BY COALESCE(s.started_at, ''), s.id`).all(e)}function lh(e,t){let s=new Map,n=new Map,r=new Map;for(let o of e){r.set(o.id,o.started_at);let i=t.get(o.id);if(!i)continue;let a=rh(i);if(a.size!==0){n.set(o.id,a);for(let l of a){let c=s.get(l);c?c.push(o.id):s.set(l,[o.id])}}}return{posting:s,vocab:n,startedAt:r}}function dh(e,t){let s=t.vocab.get(e),n=t.startedAt.get(e)??null;if(!s||!n)return[];let r=new Map;for(let i of s){let a=t.posting.get(i);if(a)for(let l of a){if(l===e)continue;let c=t.startedAt.get(l);if(!c||c>=n)continue;let u=r.get(l);u?u.push(i):r.set(l,[i])}}let o=[];for(let[i,a]of r){let l=a.length;if(l<Q_)continue;let c=t.startedAt.get(i)??null,u=ih(n,c),p=oh(u),m=Math.min(1,l/th*p);if(m<eh)continue;let f=a.slice(0,12);o.push({target_session_id:i,matched_terms:f,overlap:l,days_apart:Math.round(u*10)/10,recency:Math.round(p*1e3)/1e3,confidence:Math.round(m*1e3)/1e3})}return o.sort((i,a)=>a.confidence-i.confidence),o.slice(0,nh)}async function Za(e){if($s.citation!=="same-project")throw new Error("citation policy unexpectedly not same-project \u2014 refusing to run inference");let t=ch(e.projectId),s=new Map;for(let i of t){let a=ah(i.id);a&&s.set(i.id,a)}let n=lh(t,s),r={total_sessions:t.length,processed_sessions:0,suggestions_created:0,suggestions_skipped_existing:0,current_session_id:null};e.onProgress?.({...r});let o=[];for(let i of t){if(e.signal?.aborted)break;r.current_session_id=i.id,e.onProgress?.({...r});let a=dh(i.id,n);for(let l of a)try{let c=Qe({source_session_id:i.id,target_session_id:l.target_session_id,link_type:"citation",confidence:l.confidence,evidence:{matched_terms:l.matched_terms,overlap_count:l.overlap,recency:l.recency,days_apart:l.days_apart},inferred_by:"L2"});o.push(c.id),r.suggestions_created+=1}catch(c){console.error("[citation-inference] createSuggestion failed:",c)}r.processed_sessions+=1,e.onProgress?.({...r})}return r.current_session_id=null,e.onProgress?.({...r}),{progress:r,suggestion_ids:o}}async function Qa(e){if(!e.project){console.error("--project <name> is required."),process.exitCode=1;return}let t=he(e.project);if(!t){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}e.json||console.log(`Inferring citation suggestions \u2014 project "${t.name}"\u2026`);let s=Date.now(),n=-1,r=await Za({projectId:t.id,onProgress:i=>{if(e.json||i.processed_sessions===n)return;n=i.processed_sessions;let a=i.total_sessions>0?` (${Math.round(i.processed_sessions/i.total_sessions*100)}%)`:"";process.stdout.write(`\r ${i.processed_sessions}/${i.total_sessions} sessions${a} suggestions=${i.suggestions_created} `)}});e.json||process.stdout.write(`
1186
1186
  `);let o=Number(((Date.now()-s)/1e3).toFixed(1));e.json?console.log(JSON.stringify({project:t.name,progress:r.progress,suggestion_count:r.suggestion_ids.length,sample_suggestion_ids:r.suggestion_ids.slice(0,25),elapsed_seconds:o},null,2)):(console.log(`Done in ${o}s \u2014 sessions=${r.progress.processed_sessions}/${r.progress.total_sessions} suggestions=${r.progress.suggestions_created}`),r.progress.total_sessions===0?console.log(` \u24D8 No sessions had a populated Output Index. Run \`recall extract-outputs --project ${t.name}\` first.`):r.progress.suggestions_created===0?console.log(" \u24D8 No suggestions met the confidence threshold. This is expected on small corpora; the Output Index needs more shared vocabulary across sessions for citations to surface."):console.log(" Review the queue at GET /api/links/suggestions?status=pending (Phase F UI ships the queue review)."))}import{existsSync as xh,readFileSync as Rh}from"node:fs";import{join as kh}from"node:path";T();zt();var uh=/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/gi,ph=[/\bv\d+\.\d+(?:\.[A-Za-z]+)?\b/g,/\bPhase\s+[A-Ha-h]\b/g,/\bL\d+\b/g,/MASTER-PLAN-[A-Za-z-]+/g],mh=.95,gh=.85,fh=.7,Er=50,_h=50;function hh(e){if(!e)return[];let t=new Set,s=[],n=e.match(uh);if(!n)return s;for(let r of n){let o=r.toLowerCase();if(!t.has(o)&&(t.add(o),s.push(o),s.length>=Er))break}return s}function Eh(e){if(!e)return[];let t=new Set,s=[];for(let n of ph){n.lastIndex=0;let r=e.match(n);if(r){for(let o of r){let i=o.trim().toLowerCase().replace(/\s+/g," ");if(!(!i||i.length>64)&&!t.has(i)&&(t.add(i),s.push(i),s.length>=Er))break}if(s.length>=Er)break}}return s}function br(e){let t=_();return typeof e=="number"?t.prepare("SELECT id, project_id FROM sessions WHERE project_id = ?").all(e):t.prepare("SELECT id, project_id FROM sessions").all()}function ec(e){let t=_();return typeof e=="number"?t.prepare(`SELECT m.uuid AS message_uuid, m.session_id, m.content_text,
1187
1187
  s.project_id
1188
1188
  FROM messages m
@@ -1201,7 +1201,7 @@ show full content: recall paste --show <id>
1201
1201
  oi.plan_ids_referenced AS plan_ids_json
1202
1202
  FROM session_output_index oi
1203
1203
  JOIN sessions s ON s.id = oi.session_id
1204
- ${s}`).all(...n)}function Sh(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(s=>typeof s=="string")}catch{}return[]}function yh(e={}){if(Ds.citation!=="same-project")throw new Error("citation policy unexpectedly not same-project");let t=br(e.projectId),s=new Set(t.map(o=>o.id)),n=new Map;for(let o of t)n.set(o.id,o.project_id);let r=0;for(let o of ec(e.projectId)){if(e.signal?.aborted)break;let i=hh(o.content_text);if(i.length===0)continue;let a=n.get(o.session_id);if(a!==void 0)for(let l of i){if(l===o.session_id)continue;let c=n.get(l);if(!(c===void 0&&!s.has(l))&&!(c!==void 0&&a!==void 0&&c!==a))try{Qe({source_session_id:o.session_id,target_session_id:l,link_type:"citation",confidence:mh,evidence:{matched_uuid:l,source_message_uuid:o.message_uuid,scanner:"uuid-ref"},inferred_by:"L1"}),r+=1}catch{}}}return{created:r}}function Th(e={}){let t=bh(e.projectId);if(t.length===0)return{created:0};let s=new Map;for(let a of t){let l=Sh(a.plan_ids_json);for(let c of l){let u=c.trim().toLowerCase();if(!u)continue;let p=s.get(u);p?p.push({id:a.session_id,project_id:a.project_id}):s.set(u,[{id:a.session_id,project_id:a.project_id}])}}if(s.size===0)return{created:0};let n=br(e.projectId),r=new Map;for(let a of n)r.set(a.id,a.project_id);let o=0,i=new Map;for(let a of ec(e.projectId)){if(e.signal?.aborted)break;let l=Eh(a.content_text);if(l.length===0)continue;let c=r.get(a.session_id);if(c!==void 0)for(let u of l){let p=s.get(u);if(p)for(let m of p){if(m.id===a.session_id||m.project_id!==c)continue;let f=i.get(a.session_id);f||(f=new Map,i.set(a.session_id,f));let g=f.get(m.id);g||(g=new Set,f.set(m.id,g)),g.add(u)}}}for(let[a,l]of i)for(let[c,u]of l)try{Qe({source_session_id:a,target_session_id:c,link_type:"citation",confidence:gh,evidence:{matched_plan_ids:Array.from(u).slice(0,12),scanner:"plan-ref"},inferred_by:"L1"}),o+=1}catch{}return{created:o}}function wh(e){if(Ds.skill_track!=="same-project")throw new Error("skill_track policy unexpectedly not same-project");if(!e.registry||!Array.isArray(e.registry.terminals))return{created:0};let t=br(e.projectId),s=new Map,n=new Map;if(t.length>0){let i=_(),a=t.map(u=>u.id),l=a.map(()=>"?").join(","),c=i.prepare(`SELECT id, started_at FROM sessions WHERE id IN (${l})`).all(...a);for(let u of c)n.set(u.id,u.started_at)}for(let i of t)s.set(i.id,i.project_id);let r=new Map;for(let i of e.registry.terminals){let a=e.registry.sessions_by_pid[String(i.shell_pid)]??[];if(a.length===0)continue;let l=`${i.cwd??"<no-cwd>"}::${i.tab_name}`,c=r.get(l);c||(c=new Set,r.set(l,c));for(let u of a)c.add(u)}let o=0;for(let[,i]of r){if(i.size<2)continue;let a=new Map;for(let l of i){let c=s.get(l);if(c===void 0||typeof e.projectId=="number"&&c!==e.projectId)continue;let u=a.get(c);u||(u=[],a.set(c,u)),u.push(l)}for(let[,l]of a){if(l.length<2)continue;l.sort((u,p)=>{let m=n.get(u)??"",f=n.get(p)??"";return m<f?-1:m>f?1:u<p?-1:1});let c=0;for(let u=1;u<l.length&&!e.signal?.aborted;u++)for(let p=0;p<u&&!(c>=_h);p++)try{Qe({source_session_id:l[u],target_session_id:l[p],link_type:"skill_track",confidence:fh,evidence:{shared_tab_signature:!0,bucket_size:l.length,scanner:"tab-carry"},inferred_by:"L1"}),o+=1,c+=1}catch{}}}return{created:o}}function tc(e={}){let t=yh(e);if(e.signal?.aborted)return{uuid_refs_created:t.created,plan_refs_created:0,tab_carry_created:0,total:t.created};let s=Th(e);if(e.signal?.aborted)return{uuid_refs_created:t.created,plan_refs_created:s.created,tab_carry_created:0,total:t.created+s.created};let n=e.registry?wh({projectId:e.projectId,signal:e.signal,registry:e.registry}):{created:0};return{uuid_refs_created:t.created,plan_refs_created:s.created,tab_carry_created:n.created,total:t.created+s.created+n.created}}j();function Nh(){let e=kh(x,"terminals.json");if(xh(e))try{let t=Rh(e,"utf8"),s=JSON.parse(t);if(!Array.isArray(s.terminals))return;let n=s.terminals.filter(o=>typeof o.shell_pid=="number"&&typeof o.tab_name=="string").map(o=>({shell_pid:o.shell_pid,tab_name:o.tab_name,cwd:o.cwd??null})),r=s.sessions_by_pid??{};return{terminals:n,sessions_by_pid:r}}catch{return}}async function sc(e){let t=null;if(e.project&&(t=he(e.project),!t)){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}let s=Nh(),n=t?`project "${t.name}"`:"all projects";e.json||console.log(`L1 deterministic inference \u2014 ${n} \u2014 `+(s?`(tab registry has ${s.terminals.length} entries)`:"(no tab registry; tab-carry scanner skipped)"));let r=Date.now(),o=tc({projectId:t?.id,registry:s}),i=Number(((Date.now()-r)/1e3).toFixed(2));e.json?console.log(JSON.stringify({project:t?.name??null,...o,elapsed_seconds:i},null,2)):(console.log(`Done in ${i}s \u2014 uuid_refs=${o.uuid_refs_created} plan_refs=${o.plan_refs_created} tab_carry=${o.tab_carry_created} (total=${o.total})`),o.total===0?console.log(" \u24D8 Zero new suggestions. This is expected when L1 has already run against this corpus or when the project has no inter-session references. (Tombstones from prior reject decisions also keep re-runs idempotent.)"):console.log(" Review the queue at GET /api/links/suggestions?status=pending (or the web UI at #view=suggestions)."))}T();Je();zt();function Sr(e){if(!e||e.length===0)return 0;let t=1,s=0;for(let n of e){if(!Number.isFinite(n))continue;let r=Math.max(0,Math.min(1,n));if(t*=1-r,s+=1,t<=1e-9)return 1}return s===0?0:Math.round((1-t)*1e4)/1e4}var Tr="claude-haiku-4-5-20251001",$s=.4,wr=.95,nc=30,rc=240,Ch=new Set(["CITATION","SIMILAR","SKILL_TRACK","UNRELATED"]),Lh={CITATION:"citation",SIMILAR:"similar",SKILL_TRACK:"skill_track"};function ac(e){return _().prepare(`SELECT s.id,
1204
+ ${s}`).all(...n)}function Sh(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(s=>typeof s=="string")}catch{}return[]}function yh(e={}){if($s.citation!=="same-project")throw new Error("citation policy unexpectedly not same-project");let t=br(e.projectId),s=new Set(t.map(o=>o.id)),n=new Map;for(let o of t)n.set(o.id,o.project_id);let r=0;for(let o of ec(e.projectId)){if(e.signal?.aborted)break;let i=hh(o.content_text);if(i.length===0)continue;let a=n.get(o.session_id);if(a!==void 0)for(let l of i){if(l===o.session_id)continue;let c=n.get(l);if(!(c===void 0&&!s.has(l))&&!(c!==void 0&&a!==void 0&&c!==a))try{Qe({source_session_id:o.session_id,target_session_id:l,link_type:"citation",confidence:mh,evidence:{matched_uuid:l,source_message_uuid:o.message_uuid,scanner:"uuid-ref"},inferred_by:"L1"}),r+=1}catch{}}}return{created:r}}function Th(e={}){let t=bh(e.projectId);if(t.length===0)return{created:0};let s=new Map;for(let a of t){let l=Sh(a.plan_ids_json);for(let c of l){let u=c.trim().toLowerCase();if(!u)continue;let p=s.get(u);p?p.push({id:a.session_id,project_id:a.project_id}):s.set(u,[{id:a.session_id,project_id:a.project_id}])}}if(s.size===0)return{created:0};let n=br(e.projectId),r=new Map;for(let a of n)r.set(a.id,a.project_id);let o=0,i=new Map;for(let a of ec(e.projectId)){if(e.signal?.aborted)break;let l=Eh(a.content_text);if(l.length===0)continue;let c=r.get(a.session_id);if(c!==void 0)for(let u of l){let p=s.get(u);if(p)for(let m of p){if(m.id===a.session_id||m.project_id!==c)continue;let f=i.get(a.session_id);f||(f=new Map,i.set(a.session_id,f));let g=f.get(m.id);g||(g=new Set,f.set(m.id,g)),g.add(u)}}}for(let[a,l]of i)for(let[c,u]of l)try{Qe({source_session_id:a,target_session_id:c,link_type:"citation",confidence:gh,evidence:{matched_plan_ids:Array.from(u).slice(0,12),scanner:"plan-ref"},inferred_by:"L1"}),o+=1}catch{}return{created:o}}function wh(e){if($s.skill_track!=="same-project")throw new Error("skill_track policy unexpectedly not same-project");if(!e.registry||!Array.isArray(e.registry.terminals))return{created:0};let t=br(e.projectId),s=new Map,n=new Map;if(t.length>0){let i=_(),a=t.map(u=>u.id),l=a.map(()=>"?").join(","),c=i.prepare(`SELECT id, started_at FROM sessions WHERE id IN (${l})`).all(...a);for(let u of c)n.set(u.id,u.started_at)}for(let i of t)s.set(i.id,i.project_id);let r=new Map;for(let i of e.registry.terminals){let a=e.registry.sessions_by_pid[String(i.shell_pid)]??[];if(a.length===0)continue;let l=`${i.cwd??"<no-cwd>"}::${i.tab_name}`,c=r.get(l);c||(c=new Set,r.set(l,c));for(let u of a)c.add(u)}let o=0;for(let[,i]of r){if(i.size<2)continue;let a=new Map;for(let l of i){let c=s.get(l);if(c===void 0||typeof e.projectId=="number"&&c!==e.projectId)continue;let u=a.get(c);u||(u=[],a.set(c,u)),u.push(l)}for(let[,l]of a){if(l.length<2)continue;l.sort((u,p)=>{let m=n.get(u)??"",f=n.get(p)??"";return m<f?-1:m>f?1:u<p?-1:1});let c=0;for(let u=1;u<l.length&&!e.signal?.aborted;u++)for(let p=0;p<u&&!(c>=_h);p++)try{Qe({source_session_id:l[u],target_session_id:l[p],link_type:"skill_track",confidence:fh,evidence:{shared_tab_signature:!0,bucket_size:l.length,scanner:"tab-carry"},inferred_by:"L1"}),o+=1,c+=1}catch{}}}return{created:o}}function tc(e={}){let t=yh(e);if(e.signal?.aborted)return{uuid_refs_created:t.created,plan_refs_created:0,tab_carry_created:0,total:t.created};let s=Th(e);if(e.signal?.aborted)return{uuid_refs_created:t.created,plan_refs_created:s.created,tab_carry_created:0,total:t.created+s.created};let n=e.registry?wh({projectId:e.projectId,signal:e.signal,registry:e.registry}):{created:0};return{uuid_refs_created:t.created,plan_refs_created:s.created,tab_carry_created:n.created,total:t.created+s.created+n.created}}j();function Nh(){let e=kh(x,"terminals.json");if(xh(e))try{let t=Rh(e,"utf8"),s=JSON.parse(t);if(!Array.isArray(s.terminals))return;let n=s.terminals.filter(o=>typeof o.shell_pid=="number"&&typeof o.tab_name=="string").map(o=>({shell_pid:o.shell_pid,tab_name:o.tab_name,cwd:o.cwd??null})),r=s.sessions_by_pid??{};return{terminals:n,sessions_by_pid:r}}catch{return}}async function sc(e){let t=null;if(e.project&&(t=he(e.project),!t)){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}let s=Nh(),n=t?`project "${t.name}"`:"all projects";e.json||console.log(`L1 deterministic inference \u2014 ${n} \u2014 `+(s?`(tab registry has ${s.terminals.length} entries)`:"(no tab registry; tab-carry scanner skipped)"));let r=Date.now(),o=tc({projectId:t?.id,registry:s}),i=Number(((Date.now()-r)/1e3).toFixed(2));e.json?console.log(JSON.stringify({project:t?.name??null,...o,elapsed_seconds:i},null,2)):(console.log(`Done in ${i}s \u2014 uuid_refs=${o.uuid_refs_created} plan_refs=${o.plan_refs_created} tab_carry=${o.tab_carry_created} (total=${o.total})`),o.total===0?console.log(" \u24D8 Zero new suggestions. This is expected when L1 has already run against this corpus or when the project has no inter-session references. (Tombstones from prior reject decisions also keep re-runs idempotent.)"):console.log(" Review the queue at GET /api/links/suggestions?status=pending (or the web UI at #view=suggestions)."))}T();Je();zt();function Sr(e){if(!e||e.length===0)return 0;let t=1,s=0;for(let n of e){if(!Number.isFinite(n))continue;let r=Math.max(0,Math.min(1,n));if(t*=1-r,s+=1,t<=1e-9)return 1}return s===0?0:Math.round((1-t)*1e4)/1e4}var Tr="claude-haiku-4-5-20251001",Ds=.4,wr=.95,nc=30,rc=240,Ch=new Set(["CITATION","SIMILAR","SKILL_TRACK","UNRELATED"]),Lh={CITATION:"citation",SIMILAR:"similar",SKILL_TRACK:"skill_track"};function ac(e){return _().prepare(`SELECT s.id,
1205
1205
  s.source_session_id,
1206
1206
  s.target_session_id,
1207
1207
  s.link_type,
@@ -1220,9 +1220,9 @@ show full content: recall paste --show <id>
1220
1220
  FROM sessions s
1221
1221
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1222
1222
  LEFT JOIN projects p ON p.id = s.project_id
1223
- WHERE s.id IN (${s})`).all(...e),r=new Map;for(let o of n)r.set(o.id,o);return r}function oc(e,t){if(!e)return t.slice(0,8);let s=e.first_user_message?e.first_user_message.slice(0,80):null;return e.alias??e.auto_title??s??t.slice(0,8)}function ic(e){try{return JSON.parse(e)}catch{return e}}function Ah(e){let t=e.minConfidence??$s,s=Math.max(1,Math.min(500,e.limit??100)),n=ac(e.projectId);if(n.length===0)return[];let r=new Map,o=new Map;for(let c of n){let u=`${c.source_session_id}|${c.target_session_id}|${c.link_type}`,p=o.get(u);p||(p={source_session_id:c.source_session_id,target_session_id:c.target_session_id,link_type:c.link_type,layers:[]},o.set(u,p));let m=p.layers.find(f=>f.inferred_by===c.inferred_by);m?(m.suggestion_ids.push(c.id),c.confidence>m.confidence&&(m.confidence=c.confidence,m.evidence=ic(c.evidence))):p.layers.push({inferred_by:c.inferred_by,link_type:c.link_type,confidence:c.confidence,evidence:ic(c.evidence),suggestion_ids:[c.id]})}let i=new Set;for(let c of o.values())i.add(c.source_session_id),i.add(c.target_session_id);let a=Oh(Array.from(i)),l=[];for(let c of o.values()){let u=Sr(c.layers.map(f=>f.confidence));if(u<t)continue;let p=a.get(c.source_session_id),m=a.get(c.target_session_id);l.push({source_session_id:c.source_session_id,target_session_id:c.target_session_id,primary_link_type:c.link_type,combined_confidence:u,layers:c.layers,source_title:oc(p,c.source_session_id),target_title:oc(m,c.target_session_id),source_project:p?.project??null})}return l.sort((c,u)=>u.combined_confidence-c.combined_confidence),l.slice(0,s)}function Ih(e){let t;try{t=JSON.stringify(e)}catch{t=String(e)}return t.length>rc&&(t=t.slice(0,rc)+"\u2026"),t}function vh(e){let t=["You are classifying candidate session-pair relationships for a developer knowledge graph.","","Categories:","- CITATION: the source session explicitly references content/decisions from the target (a previous session).","- SIMILAR: same subject matter, but neither cites the other directly.","- SKILL_TRACK: same person doing the same kind of work \u2014 same skill, different tasks.","- UNRELATED: shared evidence is coincidental; no real relationship.","","Use UNRELATED with low confidence when evidence is weak or contradictory.","Output a SINGLE JSON object on one line, no markdown fences, no commentary:",'{"classifications":[{"i":0,"label":"CITATION","conf":0.85,"why":"<<=25 words>"},...]}',"",`Pairs (${e.length}):`];return e.forEach((s,n)=>{t.push(""),t.push(`[${n}] B="${(s.source_title??"").slice(0,80)}" [${s.source_session_id.slice(0,8)}] -> A="${(s.target_title??"").slice(0,80)}" [${s.target_session_id.slice(0,8)}]`),t.push(` primary_type: ${s.primary_link_type}`),t.push(` combined_conf: ${s.combined_confidence.toFixed(3)}`);for(let r of s.layers)t.push(` ${r.inferred_by} ${r.link_type} conf=${r.confidence.toFixed(2)} ev=${Ih(r.evidence)}`)}),t.join(`
1224
- `)}var yr=null;async function Mh(e,t){return yr?yr(e,t):mt(e,[],{model:t})}function Dh(e){try{let t=JSON.parse(e.trim());return{input_tokens:t?.usage?.input_tokens??0,output_tokens:t?.usage?.output_tokens??0}}catch{return{input_tokens:0,output_tokens:0}}}function $h(e){let t=e.trim();try{let i=JSON.parse(t);typeof i.result=="string"&&(t=i.result.trim())}catch{}t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let s=t.indexOf("{"),n=t.lastIndexOf("}");if(s===-1||n===-1||n<=s)return null;let r;try{r=JSON.parse(t.slice(s,n+1))}catch{return null}if(!Array.isArray(r.classifications))return null;let o=[];for(let i of r.classifications){if(!i||typeof i!="object")continue;let a=i,l=typeof a.i=="number"?a.i:typeof a.pair_index=="number"?a.pair_index:NaN;if(!Number.isInteger(l)||l<0)continue;let c=typeof a.label=="string"?a.label.toUpperCase():"";if(!Ch.has(c))continue;let u=typeof a.conf=="number"?a.conf:typeof a.confidence=="number"?a.confidence:NaN;if(!Number.isFinite(u))continue;let p=Math.max(0,Math.min(1,u)),m=typeof a.why=="string"?a.why.trim().slice(0,200):typeof a.reason=="string"?a.reason.trim().slice(0,200):"";o.push({pair_index:l,label:c,confidence:p,reason:m})}return o}async function cc(e){let t={candidates_total:0,candidates_after_filter:0,classified:0,suggestions_created:0,links_promoted:0,total_input_tokens:0,total_output_tokens:0,failures:[]};if(!yr&&!ce())return t.failures.push({batch_index:-1,error:"claude CLI not available on PATH"}),t;let s=Ah({projectId:e.projectId,minConfidence:e.minConfidence??$s,limit:e.limit??100});t.candidates_after_filter=s.length;let n=ac(e.projectId),r=new Set;for(let a of n)r.add(`${a.source_session_id}|${a.target_session_id}|${a.link_type}`);if(t.candidates_total=r.size,s.length===0)return t;let o=e.model??Tr,i=e.autoPromoteThreshold??wr;for(let a=0,l=0;a<s.length&&!e.signal?.aborted;a+=nc,l+=1){let c=s.slice(a,a+nc);e.onBatchStart?.({batch:l,pairs:c.length});let u=vh(c),p=await Mh(u,o);if(!p.success){t.failures.push({batch_index:l,error:`claude CLI exited ${p.exitCode}: ${p.stderr.slice(0,200)}`});continue}let m=$h(p.stdout);if(!m){t.failures.push({batch_index:l,error:"parse-failed"});continue}let f=Dh(p.stdout);t.total_input_tokens+=f.input_tokens,t.total_output_tokens+=f.output_tokens;for(let g of m){if(g.pair_index>=c.length)continue;let h=c[g.pair_index];if(t.classified+=1,g.label==="UNRELATED")continue;let E=Lh[g.label];if(E)try{let b=Qe({source_session_id:h.source_session_id,target_session_id:h.target_session_id,link_type:E,confidence:g.confidence,evidence:{l4_label:g.label,l4_reason:g.reason,primary_type_l1_l2_l3:h.primary_link_type,combined_pre_l4:h.combined_confidence,scanner:"l4-llm",model:o},inferred_by:"L4"});if(t.suggestions_created+=1,e.autoPromote){let S=h.layers.map(R=>R.confidence);if(S.push(g.confidence),Sr(S)>=i)try{Ka(b.id,"approved",{source:"auto"}),t.links_promoted+=1}catch{}}}catch{}}}return t}Je();var jh=1e3;function Ph(e){let t=e.minConf?Math.max(0,Math.min(1,Number(e.minConf))):$s,s=e.autoPromoteThreshold!==void 0?Math.max(0,Math.min(1,Number(e.autoPromoteThreshold))):wr,n=e.limit?Math.max(1,Number(e.limit)):jh,r=e.model??Tr,o=!!e.autoPromote||e.autoPromoteThreshold!==void 0;return{minConfidence:t,autoPromoteThreshold:s,limit:n,model:r,autoPromote:o}}async function lc(e){if(!e.project){console.error("--project <name> is required."),process.exitCode=1;return}let t=he(e.project);if(!t){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}if(!ce()){console.error("claude CLI not found on PATH. Install Claude Code first, then re-run."),process.exitCode=1;return}let{minConfidence:s,autoPromoteThreshold:n,limit:r,model:o,autoPromote:i}=Ph(e);e.json||console.log(`L4 inference \u2014 project "${t.name}" \u2014 model ${o} \u2014 pre-filter conf \u2265 ${s} \u2014 limit ${r} \u2014 auto-promote ${i?`ON (\u2265 ${n})`:"OFF"}`);let a=Date.now(),l=await cc({projectId:t.id,minConfidence:s,limit:r,autoPromote:i,autoPromoteThreshold:n,model:o,onBatchStart:u=>{e.json||process.stdout.write(`\r batch ${u.batch} (${u.pairs} pairs)\u2026 `)}});e.json||process.stdout.write(`
1225
- `);let c=Number(((Date.now()-a)/1e3).toFixed(1));if(e.json)console.log(JSON.stringify({project:t.name,model:o,pre_filter_threshold:s,auto_promote:i,auto_promote_threshold:i?n:null,...l,elapsed_seconds:c},null,2));else{if(console.log(`Done in ${c}s \u2014 pairs=${l.candidates_after_filter}/${l.candidates_total} classified=${l.classified} suggestions=${l.suggestions_created} promoted=${l.links_promoted} failures=${l.failures.length}`),console.log(`Token spend: input=${l.total_input_tokens} output=${l.total_output_tokens}`),l.failures.length>0)for(let u of l.failures.slice(0,3))console.log(` \u26A0 batch ${u.batch_index}: ${u.error}`);l.suggestions_created>0?console.log(" Review the new L4 suggestions at #view=suggestions (filter by inferred_by=L4)."):l.candidates_after_filter===0&&console.log(` \u24D8 No pairs cleared the pre-filter (combined conf \u2265 ${s}). Lower --min-conf to widen the batch, or run more L1/L2/L3 inference first.`)}}T();import{createHash as Gh}from"node:crypto";T();j();import{writeFileSync as Fh,readFileSync as LC,existsSync as Uh,mkdirSync as Bh,readdirSync as OC,unlinkSync as AC}from"node:fs";import{join as dc}from"node:path";import{randomUUID as Hh}from"node:crypto";var xr=dc(x,"bug-patterns");function Wh(){P(),Uh(xr)||Bh(xr,{recursive:!0})}function js(e){return{id:e.id,signature_hash:e.signature_hash,example_message:e.example_message,occurrence_count:e.occurrence_count,first_seen_at:e.first_seen_at,last_seen_at:e.last_seen_at,resolved_in_session_id:e.resolved_in_session_id,fix_summary:e.fix_summary}}function Xh(e){return{cluster_id:e.cluster_id,session_id:e.session_id,matched_at:e.matched_at}}function uc(e){if(!e.signature_hash)throw new Error("signature_hash is required");if(!e.example_message)throw new Error("example_message is required");if(!Array.isArray(e.member_session_ids)||e.member_session_ids.length===0)throw new Error("at least one member_session_id is required");let t=_(),s=new Date().toISOString(),n=e.id??Hh(),r=e.first_seen_at??s,o=e.last_seen_at??s,i=Array.from(new Set(e.member_session_ids));t.transaction(()=>{t.prepare(`INSERT INTO bug_pattern_clusters
1223
+ WHERE s.id IN (${s})`).all(...e),r=new Map;for(let o of n)r.set(o.id,o);return r}function oc(e,t){if(!e)return t.slice(0,8);let s=e.first_user_message?e.first_user_message.slice(0,80):null;return e.alias??e.auto_title??s??t.slice(0,8)}function ic(e){try{return JSON.parse(e)}catch{return e}}function Ah(e){let t=e.minConfidence??Ds,s=Math.max(1,Math.min(500,e.limit??100)),n=ac(e.projectId);if(n.length===0)return[];let r=new Map,o=new Map;for(let c of n){let u=`${c.source_session_id}|${c.target_session_id}|${c.link_type}`,p=o.get(u);p||(p={source_session_id:c.source_session_id,target_session_id:c.target_session_id,link_type:c.link_type,layers:[]},o.set(u,p));let m=p.layers.find(f=>f.inferred_by===c.inferred_by);m?(m.suggestion_ids.push(c.id),c.confidence>m.confidence&&(m.confidence=c.confidence,m.evidence=ic(c.evidence))):p.layers.push({inferred_by:c.inferred_by,link_type:c.link_type,confidence:c.confidence,evidence:ic(c.evidence),suggestion_ids:[c.id]})}let i=new Set;for(let c of o.values())i.add(c.source_session_id),i.add(c.target_session_id);let a=Oh(Array.from(i)),l=[];for(let c of o.values()){let u=Sr(c.layers.map(f=>f.confidence));if(u<t)continue;let p=a.get(c.source_session_id),m=a.get(c.target_session_id);l.push({source_session_id:c.source_session_id,target_session_id:c.target_session_id,primary_link_type:c.link_type,combined_confidence:u,layers:c.layers,source_title:oc(p,c.source_session_id),target_title:oc(m,c.target_session_id),source_project:p?.project??null})}return l.sort((c,u)=>u.combined_confidence-c.combined_confidence),l.slice(0,s)}function Ih(e){let t;try{t=JSON.stringify(e)}catch{t=String(e)}return t.length>rc&&(t=t.slice(0,rc)+"\u2026"),t}function vh(e){let t=["You are classifying candidate session-pair relationships for a developer knowledge graph.","","Categories:","- CITATION: the source session explicitly references content/decisions from the target (a previous session).","- SIMILAR: same subject matter, but neither cites the other directly.","- SKILL_TRACK: same person doing the same kind of work \u2014 same skill, different tasks.","- UNRELATED: shared evidence is coincidental; no real relationship.","","Use UNRELATED with low confidence when evidence is weak or contradictory.","Output a SINGLE JSON object on one line, no markdown fences, no commentary:",'{"classifications":[{"i":0,"label":"CITATION","conf":0.85,"why":"<<=25 words>"},...]}',"",`Pairs (${e.length}):`];return e.forEach((s,n)=>{t.push(""),t.push(`[${n}] B="${(s.source_title??"").slice(0,80)}" [${s.source_session_id.slice(0,8)}] -> A="${(s.target_title??"").slice(0,80)}" [${s.target_session_id.slice(0,8)}]`),t.push(` primary_type: ${s.primary_link_type}`),t.push(` combined_conf: ${s.combined_confidence.toFixed(3)}`);for(let r of s.layers)t.push(` ${r.inferred_by} ${r.link_type} conf=${r.confidence.toFixed(2)} ev=${Ih(r.evidence)}`)}),t.join(`
1224
+ `)}var yr=null;async function Mh(e,t){return yr?yr(e,t):mt(e,[],{model:t})}function $h(e){try{let t=JSON.parse(e.trim());return{input_tokens:t?.usage?.input_tokens??0,output_tokens:t?.usage?.output_tokens??0}}catch{return{input_tokens:0,output_tokens:0}}}function Dh(e){let t=e.trim();try{let i=JSON.parse(t);typeof i.result=="string"&&(t=i.result.trim())}catch{}t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let s=t.indexOf("{"),n=t.lastIndexOf("}");if(s===-1||n===-1||n<=s)return null;let r;try{r=JSON.parse(t.slice(s,n+1))}catch{return null}if(!Array.isArray(r.classifications))return null;let o=[];for(let i of r.classifications){if(!i||typeof i!="object")continue;let a=i,l=typeof a.i=="number"?a.i:typeof a.pair_index=="number"?a.pair_index:NaN;if(!Number.isInteger(l)||l<0)continue;let c=typeof a.label=="string"?a.label.toUpperCase():"";if(!Ch.has(c))continue;let u=typeof a.conf=="number"?a.conf:typeof a.confidence=="number"?a.confidence:NaN;if(!Number.isFinite(u))continue;let p=Math.max(0,Math.min(1,u)),m=typeof a.why=="string"?a.why.trim().slice(0,200):typeof a.reason=="string"?a.reason.trim().slice(0,200):"";o.push({pair_index:l,label:c,confidence:p,reason:m})}return o}async function cc(e){let t={candidates_total:0,candidates_after_filter:0,classified:0,suggestions_created:0,links_promoted:0,total_input_tokens:0,total_output_tokens:0,failures:[]};if(!yr&&!ce())return t.failures.push({batch_index:-1,error:"claude CLI not available on PATH"}),t;let s=Ah({projectId:e.projectId,minConfidence:e.minConfidence??Ds,limit:e.limit??100});t.candidates_after_filter=s.length;let n=ac(e.projectId),r=new Set;for(let a of n)r.add(`${a.source_session_id}|${a.target_session_id}|${a.link_type}`);if(t.candidates_total=r.size,s.length===0)return t;let o=e.model??Tr,i=e.autoPromoteThreshold??wr;for(let a=0,l=0;a<s.length&&!e.signal?.aborted;a+=nc,l+=1){let c=s.slice(a,a+nc);e.onBatchStart?.({batch:l,pairs:c.length});let u=vh(c),p=await Mh(u,o);if(!p.success){t.failures.push({batch_index:l,error:`claude CLI exited ${p.exitCode}: ${p.stderr.slice(0,200)}`});continue}let m=Dh(p.stdout);if(!m){t.failures.push({batch_index:l,error:"parse-failed"});continue}let f=$h(p.stdout);t.total_input_tokens+=f.input_tokens,t.total_output_tokens+=f.output_tokens;for(let g of m){if(g.pair_index>=c.length)continue;let h=c[g.pair_index];if(t.classified+=1,g.label==="UNRELATED")continue;let E=Lh[g.label];if(E)try{let b=Qe({source_session_id:h.source_session_id,target_session_id:h.target_session_id,link_type:E,confidence:g.confidence,evidence:{l4_label:g.label,l4_reason:g.reason,primary_type_l1_l2_l3:h.primary_link_type,combined_pre_l4:h.combined_confidence,scanner:"l4-llm",model:o},inferred_by:"L4"});if(t.suggestions_created+=1,e.autoPromote){let S=h.layers.map(R=>R.confidence);if(S.push(g.confidence),Sr(S)>=i)try{Ka(b.id,"approved",{source:"auto"}),t.links_promoted+=1}catch{}}}catch{}}}return t}Je();var jh=1e3;function Ph(e){let t=e.minConf?Math.max(0,Math.min(1,Number(e.minConf))):Ds,s=e.autoPromoteThreshold!==void 0?Math.max(0,Math.min(1,Number(e.autoPromoteThreshold))):wr,n=e.limit?Math.max(1,Number(e.limit)):jh,r=e.model??Tr,o=!!e.autoPromote||e.autoPromoteThreshold!==void 0;return{minConfidence:t,autoPromoteThreshold:s,limit:n,model:r,autoPromote:o}}async function lc(e){if(!e.project){console.error("--project <name> is required."),process.exitCode=1;return}let t=he(e.project);if(!t){console.error(`Project "${e.project}" not found.`),process.exitCode=1;return}if(!ce()){console.error("claude CLI not found on PATH. Install Claude Code first, then re-run."),process.exitCode=1;return}let{minConfidence:s,autoPromoteThreshold:n,limit:r,model:o,autoPromote:i}=Ph(e);e.json||console.log(`L4 inference \u2014 project "${t.name}" \u2014 model ${o} \u2014 pre-filter conf \u2265 ${s} \u2014 limit ${r} \u2014 auto-promote ${i?`ON (\u2265 ${n})`:"OFF"}`);let a=Date.now(),l=await cc({projectId:t.id,minConfidence:s,limit:r,autoPromote:i,autoPromoteThreshold:n,model:o,onBatchStart:u=>{e.json||process.stdout.write(`\r batch ${u.batch} (${u.pairs} pairs)\u2026 `)}});e.json||process.stdout.write(`
1225
+ `);let c=Number(((Date.now()-a)/1e3).toFixed(1));if(e.json)console.log(JSON.stringify({project:t.name,model:o,pre_filter_threshold:s,auto_promote:i,auto_promote_threshold:i?n:null,...l,elapsed_seconds:c},null,2));else{if(console.log(`Done in ${c}s \u2014 pairs=${l.candidates_after_filter}/${l.candidates_total} classified=${l.classified} suggestions=${l.suggestions_created} promoted=${l.links_promoted} failures=${l.failures.length}`),console.log(`Token spend: input=${l.total_input_tokens} output=${l.total_output_tokens}`),l.failures.length>0)for(let u of l.failures.slice(0,3))console.log(` \u26A0 batch ${u.batch_index}: ${u.error}`);l.suggestions_created>0?console.log(" Review the new L4 suggestions at #view=suggestions (filter by inferred_by=L4)."):l.candidates_after_filter===0&&console.log(` \u24D8 No pairs cleared the pre-filter (combined conf \u2265 ${s}). Lower --min-conf to widen the batch, or run more L1/L2/L3 inference first.`)}}T();import{createHash as Gh}from"node:crypto";T();j();import{writeFileSync as Fh,readFileSync as AC,existsSync as Uh,mkdirSync as Bh,readdirSync as IC,unlinkSync as vC}from"node:fs";import{join as dc}from"node:path";import{randomUUID as Hh}from"node:crypto";var xr=dc(x,"bug-patterns");function Wh(){P(),Uh(xr)||Bh(xr,{recursive:!0})}function js(e){return{id:e.id,signature_hash:e.signature_hash,example_message:e.example_message,occurrence_count:e.occurrence_count,first_seen_at:e.first_seen_at,last_seen_at:e.last_seen_at,resolved_in_session_id:e.resolved_in_session_id,fix_summary:e.fix_summary}}function Xh(e){return{cluster_id:e.cluster_id,session_id:e.session_id,matched_at:e.matched_at}}function uc(e){if(!e.signature_hash)throw new Error("signature_hash is required");if(!e.example_message)throw new Error("example_message is required");if(!Array.isArray(e.member_session_ids)||e.member_session_ids.length===0)throw new Error("at least one member_session_id is required");let t=_(),s=new Date().toISOString(),n=e.id??Hh(),r=e.first_seen_at??s,o=e.last_seen_at??s,i=Array.from(new Set(e.member_session_ids));t.transaction(()=>{t.prepare(`INSERT INTO bug_pattern_clusters
1226
1226
  (id, signature_hash, example_message, occurrence_count,
1227
1227
  first_seen_at, last_seen_at, resolved_in_session_id, fix_summary)
1228
1228
  VALUES (?, ?, ?, ?, ?, ?, NULL, NULL)`).run(n,e.signature_hash,e.example_message,i.length,r,o);let l=t.prepare(`INSERT INTO bug_pattern_members (cluster_id, session_id, matched_at)
@@ -1263,7 +1263,7 @@ show full content: recall paste --show <id>
1263
1263
  Top ${l.length} cluster(s):`);for(let c of l){let u=c.status==="resolved"?"\u2713 resolved":"open",p=c.example_message.slice(0,80);console.log(`
1264
1264
  [${u}] occurs=${c.occurrence_count} hash=${c.signature_hash.slice(0,8)}
1265
1265
  ${p}
1266
- first=${c.first_seen_at} last=${c.last_seen_at}`);for(let m of c.sample_members){let f=m.project?`[${m.project}] `:"";console.log(` \u2022 ${f}${m.title} (${m.session_id.slice(0,8)})`)}}console.log("\n Review at /graph/patterns in the web UI, or `recall neighborhood <session-id>` for an agent-facing bundle.")}T();import{z as qC}from"zod";T();function yc(e){let t=e.trim();if(t.length<4)return null;let s=_();if(t.length>=32)return s.prepare("SELECT id FROM sessions WHERE id = ?").get(t)?.id??null;let n=s.prepare("SELECT id FROM sessions WHERE id LIKE ? LIMIT 2").all(`${t}%`);return n.length===1?n[0].id:null}Rr();var Oc=new Set(["citation","similar","skill_track","bug_pattern","wiki_link","temporal_proximity"]),Ac=new Set(["pagerank","embedding-rerank","hybrid"]);function CE(e){if(!e)return;let t=e.split(",").map(s=>s.trim()).filter(Boolean);for(let s of t)if(!Oc.has(s))throw new Error(`invalid --edge-types value: '${s}'. Valid: ${Array.from(Oc).join(", ")}`);return t}function LE(e){if(!e)return"hybrid";if(!Ac.has(e))throw new Error(`invalid --scoring value: '${e}'. Valid: ${Array.from(Ac).join(", ")}`);return e}async function Ic(e,t){let s=yc(e);if(!s){console.error(`session not found or prefix ambiguous: ${e}`),process.exitCode=1;return}let n,r;try{n=LE(t.scoring),r=CE(t.edgeTypes)}catch(l){console.error(l instanceof Error?l.message:String(l)),process.exitCode=1;return}let o=t.budget?Math.max(100,Number(t.budget)):4e3;if(!Number.isFinite(o)){console.error("--budget must be a positive number"),process.exitCode=1;return}let i=t.maxDepth?Math.max(1,Number(t.maxDepth)):2;if(!Number.isFinite(i)){console.error("--max-depth must be a positive number"),process.exitCode=1;return}let a;try{a=Us(s,{budget:o,maxDepth:i,scoring:n,edgeTypes:r,includeWikiLinks:t.wikiLinks!==!1,includeSuggestions:!!t.includeSuggestions})}catch(l){console.error(l instanceof Error?l.message:String(l)),process.exitCode=1;return}if(t.json){process.stdout.write(JSON.stringify(a,null,2)+`
1266
+ first=${c.first_seen_at} last=${c.last_seen_at}`);for(let m of c.sample_members){let f=m.project?`[${m.project}] `:"";console.log(` \u2022 ${f}${m.title} (${m.session_id.slice(0,8)})`)}}console.log("\n Review at /graph/patterns in the web UI, or `recall neighborhood <session-id>` for an agent-facing bundle.")}T();import{z as VC}from"zod";T();function yc(e){let t=e.trim();if(t.length<4)return null;let s=_();if(t.length>=32)return s.prepare("SELECT id FROM sessions WHERE id = ?").get(t)?.id??null;let n=s.prepare("SELECT id FROM sessions WHERE id LIKE ? LIMIT 2").all(`${t}%`);return n.length===1?n[0].id:null}Rr();var Oc=new Set(["citation","similar","skill_track","bug_pattern","wiki_link","temporal_proximity"]),Ac=new Set(["pagerank","embedding-rerank","hybrid"]);function CE(e){if(!e)return;let t=e.split(",").map(s=>s.trim()).filter(Boolean);for(let s of t)if(!Oc.has(s))throw new Error(`invalid --edge-types value: '${s}'. Valid: ${Array.from(Oc).join(", ")}`);return t}function LE(e){if(!e)return"hybrid";if(!Ac.has(e))throw new Error(`invalid --scoring value: '${e}'. Valid: ${Array.from(Ac).join(", ")}`);return e}async function Ic(e,t){let s=yc(e);if(!s){console.error(`session not found or prefix ambiguous: ${e}`),process.exitCode=1;return}let n,r;try{n=LE(t.scoring),r=CE(t.edgeTypes)}catch(l){console.error(l instanceof Error?l.message:String(l)),process.exitCode=1;return}let o=t.budget?Math.max(100,Number(t.budget)):4e3;if(!Number.isFinite(o)){console.error("--budget must be a positive number"),process.exitCode=1;return}let i=t.maxDepth?Math.max(1,Number(t.maxDepth)):2;if(!Number.isFinite(i)){console.error("--max-depth must be a positive number"),process.exitCode=1;return}let a;try{a=Us(s,{budget:o,maxDepth:i,scoring:n,edgeTypes:r,includeWikiLinks:t.wikiLinks!==!1,includeSuggestions:!!t.includeSuggestions})}catch(l){console.error(l instanceof Error?l.message:String(l)),process.exitCode=1;return}if(t.json){process.stdout.write(JSON.stringify(a,null,2)+`
1267
1267
  `);return}process.stdout.write(a.bundle),a.truncated.length>0&&console.error(`
1268
1268
  [truncated ${a.truncated.length} refs to fit ${o}-token budget; ${a.budgetUsed} used / ${a.budgetRemaining} remaining]`)}T();I();var OE=[[/opus[-_ ]?4[-_. ]?7/i,{label:"Opus 4.7",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/opus[-_ ]?4[-_. ]?6/i,{label:"Opus 4.6",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet[-_ ]?4[-_. ]?6/i,{label:"Sonnet 4.6",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/sonnet[-_ ]?4[-_. ]?5/i,{label:"Sonnet 4.5",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/haiku[-_ ]?4[-_. ]?5/i,{label:"Haiku 4.5",inputCentsPerMtok:100,outputCentsPerMtok:500,cacheCreateCentsPerMtok:125,cacheReadCentsPerMtok:10}],[/opus[-_ ]?4(?!.*[5-9])/i,{label:"Opus 4",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet[-_ ]?4(?!.*[5-9])/i,{label:"Sonnet 4",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?7[-_ ]?sonnet|sonnet[-_ ]?3[-_. ]?7/i,{label:"Sonnet 3.7",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?5[-_ ]?sonnet|sonnet[-_ ]?3[-_. ]?5/i,{label:"Sonnet 3.5",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?5[-_ ]?haiku|haiku[-_ ]?3[-_. ]?5/i,{label:"Haiku 3.5",inputCentsPerMtok:80,outputCentsPerMtok:400,cacheCreateCentsPerMtok:100,cacheReadCentsPerMtok:8}],[/3[-_ ]?opus|opus[-_ ]?3/i,{label:"Opus 3",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/3[-_ ]?haiku|haiku(?!.*3[-_. ]?5)/i,{label:"Haiku 3",inputCentsPerMtok:25,outputCentsPerMtok:125,cacheCreateCentsPerMtok:30,cacheReadCentsPerMtok:3}],[/opus/i,{label:"Opus",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet/i,{label:"Sonnet",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/haiku/i,{label:"Haiku",inputCentsPerMtok:100,outputCentsPerMtok:500,cacheCreateCentsPerMtok:125,cacheReadCentsPerMtok:10}]],vc={label:"unknown",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30};function et(e){if(!e)return vc;for(let[t,s]of OE)if(t.test(e))return s;return vc}function Ie(e,t){if(e.byModel&&Object.keys(e.byModel).length>0){let i={input:0,output:0,cacheCreate:0,cacheRead:0},a=0;for(let[c,u]of Object.entries(e.byModel)){let p=et(c);i.input+=u.inputTokens/1e6*p.inputCentsPerMtok,i.output+=u.outputTokens/1e6*p.outputCentsPerMtok,i.cacheCreate+=u.cacheCreateTokens/1e6*p.cacheCreateCentsPerMtok,i.cacheRead+=u.cacheReadTokens/1e6*p.cacheReadCentsPerMtok,a+=u.inputTokens+u.outputTokens+u.cacheCreateTokens+u.cacheReadTokens}let l=i.input+i.output+i.cacheCreate+i.cacheRead;return{cents:l,dollars:l/100,totalTokens:a,parts:i}}let s=et(t),n={input:e.inputTokens/1e6*s.inputCentsPerMtok,output:e.outputTokens/1e6*s.outputCentsPerMtok,cacheCreate:e.cacheCreateTokens/1e6*s.cacheCreateCentsPerMtok,cacheRead:e.cacheReadTokens/1e6*s.cacheReadCentsPerMtok},r=n.input+n.output+n.cacheCreate+n.cacheRead,o=e.inputTokens+e.outputTokens+e.cacheCreateTokens+e.cacheReadTokens;return{cents:r,dollars:r/100,totalTokens:o,parts:n}}function se(e){let t=e/100;return t===0?"$0.00":t<.01?"<$0.01":t<1?`$${t.toFixed(2)}`:t<100?`$${t.toFixed(2)}`:t<1e4?`$${t.toFixed(0)}`:`$${(t/1e3).toFixed(1)}k`}function le(e){return!Number.isFinite(e)||e<0?"0":e<1e3?String(Math.round(e)):e<1e6?`${(e/1e3).toFixed(1)}k`:e<1e9?`${(e/1e6).toFixed(2)}M`:e<1e12?`${(e/1e9).toFixed(2)}B`:`${(e/1e12).toFixed(2)}T`}T();T();var AE=500,Bs=new Set;function Mc(){return Bs.size}function IE(){return`
1269
1269
  SELECT m.uuid, m.session_id, m.timestamp, m.raw_json
@@ -1282,7 +1282,7 @@ Top ${l.length} cluster(s):`);for(let c of l){let u=c.status==="resolved"?"\u271
1282
1282
  @input, @output, @cc, @cr, @ts
1283
1283
  )
1284
1284
  ON CONFLICT(message_uuid) DO NOTHING
1285
- `),i=0,a=0,l=new Set;for(;i<s;){let c=Math.min(n,s-i),u=JSON.stringify([...Bs]),p=r.all(u,c);if(p.length===0)break;let m=new Set;if(e.transaction(()=>{for(let g of p){let h;try{h=JSON.parse(g.raw_json)}catch{Bs.add(g.uuid);continue}let E=wn(h.message);if(!E){Bs.add(g.uuid);continue}o.run({uuid:g.uuid,session_id:g.session_id,model:h.message?.model??null,input:E.inputTokens,output:E.outputTokens,cc:E.cacheCreateTokens,cr:E.cacheReadTokens,ts:g.timestamp}),a+=1,m.add(g.session_id)}for(let g of m)is(e,g),l.add(g)})(),i+=p.length,t.onProgress?.({scanned:i,inserted:a,sessionsTouched:l.size,done:p.length<c}),p.length<c)break}return{scanned:i,inserted:a,sessionsTouched:l.size,done:!0}}function Dc(e={}){return vE(_(),e)}function kr(e){let t=new Map;for(let n of e){let r=n.model??null,o=t.get(r)??{inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,messageCount:0};o.inputTokens+=n.input_tokens,o.outputTokens+=n.output_tokens,o.cacheCreateTokens+=n.cache_create_tokens,o.cacheReadTokens+=n.cache_read_tokens,o.messageCount+=n.n,t.set(r,o)}let s=[];for(let[n,r]of t.entries()){let o=Ie({inputTokens:r.inputTokens,outputTokens:r.outputTokens,cacheCreateTokens:r.cacheCreateTokens,cacheReadTokens:r.cacheReadTokens},n);s.push({model:n,modelLabel:et(n).label,inputTokens:r.inputTokens,outputTokens:r.outputTokens,cacheCreateTokens:r.cacheCreateTokens,cacheReadTokens:r.cacheReadTokens,messageCount:r.messageCount,cost:o})}return s.sort((n,r)=>r.cost.cents-n.cost.cents)}function Nr(e){let t={};for(let s of e)t[s.model??"__unknown__"]={inputTokens:s.inputTokens,outputTokens:s.outputTokens,cacheCreateTokens:s.cacheCreateTokens,cacheReadTokens:s.cacheReadTokens};return{byModel:t}}function $c(e){let t=_(),s=t.prepare(`SELECT s.id, p.name AS project, s.started_at, s.ended_at,
1285
+ `),i=0,a=0,l=new Set;for(;i<s;){let c=Math.min(n,s-i),u=JSON.stringify([...Bs]),p=r.all(u,c);if(p.length===0)break;let m=new Set;if(e.transaction(()=>{for(let g of p){let h;try{h=JSON.parse(g.raw_json)}catch{Bs.add(g.uuid);continue}let E=wn(h.message);if(!E){Bs.add(g.uuid);continue}o.run({uuid:g.uuid,session_id:g.session_id,model:h.message?.model??null,input:E.inputTokens,output:E.outputTokens,cc:E.cacheCreateTokens,cr:E.cacheReadTokens,ts:g.timestamp}),a+=1,m.add(g.session_id)}for(let g of m)is(e,g),l.add(g)})(),i+=p.length,t.onProgress?.({scanned:i,inserted:a,sessionsTouched:l.size,done:p.length<c}),p.length<c)break}return{scanned:i,inserted:a,sessionsTouched:l.size,done:!0}}function $c(e={}){return vE(_(),e)}function kr(e){let t=new Map;for(let n of e){let r=n.model??null,o=t.get(r)??{inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,messageCount:0};o.inputTokens+=n.input_tokens,o.outputTokens+=n.output_tokens,o.cacheCreateTokens+=n.cache_create_tokens,o.cacheReadTokens+=n.cache_read_tokens,o.messageCount+=n.n,t.set(r,o)}let s=[];for(let[n,r]of t.entries()){let o=Ie({inputTokens:r.inputTokens,outputTokens:r.outputTokens,cacheCreateTokens:r.cacheCreateTokens,cacheReadTokens:r.cacheReadTokens},n);s.push({model:n,modelLabel:et(n).label,inputTokens:r.inputTokens,outputTokens:r.outputTokens,cacheCreateTokens:r.cacheCreateTokens,cacheReadTokens:r.cacheReadTokens,messageCount:r.messageCount,cost:o})}return s.sort((n,r)=>r.cost.cents-n.cost.cents)}function Nr(e){let t={};for(let s of e)t[s.model??"__unknown__"]={inputTokens:s.inputTokens,outputTokens:s.outputTokens,cacheCreateTokens:s.cacheCreateTokens,cacheReadTokens:s.cacheReadTokens};return{byModel:t}}function Dc(e){let t=_(),s=t.prepare(`SELECT s.id, p.name AS project, s.started_at, s.ended_at,
1286
1286
  s.message_count,
1287
1287
  s.total_input_tokens, s.total_output_tokens,
1288
1288
  s.total_cache_create_tokens, s.total_cache_read_tokens,
@@ -1385,7 +1385,7 @@ Top ${l.length} cluster(s):`);for(let c of l){let u=c.status==="resolved"?"\u271
1385
1385
  ${n}
1386
1386
  GROUP BY p.id, mu.model`),Q=new Map;for(let y of L){let U=y.project_id??"__none__",M=Q.get(U);M||(M={project:y.project??"(no project)",sessionIds:new Set,sessionsApprox:0,byModel:{}},Q.set(U,M)),y.sessions>M.sessionsApprox&&(M.sessionsApprox=y.sessions),M.byModel[y.model??"__unknown__"]={inputTokens:y.input_tokens,outputTokens:y.output_tokens,cacheCreateTokens:y.cache_create_tokens,cacheReadTokens:y.cache_read_tokens}}let v=[...Q.values()].map(y=>{let U=0,M=0,q=0,Be=0;for(let ut of Object.values(y.byModel))U+=ut.inputTokens,M+=ut.outputTokens,q+=ut.cacheCreateTokens,Be+=ut.cacheReadTokens;let je=Ie({inputTokens:U,outputTokens:M,cacheCreateTokens:q,cacheReadTokens:Be,byModel:y.byModel},null);return{project:y.project,sessions:y.sessionsApprox,totalTokens:je.totalTokens,cost:je}});v.sort((y,U)=>U.totalTokens-y.totalTokens);let ee=v.slice(0,20),B=t.prepare(`SELECT
1387
1387
  (SELECT COUNT(*) FROM messages WHERE role='assistant') AS assistant_messages,
1388
- (SELECT COUNT(*) FROM message_usage) AS messages_with_usage`).get();return{range:e,totalSessions:h.total_sessions,sessionsWithUsage:h.sessions_with_usage,inputTokens:u,outputTokens:p,cacheCreateTokens:m,cacheReadTokens:f,totalTokens:g.totalTokens,cost:g,daily:S,byModel:c,topSessions:R,topRepos:ee,backfill:{assistantMessages:B.assistant_messages,messagesWithUsage:B.messages_with_usage,pending:Math.max(0,B.assistant_messages-B.messages_with_usage),unrecoverable:Math.min(Mc(),Math.max(0,B.assistant_messages-B.messages_with_usage))},display:{dollars:se(g.cents),tokens:le(g.totalTokens)}}}var ze=e=>e.toLocaleString();function ME(e){return _().prepare("SELECT id FROM sessions WHERE id = ? OR id LIKE ? LIMIT 1").get(e,`${e}%`)?.id??null}async function Fc(e,t){if(t.backfill){let r=t.limit?Math.max(1,Number(t.limit)):void 0;console.log(d.dim("backfilling per-message usage from raw_json\u2026"));let o=Dc({limit:r});if(console.log(`${d.ok("backfill done")}: scanned ${d.bold(String(o.scanned))}, inserted ${d.bold(String(o.inserted))}, rolled-up ${d.bold(String(o.sessionsTouched))} sessions`),!e&&!t.project)return}if(e){let r=ME(e);if(!r){console.error(d.err(`no session matches '${e}'`)),process.exit(1);return}let o=$c(r);if(!o){console.error(d.err("session has no usage data yet \u2014 try --backfill")),process.exit(1);return}if(t.json){console.log(JSON.stringify(o,null,2));return}if(console.log(""),console.log(d.bold("session cost")),console.log(d.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(` id ${d.dim(o.sessionId)}`),console.log(` project ${d.accent(o.project??"\u2014")}`),console.log(` started ${d.dim(o.startedAt??"n/a")}`),console.log(` messages ${d.accent(ze(o.messageCount))}`),console.log(` model ${d.accent(o.primaryModelLabel)} ${d.dim(o.primaryModel??"")}`),console.log(""),console.log(` input ${ze(o.inputTokens).padStart(12)}`),console.log(` output ${ze(o.outputTokens).padStart(12)}`),console.log(` cache write ${ze(o.cacheCreateTokens).padStart(12)}`),console.log(` cache read ${ze(o.cacheReadTokens).padStart(12)}`),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"),console.log(` total tokens ${d.bold(ze(o.totalTokens).padStart(12))}`),console.log(` estimated cost ${d.accent(se(o.cost.cents).padStart(12))}`),o.byModel.length>1){console.log(""),console.log(d.dim(" by model:"));for(let i of o.byModel)console.log(` ${i.modelLabel.padEnd(14)} ${le(i.inputTokens+i.outputTokens+i.cacheCreateTokens+i.cacheReadTokens).padStart(10)} ${d.accent(se(i.cost.cents).padStart(10))}`)}console.log("");return}if(t.project){let r=jc(t.project);if(!r){console.error(d.err(`project '${t.project}' not found`)),process.exit(1);return}if(t.json){console.log(JSON.stringify(r,null,2));return}if(console.log(""),console.log(d.bold(`project \xB7 ${r.project}`)),console.log(d.dim("\u2500\u2500\u2500\u2500\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(` sessions ${d.accent(ze(r.sessionCount))}`),console.log(` total tokens ${d.accent(le(r.totalTokens).padStart(12))}`),console.log(` estimated cost ${d.accent(se(r.cost.cents).padStart(12))}`),r.byModel.length>0){console.log(""),console.log(d.dim(" by model:"));for(let o of r.byModel)console.log(` ${o.modelLabel.padEnd(14)} ${le(o.inputTokens+o.outputTokens+o.cacheCreateTokens+o.cacheReadTokens).padStart(10)} ${d.accent(se(o.cost.cents).padStart(10))}`)}if(r.topSessions.length>0){console.log(""),console.log(d.dim(" top sessions:"));for(let o of r.topSessions){let i=o.alias??o.sessionId.slice(0,8);console.log(` ${i.padEnd(22)} ${le(o.totalTokens).padStart(10)} ${d.accent(se(o.cost.cents).padStart(10))}`)}}console.log("");return}let s=t.days==="7"?"7d":t.days==="30"?"30d":"all",n=Pc(s);if(t.json){console.log(JSON.stringify(n,null,2));return}if(console.log(""),console.log(d.bold(`overview \xB7 ${s}`)),console.log(d.dim("\u2500\u2500\u2500\u2500\u2500\u2500\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(` sessions ${d.accent(ze(n.totalSessions))} ${d.dim(`(${n.sessionsWithUsage} w/ usage)`)}`),console.log(` total tokens ${d.accent(le(n.totalTokens).padStart(12))}`),console.log(` estimated cost ${d.accent(se(n.cost.cents).padStart(12))}`),n.backfill.pending>0&&console.log(d.dim(` (${ze(n.backfill.pending)} assistant messages pending \u2014 run \`recall stats --backfill\`)`)),n.byModel.length>0){console.log(""),console.log(d.dim(" by model:"));for(let r of n.byModel)console.log(` ${r.modelLabel.padEnd(14)} ${le(r.inputTokens+r.outputTokens+r.cacheCreateTokens+r.cacheReadTokens).padStart(10)} ${d.accent(se(r.cost.cents).padStart(10))}`)}if(n.topSessions.length>0){console.log(""),console.log(d.dim(" top sessions:"));for(let r of n.topSessions){let o=r.alias??r.sessionId.slice(0,8);console.log(` ${o.padEnd(22)} ${(r.project??"").slice(0,20).padEnd(22)} ${le(r.totalTokens).padStart(10)} ${d.accent(se(r.cost.cents).padStart(10))}`)}}console.log("")}I();T();T();import{execFile as DE}from"node:child_process";import{promisify as $E}from"node:util";import{stat as jE}from"node:fs/promises";var Uc=$E(DE),Bc=1e4,PE="%H%x09%aI%x09%s";async function FE(e){try{let{stdout:t}=await Uc("git",["rev-parse","--is-inside-work-tree"],{cwd:e,timeout:Bc});return t.trim()==="true"}catch{return!1}}async function UE(e,t,s){let n=["--no-pager","log","--all","--no-color","--since",t,"--until",s,`--pretty=format:${PE}`],{stdout:r}=await Uc("git",n,{cwd:e,timeout:Bc,maxBuffer:8*1024*1024}),o=[],i=new Set;for(let a of r.split(`
1388
+ (SELECT COUNT(*) FROM message_usage) AS messages_with_usage`).get();return{range:e,totalSessions:h.total_sessions,sessionsWithUsage:h.sessions_with_usage,inputTokens:u,outputTokens:p,cacheCreateTokens:m,cacheReadTokens:f,totalTokens:g.totalTokens,cost:g,daily:S,byModel:c,topSessions:R,topRepos:ee,backfill:{assistantMessages:B.assistant_messages,messagesWithUsage:B.messages_with_usage,pending:Math.max(0,B.assistant_messages-B.messages_with_usage),unrecoverable:Math.min(Mc(),Math.max(0,B.assistant_messages-B.messages_with_usage))},display:{dollars:se(g.cents),tokens:le(g.totalTokens)}}}var ze=e=>e.toLocaleString();function ME(e){return _().prepare("SELECT id FROM sessions WHERE id = ? OR id LIKE ? LIMIT 1").get(e,`${e}%`)?.id??null}async function Fc(e,t){if(t.backfill){let r=t.limit?Math.max(1,Number(t.limit)):void 0;console.log(d.dim("backfilling per-message usage from raw_json\u2026"));let o=$c({limit:r});if(console.log(`${d.ok("backfill done")}: scanned ${d.bold(String(o.scanned))}, inserted ${d.bold(String(o.inserted))}, rolled-up ${d.bold(String(o.sessionsTouched))} sessions`),!e&&!t.project)return}if(e){let r=ME(e);if(!r){console.error(d.err(`no session matches '${e}'`)),process.exit(1);return}let o=Dc(r);if(!o){console.error(d.err("session has no usage data yet \u2014 try --backfill")),process.exit(1);return}if(t.json){console.log(JSON.stringify(o,null,2));return}if(console.log(""),console.log(d.bold("session cost")),console.log(d.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),console.log(` id ${d.dim(o.sessionId)}`),console.log(` project ${d.accent(o.project??"\u2014")}`),console.log(` started ${d.dim(o.startedAt??"n/a")}`),console.log(` messages ${d.accent(ze(o.messageCount))}`),console.log(` model ${d.accent(o.primaryModelLabel)} ${d.dim(o.primaryModel??"")}`),console.log(""),console.log(` input ${ze(o.inputTokens).padStart(12)}`),console.log(` output ${ze(o.outputTokens).padStart(12)}`),console.log(` cache write ${ze(o.cacheCreateTokens).padStart(12)}`),console.log(` cache read ${ze(o.cacheReadTokens).padStart(12)}`),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"),console.log(` total tokens ${d.bold(ze(o.totalTokens).padStart(12))}`),console.log(` estimated cost ${d.accent(se(o.cost.cents).padStart(12))}`),o.byModel.length>1){console.log(""),console.log(d.dim(" by model:"));for(let i of o.byModel)console.log(` ${i.modelLabel.padEnd(14)} ${le(i.inputTokens+i.outputTokens+i.cacheCreateTokens+i.cacheReadTokens).padStart(10)} ${d.accent(se(i.cost.cents).padStart(10))}`)}console.log("");return}if(t.project){let r=jc(t.project);if(!r){console.error(d.err(`project '${t.project}' not found`)),process.exit(1);return}if(t.json){console.log(JSON.stringify(r,null,2));return}if(console.log(""),console.log(d.bold(`project \xB7 ${r.project}`)),console.log(d.dim("\u2500\u2500\u2500\u2500\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(` sessions ${d.accent(ze(r.sessionCount))}`),console.log(` total tokens ${d.accent(le(r.totalTokens).padStart(12))}`),console.log(` estimated cost ${d.accent(se(r.cost.cents).padStart(12))}`),r.byModel.length>0){console.log(""),console.log(d.dim(" by model:"));for(let o of r.byModel)console.log(` ${o.modelLabel.padEnd(14)} ${le(o.inputTokens+o.outputTokens+o.cacheCreateTokens+o.cacheReadTokens).padStart(10)} ${d.accent(se(o.cost.cents).padStart(10))}`)}if(r.topSessions.length>0){console.log(""),console.log(d.dim(" top sessions:"));for(let o of r.topSessions){let i=o.alias??o.sessionId.slice(0,8);console.log(` ${i.padEnd(22)} ${le(o.totalTokens).padStart(10)} ${d.accent(se(o.cost.cents).padStart(10))}`)}}console.log("");return}let s=t.days==="7"?"7d":t.days==="30"?"30d":"all",n=Pc(s);if(t.json){console.log(JSON.stringify(n,null,2));return}if(console.log(""),console.log(d.bold(`overview \xB7 ${s}`)),console.log(d.dim("\u2500\u2500\u2500\u2500\u2500\u2500\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(` sessions ${d.accent(ze(n.totalSessions))} ${d.dim(`(${n.sessionsWithUsage} w/ usage)`)}`),console.log(` total tokens ${d.accent(le(n.totalTokens).padStart(12))}`),console.log(` estimated cost ${d.accent(se(n.cost.cents).padStart(12))}`),n.backfill.pending>0&&console.log(d.dim(` (${ze(n.backfill.pending)} assistant messages pending \u2014 run \`recall stats --backfill\`)`)),n.byModel.length>0){console.log(""),console.log(d.dim(" by model:"));for(let r of n.byModel)console.log(` ${r.modelLabel.padEnd(14)} ${le(r.inputTokens+r.outputTokens+r.cacheCreateTokens+r.cacheReadTokens).padStart(10)} ${d.accent(se(r.cost.cents).padStart(10))}`)}if(n.topSessions.length>0){console.log(""),console.log(d.dim(" top sessions:"));for(let r of n.topSessions){let o=r.alias??r.sessionId.slice(0,8);console.log(` ${o.padEnd(22)} ${(r.project??"").slice(0,20).padEnd(22)} ${le(r.totalTokens).padStart(10)} ${d.accent(se(r.cost.cents).padStart(10))}`)}}console.log("")}I();T();T();import{execFile as $E}from"node:child_process";import{promisify as DE}from"node:util";import{stat as jE}from"node:fs/promises";var Uc=DE($E),Bc=1e4,PE="%H%x09%aI%x09%s";async function FE(e){try{let{stdout:t}=await Uc("git",["rev-parse","--is-inside-work-tree"],{cwd:e,timeout:Bc});return t.trim()==="true"}catch{return!1}}async function UE(e,t,s){let n=["--no-pager","log","--all","--no-color","--since",t,"--until",s,`--pretty=format:${PE}`],{stdout:r}=await Uc("git",n,{cwd:e,timeout:Bc,maxBuffer:8*1024*1024}),o=[],i=new Set;for(let a of r.split(`
1389
1389
  `)){if(!a)continue;let[l,c,...u]=a.split(" ");!l||i.has(l)||(i.add(l),o.push({commit_sha:l,committed_at:c??null,subject:u.join(" ")||null}))}return o}function BE(e){return _().prepare(`SELECT id, cwd, started_at, ended_at
1390
1390
  FROM sessions WHERE id = ?`).get(e)??null}function HE(e,t,s){if(s.length===0)return 0;let n=_(),r=new Date().toISOString(),o=n.prepare(`INSERT OR IGNORE INTO session_commits
1391
1391
  (session_id, commit_sha, committed_at, subject, cwd_snapshot, correlated_at)
@@ -1432,39 +1432,42 @@ Top ${l.length} cluster(s):`);for(let c of l){let u=c.status==="resolved"?"\u271
1432
1432
  AND s.auto_title_source = 'heuristic' THEN 1 ELSE 0 END) AS heuristic_only
1433
1433
  FROM sessions s
1434
1434
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1435
- WHERE s.started_at >= ?`).get(e),s=t.total??0,n=t.without_alias??0,r=t.heuristic_only??0,o=s>0?r/s:0;return{total:s,withoutAlias:n,heuristicOnly:r,fractionHeuristic:o}}catch{return{total:0,withoutAlias:0,heuristicOnly:0,fractionHeuristic:0}}}async function hb(){let e=mb(),t=fb(),s=_b(),n=!1,r=null,o=null,i=null,a=null;if(e){let u=await gb(e,"/api/health");u&&(n=!0,r=typeof u.uptimeSeconds=="number"?u.uptimeSeconds:null,o=typeof u.version=="string"?u.version:null,i=typeof u.pipeline?.silentTerminalRejections=="number"?u.pipeline.silentTerminalRejections:null,a=u.pipeline?.lastTerminalSyncAt??null)}let l=[];if(n||l.push("Daemon not reachable on 127.0.0.1 \u2014 start it with `recall start` before further diagnosis."),i!==null&&i>0&&l.push(`Daemon rejected ${i.toLocaleString()} /api/terminal/* request(s) without a valid X-Recall-Token. The editor extension is outdated relative to this daemon \u2014 tab names are not flowing through. Reinstall: \`code --install-extension extensions/vscode/clauderecall-vscode-*.vsix\`, then reload the extension host (Cmd/Ctrl+Shift+P \u2192 "Developer: Restart Extension Host").`),n&&r!==null&&r>30)if(!a)l.push(`Daemon has been running ${Math.round(r/60)} min but has not yet seen a single successful /api/terminal/sync. Either no editor extension is installed/active, or every attempt is being rejected (see counter above).`);else{let u=Date.now()-Date.parse(a);Number.isFinite(u)&&u>nl&&l.push(`Last successful /api/terminal/sync was ${Math.round(u/6e4)} min ago \u2014 extension may have crashed, been disabled, or is failing auth. Run \`recall doctor\` again after restarting the extension host.`)}return!n&&t.exists&&t.ageSeconds!==null&&t.ageSeconds>24*3600&&l.push(`~/.recall/terminals.json is ${Math.round(t.ageSeconds/3600)}h old \u2014 pipeline has not produced fresh data recently. Likely root cause is the same as the rejection counter would show; start the daemon and re-run.`),s.total>=3&&s.fractionHeuristic>=rl&&l.push(`${s.heuristicOnly}/${s.total} sessions in the last ${Mr}h (${Math.round(s.fractionHeuristic*100)}%) fell back to the heuristic first-message title. A healthy pipeline rate is < 20%. Either the extension is not syncing tab names, or the correlator cannot disambiguate. Reinstall the extension and verify the rejection counter drops to 0.`),{state:n?l.length>0?"degraded":"ok":"down",flags:l,daemon:{running:n,port:e,uptimeSeconds:r,version:o},runtime:{silentTerminalRejections:i,lastTerminalSyncAt:a},terminalsJson:t,recentSessions:s}}function ht(e){return e<1024?`${e} B`:e<1024**2?`${(e/1024).toFixed(1)} KB`:e<1024**3?`${(e/1024**2).toFixed(1)} MB`:`${(e/1024**3).toFixed(2)} GB`}function Vc(e){try{return el(e).size}catch{return 0}}function Zc(e){try{return _().prepare(`SELECT COUNT(*) AS n FROM ${e}_data WHERE block = 1`).get().n}catch{return 0}}function Eb(){let e=_(),t=e.pragma("page_size",{simple:!0})||4096,s=e.pragma("page_count",{simple:!0})||0,n=e.pragma("freelist_count",{simple:!0})||0,r="ok";try{let h=e.pragma("quick_check").map(E=>E.quick_check);r=h.length===1&&h[0]==="ok"?"ok":h.join("; ")}catch(g){r=`check failed: ${g.message}`}let o=Vc(te),i=Vc(`${te}-wal`),a=0,l=0;try{let g=lb(x);a=Number(g.bavail)*Number(g.bsize),l=Number(g.blocks)*Number(g.bsize)}catch{}let c=e.prepare(`SELECT
1435
+ WHERE s.started_at >= ?`).get(e),s=t.total??0,n=t.without_alias??0,r=t.heuristic_only??0,o=s>0?r/s:0;return{total:s,withoutAlias:n,heuristicOnly:r,fractionHeuristic:o}}catch{return{total:0,withoutAlias:0,heuristicOnly:0,fractionHeuristic:0}}}async function hb(){let e=mb(),t=fb(),s=_b(),n=!1,r=null,o=null,i=null,a=null;if(e){let u=await gb(e,"/api/health");u&&(n=!0,r=typeof u.uptimeSeconds=="number"?u.uptimeSeconds:null,o=typeof u.version=="string"?u.version:null,i=typeof u.pipeline?.silentTerminalRejections=="number"?u.pipeline.silentTerminalRejections:null,a=u.pipeline?.lastTerminalSyncAt??null)}let l=[];if(n||l.push("Daemon not reachable on 127.0.0.1 \u2014 start it with `recall start` before further diagnosis."),i!==null&&i>0&&l.push(`Daemon rejected ${i.toLocaleString()} /api/terminal/* request(s) without a valid X-Recall-Token. The editor extension is outdated relative to this daemon \u2014 tab names are not flowing through. Reinstall: \`code --install-extension extensions/vscode/clauderecall-vscode-*.vsix\`, then reload the extension host (Cmd/Ctrl+Shift+P \u2192 "Developer: Restart Extension Host").`),n&&r!==null&&r>30)if(!a)l.push(`Daemon has been running ${Math.round(r/60)} min but has not yet seen a single successful /api/terminal/sync. Either no editor extension is installed/active, or every attempt is being rejected (see counter above).`);else{let u=Date.now()-Date.parse(a);Number.isFinite(u)&&u>nl&&l.push(`Last successful /api/terminal/sync was ${Math.round(u/6e4)} min ago \u2014 extension may have crashed, been disabled, or is failing auth. Run \`recall doctor\` again after restarting the extension host.`)}return!n&&t.exists&&t.ageSeconds!==null&&t.ageSeconds>24*3600&&l.push(`~/.recall/terminals.json is ${Math.round(t.ageSeconds/3600)}h old \u2014 pipeline has not produced fresh data recently. Likely root cause is the same as the rejection counter would show; start the daemon and re-run.`),s.total>=3&&s.fractionHeuristic>=rl&&l.push(`${s.heuristicOnly}/${s.total} sessions in the last ${Mr}h (${Math.round(s.fractionHeuristic*100)}%) fell back to the heuristic first-message title. A healthy pipeline rate is < 20%. Either the extension is not syncing tab names, or the correlator cannot disambiguate. Reinstall the extension and verify the rejection counter drops to 0.`),{state:n?l.length>0?"degraded":"ok":"down",flags:l,daemon:{running:n,port:e,uptimeSeconds:r,version:o},runtime:{silentTerminalRejections:i,lastTerminalSyncAt:a},terminalsJson:t,recentSessions:s}}function ht(e){return e<1024?`${e} B`:e<1024**2?`${(e/1024).toFixed(1)} KB`:e<1024**3?`${(e/1024**2).toFixed(1)} MB`:`${(e/1024**3).toFixed(2)} GB`}function Vc(e){try{return el(e).size}catch{return 0}}function Zc(e){try{return _().prepare(`SELECT COUNT(*) AS n FROM ${e}_data WHERE block = 1`).get().n}catch{return 0}}function Eb(e){let t=_(),s=t.pragma("page_size",{simple:!0})||4096,n=t.pragma("page_count",{simple:!0})||0,r=t.pragma("freelist_count",{simple:!0})||0;e?.("Checking database integrity");let o="ok";try{let E=t.pragma("quick_check").map(b=>b.quick_check);o=E.length===1&&E[0]==="ok"?"ok":E.join("; ")}catch(h){o=`check failed: ${h.message}`}let i=Vc(te),a=Vc(`${te}-wal`),l=0,c=0;try{let h=lb(x);l=Number(h.bavail)*Number(h.bsize),c=Number(h.blocks)*Number(h.bsize)}catch{}e?.("Counting rows");let u=t.prepare(`SELECT
1436
1436
  (SELECT COUNT(*) FROM projects) AS projects,
1437
1437
  (SELECT COUNT(*) FROM sessions) AS sessions,
1438
1438
  (SELECT COUNT(*) FROM messages) AS messages,
1439
- (SELECT COUNT(*) FROM message_usage) AS message_usage`).get(),u=0;try{u=e.prepare("SELECT COUNT(*) AS n FROM vec_chunks").get().n}catch{}let p=[];a>0&&a<1*1024**3&&p.push(`Disk free is ${ht(a)} \u2014 heavy operations (synthesis, extract-outputs, vector ingest) may fail.`),i>50*1024**2&&p.push(`WAL is ${ht(i)} \u2014 run \`recall optimize\` to truncate it.`),n>s*.2&&s>1e3&&p.push(`${n.toLocaleString()} free pages (${(n/s*100).toFixed(0)}% of file) \u2014 \`recall optimize --vacuum\` will reclaim them.`);let m=Zc("messages_fts"),f=Zc("sessions_fts");return m>16&&p.push(`messages_fts has ${m} segments \u2014 \`recall optimize\` will merge them.`),{db:{sizeBytes:o,walSizeBytes:i,pageCount:s,pageSize:t,freelistCount:n,freelistBytes:n*t,integrity:r},disk:{freeBytes:a,totalBytes:l},fts:{messages:{fragments:m},sessions:{fragments:f}},vectors:{rows:u},rows:{projects:c.projects,sessions:c.sessions,messages:c.messages,messageUsage:c.message_usage},warnings:p}}async function ol(e={}){let t=_().prepare(`SELECT sa.session_id AS session_id, sa.alias AS alias, s.cwd AS cwd
1439
+ (SELECT COUNT(*) FROM message_usage) AS message_usage`).get(),p=0;try{p=t.prepare("SELECT COUNT(*) AS n FROM vec_chunks").get().n}catch{}e?.("Measuring FTS fragmentation");let m=[];l>0&&l<1*1024**3&&m.push(`Disk free is ${ht(l)} \u2014 heavy operations (synthesis, extract-outputs, vector ingest) may fail.`),a>50*1024**2&&m.push(`WAL is ${ht(a)} \u2014 run \`recall optimize\` to truncate it.`),r>n*.2&&n>1e3&&m.push(`${r.toLocaleString()} free pages (${(r/n*100).toFixed(0)}% of file) \u2014 \`recall optimize --vacuum\` will reclaim them.`);let f=Zc("messages_fts"),g=Zc("sessions_fts");return f>16&&m.push(`messages_fts has ${f} segments \u2014 \`recall optimize\` will merge them.`),{db:{sizeBytes:i,walSizeBytes:a,pageCount:n,pageSize:s,freelistCount:r,freelistBytes:r*s,integrity:o},disk:{freeBytes:l,totalBytes:c},fts:{messages:{fragments:f},sessions:{fragments:g}},vectors:{rows:p},rows:{projects:u.projects,sessions:u.sessions,messages:u.messages,messageUsage:u.message_usage},warnings:m}}function bb(e){if(!e)return{stage:()=>{},done:()=>{}};let t=!!process.stderr.isTTY,s="",n=0,r=()=>{if(!s)return;let o=Date.now()-n,i=o<1e3?`${o}ms`:`${(o/1e3).toFixed(1)}s`;t?process.stderr.write(`\r\x1B[2K ${d.ok("\u2713")} ${s} ${d.dim(`(${i})`)}
1440
+ `):process.stderr.write(` \u2713 ${s} (${i})
1441
+ `),s=""};return{stage(o){r(),s=o,n=Date.now(),t?process.stderr.write(` ${d.dim("\u2026")} ${s}`):process.stderr.write(` \u2026 ${s}
1442
+ `)},done:r}}async function ol(e={}){let t=bb(!e.json);t.stage("Scanning session aliases");let s=_().prepare(`SELECT sa.session_id AS session_id, sa.alias AS alias, s.cwd AS cwd
1440
1443
  FROM session_aliases sa
1441
1444
  LEFT JOIN sessions s ON s.id = sa.session_id
1442
- WHERE sa.alias IS NOT NULL AND sa.alias != ''`).all(),s=pb(t),n=Eb(),r=await hb();if(e.json){process.stdout.write(JSON.stringify({scanned:t.length,violations:s.length,items:s,health:n,pipeline:r},null,2)),process.stdout.write(`
1443
- `);let a=r.state==="degraded";return s.length===0&&n.db.integrity==="ok"&&!a?0:1}if(console.log(d.dim("\u2014 System health \u2014")),console.log(` Database ${ht(n.db.sizeBytes)} (${n.rows.messages.toLocaleString()} messages across ${n.rows.sessions.toLocaleString()} sessions, ${n.rows.projects.toLocaleString()} projects)`),console.log(` WAL ${ht(n.db.walSizeBytes)} (capped at 64 MB; truncated on clean shutdown)`),console.log(` Free pages ${n.db.freelistCount.toLocaleString()} (${ht(n.db.freelistBytes)} reclaimable via VACUUM)`),console.log(` FTS segments messages=${n.fts.messages.fragments}, sessions=${n.fts.sessions.fragments} (lower is faster \u2014 \`recall optimize\` merges them)`),console.log(` Vector rows ${n.vectors.rows.toLocaleString()}`),n.disk.totalBytes>0){let a=n.disk.freeBytes/n.disk.totalBytes*100;console.log(` Disk free ${ht(n.disk.freeBytes)} of ${ht(n.disk.totalBytes)} (${a.toFixed(1)}%)`)}if(console.log(` Integrity ${n.db.integrity==="ok"?d.ok("ok"):d.err(n.db.integrity)}`),n.warnings.length>0){console.log("");for(let a of n.warnings)console.log(` ${d.warn("!")} ${a}`)}if(console.log(""),console.log(d.dim("\u2014 Pipeline health (tab-name \u2192 session alias) \u2014")),r.daemon.running?console.log(` Daemon ${d.ok("running")} (port ${r.daemon.port}, version ${r.daemon.version??"?"}, up ${r.daemon.uptimeSeconds!==null?Math.round(r.daemon.uptimeSeconds/60)+" min":"?"})`):console.log(` Daemon ${d.warn("not reachable")}`),r.runtime.silentTerminalRejections!==null){let a=r.runtime.silentTerminalRejections;console.log(` Auth rejections ${a===0?d.ok("0"):d.err(a.toLocaleString())} (extension /api/terminal/* requests denied without a valid X-Recall-Token)`)}if(r.runtime.lastTerminalSyncAt!==null){let a=Date.now()-Date.parse(r.runtime.lastTerminalSyncAt),l=Number.isFinite(a)?Math.round(a/6e4):null,c=l!==null&&a>nl;console.log(` Last ext sync ${c?d.warn(`${l} min ago`):d.ok(l===0?"just now":`${l} min ago`)} (most recent successful POST /api/terminal/sync)`)}else r.daemon.running&&console.log(` Last ext sync ${d.warn("never")} (no extension has called /api/terminal/sync since the daemon started)`);if(r.terminalsJson.exists&&r.terminalsJson.ageSeconds!==null){let a=Math.round(r.terminalsJson.ageSeconds/3600),l=r.terminalsJson.ageSeconds>24*3600;console.log(` terminals.json ${l?d.warn(`${a}h old`):d.ok(`${a}h old`)} (persisted registry mtime \u2014 fresh means extensions are connecting)`)}let o=r.recentSessions;if(o.total>0){let a=Math.round(o.fractionHeuristic*100),l=o.fractionHeuristic>=rl&&o.total>=3;console.log(` Recent titles ${l?d.err(`${a}% heuristic`):d.ok(`${a}% heuristic`)} (${o.heuristicOnly}/${o.total} sessions in last ${Mr}h fell back to first-message title)`)}if(r.flags.length>0){console.log("");for(let a of r.flags)console.log(` ${d.warn("!")} ${a}`)}if(console.log(""),console.log(d.dim("\u2014 Tab-name invariant \u2014")),s.length===0)return console.log(d.ok(` \u2713 holds across ${t.length.toLocaleString()} aliased session${t.length===1?"":"s"}`)),console.log(d.dim(" No fabricated origin labels (`VS Code \xB7 cwd \xB7 branch`) found. No deprecated cwd-branch synthesis found.")),n.db.integrity==="ok"?0:1;console.log(d.err(`\u2717 ${s.length} invariant violation${s.length===1?"":"s"} found across ${t.length.toLocaleString()} aliased sessions`)),console.log("");let i=new Map;for(let a of s){let l=i.get(a.violation)??[];l.push(a),i.set(a.violation,l)}for(let[a,l]of i){console.log(d.warn(` ${a} (${l.length})`));for(let c of l.slice(0,10))console.log(` ${c.session_id.slice(0,8)} ${d.dim("\u2192")} ${JSON.stringify(c.alias)}`);l.length>10&&console.log(d.dim(` \u2026 and ${l.length-10} more (rerun with --json for the full list)`)),console.log("")}return console.log(d.dim('Remediation: `recall name <id-prefix> ""` clears a bad alias so the heuristic title takes over,\nor `recall name <id-prefix> "<actual tab name>"` sets it to the real value.')),1}I();T();j();import{existsSync as bb,readFileSync as Sb}from"node:fs";import{join as yb}from"node:path";function Tb(){let e=yb(x,"daemon.pid");if(!bb(e))return!1;try{let t=parseInt(Sb(e,"utf-8").trim(),10);return!Number.isFinite(t)||t<=0?!1:(process.kill(t,0),!0)}catch{return!1}}async function Yt(e,t){let s=Date.now();try{return t(),{step:e,ok:!0,durationMs:Date.now()-s}}catch(n){return{step:e,ok:!1,durationMs:Date.now()-s,error:n.message}}}async function il(e={}){let t=_(),s=[];if(e.vacuum&&Tb())return e.json?(process.stdout.write(JSON.stringify({ok:!1,error:"daemon-running",message:"VACUUM requires the daemon to be stopped. Run `recall stop`, then re-run with --vacuum."},null,2)+`
1445
+ WHERE sa.alias IS NOT NULL AND sa.alias != ''`).all(),n=pb(s),r=Eb(t.stage);t.stage("Probing daemon");let o=await hb();if(t.done(),e.json){process.stdout.write(JSON.stringify({scanned:s.length,violations:n.length,items:n,health:r,pipeline:o},null,2)),process.stdout.write(`
1446
+ `);let l=o.state==="degraded";return n.length===0&&r.db.integrity==="ok"&&!l?0:1}if(console.log(d.dim("\u2014 System health \u2014")),console.log(` Database ${ht(r.db.sizeBytes)} (${r.rows.messages.toLocaleString()} messages across ${r.rows.sessions.toLocaleString()} sessions, ${r.rows.projects.toLocaleString()} projects)`),console.log(` WAL ${ht(r.db.walSizeBytes)} (capped at 64 MB; truncated on clean shutdown)`),console.log(` Free pages ${r.db.freelistCount.toLocaleString()} (${ht(r.db.freelistBytes)} reclaimable via VACUUM)`),console.log(` FTS segments messages=${r.fts.messages.fragments}, sessions=${r.fts.sessions.fragments} (lower is faster \u2014 \`recall optimize\` merges them)`),console.log(` Vector rows ${r.vectors.rows.toLocaleString()}`),r.disk.totalBytes>0){let l=r.disk.freeBytes/r.disk.totalBytes*100;console.log(` Disk free ${ht(r.disk.freeBytes)} of ${ht(r.disk.totalBytes)} (${l.toFixed(1)}%)`)}if(console.log(` Integrity ${r.db.integrity==="ok"?d.ok("ok"):d.err(r.db.integrity)}`),r.warnings.length>0){console.log("");for(let l of r.warnings)console.log(` ${d.warn("!")} ${l}`)}if(console.log(""),console.log(d.dim("\u2014 Pipeline health (tab-name \u2192 session alias) \u2014")),o.daemon.running?console.log(` Daemon ${d.ok("running")} (port ${o.daemon.port}, version ${o.daemon.version??"?"}, up ${o.daemon.uptimeSeconds!==null?Math.round(o.daemon.uptimeSeconds/60)+" min":"?"})`):console.log(` Daemon ${d.warn("not reachable")}`),o.runtime.silentTerminalRejections!==null){let l=o.runtime.silentTerminalRejections;console.log(` Auth rejections ${l===0?d.ok("0"):d.err(l.toLocaleString())} (extension /api/terminal/* requests denied without a valid X-Recall-Token)`)}if(o.runtime.lastTerminalSyncAt!==null){let l=Date.now()-Date.parse(o.runtime.lastTerminalSyncAt),c=Number.isFinite(l)?Math.round(l/6e4):null,u=c!==null&&l>nl;console.log(` Last ext sync ${u?d.warn(`${c} min ago`):d.ok(c===0?"just now":`${c} min ago`)} (most recent successful POST /api/terminal/sync)`)}else o.daemon.running&&console.log(` Last ext sync ${d.warn("never")} (no extension has called /api/terminal/sync since the daemon started)`);if(o.terminalsJson.exists&&o.terminalsJson.ageSeconds!==null){let l=Math.round(o.terminalsJson.ageSeconds/3600),c=o.terminalsJson.ageSeconds>24*3600;console.log(` terminals.json ${c?d.warn(`${l}h old`):d.ok(`${l}h old`)} (persisted registry mtime \u2014 fresh means extensions are connecting)`)}let i=o.recentSessions;if(i.total>0){let l=Math.round(i.fractionHeuristic*100),c=i.fractionHeuristic>=rl&&i.total>=3;console.log(` Recent titles ${c?d.err(`${l}% heuristic`):d.ok(`${l}% heuristic`)} (${i.heuristicOnly}/${i.total} sessions in last ${Mr}h fell back to first-message title)`)}if(o.flags.length>0){console.log("");for(let l of o.flags)console.log(` ${d.warn("!")} ${l}`)}if(console.log(""),console.log(d.dim("\u2014 Tab-name invariant \u2014")),n.length===0)return console.log(d.ok(` \u2713 holds across ${s.length.toLocaleString()} aliased session${s.length===1?"":"s"}`)),console.log(d.dim(" No fabricated origin labels (`VS Code \xB7 cwd \xB7 branch`) found. No deprecated cwd-branch synthesis found.")),r.db.integrity==="ok"?0:1;console.log(d.err(`\u2717 ${n.length} invariant violation${n.length===1?"":"s"} found across ${s.length.toLocaleString()} aliased sessions`)),console.log("");let a=new Map;for(let l of n){let c=a.get(l.violation)??[];c.push(l),a.set(l.violation,c)}for(let[l,c]of a){console.log(d.warn(` ${l} (${c.length})`));for(let u of c.slice(0,10))console.log(` ${u.session_id.slice(0,8)} ${d.dim("\u2192")} ${JSON.stringify(u.alias)}`);c.length>10&&console.log(d.dim(` \u2026 and ${c.length-10} more (rerun with --json for the full list)`)),console.log("")}return console.log(d.dim('Remediation: `recall name <id-prefix> ""` clears a bad alias so the heuristic title takes over,\nor `recall name <id-prefix> "<actual tab name>"` sets it to the real value.')),1}I();T();j();import{existsSync as Sb,readFileSync as yb}from"node:fs";import{join as Tb}from"node:path";function wb(){let e=Tb(x,"daemon.pid");if(!Sb(e))return!1;try{let t=parseInt(yb(e,"utf-8").trim(),10);return!Number.isFinite(t)||t<=0?!1:(process.kill(t,0),!0)}catch{return!1}}async function Yt(e,t){let s=Date.now();try{return t(),{step:e,ok:!0,durationMs:Date.now()-s}}catch(n){return{step:e,ok:!1,durationMs:Date.now()-s,error:n.message}}}async function il(e={}){let t=_(),s=[];if(e.vacuum&&wb())return e.json?(process.stdout.write(JSON.stringify({ok:!1,error:"daemon-running",message:"VACUUM requires the daemon to be stopped. Run `recall stop`, then re-run with --vacuum."},null,2)+`
1444
1447
  `),2):(console.error(d.err("\u2717 VACUUM requires the daemon to be stopped. Run `recall stop` first, then re-run with --vacuum.")),2);s.push(await Yt("wal_checkpoint(TRUNCATE)",()=>{t.pragma("wal_checkpoint(TRUNCATE)")})),s.push(await Yt("messages_fts optimize",()=>{t.exec("INSERT INTO messages_fts(messages_fts) VALUES('optimize');")})),s.push(await Yt("sessions_fts optimize",()=>{t.exec("INSERT INTO sessions_fts(sessions_fts) VALUES('optimize');")})),s.push(await Yt("PRAGMA optimize",()=>{t.exec("PRAGMA optimize")})),e.vacuum&&s.push(await Yt("VACUUM",()=>{t.exec("VACUUM")}));let n=s.filter(r=>!r.ok);if(e.json)return process.stdout.write(JSON.stringify({ok:n.length===0,steps:s,vacuum:!!e.vacuum},null,2)+`
1445
- `),n.length===0?0:1;for(let r of s){let o=r.ok?d.ok("\u2713"):d.err("\u2717"),i=`${r.durationMs} ms`;console.log(` ${o} ${r.step.padEnd(28)} ${d.dim(i)}`),r.error&&console.log(` ${d.err(r.error)}`)}return n.length===0?(console.log(""),console.log(d.ok("All maintenance passes completed.")),e.vacuum||console.log(d.dim(" Run `recall optimize --vacuum` (with the daemon stopped) to reclaim disk pages from deleted rows.")),0):(console.log(""),console.log(d.warn(`${n.length} step(s) failed \u2014 review the errors above.`)),1)}I();T();j();import{existsSync as wb,readFileSync as xb}from"node:fs";function Rb(){let e=`${x}/daemon.port`;if(!wb(e))return null;try{let t=xb(e,"utf8").trim();return/^\d+$/.test(t)?t:null}catch{return null}}function kb(e){let t=_();if(e.length>=32){let n=t.prepare("SELECT id FROM sessions WHERE id = ?").get(e);return n?n.id:(process.stderr.write(`session not found: ${e}
1448
+ `),n.length===0?0:1;for(let r of s){let o=r.ok?d.ok("\u2713"):d.err("\u2717"),i=`${r.durationMs} ms`;console.log(` ${o} ${r.step.padEnd(28)} ${d.dim(i)}`),r.error&&console.log(` ${d.err(r.error)}`)}return n.length===0?(console.log(""),console.log(d.ok("All maintenance passes completed.")),e.vacuum||console.log(d.dim(" Run `recall optimize --vacuum` (with the daemon stopped) to reclaim disk pages from deleted rows.")),0):(console.log(""),console.log(d.warn(`${n.length} step(s) failed \u2014 review the errors above.`)),1)}I();T();j();import{existsSync as xb,readFileSync as Rb}from"node:fs";function kb(){let e=`${x}/daemon.port`;if(!xb(e))return null;try{let t=Rb(e,"utf8").trim();return/^\d+$/.test(t)?t:null}catch{return null}}function Nb(e){let t=_();if(e.length>=32){let n=t.prepare("SELECT id FROM sessions WHERE id = ?").get(e);return n?n.id:(process.stderr.write(`session not found: ${e}
1446
1449
  `),null)}let s=t.prepare("SELECT id FROM sessions WHERE id LIKE ? LIMIT 2").all(e+"%");return s.length===1?s[0].id:s.length===0?(process.stderr.write(`no session matches prefix "${e}"
1447
1450
  `),null):(process.stderr.write(`ambiguous session prefix "${e}". be more specific.
1448
- `),null)}async function al(e,t,s){let n=kb(e);if(!n){process.exitCode=1;return}let r=t.trim();if(!r){process.stderr.write(`name cannot be empty
1449
- `),process.exitCode=1;return}let o=Rb();if(!o){process.stderr.write("daemon is not running. start it with `recall start` so the alias write is durable.\n"),process.exitCode=1;return}let i;try{i=await tt("PUT",`http://127.0.0.1:${o}/api/sessions/${encodeURIComponent(n)}/alias`,{alias:r,pin:s.pin===!0})}catch(l){process.stderr.write(`failed to reach daemon at 127.0.0.1:${o}: ${l.message}
1451
+ `),null)}async function al(e,t,s){let n=Nb(e);if(!n){process.exitCode=1;return}let r=t.trim();if(!r){process.stderr.write(`name cannot be empty
1452
+ `),process.exitCode=1;return}let o=kb();if(!o){process.stderr.write("daemon is not running. start it with `recall start` so the alias write is durable.\n"),process.exitCode=1;return}let i;try{i=await tt("PUT",`http://127.0.0.1:${o}/api/sessions/${encodeURIComponent(n)}/alias`,{alias:r,pin:s.pin===!0})}catch(l){process.stderr.write(`failed to reach daemon at 127.0.0.1:${o}: ${l.message}
1450
1453
  `),process.exitCode=1;return}if(!i.ok){let l="";try{l=await i.text()}catch{}process.stderr.write(`daemon rejected alias write (HTTP ${i.status}): ${l}
1451
- `),process.exitCode=1;return}let a={session_id:n,alias:r};if(s.json){console.log(JSON.stringify(a));return}console.log(`${d.ok("renamed")} ${d.dim(n.slice(0,8))} \u2192 ${d.bold(`"${r}"`)}`)}I();T();var dl=90;async function Nb(){try{let e=`${process.env.HOME}/.recall/daemon.port`,t=await import("node:fs");if(!t.existsSync(e))return null;let s=t.readFileSync(e,"utf8").trim(),n=await _t(`http://127.0.0.1:${s}/api/terminal/registry`);return n.ok?await n.json():null}catch{return null}}function Cb(){let e=Date.now()/1e3-dl;return _().prepare(`SELECT s.id, s.cwd, s.file_mtime, NULLIF(sa.alias, '') AS alias
1454
+ `),process.exitCode=1;return}let a={session_id:n,alias:r};if(s.json){console.log(JSON.stringify(a));return}console.log(`${d.ok("renamed")} ${d.dim(n.slice(0,8))} \u2192 ${d.bold(`"${r}"`)}`)}I();T();var dl=90;async function Cb(){try{let e=`${process.env.HOME}/.recall/daemon.port`,t=await import("node:fs");if(!t.existsSync(e))return null;let s=t.readFileSync(e,"utf8").trim(),n=await _t(`http://127.0.0.1:${s}/api/terminal/registry`);return n.ok?await n.json():null}catch{return null}}function Lb(){let e=Date.now()/1e3-dl;return _().prepare(`SELECT s.id, s.cwd, s.file_mtime, NULLIF(sa.alias, '') AS alias
1452
1455
  FROM sessions s
1453
1456
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1454
1457
  WHERE s.cwd IS NOT NULL AND s.file_mtime > ?
1455
- ORDER BY s.cwd, s.file_mtime DESC`).all(e)}var Lb=new Set(["zsh","bash","fish","sh","dash","ksh","tcsh","csh","pwsh","powershell","cmd","nu"]);function cl(e){let t=e.trim().toLowerCase().replace(/^[-/]+/,"").replace(/^.*\//,"").replace(/\s*\(\d+\)\s*$/,"").trim();return!t||Lb.has(t)}var Ob=/^[⠀-⣿✳\s]+/,Ab=/^\d+(\.\d+){1,3}$/;function ll(e){let t=e.trim();return!!(!t||Ob.test(t)||Ab.test(t))}async function ul(e){let t=await Nb(),s=Cb();if(e.json){console.log(JSON.stringify({registry:t,active:s},null,2));return}if(console.log(),console.log(d.bold("TERMINAL REGISTRY")),console.log(d.dim("(what the daemon thinks each VS Code terminal is named)")),console.log(),!t){console.log(d.err(" Could not reach daemon. Is recall start running?"));return}let n=new Map;for(let o of t.terminals){let i=o.cwd??"(no cwd)",a=n.get(i);a||(a=[],n.set(i,a)),a.push(o)}for(let[o,i]of n){console.log(d.dim(` cwd: ${o}`));for(let a of i){let l=cl(a.tab_name),c=ll(a.tab_name),p=!l&&!c?d.ok("[usable]"):l?d.warn("[generic-shell]"):d.warn("[claude-auto]");console.log(` ${p} pid ${a.shell_pid} ${d.bold(`"${a.tab_name}"`)}`)}console.log()}if(console.log(d.bold(`ACTIVE SESSIONS (mtime within last ${dl}s)`)),console.log(d.dim("(sessions whose JSONL is being actively written)")),console.log(),s.length===0){console.log(d.dim(" (none)")),console.log();return}let r=new Map;for(let o of s){let i=r.get(o.cwd);i||(i=[],r.set(o.cwd,i)),i.push(o)}for(let[o,i]of r){console.log(d.dim(` cwd: ${o}`));for(let a of i)console.log(` ${d.dim(a.id.slice(0,8))} ${d.bold(a.alias??"(no alias)")} ${d.dim(`mtime ${new Date(a.file_mtime*1e3).toISOString().slice(11,19)}`)}`);console.log()}console.log(d.bold("LAYER 5 SWEEP DECISIONS")),console.log(d.dim("(what the live correlator would do for each cwd right now)")),console.log();for(let[o,i]of r){let l=(n.get(o)??[]).filter(c=>!cl(c.tab_name)&&!ll(c.tab_name));l.length===0?console.log(` ${d.warn("skip")} ${d.dim(o)} ${d.dim("\u2014 no usable terminal name (all generic or claude-auto)")}`):l.length>1?console.log(` ${d.warn("refuse")} ${d.dim(o)} ${d.dim(`\u2014 ${l.length} usable terminals, ambiguous`)}`):i.length>1?console.log(` ${d.warn("refuse")} ${d.dim(o)} ${d.dim(`\u2014 ${i.length} active sessions, ambiguous`)}`):console.log(` ${d.ok("link")} ${d.dim(o)} ${d.dim("\u2192")} ${d.dim(i[0].id.slice(0,8))} ${d.dim("=")} ${d.bold(`"${l[0].tab_name}"`)}`)}console.log()}I();T();j();import{existsSync as Ib,readFileSync as vb}from"node:fs";function Mb(){let e=`${x}/daemon.port`;if(!Ib(e))return null;try{let t=vb(e,"utf8").trim();return/^\d+$/.test(t)?t:null}catch{return null}}async function Db(e){try{let t=await _t(`http://127.0.0.1:${e}/api/terminal/registry`);return t.ok?(await t.json()).terminals??[]:[]}catch{return[]}}async function $b(e,t,s){try{return(await tt("POST",`http://127.0.0.1:${e}/api/sessions/${encodeURIComponent(t)}/relink`,{shell_pid:s})).ok}catch{return!1}}function jb(e){try{let t=JSON.parse(e);if(!Array.isArray(t))return null;for(let s=t.length-1;s>=0;s--){let n=t[s];if(n&&typeof n.alias=="string"&&n.alias!=="")return n.alias}return null}catch{return null}}function Pb(e){let t=new Map;for(let i of e){if(!i.cwd)continue;let a=i.cwd.replace(/\/+$/,""),l=t.get(a);l||(l=new Map,t.set(a,l)),l.set(i.tab_name,i.shell_pid)}let s=new Map;for(let i of e){if(!i.cwd)continue;let l=`${i.cwd.replace(/\/+$/,"")}::${i.tab_name}`,c=s.get(l);c||(c=new Set,s.set(l,c)),c.add(String(i.shell_pid))}let r=_().prepare(`SELECT sa.session_id, s.cwd, sa.previous_aliases
1458
+ ORDER BY s.cwd, s.file_mtime DESC`).all(e)}var Ob=new Set(["zsh","bash","fish","sh","dash","ksh","tcsh","csh","pwsh","powershell","cmd","nu"]);function cl(e){let t=e.trim().toLowerCase().replace(/^[-/]+/,"").replace(/^.*\//,"").replace(/\s*\(\d+\)\s*$/,"").trim();return!t||Ob.has(t)}var Ab=/^[⠀-⣿✳\s]+/,Ib=/^\d+(\.\d+){1,3}$/;function ll(e){let t=e.trim();return!!(!t||Ab.test(t)||Ib.test(t))}async function ul(e){let t=await Cb(),s=Lb();if(e.json){console.log(JSON.stringify({registry:t,active:s},null,2));return}if(console.log(),console.log(d.bold("TERMINAL REGISTRY")),console.log(d.dim("(what the daemon thinks each VS Code terminal is named)")),console.log(),!t){console.log(d.err(" Could not reach daemon. Is recall start running?"));return}let n=new Map;for(let o of t.terminals){let i=o.cwd??"(no cwd)",a=n.get(i);a||(a=[],n.set(i,a)),a.push(o)}for(let[o,i]of n){console.log(d.dim(` cwd: ${o}`));for(let a of i){let l=cl(a.tab_name),c=ll(a.tab_name),p=!l&&!c?d.ok("[usable]"):l?d.warn("[generic-shell]"):d.warn("[claude-auto]");console.log(` ${p} pid ${a.shell_pid} ${d.bold(`"${a.tab_name}"`)}`)}console.log()}if(console.log(d.bold(`ACTIVE SESSIONS (mtime within last ${dl}s)`)),console.log(d.dim("(sessions whose JSONL is being actively written)")),console.log(),s.length===0){console.log(d.dim(" (none)")),console.log();return}let r=new Map;for(let o of s){let i=r.get(o.cwd);i||(i=[],r.set(o.cwd,i)),i.push(o)}for(let[o,i]of r){console.log(d.dim(` cwd: ${o}`));for(let a of i)console.log(` ${d.dim(a.id.slice(0,8))} ${d.bold(a.alias??"(no alias)")} ${d.dim(`mtime ${new Date(a.file_mtime*1e3).toISOString().slice(11,19)}`)}`);console.log()}console.log(d.bold("LAYER 5 SWEEP DECISIONS")),console.log(d.dim("(what the live correlator would do for each cwd right now)")),console.log();for(let[o,i]of r){let l=(n.get(o)??[]).filter(c=>!cl(c.tab_name)&&!ll(c.tab_name));l.length===0?console.log(` ${d.warn("skip")} ${d.dim(o)} ${d.dim("\u2014 no usable terminal name (all generic or claude-auto)")}`):l.length>1?console.log(` ${d.warn("refuse")} ${d.dim(o)} ${d.dim(`\u2014 ${l.length} usable terminals, ambiguous`)}`):i.length>1?console.log(` ${d.warn("refuse")} ${d.dim(o)} ${d.dim(`\u2014 ${i.length} active sessions, ambiguous`)}`):console.log(` ${d.ok("link")} ${d.dim(o)} ${d.dim("\u2192")} ${d.dim(i[0].id.slice(0,8))} ${d.dim("=")} ${d.bold(`"${l[0].tab_name}"`)}`)}console.log()}I();T();j();import{existsSync as vb,readFileSync as Mb}from"node:fs";function $b(){let e=`${x}/daemon.port`;if(!vb(e))return null;try{let t=Mb(e,"utf8").trim();return/^\d+$/.test(t)?t:null}catch{return null}}async function Db(e){try{let t=await _t(`http://127.0.0.1:${e}/api/terminal/registry`);return t.ok?(await t.json()).terminals??[]:[]}catch{return[]}}async function jb(e,t,s){try{return(await tt("POST",`http://127.0.0.1:${e}/api/sessions/${encodeURIComponent(t)}/relink`,{shell_pid:s})).ok}catch{return!1}}function Pb(e){try{let t=JSON.parse(e);if(!Array.isArray(t))return null;for(let s=t.length-1;s>=0;s--){let n=t[s];if(n&&typeof n.alias=="string"&&n.alias!=="")return n.alias}return null}catch{return null}}function Fb(e){let t=new Map;for(let i of e){if(!i.cwd)continue;let a=i.cwd.replace(/\/+$/,""),l=t.get(a);l||(l=new Map,t.set(a,l)),l.set(i.tab_name,i.shell_pid)}let s=new Map;for(let i of e){if(!i.cwd)continue;let l=`${i.cwd.replace(/\/+$/,"")}::${i.tab_name}`,c=s.get(l);c||(c=new Set,s.set(l,c)),c.add(String(i.shell_pid))}let r=_().prepare(`SELECT sa.session_id, s.cwd, sa.previous_aliases
1456
1459
  FROM session_aliases sa
1457
1460
  JOIN sessions s ON s.id = sa.session_id
1458
- WHERE sa.alias = '' AND sa.previous_aliases != '[]' AND s.cwd IS NOT NULL`).all(),o=[];for(let i of r){let a=jb(i.previous_aliases);if(!a)continue;let l=i.cwd.replace(/\/+$/,""),u=t.get(l)?.get(a);if(!u)continue;let p=s.get(`${l}::${a}`);p&&p.size>1||o.push({session_id:i.session_id,cwd:l,alias_to_restore:a,matching_pid:u})}return o}async function pl(e){let t=Mb();t||(console.error(d.err("Daemon is not running. Run `recall start` first.")),process.exit(1));let s=await Db(t);s.length===0&&(console.error(d.err("Registry is empty. Open VS Code with the extension to populate it.")),process.exit(1));let n=Pb(s);if(e.json){console.log(JSON.stringify({candidates:n},null,2));return}if(n.length===0){console.log(d.dim("No restorable sessions found.")),console.log(d.dim("A session is restorable when its previous alias still matches a currently-open terminal in the same cwd, with no name collisions."));return}console.log(d.bold(`Found ${n.length} session${n.length===1?"":"s"} that can be cleanly restored:`)),console.log();let r=new Map;for(let a of n){let l=r.get(a.cwd);l||(l=[],r.set(a.cwd,l)),l.push(a)}for(let[a,l]of r){console.log(d.dim(` cwd: ${a}`));for(let c of l)console.log(` ${d.dim(c.session_id.slice(0,8))} ${d.dim("\u2192 pid")} ${c.matching_pid} ${d.dim("=")} ${d.bold(`"${c.alias_to_restore}"`)}`);console.log()}if(!e.apply){console.log(d.dim("Re-run with --apply to restore these aliases."));return}let o=0,i=0;for(let a of n)await $b(t,a.session_id,a.matching_pid)?o++:(i++,console.error(d.err(`failed to restore ${a.session_id.slice(0,8)}`)));console.log(d.ok(`Restored ${o} alias${o===1?"":"es"}.${i>0?` ${i} failed.`:""}`)),console.log(d.dim("Sessions whose previous alias did not cleanly match a current terminal still need manual relink via the \u{1F517} picker."))}I();async function ml(e,t){let s=e.trim();if(!/^[0-9a-fA-F]{4,40}$/.test(s)){console.error(d.err(`not a valid commit SHA: '${e}'`)),process.exit(1);return}let n=Hs(s);if(t.json){console.log(JSON.stringify(n,null,2));return}if(n.length===0){console.log(""),console.log(d.dim(`no correlated sessions for ${s}`)),console.log(d.dim(" (if you haven't yet, run `recall correlate` to backfill)")),console.log("");return}console.log(""),console.log(`${d.bold("commit")} ${d.accent(n[0].commitSha.slice(0,12))} ${d.dim(n[0].committedAt??"")}`),n[0].subject&&console.log(` ${n[0].subject}`),console.log(""),console.log(d.dim(`authored during ${n.length} session${n.length===1?"":"s"}:`));for(let r of n){let o=r.alias??r.sessionId.slice(0,8);console.log(` ${d.accent(o.padEnd(24))} ${d.dim((r.project??"").slice(0,24).padEnd(26))} ${d.dim(r.startedAt??"")}`),console.log(` ${d.dim(`recall show ${r.sessionId}`)}`)}console.log("")}I();T();import{execFile as Fb}from"node:child_process";import{promisify as Ub}from"node:util";import{stat as Bb}from"node:fs/promises";var Hb=Ub(Fb),Wb=60,Xb=7,Jb=7,Gb=5e3;function zb(){let e=_(),t=s=>{try{return!!e.prepare(s).get()}catch{return!1}};return{semantic:t("SELECT 1 FROM session_semantic LIMIT 1"),cost:t(`SELECT 1 FROM sessions
1461
+ WHERE sa.alias = '' AND sa.previous_aliases != '[]' AND s.cwd IS NOT NULL`).all(),o=[];for(let i of r){let a=Pb(i.previous_aliases);if(!a)continue;let l=i.cwd.replace(/\/+$/,""),u=t.get(l)?.get(a);if(!u)continue;let p=s.get(`${l}::${a}`);p&&p.size>1||o.push({session_id:i.session_id,cwd:l,alias_to_restore:a,matching_pid:u})}return o}async function pl(e){let t=$b();t||(console.error(d.err("Daemon is not running. Run `recall start` first.")),process.exit(1));let s=await Db(t);s.length===0&&(console.error(d.err("Registry is empty. Open VS Code with the extension to populate it.")),process.exit(1));let n=Fb(s);if(e.json){console.log(JSON.stringify({candidates:n},null,2));return}if(n.length===0){console.log(d.dim("No restorable sessions found.")),console.log(d.dim("A session is restorable when its previous alias still matches a currently-open terminal in the same cwd, with no name collisions."));return}console.log(d.bold(`Found ${n.length} session${n.length===1?"":"s"} that can be cleanly restored:`)),console.log();let r=new Map;for(let a of n){let l=r.get(a.cwd);l||(l=[],r.set(a.cwd,l)),l.push(a)}for(let[a,l]of r){console.log(d.dim(` cwd: ${a}`));for(let c of l)console.log(` ${d.dim(c.session_id.slice(0,8))} ${d.dim("\u2192 pid")} ${c.matching_pid} ${d.dim("=")} ${d.bold(`"${c.alias_to_restore}"`)}`);console.log()}if(!e.apply){console.log(d.dim("Re-run with --apply to restore these aliases."));return}let o=0,i=0;for(let a of n)await jb(t,a.session_id,a.matching_pid)?o++:(i++,console.error(d.err(`failed to restore ${a.session_id.slice(0,8)}`)));console.log(d.ok(`Restored ${o} alias${o===1?"":"es"}.${i>0?` ${i} failed.`:""}`)),console.log(d.dim("Sessions whose previous alias did not cleanly match a current terminal still need manual relink via the \u{1F517} picker."))}I();async function ml(e,t){let s=e.trim();if(!/^[0-9a-fA-F]{4,40}$/.test(s)){console.error(d.err(`not a valid commit SHA: '${e}'`)),process.exit(1);return}let n=Hs(s);if(t.json){console.log(JSON.stringify(n,null,2));return}if(n.length===0){console.log(""),console.log(d.dim(`no correlated sessions for ${s}`)),console.log(d.dim(" (if you haven't yet, run `recall correlate` to backfill)")),console.log("");return}console.log(""),console.log(`${d.bold("commit")} ${d.accent(n[0].commitSha.slice(0,12))} ${d.dim(n[0].committedAt??"")}`),n[0].subject&&console.log(` ${n[0].subject}`),console.log(""),console.log(d.dim(`authored during ${n.length} session${n.length===1?"":"s"}:`));for(let r of n){let o=r.alias??r.sessionId.slice(0,8);console.log(` ${d.accent(o.padEnd(24))} ${d.dim((r.project??"").slice(0,24).padEnd(26))} ${d.dim(r.startedAt??"")}`),console.log(` ${d.dim(`recall show ${r.sessionId}`)}`)}console.log("")}I();T();import{execFile as Ub}from"node:child_process";import{promisify as Bb}from"node:util";import{stat as Hb}from"node:fs/promises";var Wb=Bb(Ub),Xb=60,Jb=7,Gb=7,zb=5e3;function Yb(){let e=_(),t=s=>{try{return!!e.prepare(s).get()}catch{return!1}};return{semantic:t("SELECT 1 FROM session_semantic LIMIT 1"),cost:t(`SELECT 1 FROM sessions
1459
1462
  WHERE (COALESCE(total_input_tokens,0)
1460
1463
  + COALESCE(total_output_tokens,0)
1461
1464
  + COALESCE(total_cache_create_tokens,0)
1462
1465
  + COALESCE(total_cache_read_tokens,0)) > 0
1463
- LIMIT 1`),git:t("SELECT 1 FROM session_commits LIMIT 1")}}function Dr(e){if(!e)return[];let t=new Set,s=[];for(let n of e.split(",")){let r=n.trim().toLowerCase();!r||t.has(r)||(t.add(r),s.push(r))}return s}function gl(e){return{sessionId:e.session_id,project:e.project,alias:e.alias,startedAt:e.started_at,endedAt:e.ended_at,firstUserMessage:e.first_user_message}}function Yb(){let e=_(),t=e.prepare(`SELECT ss.keywords
1466
+ LIMIT 1`),git:t("SELECT 1 FROM session_commits LIMIT 1")}}function $r(e){if(!e)return[];let t=new Set,s=[];for(let n of e.split(",")){let r=n.trim().toLowerCase();!r||t.has(r)||(t.add(r),s.push(r))}return s}function gl(e){return{sessionId:e.session_id,project:e.project,alias:e.alias,startedAt:e.started_at,endedAt:e.ended_at,firstUserMessage:e.first_user_message}}function qb(){let e=_(),t=e.prepare(`SELECT ss.keywords
1464
1467
  FROM session_semantic ss
1465
1468
  JOIN sessions s ON s.id = ss.session_id
1466
1469
  WHERE s.started_at IS NOT NULL
1467
- AND julianday('now') - julianday(s.started_at) <= @windowDays`).all({windowDays:Xb});if(t.length===0)return null;let s=new Set;for(let o of t)for(let i of Dr(o.keywords))s.add(i);if(s.size===0)return null;let n=e.prepare(`SELECT ss.session_id AS session_id,
1470
+ AND julianday('now') - julianday(s.started_at) <= @windowDays`).all({windowDays:Jb});if(t.length===0)return null;let s=new Set;for(let o of t)for(let i of $r(o.keywords))s.add(i);if(s.size===0)return null;let n=e.prepare(`SELECT ss.session_id AS session_id,
1468
1471
  ss.summary AS summary,
1469
1472
  ss.keywords AS keywords,
1470
1473
  p.name AS project,
@@ -1480,7 +1483,7 @@ Top ${l.length} cluster(s):`);for(let c of l){let u=c.status==="resolved"?"\u271
1480
1483
  WHERE s.started_at IS NOT NULL
1481
1484
  AND s.message_count > 2
1482
1485
  AND julianday('now') - julianday(s.started_at) >= @ageDays
1483
- ORDER BY s.started_at ASC`).all({ageDays:Wb});if(n.length===0)return null;let r=null;for(let o of n){let a=Dr(o.keywords).filter(l=>s.has(l));a.length!==0&&(!r||a.length>r.overlap.length)&&(r={row:o,overlap:a})}return r?{...gl(r.row),summary:r.row.summary,keywords:Dr(r.row.keywords),matchedKeywords:r.overlap,daysAgo:Math.max(0,Math.round(r.row.days_old))}:null}function qb(){let t=_().prepare(`SELECT s.id AS session_id,
1486
+ ORDER BY s.started_at ASC`).all({ageDays:Xb});if(n.length===0)return null;let r=null;for(let o of n){let a=$r(o.keywords).filter(l=>s.has(l));a.length!==0&&(!r||a.length>r.overlap.length)&&(r={row:o,overlap:a})}return r?{...gl(r.row),summary:r.row.summary,keywords:$r(r.row.keywords),matchedKeywords:r.overlap,daysAgo:Math.max(0,Math.round(r.row.days_old))}:null}function Kb(){let t=_().prepare(`SELECT s.id AS session_id,
1484
1487
  p.name AS project,
1485
1488
  NULLIF(sa.alias, '') AS alias,
1486
1489
  s.started_at AS started_at,
@@ -1499,18 +1502,18 @@ Top ${l.length} cluster(s):`);for(let c of l){let u=c.status==="resolved"?"\u271
1499
1502
  AND (COALESCE(s.total_input_tokens, 0)
1500
1503
  + COALESCE(s.total_output_tokens, 0)
1501
1504
  + COALESCE(s.total_cache_create_tokens, 0)
1502
- + COALESCE(s.total_cache_read_tokens, 0)) > 0`).all({windowDays:Jb});if(t.length===0)return null;let s=null;for(let n of t){let r=Ie({inputTokens:n.input_tokens,outputTokens:n.output_tokens,cacheCreateTokens:n.cache_create_tokens,cacheReadTokens:n.cache_read_tokens},n.primary_model);r.cents<=0||(!s||r.cents>s.cents)&&(s={row:n,cents:r.cents,totalTokens:r.totalTokens})}return s?{...gl(s.row),totalTokens:s.totalTokens,costCents:s.cents,costDisplay:se(s.cents),tokensDisplay:le(s.totalTokens),primaryModel:s.row.primary_model,primaryModelLabel:et(s.row.primary_model).label}:null}async function Kb(e){try{if(!(await Bb(e)).isDirectory())return null}catch{return null}try{let{stdout:t}=await Hb("git",["rev-parse","HEAD"],{cwd:e,timeout:Gb}),s=t.trim();return/^[0-9a-f]{40}$/.test(s)?s:null}catch{return null}}async function Vb(){let e=_(),t=e.prepare(`SELECT s.id AS id, s.cwd AS cwd
1505
+ + COALESCE(s.total_cache_read_tokens, 0)) > 0`).all({windowDays:Gb});if(t.length===0)return null;let s=null;for(let n of t){let r=Ie({inputTokens:n.input_tokens,outputTokens:n.output_tokens,cacheCreateTokens:n.cache_create_tokens,cacheReadTokens:n.cache_read_tokens},n.primary_model);r.cents<=0||(!s||r.cents>s.cents)&&(s={row:n,cents:r.cents,totalTokens:r.totalTokens})}return s?{...gl(s.row),totalTokens:s.totalTokens,costCents:s.cents,costDisplay:se(s.cents),tokensDisplay:le(s.totalTokens),primaryModel:s.row.primary_model,primaryModelLabel:et(s.row.primary_model).label}:null}async function Vb(e){try{if(!(await Hb(e)).isDirectory())return null}catch{return null}try{let{stdout:t}=await Wb("git",["rev-parse","HEAD"],{cwd:e,timeout:zb}),s=t.trim();return/^[0-9a-f]{40}$/.test(s)?s:null}catch{return null}}async function Zb(){let e=_(),t=e.prepare(`SELECT s.id AS id, s.cwd AS cwd
1503
1506
  FROM sessions s
1504
1507
  WHERE s.cwd IS NOT NULL AND s.started_at IS NOT NULL
1505
1508
  ORDER BY COALESCE(s.ended_at, s.started_at, '') DESC
1506
- LIMIT 1`).get();if(!t?.cwd)return null;let s=await Kb(t.cwd);if(!s)return null;let n=Hs(s);if(n.length===0)return null;let r=n[0],o=e.prepare(`SELECT s.first_user_message AS first_user_message, s.ended_at AS ended_at
1509
+ LIMIT 1`).get();if(!t?.cwd)return null;let s=await Vb(t.cwd);if(!s)return null;let n=Hs(s);if(n.length===0)return null;let r=n[0],o=e.prepare(`SELECT s.first_user_message AS first_user_message, s.ended_at AS ended_at
1507
1510
  FROM sessions s
1508
- WHERE s.id = ?`).get(r.sessionId);return{sessionId:r.sessionId,project:r.project,alias:r.alias,startedAt:r.startedAt,endedAt:o?.ended_at??r.endedAt,firstUserMessage:o?.first_user_message??null,commitSha:r.commitSha,shortSha:r.commitSha.slice(0,7),subject:r.subject,committedAt:r.committedAt,cwd:t.cwd}}async function fl(){let e=zb(),t=e.semantic?Promise.resolve().then(()=>{try{return Yb()}catch(a){return console.error("[discover.rediscovered]",a),null}}):Promise.resolve(null),s=e.cost?Promise.resolve().then(()=>{try{return qb()}catch(a){return console.error("[discover.expensive]",a),null}}):Promise.resolve(null),n=e.git?Vb().catch(a=>(console.error("[discover.authored]",a),null)):Promise.resolve(null),[r,o,i]=await Promise.all([t,s,n]);return{rediscovered:r,expensive:o,authored:i,availability:e,generatedAt:new Date().toISOString()}}function jr(e,t=60){if(!e)return"";let s=e.replace(/\s+/g," ").trim();return s.length<=t?s:s.slice(0,t-1)+"\u2026"}function $r(e){return e.alias??(e.firstUserMessage?jr(e.firstUserMessage,60):null)??e.sessionId.slice(0,8)}function Zb(e){let t=e.rediscovered||e.expensive||e.authored;if(console.log(""),console.log(d.bold("today \xB7 for you")),console.log(d.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),!t){let s=[];e.availability.semantic||s.push("v0.11 semantic (`recall semantic on`)"),e.availability.cost||s.push("v0.10a cost (`recall stats --backfill`)"),e.availability.git||s.push("v0.10b git (`recall correlate`)"),console.log(d.dim(" no picks today.")),s.length>0?console.log(d.dim(" enable: "+s.join(", "))):console.log(d.dim(" data sources are live but nothing matched \u2014 try again tomorrow.")),console.log("");return}if(e.rediscovered){let s=e.rediscovered;console.log(""),console.log(` ${d.tool("\u2726 rediscovered")} ${d.dim(`(${s.daysAgo}d ago)`)}`),console.log(` ${d.bold($r(s))} ${d.dim(s.project?`\xB7 ${s.project}`:"")}`),console.log(` ${d.dim(s.sessionId.slice(0,8))}`),s.matchedKeywords.length>0&&console.log(" "+d.dim("matched: ")+s.matchedKeywords.slice(0,6).map(n=>d.tool(`#${n}`)).join(" ")),s.summary&&console.log(" "+d.dim(jr(s.summary,100)))}if(e.expensive){let s=e.expensive;console.log(""),console.log(` ${d.accent("$ most expensive \xB7 7d")} ${d.bold(s.costDisplay)} ${d.dim(`(${s.tokensDisplay} \xB7 ${s.primaryModelLabel})`)}`),console.log(` ${d.bold($r(s))} ${d.dim(s.project?`\xB7 ${s.project}`:"")}`),console.log(` ${d.dim(s.sessionId.slice(0,8))} ${d.dim(s.startedAt?W(s.startedAt):"")}`)}if(e.authored){let s=e.authored;console.log(""),console.log(` ${d.ok("\u2387 authored current HEAD")} ${d.bold(s.shortSha)} ${d.dim(s.committedAt?`(${W(s.committedAt)})`:"")}`),console.log(` ${d.bold($r(s))} ${d.dim(s.project?`\xB7 ${s.project}`:"")}`),s.subject&&console.log(` ${d.dim(jr(s.subject,80))}`),console.log(` ${d.dim(s.sessionId.slice(0,8))} ${d.dim("cwd: "+s.cwd)}`)}console.log("")}async function _l(e){let t=await fl();if(e.json){console.log(JSON.stringify(t,null,2));return}Zb(t)}I();import{spawnSync as Sl}from"node:child_process";import{readdirSync as Qb}from"node:fs";import{join as eS,resolve as tS}from"node:path";var Pr=["code","cursor","code-insiders","windsurf"],hl=[{id:"code",label:"VS Code"},{id:"cursor",label:"Cursor"},{id:"code-insiders",label:"VS Code Insiders"},{id:"windsurf",label:"Windsurf"}],sS="https://marketplace.visualstudio.com/items?itemName=clauderecallhq.clauderecall-vscode";function nS(){return eS(Te(),"extensions","vscode")}function rS(){let e=nS(),t;try{t=Qb(e)}catch{return null}let s=t.filter(n=>/^(clauderecall|claude-recall)-vscode-.*\.vsix$/i.test(n));return s.length===0?null:(s.sort((n,r)=>r.localeCompare(n,void 0,{numeric:!0})),tS(e,s[0]))}function El(e){let t=Sl(e,["--version"],{stdio:"ignore",shell:process.platform==="win32"});return t.error?!1:t.status===0}function oS(e,t){let s=Sl(e,["--install-extension",t],{stdio:"pipe",encoding:"utf8",shell:process.platform==="win32"});return s.error?{ok:!1,message:s.error.message}:s.status!==0?{ok:!1,message:(s.stderr??"").trim()||`exit code ${s.status??"null"}`}:{ok:!0,message:""}}function bl(){process.stderr.write(d.err(`no bundled .vsix found at extensions/vscode/(clauderecall|claude-recall)-vscode-*.vsix
1511
+ WHERE s.id = ?`).get(r.sessionId);return{sessionId:r.sessionId,project:r.project,alias:r.alias,startedAt:r.startedAt,endedAt:o?.ended_at??r.endedAt,firstUserMessage:o?.first_user_message??null,commitSha:r.commitSha,shortSha:r.commitSha.slice(0,7),subject:r.subject,committedAt:r.committedAt,cwd:t.cwd}}async function fl(){let e=Yb(),t=e.semantic?Promise.resolve().then(()=>{try{return qb()}catch(a){return console.error("[discover.rediscovered]",a),null}}):Promise.resolve(null),s=e.cost?Promise.resolve().then(()=>{try{return Kb()}catch(a){return console.error("[discover.expensive]",a),null}}):Promise.resolve(null),n=e.git?Zb().catch(a=>(console.error("[discover.authored]",a),null)):Promise.resolve(null),[r,o,i]=await Promise.all([t,s,n]);return{rediscovered:r,expensive:o,authored:i,availability:e,generatedAt:new Date().toISOString()}}function jr(e,t=60){if(!e)return"";let s=e.replace(/\s+/g," ").trim();return s.length<=t?s:s.slice(0,t-1)+"\u2026"}function Dr(e){return e.alias??(e.firstUserMessage?jr(e.firstUserMessage,60):null)??e.sessionId.slice(0,8)}function Qb(e){let t=e.rediscovered||e.expensive||e.authored;if(console.log(""),console.log(d.bold("today \xB7 for you")),console.log(d.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")),!t){let s=[];e.availability.semantic||s.push("v0.11 semantic (`recall semantic on`)"),e.availability.cost||s.push("v0.10a cost (`recall stats --backfill`)"),e.availability.git||s.push("v0.10b git (`recall correlate`)"),console.log(d.dim(" no picks today.")),s.length>0?console.log(d.dim(" enable: "+s.join(", "))):console.log(d.dim(" data sources are live but nothing matched \u2014 try again tomorrow.")),console.log("");return}if(e.rediscovered){let s=e.rediscovered;console.log(""),console.log(` ${d.tool("\u2726 rediscovered")} ${d.dim(`(${s.daysAgo}d ago)`)}`),console.log(` ${d.bold(Dr(s))} ${d.dim(s.project?`\xB7 ${s.project}`:"")}`),console.log(` ${d.dim(s.sessionId.slice(0,8))}`),s.matchedKeywords.length>0&&console.log(" "+d.dim("matched: ")+s.matchedKeywords.slice(0,6).map(n=>d.tool(`#${n}`)).join(" ")),s.summary&&console.log(" "+d.dim(jr(s.summary,100)))}if(e.expensive){let s=e.expensive;console.log(""),console.log(` ${d.accent("$ most expensive \xB7 7d")} ${d.bold(s.costDisplay)} ${d.dim(`(${s.tokensDisplay} \xB7 ${s.primaryModelLabel})`)}`),console.log(` ${d.bold(Dr(s))} ${d.dim(s.project?`\xB7 ${s.project}`:"")}`),console.log(` ${d.dim(s.sessionId.slice(0,8))} ${d.dim(s.startedAt?W(s.startedAt):"")}`)}if(e.authored){let s=e.authored;console.log(""),console.log(` ${d.ok("\u2387 authored current HEAD")} ${d.bold(s.shortSha)} ${d.dim(s.committedAt?`(${W(s.committedAt)})`:"")}`),console.log(` ${d.bold(Dr(s))} ${d.dim(s.project?`\xB7 ${s.project}`:"")}`),s.subject&&console.log(` ${d.dim(jr(s.subject,80))}`),console.log(` ${d.dim(s.sessionId.slice(0,8))} ${d.dim("cwd: "+s.cwd)}`)}console.log("")}async function _l(e){let t=await fl();if(e.json){console.log(JSON.stringify(t,null,2));return}Qb(t)}I();import{spawnSync as Sl}from"node:child_process";import{readdirSync as eS}from"node:fs";import{join as tS,resolve as sS}from"node:path";var Pr=["code","cursor","code-insiders","windsurf"],hl=[{id:"code",label:"VS Code"},{id:"cursor",label:"Cursor"},{id:"code-insiders",label:"VS Code Insiders"},{id:"windsurf",label:"Windsurf"}],nS="https://marketplace.visualstudio.com/items?itemName=clauderecallhq.clauderecall-vscode";function rS(){return tS(Te(),"extensions","vscode")}function oS(){let e=rS(),t;try{t=eS(e)}catch{return null}let s=t.filter(n=>/^(clauderecall|claude-recall)-vscode-.*\.vsix$/i.test(n));return s.length===0?null:(s.sort((n,r)=>r.localeCompare(n,void 0,{numeric:!0})),sS(e,s[0]))}function El(e){let t=Sl(e,["--version"],{stdio:"ignore",shell:process.platform==="win32"});return t.error?!1:t.status===0}function iS(e,t){let s=Sl(e,["--install-extension",t],{stdio:"pipe",encoding:"utf8",shell:process.platform==="win32"});return s.error?{ok:!1,message:s.error.message}:s.status!==0?{ok:!1,message:(s.stderr??"").trim()||`exit code ${s.status??"null"}`}:{ok:!0,message:""}}function bl(){process.stderr.write(d.err(`no bundled .vsix found at extensions/vscode/(clauderecall|claude-recall)-vscode-*.vsix
1509
1512
  `)),process.stderr.write(d.dim(`see PUBLISHING.md for how to build the extension, or run:
1510
1513
  `)),process.stderr.write(d.dim(` (cd extensions/vscode && npm install && npm run build && npm run package)
1511
- `))}function iS(e){return Pr.includes(e)}async function yl(e){if(e.editor!==void 0&&!iS(e.editor)){process.stderr.write(d.err(`unknown --editor target: ${e.editor}
1514
+ `))}function aS(e){return Pr.includes(e)}async function yl(e){if(e.editor!==void 0&&!aS(e.editor)){process.stderr.write(d.err(`unknown --editor target: ${e.editor}
1512
1515
  `)),process.stderr.write(d.dim(`valid values: ${Pr.join(", ")}
1513
- `)),process.exitCode=1;return}let t=rS();if(e.printPath){if(!t){bl(),process.exitCode=1;return}process.stdout.write(t+`
1516
+ `)),process.exitCode=1;return}let t=oS();if(e.printPath){if(!t){bl(),process.exitCode=1;return}process.stdout.write(t+`
1514
1517
  `);return}if(!t){bl(),process.exitCode=1;return}let s;if(e.editor){let r=e.editor;if(!El(r)){process.stderr.write(d.err(`editor CLI not found on PATH: ${r}
1515
1518
  `)),process.stderr.write(d.dim(`install the editor shell integration, or omit --editor to install into every detected editor.
1516
1519
  `)),process.stderr.write(d.dim(`see PUBLISHING.md for manual install instructions.
@@ -1520,20 +1523,20 @@ Top ${l.length} cluster(s):`);for(let c of l){let u=c.status==="resolved"?"\u271
1520
1523
  `)),process.stderr.write(d.dim(`see PUBLISHING.md for manual install instructions.
1521
1524
  `)),process.exitCode=1;return}process.stderr.write(d.dim(`bundled .vsix: ${t}
1522
1525
 
1523
- `));let n=!1;for(let r of s){let{ok:o,message:i}=oS(r.id,t);o?process.stderr.write(d.ok(`\u2713 installed into ${r.label} (${r.id})
1526
+ `));let n=!1;for(let r of s){let{ok:o,message:i}=iS(r.id,t);o?process.stderr.write(d.ok(`\u2713 installed into ${r.label} (${r.id})
1524
1527
  `)):(n=!0,process.stderr.write(d.err(`\u2717 ${r.label} (${r.id}): ${i}
1525
1528
  `)))}process.stderr.write(`
1526
1529
  `),process.stderr.write(d.bold(`next steps:
1527
1530
  `)),process.stderr.write(` 1. reload the editor window: Cmd/Ctrl+Shift+P then pick "Developer: Reload Window"
1528
1531
  `),process.stderr.write(` 2. enable the extension: open settings and set "claude-recall.autoAlias" to true
1529
1532
  `),process.stderr.write(`
1530
- `),process.stderr.write(d.dim(`marketplace install: ${sS}
1531
- `)),n&&(process.exitCode=1)}Hr();I();function Wr(e){return e>=70?d.ok:e>=40?d.warn:d.err}function wl(e,t=20){let s=Math.round(e/100*t);return"\u2588".repeat(s)+"\u2591".repeat(t-s)}function aS(e){let t=Wr(e.score);process.stdout.write(`
1533
+ `),process.stderr.write(d.dim(`marketplace install: ${nS}
1534
+ `)),n&&(process.exitCode=1)}Hr();I();function Wr(e){return e>=70?d.ok:e>=40?d.warn:d.err}function wl(e,t=20){let s=Math.round(e/100*t);return"\u2588".repeat(s)+"\u2591".repeat(t-s)}function cS(e){let t=Wr(e.score);process.stdout.write(`
1532
1535
  ${d.bold(e.projectName)} ${t(String(e.score)+"/100")}
1533
1536
  `);let s=e.breakdown,n=[["Sessions",s.sessionCount.score*100,`${s.sessionCount.raw} sessions`],["Recency",s.recency.score*100,`${s.recency.daysSinceLastSession}d ago`],["Depth",s.fragmentation.score*100,`avg ${s.fragmentation.avgMessages} msgs`],["Search",s.searchCoverage.score*100,`${Math.round(s.searchCoverage.ratio*100)}% covered`],["Tags",s.tagCoverage.score*100,`${Math.round(s.tagCoverage.ratio*100)}% tagged`]];for(let[r,o,i]of n){let a=Wr(o);process.stdout.write(` ${r.padEnd(10)} ${a(wl(o,16))} ${String(Math.round(o)).padStart(3)}% ${d.dim(i)}
1534
1537
  `)}}function xl(e,t){if(e){let r=Ur(e);if(!r){process.stderr.write(d.err(`project "${e}" not found
1535
1538
  `)),process.exitCode=1;return}if(t.json){process.stdout.write(JSON.stringify(r,null,2)+`
1536
- `);return}aS(r);return}let s=Br();if(s.length===0){process.stdout.write("No projects found. Run `recall index` first.\n");return}if(t.json){process.stdout.write(JSON.stringify(s,null,2)+`
1539
+ `);return}cS(r);return}let s=Br();if(s.length===0){process.stdout.write("No projects found. Run `recall index` first.\n");return}if(t.json){process.stdout.write(JSON.stringify(s,null,2)+`
1537
1540
  `);return}let n=[...s].sort((r,o)=>r.score-o.score);process.stdout.write(d.bold("Memory Health Scores")+` (worst first)
1538
1541
 
1539
1542
  `);for(let r of n){let o=Wr(r.score);process.stdout.write(` ${o(wl(r.score,12))} ${String(r.score).padStart(3)}/100 ${r.projectName}
@@ -1543,10 +1546,10 @@ ${d.bold(e.projectName)} ${t(String(e.score)+"/100")}
1543
1546
  `);return}let t=cs();process.stdout.write(`Verification badges: ${t?d.ok("ON"):"OFF"}
1544
1547
  `),process.stdout.write(`
1545
1548
  Toggle with: recall verify on | off
1546
- `)}I();ps();In();Pt();vn();import{hostname as AS}from"node:os";import{randomBytes as IS}from"node:crypto";We();_e();j();T();import{existsSync as cS}from"node:fs";import lS from"node:readline";import{createRequire as dS}from"node:module";import{Chalk as uS}from"chalk";var pS=dS(import.meta.url),mS=pS(`${Te()}/package.json`).version,Ll="#f97316",gS="#8b9098",fS="#10b981",_S="#f59e0b",kt=new uS({level:process.env.NO_COLOR?0:3}),Ee=kt.hex(Ll),ne=kt.hex(Ll).bold,A=kt.hex(gS),Et=kt.hex(fS),Ws=kt.hex(_S),Ol=kt.bold,Al=[" \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D","\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 ","\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D ","\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"," \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D","\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 ","\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 ","\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 ","\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 ","\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557","\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],hS=Al[0]?.length??49,kl="Never lose a Claude Code session again.",ES="CLAUDE RECALL";function bS(){if(!cS(te))return{sessions:0,projects:0};try{let t=_().prepare(`SELECT
1549
+ `)}I();ps();In();Pt();vn();import{hostname as IS}from"node:os";import{randomBytes as vS}from"node:crypto";We();_e();j();T();import{existsSync as lS}from"node:fs";import dS from"node:readline";import{createRequire as uS}from"node:module";import{Chalk as pS}from"chalk";var mS=uS(import.meta.url),gS=mS(`${Te()}/package.json`).version,Ll="#f97316",fS="#8b9098",_S="#10b981",hS="#f59e0b",kt=new pS({level:process.env.NO_COLOR?0:3}),Ee=kt.hex(Ll),ne=kt.hex(Ll).bold,A=kt.hex(fS),Et=kt.hex(_S),Ws=kt.hex(hS),Ol=kt.bold,Al=[" \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D","\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2557 ","\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D ","\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557"," \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D","\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 ","\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551 ","\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 ","\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 ","\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557","\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],ES=Al[0]?.length??49,kl="Never lose a Claude Code session again.",bS="CLAUDE RECALL";function SS(){if(!lS(te))return{sessions:0,projects:0};try{let t=_().prepare(`SELECT
1547
1550
  (SELECT COUNT(*) FROM sessions) AS sessions,
1548
- (SELECT COUNT(*) FROM projects) AS projects`).get();return{sessions:t.sessions,projects:t.projects}}catch{return{sessions:0,projects:0}}}function SS(){let e=process.stdout.columns;return typeof e!="number"||e<=0?!1:e<hS+2}function Il(){if(SS()){console.log(`${ne(ES)} ${A("\xB7")} ${A(kl)}`);return}for(let e of Al)console.log(ne(e));console.log(A(kl))}async function yS(){return{daemon:K(),counts:bS(),license:await ye()}}function TS(e){let t=[];if(t.push(` ${A("Version:")} ${Ee(`v${mS}`)} ${A("\xB7 CLI \xB7 @clauderecallhq/cli")}`),e.daemon){let s=`http://127.0.0.1:${e.daemon.port}`;t.push(` ${A("Daemon:")} ${Et("running")} on ${s} ${A(`(pid ${e.daemon.pid})`)}`)}else t.push(` ${A("Daemon:")} ${Ws("stopped")}`);if(e.counts.sessions===0)t.push(` ${A("Sessions:")} ${Ws("none indexed yet")}`);else{let s=e.counts.projects===1?"project":"projects";t.push(` ${A("Sessions:")} ${Ee(String(e.counts.sessions))} indexed across ${Ee(String(e.counts.projects))} ${s}`)}return e.license.tier==="pro"?t.push(` ${A("License:")} ${Et("Pro")}`):t.push(` ${A("License:")} Free`),t}function wS(e){let t=Ee(">");if(e.counts.sessions===0)return`${t} Run ${ne("recall index")} to scan ~/.claude/projects/`;if(!e.daemon)return`${t} Run ${ne("recall start")} to launch the local daemon`;if(e.license.tier==="free")return`${t} Run ${ne("recall upgrade")} to unlock Pro features`;let s=`http://127.0.0.1:${e.daemon.port}`;return`${t} Open ${Ee(s)} in your browser ${A("\xB7")} or run ${ne("recall --help")} for all commands`}var Xs=[{title:"Setup",commands:[{name:"index",description:"Scan your Claude sessions and build the searchable database"},{name:"status",description:"Database size, session counts, and daemon state"},{name:"projects",description:"List every project with how many sessions are in each"},{name:"install-extension",description:"Install the VS Code / Cursor / Windsurf extension"},{name:"doctor",description:"Health check: DB size, WAL, FTS fragmentation, integrity, disk space, alias invariant"},{name:"optimize",description:"Maintenance: WAL checkpoint, FTS5 merge, planner stats. Add --vacuum to reclaim free pages"}]},{title:"Browse",commands:[{name:"tui",description:"Browse and search sessions in an interactive terminal UI"},{name:"list",description:"List your sessions, newest first"},{name:"show <id>",description:"Print a full session transcript"},{name:"search <query>",description:"Full-text search across every message"},{name:"similar <id>",description:"Find sessions about the same topic (Pro)"},{name:"semantic [action]",description:'Manage semantic search (defaults to "status")'},{name:"name <id> <name>",description:"Rename a session (or its terminal tab)"}]},{title:"Pipe to Claude",commands:[{name:"context <id>",description:"Pipe a past session as markdown into a fresh `claude` chat"},{name:"neighborhood <id>",description:"Bundle a session with its parents, children, and citations for richer context"}]},{title:"Threads",commands:[{name:"threads sync",description:"Capture sessions running in this repo right now into a thread"},{name:"threads sync --preflight",description:"Preview what `threads sync` would do without writing"},{name:"threads scan",description:"Auto-detect parent-child links across past sessions"},{name:"threads list",description:"List threads, newest first"},{name:"threads show <id>",description:"Show a thread's header and session tree"},{name:"threads new <name>",description:"Create a new thread"},{name:"threads link <id>",description:"Link a session into a thread"},{name:"threads unlink <id>",description:"Remove a session from a thread"},{name:"threads set-parent <id>",description:"Change a session's parent within a thread"},{name:"threads rename <id>",description:"Rename a thread"},{name:"threads close <id>",description:"Mark a thread as closed"},{name:"threads reopen <id>",description:"Reopen a closed thread"},{name:"threads archive <id>",description:"Archive a thread"},{name:"threads merge <id>",description:"Merge one thread into another"},{name:"threads split <id>",description:"Split sessions out into a new thread"}]},{title:"Inference",commands:[{name:"infer outputs",description:"Extract code, file, and error references from sessions in one project"},{name:"infer citations",description:"Find sessions that cite the same files or errors"},{name:"infer l1",description:"Fast deterministic link inference. No LLM cost"},{name:"infer links",description:"LLM-powered link classification (Pro). Optional --auto-promote"},{name:"infer bug-patterns",description:"Cluster sessions that hit the same bug"},{name:"embeddings [action]",description:'Audit embedding coverage (defaults to "audit")'}]},{title:"Analytics",commands:[{name:"stats [id]",description:"Token + dollar usage. No args = overview, pass a session for details"},{name:"health [project]",description:"Score how well-organized each project's sessions are"},{name:"digest",description:"Today's rediscovery picks and standouts"},{name:"correlate [id]",description:"Link sessions to the git commits they wrote"},{name:"blame <sha>",description:"Find which session(s) wrote the code in a commit"}]},{title:"Daemon",commands:[{name:"start",description:"Start the background daemon (live tab tracking + web UI)"},{name:"stop",description:"Stop the background daemon"},{name:"open",description:"Open the local web UI in your browser"}]},{title:"Sharing",commands:[{name:"share [id]",description:"Save a session as a shareable PNG card"},{name:"wrapped [month]",description:"Save a monthly recap as a PNG card"}]},{title:"Diagnostics",commands:[{name:"correlator audit",description:"Find sessions with bad terminal-name aliases (--fix to clear)"},{name:"correlator debug",description:"Show how the daemon is matching open terminals to sessions"},{name:"correlator restore",description:"Restore aliases that `correlator audit --fix` cleared"},{name:"titles [action]",description:'Audit session titles in the current project (defaults to "audit")'},{name:"import-vscode-state",description:"Backfill missing tab names from your editor's workspace state"},{name:"audit-secrets",description:"Scan the database for leaked secrets"}]},{title:"Integrations",commands:[{name:"mcp",description:"Expose Recall as an MCP server (for Claude Desktop / Claude Code)"},{name:"paste",description:"Save clipboard content (or stdin) into Recall"}]},{title:"Pro & License",commands:[{name:"upgrade",description:"Open the Pro pricing page"},{name:"activate <key>",description:"Activate your Pro license (run once after purchase)"},{name:"license [action]",description:"Show the current license. Use `license deactivate` to remove it"},{name:"verify [action]",description:'Toggle verification badges in the UI (defaults to "status")'}]},{title:"Feedback",commands:[{name:"feedback",description:"Send a 1-5 rating to the team. Pass --score for non-interactive use"}]}],xS=Xs.reduce((e,t)=>e+t.commands.length,0),RS=new Set([...Xs.flatMap(e=>e.commands.map(t=>t.name.split(/\s+/)[0])),"thread","correlator-audit","correlator-debug","correlator-restore","extract-outputs","infer-citations","infer-l1","infer-links","infer-bug-patterns"]);function Nl(){let e=Xs.flatMap(s=>s.commands.map(n=>`recall ${n.name}`)),t=Math.max(...e.map(s=>s.length));console.log(),console.log(`${Ol("COMMANDS")} ${A(`\xB7 ${xS} total \xB7 q to quit \xB7 recall --help for full details`)}`),console.log(` ${A("All commands run as subcommands of")} ${ne("recall")}${A(". There is no separate")} ${Ee("threads")}${A(",")} ${Ee("thread")}${A(", or")} ${Ee("titles")} ${A("binary.")}`);for(let s of Xs){console.log(),console.log(` ${ne(s.title.toUpperCase())}`);for(let n of s.commands){let r=`recall ${n.name}`.padEnd(t," ");console.log(` ${Ee(r)} ${A(n.description)}`)}}console.log()}function kS(){return!!process.stdin.isTTY&&!!process.stdout.isTTY}async function NS(){if(!kS())return;let e=lS.createInterface({input:process.stdin,output:process.stdout}),t=`${A("Type")} ${ne("/")} ${A("for commands, or press")} ${ne("Enter")} ${A("to exit")} ${Ee("\u203A")} `;return new Promise(s=>{let n=()=>{e.question(t,r=>{let o=r.trim();if(o==="/"||o==="/help"||o==="help"||o==="?"){Nl(),n();return}if(o===""||o==="q"||o==="quit"||o==="exit"){e.close();return}let i=o.startsWith("/")?o.slice(1).trimStart():o,a=i.toLowerCase();if((a==="recall"||a.startsWith("recall "))&&(i=i.slice(6).trimStart()),i===""){Nl(),n();return}let l=(i.split(/\s+/)[0]??"").toLowerCase();RS.has(l)?console.log(` ${A("Run")} ${ne(`recall ${i}`)} ${A("in your shell to invoke that command.")}`):console.log(` ${A(`No command matches "${o}". Type`)} ${ne("/")} ${A("to browse, or")} ${ne("recall --help")} ${A("for the full list.")}`),n()})};e.on("close",()=>{console.log(),s()}),n()})}async function vl(){let e=await yS();console.log(),Il(),console.log();for(let t of TS(e))console.log(t);console.log(),console.log(wS(e)),console.log(),await NS()}var CS=[{name:"Unlimited search",detail:"full history, no caps"},{name:"Context for Claude",detail:"recall past sessions on demand"},{name:"MCP integration",detail:"native tool access from any client"},{name:"Semantic search",detail:"find by meaning, not just keywords"},{name:"Advanced UI",detail:"tags, aliases, notes, exports"}];function LS(){return process.env.NO_COLOR||process.env.CI||process.env.RECALL_NO_ANIMATION?!1:!!process.stdout.isTTY}function Xr(e){return new Promise(t=>setTimeout(t,e))}function OS(e){let s=(e.split("@")[0]??"").split(/[._+\-]/)[0]??"";return s?s.charAt(0).toUpperCase()+s.slice(1).toLowerCase():""}function Cl(){process.stdout.write("\r\x1B[2K")}async function Ml(e){let t=LS();console.log(),Il(),console.log(),t&&(process.stdout.write(` ${A("Verifying license...")}`),await Xr(260),Cl()),console.log(` ${Et("\u2713")} ${A("License verified")}`),console.log(` ${Et("\u2713")} ${A("Tier:")} ${ne("Pro")} ${A("\xB7 Lifetime")}`),console.log(` ${Et("\u2713")} ${A("Key:")} ${Ee(e.key_short)}`),console.log(` ${Et("\u2713")} ${A("Email:")} ${e.email}`),e.test_mode&&console.log(` ${Ws("!")} ${Ws("Test mode:")} this license was issued in test mode.`),console.log(),console.log(` ${Ol("Unlocking Pro features")}`),console.log();for(let r of CS)t&&(process.stdout.write(` ${A("\xB7")} ${A(r.name)}`),await Xr(110),Cl()),console.log(` ${Et("\u2713")} ${r.name} ${A(r.detail)}`);t&&await Xr(160),console.log();let s=OS(e.email),n=s?`Welcome aboard, ${s}.`:"Welcome aboard.";console.log(` ${ne(n)}`),console.log(` ${A("Run")} ${Ee("recall")} ${A("to open the dashboard, or")} ${Ee("recall help")} ${A("for the command list.")}`),console.log()}async function Dl(e){let t=e.trim();t.length<8&&(console.error(d.warn("License key looks too short. Paste the full key from your purchase email.")),process.exit(1));let s=`${AS()}-${IS(4).toString("hex")}`,n=`${xt()}/api/license/activate`,r;try{r=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({license_key:t,instance_name:s,machine_fingerprint:us()})})}catch(a){let l=a instanceof Error?a.message:"unknown error";console.error(d.warn(`Could not reach activation server at ${n}: ${l}`)),console.error(d.dim("If you are offline, try again when you have a connection.")),process.exit(1)}let o;try{o=await r.json()}catch{console.error(d.warn(`Activation server returned invalid JSON (status ${r.status}).`)),process.exit(1)}if(r.status!==200||!o.license_jwt){let a=o.error??`activation failed (status ${r.status})`;console.error(d.warn(`Activation refused: ${a}`)),process.exit(1)}let i=await ds(o.license_jwt);(!i.valid||!i.claims)&&(console.error(d.warn(`Server returned a JWT that fails local verification: ${i.reason??"unknown"}`)),console.error(d.dim("This usually means the CLI is older than the server, or the public key was rotated.")),process.exit(1)),ni({license_jwt:o.license_jwt,license_key:t,key_short:o.key_short??i.claims.key_short,customer_email:o.customer_email??i.claims.email,activated_at:new Date().toISOString(),tier:"pro",test_mode:!!i.claims.test_mode}),await Ml({...i.claims,key_short:o.key_short??i.claims.key_short,email:o.customer_email??i.claims.email})}I();import{spawn as vS}from"node:child_process";import{platform as Js}from"node:os";var $l="https://clauderecall.com/pricing";function MS(e){let t=Js()==="darwin"?"open":Js()==="win32"?"start":"xdg-open",s=Js()==="win32"?["",e]:[e];vS(t,s,{detached:!0,stdio:"ignore",shell:Js()==="win32"}).unref()}async function jl(){let{getLicenseStatus:e}=await Promise.resolve().then(()=>(_e(),gs)),t=await e();if(t.tier==="pro"){console.log(),console.log(d.bold("Already on Pro.")),console.log(` ${d.dim("Key:")} ${t.key_short}`),console.log(` ${d.dim("Email:")} ${t.customer_email}`),console.log();return}console.log(),console.log(`${d.ok("Opening")} ${$l}`),console.log(d.dim("After purchase, run: recall activate <license-key>")),console.log(),MS($l)}I();import{spawn as DS}from"node:child_process";import{platform as Gs}from"node:os";var Pl="https://clauderecall.com/pricing?trial=1&utm_source=cli&utm_medium=recall_trial";function $S(e){let t=Gs()==="darwin"?"open":Gs()==="win32"?"start":"xdg-open",s=Gs()==="win32"?["",e]:[e];DS(t,s,{detached:!0,stdio:"ignore",shell:Gs()==="win32"}).unref()}async function Fl(){let{getLicenseStatus:e}=await Promise.resolve().then(()=>(_e(),gs)),t=await e();if(t.tier==="pro"){console.log(),console.log(d.bold("You are already on Pro.")),console.log(` ${d.dim("Key:")} ${t.key_short}`),console.log(` ${d.dim("Email:")} ${t.customer_email}`),console.log();return}console.log(),console.log(`${d.ok("Opening")} ${Pl}`),console.log(d.dim("Enter your email to get a 7-day Pro trial link. No card.")),console.log(d.dim("After you click the verification email, run: recall activate <key>")),console.log(),$S(Pl)}I();import{createRequire as WS}from"module";ps();import{existsSync as Ul,mkdirSync as jS,readFileSync as PS,writeFileSync as FS}from"node:fs";import{homedir as US}from"node:os";import{join as Bl}from"node:path";import{randomBytes as BS}from"node:crypto";var Gr=Bl(US(),".recall"),Ys=Bl(Gr,"telemetry.json"),Jr={decided_at:null,decision:null,last_ping_month:null,nonce_month:null,nonce:null,last_error:null};function bt(){if(!Ul(Ys))return{...Jr};try{let e=PS(Ys,"utf8"),t=JSON.parse(e);return{...Jr,...t}}catch{return{...Jr}}}function zs(e){Ul(Gr)||jS(Gr,{recursive:!0}),FS(Ys,JSON.stringify(e,null,2)+`
1549
- `,{mode:384})}function Hl(){return Ys}function zr(e=new Date){let t=e.getUTCFullYear(),s=String(e.getUTCMonth()+1).padStart(2,"0");return`${t}-${s}`}function Wl(e,t){return e.nonce&&e.nonce_month===t?e:{...e,nonce:BS(16).toString("hex"),nonce_month:t}}function HS(e,t){return!t.nonce||!t.nonce_month?null:{event:"install",version:e,platform:process.platform,arch:process.arch,month:t.nonce_month,nonce:t.nonce}}async function Xl(e){let t=bt();if(t.decision!=="on")return{status:t.decision==="off"?"opted-out":"no-decision"};let s=zr();if(t.last_ping_month===s)return{status:"already-this-month"};t=Wl(t,s);let n=HS(e,t);if(!n)return{status:"error",detail:"no nonce"};try{let r=await fetch(`${xt()}/api/install-ping`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),signal:AbortSignal.timeout(5e3)});if(!r.ok){let i=`http ${r.status}`;return zs({...t,last_error:`${new Date().toISOString()} ${i}`}),{status:"error",detail:i}}let o=await r.json().catch(()=>({}));return zs({...t,last_ping_month:s,last_error:null}),{status:o.deduped?"deduped":"sent"}}catch(r){let o=r instanceof Error?r.message:"unknown";return zs({...t,last_error:`${new Date().toISOString()} ${o}`}),{status:"error",detail:o}}}function Nt(e){let s={...bt(),decision:e,decided_at:new Date().toISOString(),last_error:null,...e==="off"?{nonce:null,nonce_month:null,last_ping_month:null}:{}};return zs(s),s}function qs(e){let t=Wl(bt(),zr());return{event:"install",version:e,platform:process.platform,arch:process.arch,month:t.nonce_month??zr(),nonce:t.nonce??"0".repeat(32)}}var XS=WS(import.meta.url),JS=XS("../package.json").version;async function Yr(){let e=bt();console.log(),console.log(d.bold("Telemetry \u2014 anonymous install ping")),console.log(` ${d.dim("decision:")} ${e.decision??"not yet decided"}`),console.log(` ${d.dim("decided at:")} ${e.decided_at??"\u2014"}`),console.log(` ${d.dim("last ping:")} ${e.last_ping_month??"\u2014"}`),console.log(` ${d.dim("state file:")} ${Hl()}`),e.last_error&&console.log(` ${d.warn("last error:")} ${e.last_error}`),console.log(),console.log(d.dim("Next-ping payload preview (only sent if decision = on):")),console.log(d.dim(JSON.stringify(qs(JS),null,2))),console.log(),console.log(d.dim("Toggle with `recall telemetry on` / `recall telemetry off`.")),console.log(d.dim("Full disclosure: https://clauderecall.com/telemetry")),console.log()}async function Jl(){Nt("on"),console.log(),console.log(d.ok("Telemetry: opted in.")),console.log(d.dim("One anonymous ping per machine per month. No PII. Source: docs/specs/v0.16-install-ping.md")),console.log(d.dim("Reverse with `recall telemetry off`.")),console.log()}async function Gl(){Nt("off"),console.log(),console.log(d.ok("Telemetry: opted out.")),console.log(d.dim("No further pings will be sent. Existing nonce deleted.")),console.log()}async function zl(){await Yr()}import{createInterface as GS}from"node:readline/promises";import{stdin as Yl,stdout as ue}from"node:process";var zS=new Set(["telemetry","trial","upgrade","activate","license","help","version"]);function YS(e){return!(process.env.CI==="true"||process.env.RECALL_QUIET_INSTALL==="1"||process.env.RECALL_DISABLE_TELEMETRY_PROMPT==="1"||!Yl.isTTY||!ue.isTTY||e&&zS.has(e)||bt().decision!==null)}async function ql(e,t){if(!YS(e))return;let s=qs(t);ue.write(`
1551
+ (SELECT COUNT(*) FROM projects) AS projects`).get();return{sessions:t.sessions,projects:t.projects}}catch{return{sessions:0,projects:0}}}function yS(){let e=process.stdout.columns;return typeof e!="number"||e<=0?!1:e<ES+2}function Il(){if(yS()){console.log(`${ne(bS)} ${A("\xB7")} ${A(kl)}`);return}for(let e of Al)console.log(ne(e));console.log(A(kl))}async function TS(){return{daemon:K(),counts:SS(),license:await ye()}}function wS(e){let t=[];if(t.push(` ${A("Version:")} ${Ee(`v${gS}`)} ${A("\xB7 CLI \xB7 @clauderecallhq/cli")}`),e.daemon){let s=`http://127.0.0.1:${e.daemon.port}`;t.push(` ${A("Daemon:")} ${Et("running")} on ${s} ${A(`(pid ${e.daemon.pid})`)}`)}else t.push(` ${A("Daemon:")} ${Ws("stopped")}`);if(e.counts.sessions===0)t.push(` ${A("Sessions:")} ${Ws("none indexed yet")}`);else{let s=e.counts.projects===1?"project":"projects";t.push(` ${A("Sessions:")} ${Ee(String(e.counts.sessions))} indexed across ${Ee(String(e.counts.projects))} ${s}`)}return e.license.tier==="pro"?t.push(` ${A("License:")} ${Et("Pro")}`):t.push(` ${A("License:")} Free`),t}function xS(e){let t=Ee(">");if(e.counts.sessions===0)return`${t} Run ${ne("recall index")} to scan ~/.claude/projects/`;if(!e.daemon)return`${t} Run ${ne("recall start")} to launch the local daemon`;if(e.license.tier==="free")return`${t} Run ${ne("recall upgrade")} to unlock Pro features`;let s=`http://127.0.0.1:${e.daemon.port}`;return`${t} Open ${Ee(s)} in your browser ${A("\xB7")} or run ${ne("recall --help")} for all commands`}var Xs=[{title:"Setup",commands:[{name:"index",description:"Scan your Claude sessions and build the searchable database"},{name:"status",description:"Database size, session counts, and daemon state"},{name:"projects",description:"List every project with how many sessions are in each"},{name:"install-extension",description:"Install the VS Code / Cursor / Windsurf extension"},{name:"doctor",description:"Health check: DB size, WAL, FTS fragmentation, integrity, disk space, alias invariant"},{name:"optimize",description:"Maintenance: WAL checkpoint, FTS5 merge, planner stats. Add --vacuum to reclaim free pages"}]},{title:"Browse",commands:[{name:"tui",description:"Browse and search sessions in an interactive terminal UI"},{name:"list",description:"List your sessions, newest first"},{name:"show <id>",description:"Print a full session transcript"},{name:"search <query>",description:"Full-text search across every message"},{name:"similar <id>",description:"Find sessions about the same topic (Pro)"},{name:"semantic [action]",description:'Manage semantic search (defaults to "status")'},{name:"name <id> <name>",description:"Rename a session (or its terminal tab)"}]},{title:"Pipe to Claude",commands:[{name:"context <id>",description:"Pipe a past session as markdown into a fresh `claude` chat"},{name:"neighborhood <id>",description:"Bundle a session with its parents, children, and citations for richer context"}]},{title:"Threads",commands:[{name:"threads sync",description:"Capture sessions running in this repo right now into a thread"},{name:"threads sync --preflight",description:"Preview what `threads sync` would do without writing"},{name:"threads scan",description:"Auto-detect parent-child links across past sessions"},{name:"threads list",description:"List threads, newest first"},{name:"threads show <id>",description:"Show a thread's header and session tree"},{name:"threads new <name>",description:"Create a new thread"},{name:"threads link <id>",description:"Link a session into a thread"},{name:"threads unlink <id>",description:"Remove a session from a thread"},{name:"threads set-parent <id>",description:"Change a session's parent within a thread"},{name:"threads rename <id>",description:"Rename a thread"},{name:"threads close <id>",description:"Mark a thread as closed"},{name:"threads reopen <id>",description:"Reopen a closed thread"},{name:"threads archive <id>",description:"Archive a thread"},{name:"threads merge <id>",description:"Merge one thread into another"},{name:"threads split <id>",description:"Split sessions out into a new thread"}]},{title:"Inference",commands:[{name:"infer outputs",description:"Extract code, file, and error references from sessions in one project"},{name:"infer citations",description:"Find sessions that cite the same files or errors"},{name:"infer l1",description:"Fast deterministic link inference. No LLM cost"},{name:"infer links",description:"LLM-powered link classification (Pro). Optional --auto-promote"},{name:"infer bug-patterns",description:"Cluster sessions that hit the same bug"},{name:"embeddings [action]",description:'Audit embedding coverage (defaults to "audit")'}]},{title:"Analytics",commands:[{name:"stats [id]",description:"Token + dollar usage. No args = overview, pass a session for details"},{name:"health [project]",description:"Score how well-organized each project's sessions are"},{name:"digest",description:"Today's rediscovery picks and standouts"},{name:"correlate [id]",description:"Link sessions to the git commits they wrote"},{name:"blame <sha>",description:"Find which session(s) wrote the code in a commit"}]},{title:"Daemon",commands:[{name:"start",description:"Start the background daemon (live tab tracking + web UI)"},{name:"stop",description:"Stop the background daemon"},{name:"open",description:"Open the local web UI in your browser"}]},{title:"Sharing",commands:[{name:"share [id]",description:"Save a session as a shareable PNG card"},{name:"wrapped [month]",description:"Save a monthly recap as a PNG card"}]},{title:"Diagnostics",commands:[{name:"correlator audit",description:"Find sessions with bad terminal-name aliases (--fix to clear)"},{name:"correlator debug",description:"Show how the daemon is matching open terminals to sessions"},{name:"correlator restore",description:"Restore aliases that `correlator audit --fix` cleared"},{name:"titles [action]",description:'Audit session titles in the current project (defaults to "audit")'},{name:"import-vscode-state",description:"Backfill missing tab names from your editor's workspace state"},{name:"audit-secrets",description:"Scan the database for leaked secrets"}]},{title:"Integrations",commands:[{name:"mcp",description:"Expose Recall as an MCP server (for Claude Desktop / Claude Code)"},{name:"paste",description:"Save clipboard content (or stdin) into Recall"}]},{title:"Pro & License",commands:[{name:"upgrade",description:"Open the Pro pricing page"},{name:"activate <key>",description:"Activate your Pro license (run once after purchase)"},{name:"license [action]",description:"Show the current license. Use `license deactivate` to remove it"},{name:"verify [action]",description:'Toggle verification badges in the UI (defaults to "status")'}]},{title:"Feedback",commands:[{name:"feedback",description:"Send a 1-5 rating to the team. Pass --score for non-interactive use"}]}],RS=Xs.reduce((e,t)=>e+t.commands.length,0),kS=new Set([...Xs.flatMap(e=>e.commands.map(t=>t.name.split(/\s+/)[0])),"thread","correlator-audit","correlator-debug","correlator-restore","extract-outputs","infer-citations","infer-l1","infer-links","infer-bug-patterns"]);function Nl(){let e=Xs.flatMap(s=>s.commands.map(n=>`recall ${n.name}`)),t=Math.max(...e.map(s=>s.length));console.log(),console.log(`${Ol("COMMANDS")} ${A(`\xB7 ${RS} total \xB7 q to quit \xB7 recall --help for full details`)}`),console.log(` ${A("All commands run as subcommands of")} ${ne("recall")}${A(". There is no separate")} ${Ee("threads")}${A(",")} ${Ee("thread")}${A(", or")} ${Ee("titles")} ${A("binary.")}`);for(let s of Xs){console.log(),console.log(` ${ne(s.title.toUpperCase())}`);for(let n of s.commands){let r=`recall ${n.name}`.padEnd(t," ");console.log(` ${Ee(r)} ${A(n.description)}`)}}console.log()}function NS(){return!!process.stdin.isTTY&&!!process.stdout.isTTY}async function CS(){if(!NS())return;let e=dS.createInterface({input:process.stdin,output:process.stdout}),t=`${A("Type")} ${ne("/")} ${A("for commands, or press")} ${ne("Enter")} ${A("to exit")} ${Ee("\u203A")} `;return new Promise(s=>{let n=()=>{e.question(t,r=>{let o=r.trim();if(o==="/"||o==="/help"||o==="help"||o==="?"){Nl(),n();return}if(o===""||o==="q"||o==="quit"||o==="exit"){e.close();return}let i=o.startsWith("/")?o.slice(1).trimStart():o,a=i.toLowerCase();if((a==="recall"||a.startsWith("recall "))&&(i=i.slice(6).trimStart()),i===""){Nl(),n();return}let l=(i.split(/\s+/)[0]??"").toLowerCase();kS.has(l)?console.log(` ${A("Run")} ${ne(`recall ${i}`)} ${A("in your shell to invoke that command.")}`):console.log(` ${A(`No command matches "${o}". Type`)} ${ne("/")} ${A("to browse, or")} ${ne("recall --help")} ${A("for the full list.")}`),n()})};e.on("close",()=>{console.log(),s()}),n()})}async function vl(){let e=await TS();console.log(),Il(),console.log();for(let t of wS(e))console.log(t);console.log(),console.log(xS(e)),console.log(),await CS()}var LS=[{name:"Unlimited search",detail:"full history, no caps"},{name:"Context for Claude",detail:"recall past sessions on demand"},{name:"MCP integration",detail:"native tool access from any client"},{name:"Semantic search",detail:"find by meaning, not just keywords"},{name:"Advanced UI",detail:"tags, aliases, notes, exports"}];function OS(){return process.env.NO_COLOR||process.env.CI||process.env.RECALL_NO_ANIMATION?!1:!!process.stdout.isTTY}function Xr(e){return new Promise(t=>setTimeout(t,e))}function AS(e){let s=(e.split("@")[0]??"").split(/[._+\-]/)[0]??"";return s?s.charAt(0).toUpperCase()+s.slice(1).toLowerCase():""}function Cl(){process.stdout.write("\r\x1B[2K")}async function Ml(e){let t=OS();console.log(),Il(),console.log(),t&&(process.stdout.write(` ${A("Verifying license...")}`),await Xr(260),Cl()),console.log(` ${Et("\u2713")} ${A("License verified")}`),console.log(` ${Et("\u2713")} ${A("Tier:")} ${ne("Pro")} ${A("\xB7 Lifetime")}`),console.log(` ${Et("\u2713")} ${A("Key:")} ${Ee(e.key_short)}`),console.log(` ${Et("\u2713")} ${A("Email:")} ${e.email}`),e.test_mode&&console.log(` ${Ws("!")} ${Ws("Test mode:")} this license was issued in test mode.`),console.log(),console.log(` ${Ol("Unlocking Pro features")}`),console.log();for(let r of LS)t&&(process.stdout.write(` ${A("\xB7")} ${A(r.name)}`),await Xr(110),Cl()),console.log(` ${Et("\u2713")} ${r.name} ${A(r.detail)}`);t&&await Xr(160),console.log();let s=AS(e.email),n=s?`Welcome aboard, ${s}.`:"Welcome aboard.";console.log(` ${ne(n)}`),console.log(` ${A("Run")} ${Ee("recall")} ${A("to open the dashboard, or")} ${Ee("recall help")} ${A("for the command list.")}`),console.log()}async function $l(e){let t=e.trim();t.length<8&&(console.error(d.warn("License key looks too short. Paste the full key from your purchase email.")),process.exit(1));let s=`${IS()}-${vS(4).toString("hex")}`,n=`${xt()}/api/license/activate`,r;try{r=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({license_key:t,instance_name:s,machine_fingerprint:us()})})}catch(a){let l=a instanceof Error?a.message:"unknown error";console.error(d.warn(`Could not reach activation server at ${n}: ${l}`)),console.error(d.dim("If you are offline, try again when you have a connection.")),process.exit(1)}let o;try{o=await r.json()}catch{console.error(d.warn(`Activation server returned invalid JSON (status ${r.status}).`)),process.exit(1)}if(r.status!==200||!o.license_jwt){let a=o.error??`activation failed (status ${r.status})`;console.error(d.warn(`Activation refused: ${a}`)),process.exit(1)}let i=await ds(o.license_jwt);(!i.valid||!i.claims)&&(console.error(d.warn(`Server returned a JWT that fails local verification: ${i.reason??"unknown"}`)),console.error(d.dim("This usually means the CLI is older than the server, or the public key was rotated.")),process.exit(1)),ni({license_jwt:o.license_jwt,license_key:t,key_short:o.key_short??i.claims.key_short,customer_email:o.customer_email??i.claims.email,activated_at:new Date().toISOString(),tier:"pro",test_mode:!!i.claims.test_mode}),await Ml({...i.claims,key_short:o.key_short??i.claims.key_short,email:o.customer_email??i.claims.email})}I();import{spawn as MS}from"node:child_process";import{platform as Js}from"node:os";var Dl="https://clauderecall.com/pricing";function $S(e){let t=Js()==="darwin"?"open":Js()==="win32"?"start":"xdg-open",s=Js()==="win32"?["",e]:[e];MS(t,s,{detached:!0,stdio:"ignore",shell:Js()==="win32"}).unref()}async function jl(){let{getLicenseStatus:e}=await Promise.resolve().then(()=>(_e(),gs)),t=await e();if(t.tier==="pro"){console.log(),console.log(d.bold("Already on Pro.")),console.log(` ${d.dim("Key:")} ${t.key_short}`),console.log(` ${d.dim("Email:")} ${t.customer_email}`),console.log();return}console.log(),console.log(`${d.ok("Opening")} ${Dl}`),console.log(d.dim("After purchase, run: recall activate <license-key>")),console.log(),$S(Dl)}I();import{spawn as DS}from"node:child_process";import{platform as Gs}from"node:os";var Pl="https://clauderecall.com/pricing?trial=1&utm_source=cli&utm_medium=recall_trial";function jS(e){let t=Gs()==="darwin"?"open":Gs()==="win32"?"start":"xdg-open",s=Gs()==="win32"?["",e]:[e];DS(t,s,{detached:!0,stdio:"ignore",shell:Gs()==="win32"}).unref()}async function Fl(){let{getLicenseStatus:e}=await Promise.resolve().then(()=>(_e(),gs)),t=await e();if(t.tier==="pro"){console.log(),console.log(d.bold("You are already on Pro.")),console.log(` ${d.dim("Key:")} ${t.key_short}`),console.log(` ${d.dim("Email:")} ${t.customer_email}`),console.log();return}console.log(),console.log(`${d.ok("Opening")} ${Pl}`),console.log(d.dim("Enter your email to get a 7-day Pro trial link. No card.")),console.log(d.dim("After you click the verification email, run: recall activate <key>")),console.log(),jS(Pl)}I();import{createRequire as XS}from"module";ps();import{existsSync as Ul,mkdirSync as PS,readFileSync as FS,writeFileSync as US}from"node:fs";import{homedir as BS}from"node:os";import{join as Bl}from"node:path";import{randomBytes as HS}from"node:crypto";var Gr=Bl(BS(),".recall"),Ys=Bl(Gr,"telemetry.json"),Jr={decided_at:null,decision:null,last_ping_month:null,nonce_month:null,nonce:null,last_error:null};function bt(){if(!Ul(Ys))return{...Jr};try{let e=FS(Ys,"utf8"),t=JSON.parse(e);return{...Jr,...t}}catch{return{...Jr}}}function zs(e){Ul(Gr)||PS(Gr,{recursive:!0}),US(Ys,JSON.stringify(e,null,2)+`
1552
+ `,{mode:384})}function Hl(){return Ys}function zr(e=new Date){let t=e.getUTCFullYear(),s=String(e.getUTCMonth()+1).padStart(2,"0");return`${t}-${s}`}function Wl(e,t){return e.nonce&&e.nonce_month===t?e:{...e,nonce:HS(16).toString("hex"),nonce_month:t}}function WS(e,t){return!t.nonce||!t.nonce_month?null:{event:"install",version:e,platform:process.platform,arch:process.arch,month:t.nonce_month,nonce:t.nonce}}async function Xl(e){let t=bt();if(t.decision!=="on")return{status:t.decision==="off"?"opted-out":"no-decision"};let s=zr();if(t.last_ping_month===s)return{status:"already-this-month"};t=Wl(t,s);let n=WS(e,t);if(!n)return{status:"error",detail:"no nonce"};try{let r=await fetch(`${xt()}/api/install-ping`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),signal:AbortSignal.timeout(5e3)});if(!r.ok){let i=`http ${r.status}`;return zs({...t,last_error:`${new Date().toISOString()} ${i}`}),{status:"error",detail:i}}let o=await r.json().catch(()=>({}));return zs({...t,last_ping_month:s,last_error:null}),{status:o.deduped?"deduped":"sent"}}catch(r){let o=r instanceof Error?r.message:"unknown";return zs({...t,last_error:`${new Date().toISOString()} ${o}`}),{status:"error",detail:o}}}function Nt(e){let s={...bt(),decision:e,decided_at:new Date().toISOString(),last_error:null,...e==="off"?{nonce:null,nonce_month:null,last_ping_month:null}:{}};return zs(s),s}function qs(e){let t=Wl(bt(),zr());return{event:"install",version:e,platform:process.platform,arch:process.arch,month:t.nonce_month??zr(),nonce:t.nonce??"0".repeat(32)}}var JS=XS(import.meta.url);function GS(){for(let e of["../package.json","../../package.json"])try{return JS(e).version}catch{}return"0.0.0"}var zS=GS();async function Yr(){let e=bt();console.log(),console.log(d.bold("Telemetry \u2014 anonymous install ping")),console.log(` ${d.dim("decision:")} ${e.decision??"not yet decided"}`),console.log(` ${d.dim("decided at:")} ${e.decided_at??"\u2014"}`),console.log(` ${d.dim("last ping:")} ${e.last_ping_month??"\u2014"}`),console.log(` ${d.dim("state file:")} ${Hl()}`),e.last_error&&console.log(` ${d.warn("last error:")} ${e.last_error}`),console.log(),console.log(d.dim("Next-ping payload preview (only sent if decision = on):")),console.log(d.dim(JSON.stringify(qs(zS),null,2))),console.log(),console.log(d.dim("Toggle with `recall telemetry on` / `recall telemetry off`.")),console.log(d.dim("Full disclosure: https://clauderecall.com/telemetry")),console.log()}async function Jl(){Nt("on"),console.log(),console.log(d.ok("Telemetry: opted in.")),console.log(d.dim("One anonymous ping per machine per month. No PII. Source: docs/specs/v0.16-install-ping.md")),console.log(d.dim("Reverse with `recall telemetry off`.")),console.log()}async function Gl(){Nt("off"),console.log(),console.log(d.ok("Telemetry: opted out.")),console.log(d.dim("No further pings will be sent. Existing nonce deleted.")),console.log()}async function zl(){await Yr()}import{createInterface as YS}from"node:readline/promises";import{stdin as Yl,stdout as ue}from"node:process";var qS=new Set(["telemetry","trial","upgrade","activate","license","help","version"]);function KS(e){return!(process.env.CI==="true"||process.env.RECALL_QUIET_INSTALL==="1"||process.env.RECALL_DISABLE_TELEMETRY_PROMPT==="1"||!Yl.isTTY||!ue.isTTY||e&&qS.has(e)||bt().decision!==null)}async function ql(e,t){if(!KS(e))return;let s=qs(t);ue.write(`
1550
1553
  `),ue.write(` Claude Recall \u2014 anonymous install ping?
1551
1554
 
1552
1555
  `),ue.write(` npm download counts mix real installs with bots and scanners.
@@ -1562,20 +1565,20 @@ Toggle with: recall verify on | off
1562
1565
 
1563
1566
  `),ue.write(` Full disclosure: https://clauderecall.com/telemetry
1564
1567
 
1565
- `);let n=GS({input:Yl,output:ue}),r;try{r=(await n.question(" Send the install ping? [y/N]: ")).trim().toLowerCase()}finally{n.close()}r==="y"||r==="yes"?(Nt("on"),ue.write(`
1568
+ `);let n=YS({input:Yl,output:ue}),r;try{r=(await n.question(" Send the install ping? [y/N]: ")).trim().toLowerCase()}finally{n.close()}r==="y"||r==="yes"?(Nt("on"),ue.write(`
1566
1569
  Opted in. Reverse any time with \`recall telemetry off\`.
1567
1570
 
1568
1571
  `)):(Nt("off"),ue.write(`
1569
1572
  Opted out. No pings will be sent. Reverse with \`recall telemetry on\`.
1570
1573
 
1571
- `))}I();_e();Pt();Dn();async function Kl(){let e=await ye();if(console.log(),e.tier==="free"){console.log(d.bold("Tier: Free")),console.log(d.dim("Free includes: index, list, show, projects, status, the daemon, and the basic web UI.")),e.invalid_reason&&(console.log(),console.log(d.warn(`Stored license is invalid: ${e.invalid_reason}`))),console.log(),console.log("Buy Pro at https://clauderecall.com/pricing"),console.log("Then run: recall activate <license-key>"),console.log();return}console.log(d.bold("Tier: Pro")),console.log(` ${d.dim("Key:")} ${e.key_short}`),console.log(` ${d.dim("Email:")} ${e.customer_email}`),console.log(` ${d.dim("Activated:")} ${e.activated_at}`),e.expires_at&&console.log(` ${d.dim("Expires:")} ${e.expires_at}`),e.test_mode&&console.log(` ${d.warn("Test mode:")} this license was issued in test mode.`);let t=ms();t&&console.log(` ${d.dim("Last server check:")} ${t.last_checked_at}`),console.log()}async function Vl(){let e=await Bn({force:!0});if(console.log(),!e.ran){console.log(d.warn("No license stored on this machine.")),console.log(d.dim("Run `recall activate <license-key>` first.")),console.log();return}if(!e.last_checked_at){console.log(d.warn("Could not reach the license server.")),console.log(d.dim("Network error. Try again when you have a connection.")),console.log();return}if(e.revoked){console.log(d.warn("License is revoked.")),e.reason&&console.log(` ${d.dim("Reason:")} ${e.reason}`),console.log(` ${d.dim("Checked:")} ${e.last_checked_at}`),console.log();return}console.log(d.ok("License is valid.")),console.log(` ${d.dim("Checked:")} ${e.last_checked_at}`),console.log()}function Zl(){ri(),console.log(),console.log("License removed from this machine."),console.log(d.dim(`(${pt})`)),console.log()}T();I();import qS from"cli-table3";function ve(e){let t=_();if(e.length>=32){let n=t.prepare("SELECT id FROM threads WHERE id = ?").get(e);return n?n.id:(process.stderr.write(`thread not found: ${e}
1574
+ `))}I();_e();Pt();$n();async function Kl(){let e=await ye();if(console.log(),e.tier==="free"){console.log(d.bold("Tier: Free")),console.log(d.dim("Free includes: index, list, show, projects, status, the daemon, and the basic web UI.")),e.invalid_reason&&(console.log(),console.log(d.warn(`Stored license is invalid: ${e.invalid_reason}`))),console.log(),console.log("Buy Pro at https://clauderecall.com/pricing"),console.log("Then run: recall activate <license-key>"),console.log();return}console.log(d.bold("Tier: Pro")),console.log(` ${d.dim("Key:")} ${e.key_short}`),console.log(` ${d.dim("Email:")} ${e.customer_email}`),console.log(` ${d.dim("Activated:")} ${e.activated_at}`),e.expires_at&&console.log(` ${d.dim("Expires:")} ${e.expires_at}`),e.test_mode&&console.log(` ${d.warn("Test mode:")} this license was issued in test mode.`);let t=ms();t&&console.log(` ${d.dim("Last server check:")} ${t.last_checked_at}`),console.log()}async function Vl(){let e=await Bn({force:!0});if(console.log(),!e.ran){console.log(d.warn("No license stored on this machine.")),console.log(d.dim("Run `recall activate <license-key>` first.")),console.log();return}if(!e.last_checked_at){console.log(d.warn("Could not reach the license server.")),console.log(d.dim("Network error. Try again when you have a connection.")),console.log();return}if(e.revoked){console.log(d.warn("License is revoked.")),e.reason&&console.log(` ${d.dim("Reason:")} ${e.reason}`),console.log(` ${d.dim("Checked:")} ${e.last_checked_at}`),console.log();return}console.log(d.ok("License is valid.")),console.log(` ${d.dim("Checked:")} ${e.last_checked_at}`),console.log()}function Zl(){ri(),console.log(),console.log("License removed from this machine."),console.log(d.dim(`(${pt})`)),console.log()}T();I();import VS from"cli-table3";function ve(e){let t=_();if(e.length>=32){let n=t.prepare("SELECT id FROM threads WHERE id = ?").get(e);return n?n.id:(process.stderr.write(`thread not found: ${e}
1572
1575
  `),null)}let s=t.prepare("SELECT id, name FROM threads WHERE id LIKE ? ORDER BY created_at DESC").all(e+"%");if(s.length===1)return s[0].id;if(s.length===0)return process.stderr.write(`no thread matches prefix "${e}"
1573
1576
  `),null;process.stderr.write(`ambiguous thread prefix "${e}" \u2014 candidates:
1574
1577
  `);for(let n of s)process.stderr.write(` ${H(n.id)} ${n.name}
1575
1578
  `);return null}function St(e){let t=_();if(e.length>=32){let n=t.prepare("SELECT id FROM sessions WHERE id = ?").get(e);return n?n.id:(process.stderr.write(`session not found: ${e}
1576
1579
  `),null)}let s=t.prepare("SELECT id FROM sessions WHERE id LIKE ? LIMIT 2").all(e+"%");return s.length===1?s[0].id:s.length===0?(process.stderr.write(`no session matches prefix "${e}"
1577
1580
  `),null):(process.stderr.write(`ambiguous session prefix "${e}". be more specific.
1578
- `),null)}function KS(e){let t=new Map;if(e.length===0)return t;let s=e.map(()=>"?").join(","),r=_().prepare(`SELECT s.id,
1581
+ `),null)}function ZS(e){let t=new Map;if(e.length===0)return t;let s=e.map(()=>"?").join(","),r=_().prepare(`SELECT s.id,
1579
1582
  s.first_user_message,
1580
1583
  p.name AS project_name,
1581
1584
  a.alias AS alias
@@ -1584,32 +1587,32 @@ Toggle with: recall verify on | off
1584
1587
  LEFT JOIN session_aliases a ON a.session_id = s.id
1585
1588
  WHERE s.id IN (${s})`).all(...e);for(let o of r)t.set(o.id,o);return t}function Ql(e,t){let s=t.get(e),n=d.accent(H(e));if(!s)return`${n} ${d.dim("(unindexed)")}`;let r=s.alias??s.first_user_message??"",o=s.project_name?d.project(`[${s.project_name}] `):"";return`${n} ${o}${Y(r,80)}`}function qr(e){return e.archived?"archived":e.closed_at?"closed":"open"}function Ct(e){let t=qr(e);process.stderr.write(d.ok(`\u2713 ${e.name} ${d.dim(`(${H(e.id)})`)} [${t}]
1586
1589
  `))}function xe(e,t,s){if(e){process.stdout.write(JSON.stringify(t,null,2)+`
1587
- `);return}s()}function ed(e){let t=zn({includeArchived:e.archived===!0});xe(e.json===!0,t,()=>{if(t.length===0){console.log(d.dim("no threads. create one with `recall thread new <name>`."));return}let s=new qS({head:[d.bold("id"),d.bold("name"),d.bold("sessions"),d.bold("origins"),d.bold("status"),d.bold("created")],colWidths:[10,40,10,9,10,16],wordWrap:!0,style:{head:[],border:["grey"]}});for(let n of t)s.push([d.accent(H(n.id)),Y(n.name,38),String(n.session_count),String(n.origin_count),qr(n),d.dim(W(n.created_at))]);console.log(s.toString()),console.log(d.dim(`${t.length} thread${t.length===1?"":"s"}.`+(e.archived?"":" add --archived to include archived.")))})}function VS(e,t){let s=new Set(e.edges.map(a=>a.session_id)),n=new Map,r=[];for(let a of e.edges){let l=a.parent_session_id;if(a.role==="origin"||!l||!s.has(l)){r.push(a);continue}let c=n.get(l)??[];c.push(a),n.set(l,c)}let o=new Set,i=(a,l,c,u)=>{if(o.has(a.session_id))return;o.add(a.session_id);let p=u?"":c?"\u2514\u2500 ":"\u251C\u2500 ",m=a.role==="origin"?d.warn("[origin] "):"";process.stdout.write(`${l}${p}${m}${Ql(a.session_id,t)}
1590
+ `);return}s()}function ed(e){let t=zn({includeArchived:e.archived===!0});xe(e.json===!0,t,()=>{if(t.length===0){console.log(d.dim("no threads. create one with `recall thread new <name>`."));return}let s=new VS({head:[d.bold("id"),d.bold("name"),d.bold("sessions"),d.bold("origins"),d.bold("status"),d.bold("created")],colWidths:[10,40,10,9,10,16],wordWrap:!0,style:{head:[],border:["grey"]}});for(let n of t)s.push([d.accent(H(n.id)),Y(n.name,38),String(n.session_count),String(n.origin_count),qr(n),d.dim(W(n.created_at))]);console.log(s.toString()),console.log(d.dim(`${t.length} thread${t.length===1?"":"s"}.`+(e.archived?"":" add --archived to include archived.")))})}function QS(e,t){let s=new Set(e.edges.map(a=>a.session_id)),n=new Map,r=[];for(let a of e.edges){let l=a.parent_session_id;if(a.role==="origin"||!l||!s.has(l)){r.push(a);continue}let c=n.get(l)??[];c.push(a),n.set(l,c)}let o=new Set,i=(a,l,c,u)=>{if(o.has(a.session_id))return;o.add(a.session_id);let p=u?"":c?"\u2514\u2500 ":"\u251C\u2500 ",m=a.role==="origin"?d.warn("[origin] "):"";process.stdout.write(`${l}${p}${m}${Ql(a.session_id,t)}
1588
1591
  `);let f=n.get(a.session_id)??[],g=u?"":l+(c?" ":"\u2502 ");f.forEach((h,E)=>{i(h,g,E===f.length-1,!1)})};r.forEach((a,l)=>i(a,"",l===r.length-1,!0));for(let a of e.edges)o.has(a.session_id)||process.stdout.write(`${d.warn("? ")}${Ql(a.session_id,t)}
1589
1592
  `)}function td(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=Oe(s);if(!n){process.stderr.write(`thread not found: ${e}
1590
- `),process.exitCode=1;return}let r=KS(n.edges.map(o=>o.session_id));xe(t.json===!0,n,()=>{let o=qr(n);if(console.log(d.bold(n.name)),console.log(d.dim(`id ${H(n.id)} \xB7 ${o} \xB7 ${n.session_count} session${n.session_count===1?"":"s"} \xB7 ${n.origin_count} origin${n.origin_count===1?"":"s"} \xB7 created ${W(n.created_at)}`)),n.summary&&console.log(n.summary),console.log(),n.edges.length===0){console.log(d.dim("(no sessions linked \u2014 use `recall thread link ...`)"));return}VS(n,r)})}function sd(e,t){let s;if(t.origin){let r=St(t.origin);if(!r){process.exitCode=1;return}s=r}let n=Ii({name:e,summary:t.summary??null,originSessionId:s});xe(t.json===!0,n,()=>{Ct(n),process.stderr.write(d.dim(`id ${n.id}
1593
+ `),process.exitCode=1;return}let r=ZS(n.edges.map(o=>o.session_id));xe(t.json===!0,n,()=>{let o=qr(n);if(console.log(d.bold(n.name)),console.log(d.dim(`id ${H(n.id)} \xB7 ${o} \xB7 ${n.session_count} session${n.session_count===1?"":"s"} \xB7 ${n.origin_count} origin${n.origin_count===1?"":"s"} \xB7 created ${W(n.created_at)}`)),n.summary&&console.log(n.summary),console.log(),n.edges.length===0){console.log(d.dim("(no sessions linked \u2014 use `recall thread link ...`)"));return}QS(n,r)})}function sd(e,t){let s;if(t.origin){let r=St(t.origin);if(!r){process.exitCode=1;return}s=r}let n=Ii({name:e,summary:t.summary??null,originSessionId:s});xe(t.json===!0,n,()=>{Ct(n),process.stderr.write(d.dim(`id ${n.id}
1591
1594
  `)),s&&process.stderr.write(d.dim(`origin: ${H(s)}
1592
1595
  `))})}function nd(e,t){let s=ve(t.thread);if(!s){process.exitCode=1;return}let n=St(e);if(!n){process.exitCode=1;return}let r=null;if(t.parent){let a=St(t.parent);if(!a){process.exitCode=1;return}r=a}let o=t.role??(r?"child":"origin"),i=vi({threadId:s,sessionId:n,parentSessionId:r,role:o});xe(t.json===!0,i,()=>{process.stderr.write(d.ok(`\u2713 linked ${H(n)} \u2192 ${H(s)} [${o}]
1593
1596
  `))})}function rd(e,t){let s=ve(t.thread);if(!s){process.exitCode=1;return}let n=St(e);if(!n){process.exitCode=1;return}let r=Mi(s,n);xe(t.json===!0,r,()=>{if(r.removed===0){process.stderr.write(d.warn(`(no edge existed for ${H(n)} in ${H(s)})
1594
1597
  `));return}process.stderr.write(d.ok(`\u2713 unlinked ${H(n)} from ${H(s)}
1595
- `))})}function od(e,t){let s=ve(t.thread);if(!s){process.exitCode=1;return}let n=St(e);if(!n){process.exitCode=1;return}let r=null;if(t.parent&&t.parent.toLowerCase()!=="none"){let i=St(t.parent);if(!i){process.exitCode=1;return}r=i}let o=Di(s,n,r);xe(t.json===!0,o,()=>{process.stderr.write(d.ok(`\u2713 ${H(n)} in ${H(s)} \u2192 `+(r?`child of ${H(r)}`:"origin")+`
1596
- `))})}function id(e,t,s){let n=ve(e);if(!n){process.exitCode=1;return}let r=$i(n,t);xe(s.json===!0,r,()=>Ct(r))}function ad(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=ji(s);xe(t.json===!0,n,()=>Ct(n))}function cd(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=Pi(s);xe(t.json===!0,n,()=>Ct(n))}function ld(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=Fi(s);xe(t.json===!0,n,()=>Ct(n))}function dd(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=ve(t.into);if(!n){process.exitCode=1;return}if(s===n){process.stderr.write(d.err(`cannot merge a thread into itself
1598
+ `))})}function od(e,t){let s=ve(t.thread);if(!s){process.exitCode=1;return}let n=St(e);if(!n){process.exitCode=1;return}let r=null;if(t.parent&&t.parent.toLowerCase()!=="none"){let i=St(t.parent);if(!i){process.exitCode=1;return}r=i}let o=$i(s,n,r);xe(t.json===!0,o,()=>{process.stderr.write(d.ok(`\u2713 ${H(n)} in ${H(s)} \u2192 `+(r?`child of ${H(r)}`:"origin")+`
1599
+ `))})}function id(e,t,s){let n=ve(e);if(!n){process.exitCode=1;return}let r=Di(n,t);xe(s.json===!0,r,()=>Ct(r))}function ad(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=ji(s);xe(t.json===!0,n,()=>Ct(n))}function cd(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=Pi(s);xe(t.json===!0,n,()=>Ct(n))}function ld(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=Fi(s);xe(t.json===!0,n,()=>Ct(n))}function dd(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=ve(t.into);if(!n){process.exitCode=1;return}if(s===n){process.stderr.write(d.err(`cannot merge a thread into itself
1597
1600
  `)),process.exitCode=1;return}let r=Ui(s,n);xe(t.json===!0,r,()=>{process.stderr.write(d.ok(`\u2713 merged ${H(s)} \u2192 ${H(n)} (${r.session_count} sessions)
1598
1601
  `))})}function ud(e,t){let s=ve(e);if(!s){process.exitCode=1;return}let n=t.sessions.split(",").map(i=>i.trim()).filter(Boolean);if(n.length===0){process.stderr.write(d.err(`--sessions must be a non-empty comma-separated list
1599
1602
  `)),process.exitCode=1;return}let r=[];for(let i of n){let a=St(i);if(!a){process.exitCode=1;return}r.push(a)}let o=Bi({threadId:s,sessionIds:r,newThreadName:t.name});xe(t.json===!0,o,()=>{Ct(o),process.stderr.write(d.dim(`split off ${r.length} session${r.length===1?"":"s"} from ${H(s)}
1600
- `))})}T();I();import{randomUUID as Sy}from"node:crypto";import{readFileSync as ZS,statSync as QS}from"node:fs";var ey=200*1024*1024,Vr=.7,Zr=.5,gd=Zr,ty=[{maxGapMs:3600*1e3,weight:.7,label:"<1h gap"},{maxGapMs:14400*1e3,weight:.4,label:"<4h gap"},{maxGapMs:1440*60*1e3,weight:.2,label:"<24h gap"}],sy=["let's commit","lets commit","now commit","inspect the diff","inspect this diff","review the diff","review this diff","diff of all changes","diff of changes","based on what we just did","based on the things done","based on all the things","continue from","continuing from","pick up where","next step","now fix","now lets","now let's","from the previous session","from our last session","from the last session"];function pd(e){if(!e)return null;if(e.startsWith("/")){let s=e.split(" \xB7 ");if(s.length>1)return s[1].trim().toLowerCase()}let t=e.split(" \xB7 ");return t.length>1?t[t.length-1].trim().toLowerCase():null}function ny(e,t){let s=t-e;if(s<0)return{weight:0,label:null};for(let n of ty)if(s<=n.maxGapMs)return{weight:n.weight,label:n.label};return{weight:0,label:null}}function ry(e){if(e.length===0)return{weight:0,matched:null,matchedIndex:-1};let t=[.4,.35,.3,.25,.2,.15,.1],s=Math.min(e.length,t.length);for(let n=0;n<s;n++){let r=e[n];if(!r)continue;let o=r.toLowerCase();for(let i of sy)if(o.includes(i))return{weight:t[n],matched:i,matchedIndex:n}}return{weight:0,matched:null,matchedIndex:-1}}function Kr(e,t){if(!e||!t||e.length!==t.length)return 0;let s=0;for(let n=0;n<e.length;n++)s+=e[n]*t[n];return s<-1?-1:s>1?1:s}function oy(e,t){if(e.length===0||t.length===0)return 0;let s=0;for(let n of e)for(let r of t){let o=Kr(n,r);o>s&&(s=o)}return s}function iy(e,t){let s=Kr(e.mean_embedding,t.mean_embedding),n=Kr(e.tail_pool,t.head_pool),r=oy(e.sample_chunks,t.sample_chunks),o=0,i=null;if(s>o&&(o=s,i="mean"),n>o&&(o=n,i="asymmetric"),r>o&&(o=r,i="max_pool"),o<.65)return{weight:0,cosine:o,mode:null};if(o>=.85)return{weight:.3,cosine:o,mode:i};let a=(o-.65)/.2*.3;return{weight:Math.round(a*100)/100,cosine:o,mode:i}}function ay(e,t){return e.cluster_id===null||t.cluster_id===null?{weight:0,same:!1}:e.cluster_id!==t.cluster_id?{weight:0,same:!1}:{weight:.05,same:!0}}function cy(e,t){if(e.size===0||t.size===0)return{weight:0,count:0};let s=0;for(let r of t)e.has(r)&&s++;return s===0?{weight:0,count:0}:{weight:Math.min(.4,s*.1),count:s}}function ly(e,t){let s=pd(e),n=pd(t);return s&&n&&s===n?{weight:.1,brand:s}:{weight:0,brand:null}}function md(e){return e.replace(/\s+/g," ").trim().toLowerCase()}function dy(e,t){let s=0,n=null,r=!1;if(e.authored_paths.size>0){let o=t.recent_user_messages.slice(0,3).join(`
1601
- `).toLowerCase();for(let i of e.authored_paths){let a=i.toLowerCase();if(t.touched_files.has(i)||o.includes(a)){s+=.5,n=i;break}}}if(e.authored_content.length>0&&t.recent_user_messages[0]){let o=md(t.recent_user_messages[0]);if(o.length>=200)for(let i of e.authored_content){let a=md(i);if(a.length<200)continue;let l=Math.min(a.length,240),c=a.slice(0,l);if(o.includes(c)){s+=.4,r=!0;break}}}return{weight:Math.min(.6,s),pathMatch:n,contentMatch:r}}function uy(e,t,s=gd){if(t.started_at_ms<=e.started_at_ms)return null;let n=e.ended_at_ms??e.started_at_ms;if(t.started_at_ms<n)return null;let r=ny(n,t.started_at_ms),o=t.recent_user_messages.length>0?t.recent_user_messages:t.first_user_message?[t.first_user_message]:[],i=ry(o),a=cy(e.touched_files,t.touched_files),l=ly(e.auto_title,t.auto_title),c=iy(e,t),u=ay(e,t),p=dy(e,t),m=r.weight+i.weight+a.weight+l.weight+c.weight+u.weight+p.weight;if(m<s)return null;let f=[];if(r.label&&f.push(`temporal ${r.label} (+${r.weight})`),i.matched){let g=i.matchedIndex===0?"opening message":`message #${i.matchedIndex+1}`;f.push(`continuation phrase "${i.matched}" in ${g} (+${i.weight})`)}if(a.count>0&&f.push(`${a.count} file${a.count===1?"":"s"} overlap (+${a.weight.toFixed(1)})`),l.brand&&f.push(`shared brand "${l.brand}" (+${l.weight})`),c.weight>0&&c.mode&&f.push(`semantic ${c.mode==="asymmetric"?"tail\u2192head":c.mode==="max_pool"?"best-chunk":"mean"} ${c.cosine.toFixed(2)} (+${c.weight.toFixed(2)})`),u.same&&f.push(`same cluster (+${u.weight})`),p.weight>0){let g=[];p.pathMatch&&g.push(`opened authored path "${p.pathMatch.split("/").pop()}"`),p.contentMatch&&g.push("verbatim-paste of authored content"),f.push(`doc-authorship: ${g.join(" + ")} (+${p.weight.toFixed(2)})`)}return{parent_id:e.id,child_id:t.id,confidence:Math.min(1,m),signals:{temporal:r.weight,continuation:i.weight,file_overlap:a.weight,same_brand:l.weight,semantic:c.weight,cluster:u.weight,doc_authorship:p.weight},reasons:f}}function fd(e,t=gd){let s=[];for(let n=0;n<e.length;n++){let r=e[n],o=null;for(let i=0;i<n;i++){let a=e[i],l=uy(a,r,t);l&&(!o||l.confidence>o.confidence)&&(o=l)}o&&s.push(o)}return s}function _d(e,t){let s=new Map,n=a=>{let l=a;for(;s.get(l)!==l;)l=s.get(l);let c=a;for(;s.get(c)!==l;){let u=s.get(c);s.set(c,l),c=u}return l},r=(a,l)=>{let c=n(a),u=n(l);c!==u&&s.set(c,u)};for(let a of e)s.has(a.parent_id)||s.set(a.parent_id,a.parent_id),s.has(a.child_id)||s.set(a.child_id,a.child_id),r(a.parent_id,a.child_id);let o=new Map;for(let a of s.keys()){let l=n(a),c=o.get(l);c||(c=[],o.set(l,c)),c.push(a)}let i=new Map;for(let a of t)i.set(a.id,a.started_at_ms);return Array.from(o.values()).map(a=>(a.sort((l,c)=>(i.get(l)??0)-(i.get(c)??0)),{rootId:a[0],sessionIds:a}))}function hd(e,t={}){let s=t.maxUserMessages??5,n=t.userMessageMaxLen??2e3,r=new Set,o=[],i=new Set,a=[],l;try{if(QS(e).size>ey)return{touched_files:r,recent_user_messages:o,authored_paths:i,authored_content:a};l=ZS(e,"utf8")}catch{return{touched_files:r,recent_user_messages:o,authored_paths:i,authored_content:a}}let c=0;for(;c<l.length;){let u=l.indexOf(`
1602
- `,c),p=u===-1?l.length:u,m=l.slice(c,p);if(c=u===-1?l.length:u+1,!m.trim())continue;let f;try{f=JSON.parse(m)}catch{continue}let g=f;if(g.type==="user"&&g.message?.role==="user"&&typeof g.message.content=="string"&&o.length<s){let E=g.message.content.trim();E&&o.push(E.length>n?E.slice(0,n):E)}let h=g.message?.content;if(Array.isArray(h))for(let E of h){if(!E||typeof E!="object")continue;let b=E;if(b.type!=="tool_use")continue;let S=b.input??{},C=typeof S.file_path=="string"?S.file_path:null;if(C){let R=Ks(C);R&&r.add(R)}if((b.name==="Write"||b.name==="Edit"||b.name==="MultiEdit")&&C){let R=Ks(C);R&&i.add(R);let L=typeof S.content=="string"?S.content:typeof S.new_string=="string"?S.new_string:null;L&&L.length>=200&&a.push(L.length>4096?L.slice(0,4096):L)}if(b.name==="Bash"&&typeof S.command=="string")for(let R of S.command.matchAll(/(?:^|[\s'"`(=])((?:\.\.?\/|\/|src\/|test\/|docs\/|site\/)[A-Za-z0-9_./-]+)/g)){let L=Ks(R[1]);L&&r.add(L)}if((b.name==="Glob"||b.name==="Grep")&&typeof S.pattern=="string"){let R=Ks(S.pattern);R&&!R.includes("*")&&r.add(R)}}}return{touched_files:r,recent_user_messages:o,authored_paths:i,authored_content:a}}function Ks(e){let t=e.trim().replace(/^['"]|['"]$/g,"");return!t||t.length<4||/[<>|;&\$`]/.test(t)?null:t}T();var Ed=10,bd=20;function py(e){if(!e)return!1;let t=e.split(`
1603
- `);if(t.length<4)return!1;let s=0,n=0;for(let r of t)/^\s*\d{1,5}\t/.test(r)?s++:/^\s*\/[A-Za-z0-9_./-]+/.test(r.trim())&&n++;return s/t.length>.7||n/t.length>.5}function my(e){let t=e.byteLength/4;if(!Number.isInteger(t)||t<=0)return null;let s=new Float32Array(t),n=new Float32Array(e.buffer,e.byteOffset,t);return s.set(n),s}function Sd(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];if(t<=0)return!1;let s=1/Math.sqrt(t);for(let n=0;n<e.length;n++)e[n]*=s;return!0}function Qr(e){if(e.length===0)return null;let t=e[0].length,s=new Float32Array(t);for(let n of e)if(n.length===t)for(let r=0;r<t;r++)s[r]+=n[r];for(let n=0;n<t;n++)s[n]/=e.length;return Sd(s)?s:null}function yd(e){let t=new Map;if(e.length===0)return t;let s=_(),n=e.map(()=>"?").join(","),r=[];try{r=s.prepare(`SELECT cm.rowid AS rowid, cm.session_id AS session_id,
1603
+ `))})}T();I();import{randomUUID as Ty}from"node:crypto";import{readFileSync as ey,statSync as ty}from"node:fs";var sy=200*1024*1024,Vr=.7,Zr=.5,gd=Zr,ny=[{maxGapMs:3600*1e3,weight:.7,label:"<1h gap"},{maxGapMs:14400*1e3,weight:.4,label:"<4h gap"},{maxGapMs:1440*60*1e3,weight:.2,label:"<24h gap"}],ry=["let's commit","lets commit","now commit","inspect the diff","inspect this diff","review the diff","review this diff","diff of all changes","diff of changes","based on what we just did","based on the things done","based on all the things","continue from","continuing from","pick up where","next step","now fix","now lets","now let's","from the previous session","from our last session","from the last session"];function pd(e){if(!e)return null;if(e.startsWith("/")){let s=e.split(" \xB7 ");if(s.length>1)return s[1].trim().toLowerCase()}let t=e.split(" \xB7 ");return t.length>1?t[t.length-1].trim().toLowerCase():null}function oy(e,t){let s=t-e;if(s<0)return{weight:0,label:null};for(let n of ny)if(s<=n.maxGapMs)return{weight:n.weight,label:n.label};return{weight:0,label:null}}function iy(e){if(e.length===0)return{weight:0,matched:null,matchedIndex:-1};let t=[.4,.35,.3,.25,.2,.15,.1],s=Math.min(e.length,t.length);for(let n=0;n<s;n++){let r=e[n];if(!r)continue;let o=r.toLowerCase();for(let i of ry)if(o.includes(i))return{weight:t[n],matched:i,matchedIndex:n}}return{weight:0,matched:null,matchedIndex:-1}}function Kr(e,t){if(!e||!t||e.length!==t.length)return 0;let s=0;for(let n=0;n<e.length;n++)s+=e[n]*t[n];return s<-1?-1:s>1?1:s}function ay(e,t){if(e.length===0||t.length===0)return 0;let s=0;for(let n of e)for(let r of t){let o=Kr(n,r);o>s&&(s=o)}return s}function cy(e,t){let s=Kr(e.mean_embedding,t.mean_embedding),n=Kr(e.tail_pool,t.head_pool),r=ay(e.sample_chunks,t.sample_chunks),o=0,i=null;if(s>o&&(o=s,i="mean"),n>o&&(o=n,i="asymmetric"),r>o&&(o=r,i="max_pool"),o<.65)return{weight:0,cosine:o,mode:null};if(o>=.85)return{weight:.3,cosine:o,mode:i};let a=(o-.65)/.2*.3;return{weight:Math.round(a*100)/100,cosine:o,mode:i}}function ly(e,t){return e.cluster_id===null||t.cluster_id===null?{weight:0,same:!1}:e.cluster_id!==t.cluster_id?{weight:0,same:!1}:{weight:.05,same:!0}}function dy(e,t){if(e.size===0||t.size===0)return{weight:0,count:0};let s=0;for(let r of t)e.has(r)&&s++;return s===0?{weight:0,count:0}:{weight:Math.min(.4,s*.1),count:s}}function uy(e,t){let s=pd(e),n=pd(t);return s&&n&&s===n?{weight:.1,brand:s}:{weight:0,brand:null}}function md(e){return e.replace(/\s+/g," ").trim().toLowerCase()}function py(e,t){let s=0,n=null,r=!1;if(e.authored_paths.size>0){let o=t.recent_user_messages.slice(0,3).join(`
1604
+ `).toLowerCase();for(let i of e.authored_paths){let a=i.toLowerCase();if(t.touched_files.has(i)||o.includes(a)){s+=.5,n=i;break}}}if(e.authored_content.length>0&&t.recent_user_messages[0]){let o=md(t.recent_user_messages[0]);if(o.length>=200)for(let i of e.authored_content){let a=md(i);if(a.length<200)continue;let l=Math.min(a.length,240),c=a.slice(0,l);if(o.includes(c)){s+=.4,r=!0;break}}}return{weight:Math.min(.6,s),pathMatch:n,contentMatch:r}}function my(e,t,s=gd){if(t.started_at_ms<=e.started_at_ms)return null;let n=e.ended_at_ms??e.started_at_ms;if(t.started_at_ms<n)return null;let r=oy(n,t.started_at_ms),o=t.recent_user_messages.length>0?t.recent_user_messages:t.first_user_message?[t.first_user_message]:[],i=iy(o),a=dy(e.touched_files,t.touched_files),l=uy(e.auto_title,t.auto_title),c=cy(e,t),u=ly(e,t),p=py(e,t),m=r.weight+i.weight+a.weight+l.weight+c.weight+u.weight+p.weight;if(m<s)return null;let f=[];if(r.label&&f.push(`temporal ${r.label} (+${r.weight})`),i.matched){let g=i.matchedIndex===0?"opening message":`message #${i.matchedIndex+1}`;f.push(`continuation phrase "${i.matched}" in ${g} (+${i.weight})`)}if(a.count>0&&f.push(`${a.count} file${a.count===1?"":"s"} overlap (+${a.weight.toFixed(1)})`),l.brand&&f.push(`shared brand "${l.brand}" (+${l.weight})`),c.weight>0&&c.mode&&f.push(`semantic ${c.mode==="asymmetric"?"tail\u2192head":c.mode==="max_pool"?"best-chunk":"mean"} ${c.cosine.toFixed(2)} (+${c.weight.toFixed(2)})`),u.same&&f.push(`same cluster (+${u.weight})`),p.weight>0){let g=[];p.pathMatch&&g.push(`opened authored path "${p.pathMatch.split("/").pop()}"`),p.contentMatch&&g.push("verbatim-paste of authored content"),f.push(`doc-authorship: ${g.join(" + ")} (+${p.weight.toFixed(2)})`)}return{parent_id:e.id,child_id:t.id,confidence:Math.min(1,m),signals:{temporal:r.weight,continuation:i.weight,file_overlap:a.weight,same_brand:l.weight,semantic:c.weight,cluster:u.weight,doc_authorship:p.weight},reasons:f}}function fd(e,t=gd){let s=[];for(let n=0;n<e.length;n++){let r=e[n],o=null;for(let i=0;i<n;i++){let a=e[i],l=my(a,r,t);l&&(!o||l.confidence>o.confidence)&&(o=l)}o&&s.push(o)}return s}function _d(e,t){let s=new Map,n=a=>{let l=a;for(;s.get(l)!==l;)l=s.get(l);let c=a;for(;s.get(c)!==l;){let u=s.get(c);s.set(c,l),c=u}return l},r=(a,l)=>{let c=n(a),u=n(l);c!==u&&s.set(c,u)};for(let a of e)s.has(a.parent_id)||s.set(a.parent_id,a.parent_id),s.has(a.child_id)||s.set(a.child_id,a.child_id),r(a.parent_id,a.child_id);let o=new Map;for(let a of s.keys()){let l=n(a),c=o.get(l);c||(c=[],o.set(l,c)),c.push(a)}let i=new Map;for(let a of t)i.set(a.id,a.started_at_ms);return Array.from(o.values()).map(a=>(a.sort((l,c)=>(i.get(l)??0)-(i.get(c)??0)),{rootId:a[0],sessionIds:a}))}function hd(e,t={}){let s=t.maxUserMessages??5,n=t.userMessageMaxLen??2e3,r=new Set,o=[],i=new Set,a=[],l;try{if(ty(e).size>sy)return{touched_files:r,recent_user_messages:o,authored_paths:i,authored_content:a};l=ey(e,"utf8")}catch{return{touched_files:r,recent_user_messages:o,authored_paths:i,authored_content:a}}let c=0;for(;c<l.length;){let u=l.indexOf(`
1605
+ `,c),p=u===-1?l.length:u,m=l.slice(c,p);if(c=u===-1?l.length:u+1,!m.trim())continue;let f;try{f=JSON.parse(m)}catch{continue}let g=f;if(g.type==="user"&&g.message?.role==="user"&&typeof g.message.content=="string"&&o.length<s){let E=g.message.content.trim();E&&o.push(E.length>n?E.slice(0,n):E)}let h=g.message?.content;if(Array.isArray(h))for(let E of h){if(!E||typeof E!="object")continue;let b=E;if(b.type!=="tool_use")continue;let S=b.input??{},C=typeof S.file_path=="string"?S.file_path:null;if(C){let R=Ks(C);R&&r.add(R)}if((b.name==="Write"||b.name==="Edit"||b.name==="MultiEdit")&&C){let R=Ks(C);R&&i.add(R);let L=typeof S.content=="string"?S.content:typeof S.new_string=="string"?S.new_string:null;L&&L.length>=200&&a.push(L.length>4096?L.slice(0,4096):L)}if(b.name==="Bash"&&typeof S.command=="string")for(let R of S.command.matchAll(/(?:^|[\s'"`(=])((?:\.\.?\/|\/|src\/|test\/|docs\/|site\/)[A-Za-z0-9_./-]+)/g)){let L=Ks(R[1]);L&&r.add(L)}if((b.name==="Glob"||b.name==="Grep")&&typeof S.pattern=="string"){let R=Ks(S.pattern);R&&!R.includes("*")&&r.add(R)}}}return{touched_files:r,recent_user_messages:o,authored_paths:i,authored_content:a}}function Ks(e){let t=e.trim().replace(/^['"]|['"]$/g,"");return!t||t.length<4||/[<>|;&\$`]/.test(t)?null:t}T();var Ed=10,bd=20;function gy(e){if(!e)return!1;let t=e.split(`
1606
+ `);if(t.length<4)return!1;let s=0,n=0;for(let r of t)/^\s*\d{1,5}\t/.test(r)?s++:/^\s*\/[A-Za-z0-9_./-]+/.test(r.trim())&&n++;return s/t.length>.7||n/t.length>.5}function fy(e){let t=e.byteLength/4;if(!Number.isInteger(t)||t<=0)return null;let s=new Float32Array(t),n=new Float32Array(e.buffer,e.byteOffset,t);return s.set(n),s}function Sd(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];if(t<=0)return!1;let s=1/Math.sqrt(t);for(let n=0;n<e.length;n++)e[n]*=s;return!0}function Qr(e){if(e.length===0)return null;let t=e[0].length,s=new Float32Array(t);for(let n of e)if(n.length===t)for(let r=0;r<t;r++)s[r]+=n[r];for(let n=0;n<t;n++)s[n]/=e.length;return Sd(s)?s:null}function yd(e){let t=new Map;if(e.length===0)return t;let s=_(),n=e.map(()=>"?").join(","),r=[];try{r=s.prepare(`SELECT cm.rowid AS rowid, cm.session_id AS session_id,
1604
1607
  cm.text AS text, v.embedding AS embedding
1605
1608
  FROM chunk_meta cm
1606
1609
  JOIN vec_chunks v ON v.rowid = cm.rowid
1607
1610
  WHERE cm.stale = 0
1608
1611
  AND cm.session_id IN (${n})
1609
- ORDER BY cm.session_id, cm.rowid ASC`).all(...e)}catch{return t}if(r.length===0)return t;let o=new Map;for(let i of r){let a=o.get(i.session_id);a||(a=[],o.set(i.session_id,a)),a.push(i)}for(let[i,a]of o){let l=a.filter(R=>!py(R.text)),c=l.length>0?l:a,u=[];for(let R of c){let L=my(R.embedding);L&&Sd(L)&&u.push(L)}if(u.length===0)continue;let p=Math.min(Ed,u.length),m=Math.max(0,u.length-Ed),f=u.slice(0,p),g=u.slice(m),h=Qr(f),E=Qr(g),b=Qr(u),S=new Map;for(let R=0;R<f.length&&S.size<bd;R++)S.set(R,f[R]);for(let R=0;R<g.length&&S.size<bd;R++)S.set(m+R,g[R]);let C=Array.from(S.values());t.set(i,{session_id:i,full_mean:b,head_pool:h,tail_pool:E,sample_chunks:C})}return t}function gy(e,t){if(e.length!==t.length)return 0;let s=0;for(let n=0;n<e.length;n++)s+=e[n]*t[n];return s<-1?-1:s>1?1:s}function Td(e,t=.8){let s=new Map,n=[],r=[];for(let[c,u]of e)u.full_mean&&(n.push(c),r.push(u.full_mean));if(n.length===0)return s;let o=new Int32Array(n.length);for(let c=0;c<o.length;c++)o[c]=c;let i=c=>{let u=c;for(;o[u]!==u;)u=o[u];let p=c;for(;o[p]!==u;){let m=o[p];o[p]=u,p=m}return u},a=(c,u)=>{let p=i(c),m=i(u);p!==m&&(o[p]=m)};for(let c=0;c<n.length;c++)for(let u=c+1;u<n.length;u++)gy(r[c],r[u])>=t&&a(c,u);let l=new Map;for(let c=0;c<n.length;c++){let u=i(c),p=l.get(u);p===void 0&&(p=l.size,l.set(u,p)),s.set(n[c],p)}return s}var Kt={lo:.4,hi:.7},Vs="claude-haiku-4-5-20251001",wd=50;var fy={same_workflow:.15,unrelated:-.2,unsure:0};function xd(e,t,s=Kt){if(s.lo>s.hi)throw new Error(`borderline band invalid: lo=${s.lo} > hi=${s.hi}`);let n=[];for(let r of e){if(r.confidence<s.lo||r.confidence>s.hi)continue;let o=t.get(r.parent_id),i=t.get(r.child_id);!o||!i||n.push({parent:o,child:i,step1:r})}return n.sort((r,o)=>r.child.started_at_ms-o.child.started_at_ms),n}function _y(e,t){let s=e.replace(/\s+/g," ").trim();return s.length>t?s.slice(0,t-1)+"\u2026":s}function hy(e,t){if(e===null)return"unknown";let s=t-e;if(s<0)return"overlap";let n=Math.round(s/6e4);if(n<60)return`${n}m`;let r=Math.round(s/36e5);return r<24?`${r}h`:`${Math.round(s/864e5)}d`}function Ey(e){let s=e.parent.recent_user_messages,n=e.child.recent_user_messages,r=s.slice(0,3),o=s.length>3?s.slice(-3):[],i=n.slice(0,3),a=c=>c.length===0?" (none captured)":c.map(u=>` - ${_y(u,500)}`).join(`
1610
- `),l=hy(e.parent.ended_at_ms??e.parent.started_at_ms,e.child.started_at_ms);return["You are evaluating whether two Claude Code sessions belong to the same continuous workflow.","","A deterministic scorer rated this pair in the borderline band. Its signals:",e.step1.reasons.length===0?" (no signals fired strongly)":e.step1.reasons.map(c=>` - ${c}`).join(`
1612
+ ORDER BY cm.session_id, cm.rowid ASC`).all(...e)}catch{return t}if(r.length===0)return t;let o=new Map;for(let i of r){let a=o.get(i.session_id);a||(a=[],o.set(i.session_id,a)),a.push(i)}for(let[i,a]of o){let l=a.filter(R=>!gy(R.text)),c=l.length>0?l:a,u=[];for(let R of c){let L=fy(R.embedding);L&&Sd(L)&&u.push(L)}if(u.length===0)continue;let p=Math.min(Ed,u.length),m=Math.max(0,u.length-Ed),f=u.slice(0,p),g=u.slice(m),h=Qr(f),E=Qr(g),b=Qr(u),S=new Map;for(let R=0;R<f.length&&S.size<bd;R++)S.set(R,f[R]);for(let R=0;R<g.length&&S.size<bd;R++)S.set(m+R,g[R]);let C=Array.from(S.values());t.set(i,{session_id:i,full_mean:b,head_pool:h,tail_pool:E,sample_chunks:C})}return t}function _y(e,t){if(e.length!==t.length)return 0;let s=0;for(let n=0;n<e.length;n++)s+=e[n]*t[n];return s<-1?-1:s>1?1:s}function Td(e,t=.8){let s=new Map,n=[],r=[];for(let[c,u]of e)u.full_mean&&(n.push(c),r.push(u.full_mean));if(n.length===0)return s;let o=new Int32Array(n.length);for(let c=0;c<o.length;c++)o[c]=c;let i=c=>{let u=c;for(;o[u]!==u;)u=o[u];let p=c;for(;o[p]!==u;){let m=o[p];o[p]=u,p=m}return u},a=(c,u)=>{let p=i(c),m=i(u);p!==m&&(o[p]=m)};for(let c=0;c<n.length;c++)for(let u=c+1;u<n.length;u++)_y(r[c],r[u])>=t&&a(c,u);let l=new Map;for(let c=0;c<n.length;c++){let u=i(c),p=l.get(u);p===void 0&&(p=l.size,l.set(u,p)),s.set(n[c],p)}return s}var Kt={lo:.4,hi:.7},Vs="claude-haiku-4-5-20251001",wd=50;var hy={same_workflow:.15,unrelated:-.2,unsure:0};function xd(e,t,s=Kt){if(s.lo>s.hi)throw new Error(`borderline band invalid: lo=${s.lo} > hi=${s.hi}`);let n=[];for(let r of e){if(r.confidence<s.lo||r.confidence>s.hi)continue;let o=t.get(r.parent_id),i=t.get(r.child_id);!o||!i||n.push({parent:o,child:i,step1:r})}return n.sort((r,o)=>r.child.started_at_ms-o.child.started_at_ms),n}function Ey(e,t){let s=e.replace(/\s+/g," ").trim();return s.length>t?s.slice(0,t-1)+"\u2026":s}function by(e,t){if(e===null)return"unknown";let s=t-e;if(s<0)return"overlap";let n=Math.round(s/6e4);if(n<60)return`${n}m`;let r=Math.round(s/36e5);return r<24?`${r}h`:`${Math.round(s/864e5)}d`}function Sy(e){let s=e.parent.recent_user_messages,n=e.child.recent_user_messages,r=s.slice(0,3),o=s.length>3?s.slice(-3):[],i=n.slice(0,3),a=c=>c.length===0?" (none captured)":c.map(u=>` - ${Ey(u,500)}`).join(`
1613
+ `),l=by(e.parent.ended_at_ms??e.parent.started_at_ms,e.child.started_at_ms);return["You are evaluating whether two Claude Code sessions belong to the same continuous workflow.","","A deterministic scorer rated this pair in the borderline band. Its signals:",e.step1.reasons.length===0?" (no signals fired strongly)":e.step1.reasons.map(c=>` - ${c}`).join(`
1611
1614
  `),` step1_confidence: ${e.step1.confidence.toFixed(2)}`,"","PARENT SESSION","First user messages:",a(r),"Last user messages:",a(o),"",`CHILD SESSION (gap from parent: ${l})`,"First user messages:",a(i),"","Reply with EXACTLY one JSON object on a single line, no prose, no markdown:",'{"verdict":"same_workflow"|"unrelated"|"unsure","reason":"<one short sentence>"}',"","Guidance:",'- "same_workflow" = the child is clearly continuing what the parent was doing.','- "unrelated" = different problem, different files, different intent.','- "unsure" = could go either way; do not force a verdict.'].join(`
1612
- `)}function by(e){if(!e)return null;let t=e.trim();if(!t)return null;let s=t;try{let l=JSON.parse(t);typeof l.result=="string"&&(s=l.result.trim())}catch{}let n=s.match(/\{[\s\S]*\}/);if(!n)return null;let r;try{r=JSON.parse(n[0])}catch{return null}if(!r||typeof r!="object")return null;let o=r,i=typeof o.verdict=="string"?o.verdict.toLowerCase():"";if(i!=="same_workflow"&&i!=="unrelated"&&i!=="unsure")return null;let a=typeof o.reason=="string"&&o.reason.trim()?o.reason.trim():"";return{verdict:i,reason:a,delta:fy[i]}}async function Rd(e,t={}){if(t.signal?.aborted)return null;let s=t.model??Vs,n=Ey(e),r=t.spawn;if(!r)try{let i=await Promise.resolve().then(()=>(Je(),Qn));if(!i.isClaudeCliAvailable())return null;r=(a,l)=>i.spawnClaudePrompt(a,[],l)}catch{return null}let o;try{o=await Promise.race([r(n,{model:s}),new Promise(i=>{t.signal&&t.signal.addEventListener("abort",()=>i({success:!1,stdout:""}),{once:!0})})])}catch{return null}return!o.success||!o.stdout?null:by(o.stdout)}function kd(e){let t=[];for(let s of e.proposals){let n=`${s.parent_id}::${s.child_id}`,r=e.rescored.get(n);if(!r){t.push(s);continue}let o=Math.max(0,Math.min(1,s.confidence+r.delta));if(o<e.applyThreshold)continue;let i=`LLM: ${r.verdict}${r.reason?` \u2014 ${r.reason}`:""} (${r.delta>=0?"+":""}${r.delta.toFixed(2)})`;t.push({...s,confidence:o,reasons:[...s.reasons,i]})}return t}function Nd(e){return`${e.parent_id}::${e.child_id}`}async function yy(e){if(e.signal?.aborted)return null;let t,s;try{({spawnClaudePrompt:t,isClaudeCliAvailable:s}=await Promise.resolve().then(()=>(Je(),Qn)))}catch{return null}if(!s())return null;let n=[];for(let o of e.sessionIds){let i=e.rowById.get(o);if(!i)continue;let a=i.alias||i.auto_title||(i.first_user_message?i.first_user_message.slice(0,120).replace(/\n/g," "):"(no title)");n.push(`- ${a}`)}let r=`Below is a chronological list of related Claude Code sessions that form one continuous workflow. Generate a single short descriptive name for the workflow as a whole. Requirements:
1615
+ `)}function yy(e){if(!e)return null;let t=e.trim();if(!t)return null;let s=t;try{let l=JSON.parse(t);typeof l.result=="string"&&(s=l.result.trim())}catch{}let n=s.match(/\{[\s\S]*\}/);if(!n)return null;let r;try{r=JSON.parse(n[0])}catch{return null}if(!r||typeof r!="object")return null;let o=r,i=typeof o.verdict=="string"?o.verdict.toLowerCase():"";if(i!=="same_workflow"&&i!=="unrelated"&&i!=="unsure")return null;let a=typeof o.reason=="string"&&o.reason.trim()?o.reason.trim():"";return{verdict:i,reason:a,delta:hy[i]}}async function Rd(e,t={}){if(t.signal?.aborted)return null;let s=t.model??Vs,n=Sy(e),r=t.spawn;if(!r)try{let i=await Promise.resolve().then(()=>(Je(),Qn));if(!i.isClaudeCliAvailable())return null;r=(a,l)=>i.spawnClaudePrompt(a,[],l)}catch{return null}let o;try{o=await Promise.race([r(n,{model:s}),new Promise(i=>{t.signal&&t.signal.addEventListener("abort",()=>i({success:!1,stdout:""}),{once:!0})})])}catch{return null}return!o.success||!o.stdout?null:yy(o.stdout)}function kd(e){let t=[];for(let s of e.proposals){let n=`${s.parent_id}::${s.child_id}`,r=e.rescored.get(n);if(!r){t.push(s);continue}let o=Math.max(0,Math.min(1,s.confidence+r.delta));if(o<e.applyThreshold)continue;let i=`LLM: ${r.verdict}${r.reason?` \u2014 ${r.reason}`:""} (${r.delta>=0?"+":""}${r.delta.toFixed(2)})`;t.push({...s,confidence:o,reasons:[...s.reasons,i]})}return t}function Nd(e){return`${e.parent_id}::${e.child_id}`}async function wy(e){if(e.signal?.aborted)return null;let t,s;try{({spawnClaudePrompt:t,isClaudeCliAvailable:s}=await Promise.resolve().then(()=>(Je(),Qn)))}catch{return null}if(!s())return null;let n=[];for(let o of e.sessionIds){let i=e.rowById.get(o);if(!i)continue;let a=i.alias||i.auto_title||(i.first_user_message?i.first_user_message.slice(0,120).replace(/\n/g," "):"(no title)");n.push(`- ${a}`)}let r=`Below is a chronological list of related Claude Code sessions that form one continuous workflow. Generate a single short descriptive name for the workflow as a whole. Requirements:
1613
1616
  - 4 to 8 words
1614
1617
  - Title-case, no trailing punctuation
1615
1618
  - Capture the WORKFLOW (e.g., "Update Remotion deps + lint cleanup"), not any one session
@@ -1620,7 +1623,7 @@ Sessions:
1620
1623
  `+n.join(`
1621
1624
  `)+`
1622
1625
 
1623
- Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model:e.model}:{}),i=null,a=new Promise(p=>{e.signal&&(i=()=>p(null),e.signal.addEventListener("abort",i,{once:!0}))}),l=await Promise.race([o,a]);if(i&&e.signal&&e.signal.removeEventListener("abort",i),!l||!l.success)return null;let c=l.stdout.trim();if(!c)return null;let u;try{let p=JSON.parse(c);u=typeof p.result=="string"?p.result:c}catch{u=c}return u=u.trim().replace(/^["'`]+|["'`]+$/g,"").replace(/[.!?]+$/g,"").trim(),u?u.length>80?u.slice(0,77)+"...":u:null}catch{return null}}function Ty(e){let t=new Map;for(let o of e){let i=t.get(o.project);i||(i=[],t.set(o.project,i)),i.push(o)}let s=e.map(o=>o.id),n=new Map;try{n=yd(s)}catch{n=new Map}let r=new Map;for(let[o,i]of t){let a=new Map;for(let u of i){let p=n.get(u.id);p&&a.set(u.id,p)}let l=Td(a,.8),c=[];for(let u of i){let p=xy(u,n,l);p&&c.push(p)}r.set(o,c)}return{byProject:t,scannablesByProject:r}}function wy(e){let t=_(),s={},n="1=1 AND s.message_count > 2";return n+=" AND COALESCE(s.auto_title, '') NOT LIKE '[meta]%' AND COALESCE(s.auto_title, '') NOT LIKE '[output-index]%' AND COALESCE(s.auto_title, '') NOT LIKE '[skill]%'",e.project&&(n+=" AND p.name = @project",s.project=e.project),t.prepare(`SELECT s.id, p.name AS project, s.started_at, s.ended_at,
1626
+ Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model:e.model}:{}),i=null,a=new Promise(p=>{e.signal&&(i=()=>p(null),e.signal.addEventListener("abort",i,{once:!0}))}),l=await Promise.race([o,a]);if(i&&e.signal&&e.signal.removeEventListener("abort",i),!l||!l.success)return null;let c=l.stdout.trim();if(!c)return null;let u;try{let p=JSON.parse(c);u=typeof p.result=="string"?p.result:c}catch{u=c}return u=u.trim().replace(/^["'`]+|["'`]+$/g,"").replace(/[.!?]+$/g,"").trim(),u?u.length>80?u.slice(0,77)+"...":u:null}catch{return null}}function xy(e){let t=new Map;for(let o of e){let i=t.get(o.project);i||(i=[],t.set(o.project,i)),i.push(o)}let s=e.map(o=>o.id),n=new Map;try{n=yd(s)}catch{n=new Map}let r=new Map;for(let[o,i]of t){let a=new Map;for(let u of i){let p=n.get(u.id);p&&a.set(u.id,p)}let l=Td(a,.8),c=[];for(let u of i){let p=ky(u,n,l);p&&c.push(p)}r.set(o,c)}return{byProject:t,scannablesByProject:r}}function Ry(e){let t=_(),s={},n="1=1 AND s.message_count > 2";return n+=" AND COALESCE(s.auto_title, '') NOT LIKE '[meta]%' AND COALESCE(s.auto_title, '') NOT LIKE '[output-index]%' AND COALESCE(s.auto_title, '') NOT LIKE '[skill]%'",e.project&&(n+=" AND p.name = @project",s.project=e.project),t.prepare(`SELECT s.id, p.name AS project, s.started_at, s.ended_at,
1624
1627
  s.first_user_message, s.auto_title,
1625
1628
  NULLIF(sa.alias, '') AS alias,
1626
1629
  s.file_path
@@ -1628,38 +1631,38 @@ Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model
1628
1631
  JOIN projects p ON p.id = s.project_id
1629
1632
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1630
1633
  WHERE ${n}
1631
- ORDER BY p.name ASC, s.started_at ASC`).all(s)}function xy(e,t,s){if(!e.started_at)return null;let n=Date.parse(e.started_at);if(!Number.isFinite(n))return null;let r=e.ended_at?Date.parse(e.ended_at):null,o=hd(e.file_path,{maxUserMessages:7}),i=t?.get(e.id);return{id:e.id,started_at_ms:n,ended_at_ms:Number.isFinite(r)?r:null,first_user_message:e.first_user_message,recent_user_messages:o.recent_user_messages,auto_title:e.auto_title,touched_files:o.touched_files,mean_embedding:i?.full_mean??null,head_pool:i?.head_pool??null,tail_pool:i?.tail_pool??null,sample_chunks:i?.sample_chunks??[],cluster_id:s?.get(e.id)??null,authored_paths:o.authored_paths,authored_content:o.authored_content}}function Zs(e){let t=e.id.slice(0,8),s=e.alias||e.auto_title||(e.first_user_message?e.first_user_message.slice(0,50):"(no title)");return`${t} ${s}`}function Cd(e){if(!e)return"?";let t=new Date(e);if(Number.isNaN(t.getTime()))return"?";let s=n=>String(n).padStart(2,"0");return`${t.getFullYear()}-${s(t.getMonth()+1)}-${s(t.getDate())} ${s(t.getHours())}:${s(t.getMinutes())}`}function Ld(e){let t=e.alias||e.auto_title||(e.first_user_message?e.first_user_message.slice(0,60).replace(/\n/g," ").trim():`thread from ${e.id.slice(0,8)}`);return t.length>80?t.slice(0,77)+"...":t}async function Ry(e){if(!e.rescore.enabled)return{proposals:e.proposals,ran:!1,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1};let t=e.rescore.band??Kt,s=e.rescore.cap??wd,n=e.rescore.model??Vs,r=new Map(e.scannables.map(m=>[m.id,m])),o=xd(e.proposals,r,t);if(o.length===0)return{proposals:e.proposals,ran:!0,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1};if(o.length>s)return{proposals:e.proposals,ran:!1,considered:o.length,promoted:0,demoted:0,unsure:0,failed:0,capped:!0};let i=new Map,a=0,l=0,c=0,u=0;for(let m=0;m<o.length&&!e.signal?.aborted;m++){let f=o[m],g=await Rd(f,{model:n,signal:e.signal});g?(i.set(Nd(f.step1),g),g.verdict==="same_workflow"?a++:g.verdict==="unrelated"?l++:c++):u++,e.onProgress?.({phase:"rescoring",current:m+1,total:o.length,verdict:g?.verdict??"failed"})}return{proposals:kd({proposals:e.proposals,rescored:i,applyThreshold:e.applyThreshold}),ran:!0,considered:o.length,promoted:a,demoted:l,unsure:c,failed:u,capped:!1}}async function ky(e){let t=_(),s=new Map(e.rows.map(c=>[c.id,c])),n=_d(e.edges,e.scannables),r=new Date().toISOString(),o=[],i=new Map,a=0;for(let c of n){if(a++,e.signal?.aborted)break;let u=s.get(c.rootId),p=Ld(u);if(!e.llmNames){i.set(c.rootId,p),e.onProgress?.({phase:"naming",current:a,total:n.length,thread_name:p});continue}let f=await yy({rootRow:u,sessionIds:c.sessionIds,rowById:s,signal:e.signal,model:e.model})??p;i.set(c.rootId,f),e.onProgress?.({phase:"naming",current:a,total:n.length,thread_name:f})}return t.transaction(()=>{for(let c of n){if(!i.has(c.rootId))continue;let u=s.get(c.rootId),p=`auto-scan-${Sy()}`,m=i.get(c.rootId)??Ld(u),f=`Auto-detected workflow chain (${c.sessionIds.length} sessions). Source: auto-scan-v1.`;t.prepare("INSERT INTO threads (id, name, summary, created_at) VALUES (?, ?, ?, ?)").run(p,m,f,r),t.prepare(`INSERT INTO thread_edges
1634
+ ORDER BY p.name ASC, s.started_at ASC`).all(s)}function ky(e,t,s){if(!e.started_at)return null;let n=Date.parse(e.started_at);if(!Number.isFinite(n))return null;let r=e.ended_at?Date.parse(e.ended_at):null,o=hd(e.file_path,{maxUserMessages:7}),i=t?.get(e.id);return{id:e.id,started_at_ms:n,ended_at_ms:Number.isFinite(r)?r:null,first_user_message:e.first_user_message,recent_user_messages:o.recent_user_messages,auto_title:e.auto_title,touched_files:o.touched_files,mean_embedding:i?.full_mean??null,head_pool:i?.head_pool??null,tail_pool:i?.tail_pool??null,sample_chunks:i?.sample_chunks??[],cluster_id:s?.get(e.id)??null,authored_paths:o.authored_paths,authored_content:o.authored_content}}function Zs(e){let t=e.id.slice(0,8),s=e.alias||e.auto_title||(e.first_user_message?e.first_user_message.slice(0,50):"(no title)");return`${t} ${s}`}function Cd(e){if(!e)return"?";let t=new Date(e);if(Number.isNaN(t.getTime()))return"?";let s=n=>String(n).padStart(2,"0");return`${t.getFullYear()}-${s(t.getMonth()+1)}-${s(t.getDate())} ${s(t.getHours())}:${s(t.getMinutes())}`}function Ld(e){let t=e.alias||e.auto_title||(e.first_user_message?e.first_user_message.slice(0,60).replace(/\n/g," ").trim():`thread from ${e.id.slice(0,8)}`);return t.length>80?t.slice(0,77)+"...":t}async function Ny(e){if(!e.rescore.enabled)return{proposals:e.proposals,ran:!1,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1};let t=e.rescore.band??Kt,s=e.rescore.cap??wd,n=e.rescore.model??Vs,r=new Map(e.scannables.map(m=>[m.id,m])),o=xd(e.proposals,r,t);if(o.length===0)return{proposals:e.proposals,ran:!0,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1};if(o.length>s)return{proposals:e.proposals,ran:!1,considered:o.length,promoted:0,demoted:0,unsure:0,failed:0,capped:!0};let i=new Map,a=0,l=0,c=0,u=0;for(let m=0;m<o.length&&!e.signal?.aborted;m++){let f=o[m],g=await Rd(f,{model:n,signal:e.signal});g?(i.set(Nd(f.step1),g),g.verdict==="same_workflow"?a++:g.verdict==="unrelated"?l++:c++):u++,e.onProgress?.({phase:"rescoring",current:m+1,total:o.length,verdict:g?.verdict??"failed"})}return{proposals:kd({proposals:e.proposals,rescored:i,applyThreshold:e.applyThreshold}),ran:!0,considered:o.length,promoted:a,demoted:l,unsure:c,failed:u,capped:!1}}async function Cy(e){let t=_(),s=new Map(e.rows.map(c=>[c.id,c])),n=_d(e.edges,e.scannables),r=new Date().toISOString(),o=[],i=new Map,a=0;for(let c of n){if(a++,e.signal?.aborted)break;let u=s.get(c.rootId),p=Ld(u);if(!e.llmNames){i.set(c.rootId,p),e.onProgress?.({phase:"naming",current:a,total:n.length,thread_name:p});continue}let f=await wy({rootRow:u,sessionIds:c.sessionIds,rowById:s,signal:e.signal,model:e.model})??p;i.set(c.rootId,f),e.onProgress?.({phase:"naming",current:a,total:n.length,thread_name:f})}return t.transaction(()=>{for(let c of n){if(!i.has(c.rootId))continue;let u=s.get(c.rootId),p=`auto-scan-${Ty()}`,m=i.get(c.rootId)??Ld(u),f=`Auto-detected workflow chain (${c.sessionIds.length} sessions). Source: auto-scan-v1.`;t.prepare("INSERT INTO threads (id, name, summary, created_at) VALUES (?, ?, ?, ?)").run(p,m,f,r),t.prepare(`INSERT INTO thread_edges
1632
1635
  (thread_id, session_id, parent_session_id, role, confidence, source, added_at)
1633
1636
  VALUES (?, ?, NULL, 'origin', 1.0, 'auto-scan-v1', ?)`).run(p,c.rootId,r);let g=new Map;for(let h of e.edges)c.sessionIds.includes(h.child_id)&&g.set(h.child_id,h);for(let h of c.sessionIds){if(h===c.rootId)continue;let E=g.get(h);E&&t.prepare(`INSERT INTO thread_edges
1634
1637
  (thread_id, session_id, parent_session_id, role, confidence, source, added_at)
1635
- VALUES (?, ?, ?, 'child', ?, 'auto-scan-v1', ?)`).run(p,h,E.parent_id,E.confidence,r)}o.push({thread_id:p,name:m,session_count:c.sessionIds.length})}})(),{project:e.project,threads:o}}async function Od(e){let t=!!e.apply,s=e.confidenceMin?Number(e.confidenceMin):t?Vr:Zr;if(!Number.isFinite(s)||s<0||s>1){console.error(d.err("--confidence-min must be a number in [0, 1]")),process.exitCode=1;return}let n=!!e.llmRescore,r={lo:e.rescoreBandLo?Number(e.rescoreBandLo):Kt.lo,hi:e.rescoreBandHi?Number(e.rescoreBandHi):Kt.hi};if(n&&(!Number.isFinite(r.lo)||!Number.isFinite(r.hi)||r.lo<0||r.hi>1||r.lo>r.hi)){console.error(d.err("--rescore-band-lo/hi must satisfy 0 \u2264 lo \u2264 hi \u2264 1")),process.exitCode=1;return}let o=e.rescoreModel??Vs,i=wy({project:e.project});if(i.length===0){console.log(d.dim("no sessions matched"));return}let{byProject:a,scannablesByProject:l}=Ty(i),c=n?Math.min(s,r.lo):s,u=new Map,p=0;for(let[f]of a){let g=l.get(f)??[],h=fd(g,c);if(n&&h.length>0){let E=await Ry({proposals:h,scannables:g,applyThreshold:s,rescore:{enabled:!0,band:r,model:o}});h=E.proposals,E.capped?(console.error(d.err(`[${f}] borderline pairs exceeded cap (${E.considered}); skipped LLM rescore. Tighten the band or scan a smaller project.`)),h=h.filter(b=>b.confidence>=s)):n?E.failed===E.considered&&E.considered>0&&(h=h.filter(b=>b.confidence>=s)):h=h.filter(b=>b.confidence>=s)}else n&&(h=h.filter(E=>E.confidence>=s));u.set(f,{proposals:h,scannables:g}),p+=h.length}if(t){if(p===0){console.log(d.dim("no edges above threshold; nothing to apply"));return}let f={threads_created:0,edges_written:0,per_project:[]},g=!e.noLlmNames;for(let[h,{proposals:E,scannables:b}]of u){if(E.length===0)continue;let S=await ky({project:h,rows:a.get(h),edges:E,scannables:b,llmNames:g});f.per_project.push(S),f.threads_created+=S.threads.length,f.edges_written+=E.length+S.threads.length}if(e.json){console.log(JSON.stringify({mode:"apply",threshold:s,...f},null,2));return}console.log(d.ok(`Applied ${f.threads_created} thread${f.threads_created===1?"":"s"} with ${f.edges_written} edges total (threshold ${s}).`));for(let h of f.per_project){console.log(` ${d.bold(h.project)}`);for(let E of h.threads)console.log(` ${d.dim(E.thread_id.slice(0,16)+"\u2026")} ${E.name} ${d.dim(`(${E.session_count} sessions)`)}`)}console.log(),console.log(d.dim("Rollback: sqlite3 ~/.recall/db.sqlite \\")),console.log(d.dim(` "DELETE FROM thread_edges WHERE source='auto-scan-v1';`)),console.log(d.dim(` DELETE FROM threads WHERE id LIKE 'auto-scan-%';"`));return}if(e.json){let f=[];for(let[g,{proposals:h}]of u){let E=new Map(a.get(g).map(b=>[b.id,b]));for(let b of h)f.push({project:g,parent_id:b.parent_id,parent_label:Zs(E.get(b.parent_id)),child_id:b.child_id,child_label:Zs(E.get(b.child_id)),confidence:b.confidence,signals:b.signals,reasons:b.reasons})}console.log(JSON.stringify({mode:"dry-run",threshold:s,total:p,edges:f},null,2));return}console.log(d.dim(`recall thread scan \xB7 ${a.size} project${a.size===1?"":"s"} \xB7 DRY RUN \xB7 threshold ${s}`)),console.log(d.dim(" Algorithm: temporal + continuation phrase + file overlap + same brand.")),console.log();for(let[f,g]of a){let{proposals:h}=u.get(f),E=new Map(g.map(S=>[S.id,S]));if(console.log(d.bold(f)),console.log(d.dim(` ${g.length} eligible session${g.length===1?"":"s"}; ${h.length} parent-child edge${h.length===1?"":"s"} proposed.`)),h.length===0){console.log(d.dim(" (no edges above threshold \u2014 all sessions are origins)")),console.log();continue}let b=[...h].sort((S,C)=>{let R=E.get(S.child_id),L=E.get(C.child_id);return(R.started_at??"").localeCompare(L.started_at??"")});for(let S of b){let C=E.get(S.parent_id),R=E.get(S.child_id),L=S.confidence.toFixed(2);console.log(` ${d.dim(Cd(C.started_at).padEnd(16))} ${d.bold("PARENT")} ${Zs(C)}`),console.log(` ${d.dim(Cd(R.started_at).padEnd(16))} ${d.bold(" \u2514\u2500 child")} ${Zs(R)} ${d.dim(`[conf ${L}]`)}`),console.log(` ${" ".repeat(28)}${d.dim(S.reasons.join(" \xB7 "))}`),console.log()}}let m=Array.from(a.entries()).reduce((f,[g,h])=>f+(h.length-(u.get(g)?.proposals.length??0)),0);console.log(`${p} edge${p===1?"":"s"} proposed across ${a.size} project${a.size===1?"":"s"}; ${m} origin session${m===1?"":"s"} (no proposed parent).`),console.log(d.dim(` This is a DRY RUN. To write: rerun with --apply (default threshold ${Vr}).`))}I();j();import{existsSync as Ny,readFileSync as Cy}from"node:fs";function Ly(){let e=`${x}/daemon.port`;if(!Ny(e))return null;try{let t=Cy(e,"utf8").trim();return/^\d+$/.test(t)?t:null}catch{return null}}async function Oy(e){try{return(await _t(`http://127.0.0.1:${e}/api/health`,{signal:AbortSignal.timeout(1e4)})).ok}catch{return!1}}async function Ay(e){let t=await _t(`http://127.0.0.1:${e}/api/projects`);if(!t.ok)throw new Error(`failed to list projects: HTTP ${t.status}`);return await t.json()}function Iy(e,t){let s=t.replace(/\/+$/,""),n=null,r=-1;for(let o of e){if(!o.decoded_path)continue;let i=o.decoded_path.replace(/\/+$/,"");(s===i||s.startsWith(i+"/"))&&i.length>r&&(n=o,r=i.length)}return n}function vy(e,t){let s=e.find(r=>r.name===t);if(s)return s;let n=e.filter(r=>r.name.toLowerCase().includes(t.toLowerCase()));return n.length===1?n[0]:null}function Ad(e){return e.alias||e.auto_title||(e.first_user_message?Y(e.first_user_message,60):"(no title)")}function My(e){if(!e)return"?";let t=new Date(e);if(Number.isNaN(t.getTime()))return"?";let s=n=>String(n).padStart(2,"0");return`${t.getFullYear()}-${s(t.getMonth()+1)}-${s(t.getDate())} ${s(t.getHours())}:${s(t.getMinutes())}`}function Dy(e,t){let s=t==="preflight"?d.dim(`recall threads sync \xB7 ${e.project.name} \xB7 PREFLIGHT (no writes)`):d.dim(`recall threads sync \xB7 ${e.project.name}`);if(console.log(s),console.log(),e.thread.exists?console.log(` ${d.bold("Thread")} ${e.thread.name} ${d.dim(`(reusing, ${e.thread.existing_session_count} existing session${e.thread.existing_session_count===1?"":"s"})`)}`):console.log(` ${d.bold("Thread")} ${e.thread.name} ${d.ok("(new)")}`),console.log(),e.candidates.length===0){if(console.log(d.dim(" No active sessions in the rolling window.")),e.warnings.length>0)for(let c of e.warnings)console.log(d.warn(` \u26A0 ${c}`));return}let n=new Map;for(let c of e.proposed_edges)n.set(c.child_id,c);let r=new Map;for(let c of e.preserved_manual_edges)r.set(c.session_id,c.parent_session_id);let o=new Set(e.candidates.map(c=>c.session_id)),i=e.proposed_additions.length,a=e.candidates.length-i;console.log(` ${d.bold("Candidates")} ${e.candidates.length} active session${e.candidates.length===1?"":"s"} ${d.dim(`(${i} new \xB7 ${a} keep)`)}`);let l=String(e.candidates.length).length;for(let c=0;c<e.candidates.length;c++){let u=e.candidates[c],m=e.proposed_additions.some(S=>S.session_id===u.session_id)?d.ok("NEW "):d.dim("keep"),f=n.get(u.session_id)??(r.has(u.session_id)&&r.get(u.session_id)!==null,null),g=f&&o.has(f.parent_id)?" \u2514\u2500 ":" ",h=My(u.started_at),E=d.dim(`${String(c+1).padStart(l," ")}.`);console.log(` ${E} ${m} ${d.dim(h.padEnd(16))} ${g}${d.dim(u.session_id.slice(0,8))} ${Ad(u)}`);let b=" ".repeat(l+2);if(f&&o.has(f.parent_id)){let S=f.confidence.toFixed(2),C=Ad(e.candidates.find(R=>R.session_id===f.parent_id));console.log(` ${b}${" ".repeat(28)} parent ${d.dim(f.parent_id.slice(0,8))} (${C}) ${d.dim(`[conf ${S}]`)}`),console.log(` ${b}${" ".repeat(28)} ${d.dim(f.reasons.join(" \xB7 "))}`)}if(r.has(u.session_id)){let S=r.get(u.session_id);S&&console.log(` ${b}${" ".repeat(28)} ${d.bold("manual parent preserved")} ${d.dim(S.slice(0,8))}`)}}if(e.preserved_manual_edges.length>0&&(console.log(),console.log(d.dim(` ${e.preserved_manual_edges.length} manual edge${e.preserved_manual_edges.length===1?"":"s"} will be preserved.`))),e.warnings.length>0){console.log();for(let c of e.warnings)console.log(d.warn(` \u26A0 ${c}`))}}function $y(e){console.log(),console.log(d.ok(`Added ${e.added} session${e.added===1?"":"s"}, set ${e.edges_set} parent edge${e.edges_set===1?"":"s"}, preserved ${e.preserved_manual} manual edge${e.preserved_manual===1?"":"s"}.`)),console.log(d.dim(` thread_id: ${e.thread_id}`))}async function Id(e){let t=Ly();if(!t){console.error(d.err("Daemon is not running. Start it with `recall start`, then re-run this command.")),process.exitCode=1;return}if(!await Oy(t)){console.error(d.err(`Daemon on port ${t} is not responding. Try \`recall stop && recall start\`.`)),process.exitCode=1;return}let n;try{n=await Ay(t)}catch(c){console.error(d.err(c.message)),process.exitCode=1;return}let r;if(e.project){if(r=vy(n,e.project),!r){console.error(d.err(`No project matching "${e.project}". Run \`recall projects\` to list known projects.`)),process.exitCode=1;return}}else{let c=process.cwd();if(r=Iy(n,c),!r){console.error(d.err(`Current directory (${c}) does not match any known project. Pass --project <name> or cd into a project root.`)),process.exitCode=1;return}}let o=e.windowHours?Number(e.windowHours):void 0;if(o!==void 0&&(!Number.isFinite(o)||o<=0)){console.error(d.err("--window-hours must be a positive number")),process.exitCode=1;return}let i=e.preflight?"preflight":"apply",a={project_id:r.id,mode:i};o!==void 0&&(a.window_hours=o);let l;try{let c=await tt("POST",`http://127.0.0.1:${t}/api/threads/sync-active`,a);if(!c.ok){let u=await c.text().catch(()=>"");throw new Error(`HTTP ${c.status}: ${u.slice(0,200)}`)}l=await c.json()}catch(c){console.error(d.err(`Sync failed: ${c.message}`)),process.exitCode=1;return}if(e.json){console.log(JSON.stringify({mode:i,...l},null,2));return}Dy(l.plan,i),i==="apply"&&l.result?$y(l.result):i==="preflight"&&(console.log(),console.log(d.dim(" This is a PREFLIGHT. To write: re-run without --preflight.")))}T();import{writeFileSync as oT,existsSync as iT,mkdirSync as aT}from"node:fs";import{join as Vd}from"node:path";import{homedir as cT}from"node:os";import{execSync as It}from"node:child_process";import tT from"satori";import sT from"sharp";import{readFileSync as ro}from"node:fs";import{join as cn}from"node:path";var oo=cn(Te(),"dist","share","fonts"),Yd=!1,qd=[];function nT(){return Yd||(qd=[{name:"Inter",data:ro(cn(oo,"Inter-Regular.woff")),weight:400,style:"normal"},{name:"Inter",data:ro(cn(oo,"Inter-Bold.woff")),weight:700,style:"normal"},{name:"JetBrains Mono",data:ro(cn(oo,"JetBrainsMono-Regular.woff")),weight:400,style:"normal"}],Yd=!0),qd}async function rT(e){switch(e){case"A":return await Promise.resolve().then(()=>($d(),Dd));case"B":return await Promise.resolve().then(()=>(Fd(),Pd));case"C":return await Promise.resolve().then(()=>(Hd(),Bd));case"D":return await Promise.resolve().then(()=>(Jd(),Xd));case"E":return await Promise.resolve().then(()=>(zd(),Gd))}}async function ln(e,t){let n=(await rT(e)).render(t),i=await tT(n,{width:1080,height:e==="E"?1920:1350,fonts:nT()});return await sT(Buffer.from(i)).png({quality:90}).toBuffer()}function Kd(e,t){let s=new URLSearchParams({v:"1",s:t,t:e.sessionTitle,d:e.sessionDate.slice(0,10),tk:String(e.tokenCount),m:String(e.messageCount)});return typeof e.inputTokens=="number"&&s.set("i",String(e.inputTokens)),typeof e.outputTokens=="number"&&s.set("o",String(e.outputTokens)),e.verdict&&s.set("q",e.verdict),`https://clauderecall.com/card?${s.toString()}`}function lT(e,t){if(t.length>=32)return e.prepare("SELECT id FROM sessions WHERE id = ?").get(t)?.id??null;let s=e.prepare("SELECT session_id FROM session_aliases WHERE alias = ?").get(t);if(s)return s.session_id;let n=e.prepare("SELECT id FROM sessions WHERE id LIKE ? LIMIT 2").all(t+"%");return n.length===1?n[0].id:(n.length===0||process.stderr.write(`ambiguous id prefix "${t}". be more specific.
1636
- `),null)}function dT(e){return e.prepare("SELECT session_id FROM recall_events ORDER BY recalled_at DESC LIMIT 1").get()?.session_id??null}function uT(e,t){let s=e.prepare(`
1638
+ VALUES (?, ?, ?, 'child', ?, 'auto-scan-v1', ?)`).run(p,h,E.parent_id,E.confidence,r)}o.push({thread_id:p,name:m,session_count:c.sessionIds.length})}})(),{project:e.project,threads:o}}async function Od(e){let t=!!e.apply,s=e.confidenceMin?Number(e.confidenceMin):t?Vr:Zr;if(!Number.isFinite(s)||s<0||s>1){console.error(d.err("--confidence-min must be a number in [0, 1]")),process.exitCode=1;return}let n=!!e.llmRescore,r={lo:e.rescoreBandLo?Number(e.rescoreBandLo):Kt.lo,hi:e.rescoreBandHi?Number(e.rescoreBandHi):Kt.hi};if(n&&(!Number.isFinite(r.lo)||!Number.isFinite(r.hi)||r.lo<0||r.hi>1||r.lo>r.hi)){console.error(d.err("--rescore-band-lo/hi must satisfy 0 \u2264 lo \u2264 hi \u2264 1")),process.exitCode=1;return}let o=e.rescoreModel??Vs,i=Ry({project:e.project});if(i.length===0){console.log(d.dim("no sessions matched"));return}let{byProject:a,scannablesByProject:l}=xy(i),c=n?Math.min(s,r.lo):s,u=new Map,p=0;for(let[f]of a){let g=l.get(f)??[],h=fd(g,c);if(n&&h.length>0){let E=await Ny({proposals:h,scannables:g,applyThreshold:s,rescore:{enabled:!0,band:r,model:o}});h=E.proposals,E.capped?(console.error(d.err(`[${f}] borderline pairs exceeded cap (${E.considered}); skipped LLM rescore. Tighten the band or scan a smaller project.`)),h=h.filter(b=>b.confidence>=s)):n?E.failed===E.considered&&E.considered>0&&(h=h.filter(b=>b.confidence>=s)):h=h.filter(b=>b.confidence>=s)}else n&&(h=h.filter(E=>E.confidence>=s));u.set(f,{proposals:h,scannables:g}),p+=h.length}if(t){if(p===0){console.log(d.dim("no edges above threshold; nothing to apply"));return}let f={threads_created:0,edges_written:0,per_project:[]},g=!e.noLlmNames;for(let[h,{proposals:E,scannables:b}]of u){if(E.length===0)continue;let S=await Cy({project:h,rows:a.get(h),edges:E,scannables:b,llmNames:g});f.per_project.push(S),f.threads_created+=S.threads.length,f.edges_written+=E.length+S.threads.length}if(e.json){console.log(JSON.stringify({mode:"apply",threshold:s,...f},null,2));return}console.log(d.ok(`Applied ${f.threads_created} thread${f.threads_created===1?"":"s"} with ${f.edges_written} edges total (threshold ${s}).`));for(let h of f.per_project){console.log(` ${d.bold(h.project)}`);for(let E of h.threads)console.log(` ${d.dim(E.thread_id.slice(0,16)+"\u2026")} ${E.name} ${d.dim(`(${E.session_count} sessions)`)}`)}console.log(),console.log(d.dim("Rollback: sqlite3 ~/.recall/db.sqlite \\")),console.log(d.dim(` "DELETE FROM thread_edges WHERE source='auto-scan-v1';`)),console.log(d.dim(` DELETE FROM threads WHERE id LIKE 'auto-scan-%';"`));return}if(e.json){let f=[];for(let[g,{proposals:h}]of u){let E=new Map(a.get(g).map(b=>[b.id,b]));for(let b of h)f.push({project:g,parent_id:b.parent_id,parent_label:Zs(E.get(b.parent_id)),child_id:b.child_id,child_label:Zs(E.get(b.child_id)),confidence:b.confidence,signals:b.signals,reasons:b.reasons})}console.log(JSON.stringify({mode:"dry-run",threshold:s,total:p,edges:f},null,2));return}console.log(d.dim(`recall thread scan \xB7 ${a.size} project${a.size===1?"":"s"} \xB7 DRY RUN \xB7 threshold ${s}`)),console.log(d.dim(" Algorithm: temporal + continuation phrase + file overlap + same brand.")),console.log();for(let[f,g]of a){let{proposals:h}=u.get(f),E=new Map(g.map(S=>[S.id,S]));if(console.log(d.bold(f)),console.log(d.dim(` ${g.length} eligible session${g.length===1?"":"s"}; ${h.length} parent-child edge${h.length===1?"":"s"} proposed.`)),h.length===0){console.log(d.dim(" (no edges above threshold \u2014 all sessions are origins)")),console.log();continue}let b=[...h].sort((S,C)=>{let R=E.get(S.child_id),L=E.get(C.child_id);return(R.started_at??"").localeCompare(L.started_at??"")});for(let S of b){let C=E.get(S.parent_id),R=E.get(S.child_id),L=S.confidence.toFixed(2);console.log(` ${d.dim(Cd(C.started_at).padEnd(16))} ${d.bold("PARENT")} ${Zs(C)}`),console.log(` ${d.dim(Cd(R.started_at).padEnd(16))} ${d.bold(" \u2514\u2500 child")} ${Zs(R)} ${d.dim(`[conf ${L}]`)}`),console.log(` ${" ".repeat(28)}${d.dim(S.reasons.join(" \xB7 "))}`),console.log()}}let m=Array.from(a.entries()).reduce((f,[g,h])=>f+(h.length-(u.get(g)?.proposals.length??0)),0);console.log(`${p} edge${p===1?"":"s"} proposed across ${a.size} project${a.size===1?"":"s"}; ${m} origin session${m===1?"":"s"} (no proposed parent).`),console.log(d.dim(` This is a DRY RUN. To write: rerun with --apply (default threshold ${Vr}).`))}I();j();import{existsSync as Ly,readFileSync as Oy}from"node:fs";function Ay(){let e=`${x}/daemon.port`;if(!Ly(e))return null;try{let t=Oy(e,"utf8").trim();return/^\d+$/.test(t)?t:null}catch{return null}}async function Iy(e){try{return(await _t(`http://127.0.0.1:${e}/api/health`,{signal:AbortSignal.timeout(1e4)})).ok}catch{return!1}}async function vy(e){let t=await _t(`http://127.0.0.1:${e}/api/projects`);if(!t.ok)throw new Error(`failed to list projects: HTTP ${t.status}`);return await t.json()}function My(e,t){let s=t.replace(/\/+$/,""),n=null,r=-1;for(let o of e){if(!o.decoded_path)continue;let i=o.decoded_path.replace(/\/+$/,"");(s===i||s.startsWith(i+"/"))&&i.length>r&&(n=o,r=i.length)}return n}function $y(e,t){let s=e.find(r=>r.name===t);if(s)return s;let n=e.filter(r=>r.name.toLowerCase().includes(t.toLowerCase()));return n.length===1?n[0]:null}function Ad(e){return e.alias||e.auto_title||(e.first_user_message?Y(e.first_user_message,60):"(no title)")}function Dy(e){if(!e)return"?";let t=new Date(e);if(Number.isNaN(t.getTime()))return"?";let s=n=>String(n).padStart(2,"0");return`${t.getFullYear()}-${s(t.getMonth()+1)}-${s(t.getDate())} ${s(t.getHours())}:${s(t.getMinutes())}`}function jy(e,t){let s=t==="preflight"?d.dim(`recall threads sync \xB7 ${e.project.name} \xB7 PREFLIGHT (no writes)`):d.dim(`recall threads sync \xB7 ${e.project.name}`);if(console.log(s),console.log(),e.thread.exists?console.log(` ${d.bold("Thread")} ${e.thread.name} ${d.dim(`(reusing, ${e.thread.existing_session_count} existing session${e.thread.existing_session_count===1?"":"s"})`)}`):console.log(` ${d.bold("Thread")} ${e.thread.name} ${d.ok("(new)")}`),console.log(),e.candidates.length===0){if(console.log(d.dim(" No active sessions in the rolling window.")),e.warnings.length>0)for(let c of e.warnings)console.log(d.warn(` \u26A0 ${c}`));return}let n=new Map;for(let c of e.proposed_edges)n.set(c.child_id,c);let r=new Map;for(let c of e.preserved_manual_edges)r.set(c.session_id,c.parent_session_id);let o=new Set(e.candidates.map(c=>c.session_id)),i=e.proposed_additions.length,a=e.candidates.length-i;console.log(` ${d.bold("Candidates")} ${e.candidates.length} active session${e.candidates.length===1?"":"s"} ${d.dim(`(${i} new \xB7 ${a} keep)`)}`);let l=String(e.candidates.length).length;for(let c=0;c<e.candidates.length;c++){let u=e.candidates[c],m=e.proposed_additions.some(S=>S.session_id===u.session_id)?d.ok("NEW "):d.dim("keep"),f=n.get(u.session_id)??(r.has(u.session_id)&&r.get(u.session_id)!==null,null),g=f&&o.has(f.parent_id)?" \u2514\u2500 ":" ",h=Dy(u.started_at),E=d.dim(`${String(c+1).padStart(l," ")}.`);console.log(` ${E} ${m} ${d.dim(h.padEnd(16))} ${g}${d.dim(u.session_id.slice(0,8))} ${Ad(u)}`);let b=" ".repeat(l+2);if(f&&o.has(f.parent_id)){let S=f.confidence.toFixed(2),C=Ad(e.candidates.find(R=>R.session_id===f.parent_id));console.log(` ${b}${" ".repeat(28)} parent ${d.dim(f.parent_id.slice(0,8))} (${C}) ${d.dim(`[conf ${S}]`)}`),console.log(` ${b}${" ".repeat(28)} ${d.dim(f.reasons.join(" \xB7 "))}`)}if(r.has(u.session_id)){let S=r.get(u.session_id);S&&console.log(` ${b}${" ".repeat(28)} ${d.bold("manual parent preserved")} ${d.dim(S.slice(0,8))}`)}}if(e.preserved_manual_edges.length>0&&(console.log(),console.log(d.dim(` ${e.preserved_manual_edges.length} manual edge${e.preserved_manual_edges.length===1?"":"s"} will be preserved.`))),e.warnings.length>0){console.log();for(let c of e.warnings)console.log(d.warn(` \u26A0 ${c}`))}}function Py(e){console.log(),console.log(d.ok(`Added ${e.added} session${e.added===1?"":"s"}, set ${e.edges_set} parent edge${e.edges_set===1?"":"s"}, preserved ${e.preserved_manual} manual edge${e.preserved_manual===1?"":"s"}.`)),console.log(d.dim(` thread_id: ${e.thread_id}`))}async function Id(e){let t=Ay();if(!t){console.error(d.err("Daemon is not running. Start it with `recall start`, then re-run this command.")),process.exitCode=1;return}if(!await Iy(t)){console.error(d.err(`Daemon on port ${t} is not responding. Try \`recall stop && recall start\`.`)),process.exitCode=1;return}let n;try{n=await vy(t)}catch(c){console.error(d.err(c.message)),process.exitCode=1;return}let r;if(e.project){if(r=$y(n,e.project),!r){console.error(d.err(`No project matching "${e.project}". Run \`recall projects\` to list known projects.`)),process.exitCode=1;return}}else{let c=process.cwd();if(r=My(n,c),!r){console.error(d.err(`Current directory (${c}) does not match any known project. Pass --project <name> or cd into a project root.`)),process.exitCode=1;return}}let o=e.windowHours?Number(e.windowHours):void 0;if(o!==void 0&&(!Number.isFinite(o)||o<=0)){console.error(d.err("--window-hours must be a positive number")),process.exitCode=1;return}let i=e.preflight?"preflight":"apply",a={project_id:r.id,mode:i};o!==void 0&&(a.window_hours=o);let l;try{let c=await tt("POST",`http://127.0.0.1:${t}/api/threads/sync-active`,a);if(!c.ok){let u=await c.text().catch(()=>"");throw new Error(`HTTP ${c.status}: ${u.slice(0,200)}`)}l=await c.json()}catch(c){console.error(d.err(`Sync failed: ${c.message}`)),process.exitCode=1;return}if(e.json){console.log(JSON.stringify({mode:i,...l},null,2));return}jy(l.plan,i),i==="apply"&&l.result?Py(l.result):i==="preflight"&&(console.log(),console.log(d.dim(" This is a PREFLIGHT. To write: re-run without --preflight.")))}T();import{writeFileSync as aT,existsSync as cT,mkdirSync as lT}from"node:fs";import{join as Vd}from"node:path";import{homedir as dT}from"node:os";import{execSync as It}from"node:child_process";import nT from"satori";import rT from"sharp";import{readFileSync as ro}from"node:fs";import{join as cn}from"node:path";var oo=cn(Te(),"dist","share","fonts"),Yd=!1,qd=[];function oT(){return Yd||(qd=[{name:"Inter",data:ro(cn(oo,"Inter-Regular.woff")),weight:400,style:"normal"},{name:"Inter",data:ro(cn(oo,"Inter-Bold.woff")),weight:700,style:"normal"},{name:"JetBrains Mono",data:ro(cn(oo,"JetBrainsMono-Regular.woff")),weight:400,style:"normal"}],Yd=!0),qd}async function iT(e){switch(e){case"A":return await Promise.resolve().then(()=>(Dd(),$d));case"B":return await Promise.resolve().then(()=>(Fd(),Pd));case"C":return await Promise.resolve().then(()=>(Hd(),Bd));case"D":return await Promise.resolve().then(()=>(Jd(),Xd));case"E":return await Promise.resolve().then(()=>(zd(),Gd))}}async function ln(e,t){let n=(await iT(e)).render(t),i=await nT(n,{width:1080,height:e==="E"?1920:1350,fonts:oT()});return await rT(Buffer.from(i)).png({quality:90}).toBuffer()}function Kd(e,t){let s=new URLSearchParams({v:"1",s:t,t:e.sessionTitle,d:e.sessionDate.slice(0,10),tk:String(e.tokenCount),m:String(e.messageCount)});return typeof e.inputTokens=="number"&&s.set("i",String(e.inputTokens)),typeof e.outputTokens=="number"&&s.set("o",String(e.outputTokens)),e.verdict&&s.set("q",e.verdict),`https://clauderecall.com/card?${s.toString()}`}function uT(e,t){if(t.length>=32)return e.prepare("SELECT id FROM sessions WHERE id = ?").get(t)?.id??null;let s=e.prepare("SELECT session_id FROM session_aliases WHERE alias = ?").get(t);if(s)return s.session_id;let n=e.prepare("SELECT id FROM sessions WHERE id LIKE ? LIMIT 2").all(t+"%");return n.length===1?n[0].id:(n.length===0||process.stderr.write(`ambiguous id prefix "${t}". be more specific.
1639
+ `),null)}function pT(e){return e.prepare("SELECT session_id FROM recall_events ORDER BY recalled_at DESC LIMIT 1").get()?.session_id??null}function mT(e,t){let s=e.prepare(`
1637
1640
  SELECT s.id, s.started_at, s.message_count, s.first_user_message, s.auto_title,
1638
1641
  s.total_input_tokens, s.total_output_tokens
1639
1642
  FROM sessions s WHERE s.id = ?
1640
1643
  `).get(t);if(!s)return null;let r=e.prepare("SELECT alias FROM session_aliases WHERE session_id = ?").get(t)?.alias||s.auto_title||s.first_user_message?.slice(0,80)||s.id.slice(0,8),o=e.prepare(`
1641
1644
  SELECT tool_names, raw_json FROM messages
1642
1645
  WHERE session_id = ? AND tool_names IS NOT NULL AND tool_names != ''
1643
- `).all(t),i=o.length,a=new Set;for(let u of o){if(!/Read|Write|Edit/.test(u.tool_names))continue;let p=u.raw_json.match(/"(?:file_path|path)":\s*"([^"]+)"/g);if(p)for(let m of p){let f=m.match(/":\s*"([^"]+)"/);f&&a.add(f[1])}}let l=s.total_input_tokens??0,c=s.total_output_tokens??0;return{sessionTitle:r,sessionDate:s.started_at??new Date().toISOString(),recallDate:new Date().toISOString(),tokenCount:l+c,inputTokens:l,outputTokens:c,messageCount:s.message_count,filesReferenced:a.size,toolCallCount:i,verdict:""}}function pT(e){process.platform==="darwin"?It(`osascript -e 'set the clipboard to (read (POSIX file "${e}") as \xABclass PNGf\xBB)'`):process.platform==="linux"&&It(`xclip -selection clipboard -t image/png -i "${e}"`)}function mT(e){try{process.platform==="darwin"?It(`open "${e}"`):process.platform==="linux"?It(`xdg-open "${e}"`):process.platform==="win32"&&It(`start "" "${e}"`)}catch{}}async function Zd(e,t){let s=_(),n;if(e){if(n=lT(s,e),!n){process.stderr.write(`session not found: ${e}
1644
- `),process.exitCode=1;return}}else if(n=dT(s),!n){process.stderr.write("No recalled sessions yet. Run `recall context <id>` first, then `recall share`.\n"),process.exitCode=1;return}let r=uT(s,n);if(!r){process.stderr.write(`failed to load metadata for session ${n}
1645
- `),process.exitCode=1;return}let o=t.style&&["A","B","C","D"].includes(t.style.toUpperCase())?t.style.toUpperCase():"A";t.verdict&&(r.verdict=t.verdict);let i=await ln(o,r),a=n.slice(0,8),l=t.out??Vd(cT(),"Downloads");iT(l)||aT(l,{recursive:!0});let c=Vd(l,`recall-card-${a}.png`);if(oT(c,i),process.stderr.write(`Card saved to ${c}
1646
- `),t.clipboard&&(pT(c),process.stderr.write(`Copied PNG to clipboard.
1646
+ `).all(t),i=o.length,a=new Set;for(let u of o){if(!/Read|Write|Edit/.test(u.tool_names))continue;let p=u.raw_json.match(/"(?:file_path|path)":\s*"([^"]+)"/g);if(p)for(let m of p){let f=m.match(/":\s*"([^"]+)"/);f&&a.add(f[1])}}let l=s.total_input_tokens??0,c=s.total_output_tokens??0;return{sessionTitle:r,sessionDate:s.started_at??new Date().toISOString(),recallDate:new Date().toISOString(),tokenCount:l+c,inputTokens:l,outputTokens:c,messageCount:s.message_count,filesReferenced:a.size,toolCallCount:i,verdict:""}}function gT(e){process.platform==="darwin"?It(`osascript -e 'set the clipboard to (read (POSIX file "${e}") as \xABclass PNGf\xBB)'`):process.platform==="linux"&&It(`xclip -selection clipboard -t image/png -i "${e}"`)}function fT(e){try{process.platform==="darwin"?It(`open "${e}"`):process.platform==="linux"?It(`xdg-open "${e}"`):process.platform==="win32"&&It(`start "" "${e}"`)}catch{}}async function Zd(e,t){let s=_(),n;if(e){if(n=uT(s,e),!n){process.stderr.write(`session not found: ${e}
1647
+ `),process.exitCode=1;return}}else if(n=pT(s),!n){process.stderr.write("No recalled sessions yet. Run `recall context <id>` first, then `recall share`.\n"),process.exitCode=1;return}let r=mT(s,n);if(!r){process.stderr.write(`failed to load metadata for session ${n}
1648
+ `),process.exitCode=1;return}let o=t.style&&["A","B","C","D"].includes(t.style.toUpperCase())?t.style.toUpperCase():"A";t.verdict&&(r.verdict=t.verdict);let i=await ln(o,r),a=n.slice(0,8),l=t.out??Vd(dT(),"Downloads");cT(l)||lT(l,{recursive:!0});let c=Vd(l,`recall-card-${a}.png`);if(aT(c,i),process.stderr.write(`Card saved to ${c}
1649
+ `),t.clipboard&&(gT(c),process.stderr.write(`Copied PNG to clipboard.
1647
1650
  `)),t.link){let u=Kd(r,o);process.stdout.write(u+`
1648
1651
  `),process.platform==="darwin"&&(It("pbcopy",{input:u}),process.stderr.write(`Link copied to clipboard.
1649
- `))}t.open!==!1&&mT(c)}T();import{createInterface as gT}from"node:readline";import{writeFileSync as fT,existsSync as _T,mkdirSync as hT}from"node:fs";import{join as eu}from"node:path";import{homedir as ET}from"node:os";function Qd(e){return e.recallCount>=15&&e.uniqueSessionsRecalled>=10?"Context Architect":e.nightSessionRatio>.5?"Night Owl":e.sessionCount>30&&e.avgMessageCount<50?"Rapid Shipper":e.sessionCount<15&&e.avgMessageCount>200?"Deep Diver":e.debugTagRatio>.4?"Debugger":"Power User"}var wt=["january","february","march","april","may","june","july","august","september","october","november","december"],bT=["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"];function ST(e){let t=new Date;if(!e){let i=t.getFullYear(),a=t.getMonth();return{start:`${i}-${String(a+1).padStart(2,"0")}-01`,end:a===11?`${i+1}-01-01`:`${i}-${String(a+2).padStart(2,"0")}-01`,label:`${wt[a][0].toUpperCase()}${wt[a].slice(1)} ${i}`}}let s=e.match(/^(\d{4})-(\d{2})$/);if(s){let i=parseInt(s[1],10),a=parseInt(s[2],10)-1;return a<0||a>11?null:{start:`${i}-${String(a+1).padStart(2,"0")}-01`,end:a===11?`${i+1}-01-01`:`${i}-${String(a+2).padStart(2,"0")}-01`,label:`${wt[a][0].toUpperCase()}${wt[a].slice(1)} ${i}`}}let n=wt.indexOf(e.toLowerCase()),r=n===-1?bT.indexOf(e.toLowerCase()):-1,o=n!==-1?n:r;if(o!==-1){let i=t.getFullYear();return{start:`${i}-${String(o+1).padStart(2,"0")}-01`,end:o===11?`${i+1}-01-01`:`${i}-${String(o+2).padStart(2,"0")}-01`,label:`${wt[o][0].toUpperCase()}${wt[o].slice(1)} ${i}`}}return null}function yT(e){if(e.length===0)return"N/A";let t=r=>r===0?"12am":r<12?`${r}am`:r===12?"12pm":`${r-12}pm`,s=Math.min(...e),n=Math.max(...e);return`${t(s)}-${t(n+1>23?0:n+1)}`}async function tu(e,t){let s=ST(e);if(!s){process.stderr.write(`invalid month format: ${e}. Use YYYY-MM, month name, or abbreviation.
1652
+ `))}t.open!==!1&&fT(c)}T();import{createInterface as _T}from"node:readline";import{writeFileSync as hT,existsSync as ET,mkdirSync as bT}from"node:fs";import{join as eu}from"node:path";import{homedir as ST}from"node:os";function Qd(e){return e.recallCount>=15&&e.uniqueSessionsRecalled>=10?"Context Architect":e.nightSessionRatio>.5?"Night Owl":e.sessionCount>30&&e.avgMessageCount<50?"Rapid Shipper":e.sessionCount<15&&e.avgMessageCount>200?"Deep Diver":e.debugTagRatio>.4?"Debugger":"Power User"}var wt=["january","february","march","april","may","june","july","august","september","october","november","december"],yT=["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"];function TT(e){let t=new Date;if(!e){let i=t.getFullYear(),a=t.getMonth();return{start:`${i}-${String(a+1).padStart(2,"0")}-01`,end:a===11?`${i+1}-01-01`:`${i}-${String(a+2).padStart(2,"0")}-01`,label:`${wt[a][0].toUpperCase()}${wt[a].slice(1)} ${i}`}}let s=e.match(/^(\d{4})-(\d{2})$/);if(s){let i=parseInt(s[1],10),a=parseInt(s[2],10)-1;return a<0||a>11?null:{start:`${i}-${String(a+1).padStart(2,"0")}-01`,end:a===11?`${i+1}-01-01`:`${i}-${String(a+2).padStart(2,"0")}-01`,label:`${wt[a][0].toUpperCase()}${wt[a].slice(1)} ${i}`}}let n=wt.indexOf(e.toLowerCase()),r=n===-1?yT.indexOf(e.toLowerCase()):-1,o=n!==-1?n:r;if(o!==-1){let i=t.getFullYear();return{start:`${i}-${String(o+1).padStart(2,"0")}-01`,end:o===11?`${i+1}-01-01`:`${i}-${String(o+2).padStart(2,"0")}-01`,label:`${wt[o][0].toUpperCase()}${wt[o].slice(1)} ${i}`}}return null}function wT(e){if(e.length===0)return"N/A";let t=r=>r===0?"12am":r<12?`${r}am`:r===12?"12pm":`${r-12}pm`,s=Math.min(...e),n=Math.max(...e);return`${t(s)}-${t(n+1>23?0:n+1)}`}async function tu(e,t){let s=TT(e);if(!s){process.stderr.write(`invalid month format: ${e}. Use YYYY-MM, month name, or abbreviation.
1650
1653
  `),process.exitCode=1;return}let n=_(),r=n.prepare("SELECT COUNT(*) AS c FROM recall_events WHERE recalled_at >= ? AND recalled_at < ?").get(s.start,s.end).c,o=n.prepare("SELECT COALESCE(SUM(token_count), 0) AS s FROM recall_events WHERE recalled_at >= ? AND recalled_at < ?").get(s.start,s.end).s,i=n.prepare("SELECT COUNT(*) AS c FROM sessions WHERE indexed_at >= ? AND indexed_at < ?").get(s.start,s.end).c,a=n.prepare(`SELECT session_id, COUNT(*) AS c FROM recall_events
1651
1654
  WHERE recalled_at >= ? AND recalled_at < ?
1652
1655
  GROUP BY session_id ORDER BY c DESC LIMIT 1`).get(s.start,s.end),l="None";if(a){let B=n.prepare("SELECT alias FROM session_aliases WHERE session_id = ?").get(a.session_id),y=n.prepare("SELECT auto_title, first_user_message, id FROM sessions WHERE id = ?").get(a.session_id);l=B?.alias||y?.auto_title||y?.first_user_message?.slice(0,40)||a.session_id.slice(0,8)}let c=n.prepare("SELECT COALESCE(MAX(token_count), 0) AS m FROM recall_events WHERE recalled_at >= ? AND recalled_at < ?").get(s.start,s.end).m,u=n.prepare(`SELECT CAST(strftime('%H', started_at) AS INTEGER) AS h, COUNT(*) AS c
1653
1656
  FROM sessions WHERE started_at >= ? AND started_at < ?
1654
- GROUP BY h ORDER BY c DESC LIMIT 3`).all(s.start,s.end),p=yT(u.map(B=>B.h)),m=n.prepare("SELECT COUNT(DISTINCT session_id) AS c FROM recall_events WHERE recalled_at >= ? AND recalled_at < ?").get(s.start,s.end).c,f=n.prepare(`SELECT COUNT(*) AS cnt, COALESCE(AVG(message_count), 0) AS avg_msgs
1657
+ GROUP BY h ORDER BY c DESC LIMIT 3`).all(s.start,s.end),p=wT(u.map(B=>B.h)),m=n.prepare("SELECT COUNT(DISTINCT session_id) AS c FROM recall_events WHERE recalled_at >= ? AND recalled_at < ?").get(s.start,s.end).c,f=n.prepare(`SELECT COUNT(*) AS cnt, COALESCE(AVG(message_count), 0) AS avg_msgs
1655
1658
  FROM sessions WHERE started_at >= ? AND started_at < ?`).get(s.start,s.end),g=n.prepare(`SELECT COUNT(*) AS c FROM sessions
1656
1659
  WHERE started_at >= ? AND started_at < ?
1657
1660
  AND (CAST(strftime('%H', started_at) AS INTEGER) >= 22
1658
1661
  OR CAST(strftime('%H', started_at) AS INTEGER) < 4)`).get(s.start,s.end).c,h=n.prepare(`SELECT COUNT(DISTINCT st.session_id) AS c
1659
1662
  FROM session_tags st JOIN sessions s ON s.id = st.session_id
1660
1663
  WHERE s.started_at >= ? AND s.started_at < ?
1661
- AND (st.tag LIKE '%debug%' OR st.tag LIKE '%fix%' OR st.tag LIKE '%bug%' OR st.tag LIKE '%error%')`).get(s.start,s.end).c,E={recallCount:r,uniqueSessionsRecalled:m,sessionCount:f.cnt,avgMessageCount:f.avg_msgs,nightSessionRatio:f.cnt>0?g/f.cnt:0,debugTagRatio:f.cnt>0?h/f.cnt:0},b=Qd(E),S=50;try{let{computeAllHealthScores:B}=await Promise.resolve().then(()=>(Hr(),Tl)),y=B();y.length>0&&(S=Math.round(y.reduce((U,M)=>U+M.score,0)/y.length))}catch{}let C=t.verdict??"";if(!t.verdict){let B=gT({input:process.stdin,output:process.stderr});C=await new Promise(y=>{B.question("Add your take (one line, or press Enter to skip): ",U=>{B.close(),y(U.trim())})})}let R={month:s.label,totalRecalls:r,totalTokensPiped:o,sessionsIndexed:i,mostRecalledSession:l,biggestRecallTokens:c,healthScore:S,mostActiveHours:p,archetype:b,verdict:C},L=await ln("E",R),Q=s.start.slice(0,7),v=t.out??eu(ET(),"Downloads");_T(v)||hT(v,{recursive:!0});let ee=eu(v,`recall-wrapped-${Q}.png`);fT(ee,L),process.stderr.write(`Wrapped card saved to ${ee}
1662
- `)}_e();Pt();import{createRequire as TT}from"node:module";import{createInterface as wT}from"node:readline";import{stdin as xT,stdout as RT}from"node:process";var kT=TT(import.meta.url),NT=kT(`${Te()}/package.json`).version,ru="https://clauderecall.com/api/feedback",io=process.env.RECALL_FEEDBACK_API??ru,su=io===ru,ao=2e3;function ou(e){let t=wT({input:xT,output:RT});return new Promise(s=>t.question(e,n=>{t.close(),s(n.trim())}))}function nu(e){if(!/^[+-]?\d+$/.test(e))return null;let t=Number.parseInt(e,10);return!Number.isFinite(t)||t<1||t>5?null:t}async function CT(e){if(e.score!==void 0){let n=nu(e.score);return n===null?(console.error(`--score must be an integer from 1 to 5 (got "${e.score}").`),null):n}if(!process.stdin.isTTY)return console.error("feedback needs a TTY to prompt. Pass --score 1..5 (and optionally --message) to send non-interactively."),null;console.log("How is Claude Recall going for you?"),console.log(" 1 = bad 2 = meh 3 = ok 4 = good 5 = great"),console.log("");let t=await ou("Score (1-5, q to quit): ");if(t.toLowerCase()==="q"||t==="")return console.log("No worries, skipped."),null;let s=nu(t);return s===null?(console.error("Please enter an integer 1 through 5."),null):s}async function LT(e,t){if(e.message!==void 0)return e.message.trim();if(!process.stdin.isTTY)return"";let s=t<=2?"What is the biggest pain point? (Enter to skip): ":"Anything you would add? (Enter to skip): ";return await ou(s)}function OT(e){return e.length<=ao?{value:e,truncated:!1}:{value:e.slice(0,ao),truncated:!0}}async function iu(e={}){su||process.stderr.write(`[recall] RECALL_FEEDBACK_API override active (${io}); license token will NOT be sent.
1663
- `);let t=await CT(e);if(t===null)return e.score!==void 0||!process.stdin.isTTY?1:0;let s=await LT(e,t),{value:n,truncated:r}=OT(s);r&&process.stderr.write(`[recall] --message truncated to ${ao} characters before send.
1664
- `);let o=await ye(),i=jt(),a=su&&o.tier==="pro"&&i?i.license_jwt:null,l={score:t,comment:n.length>0?n:null,surface:"cli",version:NT,os:process.platform,trigger_kind:"manual",license_jwt:a};try{let c=await fetch(io,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(c.ok)return console.log(""),console.log("Thanks. Your feedback landed."),0;let u=await c.json().catch(()=>({}));return c.status===429?(console.log("You submitted feedback recently. Try again later."),0):(console.error(`Feedback failed: ${c.status} ${u.error??"unknown"}`),1)}catch(c){let u=c instanceof Error?c.message:"network error";return console.error(`Feedback could not be sent: ${u}`),1}}var ww=yw(import.meta.url),bo=ww("../package.json").version,k=new Tw;k.name("recall").description("Searchable memory for every Claude Code session you have ever run. Local, fast, offline. Run `recall` (no args) for the dashboard, or `recall --help` for the full command list.").version(bo);k.command("index").description("Scan your Claude sessions and build the searchable database. Run this once after install.").option("-f, --force","reindex all files even if unchanged").option("-v, --verbose","show each file as it is processed").action(async e=>{await Yo(e)});k.command("list").description("List your sessions, newest first.").option("-p, --project <name>","filter by project name").option("-n, --limit <n>","max rows to show","30").option("-a, --all","include short sessions (2 messages or fewer)").action(e=>{qo(e)});k.command("show <id>").description("Print a full session transcript. Accepts the full id or an 8-char prefix.").option("-r, --raw","print raw JSONL lines instead of formatted output").option("-n, --limit <n>","max messages to show").option("--no-pager","do not auto-pipe long output through less").action((e,t)=>{ti(e,t)});k.command("search <query...>").description("Search every message in every session.").option("-p, --project <name>","restrict results to one project").option("-n, --limit <n>","max results","20").action(async(e,t)=>{await gi(e.join(" "),t)});k.command("projects").description("List every project with how many sessions are in each.").action(()=>{Ei()});k.command("status").description("Show database size, session counts, and whether the daemon is running.").action(()=>{hi()});k.command("start").description("Start the background daemon. Required for live tab-name tracking and the web UI.").action(async()=>{await Es()});k.command("stop").description("Stop the background daemon.").action(async()=>{await Si()});k.command("open").description("Open the local web UI in your browser. Starts the daemon if it is not already running.").action(async()=>{await yi()});k.command("tui").description("Browse and search sessions in an interactive terminal UI. No browser needed.").action(async()=>{let{runTui:e}=await Promise.resolve().then(()=>(Fu(),Pu));await e()});k.command("context <id>").description("Pipe a past session into a fresh Claude chat. Prints condensed markdown to stdout.").option("-f, --full","include full tool call and result bodies (much longer)").option("--since <when>","only messages at or after this time (2h, 30m, 1d, YYYY-MM-DD, or ISO)").option("--subagents","also include subagent / sidechain messages").option("--prelude <text>",'prepend a custom header (e.g. "Continue this conversation")').action(async(e,t)=>{await Xi(e,t)});k.command("mcp").description("Expose Recall as an MCP server over stdio. Add this to your Claude Desktop / Claude Code MCP config to let Claude search your sessions.").option("--allow-writes","enable write tools (add_tag, set_alias, append_note, \u2026). Off by default; rate-limited and audited when on.").action(async e=>{await Ji({allowWrites:!!e.allowWrites})});k.command("paste").description("Save clipboard content (or stdin) into Recall. Opt-in. Secrets are blocked by default; pass --force to override.").option("-l, --list","list archived pastes").option("--purge <id>","permanently delete one paste by id or 8-char prefix").option("-f, --force","skip the secret-scan confirmation prompt").option("--pipe","echo the content to stdout after archiving (for shell pipelines)").option("--dry-run","preview what would be archived without writing").option("--label <text>","short description shown in `recall paste --list`").action(async e=>{await Gi(e)});k.command("audit-secrets").description("Scan the database for secrets that slipped through. Read-only by default; pass --redact to scrub in place.").option("--redact","rewrite offending rows in place (your source files are never touched)").option("-v, --verbose","print every session and message containing a hit").action(async e=>{await zi(e)});k.command("titles [action]").description('Audit session titles in the current project. Defaults to "audit".').option("-p, --project <name>","project to audit (defaults to current cwd)").option("--json","machine-readable JSON output").option("--dry-run","classify but do not write the title_quality column").action(async(e,t)=>{if((e??"audit").toLowerCase()==="audit"){await qi(t);return}console.error(`Unknown titles action: ${e}. Supported: audit`),process.exitCode=1});k.command("import-vscode-state").description("Backfill missing tab names by reading VS Code, Cursor, and Windsurf workspace state. Dry-run by default; pass --apply to write.").option("-p, --project <name>","scope to a single project").option("--apply","write the proposed names (default: dry-run)").option("--min-score <n>","minimum match score from 0 to 1 (default 0.7)","0.7").option("--limit <n>","cap the number of proposals returned").option("--source <list>","which editors to scan: vscode | cursor | windsurf | all (default all)","all").option("--json","machine-readable JSON output").action(async e=>{await sa(e)});k.command("semantic [action] [subAction]").description('Manage semantic search. Defaults to "status". Actions: on, off, status, backfill, pause, resume, install, uninstall, reindex, auto-extract <on|off>.').option("-n, --limit <n>","max sessions to process during backfill","1000").option("-f, --force","regenerate summaries even when one already exists").option("--rate <perMin>","sessions per minute when enabling").option("--model <name>","claude model id (e.g. claude-haiku-4-5-20251001)").action(async(e,t,s)=>{await Aa(e,{...s,_autoExtractAction:t})});k.command("embeddings [action]").description('Audit embedding coverage and backfill missing ones. Defaults to "audit". Actions: audit, backfill-summaries, backfill-messages.').option("-p, --project <name>","scope to a single project").option("-n, --limit <n>","max sessions to process during backfill").option("--json","emit JSON instead of formatted output").action(async(e,t)=>{await $a(e,t)});var ns=k.command("infer").description("Discover links between sessions. Subcommands: outputs | citations | l1 | links | bug-patterns.");function Hu(e){return e.description("Extract code, file, and error references from sessions in one project. Uses the local claude CLI.").requiredOption("-p, --project <name>","project name (required)").option("-n, --limit <n>","max sessions to process","200").option("-f, --force","re-extract even if already done").option("--model <name>","override the default Haiku model id").option("-y, --yes","skip the >50-session cost confirmation (for scripts)").option("--json","emit JSON summary instead of formatted output").action(async t=>{await Wa(t)})}function Wu(e){return e.description("Find sessions that cite the same files or errors. Lands proposals for review.").requiredOption("-p, --project <name>","project name (required)").option("--json","emit JSON summary instead of formatted output").action(async t=>{await Qa(t)})}function Xu(e){return e.description("Fast deterministic link inference across sessions. No LLM cost.").option("-p, --project <name>","restrict to one project (default: all)").option("--json","emit JSON summary instead of formatted output").action(async t=>{await sc(t)})}function Ju(e){return e.description("LLM-powered link classification. Pre-filters by confidence, batches the survivors through your local claude CLI (Haiku).").requiredOption("-p, --project <name>","project name (required)").option("--min-conf <n>","pre-filter threshold (default 0.4)","0.4").option("-n, --limit <n>","max candidate pairs to classify (default 1000)","1000").option("--auto-promote","promote high-confidence pairs straight into session_links").option("--auto-promote-threshold <n>","promotion threshold (default 0.95)").option("--model <name>","override the default Haiku model id").option("--json","emit JSON summary instead of formatted output").action(async t=>{await lc(t)})}function Gu(e){return e.description("Cluster sessions that hit the same bug. Idempotent.").option("-p, --project <name>","restrict to one project (default: all)").option("--min-cluster-size <n>","skip clusters smaller than this (default 3)","3").option("--semantic","add an embedding-distance pass to catch near-duplicate snippets").option("-n, --limit <n>","cap clusters in the output (default 100)","100").option("--json","emit JSON summary instead of formatted output").action(async t=>{await Sc(t)})}Hu(ns.command("outputs"));Wu(ns.command("citations"));Xu(ns.command("l1"));Ju(ns.command("links"));Gu(ns.command("bug-patterns"));Hu(k.command("extract-outputs"));Wu(k.command("infer-citations"));Xu(k.command("infer-l1"));Ju(k.command("infer-links"));Gu(k.command("infer-bug-patterns"));k.command("neighborhood <id>").description("Bundle a session with its parents, children, citations, and similar sessions. Pipe into `claude` to seed a fresh chat with rich context.").option("-b, --budget <n>","token budget for the bundle (default 4000)","4000").option("--scoring <mode>","pagerank | embedding-rerank | hybrid (default hybrid)","hybrid").option("-e, --edge-types <list>","comma-separated link types to include: citation,similar,skill_track,bug_pattern,wiki_link,temporal_proximity (default all)").option("--max-depth <n>","how far to walk the link graph (default 2)","2").option("--no-wiki-links","exclude manual wiki links").option("--include-suggestions","include pending suggestions (debug only)").option("--json","emit the full result as JSON instead of markdown").action(async(e,t)=>{await Ic(e,t)});k.command("similar <session-id>").description("Find sessions about the same topic as this one. Pro feature.").option("-n, --limit <n>","max results","10").action(async(e,t)=>{let{requireProOrExit:s}=await Promise.resolve().then(()=>(_e(),gs));await s("Similar sessions");let{isModelInstalled:n}=await Promise.resolve().then(()=>(Cs(),wa)),{loadEmbedder:r,getEmbedderStatus:o}=await Promise.resolve().then(()=>(Ve(),ir)),{findSimilarSessions:i}=await Promise.resolve().then(()=>(Bu(),Uu));if(!n()){console.error("Model not installed. Run `recall semantic install` first."),process.exitCode=1;return}o().loaded||await r();let a=Math.max(1,Math.min(50,Number(t.limit??10))),l=await i(e,a);if(l.length===0){console.log("No similar sessions found.");return}for(let c of l)console.log(` ${c.sessionId} similarity=${c.similarity.toFixed(3)}`)});k.command("stats [id]").description("How much you have spent and how many tokens you have used. No args = overview. Pass a session id for one session, or --project for one project.").option("-p, --project <name>","show stats for a single project").option("-d, --days <n>","restrict the overview to the last N days (7 or 30)").option("--backfill","compute usage for already-indexed messages (safe to rerun)").option("-n, --limit <n>","max messages to scan during backfill").option("--json","emit JSON instead of a formatted table").action(async(e,t)=>{await Fc(e,t)});k.command("correlate [id]").description("Link sessions to the git commits they wrote. Read-only. No args = batch mode; pass an id to correlate one.").option("-n, --limit <n>","max sessions to process in batch mode").option("--json","emit JSON instead of formatted output").action(async(e,t)=>{await Wc(e,t)});var So=k.command("correlator").description("Diagnose and fix terminal-to-session matching. Subcommands: audit | debug | restore.");function zu(e){return e.description("Show how the daemon is matching open terminals to sessions right now.").option("--json","emit JSON instead of formatted output").action(async t=>{await ul(t)})}function Yu(e){return e.description("Restore aliases that `correlator audit --fix` cleared, when they still cleanly match an open terminal. Dry-run by default.").option("--apply","apply the restoration (otherwise dry-run only)").option("--json","emit JSON instead of formatted output").action(async t=>{await pl(t)})}function qu(e){return e.description("Find sessions with bad terminal-name aliases from the legacy race-window bug. Use --fix to clear suspects.").option("--fix","clear suspect aliases (otherwise dry-run only)").option("-w, --window <seconds>","collision window in seconds (default 60, clamped 5..600)").option("-p, --project <name>","limit detection and --fix to a single project").option("--json","emit JSON instead of formatted output").action(async t=>{await Kc(t)})}zu(So.command("debug"));Yu(So.command("restore"));qu(So.command("audit"));zu(k.command("correlator-debug"));Yu(k.command("correlator-restore"));k.command("name <id-prefix> <name>").description("Rename a session. By default it stays linked to its terminal tab, so renaming the tab later still updates the name. Use --pin to lock the name permanently. Daemon must be running.").option("--json","emit JSON").option("--pin","lock the name; later tab renames will NOT overwrite it").action(async(e,t,s)=>{await al(e,t,s)});k.command("doctor").description("Diagnose database health: size, WAL, FTS fragmentation, integrity, alias invariant. Exits non-zero on issues.").option("--json","emit JSON instead of formatted output").action(async e=>{let t=await ol(e);process.exit(t)});k.command("optimize").description("Run maintenance: WAL checkpoint, FTS5 merge, planner stats. Use --vacuum to also reclaim free pages (requires daemon stopped).").option("--vacuum","also run VACUUM to reclaim free pages (rewrites the whole DB; daemon must be stopped)").option("--json","emit JSON instead of formatted output").action(async e=>{let t=await il(e);process.exit(t)});qu(k.command("correlator-audit"));k.command("blame <sha>").description("Look up which session(s) wrote the code in a commit. Reverse of `correlate`.").option("--json","emit JSON instead of formatted output").action(async(e,t)=>{await ml(e,t)});k.command("digest").description("Today's rediscovery picks: a session worth revisiting, the costliest of the week, and the one behind your latest commit.").option("--json","emit JSON instead of formatted output").action(async e=>{await _l(e)});k.command("install-extension").description("Install the bundled VS Code / Cursor / Windsurf extension into your editor. Auto-detects which CLIs are installed.").option("--editor <name>","install only into one editor: code | cursor | code-insiders | windsurf").option("--print-path","print the path to the bundled .vsix and exit").action(async e=>{await yl(e)});k.command("health [project]").description("Score how well-organized each project's sessions are. Worst first, or pass a project name for a single breakdown.").option("--json","emit JSON instead of formatted output").action((e,t)=>{xl(e,t)});k.command("verify [action]").description('Toggle verification badges in the UI. Defaults to "status". Actions: on, off, status.').action(e=>{Rl(e)});k.command("activate <license-key>").description("Activate your Pro license. Run once after purchase.").action(async e=>{await Dl(e)});k.command("upgrade").description("Open the Pro pricing page in your browser.").action(async()=>{await jl()});k.command("trial").description("Start a 7-day Pro trial. Opens the signup page in your browser. No card required.").action(async()=>{await Fl()});var gn=k.command("telemetry").description('Manage the opt-in anonymous install ping. Defaults to "view".');gn.command("view",{isDefault:!0}).description("Show current decision, state file path, and next-ping payload.").action(async()=>{await zl()});gn.command("on").description("Opt in. One anonymous ping per machine per month. See https://clauderecall.com/telemetry").action(async()=>{await Jl()});gn.command("off").description("Opt out. Deletes the nonce. No further pings.").action(async()=>{await Gl()});gn.command("status").description("Alias for view.").action(async()=>{await Yr()});var yo=k.command("license").description('Show or remove the Pro license on this machine. Defaults to "status".');yo.command("status",{isDefault:!0}).description("Show the current license tier.").action(async()=>{await Kl()});yo.command("deactivate").description("Remove the stored license from this machine. Reverses `recall activate`.").action(()=>{Zl()});yo.command("check").description("Force a revocation check against the license server. The daemon also runs this on a 24-hour timer in the background.").action(async()=>{await Vl()});var xw=k.command("thread").description("Group related sessions into threads, then list, show, link, merge, or scan them."),Rw=k.command("threads").description("Alias for `thread`. Both forms accept the same subcommands.");function Ku(e){e.command("sync").description("Capture sessions running in this repo right now into a thread.").option("--preflight","preview the plan without writing").option("-p, --project <name>","override the cwd-based project").option("--window-hours <n>","rolling activity window (default 6)").option("--json","machine-readable JSON output").action(async t=>{await Id(t)}),e.command("scan").description("Auto-detect parent-child links across past sessions. Dry-run by default; pass --apply to write.").option("-p, --project <name>","scope to a single project").option("--json","emit JSON instead of formatted output").option("--apply","write edges (default: dry-run preview)").option("--confidence-min <n>","override threshold (dry-run 0.5, apply 0.7)").option("--no-llm-names","skip LLM naming (free, offline)").option("--llm-rescore","LLM re-score borderline pairs (small Haiku call each)").option("--rescore-band-lo <n>","low end of the borderline band (default 0.4)").option("--rescore-band-hi <n>","high end of the borderline band (default 0.7)").option("--rescore-model <id>","model id for the rescore call (default Haiku 4.5)").action(t=>{Od(t)}),e.command("list").description("List threads, newest first.").option("--archived","include archived threads").option("--json","emit JSON instead of a table").action(t=>{ed(t)}),e.command("show <id-prefix>").description("Show a thread's header and session tree.").option("--json","emit JSON instead of formatted output").action((t,s)=>{td(t,s)}),e.command("new <name>").description("Create a new thread.").option("--origin <session-id>","seed with an origin session").option("--summary <text>","optional short summary").option("--json","emit JSON").action((t,s)=>{sd(t,s)}),e.command("link <session-id>").description("Link a session into a thread.").requiredOption("--thread <id-prefix>","thread id or prefix").option("--parent <session-id>","parent session within the thread").option("--role <role>","origin | child (default inferred from --parent)").option("--json","emit JSON").action((t,s)=>{nd(t,s)}),e.command("unlink <session-id>").description("Remove a session from a thread.").requiredOption("--thread <id-prefix>","thread id or prefix").option("--json","emit JSON").action((t,s)=>{rd(t,s)}),e.command("set-parent <session-id>").description("Change a session's parent within a thread. Use --parent none to promote to origin.").requiredOption("--thread <id-prefix>","thread id or prefix").option("--parent <session-id|none>",'new parent, or "none" to promote to origin').option("--json","emit JSON").action((t,s)=>{od(t,s)}),e.command("rename <id-prefix> <new-name>").description("Rename a thread.").option("--json","emit JSON").action((t,s,n)=>{id(t,s,n)}),e.command("close <id-prefix>").description("Mark a thread as closed (work complete).").option("--json","emit JSON").action((t,s)=>{ad(t,s)}),e.command("reopen <id-prefix>").description("Reopen a closed thread.").option("--json","emit JSON").action((t,s)=>{cd(t,s)}),e.command("archive <id-prefix>").description("Archive a thread (hidden from the default list).").option("--json","emit JSON").action((t,s)=>{ld(t,s)}),e.command("merge <source-id-prefix>").description("Merge one thread into another.").requiredOption("--into <id-prefix>","destination thread").option("--json","emit JSON").action((t,s)=>{dd(t,s)}),e.command("split <id-prefix>").description("Split sessions out of a thread into a new thread.").requiredOption("--sessions <s1,s2,...>","comma-separated session ids or prefixes").requiredOption("--name <new-name>","name for the new thread").option("--json","emit JSON").action((t,s)=>{ud(t,s)})}Ku(xw);Ku(Rw);k.command("share [id]").description("Save a session as a shareable PNG card. No args = your last recalled session. Saved to ~/Downloads and opened.").option("--style <A|B|C|D>","card style (default A: Minimal)").option("--verdict <quote>","your one-line take on the session").option("--link","also generate a shareable URL and copy it to the clipboard").option("--clipboard","also copy the PNG to the system clipboard").option("--out <path>","override the save directory").option("--no-open","do not auto-open the saved PNG").action(async(e,t)=>{await Zd(e,t)});k.command("feedback").description("Send a 1-5 rating and optional comment to the team. Interactive by default; pass --score (and optionally --message) to skip prompts.").option("--score <1-5>","rating from 1 (bad) to 5 (great)").option("--message <text>","optional comment to send with the rating").action(async e=>{let t=await iu(e);t!==0&&(process.exitCode=t)});k.command("wrapped [month]").description("Save your monthly recap as a shareable PNG card. Defaults to the current month. Accepts YYYY-MM, full name, or abbreviation.").option("--verdict <quote>","your one-line take on the month").option("--out <path>","override the save directory").action(async(e,t)=>{await tu(e,t)});process.env.CLAUDECODE&&process.stderr.write(`<claude-code-hint v="1" type="plugin" value="claude-recall@claude-plugins-official" />
1664
+ AND (st.tag LIKE '%debug%' OR st.tag LIKE '%fix%' OR st.tag LIKE '%bug%' OR st.tag LIKE '%error%')`).get(s.start,s.end).c,E={recallCount:r,uniqueSessionsRecalled:m,sessionCount:f.cnt,avgMessageCount:f.avg_msgs,nightSessionRatio:f.cnt>0?g/f.cnt:0,debugTagRatio:f.cnt>0?h/f.cnt:0},b=Qd(E),S=50;try{let{computeAllHealthScores:B}=await Promise.resolve().then(()=>(Hr(),Tl)),y=B();y.length>0&&(S=Math.round(y.reduce((U,M)=>U+M.score,0)/y.length))}catch{}let C=t.verdict??"";if(!t.verdict){let B=_T({input:process.stdin,output:process.stderr});C=await new Promise(y=>{B.question("Add your take (one line, or press Enter to skip): ",U=>{B.close(),y(U.trim())})})}let R={month:s.label,totalRecalls:r,totalTokensPiped:o,sessionsIndexed:i,mostRecalledSession:l,biggestRecallTokens:c,healthScore:S,mostActiveHours:p,archetype:b,verdict:C},L=await ln("E",R),Q=s.start.slice(0,7),v=t.out??eu(ST(),"Downloads");ET(v)||bT(v,{recursive:!0});let ee=eu(v,`recall-wrapped-${Q}.png`);hT(ee,L),process.stderr.write(`Wrapped card saved to ${ee}
1665
+ `)}_e();Pt();import{createRequire as xT}from"node:module";import{createInterface as RT}from"node:readline";import{stdin as kT,stdout as NT}from"node:process";var CT=xT(import.meta.url),LT=CT(`${Te()}/package.json`).version,ru="https://clauderecall.com/api/feedback",io=process.env.RECALL_FEEDBACK_API??ru,su=io===ru,ao=2e3;function ou(e){let t=RT({input:kT,output:NT});return new Promise(s=>t.question(e,n=>{t.close(),s(n.trim())}))}function nu(e){if(!/^[+-]?\d+$/.test(e))return null;let t=Number.parseInt(e,10);return!Number.isFinite(t)||t<1||t>5?null:t}async function OT(e){if(e.score!==void 0){let n=nu(e.score);return n===null?(console.error(`--score must be an integer from 1 to 5 (got "${e.score}").`),null):n}if(!process.stdin.isTTY)return console.error("feedback needs a TTY to prompt. Pass --score 1..5 (and optionally --message) to send non-interactively."),null;console.log("How is Claude Recall going for you?"),console.log(" 1 = bad 2 = meh 3 = ok 4 = good 5 = great"),console.log("");let t=await ou("Score (1-5, q to quit): ");if(t.toLowerCase()==="q"||t==="")return console.log("No worries, skipped."),null;let s=nu(t);return s===null?(console.error("Please enter an integer 1 through 5."),null):s}async function AT(e,t){if(e.message!==void 0)return e.message.trim();if(!process.stdin.isTTY)return"";let s=t<=2?"What is the biggest pain point? (Enter to skip): ":"Anything you would add? (Enter to skip): ";return await ou(s)}function IT(e){return e.length<=ao?{value:e,truncated:!1}:{value:e.slice(0,ao),truncated:!0}}async function iu(e={}){su||process.stderr.write(`[recall] RECALL_FEEDBACK_API override active (${io}); license token will NOT be sent.
1666
+ `);let t=await OT(e);if(t===null)return e.score!==void 0||!process.stdin.isTTY?1:0;let s=await AT(e,t),{value:n,truncated:r}=IT(s);r&&process.stderr.write(`[recall] --message truncated to ${ao} characters before send.
1667
+ `);let o=await ye(),i=jt(),a=su&&o.tier==="pro"&&i?i.license_jwt:null,l={score:t,comment:n.length>0?n:null,surface:"cli",version:LT,os:process.platform,trigger_kind:"manual",license_jwt:a};try{let c=await fetch(io,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)});if(c.ok)return console.log(""),console.log("Thanks. Your feedback landed."),0;let u=await c.json().catch(()=>({}));return c.status===429?(console.log("You submitted feedback recently. Try again later."),0):(console.error(`Feedback failed: ${c.status} ${u.error??"unknown"}`),1)}catch(c){let u=c instanceof Error?c.message:"network error";return console.error(`Feedback could not be sent: ${u}`),1}}var Rw=ww(import.meta.url),bo=Rw("../package.json").version,k=new xw;k.name("recall").description("Searchable memory for every Claude Code session you have ever run. Local, fast, offline. Run `recall` (no args) for the dashboard, or `recall --help` for the full command list.").version(bo);k.command("index").description("Scan your Claude sessions and build the searchable database. Run this once after install.").option("-f, --force","reindex all files even if unchanged").option("-v, --verbose","show each file as it is processed").action(async e=>{await Yo(e)});k.command("list").description("List your sessions, newest first.").option("-p, --project <name>","filter by project name").option("-n, --limit <n>","max rows to show","30").option("-a, --all","include short sessions (2 messages or fewer)").action(e=>{qo(e)});k.command("show <id>").description("Print a full session transcript. Accepts the full id or an 8-char prefix.").option("-r, --raw","print raw JSONL lines instead of formatted output").option("-n, --limit <n>","max messages to show").option("--no-pager","do not auto-pipe long output through less").action((e,t)=>{ti(e,t)});k.command("search <query...>").description("Search every message in every session.").option("-p, --project <name>","restrict results to one project").option("-n, --limit <n>","max results","20").action(async(e,t)=>{await gi(e.join(" "),t)});k.command("projects").description("List every project with how many sessions are in each.").action(()=>{Ei()});k.command("status").description("Show database size, session counts, and whether the daemon is running.").action(()=>{hi()});k.command("start").description("Start the background daemon. Required for live tab-name tracking and the web UI.").action(async()=>{await Es()});k.command("stop").description("Stop the background daemon.").action(async()=>{await Si()});k.command("open").description("Open the local web UI in your browser. Starts the daemon if it is not already running.").action(async()=>{await yi()});k.command("tui").description("Browse and search sessions in an interactive terminal UI. No browser needed.").action(async()=>{let{runTui:e}=await Promise.resolve().then(()=>(Fu(),Pu));await e()});k.command("context <id>").description("Pipe a past session into a fresh Claude chat. Prints condensed markdown to stdout.").option("-f, --full","include full tool call and result bodies (much longer)").option("--since <when>","only messages at or after this time (2h, 30m, 1d, YYYY-MM-DD, or ISO)").option("--subagents","also include subagent / sidechain messages").option("--prelude <text>",'prepend a custom header (e.g. "Continue this conversation")').action(async(e,t)=>{await Xi(e,t)});k.command("mcp").description("Expose Recall as an MCP server over stdio. Add this to your Claude Desktop / Claude Code MCP config to let Claude search your sessions.").option("--allow-writes","enable write tools (add_tag, set_alias, append_note, \u2026). Off by default; rate-limited and audited when on.").action(async e=>{await Ji({allowWrites:!!e.allowWrites})});k.command("paste").description("Save clipboard content (or stdin) into Recall. Opt-in. Secrets are blocked by default; pass --force to override.").option("-l, --list","list archived pastes").option("--purge <id>","permanently delete one paste by id or 8-char prefix").option("-f, --force","skip the secret-scan confirmation prompt").option("--pipe","echo the content to stdout after archiving (for shell pipelines)").option("--dry-run","preview what would be archived without writing").option("--label <text>","short description shown in `recall paste --list`").action(async e=>{await Gi(e)});k.command("audit-secrets").description("Scan the database for secrets that slipped through. Read-only by default; pass --redact to scrub in place.").option("--redact","rewrite offending rows in place (your source files are never touched)").option("-v, --verbose","print every session and message containing a hit").action(async e=>{await zi(e)});k.command("titles [action]").description('Audit session titles in the current project. Defaults to "audit".').option("-p, --project <name>","project to audit (defaults to current cwd)").option("--json","machine-readable JSON output").option("--dry-run","classify but do not write the title_quality column").action(async(e,t)=>{if((e??"audit").toLowerCase()==="audit"){await qi(t);return}console.error(`Unknown titles action: ${e}. Supported: audit`),process.exitCode=1});k.command("import-vscode-state").description("Backfill missing tab names by reading VS Code, Cursor, and Windsurf workspace state. Dry-run by default; pass --apply to write.").option("-p, --project <name>","scope to a single project").option("--apply","write the proposed names (default: dry-run)").option("--min-score <n>","minimum match score from 0 to 1 (default 0.7)","0.7").option("--limit <n>","cap the number of proposals returned").option("--source <list>","which editors to scan: vscode | cursor | windsurf | all (default all)","all").option("--json","machine-readable JSON output").action(async e=>{await sa(e)});k.command("semantic [action] [subAction]").description('Manage semantic search. Defaults to "status". Actions: on, off, status, backfill, pause, resume, install, uninstall, reindex, auto-extract <on|off>.').option("-n, --limit <n>","max sessions to process during backfill","1000").option("-f, --force","regenerate summaries even when one already exists").option("--rate <perMin>","sessions per minute when enabling").option("--model <name>","claude model id (e.g. claude-haiku-4-5-20251001)").action(async(e,t,s)=>{await Aa(e,{...s,_autoExtractAction:t})});k.command("embeddings [action]").description('Audit embedding coverage and backfill missing ones. Defaults to "audit". Actions: audit, backfill-summaries, backfill-messages.').option("-p, --project <name>","scope to a single project").option("-n, --limit <n>","max sessions to process during backfill").option("--json","emit JSON instead of formatted output").action(async(e,t)=>{await Da(e,t)});var ns=k.command("infer").description("Discover links between sessions. Subcommands: outputs | citations | l1 | links | bug-patterns.");function Hu(e){return e.description("Extract code, file, and error references from sessions in one project. Uses the local claude CLI.").requiredOption("-p, --project <name>","project name (required)").option("-n, --limit <n>","max sessions to process","200").option("-f, --force","re-extract even if already done").option("--model <name>","override the default Haiku model id").option("-y, --yes","skip the >50-session cost confirmation (for scripts)").option("--json","emit JSON summary instead of formatted output").action(async t=>{await Wa(t)})}function Wu(e){return e.description("Find sessions that cite the same files or errors. Lands proposals for review.").requiredOption("-p, --project <name>","project name (required)").option("--json","emit JSON summary instead of formatted output").action(async t=>{await Qa(t)})}function Xu(e){return e.description("Fast deterministic link inference across sessions. No LLM cost.").option("-p, --project <name>","restrict to one project (default: all)").option("--json","emit JSON summary instead of formatted output").action(async t=>{await sc(t)})}function Ju(e){return e.description("LLM-powered link classification. Pre-filters by confidence, batches the survivors through your local claude CLI (Haiku).").requiredOption("-p, --project <name>","project name (required)").option("--min-conf <n>","pre-filter threshold (default 0.4)","0.4").option("-n, --limit <n>","max candidate pairs to classify (default 1000)","1000").option("--auto-promote","promote high-confidence pairs straight into session_links").option("--auto-promote-threshold <n>","promotion threshold (default 0.95)").option("--model <name>","override the default Haiku model id").option("--json","emit JSON summary instead of formatted output").action(async t=>{await lc(t)})}function Gu(e){return e.description("Cluster sessions that hit the same bug. Idempotent.").option("-p, --project <name>","restrict to one project (default: all)").option("--min-cluster-size <n>","skip clusters smaller than this (default 3)","3").option("--semantic","add an embedding-distance pass to catch near-duplicate snippets").option("-n, --limit <n>","cap clusters in the output (default 100)","100").option("--json","emit JSON summary instead of formatted output").action(async t=>{await Sc(t)})}Hu(ns.command("outputs"));Wu(ns.command("citations"));Xu(ns.command("l1"));Ju(ns.command("links"));Gu(ns.command("bug-patterns"));Hu(k.command("extract-outputs"));Wu(k.command("infer-citations"));Xu(k.command("infer-l1"));Ju(k.command("infer-links"));Gu(k.command("infer-bug-patterns"));k.command("neighborhood <id>").description("Bundle a session with its parents, children, citations, and similar sessions. Pipe into `claude` to seed a fresh chat with rich context.").option("-b, --budget <n>","token budget for the bundle (default 4000)","4000").option("--scoring <mode>","pagerank | embedding-rerank | hybrid (default hybrid)","hybrid").option("-e, --edge-types <list>","comma-separated link types to include: citation,similar,skill_track,bug_pattern,wiki_link,temporal_proximity (default all)").option("--max-depth <n>","how far to walk the link graph (default 2)","2").option("--no-wiki-links","exclude manual wiki links").option("--include-suggestions","include pending suggestions (debug only)").option("--json","emit the full result as JSON instead of markdown").action(async(e,t)=>{await Ic(e,t)});k.command("similar <session-id>").description("Find sessions about the same topic as this one. Pro feature.").option("-n, --limit <n>","max results","10").action(async(e,t)=>{let{requireProOrExit:s}=await Promise.resolve().then(()=>(_e(),gs));await s("Similar sessions");let{isModelInstalled:n}=await Promise.resolve().then(()=>(Cs(),wa)),{loadEmbedder:r,getEmbedderStatus:o}=await Promise.resolve().then(()=>(Ve(),ir)),{findSimilarSessions:i}=await Promise.resolve().then(()=>(Bu(),Uu));if(!n()){console.error("Model not installed. Run `recall semantic install` first."),process.exitCode=1;return}o().loaded||await r();let a=Math.max(1,Math.min(50,Number(t.limit??10))),l=await i(e,a);if(l.length===0){console.log("No similar sessions found.");return}for(let c of l)console.log(` ${c.sessionId} similarity=${c.similarity.toFixed(3)}`)});k.command("stats [id]").description("How much you have spent and how many tokens you have used. No args = overview. Pass a session id for one session, or --project for one project.").option("-p, --project <name>","show stats for a single project").option("-d, --days <n>","restrict the overview to the last N days (7 or 30)").option("--backfill","compute usage for already-indexed messages (safe to rerun)").option("-n, --limit <n>","max messages to scan during backfill").option("--json","emit JSON instead of a formatted table").action(async(e,t)=>{await Fc(e,t)});k.command("correlate [id]").description("Link sessions to the git commits they wrote. Read-only. No args = batch mode; pass an id to correlate one.").option("-n, --limit <n>","max sessions to process in batch mode").option("--json","emit JSON instead of formatted output").action(async(e,t)=>{await Wc(e,t)});var So=k.command("correlator").description("Diagnose and fix terminal-to-session matching. Subcommands: audit | debug | restore.");function zu(e){return e.description("Show how the daemon is matching open terminals to sessions right now.").option("--json","emit JSON instead of formatted output").action(async t=>{await ul(t)})}function Yu(e){return e.description("Restore aliases that `correlator audit --fix` cleared, when they still cleanly match an open terminal. Dry-run by default.").option("--apply","apply the restoration (otherwise dry-run only)").option("--json","emit JSON instead of formatted output").action(async t=>{await pl(t)})}function qu(e){return e.description("Find sessions with bad terminal-name aliases from the legacy race-window bug. Use --fix to clear suspects.").option("--fix","clear suspect aliases (otherwise dry-run only)").option("-w, --window <seconds>","collision window in seconds (default 60, clamped 5..600)").option("-p, --project <name>","limit detection and --fix to a single project").option("--json","emit JSON instead of formatted output").action(async t=>{await Kc(t)})}zu(So.command("debug"));Yu(So.command("restore"));qu(So.command("audit"));zu(k.command("correlator-debug"));Yu(k.command("correlator-restore"));k.command("name <id-prefix> <name>").description("Rename a session. By default it stays linked to its terminal tab, so renaming the tab later still updates the name. Use --pin to lock the name permanently. Daemon must be running.").option("--json","emit JSON").option("--pin","lock the name; later tab renames will NOT overwrite it").action(async(e,t,s)=>{await al(e,t,s)});k.command("doctor").description("Diagnose database health: size, WAL, FTS fragmentation, integrity, alias invariant. Exits non-zero on issues.").option("--json","emit JSON instead of formatted output").action(async e=>{let t=await ol(e);process.exit(t)});k.command("optimize").description("Run maintenance: WAL checkpoint, FTS5 merge, planner stats. Use --vacuum to also reclaim free pages (requires daemon stopped).").option("--vacuum","also run VACUUM to reclaim free pages (rewrites the whole DB; daemon must be stopped)").option("--json","emit JSON instead of formatted output").action(async e=>{let t=await il(e);process.exit(t)});qu(k.command("correlator-audit"));k.command("blame <sha>").description("Look up which session(s) wrote the code in a commit. Reverse of `correlate`.").option("--json","emit JSON instead of formatted output").action(async(e,t)=>{await ml(e,t)});k.command("digest").description("Today's rediscovery picks: a session worth revisiting, the costliest of the week, and the one behind your latest commit.").option("--json","emit JSON instead of formatted output").action(async e=>{await _l(e)});k.command("install-extension").description("Install the bundled VS Code / Cursor / Windsurf extension into your editor. Auto-detects which CLIs are installed.").option("--editor <name>","install only into one editor: code | cursor | code-insiders | windsurf").option("--print-path","print the path to the bundled .vsix and exit").action(async e=>{await yl(e)});k.command("health [project]").description("Score how well-organized each project's sessions are. Worst first, or pass a project name for a single breakdown.").option("--json","emit JSON instead of formatted output").action((e,t)=>{xl(e,t)});k.command("verify [action]").description('Toggle verification badges in the UI. Defaults to "status". Actions: on, off, status.').action(e=>{Rl(e)});k.command("activate <license-key>").description("Activate your Pro license. Run once after purchase.").action(async e=>{await $l(e)});k.command("upgrade").description("Open the Pro pricing page in your browser.").action(async()=>{await jl()});k.command("trial").description("Start a 7-day Pro trial. Opens the signup page in your browser. No card required.").action(async()=>{await Fl()});var gn=k.command("telemetry").description('Manage the opt-in anonymous install ping. Defaults to "view".');gn.command("view",{isDefault:!0}).description("Show current decision, state file path, and next-ping payload.").action(async()=>{await zl()});gn.command("on").description("Opt in. One anonymous ping per machine per month. See https://clauderecall.com/telemetry").action(async()=>{await Jl()});gn.command("off").description("Opt out. Deletes the nonce. No further pings.").action(async()=>{await Gl()});gn.command("status").description("Alias for view.").action(async()=>{await Yr()});var yo=k.command("license").description('Show or remove the Pro license on this machine. Defaults to "status".');yo.command("status",{isDefault:!0}).description("Show the current license tier.").action(async()=>{await Kl()});yo.command("deactivate").description("Remove the stored license from this machine. Reverses `recall activate`.").action(()=>{Zl()});yo.command("check").description("Force a revocation check against the license server. The daemon also runs this on a 24-hour timer in the background.").action(async()=>{await Vl()});var kw=k.command("thread").description("Group related sessions into threads, then list, show, link, merge, or scan them."),Nw=k.command("threads").description("Alias for `thread`. Both forms accept the same subcommands.");function Ku(e){e.command("sync").description("Capture sessions running in this repo right now into a thread.").option("--preflight","preview the plan without writing").option("-p, --project <name>","override the cwd-based project").option("--window-hours <n>","rolling activity window (default 6)").option("--json","machine-readable JSON output").action(async t=>{await Id(t)}),e.command("scan").description("Auto-detect parent-child links across past sessions. Dry-run by default; pass --apply to write.").option("-p, --project <name>","scope to a single project").option("--json","emit JSON instead of formatted output").option("--apply","write edges (default: dry-run preview)").option("--confidence-min <n>","override threshold (dry-run 0.5, apply 0.7)").option("--no-llm-names","skip LLM naming (free, offline)").option("--llm-rescore","LLM re-score borderline pairs (small Haiku call each)").option("--rescore-band-lo <n>","low end of the borderline band (default 0.4)").option("--rescore-band-hi <n>","high end of the borderline band (default 0.7)").option("--rescore-model <id>","model id for the rescore call (default Haiku 4.5)").action(t=>{Od(t)}),e.command("list").description("List threads, newest first.").option("--archived","include archived threads").option("--json","emit JSON instead of a table").action(t=>{ed(t)}),e.command("show <id-prefix>").description("Show a thread's header and session tree.").option("--json","emit JSON instead of formatted output").action((t,s)=>{td(t,s)}),e.command("new <name>").description("Create a new thread.").option("--origin <session-id>","seed with an origin session").option("--summary <text>","optional short summary").option("--json","emit JSON").action((t,s)=>{sd(t,s)}),e.command("link <session-id>").description("Link a session into a thread.").requiredOption("--thread <id-prefix>","thread id or prefix").option("--parent <session-id>","parent session within the thread").option("--role <role>","origin | child (default inferred from --parent)").option("--json","emit JSON").action((t,s)=>{nd(t,s)}),e.command("unlink <session-id>").description("Remove a session from a thread.").requiredOption("--thread <id-prefix>","thread id or prefix").option("--json","emit JSON").action((t,s)=>{rd(t,s)}),e.command("set-parent <session-id>").description("Change a session's parent within a thread. Use --parent none to promote to origin.").requiredOption("--thread <id-prefix>","thread id or prefix").option("--parent <session-id|none>",'new parent, or "none" to promote to origin').option("--json","emit JSON").action((t,s)=>{od(t,s)}),e.command("rename <id-prefix> <new-name>").description("Rename a thread.").option("--json","emit JSON").action((t,s,n)=>{id(t,s,n)}),e.command("close <id-prefix>").description("Mark a thread as closed (work complete).").option("--json","emit JSON").action((t,s)=>{ad(t,s)}),e.command("reopen <id-prefix>").description("Reopen a closed thread.").option("--json","emit JSON").action((t,s)=>{cd(t,s)}),e.command("archive <id-prefix>").description("Archive a thread (hidden from the default list).").option("--json","emit JSON").action((t,s)=>{ld(t,s)}),e.command("merge <source-id-prefix>").description("Merge one thread into another.").requiredOption("--into <id-prefix>","destination thread").option("--json","emit JSON").action((t,s)=>{dd(t,s)}),e.command("split <id-prefix>").description("Split sessions out of a thread into a new thread.").requiredOption("--sessions <s1,s2,...>","comma-separated session ids or prefixes").requiredOption("--name <new-name>","name for the new thread").option("--json","emit JSON").action((t,s)=>{ud(t,s)})}Ku(kw);Ku(Nw);k.command("share [id]").description("Save a session as a shareable PNG card. No args = your last recalled session. Saved to ~/Downloads and opened.").option("--style <A|B|C|D>","card style (default A: Minimal)").option("--verdict <quote>","your one-line take on the session").option("--link","also generate a shareable URL and copy it to the clipboard").option("--clipboard","also copy the PNG to the system clipboard").option("--out <path>","override the save directory").option("--no-open","do not auto-open the saved PNG").action(async(e,t)=>{await Zd(e,t)});k.command("feedback").description("Send a 1-5 rating and optional comment to the team. Interactive by default; pass --score (and optionally --message) to skip prompts.").option("--score <1-5>","rating from 1 (bad) to 5 (great)").option("--message <text>","optional comment to send with the rating").action(async e=>{let t=await iu(e);t!==0&&(process.exitCode=t)});k.command("wrapped [month]").description("Save your monthly recap as a shareable PNG card. Defaults to the current month. Accepts YYYY-MM, full name, or abbreviation.").option("--verdict <quote>","your one-line take on the month").option("--out <path>","override the save directory").action(async(e,t)=>{await tu(e,t)});process.env.CLAUDECODE&&process.stderr.write(`<claude-code-hint v="1" type="plugin" value="claude-recall@claude-plugins-official" />
1665
1668
  `);k.action(async()=>{await vl()});k.hook("preAction",async(e,t)=>{let s=t.name();try{await ql(s,bo)}catch{}Xl(bo).catch(()=>{})});k.parseAsync(process.argv).catch(e=>{console.error(e),process.exit(1)});