cc-safety-net 2.0.6 → 2.0.8

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.
@@ -1,43 +1,43 @@
1
1
  #!/usr/bin/env node
2
- import{$ as ae,$a as Ur,A as pn,Aa as Zr,B as Nl,Ba as ee,C as P,Ca as Qr,D as U,Da as Xr,E as Ot,Ea as O,F as Ht,Fa as Kt,G as Wn,Ga as Tt,H as At,Ha as _t,I as G2,Ia as T,J as $2,Ja as D3,K as Et,Ka as bn,L as s2,La as m3,M as b1,Ma as fr,N as re,Na as k3,O as Rn,Oa as q3,P as f1,Pa as j3,Q as h1,Qa as it,R as Mn,Ra as F3,S as Vn,Sa as z3,T as hn,Ta as e1,U as yn,Ua as r1,V as _r,Va as a1,W as un,Wa as l1,X as g2,Xa as r3,Y as Pt,Ya as Gr,Z as C2,Za as Cr,_ as y1,_a as Mt,aa as $1,ab as Or,b as $r,ba as g1,bb as o2,c as gr,ca as Er,cb as x2,d as A,da as jr,db as l2,e as Dr,ea as Pr,eb as Tr,f as Qt,fa as Ir,fb as W,g as Z,ga as Nr,gb as fn,h as D,ha as It,hb as on,i as sn,ia as Fr,ib as x1,j as g,ja as m,jb as wn,k as w2,ka as Nt,kb as c2,l as Ar,la as w1,lb as B1,m as A2,ma as d2,mb as Kn,n as cn,na as vn,o as c3,oa as ne,p as St,pa as te,q as Wr,qa as n1,r as Ln,ra as t1,s as Rr,sa as zr,t as Ut,ta as M2,u as Kr,ua as Wt,v as Mr,va as Rt,w as _,wa as Vr,x as E,xa as S2,y as R2,ya as g3,z as K2,za as Jr}from"../chunks/index-3a1zwkma.js";var Y3=["-h","--help"];function F(n,t){let e=Object.entries(n.booleans??{}),r=Object.entries(n.values??{}),a=Object.fromEntries(e.map(([L])=>[L,!1])),l={},d=[],s=[],c=!1,i=-1;for(let[L,u]of t.entries()){if(L<=i)continue;if(u==="--"){d.push(...t.slice(L+1));break}if(Y3.includes(u)){c=!0;continue}let v=e.find(([,f])=>f.includes(u));if(v){a[v[0]]=!0;continue}let p=r.find(([,f])=>f.includes(u));if(p){let f=t[L+1];if(f===void 0||f.startsWith("-")){s.push(`${u} requires a value`);continue}l[p[0]]=f,i=L+1;continue}if(u.startsWith("-")){s.push(`Unknown option for ${n.label}: ${u}`);continue}if(n.positionals==="tail"){d.push(...t.slice(L));break}d.push(u)}if(n.positionals!=="list"&&n.positionals!=="tail")s.push(...d.map((L)=>`Unexpected argument for ${n.label}: ${L}`));return{flags:a,values:l,positionals:d,help:c,errors:s}}function r2(n){for(let t of n)console.error(t);return n.length>0}import{readdirSync as xd,statSync as s1,unlinkSync as $d}from"node:fs";import{basename as c1,dirname as gd,join as Dd,resolve as md}from"node:path";function z(n){return Array.from(n,(t)=>{let e=t.charCodeAt(0);if(e<=31||e>=127&&e<=159)return`\\x${e.toString(16).padStart(2,"0")}`;return t}).join("")}var zt=(n)=>{let t=Date.now()-new Date(n).getTime();if(!Number.isFinite(t))return"";let e=Math.floor(t/60000),r=Math.floor(e/60),a=Math.floor(r/24);if(a>0)return`${a}d ago`;if(r>0)return`${r}h ago`;if(e>0)return`${e}m ago`;return"just now"},Q2=(n)=>{let t=(n??"").trim().split(/\s+/).filter((a)=>a&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(a)),e=t[0]?.split("/").pop();if(!e)return null;let r=t[1];return r&&/^[a-z][a-z0-9-]*$/.test(r)?`${e} ${r}`:e};import{existsSync as S3,readdirSync as H3,readFileSync as A3}from"node:fs";import{join as W3}from"node:path";function u2(n,t){try{return H3(n,{withFileTypes:!0,encoding:"utf8"}).flatMap((e)=>{let r=W3(n,e.name);if(e.isDirectory())return u2(r,t);if(e.name.endsWith(".jsonl"))return[r];return[]})}catch{if(t&&S3(n))t.count++;return[]}}function Bt(n){let t=(a)=>`${a.sessionId}
3
- ${Q2(a.segment||a.command)}`,e=n.filter((a)=>a.decision!=="allow"),r=e.filter((a)=>a.sessionId).reduce((a,l)=>a.set(t(l),(a.get(t(l))??0)+1),new Map);return new Set(e.filter((a)=>a.failureStage||(r.get(t(a))??0)>=2))}function dn(n,t){try{return A3(n,"utf-8").split(`
4
- `).filter(Boolean).flatMap((e)=>{try{return[JSON.parse(e)]}catch{if(t)t.count++;return[]}})}catch{if(t)t.count++;return[]}}import{resolve as ud}from"node:path";var R3=["AKIA","ASIA","ghp_","gho_","ghu_","ghs_","ghr_","github_pat_","glpat-","xox","npm_","pypi-","rk_","sk-","sk_","gsk_","xai-","pplx-","bastn_","tgp_v1_","flp_","wfr_","fw_","fwp_","tp-","psk-"];function mr(n){let t=0,e={allocateSegment(){return t++},getNextSegmentIndex(){return t},recordGlobal(r){n.record({kind:"step",scope:"global",step:r})},recordSegment(r,a=e.currentSegmentIndex){if(a===void 0)return;n.record({kind:"step",scope:"segment",segmentIndex:a,step:r})}};return e}function kr(n={}){let t=[],e=n.maxEvents??512,r={maxTextLength:n.maxTextLength??2048,maxListLength:n.maxListLength??128,maxObjectProperties:n.maxObjectProperties??n.maxListLength??128,maxDepth:n.maxDepth??16},a=0,l,d=new Set;return{record(s){if(l)return;try{if(!s||t.length>=e){a++;return}t.push(Zt(K3(s,r,d)))}catch{a++}},finish(s){if(l)return l;try{l=Zt({events:Object.freeze(t),droppedEvents:a,terminal:M3(s,r,d)})}catch{a++,l=Object.freeze({events:Object.freeze(t),droppedEvents:a,terminal:Object.freeze({result:"blocked",reason:"trace unavailable".slice(0,r.maxTextLength),segment:"trace unavailable".slice(0,r.maxTextLength)})})}return l}}}function K3(n,t,e){if(n.kind!=="step")throw TypeError("invalid trace event");let{scope:r,step:a}=n;Sn(a,e,t);let l=X2(a,t,e);if(r==="global")return{kind:"step",scope:"global",step:l};if(r!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:n.segmentIndex,step:l}}function M3(n,t,e){let r=n.result;if(r==="allowed")return Object.freeze({result:"allowed"});if(r!=="blocked")throw TypeError("invalid trace terminal");let a=n.ruleId;return Object.freeze({result:"blocked",reason:X2(n.reason,t,e),segment:X2(n.segment,t,e),...a?{ruleId:X2(a,t,e)}:{}})}function Sn(n,t,e,r=0,a=new WeakSet){if(typeof n==="string"){let s=n.slice(0,e.maxTextLength);if(!Qt(s))return;for(let c of Dr(s))for(let i of c.match(/[^\s"'()$]+/g)??[])t.add(qr(i));return}if(!n||typeof n!=="object"||r>=e.maxDepth||a.has(n))return;if(a.add(n),Array.isArray(n)){let s=Math.min(n.length,e.maxListLength);for(let c=0;c<s;c++)Sn(n[c],t,e,r+1,a);return}let l=0,d=new Set;for(let s in n){if(!Object.hasOwn(n,s))continue;if(l>=e.maxObjectProperties)break;l++,Sn(s,t,e);let c=Jt(s,e,t);if(d.has(c))continue;d.add(c),Sn(n[s],t,e,r+1,a)}}function X2(n,t,e,r=0,a=new WeakSet){if(typeof n==="string")return Jt(n,t,e);if(!n||typeof n!=="object")return n;if(r>=t.maxDepth)return;if(a.has(n))return;if(a.add(n),Array.isArray(n)){let s=[],c=Math.min(n.length,t.maxListLength);for(let i=0;i<c;i++)s.push(X2(n[i],t,e,r+1,a));return s}let l={},d=0;for(let s in n){if(!Object.hasOwn(n,s))continue;if(d>=t.maxObjectProperties)break;d++;let c=Jt(s,t,e);if(Object.hasOwn(l,c))continue;Object.defineProperty(l,c,{value:X2(n[s],t,e,r+1,a),enumerable:!0,configurable:!0,writable:!0})}return l}function Jt(n,t,e){let r=n.slice(0,t.maxTextLength),a=Qt(r)?gr(r):r,l=e.size>0?G3(a,e):a;return(V3(l)?$r(l):l).slice(0,t.maxTextLength)}function V3(n){return n.includes("PRIVATE KEY")||n.includes("://")||n.includes("eyJ")||n.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(n)||n.length>=14&&R3.some((t)=>n.includes(t))||n.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(n)}function G3(n,t){return n.replace(/[^\s"'()$]+/g,(e)=>t.has(qr(e))?"<redacted>":e)}function qr(n){let t=2166136261,e=2166136261;for(let r=0;r<n.length;r++)t=Math.imul(t^n.charCodeAt(r),16777619),e=Math.imul(e^n.charCodeAt(n.length-r-1),16777619);return`${t>>>0}:${e>>>0}:${n.length}`}function Zt(n){if(n&&typeof n==="object"&&!Object.isFrozen(n)){for(let t of Object.values(n))Zt(t);Object.freeze(n)}return n}function Br(n,t,e,r){let a=r??jr(),l=e??a.getCommandProgram(n,t.shell??"auto"),d=kr(),s=mr(d),c=l.dialect==="powershell"?a.getCommandProgram(n,"posix"):l,i=Fr(c);s.recordGlobal({type:"parse",input:n,segments:i.map((v)=>[...v])});let L=zr(n,{...t,analyzePartialProgram:!0,trace:s},l,a),u=s.getNextSegmentIndex();if(L&&u>0&&u<i.length)s.recordSegment({type:"segment-skipped",index:u,reason:"prior-segment-blocked"},u);return Object.freeze({decision:L,trace:d.finish(L?{result:"blocked",reason:L.reason,segment:L.evidence.find((v)=>v.kind==="command")?.segment??n,...L.ruleId?{ruleId:L.ruleId}:{}}:{result:"allowed"}),program:l})}import{resolve as C3}from"node:path";function Xt(n){let t=Jr().safeParse(n);return{errors:t.success?[]:Qr(t.error.issues),ruleNames:new Set(Zr(n).map((e)=>e.toLowerCase()))}}function Yt(n){let t=Yr(n);if(!t.ok)return t.result;return Xt(t.parsed)}function Yr(n){let t=[],e=new Set;try{let r=typeof n==="string"?sn(n):n,a=g(r);if(a===null)return t.push(`File not found: ${r.path}`),{ok:!1,result:{errors:t,ruleNames:e}};if(!a.trim())return t.push("Config file is empty"),{ok:!1,result:{errors:t,ruleNames:e}};return{ok:!0,parsed:JSON.parse(a)}}catch(r){if(r instanceof Z)return t.push(r.message),{ok:!1,result:{errors:t,ruleNames:e}};let a=r instanceof Error?r.message:String(r);return t.push(r instanceof SyntaxError?"Invalid JSON":a),{ok:!1,result:{errors:t,ruleNames:e}}}}function Sr(n){return C3(n??process.cwd(),".safety-net.json")}function a2(n){let t=Yr(n);if(!t.ok)return t.result;let e=Xr(t.parsed);return{errors:e.errors,ruleNames:e.sources}}import{isAbsolute as U3,join as Hn,relative as O3,resolve as Hr,sep as T3}from"node:path";async function W2(n={}){let t=Gt(n);return _3(t,await An(t,S2()))}function _3(n,t){if(!t.ok)return t;let e=U(n),r=[...new Set(l2(e.configPath,e.lockPath,n,e.filesystemScope))];if(r.length===0)return t;return{ok:!1,errors:r,warnings:t.warnings,entries:t.entries}}async function An(n,t,e,r={}){let a=null,l=!1;try{let d=U(n),s=Kt(d.configTarget);if(!s.ok)return s.result;let c=s.config;if(n.check)return td(c,d,n);a={target:d.lockTarget,content:g(d.lockTarget)};let i=Mt(d.lockTarget);if(i.errors.some((h)=>h.startsWith("Unable to access ")))return{ok:!1,errors:i.errors,warnings:[],entries:[]};if(n.only&&i.errors.length>0)return{ok:!1,errors:i.errors,warnings:[],entries:[]};let L=i.errors.length>0?null:i.lock,u=n.only?Gr(c,L,n.only):{ok:!0,specs:c.rules};if(!u.ok)return u.result;if(n.only&&!L&&u.specs.length<c.rules.length)return{ok:!1,errors:[`No lockfile available for partial update; run ${Mr}`],warnings:[],entries:[]};let v=(await P3(u.specs,(h)=>Ur(h,d.configDir,n,L,d.filesystemScope,t),t)).map((h)=>ed(h,L,e));for(let h of v)ld(h.content,h.entry,d.configDir,n,d.filesystemScope);let p=n.only?rd(c,L,v):v.map((h)=>h.entry);l=!0,T(d.lockTarget,{version:1,rulebooks:p},void 0,r._testAfterPolicyRename);let f=new Map(v.map((h)=>[h.entry.spec,h.rulebook.rules.length])),o=dd(p,d.configDir,n,d.filesystemScope,r);return{ok:!0,errors:[],warnings:o,entries:p.map((h)=>ad(h,f))}}catch(d){if(l&&a)try{Y2(a.target,a.content)}catch(s){return H2(s)}return H2(d)}}async function Vt(n,t={}){return E3(n,Gt(t),S2())}async function E3(n,t,e,r={}){let a=null,l=!1;try{let d=U(t),s=g(d.configTarget);a={target:d.configTarget,content:s};let c=Kt(d.configTarget);if(!c.ok)return c.result;let i=c.config,L=Kr(n)?await Or(n,e):[{spec:n}],u=L.map((f)=>f.spec),v=[...new Set([...i.rules,...u])];if(v.length>Wt)return I3();if(v.length!==i.rules.length)l=!0,T(d.configTarget,{version:1,rules:v,overrides:i.overrides??{},transparent_wrappers:i.transparent_wrappers??[]},void 0,r._testAfterPolicyRename);let p=await An(t,e,new Map(L.filter((f)=>!!f.display_ref).map((f)=>[f.spec,f.display_ref])),r);if(!p.ok)Y2(d.configTarget,s);return p}catch(d){if(l&&a)try{Y2(a.target,a.content)}catch(s){return H2(s)}return H2(d)}}async function P3(n,t,e=S2()){if(n.length>Wt)throw Error(Rt);let r=Array(n.length),a=0,l,d=Array.from({length:Math.min(n.length,Vr.concurrency)},async()=>{while(!l){let s=a;if(s>=n.length)return;a++;try{r[s]=await t(n[s],s,e.controller.signal)}catch(c){if(!l)l={value:c},a=n.length,e.controller.abort(c);return}}});if(await Promise.all(d),l)throw l.value;return r}function I3(){return{ok:!1,errors:[Rt],warnings:[],entries:[]}}function Gt(n){return{cwd:n.cwd,cacheConfigDir:n.cacheConfigDir,userConfigDir:n.userConfigDir,userConfigPath:n.userConfigPath,projectConfigPath:n.projectConfigPath,global:n.global,check:n.check,only:n.only,refresh:n.refresh}}function N3(n){return{...Gt(n),deleteSource:n.deleteSource}}async function Ct(n,t={}){try{return await nd(n,N3(t),{})}catch(e){return H2(e)}}async function nd(n,t,e){let r=U(t),a=O(r.configTarget);if(a.errors.length>0)return{ok:!1,errors:a.errors,warnings:[],entries:[]};if(!a.config)return{ok:!1,errors:[`No config found at ${r.configPath}`],warnings:[],entries:[]};let l=Mt(r.lockTarget);if(l.errors.length>0)return{ok:!1,errors:l.errors,warnings:[],entries:[]};let d=Cr(a.config.rules,l.lock,n);if(!d.ok)return d.result;let s=t.deleteSource?sd(r.configDir,d.specs,l.lock,r.filesystemScope):{ok:!0,dirs:[]};if(!s.ok)return s.result;let c=g(r.configTarget);if(c===null)return H2(Error("Rules config is unavailable."));try{T(r.configTarget,{version:1,rules:a.config.rules.filter((u)=>!d.specs.includes(u)),overrides:a.config.overrides??{},transparent_wrappers:a.config.transparent_wrappers??[]},void 0,e._testAfterPolicyRename)}catch(u){throw Y2(r.configTarget,c),u}let i=await An(t,S2(),void 0,e);if(!i.ok)return Y2(r.configTarget,c),i;let L=id(s.dirs,e,r.filesystemScope);if(!L.ok){Y2(r.configTarget,c);let u=await An(t,S2(),void 0,e);if(!u.ok)return{ok:!1,errors:[...L.result.errors,...u.errors],warnings:u.warnings,entries:u.entries};return L.result}return i}async function td(n,t,e){let r=Tr(n,t.lockPath,t.configDir,e,e.global?"user":"project",t.filesystemScope);return{ok:r.errors.length===0&&r.warnings.length===0,errors:[...r.errors,...r.warnings],warnings:[],entries:r.entries}}function ed(n,t,e){let r=t?.rulebooks.find((l)=>l.spec===n.entry.spec&&l.kind==="github"),a=e?.get(n.entry.spec)??(r?.kind==="github"?r.display_ref:void 0);if(!a||n.entry.kind!=="github")return n;return{...n,entry:{...n.entry,display_ref:a}}}function rd(n,t,e){let r=new Set(n.rules),a=new Set(t?.rulebooks.map((d)=>d.spec)??[]),l=new Map(e.map((d)=>[d.entry.spec,d.entry]));return[...(t?.rulebooks.filter((d)=>r.has(d.spec))??[]).map((d)=>l.get(d.spec)??d),...e.filter((d)=>!a.has(d.entry.spec)).map((d)=>d.entry)]}function ad(n,t){return{...n,ruleCount:t.get(n.spec)}}function ld(n,t,e,r,a){let l=Ht(t,At(e,r));w2(D(a,l),n)}function dd(n,t,e,r,a){let l=At(t,e),d=Wn(l),s=D(r,d),c=A2(s);if(!c)return[];let i=n.map((u)=>D(r,Ht(u,l))),L=c.filter((u)=>u.kind==="directory").map((u)=>({directory:D(r,Hn(d,u.name)),identity:D(r,Hn(d,u.name,Rr))})).filter((u)=>!i.some((v)=>Ar(u.identity,v))).map((u)=>u.directory);for(let u of L)Wr(u);return L.flatMap((u)=>{try{return Ld(u,a),[]}catch{return["Unable to prune rules policy cache safely."]}})}function sd(n,t,e,r){let a=new Map(e?.rulebooks.map((i)=>[i.spec,i])??[]),l=t.flatMap((i)=>{let L=a.get(i);if(!L)return Ln.test(i)?[]:["--delete-source can only delete local rulebook sources"];return L.kind==="local-directory"?[]:["--delete-source can only delete local rulebook sources"]}),d=t.map((i)=>{let L=a.get(i);return Hn(n,L?.kind==="local-directory"?L.path:i)}),s=l.length>0?[]:d.flatMap((i)=>cd(n,i,r)),c=[...l,...s];return c.length>0?{ok:!1,result:{ok:!1,errors:c,warnings:[],entries:[]}}:{ok:!0,dirs:d}}function cd(n,t,e){let r=Hr(n),a=Hr(t),l=O3(r,a);if(l===""||l===".."||l.startsWith(`..${T3}`)||U3(l))return[`Refusing to delete local rulebook source outside ${n}: ${t}`];let d=D(e,a),s=A2(d);if(!s)return[`Local rulebook source directory not found: ${t}`];let c=s.find((i)=>i.name==="rulebook.json");if(!c)return[`Local rulebook source directory is missing rulebook.json: ${t}`];if(c.kind!=="file")throw new Z(e.label);if(g(D(e,Hn(a,"rulebook.json"))),s.length>1)return[`Local rulebook source directory contains extra files: ${t}. delete manually if you really want to remove the directory.`];return[]}function id(n,t,e){let r=n.flatMap((a)=>{try{return pd(D(e,a),t),[]}catch(l){return[`Failed to delete local rulebook source ${a}: ${l instanceof Error?l.message:String(l)}`]}});return r.length>0?{ok:!1,result:{ok:!1,errors:r,warnings:[],entries:[]}}:{ok:!0}}function Ld(n,t){if(t._testPruneRulebookCacheDir){t._testPruneRulebookCacheDir(n.path);return}St(n)}function pd(n,t){if(t._testDeleteLocalSourceDir){t._testDeleteLocalSourceDir(n.path);return}St(n)}function Y2(n,t){if(t===null){cn(n);return}w2(n,t)}function H2(n){return{ok:!1,errors:[n instanceof Error?n.message:String(n)],warnings:[],entries:[]}}function V2(n,t){let e=vd(t),r=n1(e),a={effectiveLevel:r.effectiveLevel,selectedPreset:e.policySnapshot.policy.safety.level??"standard",effectiveCapabilities:r.effectiveCapabilities,destructiveCommandRuleOverrides:e.policySnapshot.policy.destructiveCommandRuleOverrides},{configSource:l,configValid:d}=od({cwd:t?.cwd,userConfigDir:t?.userConfigDir});if(!n||!n.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:l,configValid:d,...a};let s=bd(n,e);if(s)return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",ruleModule:s.ruleModule,ruleFunction:s.ruleFunction,matched:!0,reason:s.reason}]}]},result:"blocked",reason:A(s.reason),segment:A(s.target),...s.ruleId?{ruleId:A(s.ruleId)}:{},configSource:l,configValid:d,...a};let c=Br(n,e),i=c.decision,L=i?.ruleId??fd(n,e),u=un.find((p)=>p.id===L&&p.activationCapability),v=u?r.policy.effectiveDestructiveCommandRules[u.id]:void 0;return{trace:yd(c.trace),result:i?"blocked":"allowed",reason:i?A(i.reason):void 0,segment:i?A(i.evidence.find((p)=>p.kind==="command")?.segment??n):void 0,ruleId:i?.ruleId?A(i.ruleId):void 0,customRule:hd(wd(i?.ruleId,e.policySnapshot)),configSource:l,configValid:d,...a,...u&&v?{ruleActivation:{id:u.id,...v}}:{}}}function od(n){let t=_(n?.cwd),e=n?.userConfigPath??E(n),r=P({cwd:n?.cwd,userConfigDir:n?.userConfigDir,userConfigPath:n?.userConfigPath});try{if(g(r.projectConfigTarget)!==null){if(a2(r.projectConfigTarget).errors.length===0)return{configSource:t,configValid:!0};return{configSource:t,configValid:!1}}}catch(a){if(a instanceof Z)return{configSource:t,configValid:!1};throw a}try{if(g(r.userConfigTarget)!==null){let a=a2(r.userConfigTarget);return{configSource:e,configValid:a.errors.length===0}}return{configSource:null,configValid:!0}}catch(a){if(a instanceof Z)return{configSource:e,configValid:!1};throw a}}function vd(n){let t=ud(n?.cwd??process.cwd()),e=n?.policySnapshot??W({cwd:t,userConfigDir:n?.userConfigDir}),r=d2(e.policy);return{cwd:t,effectiveCwd:t,policySnapshot:e,environment:_r(),protectedGitMetadata:Nr(t),effectiveCapabilities:r.capabilities,strict:n?.strict??r.strict,paranoidRm:r.paranoidRm,paranoidInterpreters:r.paranoidInterpreters,worktreeMode:r.worktreeMode}}function bd(n,t){let e=t.cwd??process.cwd(),r=Er(M2("",{command:n},{kind:"command",shell:"posix"},{executionCwd:e,configCwd:e},n)),a=r1(r);if(a)return{reason:e1,target:a.target,ruleId:"policy-protection",ruleModule:"policy-protection",ruleFunction:"findPolicyConfigMutationTarget"};let l=Ir(r,t.protectedGitMetadata);if(l)return{reason:Pr,target:l.target,ruleId:"git-metadata-protection",ruleModule:"git-metadata-protection",ruleFunction:"findGitMetadataMutationTarget"};let d=t.policySnapshot.policy,s=d.secretProtection.enabled===!1?null:l1(r,d.secretProtection,{strict:t.strict});if(s)return{reason:a1,target:s.target,ruleId:s.ruleId,ruleModule:"secret-protection",ruleFunction:"findSensitiveTarget"};return null}function fd(n,t){let e=t.policySnapshot.policy,r=on({...e,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...e.destructiveCommandRuleOverrides,...Object.fromEntries(un.flatMap((a)=>a.activationCapability?[[a.id,"on"]]:[]))}},t.policySnapshot.state==="degraded"?{diagnostics:t.policySnapshot.diagnostics,reason:t.policySnapshot.reason}:void 0);return t1(n,{...t,policySnapshot:r,strict:!0,paranoidRm:!0,paranoidInterpreters:!0})?.ruleId}function hd(n){if(!n)return;return{id:A(n.id),...n.rulebook?{rulebook:{name:A(n.rulebook.name),version:A(n.rulebook.version)}}:{},...n.source?{source:A(n.source)}:{},...n.override?{override:{type:"reason",reason:A(n.override.reason)}}:{}}}function yd(n){let t=n.events.flatMap((r)=>r.kind==="step"&&r.scope==="global"?[r.step]:[]),e=new Map;for(let r of n.events){if(r.kind!=="step"||r.scope!=="segment")continue;let a=e.get(r.segmentIndex)??{index:r.segmentIndex,steps:[]};a.steps.push(r.step),e.set(r.segmentIndex,a)}return{steps:t,segments:[...e.values()]}}function wd(n,t){let e=n?.replace(/^custom\./,"");if(!e||!t.policy.rules.some((r)=>r.name===e))return;return t.ruleMetadata[e]??Object.freeze({id:e})}function kd(n){let t=G2(),e=F({label:"logs",booleans:{all:["--all"],suspect:["--suspect"],json:["--json"],pruneLegacy:["--prune-legacy"],dryRun:["--dry-run"]},values:{id:["--id"],limit:["--limit"],since:["--since"],agent:["--agent"],rule:["--rule"],session:["--session"],project:["--project"]}},n);if(r2(e.errors))return null;if(e.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(e.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let r=e.values.limit===void 0?20:d1(e.values.limit);if(r===null)return console.error("--limit must be a positive number"),null;let a=e.values.since===void 0?Math.min(30,t):d1(e.values.since);if(a===null||a>t)return console.error(`--since must be a positive number of days no greater than ${t}`),null;let l={limit:r,limitExplicit:e.values.limit!==void 0,since:a,sinceExplicit:e.values.since!==void 0,all:e.flags.all,json:e.flags.json,suspect:e.flags.suspect,pruneLegacy:e.flags.pruneLegacy,dryRun:e.flags.dryRun,id:e.values.id,agent:e.values.agent,rule:e.values.rule,session:e.values.session,project:e.values.project===void 0?void 0:md(e.values.project)};if(l.id&&(l.agent!==void 0||l.rule!==void 0||l.session!==void 0||l.project!==void 0||l.suspect||l.sinceExplicit||l.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(l.pruneLegacy&&(l.id!==void 0||l.agent!==void 0||l.rule!==void 0||l.session!==void 0||l.project!==void 0||l.suspect||l.all||l.sinceExplicit||l.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(l.dryRun&&!l.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return l}async function i1(n,t={}){let e=kd(n);if(!e)return 1;let r=t.logsDir??s2();if(e.pruneLegacy)return qd(r,e.json,e.dryRun);if(!r)return console.log(e.json?"[]":e.id?`No retained audit log entry found for id ${z(e.id)}.`:"No audit log entries found."),0;$2(r);let a={count:0},l=u2(r,a).flatMap((L)=>dn(L,a).map((u)=>({entry:u,file:L})));if(a.count>0)console.error(`warning: ${a.count} audit log ${a.count===1?"source":"sources"} could not be read; these results are incomplete`);if(e.id)return Bd(l,e,t.timeZone);let d=Date.now()-e.since*24*60*60*1000,s=l.filter((L)=>Jd(L,e,r,d)),c=e.suspect?Bt(s.map((L)=>L.entry)):null,i=(c?s.filter((L)=>c.has(L.entry)):s).sort((L,u)=>Date.parse(u.entry.ts)-Date.parse(L.entry.ts)).slice(0,e.limit);if(e.json)return console.log(JSON.stringify(i.map((L)=>L.entry),null,2)),0;if(i.length===0)return console.log("No audit log entries found."),0;for(let L of i)console.log(Xd(L.entry,t.timeZone));return 0}function qd(n,t,e){let r=n?Fd(n).map((s)=>Dd(n,s)):[];if(e)return jd(r,t);let a=[],l=0,d=0;for(let s of r){let c=s1(s,{throwIfNoEntry:!1})?.size??0,i=zd(s);if(i){a.push(`${c1(s)}: ${i}`);continue}l++,d+=c}if(t)return console.log(JSON.stringify({removedFiles:l,removedBytes:d,failedFiles:a.length})),a.length===0?0:1;console.log(l===0&&a.length===0?"No legacy audit log files found.":`Removed ${l} legacy audit log ${l===1?"file":"files"} (${L1(d)}).`);for(let s of a)console.error(`Could not remove ${z(s)}`);if(console.log("Nested v2 audit logs were not changed."),l>0)console.log("This deletion cannot be undone.");return a.length===0?0:1}function jd(n,t){let e=n.reduce((r,a)=>r+(s1(a,{throwIfNoEntry:!1})?.size??0),0);if(t)return console.log(JSON.stringify({dryRun:!0,files:n.length,bytes:e})),0;if(console.log(n.length===0?"No legacy audit log files found.":`Would remove ${n.length} legacy audit log ${n.length===1?"file":"files"} (${L1(e)}).`),console.log("Nested v2 audit logs are not included."),n.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Fd(n){try{return xd(n,{withFileTypes:!0}).filter((t)=>t.isFile()&&t.name.endsWith(".jsonl")).map((t)=>t.name)}catch{return[]}}function zd(n){try{return $d(n),null}catch(t){return t instanceof Error?t.message:String(t)}}function L1(n){let t=["B","KiB","MiB","GiB"],e=Math.min(Math.floor(Math.log2(Math.max(n,1))/10),t.length-1);return`${Math.round(n/1024**e*10)/10} ${t[e]}`}function Bd(n,t,e){let r=n.filter((l)=>l.entry.id===t.id);if(r.length>1)return console.error(`Multiple audit log entries found for id ${z(t.id??"")}.`),1;if(t.json)return console.log(JSON.stringify(r.map((l)=>l.entry),null,2)),0;let a=r[0];if(!a)return console.log(`No retained audit log entry found for id ${z(t.id??"")}.`),0;return console.log(Yd(a.entry,e)),0}function Jd(n,t,e,r){if(!t.all&&n.entry.decision==="allow")return!1;if(Date.parse(n.entry.ts)<r)return!1;if(t.agent!==void 0&&n.entry.agent!==t.agent)return!1;if(t.rule!==void 0&&n.entry.ruleId!==t.rule)return!1;if(t.session!==void 0&&!Zd(n,e,t.session))return!1;if(t.project!==void 0&&!Qd(n.entry.cwd,t.project))return!1;return!0}function Zd(n,t,e){if(n.entry.sessionId===e)return!0;return gd(n.file)===t&&c1(n.file,".jsonl")===e}function Qd(n,t){if(!n)return!1;return n===t||n.startsWith(`${t}/`)}function Xd(n,t){let e=z(n.id??"-"),r=z(n.decision??"deny"),a=n.cwd?` [${z(n.cwd)}]`:"",l=n.segment||n.command,d=l===n.command?"":"↳ ",s=l.length>50?`${l.slice(0,50)}…`:l;return`${e.padEnd(16)} ${z(p1(n.ts,t))} ${r.padEnd(5)} ${z(n.agent??"-").padEnd(15)} ${z(n.ruleId??"-").padEnd(20)} ${d}${z(s)}${a}`}function Yd(n,t){let e=(a)=>z(a===void 0||a===null||a===""?"-":a),r=n.shape?`${n.agent??"-"} (shape: ${n.shape})`:n.agent??"-";return[`id: ${e(n.id)}`,`ts: ${e(p1(n.ts,t))}`,`decision: ${e(n.decision)}`,`agent: ${e(r)}`,`level: ${e(n.level)}`,`tool: ${e(n.toolName)}`,`rule: ${e(n.ruleId)}`,`intent: ${e(n.intent)}`,`stage: ${e(n.failureStage)}`,`error: ${e(n.errorCode)}`,`session: ${e(n.sessionId)}`,`cwd: ${e(n.cwd)}`,`version: ${e(n.v)}`,`truncated: ${e(n.truncated===!0?"yes":void 0)}`,`reason: ${e(n.reason)}`,`command: ${e(n.command)}`,`segment: ${e(n.segment)}`].join(`
5
- `)}function p1(n,t){let e=new Date(n);if(Number.isNaN(e.getTime()))return n;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:t}).format(e)}function d1(n){let t=Number(n);return Number.isFinite(t)&&t>0?t:null}var u1={name:"doctor",aliases:["--doctor"],description:"Run diagnostic checks to verify installation and configuration",usage:"doctor [options]",options:[{flags:"--json",description:"Output diagnostics as JSON"},{flags:"--skip-update-check",description:"Skip npm registry version check"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net doctor","cc-safety-net doctor --json","cc-safety-net doctor --skip-update-check"]};var o1={name:"explain",description:"Show step-by-step analysis trace of how a command would be analyzed",usage:"explain [options] <command>",argument:"<command>",options:[{flags:"--json",description:"Output analysis as JSON"},{flags:"--cwd",argument:"<path>",description:"Use custom working directory"},{flags:"-h, --help",description:"Show this help"}],examples:['cc-safety-net explain "git reset --hard"','cc-safety-net explain --json "rm -rf /"','cc-safety-net explain --cwd /tmp "git status"']};var v1={name:"gui",description:"Open the local policy editor GUI",usage:"gui [options]",options:[{flags:"--no-open",description:"Print the URL without opening a browser"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net gui","cc-safety-net gui --no-open"]};import{isAbsolute as D1,relative as Ud}from"node:path";var Sd=8388608;function Hd(n,t){console.log(JSON.stringify(n(f1(t))))}async function Ad(n){let t;try{t=(await le(process.stdin)).trim()}catch{n({reason:"Failed to parse hook input JSON."});return}if(!t){n({reason:"Missing hook input JSON."});return}return de(t,n,"Failed to parse hook input JSON.")}async function le(n){let t=[],e=0;for await(let r of n){let a=typeof r==="string"?Buffer.from(r,"utf-8"):Buffer.from(r.buffer,r.byteOffset,r.byteLength);if(e+=a.byteLength,e>Sd)throw Wd(n),Error("hook input byte limit exceeded");t.push(a)}return Buffer.concat(t,e).toString("utf-8")}function Wd(n){let t=n.destroy??n.cancel;if(!t)return;try{Promise.resolve(t.call(n)).catch(()=>{})}catch{}}function de(n,t,e){try{return JSON.parse(n)}catch{t({reason:e});return}}function X(n,t){let e=t.get(n);return e?{kind:"command",shell:e}:{kind:y1(n)}}function I(n,t,e,r){let a=n===void 0?process.cwd():n,l=typeof a==="string"&&a.trim()!==""?c2([a]):void 0;if(l)return{configCwd:l,executionCwd:l};return H(r,t,e,Vd(a)),null}function H(n,t,e,r){let a;try{a=ae(t)}catch(l){if(!(l instanceof C2))throw l}n(Rn({command:a,segment:r,toolName:e}))}async function Rd(n){let t=await Ad(n.outputDeny);if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t)){H(n.outputDeny);return}if(!n.isSupported(t))return;let e=n.getAgent?.(t)??n.agent,r=n.agent===e?void 0:n.agent,a=Cd(t),l=(p,f)=>{b1(p,()=>n.getSessionId(t),{agent:e,shape:r,toolName:f,cwd:a}),n.outputDeny(p)},d=n.getToolName(t);if(typeof d!=="string"||d.trim()===""){H((p)=>l(p),Gd(t));return}let s=d,c=(p)=>l(p,s),i;try{i=n.getToolInput(t,s,c)}catch(p){if(!(p instanceof C2))throw p;H(c,void 0,s);return}if(!i.ok)return;let L=n.getContext(t,i.input,s,c);if(!L)return;let u;try{u=ae(i.input)}catch(p){if(!(p instanceof C2))throw p;H(c,void 0,s);return}let v=M2(s,i.input,i.route,L,u??null);try{let p=Kn(v,{guard:{auditAllowed:w1(),dependencies:n.guardDependencies},audit:{agent:e,shape:r,getSessionId:()=>n.getSessionId(t)}}),f=re(p,{includeEvidence:!0,toolName:p.stage==="command-analysis"?void 0:s});if(f){n.outputDeny(f);return}n.outputAllow?.()}catch(p){if(!(p instanceof x1))throw p;Kd(p);let f=re(p.evaluation,{includeEvidence:!0,toolName:p.evaluation.stage==="command-analysis"?void 0:s});if(f)n.outputDeny(f);return}}function Kd(n){if(!vn(m.debug))return;console.error(`CC Safety Net debug: ${Md(n.stage)}: ${h1(n.cause)}`)}function Md(n){if(n==="policy-protection")return"hook policy protection failed";if(n==="config-load")return"hook config loading failed";if(n==="secret-protection")return"hook secret protection failed";return"hook analysis failed"}function Vd(n){return typeof n==="string"?n:void 0}function Gd(n){if(!n||typeof n!=="object"||Array.isArray(n))return;if(Object.hasOwn(n,"tool_input"))return n.tool_input;let t=n.toolCall;if(t&&typeof t==="object"&&!Array.isArray(t))return t.args;return}function Cd(n){if(!n||typeof n!=="object"||Array.isArray(n))return null;let t=n.cwd;if(typeof t==="string")return t;let e=n.toolCall;if(!e||typeof e!=="object"||Array.isArray(e))return null;let r=e.args;if(!r||typeof r!=="object"||Array.isArray(r))return null;let a=r.Cwd;return typeof a==="string"?a:null}async function Y(n){let t=(a)=>Hd(n.createDenyOutput,a),e=n.createAllowOutput;await Rd({...n,outputDeny:t,outputAllow:e?()=>console.log(JSON.stringify(e())):void 0})}var Od=new Map([["run_command","auto"]]),Td=new Set(["absolutepath","directorypath","file_path","filepath","path","searchdirectory","searchpath","target_file","targetfile"]);function m1(n){return X(n,Od)}async function k1(){await Y({agent:"antigravity-cli",createDenyOutput:(n)=>({decision:"deny",reason:n}),isSupported:()=>!0,getToolName:(n)=>n.toolCall?.name,getToolInput:(n,t)=>({ok:!0,input:Nd(n.toolCall?.args,t),route:m1(t)}),getContext:_d,getSessionId:(n)=>n.conversationId})}function _d(n,t,e,r){let l=Id(n).flatMap((i)=>{let L=c2([i]);return L?[L]:[]});if(!l[0])return D2(r,t,e),null;if(e!=="run_command"){let i;try{i=Ed(t,e,l)}catch(L){if(L instanceof C2)return D2(r,void 0,e),null;if(!(L instanceof Mn))throw L;return D2(r,t,e),null}if(!i)return D2(r,t,e),null;return{configCwd:i,executionCwd:i,policyConfigCwds:l}}let d=n.toolCall?.args;if(!d||!Object.hasOwn(d,"Cwd"))return{configCwd:l[0],executionCwd:l[0],policyConfigCwds:l};let s=d.Cwd;if(typeof s!=="string"||s.trim()==="")return D2(r,t,e),null;let c=wn(s,l);if(c){let i=q1(c,l);if(!i)return D2(r,t,e,s),null;return{configCwd:i,executionCwd:c,policyConfigCwds:l}}return D2(r,t,e,s),null}function Ed(n,t,e){let r=m1(t),a=[...$1(n,Td),...r.kind==="patch"?g1(n):[]].filter(D1),l=Vn(),d=new Set(a.flatMap((s)=>{let c=q1(hn(s,yn,l),e);return c?[c]:[]}));if(d.size>1)return null;return[...d][0]??e[0]??null}function q1(n,t){return t.filter((e)=>Pd(n,e)).reduce((e,r)=>r.length>e.length?r:e,"")||null}function Pd(n,t){let e=Ud(t,n);return e===""||!e.startsWith("..")&&!D1(e)}function D2(n,t,e,r){let a=t&&typeof t==="object"?t.command:void 0;n(Rn({command:typeof a==="string"?a:void 0,segment:r,toolName:e}))}function Id(n){if(n.workspacePaths===void 0)return[process.cwd()];let t=Array.isArray(n.workspacePaths)?n.workspacePaths.filter((e)=>typeof e==="string"&&e.trim()!==""):[];return c2(t)?t:[]}function Nd(n,t){if(!n)return;if(t!=="run_command")return n;return{...n,command:typeof n.CommandLine==="string"&&n.CommandLine!==""?n.CommandLine:void 0}}var U2=[{id:"antigravity-cli",displayName:"Antigravity CLI",doctorOrder:3,runtime:{order:1,flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:2,flag:"--agy-cli",installLabel:"Antigravity CLI",helpTarget:"Antigravity CLI hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",doctorOrder:1,runtime:{order:2,displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{order:3,flag:"--claude-code",installLabel:"Claude Code",helpTarget:"Claude Code plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",doctorOrder:4,install:{order:4,flag:"--codex",installLabel:"Codex",helpTarget:"Codex plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",doctorOrder:7,runtime:{order:5,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:7,flag:"--copilot-cli",installLabel:"GitHub Copilot CLI",helpTarget:"GitHub Copilot CLI plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:6,runtime:{order:4,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:6,flag:"--gemini-cli",installLabel:"Gemini CLI",helpTarget:"Gemini CLI extension",probeCommand:["gemini","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:8,runtime:{order:6,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--hermes-agent",installLabel:"Hermes Agent",helpTarget:"Hermes Agent plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:9,runtime:{order:7,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:9,flag:"--kimi-code",installLabel:"Kimi Code",helpTarget:"Kimi Code hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:10,install:{order:10,flag:"--openclaw",installLabel:"OpenClaw",helpTarget:"OpenClaw plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:11,install:{order:11,flag:"--opencode",installLabel:"OpenCode",helpTarget:"OpenCode plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:12,install:{order:12,flag:"--pi",installLabel:"Pi",helpTarget:"Pi package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",doctorOrder:5,runtime:{order:3,flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{order:5,flag:"--cursor",installLabel:"Cursor",helpTarget:"Cursor hook config",probeCommand:["cursor","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",installLabel:"Amp Code",helpTarget:"Amp Code plugin",probeCommand:["amp","--version"]}}],j1=U2.slice().sort((n,t)=>n.doctorOrder-t.doctorOrder).map((n)=>n.id),F1=U2.filter((n)=>("runtime"in n)).slice().sort((n,t)=>n.runtime.order-t.runtime.order).map((n)=>({id:n.id,displayName:"displayName"in n.runtime?n.runtime.displayName:n.displayName,flags:n.runtime.flags,legacyFlags:"legacyFlags"in n.runtime?n.runtime.legacyFlags:[],description:n.runtime.description,legacyTopLevelFlags:n.runtime.legacyTopLevelFlags})),i2=U2.slice().sort((n,t)=>n.install.order-t.install.order).map((n)=>({id:n.id,...n.install})).map(({order:n,...t})=>t),B6=Object.fromEntries(U2.map((n)=>[n.id,n.displayName]));function v2(n){return U2.find((t)=>t.id===n)?.displayName??n}function b2(n){return U2.find((t)=>t.id===n)?.install.installLabel??n}import{homedir as ns}from"node:os";import{isAbsolute as z1,join as se}from"node:path";function J1(n){if(n!==void 0&&n!==null&&!z1(n))return"unknown";try{let t=Vn(),e=n?hn(n,yn,t):void 0,r=process.env.HOME||ns(),a=[["codex",process.env.CODEX_HOME||se(r,".codex")],["copilot-cli",process.env.COPILOT_HOME||se(r,".copilot")],["claude-code",process.env.CLAUDE_CONFIG_DIR||se(r,".claude")]],l=e?a.flatMap(([d,s])=>{if(!z1(s))return[];return B1(e,hn(s,yn,t))?[d]:[]}):[];if(l.length===1)return l[0]??"unknown";if(l.length>1)return"unknown"}catch(t){if(t instanceof Mn)return"unknown";return"unknown"}if(process.env.CLAUDECODE==="1"||Boolean(process.env.CLAUDE_CODE_ENTRYPOINT))return"claude-code";return"unknown"}var ce="PreToolUse",Z1="BeforeTool",Q1="pre_tool_call",ie="PreToolUse";var ts=new Map([["Bash","posix"],["PowerShell","powershell"]]);function es(n){return X(n,ts)}async function X1(){await Y({agent:"claude-code",getAgent:(n)=>J1(n.transcript_path),createDenyOutput:(n)=>({hookSpecificOutput:{hookEventName:ce,permissionDecision:"deny",permissionDecisionReason:n}}),isSupported:(n)=>n.hook_event_name===ce,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:es(t)}),getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>n.session_id})}var rs=new Map([["bash","auto"],["Bash","auto"]]);function as(n){return X(n,rs)}async function Y1(){await Y({agent:"copilot-cli",createDenyOutput:(n)=>({permissionDecision:"deny",permissionDecisionReason:n}),isSupported:()=>!0,getToolName:(n)=>n.toolName,getToolInput:(n,t,e)=>{if(typeof n.toolArgs!=="string")return e({reason:"Failed to parse toolArgs JSON."}),{ok:!1};let r=de(n.toolArgs,e,"Failed to parse toolArgs JSON.");if(r===void 0)return{ok:!1};return{ok:!0,input:r,route:as(t)}},getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>typeof n.sessionId==="string"&&n.sessionId.trim()?n.sessionId:void 0})}var ls=new Map([["Shell","auto"]]);function ds(n){return X(n,ls)}async function S1(){await Y({agent:"cursor",createDenyOutput:(n)=>({permission:"deny",user_message:n,agent_message:n}),createAllowOutput:()=>({permission:"allow"}),isSupported:()=>!0,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:ds(t)}),getContext:ss,getSessionId:(n)=>n.conversation_id})}function ss(n,t,e,r){let a=cs(n);if(!a[0])return H(r,t,e),null;let l=wn(Ls(n.cwd),a);if(!l)return H(r,t,e,typeof n.cwd==="string"?n.cwd:void 0),null;if(t===null||typeof t!=="object"||Array.isArray(t))return{configCwd:l,executionCwd:l,policyConfigCwds:a};if(!Object.hasOwn(t,"working_directory"))return{configCwd:l,executionCwd:l,policyConfigCwds:a};let d=t.working_directory;if(typeof d!=="string"||d.trim()==="")return H(r,t,e),null;let s=wn(d,a);if(!s)return H(r,t,e,d),null;return{configCwd:l,executionCwd:s,policyConfigCwds:a}}function cs(n){return is(n).flatMap((t)=>{let e=c2([t]);return e?[e]:[]})}function is(n){if(n.workspace_roots===void 0)return typeof n.cwd==="string"&&n.cwd.trim()!==""?[n.cwd]:[];if(!Array.isArray(n.workspace_roots))return[];return n.workspace_roots.filter((t)=>typeof t==="string"&&t.trim()!=="")}function Ls(n){return typeof n==="string"&&n.trim()!==""?n:"."}var ps=new Map([["run_shell_command","auto"]]);function us(n){return X(n,ps)}async function H1(){await Y({agent:"gemini-cli",createDenyOutput:(n)=>({decision:"deny",reason:n,systemMessage:n}),isSupported:(n)=>n.hook_event_name===Z1,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:us(t)}),getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>n.session_id})}import{resolve as os}from"node:path";var vs=new Map([["terminal","posix"]]);async function A1(){await Y({agent:"hermes-agent",createDenyOutput:(n)=>({action:"block",message:n}),isSupported:(n)=>n.hook_event_name===Q1,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:X(t,vs)}),getContext:bs,getSessionId:(n)=>n.session_id})}function bs(n,t,e,r){let a=I(n.cwd,t,e,r);if(!a)return null;if(!t||typeof t!=="object"||Array.isArray(t))return a;if(!Object.hasOwn(t,"workdir"))return a;let l=t.workdir;if(typeof l!=="string"||l.trim()==="")return H(r,t,e),null;let d=c2([os(a.configCwd,l)]);if(!d)return H(r,t,e,l),null;return{...a,executionCwd:d}}var fs=new Map([["Bash","posix"]]);function hs(n){return X(n,fs)}async function W1(){await Y({agent:"kimi-code",createDenyOutput:(n)=>({hookSpecificOutput:{hookEventName:ie,permissionDecision:"deny",permissionDecisionReason:n}}),isSupported:(n)=>n.hook_event_name===ie,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:hs(t)}),getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>n.session_id})}var ys={"antigravity-cli":k1,"claude-code":X1,"copilot-cli":Y1,cursor:S1,"gemini-cli":H1,"hermes-agent":A1,"kimi-code":W1},O2=F1.map((n)=>({...n,run:ys[n.id]}));function R1(n){let t=F({label:"hook",booleans:Object.fromEntries(O2.map((r)=>[r.id,[...r.flags,...r.legacyFlags]]))},n);if(t.errors.length>0)return;let e=O2.filter((r)=>t.flags[r.id]);return e.length===1?e[0]:void 0}function K1(n){return O2.find((t)=>t.legacyTopLevelFlags.some((e)=>e===n))}var ws=O2.map((n)=>({flags:n.flags.join(", "),description:n.description})),xs=O2.flatMap((n)=>n.flags.map((t)=>`cc-safety-net hook ${t}`)),M1={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...ws,{flags:"-h, --help",description:"Show this help"}],examples:xs};var V1={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...i2.map((n)=>({flags:n.flag,description:`Install ${n.helpTarget}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...i2.map((n)=>`cc-safety-net install ${n.flag}`)]},G1={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...i2.map((n)=>({flags:n.flag,description:`Uninstall ${n.helpTarget}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...i2.map((n)=>`cc-safety-net uninstall ${n.flag}`)]},C1={name:"update",description:"Update every installed CC Safety Net integration to the latest version",usage:"update",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net update"]};var U1={name:"logs",description:"Browse audit log entries recorded by hooks",usage:"logs [options]",options:[{flags:"--id",argument:"<id>",description:"Show one entry from retained history by its 16-character id (not guaranteed once it is older than the configured retention)"},{flags:"--limit",argument:"<n>",description:"Maximum entries to print",default:"20"},{flags:"--since",argument:"<days>",description:"Only include entries newer than this many days (max: the configured audit retention, 1-365)",default:"30"},{flags:"--agent",argument:"<name>",description:"Filter by agent name"},{flags:"--rule",argument:"<ruleId>",description:"Filter by rule id"},{flags:"--session",argument:"<id>",description:"Filter by session id"},{flags:"--project",argument:"<path>",description:"Filter by project path"},{flags:"--suspect",description:"Only denials that look like false positives"},{flags:"--all",description:"Include allow entries"},{flags:"--prune-legacy",description:"Permanently delete all legacy root-level logs; nested logs are untouched"},{flags:"--dry-run",description:"With --prune-legacy, report what would be deleted and delete nothing"},{flags:"--json",description:"Output entries as JSON"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net logs --id 3fa9c2d1a70e8b42","cc-safety-net logs --agent claude-code","cc-safety-net logs --project . --since 7","cc-safety-net logs --suspect --since 7","cc-safety-net logs --json","cc-safety-net logs --prune-legacy --dry-run","cc-safety-net logs --prune-legacy"]};var T2={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add <source>",description:"Add a rulebook source and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Refresh rulebook lock/cache state"},{usage:"sync",description:"Sync configured rulebooks"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--check",description:"Check without changing lock/cache state"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net rule init","cc-safety-net rule init --example","cc-safety-net rule wrapper add rtk","cc-safety-net rule add project-rules","cc-safety-net rule sync","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var O1={name:"status",description:"Show what the runtime is enforcing right now",usage:"status",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net status"]};var T1={name:"statusline",description:"Print status line with mode indicators for shell integration",usage:"statusline --claude-code",options:[{flags:"-cc, --claude-code",description:"Print status line for Claude Code"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net statusline -cc","cc-safety-net statusline --claude-code"]};var _1=[O1,u1,U1,o1,T2,V1,C1,G1,M1,v1,T1];function $s(n){return n.aliases??[]}function gs(n){return!n.hidden}function Gn(n){let t=n.toLowerCase();return _1.find((e)=>e.name.toLowerCase()===t||$s(e).some((r)=>r.toLowerCase()===t))}function E1(){return _1.filter(gs)}import{readFileSync as Ds}from"node:fs";import{basename as ms}from"node:path";function Cn(n=7,t=s2()){let e=Date.now()-n*24*60*60*1000,r=[],a=new Set,l=0,d,s,c,i;if(t)$2(t);let L={count:0},u=t?u2(t,L):[];for(let p of u)try{let o=Ds(p,"utf-8").trim().split(`
6
- `).filter(Boolean);for(let h of o)try{let x=JSON.parse(h);if(x.decision==="allow")continue;let w=new Date(x.ts).getTime();if(w>=e){if(l++,a.add(x.sessionId??ms(p,".jsonl")),s===void 0||w<=s)d=x.ts,s=w;if(i===void 0||w>i)c=x.ts,i=w;ks(r,x,w)}}catch{L.count++}}catch{L.count++}let v=r.map((p)=>({timestamp:p.ts,command:p.command,reason:p.reason,relativeTime:zt(new Date(p.ts))}));return{totalBlocked:l,sessionCount:a.size,recentEntries:v,oldestEntry:d,newestEntry:c,unreadable:L.count}}function ks(n,t,e){let r=n.findIndex((a)=>e>new Date(a.ts).getTime());if(r===-1){if(n.length<3)n.push(t);return}if(n.splice(r,0,t),n.length>3)n.pop()}import{dirname as qs}from"node:path";function P1(n,t,e,r,a){let l;try{if(g(r)===null)return{path:n,exists:!1,valid:!1,ruleCount:0};l=a2(r),l.errors.push(...l2(n,t,{userConfigDir:e},a))}catch(d){if(!(d instanceof Z))throw d;l={errors:[d.message],ruleNames:new Set}}return{path:n,exists:!0,valid:l.errors.length===0,ruleCount:l.ruleNames.size,...l.errors.length>0?{errors:l.errors}:{}}}function js(n,t){return{source:t,name:n.name,command:n.command,subcommand:n.subcommand,blockArgs:[...n.block_args],reason:n.reason}}function I1(n,t){let e=t?.userConfigPath??E(),r=t?.projectConfigPath??_(n),a=qs(e),l=o2({cwd:n,userConfigPath:e,projectConfigPath:r,userConfigDir:a}),d=P({cwd:n,userConfigPath:e,projectConfigPath:r,userConfigDir:a}),s=new Map(l.rulebooks.flatMap((c)=>c.rules.map((i)=>[i,c.source])));return{userConfig:P1(e,R2({userConfigPath:e}),a,d.userConfigTarget,d.userScope),projectConfig:P1(r,K2(r),a,d.projectConfigTarget,d.projectScope),effectiveRules:l.rules.map((c)=>js(c,s.get(c.name)??"project")),shadowedRules:[]}}var Fs=[{flag:m.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:m.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:m.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:m.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:m.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:m.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:m.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:m.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function N1(){return[...Fs.map((n)=>({name:n.flag.name,value:ne(n.flag),isSet:te(n.flag),legacyName:n.flag.legacyName,legacyValue:n.flag.legacyName?process.env[n.flag.legacyName]:void 0,legacyIsSet:n.flag.legacyName?process.env[n.flag.legacyName]!==void 0:void 0,description:n.description,defaultBehavior:n.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:process.env.CC_SAFETY_NET_HOME,isSet:process.env.CC_SAFETY_NET_HOME!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var na={error:0,warning:1,info:2},zs=["policy","config","audit"];function Bs(n){return n.map((t)=>{if(t==="ownership")return"is not owned by the current user";if(t==="permissions")return"has unsafe permissions";if(t==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Js=[{derive:(n)=>n.hooks.length>0&&n.hooks.every((t)=>!t.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(n)=>n.hooks.filter((t)=>t.inspectionStatus==="failed").map((t)=>{let e=v2(t.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${e} inspection failed`,detail:`Doctor could not verify the ${e} integration configuration.`,fixHint:`Correct the reported ${e} configuration error, then run \`cc-safety-net doctor\` again.`,integration:t.platform}})},{derive:(n)=>n.userConfig.exists&&!n.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:n.userConfig.path}]:[]},{derive:(n)=>n.projectConfig.exists&&!n.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:n.projectConfig.path}]:[]},{derive:(n)=>n.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${n.configState.reason}`,fixHint:"Correct the named source, run `cc-safety-net rule sync` for a rule source, then rerun doctor."}]:[]},{derive:(n)=>{let t=n.environment.find((e)=>e.name==="CC_SAFETY_NET_AUDIT_SCOPE");return Nt(t?.value)==="invalid"?[{checkId:"environment.audit-scope-invalid",severity:"warning",title:"Audit scope value is invalid",detail:"CC_SAFETY_NET_AUDIT_SCOPE is not `all` or `blocked`, so allowed command decisions are not recorded.",fixHint:"Set CC_SAFETY_NET_AUDIT_SCOPE to `all` or `blocked`, then restart the integration."}]:[]}},...zs.map((n)=>({derive:(t)=>t.posture.directories.filter((e)=>e.kind===n&&e.status==="unsafe").map((e)=>({checkId:`posture.${n}-directory-unsafe`,severity:"error",title:`${n[0]?.toUpperCase()}${n.slice(1)} directory is unsafe`,detail:`The ${n} directory ${Bs(e.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...e.path?{path:e.path}:{}}))})),{derive:(n)=>{let t=[...n.effectiveSafety.weakenedRuleOverrides].sort();return t.length>0?[{checkId:"posture.rule-overrides-weaken-preset",severity:"warning",title:"Rule overrides weaken the selected preset",detail:`Explicit overrides disable rules the resolved preset would enable: ${t.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${t.join(", ")}.`}]:[]}}];function ta(n){return Js.flatMap((t,e)=>t.derive(n).map((r,a)=>({finding:r,catalogOrder:e,occurrence:a}))).sort((t,e)=>na[t.finding.severity]-na[e.finding.severity]||t.catalogOrder-e.catalogOrder||t.occurrence-e.occurrence).map((t)=>t.finding)}function N(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var Zs=(n)=>N()?`\x1B[32m${n}\x1B[0m`:n,Qs=(n)=>N()?`\x1B[33m${n}\x1B[0m`:n,Xs=(n)=>N()?`\x1B[34m${n}\x1B[0m`:n,Ys=(n)=>N()?`\x1B[35m${n}\x1B[0m`:n,Ss=(n)=>N()?`\x1B[36m${n}\x1B[0m`:n,Hs=(n)=>N()?`\x1B[31m${n}\x1B[0m`:n,As=(n)=>N()?`\x1B[2m${n}\x1B[0m`:n,Ws=(n)=>N()?`\x1B[1m${n}\x1B[0m`:n,b={green:Zs,yellow:Qs,blue:Xs,magenta:Ys,cyan:Ss,red:Hs,dim:As,bold:Ws},Rs="\x1B[0m",Ks=[39,82,198,226,208,51,196,46,201,214,93,154,220,27,49,190,200,33,129,227,45,160,63,118,123,202];function Ms(n){let t=n;return()=>{return t=(t*1664525+1013904223)%4294967296,t/4294967296}}function Vs(n){let t=[...Ks],e=Ms(n);for(let r=t.length-1;r>0;r--){let a=Math.floor(e()*(r+1)),l=t[r];t[r]=t[a],t[a]=l}return t}function Gs(n,t=0){if(!N())return"";let e=Vs(t);return`\x1B[38;5;${e[n%e.length]}m`}function ea(n,t,e=0){if(!N())return`"${n}"`;return`${Gs(t,e)}"${n}"${Rs}`}var Cs=new RegExp("\x1B\\[[0-9;]*m","g"),Le=(n)=>n.replace(Cs,"").length;function m2(n){let t=(n.headers??n.rows[0]??[]).map((d,s)=>{let c=Math.max(...n.rows.map((i)=>Le(i[s]??"")));return Math.max(Le(d),c)}),e=(d,s)=>d+" ".repeat(Math.max(0,s-Le(d))),r=(d,s)=>s[0]+t.map((c)=>d.repeat(c+2)).join(s[1])+s[2],a=(d)=>`│ ${d.map((s,c)=>e(s,t[c]??0)).join(" │ ")} │`,l=n.headers?[` ${a(n.headers)}`,` ${r("─",["├","┼","┤"])}`]:[];return[` ${r("─",["┌","┬","┐"])}`,...l,...n.rows.map((d)=>` ${a(d)}`),` ${r("─",["└","┴","┘"])}`].join(`
7
- `)}function ra(n){let t=[];t.push("Hook Integration"),t.push(Us(n));let e=[],r=[];for(let a of n){let l=v2(a.platform);if(a.errors&&a.errors.length>0)for(let d of a.errors)if(a.configured)e.push({platform:l,message:d});else r.push({platform:l,message:d})}for(let a of e)t.push(` Warning (${a.platform}): ${a.message}`);for(let a of r)t.push(b.red(` Error (${a.platform}): ${a.message}`));return t.join(`
8
- `)}function Us(n){let t=["Platform","Discovery","Configuration","Inspection"],e=n.map((r)=>{let a=v2(r.platform);if(r.inspectionStatus==="not-inspected"){let c=b.dim("Not inspected");return[a,c,c,c]}let l=r.detected?b.green("Detected"):r.inspectionStatus==="failed"?b.red("Unknown"):b.dim("Not detected"),d=r.configured?b.green("Configured"):r.detected?b.yellow("Not configured"):r.inspectionStatus==="failed"?b.red("Unknown"):b.dim("Not applicable"),s=r.inspectionStatus==="verified"?b.green("Verified"):r.inspectionStatus==="failed"?b.red("Failed"):b.dim("Not applicable");return[a,l,d,s]});return m2({headers:t,rows:e})}function aa(n){let e=["Guard Engine Verification",` Synthetic self-test: ${n.failed>0?b.red(`${n.passed}/${n.total} FAIL`):b.green(`${n.passed}/${n.total} passed`)}`],r=n.results.filter((a)=>!a.passed);if(r.length>0){e.push(""),e.push(b.red(" Failures:"));for(let a of r)e.push(b.red(` • ${a.description}`)),e.push(b.red(` expected ${a.expected}, got ${a.actual}`))}return e.join(`
9
- `)}function Os(n){if(n.length===0)return" (no custom rules)";let t=["Source","Name","Command","Block Args"],e=n.map((r)=>[r.source,r.name,r.subcommand?`${r.command} ${r.subcommand}`:r.command,r.blockArgs.join(", ")]);return m2({headers:t,rows:e})}function la(n){let t=[];if(t.push("Configuration"),t.push(Ts(n.userConfig,n.projectConfig)),t.push(""),n.effectiveRules.length>0)t.push(` Effective rules (${n.effectiveRules.length} total):`),t.push(Os(n.effectiveRules));else t.push(" Effective rules: (none - using built-in rules only)");for(let e of n.shadowedRules)t.push(""),t.push(` Note: Project rule "${e.name}" shadows user rule with same name`);return t.join(`
10
- `)}function Ts(n,t){let e=["Scope","Status"],r=(l)=>{if(!l.exists)return b.dim("N/A");if(!l.valid)return b.red(`Invalid (${l.errors?.[0]??"unknown error"})`);return b.green("Configured")},a=[["User",r(n)],["Project",r(t)]];return m2({headers:e,rows:a})}function da(n){let t=[];return t.push("Environment"),t.push(_s(n)),t.join(`
11
- `)}function sa(n){let t=["Effective Safety",` Selected preset: ${n.effectiveSafety.selectedPreset}`,` Effective: ${n.effectiveSafety.level}`],e=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[r,a]of e){let l=n.effectiveSafety.capabilities[r],d=l.enabled?b.green("ON"):b.dim("OFF"),s=l.sources.length>0?` (${l.sources.join(", ")})`:"";t.push(` ${a}: ${d} via ${l.source}${s}`)}t.push(` Stored rule customizations: ${n.effectiveSafety.ruleCounts.stored}`),t.push(` Effective rule customizations: ${n.effectiveSafety.ruleCounts.effective}`);for(let[r,a]of Object.entries(n.effectiveSafety.ruleOverrides))t.push(` ${r}: ${a}`);return t.join(`
12
- `)}function ca(n){let t=["Findings"];if(n.length===0)return t.push(" No findings from inspected doctor facts."),t.join(`
13
- `);for(let e of n){let r=`[${e.severity.toUpperCase()}] ${e.checkId}: ${z(e.title)}`,a=e.severity==="error"?b.red:e.severity==="warning"?b.yellow:b.blue;if(t.push(` ${a(r)}`),t.push(` ${z(e.detail)}`),e.path)t.push(` Path: ${z(e.path)}`);if(e.fixHint)t.push(` Fix: ${z(e.fixHint)}`)}return t.join(`
14
- `)}function _s(n){let t=["Variable","Status","Legacy"],e=n.map((r)=>{let a=r.isSet?b.green("✓"):b.dim("✗"),l=r.legacyName&&r.legacyIsSet?`${r.legacyName} ${b.green("✓")}`:r.legacyName??"";return[r.name,a,l]});return m2({headers:t,rows:e})}function ia(n){let t=[];if(n.totalBlocked===0)t.push("Recent Activity"),t.push(" No blocked commands in the last 7 days"),t.push(" Tip: This is normal for new installations");else t.push(`Recent Activity · last 7 days (${n.totalBlocked} blocked / ${n.sessionCount} sessions)`),t.push(Es(n.recentEntries));if(n.unreadable>0)t.push(` Warning: ${n.unreadable} audit log ${n.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return t.join(`
15
- `)}function Es(n){let t=["Time","Command"],e=n.map((r)=>{let a=z(r.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),l=a.length>40?`${a.slice(0,37)}...`:a;return[r.relativeTime,l]});return m2({headers:t,rows:e})}function La(n){let t=[];if(t.push("Update Check"),n.latestVersion===null&&!n.error)return t.push(Un([["Status",b.dim("Skipped")],["Installed",n.currentVersion]])),t.join(`
16
- `);if(n.error)return t.push(Un([["Status",`${b.yellow("⚠")} Error`],["Installed",n.currentVersion],["Error",b.dim(n.error)]])),t.join(`
17
- `);if(n.updateAvailable)return t.push(Un([["Status",`${b.yellow("⚠")} Update Available`],["Current",n.currentVersion],["Latest",b.green(n.latestVersion??"")]])),t.push(""),t.push(" Run: bunx cc-safety-net@latest doctor"),t.push(" Or: npx cc-safety-net@latest doctor"),t.join(`
18
- `);return t.push(Un([["Status",`${b.green("✓")} Up to date`],["Version",n.currentVersion]])),t.join(`
19
- `)}function Un(n){return m2({rows:n})}function pa(n){let t=[];return t.push("System Info"),t.push(Ps(n)),t.join(`
20
- `)}function Ps(n){let t=["Component","Version"],e=(l)=>{if(l===null)return b.dim("not found");return l},a=[{label:"cc-safety-net",value:n.version},{label:"Claude Code",value:n.claudeCodeVersion},{label:"Amp Code",value:n.ampVersion},{label:"Antigravity CLI",value:n.antigravityCliVersion},{label:"Codex",value:n.codexCliVersion},{label:"Cursor",value:n.cursorVersion},{label:"Gemini CLI",value:n.geminiCliVersion},{label:"GitHub Copilot CLI",value:n.copilotCliVersion},{label:"Hermes Agent",value:n.hermesAgentVersion},{label:"Kimi Code",value:n.kimiCodeVersion},{label:"OpenClaw",value:n.openClawVersion},{label:"OpenCode",value:n.openCodeVersion},{label:"Pi",value:n.piCliVersion},{label:"Node.js",value:n.nodeVersion},{label:"npm",value:n.npmVersion},{label:"Bun",value:n.bunVersion},{label:"Platform",value:n.platform}].map((l)=>[l.label,e(l.value)]);return m2({headers:t,rows:a})}function ua(n){if(n.findings.length===0)return b.green(`
21
- No findings from inspected doctor facts.`);let t={error:n.findings.filter((l)=>l.severity==="error").length,warning:n.findings.filter((l)=>l.severity==="warning").length,info:n.findings.filter((l)=>l.severity==="info").length},e=["error","warning","info"].filter((l)=>t[l]>0).map((l)=>`${t[l]} ${l}`),r=n.findings.length===1?"finding":"findings",a=`
22
- ${n.findings.length} ${r}: ${e.join(", ")}.`;if(t.error>0)return b.red(a);if(t.warning>0)return b.yellow(a);return b.blue(a)}import{lstatSync as Is}from"node:fs";import{dirname as pe}from"node:path";function ue(n,t){try{let e=Is(t);if(e.isSymbolicLink())return{kind:n,path:t,status:"unsafe",issues:["symlink"]};if(!e.isDirectory())return{kind:n,path:t,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:n,path:t,status:"unknown",issues:[]};let r=[...e.uid!==process.getuid()?["ownership"]:[],...(e.mode&18)!==0?["permissions"]:[]];return{kind:n,path:t,status:r.length>0?"unsafe":"safe",issues:r}}catch(e){if(typeof e==="object"&&e!==null&&"code"in e&&e.code==="ENOENT")return{kind:n,path:t,status:"not-applicable",issues:[]};return{kind:n,path:t,status:"unknown",issues:[]}}}function oa(n){let t=s2();return{directories:[ue("policy",pe(pe(n))),ue("config",pe(n)),...t?[ue("audit",t)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as Ns}from"node:child_process";import{existsSync as va}from"node:fs";import{delimiter as nc,extname as tc,join as ec}from"node:path";import{stripVTControlCharacters as ba}from"node:util";var ha="2.0.6",rc=5000,ac="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function j(){return ha}function oe(n,t){let e=n[t];if(e)return e;let r=Object.keys(n).find((a)=>a.toLowerCase()===t.toLowerCase()&&!!n[a]);return r?n[r]:e}function lc(n){return(oe(n,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((t)=>t.length>0)}function dc(n,t){let e=tc(n)?[n]:[...lc(t).map((r)=>`${n}${r}`),n];if(n.includes("/")||n.includes("\\"))return e.find((r)=>va(r))??n;return(oe(t,"PATH")??"").split(nc).flatMap((r)=>e.map((a)=>ec(r,a))).find((r)=>va(r))??n}function fa(n){if(!/[\s"&|<>^]/.test(n))return n;return`"${n.replace(/"/g,'""')}"`}function f2(n,t){let[e,...r]=n,a=t[ac]==="win32"?"win32":process.platform;if(!e||a!=="win32")return{cmd:e??"",args:r};let l=dc(e,t);if(!/\.(?:bat|cmd)$/i.test(l))return{cmd:l,args:r};return{cmd:oe(t,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",fa(l),...r.map(fa)].join(" ")]}}var _2=async(n,t=rc)=>{let e=await sc(n,{timeoutMs:t});if(e.code!==0)return null;return ba(e.stdout).trim()||ba(e.stderr).trim()||null};function sc(n,t){let[e,...r]=n;if(!e)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((a)=>{try{let l=f2([e,...r],process.env),d=Ns(l.cmd,l.args,{stdio:["ignore","pipe","pipe"]}),s=!1,c="",i="";d.stdout.on("data",(v)=>{c+=v.toString()}),d.stderr.on("data",(v)=>{i+=v.toString()});let L=(v)=>{if(s)return;s=!0,clearTimeout(u),a(v)},u=setTimeout(()=>{d.kill(),L({code:null,stdout:c,stderr:i})},t.timeoutMs);d.on("close",(v)=>{L({code:v,stdout:c,stderr:i})}),d.on("error",()=>{L({code:null,stdout:c,stderr:i})})}catch{a({code:null,stdout:"",stderr:""})}})}function Q(n){if(!n)return null;let t=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(n);if(t)return t[1]??null;let e=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(n);if(e)return e[1]??null;return n.split(`
23
- `)[0]?.trim()||null}async function xn(n=_2){let[t,e,r,a,l,d,s,c,i,L,u,v,p,f,o,h,x]=await Promise.all([n(["claude","--version"]),n(["agy","--version"]),n(["opencode","--version"]),n(["codex","--version"]),n(["codex","plugin","list"]),n(["gemini","--version"]),n(["copilot","--binary-version"]),n(["hermes","--version"]),n(["kimi","--version"]),n(["openclaw","--version"]),n(["pi","--version"]),n(["cursor","--version"]),n(["amp","--version"]),n(["amp","plugins","list"],30000),n(["node","--version"]),n(["npm","--version"]),n(["bun","--version"])]);return{version:ha,claudeCodeVersion:Q(t),antigravityCliVersion:Q(e),openCodeVersion:Q(r),codexCliVersion:Q(a),codexPluginListOutput:l,geminiCliVersion:Q(d),copilotCliVersion:Q(s),hermesAgentVersion:Q(c),kimiCodeVersion:Q(i),openClawVersion:Q(L),piCliVersion:Q(u),cursorVersion:Q(v),ampVersion:Q(p),ampPluginListOutput:f,nodeVersion:Q(o),npmVersion:Q(h),bunVersion:Q(x),platform:`${process.platform} ${process.arch}`}}function ve(n,t){if(t==="dev")return!1;let e=n.split(".").map(Number),r=t.split(".").map(Number),[a=0,l=0,d=0]=e,[s=0,c=0,i=0]=r;if(a!==s)return a>s;if(l!==c)return l>c;return d>i}async function E2(){let n=j(),t=new AbortController,e=setTimeout(()=>t.abort(),3000);try{let r=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:t.signal});if(!r.ok)return{currentVersion:n,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${r.status}`};let a=await r.json(),l=ve(a.version,n);return{currentVersion:n,latestVersion:a.version,updateAvailable:l}}catch(r){return{currentVersion:n,latestVersion:null,updateAvailable:!1,error:r instanceof Error?r.message:"Network error"}}finally{clearTimeout(e)}}import*as ka from"node:readline";var $a=(n)=>`\x1B[${n}B`,cc=(n)=>`\x1B[${n}A`;var ya=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function ic(n){return new Promise((t)=>setTimeout(t,n))}function Lc(n,t,e){if(!e)return t(n);if(e.aborted)return Promise.resolve();return new Promise((r,a)=>{let l=()=>e.removeEventListener("abort",d),d=()=>{l(),r()};e.addEventListener("abort",d,{once:!0}),t(n).then(()=>{l(),r()},(s)=>{l(),a(s)})})}function $n(n,t){return n&&n>0?n:t}function On(n){return Math.max(0,Math.min(1,n))}function P2(n){return Math.max(0,Math.min(255,Math.round(n)))}function be(n){return n<=0.0031308?12.92*n:1.055*n**0.4166666666666667-0.055}function pc(n,t,e){let r=e*Math.PI/180,a=t*Math.cos(r),l=t*Math.sin(r),d=(n+0.3963377774*a+0.2158037573*l)**3,s=(n-0.1055613458*a-0.0638541728*l)**3,c=(n-0.0894841775*a-1.291485548*l)**3;return{blue:P2(be(On(-0.0041960863*d-0.7034186147*s+1.707614701*c))*255),green:P2(be(On(-1.2684380046*d+2.6097574011*s-0.3413193965*c))*255),red:P2(be(On(4.0767416621*d-3.3077115913*s+0.2309699292*c))*255)}}function fe(n,t){let e=(t*n*180/Math.PI%360+360)%360;return pc(0.72,0.15,e)}function ga(n,t=0.1){let e=fe(t,n);return`\x1B[38;2;${e.red};${e.green};${e.blue}m`}function uc(n,t){return{blue:P2(n.blue+(255-n.blue)*t),green:P2(n.green+(255-n.green)*t),red:P2(n.red+(255-n.red)*t)}}function Da(n,t,e){let r=Math.imul(n+2654435769,2246822507)^Math.imul(t+3266489909,668265263)^Math.imul(e+374761393,2654435761),a=r^r>>>15,l=Math.imul(a,739982445),d=l^l>>>12,s=Math.imul(d,695872825);return((s^s>>>15)>>>0)/4294967296}function oc(n,t,e){let r=Math.floor(Da(n,t,e)*ya.length);return ya[r]??"░"}function wa(n){let t=On(n);return t*t*t*(t*(t*6-15)+10)}function vc(n){if(n.length===0)return"";let t=[],e=!1,r="";for(let a of n){let l=`${a.red};${a.green};${a.blue}`;if(a.bold!==e)t.push(a.bold?"\x1B[1m":"\x1B[22m"),e=a.bold;if(l!==r)t.push(`\x1B[38;2;${l}m`),r=l;t.push(a.character)}return`${t.join("")}\x1B[22m\x1B[39m`}function bc(n,t,e,r,a){return n.map((l,d)=>({...fe(e,r+t+d/a),bold:!1,character:l}))}function fc(n,t,e,r,a,l,d,s){let c=Math.max(1,r*0.75),i=Math.min(1,e/c),L=a*wa(i),u=Math.max(0,(e-c)/Math.max(1,r-c)),v=(1-wa(e/r))*s*2,p=0.35*Math.max(0,1-u*2),f=i>=1,o=Math.min(n.length,Math.ceil(L+2+1));return n.slice(0,o).map((h,x)=>{let w=fe(l,d+t+x/s+v),y=x+Da(t,x,7919)*2-1;if(y>L+2)return{...w,bold:!1,character:" "};let J=L-y,Z2=0.8*Math.exp(-(J*J)/12.5),ln=Math.min(0.9,Z2+p),jt=!f&&y>L-4;return{...uc(w,ln),bold:ln>0.3,character:jt?oc(t,x,e):h}})}function xa(n){return`\x1B[?2026h${n.map((t,e)=>`\x1B8${e>0?$a(e):""}${vc(t)}`).join("")}\x1B[?2026l`}async function he(n,t={}){if(!n)return;let e=t.output??process.stdout,r=t.sleep??ic,a=$n(t.frequency,0.1),l=t.seed??0,d=$n(t.speed,40),s=$n(t.spread,3),c=$n(t.frameRate,60),i=Math.max(1,Math.floor($n(t.duration,12))),L=n.split(`
24
- `).map((o)=>Array.from(o)),u=Math.max(...L.map((o)=>o.length)),v=1000*i*L.filter((o)=>o.length>0).length/d,p=u>0?Math.max(1,Math.ceil(v/(1000/c))):0,f=p>0?v/p:0;e.write(`\x1B[?25l${L.length>1?`${`
25
- `.repeat(L.length-1)}${cc(L.length-1)}`:""}\x1B7`);try{for(let o=1;o<=p;o+=1){if(t.signal?.aborted)break;e.write(xa(L.map((h,x)=>fc(h,x,o,p,u,a,l,s)))),await Lc(f,r,t.signal)}}finally{if(e.write(xa(L.map((o,h)=>bc(o,h,a,l,s)))),e.write("\x1B8"),L.length>1)e.write($a(L.length-1));e.write(`
26
- \x1B[0m\x1B[?25h`)}}var ma=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
27
- `);function hc(n){return Boolean(n.isTTY)}async function gn(n={}){let t=n.output??process.stdout;if(!hc(t))return;let e=n.input??process.stdin,r={duration:n.duration,frequency:n.frequency,output:t,seed:n.seed??Math.random()*8192,sleep:n.sleep,speed:n.speed,spread:n.spread};if(!e.isTTY||typeof e.setRawMode!=="function"){await he(ma,r);return}let a=new AbortController,l=e.readableFlowing===!0,d=e.isRaw===!0,s=!1,c=(i,L)=>{if(L.ctrl&&L.name==="c")s=!0;if(s||L.name==="return"||L.name==="enter")a.abort()};ka.emitKeypressEvents(e),e.on("keypress",c),e.setRawMode(!0),e.resume();try{await he(ma,{...r,signal:a.signal})}finally{if(e.off("keypress",c),e.setRawMode(d),!l)e.pause()}if(!s)return;if(n.onInterrupt){n.onInterrupt();return}process.kill(process.pid,"SIGINT")}var qa="\r\x1B[2K",yc="\x1B[?25l",wc="\x1B[39m",xc="\x1B[?25h",$c=100,gc=0.55,Dc=80,ja=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function mc(n){return new Promise((t)=>setTimeout(t,n))}async function Tn(n,t={}){let e=t.output??process.stdout;if(!e.isTTY)return n;let r=t.sleep??mc,a=!1,l=n.then((s)=>{return a=!0,s},(s)=>{throw a=!0,s});if(await Promise.race([l.then(()=>!0),r($c).then(()=>!1)]))return l;e.write(yc);try{for(let s=0;!a;s+=1)e.write(`${qa}${ga(s*gc)}${ja[s%ja.length]}${wc} ${t.loadingMessage??"Loading…"}`),await Promise.race([l,r(Dc)]);return await l}finally{e.write(`${qa}${xc}`)}}async function Dn(n,t,e,r={}){let a=t();if(n)await e();if(n&&a.ready)await Tn(a.ready,r);return a.finish()}import{homedir as Yi}from"node:os";import{stripVTControlCharacters as kc}from"node:util";var _n="amp plugins list",qc=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function Fa(n){if(!n.ampPluginListOutput)return{platform:"amp",status:"n/a"};let t=kc(n.ampPluginListOutput).split(`
28
- `).map((e)=>qc.exec(e)?.[1]).find((e)=>e!==void 0);if(!t)return{platform:"amp",status:"n/a"};if(t!=="active")return{platform:"amp",status:"disabled",method:_n,configPath:_n,errors:[`Amp personal plugin cc-safety-net is ${t}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:_n,configPath:_n}}import{existsSync as Fc,readFileSync as zc}from"node:fs";import{join as jc}from"node:path";function mn(n){return jc(n,".gemini","config","hooks.json")}var Bc=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Jc(n){if(!n||typeof n!=="object"||Array.isArray(n))return[];return Object.values(n).flatMap((t)=>{if(!t||typeof t!=="object"||Array.isArray(t))return[];let e=t,r=e.PreToolUse;if(!Array.isArray(r))return[];return r.flatMap((a)=>{if(!a||typeof a!=="object"||Array.isArray(a))return[];let l=a.hooks;if(!Array.isArray(l))return[];return l.flatMap((d)=>{if(!d||typeof d!=="object"||Array.isArray(d))return[];let s=d.command;if(typeof s!=="string"||!Bc.test(s))return[];return[{command:s,enabled:e.enabled!==!1}]})})})}function za(n){let t=mn(n.homeDir);if(!Fc(t))return{platform:"antigravity-cli",status:"n/a",configPath:t};let e;try{e=Jc(JSON.parse(zc(t,"utf-8")))}catch(r){return{platform:"antigravity-cli",status:"n/a",configPath:t,errors:[`Failed to parse Antigravity hooks config ${t}: ${r instanceof Error?r.message:String(r)}`]}}if(e.some((r)=>r.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:t};if(e.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:t};return{platform:"antigravity-cli",status:"n/a",configPath:t}}import{join as Ba}from"node:path";import{existsSync as Zc,lstatSync as Qc,readFileSync as Xc}from"node:fs";function n2(n,t=(e)=>e){if(!Zc(n))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(t(Xc(n,"utf-8")))}}catch{return{kind:"unreadable"}}}function S(n){try{return Qc(n)}catch{return}}function En(n,t){let e=S(t);if(!e)return{platform:n,status:"n/a",configPath:t};if(!e.isSymbolicLink()&&e.isDirectory())return;return{platform:n,status:"n/a",configPath:t,errors:[`${t} is a symlink or not a directory; move or remove it before installing`]}}function $(n,t){return typeof n==="object"&&n!==null?n[t]:void 0}var ye="cc-safety-net@cc-marketplace";function Ja(n){return Ba(n,".claude","plugins","installed_plugins.json")}function Za(n,t){let e=$($(n,"plugins"),t);return Array.isArray(e)&&e.length>0}function Pn(n,t){let e=n2(Ja(n));return e.kind==="ok"&&Za(e.value,t)}function we(n){let t=Ja(n),e=n2(t);if(e.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(e.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!Za(e.value,ye))return{platform:"claude-code",status:"n/a"};let r=Ba(n,".claude","settings.json"),a=n2(r);if(a.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(a.kind==="ok"&&$($(a.value,"enabledPlugins"),ye)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:r,errors:[`${ye} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:t}}function Qa(n){return we(n.homeDir)}function Xa(n){if(!n.codexPluginListOutput)return{platform:"codex",status:"n/a"};let t=n.codexPluginListOutput.split(`
29
- `).find((e)=>e.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!t)return{platform:"codex",status:"n/a"};if(!t.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list"}}import{existsSync as nt,readdirSync as Yc,readFileSync as Sc}from"node:fs";import{join as K}from"node:path";var t2="cc-safety-net@cc-marketplace",In=["cc-marketplace","cc-safety-net"],Ya=["_direct","copilot-safety-net"],Sa=["cc-marketplace","safety-net"],Ha="safety-net@cc-marketplace";function Nn(n,t){let e=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${e}([^a-z0-9-]|$)`,"m").test(n??"")}function Aa(n){return Nn(n,"cc-safety-net@cc-marketplace")}function Wa(n){return Nn(n,"cc-marketplace")}function Ra(n){return Nn(n,"copilot-safety-net")}function Ka(n){return Nn(n,"safety-net@cc-marketplace")}function R(n){let t="",e=0,r=!1,a=!1,l=-1;while(e<n.length){let d=n[e],s=n[e+1];if(a){t+=d,a=!1,e++;continue}if(d==='"'&&!r){r=!0,l=-1,t+=d,e++;continue}if(d==='"'&&r){r=!1,t+=d,e++;continue}if(d==="\\"&&r){a=!0,t+=d,e++;continue}if(r){t+=d,e++;continue}if(d==="/"&&s==="/"){while(e<n.length&&n[e]!==`
30
- `)e++;continue}if(d==="/"&&s==="*"){e+=2;while(e<n.length-1){if(n[e]==="*"&&n[e+1]==="/"){e+=2;break}e++}continue}if(d===","){l=t.length,t+=d,e++;continue}if(d==="}"||d==="]"){if(l!==-1){let c=t.slice(l+1);if(/^\s*$/.test(c))t=t.slice(0,l)+c}l=-1,t+=d,e++;continue}if(!/\s/.test(d))l=-1;t+=d,e++}return t}function xe(n){if(!n?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(n)}function Va(n,t){if(!n)return null;let e=n.match(/(\d+)\.(\d+)\.(\d+)/);if(!e)return null;let r=[Number(e[1]),Number(e[2]),Number(e[3])];for(let a=0;a<t.length;a++){let l=r[a]??0,d=t[a]??0;if(l!==d)return l>d}return!0}function Hc(n){return Va(n,[0,0,422])}function Ac(n){return Va(n,[1,0,8])}function kn(n){return process.env.COPILOT_HOME||K(n,".copilot")}function ge(n){return(n.hooks?.preToolUse??[]).some((e)=>{if(e.type!=="command")return!1;return xe(e.command)||xe(e.bash)||xe(e.powershell)})}function De(n,t){try{return JSON.parse(R(Sc(n,"utf-8")))}catch(e){t?.push(`Failed to parse ${n}: ${e instanceof Error?e.message:String(e)}`);return}}function Ga(n,t){try{return Yc(n).filter((e)=>e.endsWith(".json")).sort((e,r)=>e.localeCompare(r))}catch(e){return t?.push(`Failed to read ${n}: ${e instanceof Error?e.message:String(e)}`),[]}}function Wc(n,t){if(!nt(n))return[];let e=[];for(let r of Ga(n,t)){let a=K(n,r),l=De(a,t);if(l&&ge(l))e.push(a)}return e}function $e(n,t){if(!nt(n))return;let e=De(n,t);if(!e)return;return{path:n,config:e}}function Ma(n,t,e,r){if(t){n.push(`GitHub Copilot CLI ${t} does not support ${e}; requires ${r}+`);return}n.push(`GitHub Copilot CLI version unavailable; skipping ${e} because it requires ${r}+`)}function Rc(n){let t=[n.localSettings,n.repoSettings,n.userConfig];for(let e of t){if(e?.config.disableAllHooks===!0)return e.path;if(e?.config.disableAllHooks===!1)return}return}function Kc(n,t,e,r){let a=kn(n),l=K(t,".github","hooks"),d=K(a,"hooks"),s=K(t,".github","copilot"),c=Ac(e),i=c===!0?r:void 0,L={userConfig:$e(K(a,"config.json"),i),repoSettings:$e(K(s,"settings.json"),i),localSettings:$e(K(s,"settings.local.json"),i)};if(c!==!1){let w=Rc(L);if(w){if(c===null)r.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${w} as active`);return{activeConfigPaths:[],disabledBy:w}}}let u=Wc(l,r),v=Hc(e),p=v===!0?r:void 0,f=nt(d)?Ga(d,p):[],o=[];for(let w of f){let y=K(d,w),J=De(y,p);if(J&&ge(J))o.push(y)}if(v!==!0&&o.length>0)Ma(r,e,`user hook files in ${d}`,"0.0.422"),o.length=0;let h=[],x=[L.localSettings,L.repoSettings,L.userConfig];for(let w of x){if(!w)continue;if(!ge(w.config))continue;if(c===!0){h.push(w.path);continue}Ma(r,e,"inline hook definitions in Copilot config files","1.0.8");break}return{activeConfigPaths:[...h.filter((w)=>w.endsWith("settings.local.json")),...h.filter((w)=>w.endsWith("settings.json")),...u,...h.filter((w)=>w.endsWith("config.json")),...o]}}function Ca(n){let t=[],e=Kc(n.homeDir,n.cwd,n.copilotCliVersion,t);if(e.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:e.disabledBy,configPaths:[e.disabledBy],errors:t.length>0?t:void 0};let r=kn(n.homeDir),a=K(r,"installed-plugins",...In),l=nt(a),d=K(r,"settings.json"),s=n2(d,R);if(l&&s.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(l&&s.kind==="ok"&&$($(s.value,"enabledPlugins"),t2)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:d,errors:[`${t2} is installed but not enabled in Copilot CLI`]};if(l||e.activeConfigPaths.length>0){let c=l,i=e.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:c?"plugin config":"hook config",configPath:i??(c?a:void 0),configPaths:e.activeConfigPaths.length>0?e.activeConfigPaths:void 0,errors:t.length>0?t:void 0}}return{platform:"copilot-cli",status:"n/a",errors:t.length>0?t:void 0}}import{existsSync as Pc,readFileSync as Ic}from"node:fs";import{existsSync as Ua,mkdirSync as Gc,readFileSync as Cc}from"node:fs";import{dirname as Uc,join as Oc}from"node:path";import{renameSync as Mc,writeFileSync as Vc}from"node:fs";function B(n,t){let e=`${n}.${process.pid}.tmp`;Vc(e,t),Mc(e,n)}var qn="npx -y cc-safety-net hook --cursor",Oa=30;function et(n){return Oc(n,".cursor","hooks.json")}function k2(n){return typeof n==="object"&&n!==null&&!Array.isArray(n)}function me(){return{command:qn,timeout:Oa,failClosed:!0}}function tt(n){return k2(n)&&n.command===qn}function Tc(n){return Object.keys(n).length===3&&n.command===qn&&n.timeout===Oa&&n.failClosed===!0}function _c(n){try{return JSON.parse(Cc(n,"utf-8"))}catch(t){if(t instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${n}: ${t.message}`);throw t}}function Ta(n){let t=_c(n);if(!k2(t))throw Error(`Cursor hooks config ${n} must be a JSON object`);if(t.version!==1)throw Error(`Cursor hooks config ${n} must set "version": 1`);if(t.hooks!==void 0&&!k2(t.hooks))throw Error(`Cursor hooks config ${n} "hooks" must be an object`);let e=k2(t.hooks)?t.hooks.preToolUse:void 0;if(e!==void 0&&!Array.isArray(e))throw Error(`Cursor hooks config ${n} "hooks.preToolUse" must be an array`);return t}function _a(n){let t=k2(n.hooks)?n.hooks.preToolUse:void 0;return Array.isArray(t)?t:[]}function Ec(n){if(!n.some(tt))return[...n,me()];return n.reduce((t,e)=>{if(!tt(e))return t.result.push(e),t;if(!t.inserted)t.result.push(me()),t.inserted=!0;return t},{result:[],inserted:!1}).result}function Ea(n,t,e){let r=k2(t.hooks)?t.hooks:{},a={...t,hooks:{...r,preToolUse:e}};B(n,`${JSON.stringify(a,null,2)}
31
- `)}function Pa(n){let t=et(n);if(!Ua(t))return Gc(Uc(t),{recursive:!0}),B(t,`${JSON.stringify({version:1,hooks:{preToolUse:[me()]}},null,2)}
32
- `),{path:t,alreadyInstalled:!1};let e=Ta(t),r=_a(e),a=r.filter(tt);if(k2(e.hooks)&&Array.isArray(e.hooks.preToolUse)&&a.length===1&&a[0]!==void 0&&Tc(a[0]))return{path:t,alreadyInstalled:!0};return Ea(t,e,Ec(r)),{path:t,alreadyInstalled:!1}}function Ia(n){let t=et(n);if(!Ua(t))return{path:t,alreadyInstalled:!1};let e=Ta(t),r=_a(e),a=r.filter((l)=>!tt(l));if(a.length===r.length)return{path:t,alreadyInstalled:!1};return Ea(t,e,a),{path:t,alreadyInstalled:!0}}function Nc(n){if(!n||typeof n!=="object"||Array.isArray(n))return[];let t=n.hooks;if(!t||typeof t!=="object"||Array.isArray(t))return[];let e=t.preToolUse;if(!Array.isArray(e))return[];return e.filter((r)=>!!r&&typeof r==="object"&&!Array.isArray(r)&&r.command===qn)}function ni(n){let t=[];if(n.length>1)t.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let e=n[0];if(e&&e.failClosed!==!0)t.push('Managed hook is missing "failClosed": true; reinstall to repair');if(e&&e.timeout!==30)t.push('Managed hook "timeout" is not 30; reinstall to repair');return t}function Na(n){let t=et(n.homeDir);if(!Pc(t))return{platform:"cursor",status:"n/a",configPath:t};let e;try{e=JSON.parse(Ic(t,"utf-8"))}catch(l){return{platform:"cursor",status:"n/a",configPath:t,errors:[`Failed to parse Cursor hooks config ${t}: ${l instanceof Error?l.message:String(l)}`]}}let r=Nc(e);if(r.length===0)return{platform:"cursor",status:"n/a",configPath:t};let a=ni(r);return{platform:"cursor",status:"configured",method:"hook config",configPath:t,errors:a.length>0?a:void 0}}import{existsSync as ti}from"node:fs";import{join as ke}from"node:path";var qe="gemini-safety-net";function je(n){let t=ke(n,".gemini","extensions"),e=ke(t,qe);if(!ti(e))return{platform:"gemini-cli",status:"n/a"};let r=ke(t,"extension-enablement.json"),a=n2(r);if(a.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let l=a.kind==="ok"?$($(a.value,qe),"overrides"):void 0;if(Array.isArray(l)&&l.some((s)=>typeof s==="string"&&s.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:r,errors:[`${qe} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:e}}function n0(n){return je(n.homeDir)}import{readFileSync as i0}from"node:fs";import{join as L0}from"node:path";var M="cc-safety-net",t0="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent";function e0(n){return`# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent
2
+ import{$ as u1,$a as Et,A as on,Aa as Rr,B as pl,Ba as Vr,C as n2,Ca as p1,D as _,Da as Ar,E as t1,Ea as Mr,F as Ut,Fa as E,G as Mn,Ga as _t,H as Ct,Ha as r1,I as T2,Ia as e1,J as g2,Ja as P,K as a1,Ka as Yl,L as i2,La as wn,M as ge,Ma as Sl,N as v1,Na as kr,O as Gn,Oa as Hl,P as ke,Pa as Wl,Q as qe,Qa as Kl,R as k2,Ra as wt,S as Cn,Sa as Rl,T as $n,Ta as Vl,U as Dn,Ua as pe,V as ae,Va as ve,W as fn,Wa as ue,X as q2,Xa as be,Y as l1,Ya as ol,Z as p2,Za as Nr,_ as je,_a as ne,aa as Be,ab as te,b as Br,ba as Je,bb as re,c as Jr,ca as s1,cb as y2,d as V,da as le,db as m2,e as Zr,ea as Sr,eb as c2,f as Vt,fa as se,fb as ee,g as Y,ga as de,gb as A,h as g,ha as ce,hb as xn,i as vn,ia as d1,ib as yn,j as D,ja as Hr,jb as Fe,k as D2,ka as k,kb as z2,l as Or,la as c1,lb as v2,m as A2,ma as ze,mb as We,n as un,na as L2,nb as Un,o as xl,oa as hn,p as Gt,pa as L1,q as Tr,qa as i1,r as bn,ra as Le,s as _r,sa as ie,t as n1,ta as Wr,u as Er,ua as C2,v as Pr,va as Ot,w as I,wa as Tt,x as N,xa as Ir,y as G2,ya as R2,z as U2,za as Xl}from"../chunks/index-hwg5anw1.js";var Ol=["-h","--help"];function J(n,t){let r=Object.entries(n.booleans??{}),e=Object.entries(n.values??{}),a=Object.fromEntries(r.map(([i])=>[i,!1])),l={},s=[],d=[],c=!1,L=-1;for(let[i,v]of t.entries()){if(i<=L)continue;if(v==="--"){s.push(...t.slice(i+1));break}if(Ol.includes(v)){c=!0;continue}let b=r.find(([,f])=>f.includes(v));if(b){a[b[0]]=!0;continue}let p=e.find(([,f])=>f.includes(v));if(p){let f=t[i+1];if(f===void 0||f.startsWith("-")){d.push(`${v} requires a value`);continue}l[p[0]]=f,L=i+1;continue}if(v.startsWith("-")){d.push(`Unknown option for ${n.label}: ${v}`);continue}if(n.positionals==="tail"){s.push(...t.slice(i));break}s.push(v)}if(n.positionals!=="list"&&n.positionals!=="tail")d.push(...s.map((i)=>`Unexpected argument for ${n.label}: ${i}`));return{flags:a,values:l,positionals:s,help:c,errors:d}}function s2(n){for(let t of n)console.error(t);return n.length>0}import{readdirSync as Zs,statSync as fe,unlinkSync as Qs}from"node:fs";import{basename as ye,dirname as Xs,join as Ys,resolve as Ss}from"node:path";function Z(n){return Array.from(n,(t)=>{let r=t.charCodeAt(0);if(r<=31||r>=127&&r<=159)return`\\x${r.toString(16).padStart(2,"0")}`;return t}).join("")}var Ht=(n)=>{let t=Date.now()-new Date(n).getTime();if(!Number.isFinite(t))return"";let r=Math.floor(t/60000),e=Math.floor(r/60),a=Math.floor(e/24);if(a>0)return`${a}d ago`;if(e>0)return`${e}h ago`;if(r>0)return`${r}m ago`;return"just now"},H2=(n)=>{let t=(n??"").trim().split(/\s+/).filter((a)=>a&&!/^[A-Za-z_][A-Za-z0-9_]*=/.test(a)),r=t[0]?.split("/").pop();if(!r)return null;let e=t[1];return e&&/^[a-z][a-z0-9-]*$/.test(e)?`${r} ${e}`:r};import{existsSync as Tl,readdirSync as _l,readFileSync as El}from"node:fs";import{join as Pl}from"node:path";function f2(n,t){try{return _l(n,{withFileTypes:!0,encoding:"utf8"}).flatMap((r)=>{let e=Pl(n,r.name);if(r.isDirectory())return f2(e,t);if(r.name.endsWith(".jsonl"))return[e];return[]})}catch{if(t&&Tl(n))t.count++;return[]}}function Wt(n){let t=(a)=>`${a.sessionId}
3
+ ${H2(a.segment||a.command)}`,r=n.filter((a)=>a.decision!=="allow"),e=r.filter((a)=>a.sessionId).reduce((a,l)=>a.set(t(l),(a.get(t(l))??0)+1),new Map);return new Set(r.filter((a)=>a.failureStage||(e.get(t(a))??0)>=2))}function pn(n,t){try{return El(n,"utf-8").split(`
4
+ `).filter(Boolean).flatMap((r)=>{try{return[JSON.parse(r)]}catch{if(t)t.count++;return[]}})}catch{if(t)t.count++;return[]}}import{resolve as gs}from"node:path";var Il=["AKIA","ASIA","ghp_","gho_","ghu_","ghs_","ghr_","github_pat_","glpat-","xox","npm_","pypi-","rk_","sk-","sk_","gsk_","xai-","pplx-","bastn_","tgp_v1_","flp_","wfr_","fw_","fwp_","tp-","psk-"];function Qr(n){let t=0,r={allocateSegment(){return t++},getNextSegmentIndex(){return t},recordGlobal(e){n.record({kind:"step",scope:"global",step:e})},recordSegment(e,a=r.currentSegmentIndex){if(a===void 0)return;n.record({kind:"step",scope:"segment",segmentIndex:a,step:e})}};return r}function Xr(n={}){let t=[],r=n.maxEvents??512,e={maxTextLength:n.maxTextLength??2048,maxListLength:n.maxListLength??128,maxObjectProperties:n.maxObjectProperties??n.maxListLength??128,maxDepth:n.maxDepth??16},a=0,l,s=new Set;return{record(d){if(l)return;try{if(!d||t.length>=r){a++;return}t.push(Rt(Nl(d,e,s)))}catch{a++}},finish(d){if(l)return l;try{l=Rt({events:Object.freeze(t),droppedEvents:a,terminal:ns(d,e,s)})}catch{a++,l=Object.freeze({events:Object.freeze(t),droppedEvents:a,terminal:Object.freeze({result:"blocked",reason:"trace unavailable".slice(0,e.maxTextLength),segment:"trace unavailable".slice(0,e.maxTextLength)})})}return l}}}function Nl(n,t,r){if(n.kind!=="step")throw TypeError("invalid trace event");let{scope:e,step:a}=n;Rn(a,r,t);let l=W2(a,t,r);if(e==="global")return{kind:"step",scope:"global",step:l};if(e!=="segment")throw TypeError("invalid trace event scope");return{kind:"step",scope:"segment",segmentIndex:n.segmentIndex,step:l}}function ns(n,t,r){let e=n.result;if(e==="allowed")return Object.freeze({result:"allowed"});if(e!=="blocked")throw TypeError("invalid trace terminal");let a=n.ruleId;return Object.freeze({result:"blocked",reason:W2(n.reason,t,r),segment:W2(n.segment,t,r),...a?{ruleId:W2(a,t,r)}:{}})}function Rn(n,t,r,e=0,a=new WeakSet){if(typeof n==="string"){let d=n.slice(0,r.maxTextLength);if(!Vt(d))return;for(let c of Zr(d))for(let L of c.match(/[^\s"'()$]+/g)??[])t.add(Yr(L));return}if(!n||typeof n!=="object"||e>=r.maxDepth||a.has(n))return;if(a.add(n),Array.isArray(n)){let d=Math.min(n.length,r.maxListLength);for(let c=0;c<d;c++)Rn(n[c],t,r,e+1,a);return}let l=0,s=new Set;for(let d in n){if(!Object.hasOwn(n,d))continue;if(l>=r.maxObjectProperties)break;l++,Rn(d,t,r);let c=Kt(d,r,t);if(s.has(c))continue;s.add(c),Rn(n[d],t,r,e+1,a)}}function W2(n,t,r,e=0,a=new WeakSet){if(typeof n==="string")return Kt(n,t,r);if(!n||typeof n!=="object")return n;if(e>=t.maxDepth)return;if(a.has(n))return;if(a.add(n),Array.isArray(n)){let d=[],c=Math.min(n.length,t.maxListLength);for(let L=0;L<c;L++)d.push(W2(n[L],t,r,e+1,a));return d}let l={},s=0;for(let d in n){if(!Object.hasOwn(n,d))continue;if(s>=t.maxObjectProperties)break;s++;let c=Kt(d,t,r);if(Object.hasOwn(l,c))continue;Object.defineProperty(l,c,{value:W2(n[d],t,r,e+1,a),enumerable:!0,configurable:!0,writable:!0})}return l}function Kt(n,t,r){let e=n.slice(0,t.maxTextLength),a=Vt(e)?Jr(e):e,l=r.size>0?rs(a,r):a;return(ts(l)?Br(l):l).slice(0,t.maxTextLength)}function ts(n){return n.includes("PRIVATE KEY")||n.includes("://")||n.includes("eyJ")||n.includes(":")&&/(?:authorization|cookie|x-api-key|api-key|(?:^|\s)(?:-u|--user)(?:\s|=))/i.test(n)||n.length>=14&&Il.some((t)=>n.includes(t))||n.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(n)}function rs(n,t){return n.replace(/[^\s"'()$]+/g,(r)=>t.has(Yr(r))?"<redacted>":r)}function Yr(n){let t=2166136261,r=2166136261;for(let e=0;e<n.length;e++)t=Math.imul(t^n.charCodeAt(e),16777619),r=Math.imul(r^n.charCodeAt(n.length-e-1),16777619);return`${t>>>0}:${r>>>0}:${n.length}`}function Rt(n){if(n&&typeof n==="object"&&!Object.isFrozen(n)){for(let t of Object.values(n))Rt(t);Object.freeze(n)}return n}function Kr(n,t,r){let e=r??Sr(),a=e.getCommandProgram(n,t.shell??"auto"),l=Xr(),s=Qr(l),d=a.dialect==="powershell"?e.getCommandProgram(n,"posix"):a,c=Hr(d);s.recordGlobal({type:"parse",input:n,segments:c.map((v)=>[...v])});let L=Wr(n,{...t,analyzePartialProgram:!0,trace:s},a,e),i=s.getNextSegmentIndex();if(L&&i>0&&i<c.length)s.recordSegment({type:"segment-skipped",index:i,reason:"prior-segment-blocked"},i);return Object.freeze({decision:L,trace:l.finish(L?{result:"blocked",reason:L.reason,segment:L.evidence.find((v)=>v.kind==="command")?.segment??n,...L.ruleId?{ruleId:L.ruleId}:{}}:{result:"allowed"}),program:a})}import{resolve as es}from"node:path";function At(n){let t=Rr().safeParse(n);return{errors:t.success?[]:Ar(t.error.issues),ruleNames:new Set(Vr(n).map((r)=>r.toLowerCase()))}}function Mt(n){let t=Gr(n);if(!t.ok)return t.result;return At(t.parsed)}function Gr(n){let t=[],r=new Set;try{let e=typeof n==="string"?vn(n):n,a=D(e);if(a===null)return t.push(`File not found: ${e.path}`),{ok:!1,result:{errors:t,ruleNames:r}};if(!a.trim())return t.push("Config file is empty"),{ok:!1,result:{errors:t,ruleNames:r}};return{ok:!0,parsed:JSON.parse(a)}}catch(e){if(e instanceof Y)return t.push(e.message),{ok:!1,result:{errors:t,ruleNames:r}};let a=e instanceof Error?e.message:String(e);return t.push(e instanceof SyntaxError?"Invalid JSON":a),{ok:!1,result:{errors:t,ruleNames:r}}}}function Ur(n){return es(n??process.cwd(),".safety-net.json")}function d2(n){let t=Gr(n);if(!t.ok)return t.result;let r=Mr(t.parsed);return{errors:r.errors,ruleNames:r.sources}}import{isAbsolute as as,join as Vn,relative as ls,resolve as Cr,sep as ss}from"node:path";async function M2(n={}){let t=It(n);return ds(t,await An(t,R2()))}function ds(n,t){if(!t.ok)return t;let r=_(n),e=[...new Set(c2(r.configPath,r.lockPath,n,r.filesystemScope))];if(e.length===0)return t;return{ok:!1,errors:e,warnings:t.warnings,entries:t.entries}}async function An(n,t,r,e={}){let a=null,l=!1;try{let s=_(n),d=_t(s.configTarget);if(!d.ok)return d.result;let c=d.config;if(n.check)return us(c,s,n);a={target:s.lockTarget,content:D(s.lockTarget)};let L=Et(s.lockTarget);if(L.errors.some((h)=>h.startsWith("Unable to access ")))return{ok:!1,errors:L.errors,warnings:[],entries:[]};if(n.only&&L.errors.length>0)return{ok:!1,errors:L.errors,warnings:[],entries:[]};let i=L.errors.length>0?null:L.lock,v=n.only?Nr(c,i,n.only):{ok:!0,specs:c.rules};if(!v.ok)return v.result;if(n.only&&!i&&v.specs.length<c.rules.length)return{ok:!1,errors:[`No lockfile available for partial update; run ${Pr}`],warnings:[],entries:[]};let b=(await Ls(v.specs,(h)=>te(h,s.configDir,n,i,s.filesystemScope,t),t)).map((h)=>bs(h,i,r));for(let h of b)ys(h.content,h.entry,s.configDir,n,s.filesystemScope);let p=n.only?os(c,i,b):b.map((h)=>h.entry);l=!0,P(s.lockTarget,{version:1,rulebooks:p},void 0,e._testAfterPolicyRename);let f=new Map(b.map((h)=>[h.entry.spec,h.rulebook.rules.length])),u=hs(p,s.configDir,n,s.filesystemScope,e);return{ok:!0,errors:[],warnings:u,entries:p.map((h)=>fs(h,f))}}catch(s){if(l&&a)try{K2(a.target,a.content)}catch(d){return V2(d)}return V2(s)}}async function Pt(n,t={}){return cs(n,It(t),R2())}async function cs(n,t,r,e={}){let a=null,l=!1;try{let s=_(t),d=D(s.configTarget);a={target:s.configTarget,content:d};let c=_t(s.configTarget);if(!c.ok)return c.result;let L=c.config,i=Er(n)?await re(n,r):[{spec:n}],v=i.map((f)=>f.spec),b=[...new Set([...L.rules,...v])];if(b.length>Ot)return is();if(b.length!==L.rules.length)l=!0,P(s.configTarget,{version:1,rules:b,overrides:L.overrides??{},transparent_wrappers:L.transparent_wrappers??[]},void 0,e._testAfterPolicyRename);let p=await An(t,r,new Map(i.filter((f)=>!!f.display_ref).map((f)=>[f.spec,f.display_ref])),e);if(!p.ok)K2(s.configTarget,d);return p}catch(s){if(l&&a)try{K2(a.target,a.content)}catch(d){return V2(d)}return V2(s)}}async function Ls(n,t,r=R2()){if(n.length>Ot)throw Error(Tt);let e=Array(n.length),a=0,l,s=Array.from({length:Math.min(n.length,Ir.concurrency)},async()=>{while(!l){let d=a;if(d>=n.length)return;a++;try{e[d]=await t(n[d],d,r.controller.signal)}catch(c){if(!l)l={value:c},a=n.length,r.controller.abort(c);return}}});if(await Promise.all(s),l)throw l.value;return e}function is(){return{ok:!1,errors:[Tt],warnings:[],entries:[]}}function It(n){return{cwd:n.cwd,cacheConfigDir:n.cacheConfigDir,userConfigDir:n.userConfigDir,userConfigPath:n.userConfigPath,projectConfigPath:n.projectConfigPath,global:n.global,check:n.check,only:n.only,refresh:n.refresh}}function ps(n){return{...It(n),deleteSource:n.deleteSource}}async function Nt(n,t={}){try{return await vs(n,ps(t),{})}catch(r){return V2(r)}}async function vs(n,t,r){let e=_(t),a=E(e.configTarget);if(a.errors.length>0)return{ok:!1,errors:a.errors,warnings:[],entries:[]};if(!a.config)return{ok:!1,errors:[`No config found at ${e.configPath}`],warnings:[],entries:[]};let l=Et(e.lockTarget);if(l.errors.length>0)return{ok:!1,errors:l.errors,warnings:[],entries:[]};let s=ne(a.config.rules,l.lock,n);if(!s.ok)return s.result;let d=t.deleteSource?ws(e.configDir,s.specs,l.lock,e.filesystemScope):{ok:!0,dirs:[]};if(!d.ok)return d.result;let c=D(e.configTarget);if(c===null)return V2(Error("Rules config is unavailable."));try{P(e.configTarget,{version:1,rules:a.config.rules.filter((v)=>!s.specs.includes(v)),overrides:a.config.overrides??{},transparent_wrappers:a.config.transparent_wrappers??[]},void 0,r._testAfterPolicyRename)}catch(v){throw K2(e.configTarget,c),v}let L=await An(t,R2(),void 0,r);if(!L.ok)return K2(e.configTarget,c),L;let i=$s(d.dirs,r,e.filesystemScope);if(!i.ok){K2(e.configTarget,c);let v=await An(t,R2(),void 0,r);if(!v.ok)return{ok:!1,errors:[...i.result.errors,...v.errors],warnings:v.warnings,entries:v.entries};return i.result}return L}async function us(n,t,r){let e=ee(n,t.lockPath,t.configDir,r,r.global?"user":"project",t.filesystemScope);return{ok:e.errors.length===0&&e.warnings.length===0,errors:[...e.errors,...e.warnings],warnings:[],entries:e.entries}}function bs(n,t,r){let e=t?.rulebooks.find((l)=>l.spec===n.entry.spec&&l.kind==="github"),a=r?.get(n.entry.spec)??(e?.kind==="github"?e.display_ref:void 0);if(!a||n.entry.kind!=="github")return n;return{...n,entry:{...n.entry,display_ref:a}}}function os(n,t,r){let e=new Set(n.rules),a=new Set(t?.rulebooks.map((s)=>s.spec)??[]),l=new Map(r.map((s)=>[s.entry.spec,s.entry]));return[...(t?.rulebooks.filter((s)=>e.has(s.spec))??[]).map((s)=>l.get(s.spec)??s),...r.filter((s)=>!a.has(s.entry.spec)).map((s)=>s.entry)]}function fs(n,t){return{...n,ruleCount:t.get(n.spec)}}function ys(n,t,r,e,a){let l=Ut(t,Ct(r,e));D2(g(a,l),n)}function hs(n,t,r,e,a){let l=Ct(t,r),s=Mn(l),d=g(e,s),c=A2(d);if(!c)return[];let L=n.map((v)=>g(e,Ut(v,l))),i=c.filter((v)=>v.kind==="directory").map((v)=>({directory:g(e,Vn(s,v.name)),identity:g(e,Vn(s,v.name,_r))})).filter((v)=>!L.some((b)=>Or(v.identity,b))).map((v)=>v.directory);for(let v of i)Tr(v);return i.flatMap((v)=>{try{return Ds(v,a),[]}catch{return["Unable to prune rules policy cache safely."]}})}function ws(n,t,r,e){let a=new Map(r?.rulebooks.map((L)=>[L.spec,L])??[]),l=t.flatMap((L)=>{let i=a.get(L);if(!i)return bn.test(L)?[]:["--delete-source can only delete local rulebook sources"];return i.kind==="local-directory"?[]:["--delete-source can only delete local rulebook sources"]}),s=t.map((L)=>{let i=a.get(L);return Vn(n,i?.kind==="local-directory"?i.path:L)}),d=l.length>0?[]:s.flatMap((L)=>xs(n,L,e)),c=[...l,...d];return c.length>0?{ok:!1,result:{ok:!1,errors:c,warnings:[],entries:[]}}:{ok:!0,dirs:s}}function xs(n,t,r){let e=Cr(n),a=Cr(t),l=ls(e,a);if(l===""||l===".."||l.startsWith(`..${ss}`)||as(l))return[`Refusing to delete local rulebook source outside ${n}: ${t}`];let s=g(r,a),d=A2(s);if(!d)return[`Local rulebook source directory not found: ${t}`];let c=d.find((L)=>L.name==="rulebook.json");if(!c)return[`Local rulebook source directory is missing rulebook.json: ${t}`];if(c.kind!=="file")throw new Y(r.label);if(D(g(r,Vn(a,"rulebook.json"))),d.length>1)return[`Local rulebook source directory contains extra files: ${t}. delete manually if you really want to remove the directory.`];return[]}function $s(n,t,r){let e=n.flatMap((a)=>{try{return ms(g(r,a),t),[]}catch(l){return[`Failed to delete local rulebook source ${a}: ${l instanceof Error?l.message:String(l)}`]}});return e.length>0?{ok:!1,result:{ok:!1,errors:e,warnings:[],entries:[]}}:{ok:!0}}function Ds(n,t){if(t._testPruneRulebookCacheDir){t._testPruneRulebookCacheDir(n.path);return}Gt(n)}function ms(n,t){if(t._testDeleteLocalSourceDir){t._testDeleteLocalSourceDir(n.path);return}Gt(n)}function K2(n,t){if(t===null){un(n);return}D2(n,t)}function V2(n){return{ok:!1,errors:[n instanceof Error?n.message:String(n)],warnings:[],entries:[]}}function O2(n,t){let r=qs(t),e=Le(r),a={effectiveLevel:e.effectiveLevel,selectedPreset:r.policySnapshot.policy.safety.level??"standard",effectiveCapabilities:e.effectiveCapabilities,destructiveCommandRuleOverrides:r.policySnapshot.policy.destructiveCommandRuleOverrides},{configSource:l,configValid:s}=ks({cwd:t?.cwd,userConfigDir:t?.userConfigDir});if(!n||!n.trim())return{trace:{steps:[{type:"error",message:"No command provided"}],segments:[]},result:"allowed",configSource:l,configValid:s,...a};let d=js(n,r);if(d)return{trace:{steps:[],segments:[{index:0,steps:[{type:"rule-check",rule:d.rule,matched:!0,reason:d.reason}]}]},result:"blocked",reason:V(d.reason),segment:V(d.target),...d.ruleId?{ruleId:V(d.ruleId)}:{},configSource:l,configValid:s,...a};let c=Kr(n,r),L=c.decision,i=L?.ruleId??zs(n,r),v=fn.find((p)=>p.id===i&&p.activationCapability),b=v?e.policy.effectiveDestructiveCommandRules[v.id]:void 0;return{trace:Bs(c.trace),result:L?"blocked":"allowed",reason:L?V(L.reason):void 0,segment:L?V(L.evidence.find((p)=>p.kind==="command")?.segment??n):void 0,ruleId:L?.ruleId?V(L.ruleId):void 0,customRule:Fs(Js(L?.ruleId,r.policySnapshot)),configSource:l,configValid:s,...a,...v&&b?{ruleActivation:{id:v.id,...b}}:{}}}function ks(n){let t=I(n?.cwd),r=n?.userConfigPath??N(n),e=n2({cwd:n?.cwd,userConfigDir:n?.userConfigDir,userConfigPath:n?.userConfigPath});try{if(D(e.projectConfigTarget)!==null){if(d2(e.projectConfigTarget).errors.length===0)return{configSource:t,configValid:!0};return{configSource:t,configValid:!1}}}catch(a){if(a instanceof Y)return{configSource:t,configValid:!1};throw a}try{if(D(e.userConfigTarget)!==null){let a=d2(e.userConfigTarget);return{configSource:r,configValid:a.errors.length===0}}return{configSource:null,configValid:!0}}catch(a){if(a instanceof Y)return{configSource:r,configValid:!1};throw a}}function qs(n){let t=gs(n?.cwd??process.cwd()),r=n?.policySnapshot??A({cwd:t,userConfigDir:n?.userConfigDir}),e=L2(r.policy);return{cwd:t,effectiveCwd:t,policySnapshot:r,environment:ae(),protectedGitMetadata:ce(t),effectiveCapabilities:e.capabilities,strict:n?.strict??e.strict,paranoidRm:e.paranoidRm,paranoidInterpreters:e.paranoidInterpreters,worktreeMode:e.worktreeMode}}function js(n,t){let r=t.cwd??process.cwd(),e=le(C2("",{command:n},{kind:"command",shell:"posix"},{executionCwd:r,configCwd:r},n)),a=ve(e);if(a)return{reason:pe,target:a.target,ruleId:"policy-protection",rule:"policy-protection:findPolicyConfigMutationTargetInSemanticFacts"};let l=de(e,t.protectedGitMetadata);if(l)return{reason:se,target:l.target,ruleId:"git-metadata-protection",rule:"git-metadata-protection:findGitMetadataMutationTargetInSemanticFacts"};let s=t.policySnapshot.policy,d=s.secretProtection.enabled===!1?null:be(e,s.secretProtection,{strict:t.strict});if(d)return{reason:ue,target:d.target,ruleId:d.ruleId,rule:"secret-protection:findSensitiveTargetInSemanticFacts"};return null}function zs(n,t){let r=t.policySnapshot.policy,e=yn({...r,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...r.destructiveCommandRuleOverrides,...Object.fromEntries(fn.flatMap((a)=>a.activationCapability?[[a.id,"on"]]:[]))}},t.policySnapshot.state==="degraded"?{diagnostics:t.policySnapshot.diagnostics,reason:t.policySnapshot.reason}:void 0);return ie(n,{...t,policySnapshot:e,strict:!0,paranoidRm:!0,paranoidInterpreters:!0})?.ruleId}function Fs(n){if(!n)return;return{id:V(n.id),...n.rulebook?{rulebook:{name:V(n.rulebook.name),version:V(n.rulebook.version)}}:{},...n.source?{source:V(n.source)}:{},...n.override?{override:{type:"reason",reason:V(n.override.reason)}}:{}}}function Bs(n){let t=n.events.flatMap((e)=>e.kind==="step"&&e.scope==="global"?[e.step]:[]),r=new Map;for(let e of n.events){if(e.kind!=="step"||e.scope!=="segment")continue;let a=r.get(e.segmentIndex)??{index:e.segmentIndex,steps:[]};a.steps.push(e.step),r.set(e.segmentIndex,a)}return{steps:t,segments:[...r.values()]}}function Js(n,t){let r=n?.replace(/^custom\./,"");if(!r||!t.policy.rules.some((e)=>e.name===r))return;return t.ruleMetadata[r]??Object.freeze({id:r})}function Hs(n){let t=T2(),r=J({label:"logs",booleans:{all:["--all"],suspect:["--suspect"],json:["--json"],pruneLegacy:["--prune-legacy"],dryRun:["--dry-run"]},values:{id:["--id"],limit:["--limit"],since:["--since"],agent:["--agent"],rule:["--rule"],session:["--session"],project:["--project"]}},n);if(s2(r.errors))return null;if(r.values.id!==void 0&&!/^[a-f0-9]{16}$/.test(r.values.id))return console.error("--id must be 16 hexadecimal characters"),null;let e=r.values.limit===void 0?20:oe(r.values.limit);if(e===null)return console.error("--limit must be a positive number"),null;let a=r.values.since===void 0?Math.min(30,t):oe(r.values.since);if(a===null||a>t)return console.error(`--since must be a positive number of days no greater than ${t}`),null;let l={limit:e,limitExplicit:r.values.limit!==void 0,since:a,sinceExplicit:r.values.since!==void 0,all:r.flags.all,json:r.flags.json,suspect:r.flags.suspect,pruneLegacy:r.flags.pruneLegacy,dryRun:r.flags.dryRun,id:r.values.id,agent:r.values.agent,rule:r.values.rule,session:r.values.session,project:r.values.project===void 0?void 0:Ss(r.values.project)};if(l.id&&(l.agent!==void 0||l.rule!==void 0||l.session!==void 0||l.project!==void 0||l.suspect||l.sinceExplicit||l.limitExplicit))return console.error("--id cannot be combined with --agent, --rule, --session, --project, --suspect, --since, or --limit"),null;if(l.pruneLegacy&&(l.id!==void 0||l.agent!==void 0||l.rule!==void 0||l.session!==void 0||l.project!==void 0||l.suspect||l.all||l.sinceExplicit||l.limitExplicit))return console.error("--prune-legacy cannot be combined with --id, --agent, --rule, --session, --project, --suspect, --all, --since, or --limit"),null;if(l.dryRun&&!l.pruneLegacy)return console.error("--dry-run requires --prune-legacy"),null;return l}async function he(n,t={}){let r=Hs(n);if(!r)return 1;let e=t.logsDir??i2();if(r.pruneLegacy)return Ws(e,r.json,r.dryRun);if(!e)return console.log(r.json?"[]":r.id?`No retained audit log entry found for id ${Z(r.id)}.`:"No audit log entries found."),0;g2(e);let a={count:0},l=f2(e,a).flatMap((i)=>pn(i,a).map((v)=>({entry:v,file:i})));if(a.count>0)console.error(`warning: ${a.count} audit log ${a.count===1?"source":"sources"} could not be read; these results are incomplete`);if(r.id)return As(l,r,t.timeZone);let s=Date.now()-r.since*24*60*60*1000,d=l.filter((i)=>Ms(i,r,e,s)),c=r.suspect?Wt(d.map((i)=>i.entry)):null,L=(c?d.filter((i)=>c.has(i.entry)):d).sort((i,v)=>Date.parse(v.entry.ts)-Date.parse(i.entry.ts)).slice(0,r.limit);if(r.json)return console.log(JSON.stringify(L.map((i)=>i.entry),null,2)),0;if(L.length===0)return console.log("No audit log entries found."),0;for(let i of L)console.log(Cs(i.entry,t.timeZone));return 0}function Ws(n,t,r){let e=n?Rs(n).map((d)=>Ys(n,d)):[];if(r)return Ks(e,t);let a=[],l=0,s=0;for(let d of e){let c=fe(d,{throwIfNoEntry:!1})?.size??0,L=Vs(d);if(L){a.push(`${ye(d)}: ${L}`);continue}l++,s+=c}if(t)return console.log(JSON.stringify({removedFiles:l,removedBytes:s,failedFiles:a.length})),a.length===0?0:1;console.log(l===0&&a.length===0?"No legacy audit log files found.":`Removed ${l} legacy audit log ${l===1?"file":"files"} (${we(s)}).`);for(let d of a)console.error(`Could not remove ${Z(d)}`);if(console.log("Nested v2 audit logs were not changed."),l>0)console.log("This deletion cannot be undone.");return a.length===0?0:1}function Ks(n,t){let r=n.reduce((e,a)=>e+(fe(a,{throwIfNoEntry:!1})?.size??0),0);if(t)return console.log(JSON.stringify({dryRun:!0,files:n.length,bytes:r})),0;if(console.log(n.length===0?"No legacy audit log files found.":`Would remove ${n.length} legacy audit log ${n.length===1?"file":"files"} (${we(r)}).`),console.log("Nested v2 audit logs are not included."),n.length>0)console.log("Run the same command without --dry-run to delete them.");return 0}function Rs(n){try{return Zs(n,{withFileTypes:!0}).filter((t)=>t.isFile()&&t.name.endsWith(".jsonl")).map((t)=>t.name)}catch{return[]}}function Vs(n){try{return Qs(n),null}catch(t){return t instanceof Error?t.message:String(t)}}function we(n){let t=["B","KiB","MiB","GiB"],r=Math.min(Math.floor(Math.log2(Math.max(n,1))/10),t.length-1);return`${Math.round(n/1024**r*10)/10} ${t[r]}`}function As(n,t,r){let e=n.filter((l)=>l.entry.id===t.id);if(e.length>1)return console.error(`Multiple audit log entries found for id ${Z(t.id??"")}.`),1;if(t.json)return console.log(JSON.stringify(e.map((l)=>l.entry),null,2)),0;let a=e[0];if(!a)return console.log(`No retained audit log entry found for id ${Z(t.id??"")}.`),0;return console.log(Os(a.entry,r)),0}function Ms(n,t,r,e){if(!t.all&&n.entry.decision==="allow")return!1;if(Date.parse(n.entry.ts)<e)return!1;if(t.agent!==void 0&&n.entry.agent!==t.agent)return!1;if(t.rule!==void 0&&n.entry.ruleId!==t.rule)return!1;if(t.session!==void 0&&!Gs(n,r,t.session))return!1;if(t.project!==void 0&&!Us(n.entry.cwd,t.project))return!1;return!0}function Gs(n,t,r){if(n.entry.sessionId===r)return!0;return Xs(n.file)===t&&ye(n.file,".jsonl")===r}function Us(n,t){if(!n)return!1;return n===t||n.startsWith(`${t}/`)}function Cs(n,t){let r=Z(n.id??"-"),e=Z(n.decision??"deny"),a=n.cwd?` [${Z(n.cwd)}]`:"",l=n.segment||n.command,s=l===n.command?"":"↳ ",d=l.length>50?`${l.slice(0,50)}…`:l;return`${r.padEnd(16)} ${Z(xe(n.ts,t))} ${e.padEnd(5)} ${Z(n.agent??"-").padEnd(15)} ${Z(n.ruleId??"-").padEnd(20)} ${s}${Z(d)}${a}`}function Os(n,t){let r=(a)=>Z(a===void 0||a===null||a===""?"-":a),e=n.shape?`${n.agent??"-"} (shape: ${n.shape})`:n.agent??"-";return[`id: ${r(n.id)}`,`ts: ${r(xe(n.ts,t))}`,`decision: ${r(n.decision)}`,`agent: ${r(e)}`,`level: ${r(n.level)}`,`tool: ${r(n.toolName)}`,`rule: ${r(n.ruleId)}`,`intent: ${r(n.intent)}`,`stage: ${r(n.failureStage)}`,`error: ${r(n.errorCode)}`,`session: ${r(n.sessionId)}`,`cwd: ${r(n.cwd)}`,`version: ${r(n.v)}`,`truncated: ${r(n.truncated===!0?"yes":void 0)}`,`reason: ${r(n.reason)}`,`command: ${r(n.command)}`,`segment: ${r(n.segment)}`].join(`
5
+ `)}function xe(n,t){let r=new Date(n);if(Number.isNaN(r.getTime()))return n;return new Intl.DateTimeFormat("sv-SE",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hourCycle:"h23",timeZone:t}).format(r)}function oe(n){let t=Number(n);return Number.isFinite(t)&&t>0?t:null}var $e={name:"doctor",aliases:["--doctor"],description:"Run diagnostic checks to verify installation and configuration",usage:"doctor [options]",options:[{flags:"--json",description:"Output diagnostics as JSON"},{flags:"--skip-update-check",description:"Skip npm registry version check"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net doctor","cc-safety-net doctor --json","cc-safety-net doctor --skip-update-check"]};var De={name:"explain",description:"Show step-by-step analysis trace of how a command would be analyzed",usage:"explain [options] <command>",argument:"<command>",options:[{flags:"--json",description:"Output analysis as JSON"},{flags:"--cwd",argument:"<path>",description:"Use custom working directory"},{flags:"-h, --help",description:"Show this help"}],examples:['cc-safety-net explain "git reset --hard"','cc-safety-net explain --json "rm -rf /"','cc-safety-net explain --cwd /tmp "git status"']};var me={name:"gui",description:"Open the local policy editor GUI",usage:"gui [options]",options:[{flags:"--no-open",description:"Print the URL without opening a browser"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net gui","cc-safety-net gui --no-open"]};import{isAbsolute as Ze,relative as ad}from"node:path";var Ts=8388608;function _s(n,t){console.log(JSON.stringify(n(ke(t))))}async function Es(n){let t;try{t=(await b1(process.stdin)).trim()}catch{n({reason:"Failed to parse hook input JSON."});return}if(!t){n({reason:"Missing hook input JSON."});return}return o1(t,n,"Failed to parse hook input JSON.")}async function b1(n){let t=[],r=0;for await(let e of n){let a=typeof e==="string"?Buffer.from(e,"utf-8"):Buffer.from(e.buffer,e.byteOffset,e.byteLength);if(r+=a.byteLength,r>Ts)throw Ps(n),Error("hook input byte limit exceeded");t.push(a)}return Buffer.concat(t,r).toString("utf-8")}function Ps(n){let t=n.destroy??n.cancel;if(!t)return;try{Promise.resolve(t.call(n)).catch(()=>{})}catch{}}function o1(n,t,r){try{return JSON.parse(n)}catch{t({reason:r});return}}function W(n,t){let r=t.get(n);return r?{kind:"command",shell:r}:{kind:je(n)}}function t2(n,t,r,e){let a=n===void 0?process.cwd():n,l=typeof a==="string"&&a.trim()!==""?v2([a]):void 0;if(l)return{configCwd:l,executionCwd:l};return X(e,t,r,td(a)),null}function X(n,t,r,e){let a;try{a=u1(t)}catch(l){if(!(l instanceof p2))throw l}n(Gn({command:a,segment:e,toolName:r}))}async function Is(n){let t=await Es(n.outputDeny);if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t)){X(n.outputDeny);return}if(!n.isSupported(t))return;let r=n.getAgent?.(t)??n.agent,e=n.agent===r?void 0:n.agent,a=ed(t),l=(p,f)=>{ge(p,()=>n.getSessionId(t),{agent:r,shape:e,toolName:f,cwd:a}),n.outputDeny(p)},s=n.getToolName(t);if(typeof s!=="string"||s.trim()===""){X((p)=>l(p),rd(t));return}let d=s,c=(p)=>l(p,d),L;try{L=n.getToolInput(t,d,c)}catch(p){if(!(p instanceof p2))throw p;X(c,void 0,d);return}if(!L.ok)return;let i=n.getContext(t,L.input,d,c);if(!i)return;let v;try{v=u1(L.input)}catch(p){if(!(p instanceof p2))throw p;X(c,void 0,d);return}let b=C2(d,L.input,L.route,i,v??null);try{let p=Un(b,{guard:{auditAllowed:ze(),dependencies:n.guardDependencies},audit:{agent:r,shape:e,getSessionId:()=>n.getSessionId(t)}}),f=v1(p,{includeEvidence:!0,toolName:p.stage==="command-analysis"?void 0:d});if(f){n.outputDeny(f);return}n.outputAllow?.()}catch(p){if(!(p instanceof Fe))throw p;Ns(p);let f=v1(p.evaluation,{includeEvidence:!0,toolName:p.evaluation.stage==="command-analysis"?void 0:d});if(f)n.outputDeny(f);return}}function Ns(n){if(!hn(k.debug))return;console.error(`CC Safety Net debug: ${nd(n.stage)}: ${qe(n.cause)}`)}function nd(n){if(n==="policy-protection")return"hook policy protection failed";if(n==="config-load")return"hook config loading failed";if(n==="secret-protection")return"hook secret protection failed";return"hook analysis failed"}function td(n){return typeof n==="string"?n:void 0}function rd(n){if(!n||typeof n!=="object"||Array.isArray(n))return;if(Object.hasOwn(n,"tool_input"))return n.tool_input;let t=n.toolCall;if(t&&typeof t==="object"&&!Array.isArray(t))return t.args;return}function ed(n){if(!n||typeof n!=="object"||Array.isArray(n))return null;let t=n.cwd;if(typeof t==="string")return t;let r=n.toolCall;if(!r||typeof r!=="object"||Array.isArray(r))return null;let e=r.args;if(!e||typeof e!=="object"||Array.isArray(e))return null;let a=e.Cwd;return typeof a==="string"?a:null}async function K(n){let t=(a)=>_s(n.createDenyOutput,a),r=n.createAllowOutput;await Is({...n,outputDeny:t,outputAllow:r?()=>console.log(JSON.stringify(r())):void 0})}var ld=new Map([["run_command","auto"]]),sd=new Set(["absolutepath","directorypath","file_path","filepath","path","searchdirectory","searchpath","target_file","targetfile"]);function Qe(n){return W(n,ld)}async function Xe(){await K({agent:"antigravity-cli",createDenyOutput:(n)=>({decision:"deny",reason:n}),isSupported:()=>!0,getToolName:(n)=>n.toolCall?.name,getToolInput:(n,t)=>({ok:!0,input:pd(n.toolCall?.args,t),route:Qe(t)}),getContext:dd,getSessionId:(n)=>n.conversationId})}function dd(n,t,r,e){let l=id(n).flatMap((L)=>{let i=v2([L]);return i?[i]:[]});if(!l[0])return j2(e,t,r),null;if(r!=="run_command"){let L;try{L=cd(t,r,l)}catch(i){if(i instanceof p2)return j2(e,void 0,r),null;if(!(i instanceof k2))throw i;return j2(e,t,r),null}if(!L)return j2(e,t,r),null;return{configCwd:L,executionCwd:L,policyConfigCwds:l}}let s=n.toolCall?.args;if(!s||!Object.hasOwn(s,"Cwd"))return{configCwd:l[0],executionCwd:l[0],policyConfigCwds:l};let d=s.Cwd;if(typeof d!=="string"||d.trim()==="")return j2(e,t,r),null;let c=z2(d,l);if(c){let L=Ye(c,l);if(!L)return j2(e,t,r,d),null;return{configCwd:L,executionCwd:c,policyConfigCwds:l}}return j2(e,t,r,d),null}function cd(n,t,r){let e=Qe(t),a=[...Be(n,sd),...e.kind==="patch"?Je(n):[]].filter(Ze),l=Cn(),s=new Set(a.flatMap((d)=>{let c=Ye($n(d,Dn,l),r);return c?[c]:[]}));if(s.size>1)return null;return[...s][0]??r[0]??null}function Ye(n,t){return t.filter((r)=>Ld(n,r)).reduce((r,e)=>e.length>r.length?e:r,"")||null}function Ld(n,t){let r=ad(t,n);return r===""||!r.startsWith("..")&&!Ze(r)}function j2(n,t,r,e){let a=t&&typeof t==="object"?t.command:void 0;n(Gn({command:typeof a==="string"?a:void 0,segment:e,toolName:r}))}function id(n){if(n.workspacePaths===void 0)return[process.cwd()];let t=Array.isArray(n.workspacePaths)?n.workspacePaths.filter((r)=>typeof r==="string"&&r.trim()!==""):[];return v2(t)?t:[]}function pd(n,t){if(!n)return;if(t!=="run_command")return n;return{...n,command:typeof n.CommandLine==="string"&&n.CommandLine!==""?n.CommandLine:void 0}}var mn=[{id:"antigravity-cli",displayName:"Antigravity CLI",doctorOrder:3,runtime:{order:1,flags:["-ac","--agy-cli"],description:"Run as Antigravity CLI PreToolUse hook",legacyTopLevelFlags:[]},install:{order:2,flag:"--agy-cli",artifactKind:"hook config",probeCommand:["agy","--version"]}},{id:"claude-code",displayName:"Claude Code",doctorOrder:1,runtime:{order:2,displayName:"Coding CLI",flags:["-cc","--coding-cli"],legacyFlags:["--claude-code"],description:"Run as Coding CLI PreToolUse hook",legacyTopLevelFlags:["-cc","--claude-code"]},install:{order:3,flag:"--claude-code",artifactKind:"plugin",probeCommand:["claude","--version"]}},{id:"codex",displayName:"Codex",doctorOrder:4,install:{order:4,flag:"--codex",artifactKind:"plugin",probeCommand:["codex","--version"]}},{id:"copilot-cli",displayName:"GitHub Copilot CLI",doctorOrder:7,runtime:{order:5,flags:["-cp","--copilot-cli"],description:"Run as GitHub Copilot CLI PreToolUse hook",legacyTopLevelFlags:["-cp","--copilot-cli"]},install:{order:7,flag:"--copilot-cli",artifactKind:"plugin",probeCommand:["copilot","--binary-version"]}},{id:"gemini-cli",displayName:"Gemini CLI",doctorOrder:6,runtime:{order:4,flags:["-gc","--gemini-cli"],description:"Run as Gemini CLI BeforeTool hook",legacyTopLevelFlags:["-gc","--gemini-cli"]},install:{order:6,flag:"--gemini-cli",artifactKind:"extension",probeCommand:["gemini","--version"]}},{id:"hermes-agent",displayName:"Hermes Agent",doctorOrder:8,runtime:{order:6,flags:["-ha","--hermes-agent"],description:"Run as Hermes Agent pre_tool_call hook",legacyTopLevelFlags:[]},install:{order:8,flag:"--hermes-agent",artifactKind:"plugin",probeCommand:["hermes","--version"]}},{id:"kimi-code",displayName:"Kimi Code",doctorOrder:9,runtime:{order:7,flags:["-kc","--kimi-code"],description:"Run as Kimi Code PreToolUse hook",legacyTopLevelFlags:[]},install:{order:9,flag:"--kimi-code",artifactKind:"hook config",probeCommand:["kimi","--version"]}},{id:"openclaw",displayName:"OpenClaw",doctorOrder:10,install:{order:10,flag:"--openclaw",artifactKind:"plugin",probeCommand:["openclaw","--version"]}},{id:"opencode",displayName:"OpenCode",doctorOrder:11,install:{order:11,flag:"--opencode",artifactKind:"plugin",probeCommand:["opencode","--version"]}},{id:"pi",displayName:"Pi",doctorOrder:12,install:{order:12,flag:"--pi",artifactKind:"package",probeCommand:["pi","--version"]}},{id:"cursor",displayName:"Cursor",doctorOrder:5,runtime:{order:3,flags:["-cu","--cursor"],description:"Run as Cursor preToolUse hook",legacyTopLevelFlags:[]},install:{order:5,flag:"--cursor",artifactKind:"hook config",probeCommand:["cursor","--version"]}},{id:"amp",displayName:"Amp Code",doctorOrder:2,install:{order:1,flag:"--amp",artifactKind:"plugin",probeCommand:["amp","--version"]}}],On=mn.slice().sort((n,t)=>n.doctorOrder-t.doctorOrder).map((n)=>n.id),Se=mn.filter((n)=>("runtime"in n)).slice().sort((n,t)=>n.runtime.order-t.runtime.order).map((n)=>({id:n.id,displayName:"displayName"in n.runtime?n.runtime.displayName:n.displayName,flags:n.runtime.flags,legacyFlags:"legacyFlags"in n.runtime?n.runtime.legacyFlags:[],description:n.runtime.description,legacyTopLevelFlags:n.runtime.legacyTopLevelFlags})),G=mn.slice().sort((n,t)=>n.install.order-t.install.order).map((n)=>({id:n.id,...n.install})).map(({order:n,...t})=>t),E6=Object.fromEntries(mn.map((n)=>[n.id,n.displayName]));function j(n){return mn.find((t)=>t.id===n)?.displayName??n}import{homedir as vd}from"node:os";import{isAbsolute as He,join as f1}from"node:path";function Ke(n){if(n!==void 0&&n!==null&&!He(n))return"unknown";try{let t=Cn(),r=n?$n(n,Dn,t):void 0,e=process.env.HOME||vd(),a=[["codex",process.env.CODEX_HOME||f1(e,".codex")],["copilot-cli",process.env.COPILOT_HOME||f1(e,".copilot")],["claude-code",process.env.CLAUDE_CONFIG_DIR||f1(e,".claude")]],l=r?a.flatMap(([s,d])=>{if(!He(d))return[];return We(r,$n(d,Dn,t))?[s]:[]}):[];if(l.length===1)return l[0]??"unknown";if(l.length>1)return"unknown"}catch(t){if(t instanceof k2)return"unknown";return"unknown"}if(process.env.CLAUDECODE==="1"||Boolean(process.env.CLAUDE_CODE_ENTRYPOINT))return"claude-code";return"unknown"}var y1="PreToolUse",Re="BeforeTool",Ve="pre_tool_call",h1="PreToolUse";var ud=new Map([["Bash","posix"],["PowerShell","powershell"]]);function bd(n){return W(n,ud)}async function Ae(){await K({agent:"claude-code",getAgent:(n)=>Ke(n.transcript_path),createDenyOutput:(n)=>({hookSpecificOutput:{hookEventName:y1,permissionDecision:"deny",permissionDecisionReason:n}}),isSupported:(n)=>n.hook_event_name===y1,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:bd(t)}),getContext:(n,t,r,e)=>t2(n.cwd,t,r,e),getSessionId:(n)=>n.session_id})}var od=new Map([["bash","auto"],["Bash","auto"],["powershell","powershell"],["PowerShell","powershell"]]);function fd(n){return W(n,od)}async function Me(){await K({agent:"copilot-cli",createDenyOutput:(n)=>({permissionDecision:"deny",permissionDecisionReason:n}),isSupported:()=>!0,getToolName:(n)=>n.toolName,getToolInput:(n,t,r)=>{if(typeof n.toolArgs!=="string")return r({reason:"Failed to parse toolArgs JSON."}),{ok:!1};let e=o1(n.toolArgs,r,"Failed to parse toolArgs JSON.");if(e===void 0)return{ok:!1};return{ok:!0,input:e,route:fd(t)}},getContext:(n,t,r,e)=>t2(n.cwd,t,r,e),getSessionId:(n)=>typeof n.sessionId==="string"&&n.sessionId.trim()?n.sessionId:void 0})}var yd=new Map([["Shell","auto"]]);function hd(n){return W(n,yd)}async function Ge(){await K({agent:"cursor",createDenyOutput:(n)=>({permission:"deny",user_message:n,agent_message:n}),createAllowOutput:()=>({permission:"allow"}),isSupported:()=>!0,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:hd(t)}),getContext:wd,getSessionId:(n)=>n.conversation_id})}function wd(n,t,r,e){let a=xd(n);if(!a[0])return X(e,t,r),null;let l=z2(Dd(n.cwd),a);if(!l)return X(e,t,r,typeof n.cwd==="string"?n.cwd:void 0),null;if(t===null||typeof t!=="object"||Array.isArray(t))return{configCwd:l,executionCwd:l,policyConfigCwds:a};if(!Object.hasOwn(t,"working_directory"))return{configCwd:l,executionCwd:l,policyConfigCwds:a};let s=t.working_directory;if(typeof s!=="string"||s.trim()==="")return X(e,t,r),null;let d=z2(s,a);if(!d)return X(e,t,r,s),null;return{configCwd:l,executionCwd:d,policyConfigCwds:a}}function xd(n){return $d(n).flatMap((t)=>{let r=v2([t]);return r?[r]:[]})}function $d(n){if(n.workspace_roots===void 0)return typeof n.cwd==="string"&&n.cwd.trim()!==""?[n.cwd]:[];if(!Array.isArray(n.workspace_roots))return[];return n.workspace_roots.filter((t)=>typeof t==="string"&&t.trim()!=="")}function Dd(n){return typeof n==="string"&&n.trim()!==""?n:"."}var md=new Map([["run_shell_command","auto"]]);function gd(n){return W(n,md)}async function Ue(){await K({agent:"gemini-cli",createDenyOutput:(n)=>({decision:"deny",reason:n,systemMessage:n}),isSupported:(n)=>n.hook_event_name===Re,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:gd(t)}),getContext:(n,t,r,e)=>t2(n.cwd,t,r,e),getSessionId:(n)=>n.session_id})}import{resolve as kd}from"node:path";var qd=new Map([["terminal","posix"]]);async function Ce(){await K({agent:"hermes-agent",createDenyOutput:(n)=>({action:"block",message:n}),isSupported:(n)=>n.hook_event_name===Ve,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:W(t,qd)}),getContext:jd,getSessionId:(n)=>n.session_id})}function jd(n,t,r,e){let a=t2(n.cwd,t,r,e);if(!a)return null;if(!t||typeof t!=="object"||Array.isArray(t))return a;if(!Object.hasOwn(t,"workdir"))return a;let l=t.workdir;if(typeof l!=="string"||l.trim()==="")return X(e,t,r),null;let s=v2([kd(a.configCwd,l)]);if(!s)return X(e,t,r,l),null;return{...a,executionCwd:s}}var Oe=new Map([["Bash","posix"]]);function zd(n){return W(n,Oe)}async function Te(){await K({agent:"kimi-code",createDenyOutput:(n)=>({hookSpecificOutput:{hookEventName:h1,permissionDecision:"deny",permissionDecisionReason:n}}),isSupported:(n)=>n.hook_event_name===h1,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:zd(t)}),getContext:(n,t,r,e)=>{let a=t2(n.cwd,t,r,e);if(!a)return null;let l=n.tool_input;if(!Oe.has(r)||!l||!Object.hasOwn(l,"cwd"))return a;let s=l.cwd;if(typeof s!=="string"||s.trim()==="")return X(e,t,r),null;let d=z2(s,[a.configCwd]);if(!d)return X(e,t,r,s),null;return{configCwd:a.configCwd,executionCwd:d}},getSessionId:(n)=>n.session_id})}var Fd={"antigravity-cli":Xe,"claude-code":Ae,"copilot-cli":Me,cursor:Ge,"gemini-cli":Ue,"hermes-agent":Ce,"kimi-code":Te},_2=Se.map((n)=>({...n,run:Fd[n.id]}));function _e(n){let t=J({label:"hook",booleans:Object.fromEntries(_2.map((e)=>[e.id,[...e.flags,...e.legacyFlags]]))},n);if(t.errors.length>0)return;let r=_2.filter((e)=>t.flags[e.id]);return r.length===1?r[0]:void 0}function Ee(n){return _2.find((t)=>t.legacyTopLevelFlags.some((r)=>r===n))}var Bd=_2.map((n)=>({flags:n.flags.join(", "),description:n.description})),Jd=_2.flatMap((n)=>n.flags.map((t)=>`cc-safety-net hook ${t}`)),Pe={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Bd,{flags:"-h, --help",description:"Show this help"}],examples:Jd};var Ie={name:"install",description:"Install CC Safety Net into a coding agent CLI",usage:"install [TARGET_FLAG]",options:[...G.map((n)=>({flags:n.flag,description:`Install ${j(n.id)} ${n.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net install",...G.map((n)=>`cc-safety-net install ${n.flag}`)]},Ne={name:"uninstall",description:"Uninstall CC Safety Net from a coding agent CLI",usage:"uninstall [TARGET_FLAG]",options:[...G.map((n)=>({flags:n.flag,description:`Uninstall ${j(n.id)} ${n.artifactKind}`})),{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net uninstall",...G.map((n)=>`cc-safety-net uninstall ${n.flag}`)]},na={name:"update",description:"Update every installed CC Safety Net integration to the latest version",usage:"update",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net update"]};var ta={name:"logs",description:"Browse audit log entries recorded by hooks",usage:"logs [options]",options:[{flags:"--id",argument:"<id>",description:"Show one entry from retained history by its 16-character id (not guaranteed once it is older than the configured retention)"},{flags:"--limit",argument:"<n>",description:"Maximum entries to print",default:"20"},{flags:"--since",argument:"<days>",description:"Only include entries newer than this many days (max: the configured audit retention, 1-365)",default:"30"},{flags:"--agent",argument:"<name>",description:"Filter by agent name"},{flags:"--rule",argument:"<ruleId>",description:"Filter by rule id"},{flags:"--session",argument:"<id>",description:"Filter by session id"},{flags:"--project",argument:"<path>",description:"Filter by project path"},{flags:"--suspect",description:"Only denials that look like false positives"},{flags:"--all",description:"Include allow entries"},{flags:"--prune-legacy",description:"Permanently delete all legacy root-level logs; nested logs are untouched"},{flags:"--dry-run",description:"With --prune-legacy, report what would be deleted and delete nothing"},{flags:"--json",description:"Output entries as JSON"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net logs --id 3fa9c2d1a70e8b42","cc-safety-net logs --agent claude-code","cc-safety-net logs --project . --since 7","cc-safety-net logs --suspect --since 7","cc-safety-net logs --json","cc-safety-net logs --prune-legacy --dry-run","cc-safety-net logs --prune-legacy"]};var E2={name:"rule",description:"Manage CC Safety Net rule config and rulebook sources",usage:"rule <subcommand>",subcommands:[{usage:"init [--example]",description:"Create inert rule config"},{usage:"add <source>",description:"Add a rulebook source and sync"},{usage:"remove <source>",description:"Remove a rulebook source and sync"},{usage:"update [source]",description:"Refresh rulebook lock/cache state"},{usage:"sync",description:"Sync configured rulebooks"},{usage:"list",description:"List active rulebooks"},{usage:"wrapper add <command>",description:"Trust a transparent command wrapper"},{usage:"wrapper remove <command>",description:"Remove a transparent command wrapper"},{usage:"wrapper list",description:"List transparent command wrappers"},{usage:"migrate [--cleanup]",description:"Migrate legacy inline rules"},{usage:"doc",description:"Print the rulebook authoring guide"},{usage:"verify",description:"Validate rule config files"}],options:[{flags:"-g, --global",description:"Use user-scope rule config"},{flags:"--check",description:"Check without changing lock/cache state"},{flags:"--cleanup",description:"Delete legacy files after rule migrate verifies them"},{flags:"--delete-source",description:"Delete clean local source directory on remove"},{flags:"--example",description:"Create an inactive example rulebook with rule init"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net rule init","cc-safety-net rule init --example","cc-safety-net rule wrapper add rtk","cc-safety-net rule add project-rules","cc-safety-net rule sync","cc-safety-net rule migrate --cleanup","cc-safety-net rule verify"]};var ra={name:"status",description:"Show what the runtime is enforcing right now",usage:"status",options:[{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net status"]};var ea={name:"statusline",description:"Print status line with mode indicators for shell integration",usage:"statusline --claude-code",options:[{flags:"-cc, --claude-code",description:"Print status line for Claude Code"},{flags:"-h, --help",description:"Show this help"}],examples:["cc-safety-net statusline -cc","cc-safety-net statusline --claude-code"]};var aa=[ra,$e,ta,De,E2,Ie,na,Ne,Pe,me,ea];function Zd(n){return n.aliases??[]}function Qd(n){return!n.hidden}function Tn(n){let t=n.toLowerCase();return aa.find((r)=>r.name.toLowerCase()===t||Zd(r).some((e)=>e.toLowerCase()===t))}function la(){return aa.filter(Qd)}import{readFileSync as Xd}from"node:fs";import{basename as Yd}from"node:path";function _n(n=7,t=i2()){let r=Date.now()-n*24*60*60*1000,e=[],a=new Set,l=0,s,d,c,L;if(t)g2(t);let i={count:0},v=t?f2(t,i):[];for(let p of v)try{let u=Xd(p,"utf-8").trim().split(`
6
+ `).filter(Boolean);for(let h of u)try{let w=JSON.parse(h);if(w.decision==="allow")continue;let $=new Date(w.ts).getTime();if($>=r){if(l++,a.add(w.sessionId??Yd(p,".jsonl")),d===void 0||$<=d)s=w.ts,d=$;if(L===void 0||$>L)c=w.ts,L=$;Sd(e,w,$)}}catch{i.count++}}catch{i.count++}let b=e.map((p)=>({timestamp:p.ts,command:p.command,reason:p.reason,relativeTime:Ht(new Date(p.ts))}));return{totalBlocked:l,sessionCount:a.size,recentEntries:b,oldestEntry:s,newestEntry:c,unreadable:i.count}}function Sd(n,t,r){let e=n.findIndex((a)=>r>new Date(a.ts).getTime());if(e===-1){if(n.length<3)n.push(t);return}if(n.splice(e,0,t),n.length>3)n.pop()}import{dirname as Hd}from"node:path";function sa(n,t,r,e,a){let l;try{if(D(e)===null)return{path:n,exists:!1,valid:!1,ruleCount:0};l=d2(e),l.errors.push(...c2(n,t,{userConfigDir:r},a))}catch(s){if(!(s instanceof Y))throw s;l={errors:[s.message],ruleNames:new Set}}return{path:n,exists:!0,valid:l.errors.length===0,ruleCount:l.ruleNames.size,...l.errors.length>0?{errors:l.errors}:{}}}function Wd(n,t){return{source:t,name:n.name,command:n.command,subcommand:n.subcommand,blockArgs:[...n.block_args],reason:n.reason}}function da(n,t){let r=t?.userConfigPath??N(),e=t?.projectConfigPath??I(n),a=Hd(r),l=y2({cwd:n,userConfigPath:r,projectConfigPath:e,userConfigDir:a}),s=n2({cwd:n,userConfigPath:r,projectConfigPath:e,userConfigDir:a}),d=new Map(l.rulebooks.flatMap((c)=>c.rules.map((L)=>[L,c.source])));return{userConfig:sa(r,G2({userConfigPath:r}),a,s.userConfigTarget,s.userScope),projectConfig:sa(e,U2(e),a,s.projectConfigTarget,s.projectScope),effectiveRules:l.rules.map((c)=>Wd(c,d.get(c.name)??"project")),shadowedRules:[]}}var Kd=[{flag:k.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:k.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:k.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:k.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:k.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:k.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:k.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:k.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function ca(){return[...Kd.map((n)=>({name:n.flag.name,value:L1(n.flag),isSet:i1(n.flag),legacyName:n.flag.legacyName,legacyValue:n.flag.legacyName?process.env[n.flag.legacyName]:void 0,legacyIsSet:n.flag.legacyName?process.env[n.flag.legacyName]!==void 0:void 0,description:n.description,defaultBehavior:n.defaultBehavior})),{name:"CC_SAFETY_NET_HOME",value:process.env.CC_SAFETY_NET_HOME,isSet:process.env.CC_SAFETY_NET_HOME!==void 0,description:"Override user-scope config/cache directory",defaultBehavior:"~/.cc-safety-net"}]}var La={error:0,warning:1,info:2},Rd=["policy","config","audit"];function Vd(n){return n.map((t)=>{if(t==="ownership")return"is not owned by the current user";if(t==="permissions")return"has unsafe permissions";if(t==="symlink")return"is a symbolic link";return"is not a directory"}).join(" and ")}var Ad=[{derive:(n)=>n.hooks.length>0&&n.hooks.every((t)=>!t.configured)?[{checkId:"integration.none-configured",severity:"error",title:"No integration configured",detail:"CC Safety Net is not connected to any supported coding-agent integration.",fixHint:"Run `cc-safety-net install` and configure at least one integration."}]:[]},{derive:(n)=>n.hooks.filter((t)=>t.inspectionStatus==="failed").map((t)=>{let r=j(t.platform);return{checkId:"integration.inspection-failed",severity:"error",title:`${r} inspection failed`,detail:`Doctor could not verify the ${r} integration configuration.`,fixHint:`Correct the reported ${r} configuration error, then run \`cc-safety-net doctor\` again.`,integration:t.platform}})},{derive:(n)=>n.userConfig.exists&&!n.userConfig.valid?[{checkId:"config.user-invalid",severity:"error",title:"User configuration is invalid",detail:"Doctor could not load a valid user rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:n.userConfig.path}]:[]},{derive:(n)=>n.projectConfig.exists&&!n.projectConfig.valid?[{checkId:"config.project-invalid",severity:"error",title:"Project configuration is invalid",detail:"Doctor could not load a valid project rules configuration.",fixHint:"Run `cc-safety-net rule verify`, correct the reported error, then rerun doctor.",path:n.projectConfig.path}]:[]},{derive:(n)=>n.configState.state==="degraded"?[{checkId:"config.runtime-degraded",severity:"warning",title:"Runtime is enforcing a fallback configuration",detail:`The rejected candidate configuration is not active: ${n.configState.reason}`,fixHint:"Correct the named source, run `cc-safety-net rule sync` for a rule source, then rerun doctor."}]:[]},{derive:(n)=>{let t=n.environment.find((r)=>r.name==="CC_SAFETY_NET_AUDIT_SCOPE");return c1(t?.value)==="invalid"?[{checkId:"environment.audit-scope-invalid",severity:"warning",title:"Audit scope value is invalid",detail:"CC_SAFETY_NET_AUDIT_SCOPE is not `all` or `blocked`, so allowed command decisions are not recorded.",fixHint:"Set CC_SAFETY_NET_AUDIT_SCOPE to `all` or `blocked`, then restart the integration."}]:[]}},...Rd.map((n)=>({derive:(t)=>t.posture.directories.filter((r)=>r.kind===n&&r.status==="unsafe").map((r)=>({checkId:`posture.${n}-directory-unsafe`,severity:"error",title:`${n[0]?.toUpperCase()}${n.slice(1)} directory is unsafe`,detail:`The ${n} directory ${Vd(r.issues)}.`,fixHint:"Ensure this is a real directory owned by the current user with no group or other write access, then rerun doctor.",...r.path?{path:r.path}:{}}))})),{derive:(n)=>{let t=[...n.effectiveSafety.weakenedRuleOverrides].sort();return t.length>0?[{checkId:"posture.rule-overrides-weaken-preset",severity:"warning",title:"Rule overrides weaken the selected preset",detail:`Explicit overrides disable rules the resolved preset would enable: ${t.join(", ")}.`,fixHint:`Remove these \`off\` overrides or set them to \`on\`: ${t.join(", ")}.`}]:[]}}];function ia(n){return Ad.flatMap((t,r)=>t.derive(n).map((e,a)=>({finding:e,catalogOrder:r,occurrence:a}))).sort((t,r)=>La[t.finding.severity]-La[r.finding.severity]||t.catalogOrder-r.catalogOrder||t.occurrence-r.occurrence).map((t)=>t.finding)}function r2(){return Boolean(process.stdout.isTTY&&!process.env.NO_COLOR)}var Md=(n)=>r2()?`\x1B[32m${n}\x1B[0m`:n,Gd=(n)=>r2()?`\x1B[33m${n}\x1B[0m`:n,Ud=(n)=>r2()?`\x1B[34m${n}\x1B[0m`:n,Cd=(n)=>r2()?`\x1B[35m${n}\x1B[0m`:n,Od=(n)=>r2()?`\x1B[36m${n}\x1B[0m`:n,Td=(n)=>r2()?`\x1B[31m${n}\x1B[0m`:n,_d=(n)=>r2()?`\x1B[2m${n}\x1B[0m`:n,Ed=(n)=>r2()?`\x1B[1m${n}\x1B[0m`:n,o={green:Md,yellow:Gd,blue:Ud,magenta:Cd,cyan:Od,red:Td,dim:_d,bold:Ed},Pd="\x1B[0m",Id=[39,82,198,226,208,51,196,46,201,214,93,154,220,27,49,190,200,33,129,227,45,160,63,118,123,202];function Nd(n){let t=n;return()=>{return t=(t*1664525+1013904223)%4294967296,t/4294967296}}function nc(n){let t=[...Id],r=Nd(n);for(let e=t.length-1;e>0;e--){let a=Math.floor(r()*(e+1)),l=t[e];t[e]=t[a],t[a]=l}return t}function tc(n,t=0){if(!r2())return"";let r=nc(t);return`\x1B[38;5;${r[n%r.length]}m`}function pa(n,t,r=0){if(!r2())return`"${n}"`;return`${tc(t,r)}"${n}"${Pd}`}var rc=new RegExp("\x1B\\[[0-9;]*m","g"),w1=(n)=>n.replace(rc,"").length;function F2(n){let t=(n.headers??n.rows[0]??[]).map((s,d)=>{let c=Math.max(...n.rows.map((L)=>w1(L[d]??"")));return Math.max(w1(s),c)}),r=(s,d)=>s+" ".repeat(Math.max(0,d-w1(s))),e=(s,d)=>d[0]+t.map((c)=>s.repeat(c+2)).join(d[1])+d[2],a=(s)=>`│ ${s.map((d,c)=>r(d,t[c]??0)).join(" │ ")} │`,l=n.headers?[` ${a(n.headers)}`,` ${e("─",["├","┼","┤"])}`]:[];return[` ${e("─",["┌","┬","┐"])}`,...l,...n.rows.map((s)=>` ${a(s)}`),` ${e("─",["└","┴","┘"])}`].join(`
7
+ `)}function va(n){let t=[];t.push("Hook Integration"),t.push(ec(n));let r=[],e=[];for(let a of n){let l=j(a.platform);if(a.errors&&a.errors.length>0)for(let s of a.errors)if(a.configured)r.push({platform:l,message:s});else e.push({platform:l,message:s})}for(let a of r)t.push(` Warning (${a.platform}): ${a.message}`);for(let a of e)t.push(o.red(` Error (${a.platform}): ${a.message}`));return t.join(`
8
+ `)}function ec(n){let t=["Platform","Discovery","Configuration","Inspection"],r=n.map((e)=>{let a=j(e.platform);if(e.inspectionStatus==="not-inspected"){let c=o.dim("Not inspected");return[a,c,c,c]}let l=e.detected?o.green("Detected"):e.inspectionStatus==="failed"?o.red("Unknown"):o.dim("Not detected"),s=e.configured?o.green("Configured"):e.detected?o.yellow("Not configured"):e.inspectionStatus==="failed"?o.red("Unknown"):o.dim("Not applicable"),d=e.inspectionStatus==="verified"?o.green("Verified"):e.inspectionStatus==="failed"?o.red("Failed"):o.dim("Not applicable");return[a,l,s,d]});return F2({headers:t,rows:r})}function ua(n){let r=["Guard Engine Verification",` Synthetic self-test: ${n.failed>0?o.red(`${n.passed}/${n.total} FAIL`):o.green(`${n.passed}/${n.total} passed`)}`],e=n.results.filter((a)=>!a.passed);if(e.length>0){r.push(""),r.push(o.red(" Failures:"));for(let a of e)r.push(o.red(` • ${a.description}`)),r.push(o.red(` expected ${a.expected}, got ${a.actual}`))}return r.join(`
9
+ `)}function ac(n){if(n.length===0)return" (no custom rules)";let t=["Source","Name","Command","Block Args"],r=n.map((e)=>[e.source,e.name,e.subcommand?`${e.command} ${e.subcommand}`:e.command,e.blockArgs.join(", ")]);return F2({headers:t,rows:r})}function ba(n){let t=[];if(t.push("Configuration"),t.push(lc(n.userConfig,n.projectConfig)),t.push(""),n.effectiveRules.length>0)t.push(` Effective rules (${n.effectiveRules.length} total):`),t.push(ac(n.effectiveRules));else t.push(" Effective rules: (none - using built-in rules only)");for(let r of n.shadowedRules)t.push(""),t.push(` Note: Project rule "${r.name}" shadows user rule with same name`);return t.join(`
10
+ `)}function lc(n,t){let r=["Scope","Status"],e=(l)=>{if(!l.exists)return o.dim("N/A");if(!l.valid)return o.red(`Invalid (${l.errors?.[0]??"unknown error"})`);return o.green("Configured")},a=[["User",e(n)],["Project",e(t)]];return F2({headers:r,rows:a})}function oa(n){let t=[];return t.push("Environment"),t.push(sc(n)),t.join(`
11
+ `)}function fa(n){let t=["Effective Safety",` Selected preset: ${n.effectiveSafety.selectedPreset}`,` Effective: ${n.effectiveSafety.level}`],r=[["fail_closed","fail_closed"],["paranoid_rm","paranoid_rm"],["paranoid_interpreters","paranoid_interpreters"]];for(let[e,a]of r){let l=n.effectiveSafety.capabilities[e],s=l.enabled?o.green("ON"):o.dim("OFF"),d=l.sources.length>0?` (${l.sources.join(", ")})`:"";t.push(` ${a}: ${s} via ${l.source}${d}`)}t.push(` Stored rule customizations: ${n.effectiveSafety.ruleCounts.stored}`),t.push(` Effective rule customizations: ${n.effectiveSafety.ruleCounts.effective}`);for(let[e,a]of Object.entries(n.effectiveSafety.ruleOverrides))t.push(` ${e}: ${a}`);return t.join(`
12
+ `)}function ya(n){let t=["Findings"];if(n.length===0)return t.push(" No findings from inspected doctor facts."),t.join(`
13
+ `);for(let r of n){let e=`[${r.severity.toUpperCase()}] ${r.checkId}: ${Z(r.title)}`,a=r.severity==="error"?o.red:r.severity==="warning"?o.yellow:o.blue;if(t.push(` ${a(e)}`),t.push(` ${Z(r.detail)}`),r.path)t.push(` Path: ${Z(r.path)}`);if(r.fixHint)t.push(` Fix: ${Z(r.fixHint)}`)}return t.join(`
14
+ `)}function sc(n){let t=["Variable","Status","Legacy"],r=n.map((e)=>{let a=e.isSet?o.green("✓"):o.dim("✗"),l=e.legacyName&&e.legacyIsSet?`${e.legacyName} ${o.green("✓")}`:e.legacyName??"";return[e.name,a,l]});return F2({headers:t,rows:r})}function ha(n){let t=[];if(n.totalBlocked===0)t.push("Recent Activity"),t.push(" No blocked commands in the last 7 days"),t.push(" Tip: This is normal for new installations");else t.push(`Recent Activity · last 7 days (${n.totalBlocked} blocked / ${n.sessionCount} sessions)`),t.push(dc(n.recentEntries));if(n.unreadable>0)t.push(` Warning: ${n.unreadable} audit log ${n.unreadable===1?"source":"sources"} could not be read; this summary is incomplete`);return t.join(`
15
+ `)}function dc(n){let t=["Time","Command"],r=n.map((e)=>{let a=Z(e.command.replace(/\r\n|\r|\n/g," ↵ ").replace(/\t/g," ")),l=a.length>40?`${a.slice(0,37)}...`:a;return[e.relativeTime,l]});return F2({headers:t,rows:r})}function wa(n){let t=[];if(t.push("Update Check"),n.latestVersion===null&&!n.error)return t.push(En([["Status",o.dim("Skipped")],["Installed",n.currentVersion]])),t.join(`
16
+ `);if(n.error)return t.push(En([["Status",`${o.yellow("⚠")} Error`],["Installed",n.currentVersion],["Error",o.dim(n.error)]])),t.join(`
17
+ `);if(n.updateAvailable)return t.push(En([["Status",`${o.yellow("⚠")} Update Available`],["Current",n.currentVersion],["Latest",o.green(n.latestVersion??"")]])),t.push(""),t.push(" Run: bunx cc-safety-net@latest doctor"),t.push(" Or: npx cc-safety-net@latest doctor"),t.join(`
18
+ `);return t.push(En([["Status",`${o.green("✓")} Up to date`],["Version",n.currentVersion]])),t.join(`
19
+ `)}function En(n){return F2({rows:n})}function xa(n){let t=[];return t.push("System Info"),t.push(cc(n)),t.join(`
20
+ `)}function cc(n){let t=["Component","Version"],r=(l)=>{if(l===null)return o.dim("not found");return l},a=[{label:"cc-safety-net",value:n.version},...On.map((l)=>({label:j(l),value:n.versions[l]??null})),{label:"Node.js",value:n.nodeVersion},{label:"npm",value:n.npmVersion},{label:"Bun",value:n.bunVersion},{label:"Platform",value:n.platform}].map((l)=>[l.label,r(l.value)]);return F2({headers:t,rows:a})}function $a(n){if(n.findings.length===0)return o.green(`
21
+ No findings from inspected doctor facts.`);let t={error:n.findings.filter((l)=>l.severity==="error").length,warning:n.findings.filter((l)=>l.severity==="warning").length,info:n.findings.filter((l)=>l.severity==="info").length},r=["error","warning","info"].filter((l)=>t[l]>0).map((l)=>`${t[l]} ${l}`),e=n.findings.length===1?"finding":"findings",a=`
22
+ ${n.findings.length} ${e}: ${r.join(", ")}.`;if(t.error>0)return o.red(a);if(t.warning>0)return o.yellow(a);return o.blue(a)}import{lstatSync as Lc}from"node:fs";import{dirname as x1}from"node:path";function $1(n,t){try{let r=Lc(t);if(r.isSymbolicLink())return{kind:n,path:t,status:"unsafe",issues:["symlink"]};if(!r.isDirectory())return{kind:n,path:t,status:"unsafe",issues:["not-directory"]};if(process.platform==="win32"||typeof process.getuid!=="function")return{kind:n,path:t,status:"unknown",issues:[]};let e=[...r.uid!==process.getuid()?["ownership"]:[],...(r.mode&18)!==0?["permissions"]:[]];return{kind:n,path:t,status:e.length>0?"unsafe":"safe",issues:e}}catch(r){if(typeof r==="object"&&r!==null&&"code"in r&&r.code==="ENOENT")return{kind:n,path:t,status:"not-applicable",issues:[]};return{kind:n,path:t,status:"unknown",issues:[]}}}function Da(n){let t=i2();return{directories:[$1("policy",x1(x1(n))),$1("config",x1(n)),...t?[$1("audit",t)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as ic}from"node:child_process";import{existsSync as ma}from"node:fs";import{delimiter as pc,extname as vc,join as uc}from"node:path";import{stripVTControlCharacters as ga}from"node:util";var qa="2.0.8",bc=5000,oc="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function B(){return qa}function D1(n,t){let r=n[t];if(r)return r;let e=Object.keys(n).find((a)=>a.toLowerCase()===t.toLowerCase()&&!!n[a]);return e?n[e]:r}function fc(n){return(D1(n,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((t)=>t.length>0)}function yc(n,t){let r=vc(n)?[n]:[...fc(t).map((e)=>`${n}${e}`),n];if(n.includes("/")||n.includes("\\"))return r.find((e)=>ma(e))??n;return(D1(t,"PATH")??"").split(pc).flatMap((e)=>r.map((a)=>uc(e,a))).find((e)=>ma(e))??n}function ka(n){if(!/[\s"&|<>^]/.test(n))return n;return`"${n.replace(/"/g,'""')}"`}function h2(n,t){let[r,...e]=n,a=t[oc]==="win32"?"win32":process.platform;if(!r||a!=="win32")return{cmd:r??"",args:e};let l=yc(r,t);if(!/\.(?:bat|cmd)$/i.test(l))return{cmd:l,args:e};return{cmd:D1(t,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",ka(l),...e.map(ka)].join(" ")]}}var P2=async(n,t=bc)=>{let r=await hc(n,{timeoutMs:t});if(r.code!==0)return null;return ga(r.stdout).trim()||ga(r.stderr).trim()||null};function hc(n,t){let[r,...e]=n;if(!r)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((a)=>{try{let l=h2([r,...e],process.env),s=ic(l.cmd,l.args,{stdio:["ignore","pipe","pipe"]}),d=!1,c="",L="";s.stdout.on("data",(b)=>{c+=b.toString()}),s.stderr.on("data",(b)=>{L+=b.toString()});let i=(b)=>{if(d)return;d=!0,clearTimeout(v),a(b)},v=setTimeout(()=>{s.kill(),i({code:null,stdout:c,stderr:L})},t.timeoutMs);s.on("close",(b)=>{i({code:b,stdout:c,stderr:L})}),s.on("error",()=>{i({code:null,stdout:c,stderr:L})})}catch{a({code:null,stdout:"",stderr:""})}})}function Pn(n){if(!n)return null;let t=/Claude Code\s+(\d+\.\d+\.\d+)/i.exec(n);if(t)return t[1]??null;let r=/v?(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?)/i.exec(n);if(r)return r[1]??null;return n.split(`
23
+ `)[0]?.trim()||null}async function gn(n=P2){let[t,r,e,a,l,s]=await Promise.all([Promise.all(G.map(async(d)=>[d.id,Pn(await n([...d.probeCommand]))])),n(["codex","plugin","list"],30000),n(["amp","plugins","list"],30000),n(["node","--version"]),n(["npm","--version"]),n(["bun","--version"])]);return{version:qa,versions:Object.fromEntries(t),codexPluginListOutput:r,ampPluginListOutput:e,nodeVersion:Pn(a),npmVersion:Pn(l),bunVersion:Pn(s),platform:`${process.platform} ${process.arch}`}}function m1(n,t){if(t==="dev")return!1;let r=n.split(".").map(Number),e=t.split(".").map(Number),[a=0,l=0,s=0]=r,[d=0,c=0,L=0]=e;if(a!==d)return a>d;if(l!==c)return l>c;return s>L}async function I2(){let n=B(),t=new AbortController,r=setTimeout(()=>t.abort(),3000);try{let e=await fetch("https://registry.npmjs.org/cc-safety-net/latest",{signal:t.signal});if(!e.ok)return{currentVersion:n,latestVersion:null,updateAvailable:!1,error:`npm registry returned ${e.status}`};let a=await e.json(),l=m1(a.version,n);return{currentVersion:n,latestVersion:a.version,updateAvailable:l}}catch(e){return{currentVersion:n,latestVersion:null,updateAvailable:!1,error:e instanceof Error?e.message:"Network error"}}finally{clearTimeout(r)}}import*as Xa from"node:readline";var Ba=(n)=>`\x1B[${n}B`,wc=(n)=>`\x1B[${n}A`;var ja=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function xc(n){return new Promise((t)=>setTimeout(t,n))}function $c(n,t,r){if(!r)return t(n);if(r.aborted)return Promise.resolve();return new Promise((e,a)=>{let l=()=>r.removeEventListener("abort",s),s=()=>{l(),e()};r.addEventListener("abort",s,{once:!0}),t(n).then(()=>{l(),e()},(d)=>{l(),a(d)})})}function kn(n,t){return n&&n>0?n:t}function In(n){return Math.max(0,Math.min(1,n))}function N2(n){return Math.max(0,Math.min(255,Math.round(n)))}function g1(n){return n<=0.0031308?12.92*n:1.055*n**0.4166666666666667-0.055}function Dc(n,t,r){let e=r*Math.PI/180,a=t*Math.cos(e),l=t*Math.sin(e),s=(n+0.3963377774*a+0.2158037573*l)**3,d=(n-0.1055613458*a-0.0638541728*l)**3,c=(n-0.0894841775*a-1.291485548*l)**3;return{blue:N2(g1(In(-0.0041960863*s-0.7034186147*d+1.707614701*c))*255),green:N2(g1(In(-1.2684380046*s+2.6097574011*d-0.3413193965*c))*255),red:N2(g1(In(4.0767416621*s-3.3077115913*d+0.2309699292*c))*255)}}function k1(n,t){let r=(t*n*180/Math.PI%360+360)%360;return Dc(0.72,0.15,r)}function Ja(n,t=0.1){let r=k1(t,n);return`\x1B[38;2;${r.red};${r.green};${r.blue}m`}function mc(n,t){return{blue:N2(n.blue+(255-n.blue)*t),green:N2(n.green+(255-n.green)*t),red:N2(n.red+(255-n.red)*t)}}function Za(n,t,r){let e=Math.imul(n+2654435769,2246822507)^Math.imul(t+3266489909,668265263)^Math.imul(r+374761393,2654435761),a=e^e>>>15,l=Math.imul(a,739982445),s=l^l>>>12,d=Math.imul(s,695872825);return((d^d>>>15)>>>0)/4294967296}function gc(n,t,r){let e=Math.floor(Za(n,t,r)*ja.length);return ja[e]??"░"}function za(n){let t=In(n);return t*t*t*(t*(t*6-15)+10)}function kc(n){if(n.length===0)return"";let t=[],r=!1,e="";for(let a of n){let l=`${a.red};${a.green};${a.blue}`;if(a.bold!==r)t.push(a.bold?"\x1B[1m":"\x1B[22m"),r=a.bold;if(l!==e)t.push(`\x1B[38;2;${l}m`),e=l;t.push(a.character)}return`${t.join("")}\x1B[22m\x1B[39m`}function qc(n,t,r,e,a){return n.map((l,s)=>({...k1(r,e+t+s/a),bold:!1,character:l}))}function jc(n,t,r,e,a,l,s,d){let c=Math.max(1,e*0.75),L=Math.min(1,r/c),i=a*za(L),v=Math.max(0,(r-c)/Math.max(1,e-c)),b=(1-za(r/e))*d*2,p=0.35*Math.max(0,1-v*2),f=L>=1,u=Math.min(n.length,Math.ceil(i+2+1));return n.slice(0,u).map((h,w)=>{let $=k1(l,s+t+w/d+b),y=w+Za(t,w,7919)*2-1;if(y>i+2)return{...$,bold:!1,character:" "};let m=i-y,H=0.8*Math.exp(-(m*m)/12.5),o2=Math.min(0.9,H+p),Yt=!f&&y>i-4;return{...mc($,o2),bold:o2>0.3,character:Yt?gc(t,w,r):h}})}function Fa(n){return`\x1B[?2026h${n.map((t,r)=>`\x1B8${r>0?Ba(r):""}${kc(t)}`).join("")}\x1B[?2026l`}async function q1(n,t={}){if(!n)return;let r=t.output??process.stdout,e=t.sleep??xc,a=kn(t.frequency,0.1),l=t.seed??0,s=kn(t.speed,40),d=kn(t.spread,3),c=kn(t.frameRate,60),L=Math.max(1,Math.floor(kn(t.duration,12))),i=n.split(`
24
+ `).map((u)=>Array.from(u)),v=Math.max(...i.map((u)=>u.length)),b=1000*L*i.filter((u)=>u.length>0).length/s,p=v>0?Math.max(1,Math.ceil(b/(1000/c))):0,f=p>0?b/p:0;r.write(`\x1B[?25l${i.length>1?`${`
25
+ `.repeat(i.length-1)}${wc(i.length-1)}`:""}\x1B7`);try{for(let u=1;u<=p;u+=1){if(t.signal?.aborted)break;r.write(Fa(i.map((h,w)=>jc(h,w,u,p,v,a,l,d)))),await $c(f,e,t.signal)}}finally{if(r.write(Fa(i.map((u,h)=>qc(u,h,a,l,d)))),r.write("\x1B8"),i.length>1)r.write(Ba(i.length-1));r.write(`
26
+ \x1B[0m\x1B[?25h`)}}var Qa=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
27
+ `);function zc(n){return Boolean(n.isTTY)}async function qn(n={}){let t=n.output??process.stdout;if(!zc(t))return;let r=n.input??process.stdin,e={duration:n.duration,frequency:n.frequency,output:t,seed:n.seed??Math.random()*8192,sleep:n.sleep,speed:n.speed,spread:n.spread};if(!r.isTTY||typeof r.setRawMode!=="function"){await q1(Qa,e);return}let a=new AbortController,l=r.readableFlowing===!0,s=r.isRaw===!0,d=!1,c=(L,i)=>{if(i.ctrl&&i.name==="c")d=!0;if(d||i.name==="return"||i.name==="enter")a.abort()};Xa.emitKeypressEvents(r),r.on("keypress",c),r.setRawMode(!0),r.resume();try{await q1(Qa,{...e,signal:a.signal})}finally{if(r.off("keypress",c),r.setRawMode(s),!l)r.pause()}if(!d)return;if(n.onInterrupt){n.onInterrupt();return}process.kill(process.pid,"SIGINT")}var Ya="\r\x1B[2K",Fc="\x1B[?25l",Bc="\x1B[39m",Jc="\x1B[?25h",Zc=100,Qc=0.55,Xc=80,Sa=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function Yc(n){return new Promise((t)=>setTimeout(t,n))}async function Nn(n,t={}){let r=t.output??process.stdout;if(!r.isTTY)return n;let e=t.sleep??Yc,a=!1,l=n.then((d)=>{return a=!0,d},(d)=>{throw a=!0,d});if(await Promise.race([l.then(()=>!0),e(Zc).then(()=>!1)]))return l;r.write(Fc);try{for(let d=0;!a;d+=1)r.write(`${Ya}${Ja(d*Qc)}${Sa[d%Sa.length]}${Bc} ${t.loadingMessage??"Loading…"}`),await Promise.race([l,e(Xc)]);return await l}finally{r.write(`${Ya}${Jc}`)}}async function jn(n,t,r,e={}){let a=t();if(n)await r();if(n&&a.ready)await Nn(a.ready,e);return a.finish()}import{homedir as ei}from"node:os";import{stripVTControlCharacters as Sc}from"node:util";var nt="amp plugins list",Hc=/^\s*[✓✗]\s+cc-safety-net(?:\.ts)?\s+\(User Plugins\)\s+(\S+)\s*$/;function Ha(n){if(!n.ampPluginListOutput)return{platform:"amp",status:"n/a"};let t=Sc(n.ampPluginListOutput).split(`
28
+ `).map((r)=>Hc.exec(r)?.[1]).find((r)=>r!==void 0);if(!t)return{platform:"amp",status:"n/a"};if(t!=="active")return{platform:"amp",status:"disabled",method:nt,configPath:nt,errors:[`Amp personal plugin cc-safety-net is ${t}; run "plugins: reload" in Amp or reinstall with install --amp`]};return{platform:"amp",status:"configured",method:nt,configPath:nt}}import{existsSync as Kc,readFileSync as Rc}from"node:fs";import{join as Wc}from"node:path";function zn(n){return Wc(n,".gemini","config","hooks.json")}var Vc=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function Ac(n){if(!n||typeof n!=="object"||Array.isArray(n))return[];return Object.values(n).flatMap((t)=>{if(!t||typeof t!=="object"||Array.isArray(t))return[];let r=t,e=r.PreToolUse;if(!Array.isArray(e))return[];return e.flatMap((a)=>{if(!a||typeof a!=="object"||Array.isArray(a))return[];let l=a.hooks;if(!Array.isArray(l))return[];return l.flatMap((s)=>{if(!s||typeof s!=="object"||Array.isArray(s))return[];let d=s.command;if(typeof d!=="string"||!Vc.test(d))return[];return[{command:d,enabled:r.enabled!==!1}]})})})}function Wa(n){let t=zn(n.homeDir);if(!Kc(t))return{platform:"antigravity-cli",status:"n/a",configPath:t};let r;try{r=Ac(JSON.parse(Rc(t,"utf-8")))}catch(e){return{platform:"antigravity-cli",status:"n/a",configPath:t,errors:[`Failed to parse Antigravity hooks config ${t}: ${e instanceof Error?e.message:String(e)}`]}}if(r.some((e)=>e.enabled))return{platform:"antigravity-cli",status:"configured",method:"hook config",configPath:t};if(r.length>0)return{platform:"antigravity-cli",status:"disabled",method:"hook config",configPath:t};return{platform:"antigravity-cli",status:"n/a",configPath:t}}import{join as Ka}from"node:path";import{existsSync as Mc,lstatSync as Gc,readFileSync as Uc}from"node:fs";function e2(n,t=(r)=>r){if(!Mc(n))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(t(Uc(n,"utf-8")))}}catch{return{kind:"unreadable"}}}function F(n){try{return Gc(n)}catch{return}}function tt(n,t){let r=F(t);if(!r)return{platform:n,status:"n/a",configPath:t};if(!r.isSymbolicLink()&&r.isDirectory())return;return{platform:n,status:"n/a",configPath:t,errors:[`${t} is a symlink or not a directory; move or remove it before installing`]}}function x(n,t){return typeof n==="object"&&n!==null?n[t]:void 0}var j1="cc-safety-net@cc-marketplace";function Ra(n){return Ka(n,".claude","plugins","installed_plugins.json")}function Va(n,t){let r=x(x(n,"plugins"),t);return Array.isArray(r)&&r.length>0}function rt(n,t){let r=e2(Ra(n));return r.kind==="ok"&&Va(r.value,t)}function z1(n){let t=Ra(n),r=e2(t);if(r.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(r.kind==="missing")return{platform:"claude-code",status:"n/a"};if(!Va(r.value,j1))return{platform:"claude-code",status:"n/a"};let e=Ka(n,".claude","settings.json"),a=e2(e);if(a.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(a.kind==="ok"&&x(x(a.value,"enabledPlugins"),j1)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:e,errors:[`${j1} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:t}}function Aa(n){return z1(n.homeDir)}function Ma(n){if(!n.codexPluginListOutput)return{platform:"codex",status:"n/a"};let t=n.codexPluginListOutput.split(`
29
+ `).find((r)=>r.includes("https://github.com/kenryu42/cc-safety-net.git"));if(!t)return{platform:"codex",status:"n/a"};if(!t.includes("installed,"))return{platform:"codex",status:"n/a"};if(!t.includes("installed, enabled"))return{platform:"codex",status:"disabled",method:"codex plugin list",configPath:"codex plugin list",errors:["Codex plugin line for https://github.com/kenryu42/cc-safety-net.git must contain installed, enabled."]};return{platform:"codex",status:"configured",method:"codex plugin list",configPath:"codex plugin list"}}import{existsSync as lt,readdirSync as Cc,readFileSync as Oc}from"node:fs";import{join as S}from"node:path";var a2="cc-safety-net@cc-marketplace",et=["cc-marketplace","cc-safety-net"],Ga=["_direct","copilot-safety-net"],Ua=["cc-marketplace","safety-net"],Ca="safety-net@cc-marketplace";function at(n,t){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${r}([^a-z0-9-]|$)`,"m").test(n??"")}function Oa(n){return at(n,"cc-safety-net@cc-marketplace")}function Ta(n){return at(n,"cc-marketplace")}function _a(n){return at(n,"copilot-safety-net")}function Ea(n){return at(n,"safety-net@cc-marketplace")}function M(n){let t="",r=0,e=!1,a=!1,l=-1;while(r<n.length){let s=n[r],d=n[r+1];if(a){t+=s,a=!1,r++;continue}if(s==='"'&&!e){e=!0,l=-1,t+=s,r++;continue}if(s==='"'&&e){e=!1,t+=s,r++;continue}if(s==="\\"&&e){a=!0,t+=s,r++;continue}if(e){t+=s,r++;continue}if(s==="/"&&d==="/"){while(r<n.length&&n[r]!==`
30
+ `)r++;continue}if(s==="/"&&d==="*"){r+=2;while(r<n.length-1){if(n[r]==="*"&&n[r+1]==="/"){r+=2;break}r++}continue}if(s===","){l=t.length,t+=s,r++;continue}if(s==="}"||s==="]"){if(l!==-1){let c=t.slice(l+1);if(/^\s*$/.test(c))t=t.slice(0,l)+c}l=-1,t+=s,r++;continue}if(!/\s/.test(s))l=-1;t+=s,r++}return t}function F1(n){if(!n?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(n)}function Ia(n,t){if(!n)return null;let r=n.match(/(\d+)\.(\d+)\.(\d+)/);if(!r)return null;let e=[Number(r[1]),Number(r[2]),Number(r[3])];for(let a=0;a<t.length;a++){let l=e[a]??0,s=t[a]??0;if(l!==s)return l>s}return!0}function Tc(n){return Ia(n,[0,0,422])}function _c(n){return Ia(n,[1,0,8])}function Fn(n){return process.env.COPILOT_HOME||S(n,".copilot")}function B1(n){return(n.hooks?.preToolUse??[]).some((r)=>{if(r.type!=="command")return!1;return F1(r.command)||F1(r.bash)||F1(r.powershell)})}function J1(n,t){try{return JSON.parse(M(Oc(n,"utf-8")))}catch(r){t?.push(`Failed to parse ${n}: ${r instanceof Error?r.message:String(r)}`);return}}function Na(n,t){try{return Cc(n).filter((r)=>r.endsWith(".json")).sort((r,e)=>r.localeCompare(e))}catch(r){return t?.push(`Failed to read ${n}: ${r instanceof Error?r.message:String(r)}`),[]}}function Ec(n,t){if(!lt(n))return[];let r=[];for(let e of Na(n,t)){let a=S(n,e),l=J1(a,t);if(l&&B1(l))r.push(a)}return r}function nn(n,t){if(!lt(n))return;let r=J1(n,t);if(!r)return;return{path:n,config:r}}function Pa(n,t,r,e){if(t){n.push(`GitHub Copilot CLI ${t} does not support ${r}; requires ${e}+`);return}n.push(`GitHub Copilot CLI version unavailable; skipping ${r} because it requires ${e}+`)}function Pc(n){for(let t of n){if(t?.config.disableAllHooks===!0)return t.path;if(t?.config.disableAllHooks===!1)return}return}function Ic(n,t,r,e){let a=Fn(n),l=S(t,".github","hooks"),s=S(a,"hooks"),d=S(t,".github","copilot"),c=S(t,".claude"),L=_c(r),i=L===!0?e:void 0,v=[nn(S(d,"settings.local.json"),i),nn(S(d,"settings.json"),i),nn(S(c,"settings.local.json"),i),nn(S(c,"settings.json"),i)],b=[nn(S(a,"settings.json"),i),nn(S(a,"config.json"),i)];if(L!==!1){let m=Pc([...v,...b]);if(m){if(L===null)e.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${m} as active`);return{activeConfigPaths:[],disabledBy:m}}}let p=Ec(l,e),f=Tc(r),u=f===!0?e:void 0,h=lt(s)?Na(s,u):[],w=[];for(let m of h){let H=S(s,m),o2=J1(H,u);if(o2&&B1(o2))w.push(H)}if(f!==!0&&w.length>0)Pa(e,r,`user hook files in ${s}`,"0.0.422"),w.length=0;let $=[];for(let m of[...v,...b]){if(!m)continue;if(!B1(m.config))continue;if(L===!0){$.push(m);continue}Pa(e,r,"inline hook definitions in Copilot config files","1.0.8");break}let y=(m)=>m.filter((H)=>!!H&&$.includes(H)).map((H)=>H.path);return{activeConfigPaths:[...y(v),...p,...y(b),...w]}}function n0(n){let t=[],r=Ic(n.homeDir,n.cwd,n.copilotCliVersion,t);if(r.disabledBy)return{platform:"copilot-cli",status:"disabled",method:"hook config",configPath:r.disabledBy,configPaths:[r.disabledBy],errors:t.length>0?t:void 0};let e=Fn(n.homeDir),a=S(e,"installed-plugins",...et),l=lt(a),s=S(e,"settings.json"),d=e2(s,M);if(l&&d.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(l&&d.kind==="ok"&&x(x(d.value,"enabledPlugins"),a2)===!1)return{platform:"copilot-cli",status:"disabled",method:"plugin config",configPath:s,errors:[`${a2} is installed but not enabled in Copilot CLI`]};if(l||r.activeConfigPaths.length>0){let c=l,L=r.activeConfigPaths[0];return{platform:"copilot-cli",status:"configured",method:c?"plugin config":"hook config",configPath:L??(c?a:void 0),configPaths:r.activeConfigPaths.length>0?r.activeConfigPaths:void 0,errors:t.length>0?t:void 0}}return{platform:"copilot-cli",status:"n/a",errors:t.length>0?t:void 0}}import{existsSync as cL,readFileSync as LL}from"node:fs";import{existsSync as t0,mkdirSync as tL,readFileSync as rL}from"node:fs";import{dirname as eL,join as aL}from"node:path";import{renameSync as Nc,writeFileSync as nL}from"node:fs";function Q(n,t){let r=`${n}.${process.pid}.tmp`;nL(r,t),Nc(r,n)}var Bn="npx -y cc-safety-net hook --cursor",r0=30;function dt(n){return aL(n,".cursor","hooks.json")}function B2(n){return typeof n==="object"&&n!==null&&!Array.isArray(n)}function Z1(){return{command:Bn,timeout:r0,failClosed:!0}}function st(n){return B2(n)&&n.command===Bn}function lL(n){return Object.keys(n).length===3&&n.command===Bn&&n.timeout===r0&&n.failClosed===!0}function sL(n){try{return JSON.parse(rL(n,"utf-8"))}catch(t){if(t instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${n}: ${t.message}`);throw t}}function e0(n){let t=sL(n);if(!B2(t))throw Error(`Cursor hooks config ${n} must be a JSON object`);if(t.version!==1)throw Error(`Cursor hooks config ${n} must set "version": 1`);if(t.hooks!==void 0&&!B2(t.hooks))throw Error(`Cursor hooks config ${n} "hooks" must be an object`);let r=B2(t.hooks)?t.hooks.preToolUse:void 0;if(r!==void 0&&!Array.isArray(r))throw Error(`Cursor hooks config ${n} "hooks.preToolUse" must be an array`);return t}function a0(n){let t=B2(n.hooks)?n.hooks.preToolUse:void 0;return Array.isArray(t)?t:[]}function dL(n){if(!n.some(st))return[...n,Z1()];return n.reduce((t,r)=>{if(!st(r))return t.result.push(r),t;if(!t.inserted)t.result.push(Z1()),t.inserted=!0;return t},{result:[],inserted:!1}).result}function l0(n,t,r){let e=B2(t.hooks)?t.hooks:{},a={...t,hooks:{...e,preToolUse:r}};Q(n,`${JSON.stringify(a,null,2)}
31
+ `)}function s0(n){let t=dt(n);if(!t0(t))return tL(eL(t),{recursive:!0}),Q(t,`${JSON.stringify({version:1,hooks:{preToolUse:[Z1()]}},null,2)}
32
+ `),{path:t,alreadyInstalled:!1};let r=e0(t),e=a0(r),a=e.filter(st);if(B2(r.hooks)&&Array.isArray(r.hooks.preToolUse)&&a.length===1&&a[0]!==void 0&&lL(a[0]))return{path:t,alreadyInstalled:!0};return l0(t,r,dL(e)),{path:t,alreadyInstalled:!1}}function d0(n){let t=dt(n);if(!t0(t))return{path:t,alreadyInstalled:!1};let r=e0(t),e=a0(r),a=e.filter((l)=>!st(l));if(a.length===e.length)return{path:t,alreadyInstalled:!1};return l0(t,r,a),{path:t,alreadyInstalled:!0}}function iL(n){if(!n||typeof n!=="object"||Array.isArray(n))return[];let t=n.hooks;if(!t||typeof t!=="object"||Array.isArray(t))return[];let r=t.preToolUse;if(!Array.isArray(r))return[];return r.filter((e)=>!!e&&typeof e==="object"&&!Array.isArray(e)&&e.command===Bn)}function pL(n){let t=[];if(n.length>1)t.push("Multiple managed cc-safety-net hooks found; reinstall to collapse duplicates");let r=n[0];if(r&&r.failClosed!==!0)t.push('Managed hook is missing "failClosed": true; reinstall to repair');if(r&&r.timeout!==30)t.push('Managed hook "timeout" is not 30; reinstall to repair');return t}function c0(n){let t=dt(n.homeDir);if(!cL(t))return{platform:"cursor",status:"n/a",configPath:t};let r;try{r=JSON.parse(LL(t,"utf-8"))}catch(l){return{platform:"cursor",status:"n/a",configPath:t,errors:[`Failed to parse Cursor hooks config ${t}: ${l instanceof Error?l.message:String(l)}`]}}let e=iL(r);if(e.length===0)return{platform:"cursor",status:"n/a",configPath:t};let a=pL(e);return{platform:"cursor",status:"configured",method:"hook config",configPath:t,errors:a.length>0?a:void 0}}import{existsSync as vL}from"node:fs";import{join as Q1}from"node:path";var X1="gemini-safety-net";function Y1(n){let t=Q1(n,".gemini","extensions"),r=Q1(t,X1);if(!vL(r))return{platform:"gemini-cli",status:"n/a"};let e=Q1(t,"extension-enablement.json"),a=e2(e);if(a.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let l=a.kind==="ok"?x(x(a.value,X1),"overrides"):void 0;if(Array.isArray(l)&&l.some((d)=>typeof d==="string"&&d.startsWith("!")))return{platform:"gemini-cli",status:"disabled",method:"extension config",configPath:e,errors:[`${X1} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:r}}function L0(n){return Y1(n.homeDir)}import{readFileSync as h0}from"node:fs";import{join as w0}from"node:path";var U="cc-safety-net",i0="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent";function p0(n){return`# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent
33
33
  # version: ${n}
34
- `}function ei(n){return`${e0(n)}name: cc-safety-net
34
+ `}function uL(n){return`${p0(n)}name: cc-safety-net
35
35
  version: "${n}"
36
36
  description: "Block destructive commands and secret-file access before Hermes runs a tool."
37
37
  author: "cc-safety-net"
38
38
  provides_hooks:
39
39
  - pre_tool_call
40
- `}function ri(n){return`${e0(n)}"""CC Safety Net guard for Hermes Agent.
40
+ `}function bL(n){return`${p0(n)}"""CC Safety Net guard for Hermes Agent.
41
41
 
42
42
  Registers pre_tool_call and forwards the tool call to the packaged CC Safety Net
43
43
  adapter (cc-safety-net hook --hermes-agent) over JSON stdin. The adapter prints nothing
@@ -70,12 +70,18 @@ def _terminal_cwd(task_id, process_cwd):
70
70
  \`workdir or get_session_cwd(session_key) or default_cwd\`, and that record is rewritten
71
71
  after every completed command, so it IS the session's \`cd\` state. The session key is
72
72
  derived exactly as terminal_tool derives it: the contextvar when set, the raw task_id
73
- otherwise. No record yet (first command of a session) means the process directory.
73
+ otherwise. No record yet (first command of a session) means \`default_cwd\`, which the local
74
+ terminal backend reads from \`TERMINAL_CWD\` (\`hermes_cli/config.py\` bridges the configured
75
+ \`terminal.cwd\` into it) and only then falls back to the process directory.
74
76
  """
75
77
  from tools.approval import get_current_session_key
76
78
  from tools.terminal_tool import get_session_cwd
77
79
 
78
- return get_session_cwd(get_current_session_key(default="") or (task_id or "")) or process_cwd
80
+ return (
81
+ get_session_cwd(get_current_session_key(default="") or (task_id or ""))
82
+ or os.environ.get("TERMINAL_CWD")
83
+ or process_cwd
84
+ )
79
85
 
80
86
 
81
87
  def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
@@ -169,83 +175,84 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
169
175
 
170
176
  def register(ctx):
171
177
  ctx.register_hook("pre_tool_call", _pre_tool_call)
172
- `}function jn(n){return[{name:"__init__.py",content:ri(n)},{name:"plugin.yaml",content:ei(n)}]}import{mkdirSync as ai,readdirSync as li,readFileSync as di,rmSync as Fe}from"node:fs";import{join as q2}from"node:path";var si="__pycache__";function ze(n){let t=process.env.HERMES_HOME?.trim();return t?t:q2(n,".hermes")}function Be(n){return q2(ze(n),"plugins",M)}function Je(n){return n.startsWith(t0)}function Ze(n,t){let e=Be(n),r=S(e);if(r&&(r.isSymbolicLink()||!r.isDirectory()))throw Error(`Refusing to ${t} ${e}: not a regular directory. Move or remove it and rerun ${t==="install"?"install":"uninstall"} --hermes-agent.`);return e}function r0(n,t){let e=S(n);if(!e)return;if(e.isSymbolicLink()||!e.isFile())throw Error(`Refusing to ${t} ${n}: not a regular file. Move or remove it.`);let r=di(n,"utf-8");if(!Je(r))throw Error(`Refusing to ${t} unmanaged file at ${n}. Move or remove it.`);return r}function a0(n){let t=Ze(n,"install"),e=jn(j());if(e.map((a)=>r0(q2(t,a.name),"overwrite")).every((a,l)=>a===e[l]?.content))return{path:t,alreadyInstalled:!0};return ai(t,{recursive:!0}),e.forEach((a)=>{B(q2(t,a.name),a.content)}),{path:t,alreadyInstalled:!1}}function Qe(n){let t=Ze(n,"remove");if(!S(t))return[];return jn(j()).filter((e)=>r0(q2(t,e.name),"remove")!==void 0)}function l0(n){let t=Ze(n,"remove");if(!S(t))return{path:t,alreadyInstalled:!1};let e=Qe(n);if(e.forEach((r)=>{Fe(q2(t,r.name))}),Fe(q2(t,si),{recursive:!0,force:!0}),li(t).length===0)Fe(t,{recursive:!0});return{path:t,alreadyInstalled:e.length>0}}var rt="hermes-agent",d0=/^([^\s#][^:]*):/,ci=/^\s+([A-Za-z_][\w-]*):/,s0=/^\s+-\s*(.*)$/;function ii(n){return n.trim().replace(/^(["'])(.*)\1$/,"$2")}function Li(n){let t=n.split(/\r?\n/),e=t.findIndex((l)=>d0.exec(l)?.[1]?.trim()==="plugins");if(e===-1)return[];let r=t.slice(e+1),a=r.findIndex((l)=>d0.test(l));return a===-1?r:r.slice(0,a)}function c0(n,t){let e=Li(n),r=e.findIndex((d)=>ci.exec(d)?.[1]===t);if(r===-1)return[];let a=e.slice(r+1),l=a.findIndex((d)=>!s0.test(d));return(l===-1?a:a.slice(0,l)).map((d)=>ii(s0.exec(d)?.[1]??""))}function pi(n){try{return i0(L0(ze(n),"config.yaml"),"utf-8")}catch{return}}function Xe(n){let t=pi(n)??"";return c0(t,"enabled").includes(M)&&!c0(t,"disabled").includes(M)}function p0(n){return/^# version:\s*(.+)$/m.exec(n)?.[1]?.trim()}function ui(n,t){let e=S(n);if(!e)return{error:`${t.name} is missing from ${n}; run install --hermes-agent`};if(e.isSymbolicLink()||!e.isFile())return{error:`${n} is a symlink or not a regular file; move or remove it`};try{let r=i0(n,"utf-8");if(!Je(r))return{error:`Unmanaged ${t.name} occupies ${n}; move or remove it`};if(p0(r)===j()&&r!==t.content)return{error:`Modified ${t.name} occupies ${n}; run install --hermes-agent to restore it`};return{content:r}}catch(r){return{error:`Failed to read ${n}: ${r instanceof Error?r.message:String(r)}`}}}function u0(n){let t=Be(n.homeDir),e=En(rt,t);if(e)return e;let r=jn(j()).map((s)=>ui(L0(t,s.name),s)),a=r.flatMap((s)=>("error"in s)?[s.error]:[]);if(a.length>0)return{platform:rt,status:"n/a",configPath:t,errors:a};let l=r.some((s)=>("content"in s)&&p0(s.content)!==j()),d=l?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!Xe(n.homeDir))return{platform:rt,status:"disabled",method:"plugin directory",configPath:t,errors:[`${M} is not enabled in Hermes; run \`hermes plugins enable ${M}\``,...d]};return{platform:rt,status:"configured",method:"plugin directory",configPath:t,errors:l?d:void 0}}import{existsSync as oi,readFileSync as vi}from"node:fs";import{join as o0}from"node:path";var bi=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function fi(n){return o0(process.env.KIMI_CODE_HOME||o0(n,".kimi-code"),"config.toml")}function Fn(n){let t=fi(n.homeDir);if(!oi(t))return{platform:"kimi-code",status:"n/a",configPath:t};try{if(!bi.test(vi(t,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:t}}catch(e){return{platform:"kimi-code",status:"n/a",configPath:t,errors:[`Failed to read ${t}: ${e instanceof Error?e.message:String(e)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:t}}import{readFileSync as D0}from"node:fs";import{join as Bn}from"node:path";var q="cc-safety-net",V="index.js",I2="openclaw.plugin.json",N2="package.json";var at="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as wi,lstatSync as xi,readdirSync as $i,readFileSync as gi}from"node:fs";import{dirname as f0,join as j2}from"node:path";import{fileURLToPath as Di}from"node:url";import{spawn as hi}from"node:child_process";function yi(n){return n.join(" ")}function Ye(n,t,e){return[`Failed to run ${yi(n)}${t===null?"":` (exit ${t})`}.`,e.trim()].filter(Boolean).join(`
173
- `)}function Se(n){let t={stdout:"",stderr:""};return n.stdout.setEncoding("utf-8"),n.stderr.setEncoding("utf-8"),n.stdout.on("data",(e)=>{t.stdout+=e}),n.stderr.on("data",(e)=>{t.stderr+=e}),t}function e2(n,t){return new Promise((e,r)=>{let a=f2([...n],process.env),l=hi(a.cmd,a.args,{stdio:["ignore","pipe","pipe"]}),d=Se(l),s=()=>[d.stdout,d.stderr].filter(Boolean).join(`
174
- `),c=t?.timeoutMs??120000,i=setTimeout(()=>{l.kill(),r(Error(Ye(n,null,`Timed out after ${c}ms.
175
- ${s()}`.trim())))},c);l.on("error",(L)=>{clearTimeout(i),r(Error(Ye(n,null,`${L.message}
176
- ${s()}`.trim())))}),l.on("close",(L)=>{if(clearTimeout(i),L!==0){r(Error(Ye(n,L,s())));return}e(t?.stdoutOnly?d.stdout:s())})})}async function He(n){for(let t of n)await e2(t)}async function v0(n){for(let t of n)try{await e2(t)}catch(e){console.warn(e instanceof Error?e.message:String(e))}}var b0=j2("openclaw",q),mi=[V,I2,N2];function h0(n){let t=process.env.OPENCLAW_STATE_DIR?.trim();if(t)return t;let e=process.env.OPENCLAW_CONFIG_PATH?.trim();return e?f0(e):j2(n,".openclaw")}function y0(n){let t=process.env.OPENCLAW_CONFIG_PATH?.trim();return t?t:j2(h0(n),"openclaw.json")}function Ae(n){return j2(h0(n),"extensions",q)}function ki(n){let t=$i(n);if(t.length===0)return!0;if(t.some((a)=>!mi.includes(a)))return!1;let e=j2(n,V),r=S(e);return r!==void 0&&!r.isSymbolicLink()&&r.isFile()&&gi(e,"utf-8").startsWith(at)}function We(n){let t=Ae(n),e=S(t);if(!e)return;if(!e.isSymbolicLink()&&e.isDirectory()&&ki(t))return;throw Error(`Refusing to modify ${t}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function w0(){let n=f0(Di(import.meta.url));return[j2(n,"..",b0),j2(n,"..","..","..","dist",b0)]}function Re(n=w0()){return n.find((t)=>wi(t)&&xi(t).isDirectory())}function qi(n=w0()){let t=Re(n);if(!t)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return t}function x0(n=qi()){return[["openclaw","plugins","install",n,"--force"],["openclaw","plugins","enable",q]]}function ji(n){let t=(()=>{try{return JSON.parse(n)}catch{return}})(),e=$($(t,"plugin"),"status");return typeof e==="string"?e:void 0}async function $0(){let n=ji(await e2(["openclaw","plugins","inspect",q,"--runtime","--json"],{stdoutOnly:!0}));if(n==="loaded")return;throw Error(`${n===void 0?`The ${q} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${q} plugin with status "${n}".`} Run \`openclaw plugins inspect ${q} --runtime\` for details.`)}var lt="openclaw",zn=`run \`openclaw plugins enable ${q}\``;function nn(n,t){let e=Bn(n,t),r=S(e);if(!r)return{error:`${t} is missing from ${e}; run install --openclaw`};if(r.isSymbolicLink()||!r.isFile())return{error:`${e} is a symlink or not a regular file; move or remove it`};try{return{content:D0(e,"utf-8")}}catch(a){return{error:`Failed to read ${e}: ${a instanceof Error?a.message:String(a)}`}}}function m0(n){try{return JSON.parse(R(n))}catch{return}}function Fi(n){let t=nn(n,I2);if("error"in t)return t.error;if($(m0(t.content),"id")===q)return;return`${Bn(n,I2)} is not a valid ${q} manifest; run install --openclaw`}function zi(n){let t=nn(n,N2);if("error"in t)return t.error;let e=$($(m0(t.content),"openclaw"),"extensions");if(Array.isArray(e)&&e.includes(`./${V}`))return;return`${Bn(n,N2)} does not point OpenClaw at ${V}; run install --openclaw`}function g0(n){return Array.isArray(n)?n.filter((t)=>typeof t==="string"):[]}function Bi(n){let t=y0(n);if(!S(t))return`${q} is not enabled; ${zn}`;let e=(()=>{try{return JSON.parse(R(D0(t,"utf-8")))}catch{return}})();if(e===void 0)return`Failed to read ${t}; fix it, then ${zn}`;let r=$(e,"plugins");if($(r,"enabled")===!1)return`plugins.enabled is false in ${t}; no OpenClaw plugin loads`;let a=$($($(r,"entries"),q),"enabled");if(g0($(r,"deny")).includes(q)||a===!1)return`${q} is disabled in ${t}; ${zn}`;let l=g0($(r,"allow"));if(l.length>0&&!l.includes(q))return`plugins.allow in ${t} does not list ${q}; add it, then ${zn}`;if(l.includes(q)||a===!0)return;return`${q} is not enabled; ${zn}`}function k0(n){return/^\/\/ version:\s*(.+)$/m.exec(n)?.[1]?.trim()}function Ji(n,t,e){if(e===void 0)return[];let r=nn(e,V);if("error"in r||k0(r.content)!==t)return[];return[V,I2,N2].flatMap((a)=>{let l=nn(n,a),d=nn(e,a);if("error"in l||"error"in d||l.content===d.content)return[];return[`Modified ${a} occupies ${Bn(n,a)}; run install --openclaw to restore it`]})}function q0(n){let t=Ae(n.homeDir),e=En(lt,t);if(e)return e;let r=nn(t,V),l=["error"in r?r.error:r.content.startsWith(at)?void 0:`Unmanaged ${V} occupies ${Bn(t,V)}; move or remove it`,Fi(t),zi(t)].filter((L)=>L!==void 0),d="content"in r?k0(r.content):void 0,s=l.length>0?l:Ji(t,d,Re());if(s.length>0)return{platform:lt,status:"n/a",configPath:t,errors:s};let c=d===j()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],i=Bi(n.homeDir);if(i)return{platform:lt,status:"disabled",method:"plugin directory",configPath:t,errors:[i,...c]};return{platform:lt,status:"configured",method:"plugin directory",configPath:t,errors:c.length>0?c:void 0}}import{existsSync as Zi,readFileSync as Qi}from"node:fs";import{join as j0}from"node:path";function F0(n){let t=[],e=j0(n.homeDir,".config","opencode"),r=["opencode.json","opencode.jsonc"];for(let a of r){let l=j0(e,a);if(Zi(l))try{let d=Qi(l,"utf-8"),s=R(d);if((JSON.parse(s).plugin??[]).some((u)=>u.includes("cc-safety-net")))return{platform:"opencode",status:"configured",method:"plugin array",configPath:l,errors:t.length>0?t:void 0}}catch(d){t.push(`Failed to parse ${a}: ${d instanceof Error?d.message:String(d)}`)}}return{platform:"opencode",status:"n/a",errors:t.length>0?t:void 0}}import{join as Xi}from"node:path";function Ke(n){return Xi(n,".pi","agent","settings.json")}function Me(n){if(typeof n!=="string")return!1;return n==="npm:cc-safety-net"||n.startsWith("npm:cc-safety-net@")}function z0(n){let t=Ke(n.homeDir),e=n2(t);if(e.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(e.kind==="missing")return{platform:"pi",status:"n/a"};let r=$(e.value,"packages");if(!Array.isArray(r))return{platform:"pi",status:"n/a"};let a=r.find((s)=>Me(typeof s==="string"?s:$(s,"source")));if(a===void 0)return{platform:"pi",status:"n/a"};let l=$(a,"extensions");if(Array.isArray(l)&&l.some((s)=>typeof s==="string"&&s.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:t,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:t}}var Si={amp:Fa,"antigravity-cli":za,"claude-code":Qa,codex:Xa,"copilot-cli":Ca,cursor:Na,"gemini-cli":n0,"hermes-agent":u0,"kimi-code":Fn,openclaw:q0,opencode:F0,pi:z0};function tn(n,t){let e={...t,cwd:n,homeDir:t?.homeDir??Yi()};return j1.map((r)=>Hi(Si[r](e)))}function Hi(n){if(n.status==="not-inspected")return{platform:n.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:n.platform,detected:n.status!=="n/a",configured:n.status==="configured",inspectionStatus:n.status!=="n/a"?"verified":n.errors&&n.errors.length>0?"failed":"not-applicable",method:n.method,configPath:n.configPath,configPaths:n.configPaths,errors:n.errors}}import{tmpdir as Ai}from"node:os";import{join as Wi}from"node:path";var Ri=Object.freeze([{command:"git reset --hard",description:"git reset --hard",expectBlocked:!0},{command:"rm -rf /",description:"rm -rf /",expectBlocked:!0},{command:"rm -rf ./node_modules",description:"rm in cwd (safe)",expectBlocked:!1}]),Ki=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),safety:Object.freeze({}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),Mi={strict:!1,paranoidRm:!1,paranoidInterpreters:!1,worktreeMode:!1,effectiveLevel:"standard",capabilities:{fail_closed:{enabled:!1,source:"preset",sources:[]},paranoid_rm:{enabled:!1,source:"preset",sources:[]},paranoid_interpreters:{enabled:!1,source:"preset",sources:[]}},sources:{failClosed:[],paranoidRm:[],paranoidInterpreters:[],worktreeMode:[]}};function B0(){let n=Wi(Ai(),"cc-safety-net-self-test"),t=Ri.map((e)=>{let r=Kn(M2("self-test",{command:e.command},{kind:"command",shell:"auto"},{configCwd:n,executionCwd:n},e.command),{guard:{dependencies:{loadPolicySnapshot:()=>Ki,getModes:()=>Mi,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),a=e.expectBlocked?"blocked":"allowed",l=r.decision.kind==="deny"?"blocked":"allowed";return{command:e.command,description:e.description,expected:a,actual:l,passed:a===l,reason:r.decision.kind==="deny"?r.decision.reason:void 0,ruleId:r.decision.kind==="deny"?r.decision.ruleId:void 0}});return{passed:t.filter((e)=>e.passed).length,failed:t.filter((e)=>!e.passed).length,total:t.length,results:t}}function Ve(n){let t=F({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},n);if(r2(t.errors))return null;return{json:t.flags.json,skipUpdateCheck:t.flags.skipUpdateCheck}}async function J0(n={}){let t=await Dn(!n.json,()=>{let e=Vi(n);return{ready:e,finish:()=>e}},()=>gn(),{loadingMessage:"Checking system status…"});if(n.json)console.log(JSON.stringify(t,null,2));else Ci(t);return Gi(t.hooks,t.engineSelfTest,{userConfig:t.userConfig,projectConfig:t.projectConfig})?1:0}async function Vi(n){let t=n.cwd??process.cwd(),e=await xn(),r=tn(t,{ampPluginListOutput:e.ampPluginListOutput,codexPluginListOutput:e.codexPluginListOutput,copilotCliVersion:e.copilotCliVersion}),a=I1(t),l=N1(),d=W({cwd:t}),s=d.policy,c=d2(s),i=g2(s,c.capabilities),L=Cn(7),u=n.skipUpdateCheck?{currentVersion:j(),latestVersion:null,updateAvailable:!1}:await E2(),v={hooks:r,engineSelfTest:B0(),userConfig:a.userConfig,projectConfig:a.projectConfig,configState:fn(d),effectiveRules:a.effectiveRules,shadowedRules:a.shadowedRules,environment:l,effectiveSafety:{selectedPreset:s.safety.level??"standard",level:c.effectiveLevel,capabilities:c.capabilities,ruleOverrides:s.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(i).filter(([,p])=>p.source==="rule_override"&&p.override==="off"&&p.inheritedEnabled&&p.changesInherited).map(([p])=>p),ruleCounts:{stored:Object.keys(s.destructiveCommandRuleOverrides).length,effective:Object.values(i).filter((p)=>p.changesInherited).length}},posture:oa(a.userConfig.path),activity:L,update:u,system:e};return{...v,findings:ta(v)}}function Gi(n,t,e){return n.length>0&&n.every((r)=>!r.configured)||n.some((r)=>r.inspectionStatus==="failed")||t.failed>0||e.userConfig.exists&&!e.userConfig.valid||e.projectConfig.exists&&!e.projectConfig.valid}function Ci(n){console.log(),console.log(ra(n.hooks)),console.log(),console.log(aa(n.engineSelfTest)),console.log(),console.log(la(n)),console.log(),console.log(da(n.environment)),console.log(),console.log(sa(n)),console.log(),console.log(ca(n.findings)),console.log(),console.log(ia(n.activity)),console.log(),console.log(pa(n.system)),console.log(),console.log(La(n.update)),console.log(ua(n))}import{existsSync as Ui}from"node:fs";var Oi=/^[A-Za-z0-9_@%+=:,./-]+$/,Z0="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Ge(n){let t=F({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},n);if(r2(t.errors))return console.error(Z0),console.error("Pass -- before a command that starts with dashes."),null;if(t.values.cwd!==void 0&&!Ui(t.values.cwd))return console.error(`Error: --cwd path does not exist: ${t.values.cwd}`),null;let e=t.positionals.length===1?t.positionals[0]:t.positionals.map((r)=>Oi.test(r)?r:`'${r.replaceAll("'","'\\''")}'`).join(" ");if(!e)return console.error("Error: No command provided"),console.error(Z0),null;return{json:t.flags.json,cwd:t.values.cwd,command:e}}function Q0(n){if(n)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function X0(n,t){let r=t-18;return[`${n.dtl}${n.dh.repeat(t)}${n.dtr}`,`${n.dv} Command Analysis${" ".repeat(r)}${n.dv}`,`${n.dbl}${n.dh.repeat(t)}${n.dbr}`]}function Ce(n){return JSON.stringify(n)}function Y0(n,t=0){return`[${n.map((r,a)=>ea(r,a,t)).join(",")}]`}function dt(n,t,e=70){let r=n.split(" "),a=[],l="";for(let d of r)if(l&&l.length+d.length+1>e)a.push(l),l=d;else l=l?`${l} ${d}`:d;if(l)a.push(l);return a.map((d,s)=>s===0?d:`${t}${d}`)}function S0(n,t,e){let r=[];switch(n.type){case"parse":return null;case"env-strip":{r.push(""),r.push(`STEP ${t} ${e.h} Strip environment variables`);let a=Object.keys(n.envVars);return r.push(` Removed: ${a.map((l)=>`${l}=<redacted>`).join(", ")}`),r.push(` Tokens: ${Ce(n.output)}`),{lines:r,incrementStep:!0}}case"leading-tokens-stripped":return r.push(""),r.push(`STEP ${t} ${e.h} Strip wrappers`),r.push(` Removed: ${n.removed.join(", ")}`),r.push(` Tokens: ${Ce(n.output)}`),{lines:r,incrementStep:!0};case"shell-wrapper":return r.push(""),r.push(`STEP ${t} ${e.h} Detect shell wrapper`),r.push(` Wrapper: ${n.wrapper} -c`),r.push(` Inner: ${n.innerCommand}`),{lines:r,incrementStep:!0};case"interpreter":{if(r.push(""),r.push(`STEP ${t} ${e.h} Detect interpreter`),r.push(` Interpreter: ${n.interpreter}`),r.push(` Code: ${n.codeArg}`),n.paranoidBlocked)r.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:r,incrementStep:!0}}case"busybox":return r.push(""),r.push(`STEP ${t} ${e.h} Busybox wrapper`),r.push(` Subcommand: ${n.subcommand}`),{lines:r,incrementStep:!0};case"transparent-wrapper":return r.push(""),r.push(`STEP ${t} ${e.h} Transparent wrapper`),r.push(` Wrapper: ${n.wrapper}`),r.push(` Tokens: ${Ce(n.output)}`),{lines:r,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{r.push(""),r.push(`STEP ${t} ${e.h} Match rules`);let a=`${n.ruleModule}:${n.ruleFunction}()`;if(r.push(` Rule: ${a}`),n.matched)r.push(" Result: MATCHED");else r.push(" Result: No match");return{lines:r,incrementStep:!0}}case"worktree-relaxation":return r.push(""),r.push(`STEP ${t} ${e.h} Worktree relaxation`),r.push(` Mode: ${m.worktree.name}`),r.push(` Git cwd: ${n.gitCwd}`),r.push(" Result: Allowed local discard in linked worktree"),{lines:r,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(n.embeddedCommandFound)return r.push(""),r.push(`STEP ${t} ${e.h} Fallback scan`),r.push(` Found: ${n.embeddedCommandFound}`),{lines:r,incrementStep:!0};return null}case"custom-rules-check":{if(n.rulesChecked){if(r.push(""),r.push(`STEP ${t} ${e.h} Custom rules`),n.matched)r.push(" Result: MATCHED");else r.push(" Result: No match");return{lines:r,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(n.matched)return r.push(""),r.push(`STEP ${t} ${e.h} Dangerous text check`),r.push(` Token: ${n.token}`),r.push(" Result: MATCHED"),{lines:r,incrementStep:!0};return null}case"strict-unparseable":return r.push(""),r.push(`STEP ${t} ${e.h} Strict mode check`),r.push(` Command: ${n.rawCommand}`),r.push(" Result: ✗ UNPARSEABLE"),{lines:r,incrementStep:!0};case"segment-skipped":return null;case"error":return r.push(""),r.push(`ERROR: ${n.message}`),{lines:r,incrementStep:!1};default:return null}}function Ue(n,t){let e=Q0(t?.asciiOnly??!1),r=58,a=[],l=1;a.push(...X0(e,58)),a.push("");let d=n.trace.steps.find((p)=>p.type==="error");if(d&&d.type==="error"){a.push("ERROR"),a.push(` ${d.message}`),a.push(""),a.push("RESULT"),a.push(` Status: ${n.result==="blocked"?b.red("BLOCKED"):b.green("ALLOWED")}`),a.push(""),a.push("CONFIG");let p=n.configSource??"none";return a.push(` Path: ${p}`),a.join(`
177
- `)}let s=n.trace.steps.find((p)=>p.type==="parse");if(s&&s.type==="parse"){a.push("INPUT"),a.push(` ${s.input}`),a.push(""),a.push(`STEP ${l} ${e.h} Split shell commands`),l++;for(let p=0;p<s.segments.length;p++){let f=s.segments[p];if(f){let o=Math.random();a.push(` Segment ${p+1}: ${Y0(f,o)}`)}}}let c=n.trace.segments,i=c.length>1;for(let p of c){if(i){a.push("");let x="";if(s&&s.type==="parse"){let Ft=s.segments[p.index];if(Ft)x=Ft.join(" ")}let w=54,y=x,J=` Segment ${p.index+1}: `,Z2=" ";if(x){if(J.length+x.length+Z2.length>w){let X3=w-J.length-Z2.length;y=`${x.substring(0,X3-1)}…`}}let ln=x?`${J}${y}${Z2}`:` Segment ${p.index+1} `,jt=x?`${J}${b.cyan(y)}${Z2}`:ln,wr=58-ln.length,xr=Math.floor(wr/2),Q3=wr-xr;a.push(`${e.sh.repeat(xr)}${jt}${e.sh.repeat(Q3)}`)}if(p.steps.find((x)=>x.type==="segment-skipped")){a.push(""),a.push(" (skipped — prior segment blocked)");continue}let o=!1,h=!1;for(let x of p.steps){let w=S0(x,l,e);if(w){if(h=!0,x.type==="recurse"){a.push("");let y=" RECURSING ",J=58-y.length-4;a.push(` ${e.tl}${e.h}${y}${e.h.repeat(J)}`),a.push(` ${e.v}`),o=!0;continue}for(let y of w.lines)if(o)a.push(` ${e.v} ${y}`);else a.push(y);if(w.incrementStep)l++}}if(o)a.push(` ${e.v}`),a.push(` ${e.bl}${e.h.repeat(56)}`),o=!1;if(!h)a.push(""),a.push(` ${b.green("✓")} Allowed (no matching rules)`)}if(a.push(""),a.push("RESULT"),n.result==="blocked"){if(a.push(` Status: ${b.red("BLOCKED")}`),n.customRule){if(a.push(` Rule: ${n.customRule.id}`),n.customRule.rulebook)a.push(` Rulebook: ${n.customRule.rulebook.name} ${n.customRule.rulebook.version}`);if(n.customRule.source)a.push(` Source: ${n.customRule.source}`);if(n.customRule.override)a.push(` Override: reason ${n.customRule.override.reason}`)}if(n.reason){let p=dt(n.reason," ");a.push(` Reason: ${p[0]}`);for(let f=1;f<p.length;f++)a.push(p[f]??"")}}else a.push(` Status: ${b.green("ALLOWED")}`);a.push(""),a.push("CONFIG");let L=n.configSource??"none",u=n.configValid?"":" (invalid)";a.push(` Path: ${L}${u}`),a.push(` Safety preset: ${n.selectedPreset??"standard"}`),a.push(` Effective capabilities: ${n.effectiveLevel}`);let v=Object.entries(n.destructiveCommandRuleOverrides??{});if(a.push(` Rule customizations: ${v.length}`),n.ruleActivation)a.push(` Rule activation: ${n.ruleActivation.id} — ${n.ruleActivation.enabled?"on":"off"} via ${n.ruleActivation.source}`);return a.join(`
178
- `)}function Oe(n){return JSON.stringify(n,null,2)}var H0="2.0.6",G=" ",F2="cc-safety-net";function A0(n){return n.argument?`${n.flags} ${n.argument}`:n.flags}function Ti(n){return Math.max(...n.map((t)=>A0(t).length))}function _i(n){return Math.max(...n.map((t)=>t.usage.length))}function Ei(n){return Math.max(...n.map((t)=>`${F2} ${t.usage}`.length))}function Pi(n,t){let e=`${F2} ${n.usage}`;return`${G}${e.padEnd(t+2)}${n.description}`}function L2(n,t){return`${G}${n.padEnd(Math.max(40,n.length+2))}${t}`}function st(n,t=console.log){let e=[];if(e.push(`${F2} ${n.name}`),e.push(""),e.push(`${G}${n.description}`),e.push(""),e.push("USAGE:"),e.push(`${G}${F2} ${n.usage}`),e.push(""),n.subcommands&&n.subcommands.length>0){e.push("SUBCOMMANDS:");let r=_i(n.subcommands);for(let a of n.subcommands)e.push(`${G}${a.usage.padEnd(r+2)}${a.description}`);e.push("")}if(n.options.length>0){e.push("OPTIONS:");let r=Ti(n.options);for(let a of n.options){let l=A0(a),d=a.default?`${a.description} (default: ${a.default})`:a.description;e.push(`${G}${l.padEnd(r+2)}${d}`)}e.push("")}if(n.examples&&n.examples.length>0){e.push("EXAMPLES:");for(let r of n.examples)e.push(`${G}${r}`)}t(e.join(`
179
- `))}function Te(){let n=E1(),t=Ei(n),e=[];e.push(`${F2} v${H0}`),e.push(""),e.push("Blocks destructive commands and secret access."),e.push(""),e.push("COMMANDS:");for(let r of n)e.push(Pi(r,t));e.push(""),e.push("GLOBAL OPTIONS:"),e.push(`${G}-h, --help Show help (use with command for command-specific help)`),e.push(`${G}-V, --version Show version`),e.push(""),e.push("HELP:"),e.push(`${G}${F2} help <command> Show help for a specific command`),e.push(`${G}${F2} <command> --help Show help for a specific command`),e.push(""),e.push("ENVIRONMENT VARIABLES:"),e.push(L2(`${m.level.name}=standard|strict|paranoid`,"Set session safety level")),e.push(L2(`${m.worktree.name}=1`,"Allow local git discards in linked worktrees")),e.push(L2(`${m.debug.name}=1`,"Print diagnostic messages to stderr")),e.push(L2(`${m.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),e.push(L2("CC_SAFETY_NET_HOME","Override rule config home directory")),e.push(""),e.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),e.push(L2(`${m.strict.name}=1`,"Force safety.overrides.fail_closed on")),e.push(L2(`${m.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),e.push(L2(`${m.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),e.push(L2(`${m.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),e.push(""),e.push("Documentation: https://ccsafetynet.com/docs"),console.log(e.join(`
180
- `))}function W0(){console.log(H0)}function Jn(n,t=console.log){let e=Gn(n);if(!e)return!1;if(e.hidden||e.name.toLowerCase()!==n.toLowerCase())return!1;return st(e,t),!0}import{existsSync as ir,readFileSync as Ml}from"node:fs";import{homedir as EL}from"node:os";import{join as sr}from"node:path";import*as h2 from"node:readline";function Ii(n){return n==="install"?"Install":"Uninstall"}function Ni(n){return n==="install"?"Installing":"Uninstalling"}function nL(n){return n==="install"?"into":"from"}function M0(n){return n?.available===!0}function tL(n,t){let e=new Set(t);return n.filter((r)=>e.has(r.target)).map((r)=>r.target)}function R0(n,t,e){if(n.length===0||n.every((r)=>!r.available))return t;return Array.from({length:n.length},(r,a)=>a+1).map((r)=>(t+r*e+n.length)%n.length).find((r)=>M0(n[r]))}function eL(n,t,e){if(e.ctrl&&e.name==="c")return"interrupt";if(e.name==="escape"||t==="q")return"abort";if(n==="install"&&(t==="u"||t==="U"))return"update";if(e.name==="up"||t==="k")return"up";if(e.name==="down"||t==="j")return"down";if(e.name==="space"||t===" ")return"toggle";if(e.name==="return"||e.name==="enter")return"confirm";return null}function rL(n){return{cursor:n.findIndex((t)=>t.available),selected:[]}}function aL(n,t,e){if(e==="confirm"||e==="update"||e==="abort"||e==="interrupt")return{state:n,done:e};if(e==="up")return{state:{...n,cursor:R0(t,n.cursor,-1)}};if(e==="down")return{state:{...n,cursor:R0(t,n.cursor,1)}};let r=t[n.cursor];if(!M0(r))return{state:n};let a=n.selected.includes(r.target)?n.selected.filter((l)=>l!==r.target):tL(t,[...n.selected,r.target]);return{state:{...n,selected:a}}}var V0="◉",G0="◯",C0=">",U0=" ";function lL(n,t,e,r={}){let a=r.color!==!1,l=a?b.dim:(c)=>c,d=a?b.green:(c)=>c,s=a?b.bold:(c)=>c;return["",`${Ii(n)} CC Safety Net ${nL(n)}:`,"",...t.map((c,i)=>{let L=e.selected.includes(c.target),u=i===e.cursor,v=L?V0:G0,p=u?C0:U0,f=c.available?"":` (${c.unavailableReason??"not installed"})`,o=`${v} ${c.label}${f}`,h=!c.available?l(o):L?d(o):u?s(o):o;return`${p} ${h}`}),"",n==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":t.some((c)=>c.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${n}. q/Esc: close`].join(`
181
- `)}var K0=["global-hook","plugin"];function dL(n,t,e={}){let r=e.color!==!1?b.bold:(l)=>l;return["","Install the Kimi Code integration as:","",...[`Global hook — ${t?"already installed; selecting it reports the current state":"write the hook into ~/.kimi-code/config.toml now"}`,"Native Kimi plugin — print the steps to run inside Kimi Code"].map((l,d)=>{let s=d===n,c=`${s?V0:G0} ${l}`;return`${s?C0:U0} ${s?r(c):c}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
182
- `)}function O0(n){let{input:t,output:e}=n;h2.emitKeypressEvents(t);let r=t.isRaw===!0;t.setRawMode(!0),t.resume();let a=0,l=()=>{if(a===0)return;h2.moveCursor(e,0,-a),h2.cursorTo(e,0),h2.clearScreenDown(e)},d=()=>{l();let s=n.render();e.write(`${s}
183
- `),a=s.split(`
184
- `).length};return new Promise((s)=>{let c=(L)=>{t.off("keypress",i),t.setRawMode(r),t.pause(),l(),s(L)};function i(L,u){n.onKey(L,u,{finish:c,draw:d})}t.on("keypress",i),d()})}function T0(n={}){let t=0;return O0({input:n.input??process.stdin,output:n.output??process.stdout,render:()=>dL(t,n.globalHookInstalled===!0),onKey:(e,r,a)=>{if(r.ctrl&&r.name==="c"){a.finish(null),(n.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(r.name==="escape"||e==="q")return a.finish(null);if(r.name==="return"||r.name==="enter")return a.finish(K0[t]);if(r.name==="up"||r.name==="down"||e==="k"||e==="j")t=(t+1)%K0.length,a.draw()}})}function _e(n=process.stdin,t=process.stdout){return Boolean(n.isTTY&&t.isTTY&&typeof n.setRawMode==="function")}function _0(n,t,e={}){let r=e.output??process.stdout,a=rL(t);return O0({input:e.input??process.stdin,output:r,render:()=>lL(n,t,a),onKey:(l,d,s)=>{let c=eL(n,l,d);if(!c)return;let i=aL(a,t,c);if(a=i.state,i.done==="interrupt"){s.finish(null),(e.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(i.done==="abort")return s.finish(null);if(i.done==="update")return s.finish("update");if(i.done==="confirm"){if(a.selected.length===0){r.write("\x07"),s.draw();return}s.finish([...a.selected]),r.write(`${Ni(n)} selected integrations...
185
- `);return}s.draw()}})}import{existsSync as P0,lstatSync as I0,mkdtempSync as cL,readFileSync as Lt,rmSync as N0}from"node:fs";import{tmpdir as iL}from"node:os";import{dirname as LL,join as z2}from"node:path";import{fileURLToPath as pL}from"node:url";var Ee="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp";import{spawn as sL}from"node:child_process";var Pe=(n,t)=>{let e=f2([...n],process.env);return new Promise((r)=>{let a=sL(e.cmd,e.args,{cwd:t,stdio:["ignore","pipe","pipe"]}),l=Se(a),d=!1,s=setTimeout(()=>{d=!0,a.kill()},120000);a.on("error",(c)=>{clearTimeout(s),r({status:null,errorCode:c.code,stdout:l.stdout,stderr:[c.message,l.stderr].filter(Boolean).join(`
186
- `)})}),a.on("close",(c)=>{clearTimeout(s),r({status:d?null:c,errorCode:d?"ETIMEDOUT":void 0,stdout:l.stdout,stderr:l.stderr})})})};var E0=z2("amp","cc-safety-net.ts"),p2="cc-safety-net.ts";function uL(n){return z2(n,".config","amp","plugins",p2)}function oL(){let n=LL(pL(import.meta.url));return[z2(n,"..",E0),z2(n,"..","..","..","dist",E0)]}function vL(n=oL()){let t=n.find((e)=>P0(e)&&I0(e).isFile());if(!t)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return t}function nl(n){try{return I0(n)}catch{return}}function tl(n){try{return JSON.parse(n)}catch{return}}function el(n){return n.subarray(0,Buffer.byteLength(Ee)).toString("utf-8")===Ee}async function Zn(n,t,e){let r=await n(t,e);if(r.status===0)return r;throw Error([`Failed to run ${t.join(" ")}${r.status===null?"":` (exit ${r.status})`}.`,[r.stdout,r.stderr].filter(Boolean).join(`
178
+ `}function Jn(n){return[{name:"__init__.py",content:bL(n)},{name:"plugin.yaml",content:uL(n)}]}import{mkdirSync as oL,readdirSync as fL,readFileSync as yL,rmSync as S1}from"node:fs";import{join as J2}from"node:path";var hL="__pycache__";function H1(n){let t=process.env.HERMES_HOME?.trim();return t?t:J2(n,".hermes")}function W1(n){return J2(H1(n),"plugins",U)}function K1(n){return n.startsWith(i0)}function R1(n,t){let r=W1(n),e=F(r);if(e&&(e.isSymbolicLink()||!e.isDirectory()))throw Error(`Refusing to ${t} ${r}: not a regular directory. Move or remove it and rerun ${t==="install"?"install":"uninstall"} --hermes-agent.`);return r}function v0(n,t){let r=F(n);if(!r)return;if(r.isSymbolicLink()||!r.isFile())throw Error(`Refusing to ${t} ${n}: not a regular file. Move or remove it.`);let e=yL(n,"utf-8");if(!K1(e))throw Error(`Refusing to ${t} unmanaged file at ${n}. Move or remove it.`);return e}function u0(n){let t=R1(n,"install"),r=Jn(B());if(r.map((a)=>v0(J2(t,a.name),"overwrite")).every((a,l)=>a===r[l]?.content))return{path:t,alreadyInstalled:!0};return oL(t,{recursive:!0}),r.forEach((a)=>{Q(J2(t,a.name),a.content)}),{path:t,alreadyInstalled:!1}}function V1(n){let t=R1(n,"remove");if(!F(t))return[];return Jn(B()).filter((r)=>v0(J2(t,r.name),"remove")!==void 0)}function b0(n){let t=R1(n,"remove");if(!F(t))return{path:t,alreadyInstalled:!1};let r=V1(n);if(r.forEach((e)=>{S1(J2(t,e.name))}),S1(J2(t,hL),{recursive:!0,force:!0}),fL(t).length===0)S1(t,{recursive:!0});return{path:t,alreadyInstalled:r.length>0}}var ct="hermes-agent",o0=/^([^\s#][^:]*):/,wL=/^\s+([A-Za-z_][\w-]*):/,f0=/^\s+-\s*(.*)$/;function xL(n){return n.trim().replace(/^(["'])(.*)\1$/,"$2")}function $L(n){let t=n.split(/\r?\n/),r=t.findIndex((l)=>o0.exec(l)?.[1]?.trim()==="plugins");if(r===-1)return[];let e=t.slice(r+1),a=e.findIndex((l)=>o0.test(l));return a===-1?e:e.slice(0,a)}function y0(n,t){let r=$L(n),e=r.findIndex((s)=>wL.exec(s)?.[1]===t);if(e===-1)return[];let a=r.slice(e+1),l=a.findIndex((s)=>!f0.test(s));return(l===-1?a:a.slice(0,l)).map((s)=>xL(f0.exec(s)?.[1]??""))}function DL(n){try{return h0(w0(H1(n),"config.yaml"),"utf-8")}catch{return}}function A1(n){let t=DL(n)??"";return y0(t,"enabled").includes(U)&&!y0(t,"disabled").includes(U)}function x0(n){return/^# version:\s*(.+)$/m.exec(n)?.[1]?.trim()}function mL(n,t){let r=F(n);if(!r)return{error:`${t.name} is missing from ${n}; run install --hermes-agent`};if(r.isSymbolicLink()||!r.isFile())return{error:`${n} is a symlink or not a regular file; move or remove it`};try{let e=h0(n,"utf-8");if(!K1(e))return{error:`Unmanaged ${t.name} occupies ${n}; move or remove it`};if(x0(e)===B()&&e!==t.content)return{error:`Modified ${t.name} occupies ${n}; run install --hermes-agent to restore it`};return{content:e}}catch(e){return{error:`Failed to read ${n}: ${e instanceof Error?e.message:String(e)}`}}}function $0(n){let t=W1(n.homeDir),r=tt(ct,t);if(r)return r;let e=Jn(B()).map((d)=>mL(w0(t,d.name),d)),a=e.flatMap((d)=>("error"in d)?[d.error]:[]);if(a.length>0)return{platform:ct,status:"n/a",configPath:t,errors:a};let l=e.some((d)=>("content"in d)&&x0(d.content)!==B()),s=l?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!A1(n.homeDir))return{platform:ct,status:"disabled",method:"plugin directory",configPath:t,errors:[`${U} is not enabled in Hermes; run \`hermes plugins enable ${U}\``,...s]};return{platform:ct,status:"configured",method:"plugin directory",configPath:t,errors:l?s:void 0}}import{existsSync as gL,readFileSync as kL}from"node:fs";import{join as D0}from"node:path";var qL=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function jL(n){return D0(process.env.KIMI_CODE_HOME||D0(n,".kimi-code"),"config.toml")}function Zn(n){let t=jL(n.homeDir);if(!gL(t))return{platform:"kimi-code",status:"n/a",configPath:t};try{if(!qL.test(kL(t,"utf-8")))return{platform:"kimi-code",status:"n/a",configPath:t}}catch(r){return{platform:"kimi-code",status:"n/a",configPath:t,errors:[`Failed to read ${t}: ${r instanceof Error?r.message:String(r)}`]}}return{platform:"kimi-code",status:"configured",method:"hook config",configPath:t}}import{readFileSync as Z0}from"node:fs";import{join as Xn}from"node:path";var z="cc-safety-net",C="index.js",tn="openclaw.plugin.json",rn="package.json";var Lt="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as BL,lstatSync as JL,readdirSync as ZL,readFileSync as QL}from"node:fs";import{dirname as k0,join as w2}from"node:path";import{fileURLToPath as XL}from"node:url";import{spawn as zL}from"node:child_process";function FL(n){return n.join(" ")}function M1(n,t,r){return[`Failed to run ${FL(n)}${t===null?"":` (exit ${t})`}.`,r.trim()].filter(Boolean).join(`
179
+ `)}function G1(n){let t={stdout:"",stderr:""};return n.stdout.setEncoding("utf-8"),n.stderr.setEncoding("utf-8"),n.stdout.on("data",(r)=>{t.stdout+=r}),n.stderr.on("data",(r)=>{t.stderr+=r}),t}function l2(n,t){return new Promise((r,e)=>{let a=h2([...n],process.env),l=zL(a.cmd,a.args,{stdio:["ignore","pipe","pipe"]}),s=G1(l),d=()=>[s.stdout,s.stderr].filter(Boolean).join(`
180
+ `),c=t?.timeoutMs??120000,L=setTimeout(()=>{l.kill(),e(Error(M1(n,null,`Timed out after ${c}ms.
181
+ ${d()}`.trim())))},c);l.on("error",(i)=>{clearTimeout(L),e(Error(M1(n,null,`${i.message}
182
+ ${d()}`.trim())))}),l.on("close",(i)=>{if(clearTimeout(L),i!==0){e(Error(M1(n,i,d())));return}r(t?.stdoutOnly?s.stdout:d())})})}async function U1(n){for(let t of n)await l2(t)}async function m0(n){for(let t of n)try{await l2(t)}catch(r){console.warn(r instanceof Error?r.message:String(r))}}var g0=w2("openclaw",z),YL=[C,tn,rn];function C1(n,t){if(n==="~")return t;if(n.startsWith("~/")||n.startsWith("~\\"))return w2(t,n.slice(2));return n}function q0(n){let t=process.env.OPENCLAW_STATE_DIR?.trim();if(t)return C1(t,n);let r=process.env.OPENCLAW_CONFIG_PATH?.trim();return r?k0(C1(r,n)):w2(n,".openclaw")}function j0(n){let t=process.env.OPENCLAW_CONFIG_PATH?.trim();return t?C1(t,n):w2(q0(n),"openclaw.json")}function O1(n){return w2(q0(n),"extensions",z)}function SL(n){let t=ZL(n);if(t.length===0)return!0;if(t.some((a)=>!YL.includes(a)))return!1;let r=w2(n,C),e=F(r);return e!==void 0&&!e.isSymbolicLink()&&e.isFile()&&QL(r,"utf-8").startsWith(Lt)}function T1(n){let t=O1(n),r=F(t);if(!r)return;if(!r.isSymbolicLink()&&r.isDirectory()&&SL(t))return;throw Error(`Refusing to modify ${t}: it does not hold a cc-safety-net managed OpenClaw plugin. Move or remove it, then run the command again.`)}function z0(){let n=k0(XL(import.meta.url));return[w2(n,"..",g0),w2(n,"..","..","..","dist",g0)]}function _1(n=z0()){return n.find((t)=>BL(t)&&JL(t).isDirectory())}function HL(n=z0()){let t=_1(n);if(!t)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return t}function F0(n=HL()){return[["openclaw","plugins","install",n,"--force"],["openclaw","plugins","enable",z]]}function WL(n){let t=(()=>{try{return JSON.parse(n)}catch{return}})(),r=x(x(t,"plugin"),"status");return typeof r==="string"?r:void 0}async function B0(){let n=WL(await l2(["openclaw","plugins","inspect",z,"--runtime","--json"],{stdoutOnly:!0}));if(n==="loaded")return;throw Error(`${n===void 0?`The ${z} plugin's load state could not be verified: OpenClaw's runtime inspect report was unreadable.`:`OpenClaw reports the ${z} plugin with status "${n}".`} Run \`openclaw plugins inspect ${z} --runtime\` for details.`)}var it="openclaw",Qn=`run \`openclaw plugins enable ${z}\``;function en(n,t){let r=Xn(n,t),e=F(r);if(!e)return{error:`${t} is missing from ${r}; run install --openclaw`};if(e.isSymbolicLink()||!e.isFile())return{error:`${r} is a symlink or not a regular file; move or remove it`};try{return{content:Z0(r,"utf-8")}}catch(a){return{error:`Failed to read ${r}: ${a instanceof Error?a.message:String(a)}`}}}function Q0(n){try{return JSON.parse(M(n))}catch{return}}function KL(n){let t=en(n,tn);if("error"in t)return t.error;if(x(Q0(t.content),"id")===z)return;return`${Xn(n,tn)} is not a valid ${z} manifest; run install --openclaw`}function RL(n){let t=en(n,rn);if("error"in t)return t.error;let r=x(x(Q0(t.content),"openclaw"),"extensions");if(Array.isArray(r)&&r.includes(`./${C}`))return;return`${Xn(n,rn)} does not point OpenClaw at ${C}; run install --openclaw`}function J0(n){return Array.isArray(n)?n.filter((t)=>typeof t==="string"):[]}function VL(n){let t=j0(n);if(!F(t))return`${z} is not enabled; ${Qn}`;let r=(()=>{try{return JSON.parse(M(Z0(t,"utf-8")))}catch{return}})();if(r===void 0)return`Failed to read ${t}; fix it, then ${Qn}`;let e=x(r,"plugins");if(x(e,"enabled")===!1)return`plugins.enabled is false in ${t}; no OpenClaw plugin loads`;let a=x(x(x(e,"entries"),z),"enabled");if(J0(x(e,"deny")).includes(z)||a===!1)return`${z} is disabled in ${t}; ${Qn}`;let l=J0(x(e,"allow"));if(l.length>0&&!l.includes(z))return`plugins.allow in ${t} does not list ${z}; add it, then ${Qn}`;if(l.includes(z)||a===!0)return;return`${z} is not enabled; ${Qn}`}function X0(n){return/^\/\/ version:\s*(.+)$/m.exec(n)?.[1]?.trim()}function AL(n,t,r){if(r===void 0)return[];let e=en(r,C);if("error"in e||X0(e.content)!==t)return[];return[C,tn,rn].flatMap((a)=>{let l=en(n,a),s=en(r,a);if("error"in l||"error"in s||l.content===s.content)return[];return[`Modified ${a} occupies ${Xn(n,a)}; run install --openclaw to restore it`]})}function Y0(n){let t=O1(n.homeDir),r=tt(it,t);if(r)return r;let e=en(t,C),l=["error"in e?e.error:e.content.startsWith(Lt)?void 0:`Unmanaged ${C} occupies ${Xn(t,C)}; move or remove it`,KL(t),RL(t)].filter((i)=>i!==void 0),s="content"in e?X0(e.content):void 0,d=l.length>0?l:AL(t,s,_1());if(d.length>0)return{platform:it,status:"n/a",configPath:t,errors:d};let c=s===B()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],L=VL(n.homeDir);if(L)return{platform:it,status:"disabled",method:"plugin directory",configPath:t,errors:[L,...c]};return{platform:it,status:"configured",method:"plugin directory",configPath:t,errors:c.length>0?c:void 0}}import{existsSync as NL,readFileSync as ni}from"node:fs";import{join as ti}from"node:path";import{existsSync as E1,readFileSync as R0,rmSync as GL}from"node:fs";import{join as u2}from"node:path";import{pathToFileURL as UL}from"node:url";function S0(n){return n!==void 0&&/\s/.test(n)}function ML(n,t,r){let e=t+1,a=!1;while(e<n.length){let l=n[e];if(a){a=!1,e++;continue}if(l==="\\"){a=!0,e++;continue}if(l==='"')return e+1;e++}throw Error(r)}function pt(n,t,r){let e=n[t],a=e==="["?"]":"}",l=0,s=t;while(s<n.length){let d=r.skipComment?.(n,s)??s;if(d!==s){s=d;continue}if(n[s]==='"'){s=ML(n,s,r.stringError);continue}if(n[s]===e)l++;if(n[s]===a){if(l--,l===0)return s}s++}throw Error(r.bracketError)}function H0(n,t){let r=n.lastIndexOf(`
183
+ `,t)+1;return/^[ \t]*/.exec(n.slice(r))?.[0]??""}function vt(n,t){let{start:r,end:e,end:a}=t;while(S0(n[a]))a++;if(n[a]===","){if(e=a+1,n[e]===`
184
+ `)e++;return`${n.slice(0,r)}${n.slice(e)}`}a=t.start-1;while(S0(n[a]))a--;if(n[a]===","){r=a;let l=n.lastIndexOf(`
185
+ `,r-1);if(l!==-1&&/^\s*$/.test(n.slice(l+1,r)))r=l}return`${n.slice(0,r)}${n.slice(e)}`}var ut="cc-safety-net",V0=`${ut}@latest`,A0=["opencode.json","opencode.jsonc"],W0="CCSafetyNetPlugin";function bt(n){return u2(process.env.XDG_CONFIG_HOME||u2(n,".config"),"opencode")}function CL(n){return u2(bt(n),A0[0])}function OL(n){return A0.map((t)=>u2(bt(n),t))}function M0(n){return u2(process.env.XDG_CACHE_HOME||u2(n,".cache"),"opencode","packages",V0)}function P1(n){GL(M0(n),{recursive:!0,force:!0})}async function G0(n){let t=u2(M0(n),"node_modules",ut),r=u2(t,"package.json");if(!E1(r))throw Error(`The OpenCode plugin cache at ${t} is missing its package, so OpenCode would load nothing and fail open. Run \`opencode plugin -g -f ${V0}\` for details.`);let e=x(JSON.parse(R0(r,"utf-8")),"main");if(typeof e!=="string")throw Error(`The cached OpenCode plugin at ${t} declares no "main" entry.`);let a=u2(t,e);if(typeof(await import(UL(a).href))[W0]==="function")return;throw Error(`The cached OpenCode plugin at ${a} does not export a callable ${W0}, so OpenCode would load nothing and fail open.`)}function ot(n,t){if(n[t]==="/"&&n[t+1]==="/"){let r=n.indexOf(`
186
+ `,t+2);return r===-1?n.length:r+1}if(n[t]==="/"&&n[t+1]==="*"){let r=n.indexOf("*/",t+2);return r===-1?n.length:r+2}return t}function K0(n,t){let r=t;while(r<n.length){if(/\s/.test(n[r]??"")){r++;continue}let e=ot(n,r);if(e===r)return r;r=e}return r}function U0(n,t){let r=t+1,e=!1;while(r<n.length){if(e){e=!1,r++;continue}if(n[r]==="\\"){e=!0,r++;continue}if(n[r]==='"')return r+1;r++}throw Error("Unterminated string in OpenCode config")}function C0(n,t,r){return JSON.parse(n.slice(t,r))}function TL(n,t){return pt(n,t,{skipComment:ot,stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"})}function _L(n){let t=0,r=0;while(r<n.length){let e=ot(n,r);if(e!==r){r=e;continue}if(n[r]==='"'){let a=U0(n,r);if(t===1&&C0(n,r,a)==="plugin"){let l=K0(n,a),s=K0(n,l+1);if(n[l]===":"&&n[s]==="[")return{start:s,end:TL(n,s)}}r=a;continue}if(n[r]==="{"||n[r]==="[")t++;if(n[r]==="}"||n[r]==="]")t--;r++}return}function EL(n,t){let r=[],e=t.start+1;while(e<t.end){let a=ot(n,e);if(a!==e){e=a;continue}if(n[e]==='"'){let l=U0(n,e),s=C0(n,e,l);if(typeof s==="string"&&s.includes(ut))r.push({start:e,end:l});e=l;continue}e++}return r}function O0(n,t){try{return JSON.parse(M(n))}catch(r){if(r instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${t}: ${r.message}`);throw r}}function PL(n){if(!n||typeof n!=="object"||Array.isArray(n))return!1;let t=n.plugin;if(!Array.isArray(t))return!1;return t.some((r)=>typeof r==="string"&&r.includes(ut))}function IL(n,t){let r=_L(n);if(!r)throw Error(`Failed to locate OpenCode plugin array in ${t}`);let e=[...EL(n,r)].reverse().reduce(vt,n);return O0(e,t),e}function T0(n){P1(n);let t=OL(n),r=t.find((a)=>E1(a)),e=[];for(let a of t){if(!E1(a))continue;try{let l=R0(a,"utf-8");if(!PL(O0(l,a)))continue;return Q(a,IL(l,a)),{path:a,alreadyInstalled:!0}}catch(l){e.push(l instanceof Error?l.message:String(l))}}if(e.length>0)throw Error(e.join(`
187
+ `));return{path:r??CL(n),alreadyInstalled:!1}}function _0(n){let t=[],r=bt(n.homeDir),e=["opencode.json","opencode.jsonc"];for(let a of e){let l=ti(r,a);if(NL(l))try{let s=ni(l,"utf-8"),d=M(s);if((JSON.parse(d).plugin??[]).some((v)=>v.includes("cc-safety-net")))return{platform:"opencode",status:"configured",method:"plugin array",configPath:l,errors:t.length>0?t:void 0}}catch(s){t.push(`Failed to parse ${a}: ${s instanceof Error?s.message:String(s)}`)}}return{platform:"opencode",status:"n/a",errors:t.length>0?t:void 0}}import{join as ri}from"node:path";function I1(n){return ri(n,".pi","agent","settings.json")}function N1(n){if(typeof n!=="string")return!1;return n==="npm:cc-safety-net"||n.startsWith("npm:cc-safety-net@")}function E0(n){let t=I1(n.homeDir),r=e2(t);if(r.kind==="unreadable")return{platform:"pi",status:"not-inspected"};if(r.kind==="missing")return{platform:"pi",status:"n/a"};let e=x(r.value,"packages");if(!Array.isArray(e))return{platform:"pi",status:"n/a"};let a=e.find((d)=>N1(typeof d==="string"?d:x(d,"source")));if(a===void 0)return{platform:"pi",status:"n/a"};let l=x(a,"extensions");if(Array.isArray(l)&&l.some((d)=>typeof d==="string"&&d.startsWith("-")))return{platform:"pi",status:"disabled",method:"package config",configPath:t,errors:["npm:cc-safety-net is installed but its extension is disabled in Pi settings"]};return{platform:"pi",status:"configured",method:"package config",configPath:t}}var ai={amp:Ha,"antigravity-cli":Wa,"claude-code":Aa,codex:Ma,"copilot-cli":n0,cursor:c0,"gemini-cli":L0,"hermes-agent":$0,"kimi-code":Zn,openclaw:Y0,opencode:_0,pi:E0};function an(n,t){let r={...t,cwd:n,homeDir:t?.homeDir??ei()};return On.map((e)=>li(ai[e](r)))}function li(n){if(n.status==="not-inspected")return{platform:n.platform,detected:!1,configured:!1,inspectionStatus:"not-inspected"};return{platform:n.platform,detected:n.status!=="n/a",configured:n.status==="configured",inspectionStatus:n.status!=="n/a"?"verified":n.errors&&n.errors.length>0?"failed":"not-applicable",method:n.method,configPath:n.configPath,configPaths:n.configPaths,errors:n.errors}}import{tmpdir as si}from"node:os";import{join as di}from"node:path";var ci=Object.freeze([{command:"git reset --hard",description:"git reset --hard",expectBlocked:!0},{command:"rm -rf /",description:"rm -rf /",expectBlocked:!0},{command:"rm -rf ./node_modules",description:"rm in cwd (safe)",expectBlocked:!1}]),Li=Object.freeze({state:"ready",diagnostics:Object.freeze([]),ruleMetadata:Object.freeze({}),policy:Object.freeze({rules:Object.freeze([]),transparentWrappers:Object.freeze([]),safety:Object.freeze({}),worktreeMode:!1,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:Object.freeze({}),destructiveCommandAllowPaths:Object.freeze([]),secretProtection:Object.freeze({enabled:!0,disabledRules:Object.freeze([]),denyPaths:Object.freeze([]),allowPaths:Object.freeze([])})})}),ii={strict:!1,paranoidRm:!1,paranoidInterpreters:!1,worktreeMode:!1,effectiveLevel:"standard",capabilities:{fail_closed:{enabled:!1,source:"preset",sources:[]},paranoid_rm:{enabled:!1,source:"preset",sources:[]},paranoid_interpreters:{enabled:!1,source:"preset",sources:[]}}};function P0(){let n=di(si(),"cc-safety-net-self-test"),t=ci.map((r)=>{let e=Un(C2("self-test",{command:r.command},{kind:"command",shell:"auto"},{configCwd:n,executionCwd:n},r.command),{guard:{dependencies:{loadPolicySnapshot:()=>Li,getModes:()=>ii,findPolicyMutation:()=>null}},audit:{agent:"self-test",getSessionId:()=>{return}}}),a=r.expectBlocked?"blocked":"allowed",l=e.decision.kind==="deny"?"blocked":"allowed";return{command:r.command,description:r.description,expected:a,actual:l,passed:a===l,reason:e.decision.kind==="deny"?e.decision.reason:void 0,ruleId:e.decision.kind==="deny"?e.decision.ruleId:void 0}});return{passed:t.filter((r)=>r.passed).length,failed:t.filter((r)=>!r.passed).length,total:t.length,results:t}}function nr(n){let t=J({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},n);if(s2(t.errors))return null;return{json:t.flags.json,skipUpdateCheck:t.flags.skipUpdateCheck}}async function I0(n={}){let t=await jn(!n.json,()=>{let r=pi(n);return{ready:r,finish:()=>r}},()=>qn(),{loadingMessage:"Checking system status…"});if(n.json)console.log(JSON.stringify(t,null,2));else ui(t);return vi(t.hooks,t.engineSelfTest,{userConfig:t.userConfig,projectConfig:t.projectConfig})?1:0}async function pi(n){let t=n.cwd??process.cwd(),r=await gn(),e=an(t,{ampPluginListOutput:r.ampPluginListOutput,codexPluginListOutput:r.codexPluginListOutput,copilotCliVersion:r.versions["copilot-cli"]}),a=da(t),l=ca(),s=A({cwd:t}),d=s.policy,c=L2(d),L=q2(d,c.capabilities),i=_n(7),v=n.skipUpdateCheck?{currentVersion:B(),latestVersion:null,updateAvailable:!1}:await I2(),b={hooks:e,engineSelfTest:P0(),userConfig:a.userConfig,projectConfig:a.projectConfig,configState:xn(s),effectiveRules:a.effectiveRules,shadowedRules:a.shadowedRules,environment:l,effectiveSafety:{selectedPreset:d.safety.level??"standard",level:c.effectiveLevel,capabilities:c.capabilities,ruleOverrides:d.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(L).filter(([,p])=>p.source==="rule_override"&&p.override==="off"&&p.inheritedEnabled&&p.changesInherited).map(([p])=>p),ruleCounts:{stored:Object.keys(d.destructiveCommandRuleOverrides).length,effective:Object.values(L).filter((p)=>p.changesInherited).length}},posture:Da(a.userConfig.path),activity:i,update:v,system:r};return{...b,findings:ia(b)}}function vi(n,t,r){return n.length>0&&n.every((e)=>!e.configured)||n.some((e)=>e.inspectionStatus==="failed")||t.failed>0||r.userConfig.exists&&!r.userConfig.valid||r.projectConfig.exists&&!r.projectConfig.valid}function ui(n){console.log(),console.log(va(n.hooks)),console.log(),console.log(ua(n.engineSelfTest)),console.log(),console.log(ba(n)),console.log(),console.log(oa(n.environment)),console.log(),console.log(fa(n)),console.log(),console.log(ya(n.findings)),console.log(),console.log(ha(n.activity)),console.log(),console.log(xa(n.system)),console.log(),console.log(wa(n.update)),console.log($a(n))}import{existsSync as bi}from"node:fs";var oi=/^[A-Za-z0-9_@%+=:,./-]+$/,N0="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function tr(n){let t=J({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},n);if(s2(t.errors))return console.error(N0),console.error("Pass -- before a command that starts with dashes."),null;if(t.values.cwd!==void 0&&!bi(t.values.cwd))return console.error(`Error: --cwd path does not exist: ${t.values.cwd}`),null;let r=t.positionals.length===1?t.positionals[0]:t.positionals.map((e)=>oi.test(e)?e:`'${e.replaceAll("'","'\\''")}'`).join(" ");if(!r)return console.error("Error: No command provided"),console.error(N0),null;return{json:t.flags.json,cwd:t.values.cwd,command:r}}function n3(n){if(n)return{dh:"=",dv:"|",dtl:"+",dtr:"+",dbl:"+",dbr:"+",h:"-",v:"|",tl:"+",tr:"+",bl:"+",br:"+",sh:"="};return{dh:"═",dv:"║",dtl:"╔",dtr:"╗",dbl:"╚",dbr:"╝",h:"─",v:"│",tl:"┌",tr:"┐",bl:"└",br:"┘",sh:"━"}}function t3(n,t){let e=t-18;return[`${n.dtl}${n.dh.repeat(t)}${n.dtr}`,`${n.dv} Command Analysis${" ".repeat(e)}${n.dv}`,`${n.dbl}${n.dh.repeat(t)}${n.dbr}`]}function rr(n){return JSON.stringify(n)}function r3(n,t=0){return`[${n.map((e,a)=>pa(e,a,t)).join(",")}]`}function ft(n,t,r=70){let e=n.split(" "),a=[],l="";for(let s of e)if(l&&l.length+s.length+1>r)a.push(l),l=s;else l=l?`${l} ${s}`:s;if(l)a.push(l);return a.map((s,d)=>d===0?s:`${t}${s}`)}function e3(n,t,r){let e=[];switch(n.type){case"parse":return null;case"env-strip":return e.push(""),e.push(`STEP ${t} ${r.h} Strip environment variables`),e.push(` Removed: ${n.envVars.map((a)=>`${a}=<redacted>`).join(", ")}`),e.push(` Tokens: ${rr(n.output)}`),{lines:e,incrementStep:!0};case"leading-tokens-stripped":return e.push(""),e.push(`STEP ${t} ${r.h} Strip wrappers`),e.push(` Removed: ${n.removed.join(", ")}`),e.push(` Tokens: ${rr(n.output)}`),{lines:e,incrementStep:!0};case"shell-wrapper":return e.push(""),e.push(`STEP ${t} ${r.h} Detect shell wrapper`),e.push(` Wrapper: ${n.wrapper} -c`),e.push(` Inner: ${n.innerCommand}`),{lines:e,incrementStep:!0};case"interpreter":{if(e.push(""),e.push(`STEP ${t} ${r.h} Detect interpreter`),e.push(` Interpreter: ${n.interpreter}`),e.push(` Code: ${n.codeArg}`),n.paranoidBlocked)e.push(" Result: ✗ BLOCKED (paranoid mode)");return{lines:e,incrementStep:!0}}case"busybox":return e.push(""),e.push(`STEP ${t} ${r.h} Busybox wrapper`),e.push(` Subcommand: ${n.subcommand}`),{lines:e,incrementStep:!0};case"transparent-wrapper":return e.push(""),e.push(`STEP ${t} ${r.h} Transparent wrapper`),e.push(` Wrapper: ${n.wrapper}`),e.push(` Tokens: ${rr(n.output)}`),{lines:e,incrementStep:!0};case"recurse":return{lines:[],incrementStep:!1};case"rule-check":{if(e.push(""),e.push(`STEP ${t} ${r.h} Match rules`),e.push(` Rule: ${n.rule}()`),n.matched)e.push(" Result: MATCHED");else e.push(" Result: No match");return{lines:e,incrementStep:!0}}case"worktree-relaxation":return e.push(""),e.push(`STEP ${t} ${r.h} Worktree relaxation`),e.push(` Mode: ${k.worktree.name}`),e.push(` Git cwd: ${n.gitCwd}`),e.push(" Result: Allowed local discard in linked worktree"),{lines:e,incrementStep:!0};case"tmpdir-check":return null;case"fallback-scan":{if(n.embeddedCommandFound)return e.push(""),e.push(`STEP ${t} ${r.h} Fallback scan`),e.push(` Found: ${n.embeddedCommandFound}`),{lines:e,incrementStep:!0};return null}case"custom-rules-check":{if(n.rulesChecked){if(e.push(""),e.push(`STEP ${t} ${r.h} Custom rules`),n.matched)e.push(" Result: MATCHED");else e.push(" Result: No match");return{lines:e,incrementStep:!0}}return null}case"cwd-change":return null;case"dangerous-text":{if(n.matched)return e.push(""),e.push(`STEP ${t} ${r.h} Dangerous text check`),e.push(` Token: ${n.token}`),e.push(" Result: MATCHED"),{lines:e,incrementStep:!0};return null}case"strict-unparseable":return e.push(""),e.push(`STEP ${t} ${r.h} Strict mode check`),e.push(` Command: ${n.rawCommand}`),e.push(" Result: ✗ UNPARSEABLE"),{lines:e,incrementStep:!0};case"segment-skipped":return null;case"error":return e.push(""),e.push(`ERROR: ${n.message}`),{lines:e,incrementStep:!1};default:return null}}function er(n,t){let r=n3(t?.asciiOnly??!1),e=58,a=[],l=1;a.push(...t3(r,58)),a.push("");let s=n.trace.steps.find((p)=>p.type==="error");if(s&&s.type==="error"){a.push("ERROR"),a.push(` ${s.message}`),a.push(""),a.push("RESULT"),a.push(` Status: ${n.result==="blocked"?o.red("BLOCKED"):o.green("ALLOWED")}`),a.push(""),a.push("CONFIG");let p=n.configSource??"none";return a.push(` Path: ${p}`),a.join(`
188
+ `)}let d=n.trace.steps.find((p)=>p.type==="parse");if(d&&d.type==="parse"){a.push("INPUT"),a.push(` ${d.input}`),a.push(""),a.push(`STEP ${l} ${r.h} Split shell commands`),l++;for(let p=0;p<d.segments.length;p++){let f=d.segments[p];if(f){let u=Math.random();a.push(` Segment ${p+1}: ${r3(f,u)}`)}}}let c=n.trace.segments,L=c.length>1;for(let p of c){if(L){a.push("");let w="";if(d&&d.type==="parse"){let St=d.segments[p.index];if(St)w=St.join(" ")}let $=54,y=w,m=` Segment ${p.index+1}: `,H=" ";if(w){if(m.length+w.length+H.length>$){let Cl=$-m.length-H.length;y=`${w.substring(0,Cl-1)}…`}}let o2=w?`${m}${y}${H}`:` Segment ${p.index+1} `,Yt=w?`${m}${o.cyan(y)}${H}`:o2,zr=58-o2.length,Fr=Math.floor(zr/2),Ul=zr-Fr;a.push(`${r.sh.repeat(Fr)}${Yt}${r.sh.repeat(Ul)}`)}if(p.steps.find((w)=>w.type==="segment-skipped")){a.push(""),a.push(" (skipped — prior segment blocked)");continue}let u=!1,h=!1;for(let w of p.steps){let $=e3(w,l,r);if($){if(h=!0,w.type==="recurse"){a.push("");let y=" RECURSING ",m=58-y.length-4;a.push(` ${r.tl}${r.h}${y}${r.h.repeat(m)}`),a.push(` ${r.v}`),u=!0;continue}for(let y of $.lines)if(u)a.push(` ${r.v} ${y}`);else a.push(y);if($.incrementStep)l++}}if(u)a.push(` ${r.v}`),a.push(` ${r.bl}${r.h.repeat(56)}`),u=!1;if(!h)a.push(""),a.push(` ${o.green("✓")} Allowed (no matching rules)`)}if(a.push(""),a.push("RESULT"),n.result==="blocked"){if(a.push(` Status: ${o.red("BLOCKED")}`),n.customRule){if(a.push(` Rule: ${n.customRule.id}`),n.customRule.rulebook)a.push(` Rulebook: ${n.customRule.rulebook.name} ${n.customRule.rulebook.version}`);if(n.customRule.source)a.push(` Source: ${n.customRule.source}`);if(n.customRule.override)a.push(` Override: reason ${n.customRule.override.reason}`)}if(n.reason){let p=ft(n.reason," ");a.push(` Reason: ${p[0]}`);for(let f=1;f<p.length;f++)a.push(p[f]??"")}}else a.push(` Status: ${o.green("ALLOWED")}`);a.push(""),a.push("CONFIG");let i=n.configSource??"none",v=n.configValid?"":" (invalid)";a.push(` Path: ${i}${v}`),a.push(` Safety preset: ${n.selectedPreset??"standard"}`),a.push(` Effective capabilities: ${n.effectiveLevel}`);let b=Object.entries(n.destructiveCommandRuleOverrides??{});if(a.push(` Rule customizations: ${b.length}`),n.ruleActivation)a.push(` Rule activation: ${n.ruleActivation.id} — ${n.ruleActivation.enabled?"on":"off"} via ${n.ruleActivation.source}`);return a.join(`
189
+ `)}function ar(n){return JSON.stringify(n,null,2)}function a3(n){return new Promise((t)=>{process.stdout.write(`${n}
190
+ `,()=>t())})}async function l3(n){let t=tr(n);if(!t)return 1;try{let r=O2(t.command,{cwd:t.cwd}),e=!!process.env.NO_COLOR||!process.stdout.isTTY;return await a3(t.json?ar(r):er(r,{asciiOnly:e})),0}catch(r){if(!(r instanceof s1)&&!(r instanceof k2)&&!(r instanceof p2))throw r;if(t.json)return await a3(JSON.stringify({error:r.message})),1;return console.error(r.message),1}}var s3="2.0.8",O=" ",Z2="cc-safety-net";function d3(n){return n.argument?`${n.flags} ${n.argument}`:n.flags}function fi(n){return Math.max(...n.map((t)=>d3(t).length))}function yi(n){return Math.max(...n.map((t)=>t.usage.length))}function hi(n){return Math.max(...n.map((t)=>`${Z2} ${t.usage}`.length))}function wi(n,t){let r=`${Z2} ${n.usage}`;return`${O}${r.padEnd(t+2)}${n.description}`}function b2(n,t){return`${O}${n.padEnd(Math.max(40,n.length+2))}${t}`}function yt(n,t=console.log){let r=[];if(r.push(`${Z2} ${n.name}`),r.push(""),r.push(`${O}${n.description}`),r.push(""),r.push("USAGE:"),r.push(`${O}${Z2} ${n.usage}`),r.push(""),n.subcommands&&n.subcommands.length>0){r.push("SUBCOMMANDS:");let e=yi(n.subcommands);for(let a of n.subcommands)r.push(`${O}${a.usage.padEnd(e+2)}${a.description}`);r.push("")}if(n.options.length>0){r.push("OPTIONS:");let e=fi(n.options);for(let a of n.options){let l=d3(a),s=a.default?`${a.description} (default: ${a.default})`:a.description;r.push(`${O}${l.padEnd(e+2)}${s}`)}r.push("")}if(n.examples&&n.examples.length>0){r.push("EXAMPLES:");for(let e of n.examples)r.push(`${O}${e}`)}t(r.join(`
191
+ `))}function lr(){let n=la(),t=hi(n),r=[];r.push(`${Z2} v${s3}`),r.push(""),r.push("Blocks destructive commands and secret access."),r.push(""),r.push("COMMANDS:");for(let e of n)r.push(wi(e,t));r.push(""),r.push("GLOBAL OPTIONS:"),r.push(`${O}-h, --help Show help (use with command for command-specific help)`),r.push(`${O}-V, --version Show version`),r.push(""),r.push("HELP:"),r.push(`${O}${Z2} help <command> Show help for a specific command`),r.push(`${O}${Z2} <command> --help Show help for a specific command`),r.push(""),r.push("ENVIRONMENT VARIABLES:"),r.push(b2(`${k.level.name}=standard|strict|paranoid`,"Set session safety level")),r.push(b2(`${k.worktree.name}=1`,"Allow local git discards in linked worktrees")),r.push(b2(`${k.debug.name}=1`,"Print diagnostic messages to stderr")),r.push(b2(`${k.auditScope.name}=all|blocked`,"Record all command decisions, or denials only")),r.push(b2("CC_SAFETY_NET_HOME","Override rule config home directory")),r.push(""),r.push("LEGACY ENVIRONMENT VARIABLES (STILL SUPPORTED):"),r.push(b2(`${k.strict.name}=1`,"Force safety.overrides.fail_closed on")),r.push(b2(`${k.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),r.push(b2(`${k.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),r.push(b2(`${k.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),r.push(""),r.push("Documentation: https://ccsafetynet.com/docs"),console.log(r.join(`
192
+ `))}function c3(){console.log(s3)}function Yn(n,t=console.log){let r=Tn(n);if(!r)return!1;if(r.hidden||r.name.toLowerCase()!==n.toLowerCase())return!1;return yt(r,t),!0}import{existsSync as hr,readFileSync as nl}from"node:fs";import{homedir as b5}from"node:os";import{join as fr}from"node:path";import*as x2 from"node:readline";function xi(n){return n==="install"?"Install":"Uninstall"}function $i(n){return n==="install"?"Installing":"Uninstalling"}function Di(n){return n==="install"?"into":"from"}function p3(n){return n?.available===!0}function mi(n,t){let r=new Set(t);return n.filter((e)=>r.has(e.target)).map((e)=>e.target)}function L3(n,t,r){if(n.length===0||n.every((e)=>!e.available))return t;return Array.from({length:n.length},(e,a)=>a+1).map((e)=>(t+e*r+n.length)%n.length).find((e)=>p3(n[e]))}function gi(n,t,r){if(r.ctrl&&r.name==="c")return"interrupt";if(r.name==="escape"||t==="q")return"abort";if(n==="install"&&(t==="u"||t==="U"))return"update";if(r.name==="up"||t==="k")return"up";if(r.name==="down"||t==="j")return"down";if(r.name==="space"||t===" ")return"toggle";if(r.name==="return"||r.name==="enter")return"confirm";return null}function ki(n){return{cursor:n.findIndex((t)=>t.available),selected:[]}}function qi(n,t,r){if(r==="confirm"||r==="update"||r==="abort"||r==="interrupt")return{state:n,done:r};if(r==="up")return{state:{...n,cursor:L3(t,n.cursor,-1)}};if(r==="down")return{state:{...n,cursor:L3(t,n.cursor,1)}};let e=t[n.cursor];if(!p3(e))return{state:n};let a=n.selected.includes(e.target)?n.selected.filter((l)=>l!==e.target):mi(t,[...n.selected,e.target]);return{state:{...n,selected:a}}}var v3="◉",u3="◯",b3=">",o3=" ";function ji(n,t,r,e={}){let a=e.color!==!1,l=a?o.dim:(c)=>c,s=a?o.green:(c)=>c,d=a?o.bold:(c)=>c;return["",`${xi(n)} CC Safety Net ${Di(n)}:`,"",...t.map((c,L)=>{let i=r.selected.includes(c.target),v=L===r.cursor,b=i?v3:u3,p=v?b3:o3,f=c.available?"":` (${c.unavailableReason??"not installed"})`,u=`${b} ${c.label}${f}`,h=!c.available?l(u):i?s(u):v?d(u):u;return`${p} ${h}`}),"",n==="install"?"Space: select Enter: confirm u: update installed Up/Down: move q/Esc: cancel":t.some((c)=>c.available)?"Space: select Enter: confirm Up/Down: move q/Esc: cancel":`No selectable integrations found for ${n}. q/Esc: close`].join(`
193
+ `)}var i3=["global-hook","plugin"];function zi(n,t,r={}){let e=r.color!==!1?o.bold:(l)=>l;return["","Install the Kimi Code integration as:","",...[`Global hook — ${t?"already installed; selecting it reports the current state":"write the hook into ~/.kimi-code/config.toml now"}`,"Native Kimi plugin — print the steps to run inside Kimi Code"].map((l,s)=>{let d=s===n,c=`${d?v3:u3} ${l}`;return`${d?b3:o3} ${d?e(c):c}`}),"","Enter: confirm Up/Down: move q/Esc: cancel"].join(`
194
+ `)}function f3(n){let{input:t,output:r}=n;x2.emitKeypressEvents(t);let e=t.isRaw===!0;t.setRawMode(!0),t.resume();let a=0,l=()=>{if(a===0)return;x2.moveCursor(r,0,-a),x2.cursorTo(r,0),x2.clearScreenDown(r)},s=()=>{l();let d=n.render();r.write(`${d}
195
+ `),a=d.split(`
196
+ `).length};return new Promise((d)=>{let c=(i)=>{t.off("keypress",L),t.setRawMode(e),t.pause(),l(),d(i)};function L(i,v){n.onKey(i,v,{finish:c,draw:s})}t.on("keypress",L),s()})}function y3(n={}){let t=0;return f3({input:n.input??process.stdin,output:n.output??process.stdout,render:()=>zi(t,n.globalHookInstalled===!0),onKey:(r,e,a)=>{if(e.ctrl&&e.name==="c"){a.finish(null),(n.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(e.name==="escape"||r==="q")return a.finish(null);if(e.name==="return"||e.name==="enter")return a.finish(i3[t]);if(e.name==="up"||e.name==="down"||r==="k"||r==="j")t=(t+1)%i3.length,a.draw()}})}function sr(n=process.stdin,t=process.stdout){return Boolean(n.isTTY&&t.isTTY&&typeof n.setRawMode==="function")}function h3(n,t,r={}){let e=r.output??process.stdout,a=ki(t);return f3({input:r.input??process.stdin,output:e,render:()=>ji(n,t,a),onKey:(l,s,d)=>{let c=gi(n,l,s);if(!c)return;let L=qi(a,t,c);if(a=L.state,L.done==="interrupt"){d.finish(null),(r.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(L.done==="abort")return d.finish(null);if(L.done==="update")return d.finish("update");if(L.done==="confirm"){if(a.selected.length===0){e.write("\x07"),d.draw();return}d.finish([...a.selected]),e.write(`${$i(n)} selected integrations...
197
+ `);return}d.draw()}})}import{existsSync as x3,lstatSync as Bi,mkdirSync as Ji,mkdtempSync as Zi,readdirSync as Qi,readFileSync as sn,rmSync as xt}from"node:fs";import{tmpdir as Xi}from"node:os";import{basename as Yi,dirname as Si,join as R}from"node:path";import{fileURLToPath as Hi}from"node:url";var dr="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp",Q2="cc-safety-net",X2="cc-safety-net/index.ts";import{spawn as Fi}from"node:child_process";var cr=(n,t)=>{let r=h2([...n],process.env);return new Promise((e)=>{let a=Fi(r.cmd,r.args,{cwd:t,stdio:["ignore","pipe","pipe"]}),l=G1(a),s=!1,d=setTimeout(()=>{s=!0,a.kill()},120000);a.on("error",(c)=>{clearTimeout(d),e({status:null,errorCode:c.code,stdout:l.stdout,stderr:[c.message,l.stderr].filter(Boolean).join(`
198
+ `)})}),a.on("close",(c)=>{clearTimeout(d),e({status:s?null:c,errorCode:s?"ETIMEDOUT":void 0,stdout:l.stdout,stderr:l.stderr})})})};var ln="cc-safety-net.ts",w3=R("amp",X2);function Wi(n){return R(n,".config","amp","plugins","cc-safety-net.ts")}function Ki(){let n=Si(Hi(import.meta.url));return[R(n,"..",w3),R(n,"..","..","..","dist",w3)]}function Ri(n=Ki()){let t=n.find((r)=>x3(r)&&Bi(r).isFile());if(!t)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return t}function $3(n){try{return JSON.parse(n)}catch{return}}function $t(n){return n.subarray(0,Buffer.byteLength(dr)).toString("utf-8")===dr}async function Sn(n,t,r){let e=await n(t,r);if(e.status===0)return e;throw Error([`Failed to run ${t.join(" ")}${e.status===null?"":` (exit ${e.status})`}.`,[e.stdout,e.stderr].filter(Boolean).join(`
187
199
  `).trim()].filter(Boolean).join(`
188
- `))}async function rl(n){let t=await n(["amp","plugins","repositories","--json"]);if(t.status===null)throw Error(`${t.errorCode==="ENOENT"?'Amp CLI not found. Install the amp CLI, sign in with "amp login", and rerun install --amp.':`amp plugins repositories --json did not finish (${t.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
200
+ `))}async function D3(n){let t=await n(["amp","plugins","repositories","--json"]);if(t.status===null)throw Error(`${t.errorCode==="ENOENT"?'Amp CLI not found. Install the amp CLI, sign in with "amp login", and rerun install --amp.':`amp plugins repositories --json did not finish (${t.errorCode??"terminated"}). Check that the amp CLI responds and rerun install --amp.`}
189
201
  ${t.stderr}`.trim());if(t.status!==0)throw Error(`Failed to run amp plugins repositories --json (exit ${t.status}). Sign in with "amp login" and rerun install --amp.
190
202
  ${[t.stdout,t.stderr].filter(Boolean).join(`
191
- `)}`.trim());let e=tl(t.stdout),r=(Array.isArray(e)?e:[]).filter((a)=>$(a,"scope")==="user"&&$(a,"exists")===!0&&$(a,"viewerCanWrite")===!0).map((a)=>$(a,"cloneRef")).find((a)=>typeof a==="string"&&a.length>0);if(!r)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return r}async function al(n,t){let e=cL(z2(iL(),"cc-safety-net-amp-"));try{return await Zn(n,["amp","clone","user-plugins",e]),await t(e)}finally{N0(e,{recursive:!0,force:!0})}}function ll(n,t){let e=z2(n,p2),r=nl(e);if(!r)return;if(r.isSymbolicLink()||!r.isFile())throw Error(`Refusing to ${t} ${p2} in your Amp personal plugins repository: not a regular file. Remove it there and rerun install --amp.`);let a=Lt(e);if(el(a))return a;throw Error(`Refusing to ${t} unmanaged file ${p2} in your Amp personal plugins repository. Remove it there and rerun install --amp.`)}async function dl(n,t,e,r){if(await Zn(n,e,t),(await Zn(n,["git","status","--porcelain"],t)).stdout.trim()==="")return!1;return await Zn(n,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",r],t),await Zn(n,["git","push","origin","HEAD"],t),!0}function ct(n,t){let e=uL(n),r=nl(e);if(!r)return;if(!r.isSymbolicLink()&&r.isFile()&&el(Lt(e))){N0(e);return}if(t==="keep")return;throw Error(`Local Amp plugin ${e} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function bL(){let n=bn();if(!P0(n))return"";let t=tl(Lt(n,"utf-8"));if(!t||typeof t!=="object"||Array.isArray(t))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(it(t))};
192
- `}async function sl(n,t=vL(),e=Pe){let r=Buffer.concat([Lt(t),Buffer.from(bL(),"utf-8")]),a=await rl(e);return al(e,async(l)=>{let d=`${a}/${p2}`;if(ll(l,"overwrite")?.equals(r))return ct(n,"fail"),{path:d,alreadyInstalled:!0};B(z2(l,p2),r);let s=await dl(e,l,["git","add",p2],`chore: update cc-safety-net plugin to v${j()}`);return ct(n,"fail"),{path:d,alreadyInstalled:!s}})}async function cl(n,t=Pe){let e=await rl(t);return al(t,async(r)=>{let a=`${e}/${p2}`;if(!ll(r,"remove"))return ct(n,"keep"),{path:a,alreadyInstalled:!1};return await dl(t,r,["git","rm",p2],`chore: remove cc-safety-net plugin v${j()}`),ct(n,"keep"),{path:a,alreadyInstalled:!0}})}import{existsSync as il,mkdirSync as fL,readFileSync as hL}from"node:fs";import{dirname as yL}from"node:path";var Ie="npx -y cc-safety-net hook --agy-cli",y2="cc-safety-net";function ut(){return{PreToolUse:[{hooks:[{type:"command",command:Ie,timeout:30}]}]}}function Ll(n){try{let t=JSON.parse(hL(n,"utf-8"));if(!t||typeof t!=="object"||Array.isArray(t))throw Error("Antigravity hooks config must be a JSON object");return t}catch(t){if(t instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${n}: ${t.message}`);throw t}}function pl(n){let t=n[y2];if(t===void 0)return n[y2]=ut(),n[y2];if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`Antigravity hooks config entry "${y2}" must be an object`);if(!Array.isArray(t.PreToolUse))t.PreToolUse=[];return t}function ul(n){if(!Array.isArray(n.PreToolUse))return!1;return n.PreToolUse.some((t)=>Array.isArray(t.hooks)&&t.hooks.some((e)=>e.command===Ie))}function wL(n){return Object.values(n).some((t)=>t.enabled!==!1&&ul(t))}function xL(n){if(n[y2]===void 0)return!1;let t=pl(n);if(t.enabled!==!1||!ul(t))return!1;return t.enabled=!0,!0}function $L(n){if(n[y2]===void 0){n[y2]=ut();return}let t=pl(n);t.PreToolUse??=[],t.enabled=!0,t.PreToolUse.push(ut().PreToolUse?.[0]??{hooks:[]})}function gL(n){let t=!1;for(let e of Object.values(n)){if(!Array.isArray(e.PreToolUse))continue;e.PreToolUse=e.PreToolUse.flatMap((r)=>{if(!Array.isArray(r.hooks))return[r];let a=r.hooks.filter((l)=>l.command!==Ie);if(a.length!==r.hooks.length)t=!0;return a.length===0?[]:[{...r,hooks:a}]})}return t}function pt(n,t){B(n,`${JSON.stringify(t,null,2)}
193
- `)}function ol(n){let t=mn(n);if(fL(yL(t),{recursive:!0}),!il(t))return pt(t,{[y2]:ut()}),{path:t,alreadyInstalled:!1};let e=Ll(t);if(wL(e))return{path:t,alreadyInstalled:!0};if(xL(e))return pt(t,e),{path:t,alreadyInstalled:!1};return $L(e),pt(t,e),{path:t,alreadyInstalled:!1}}function vl(n){let t=mn(n);if(!il(t))return{path:t,alreadyInstalled:!1};let e=Ll(t);if(!gL(e))return{path:t,alreadyInstalled:!1};return pt(t,e),{path:t,alreadyInstalled:!0}}import{spawn as DL,spawnSync as mL}from"node:child_process";var C=i2.map((n)=>({target:n.id,flag:n.flag,label:n.installLabel,probeCommand:n.probeCommand})),bl=new Map(C.map((n)=>[n.flag,n.target]));function Ne(n){let t=new Set(n);return C.map((e)=>e.target).filter((e)=>t.has(e))}async function fl(n,t){for(let e of n)await t(e)}var hl=5000;function kL(n){let t=f2([...n],process.env),e=mL(t.cmd,t.args,{env:process.env,stdio:"ignore",timeout:hl});return!e.error&&e.status===0}function tr(n){return new Promise((t)=>{let e=f2([...n],process.env),r=DL(e.cmd,e.args,{env:process.env,stdio:"ignore"}),a=!1,l=(s)=>{if(a)return;a=!0,clearTimeout(d),t(s)},d=setTimeout(()=>{r.kill(),l(!1)},hl);r.on("error",()=>l(!1)),r.on("close",(s)=>l(s===0))})}function qL(n=kL,t={}){let e=new Set(t.configuredTargets??[]);if(t.async)return Promise.all(C.map(async(a)=>({target:a.target,flag:a.flag,label:a.label,...nr(t.action,await n(a.probeCommand),e.has(a.target))})));let r=n;return C.map((a)=>({target:a.target,flag:a.flag,label:a.label,...nr(t.action,r(a.probeCommand),e.has(a.target))}))}function yl(n=tr,t={}){return qL(n,{...t,async:!0})}function wl(n,t){let e=new Set(t.configuredTargets??[]);return n.map((r)=>({...r,...nr(t.action,r.available,e.has(r.target))}))}function nr(n,t,e){if(n==="uninstall")return e?{available:!0}:{available:!1,unavailableReason:"not installed"};if(n==="install"&&e)return{available:!1,unavailableReason:"already installed"};if(!t)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}import{existsSync as xl,readdirSync as jL,rmSync as FL}from"node:fs";import{join as en}from"node:path";function ot(n,t=process.platform){let e=en(process.env.npm_config_cache||(t==="win32"?en(process.env.LOCALAPPDATA||en(n,"AppData","Local"),"npm-cache"):en(n,".npm")),"_npx");if(!xl(e))return;jL(e).filter((r)=>xl(en(e,r,"node_modules","cc-safety-net"))).forEach((r)=>{FL(en(e,r),{recursive:!0,force:!0})})}import{existsSync as ml,mkdirSync as BL,readFileSync as kl}from"node:fs";import{dirname as JL,join as Dl}from"node:path";function $l(n){return n!==void 0&&/\s/.test(n)}function zL(n,t,e){let r=t+1,a=!1;while(r<n.length){let l=n[r];if(a){a=!1,r++;continue}if(l==="\\"){a=!0,r++;continue}if(l==='"')return r+1;r++}throw Error(e)}function vt(n,t,e){let r=n[t],a=r==="["?"]":"}",l=0,d=t;while(d<n.length){let s=e.skipComment?.(n,d)??d;if(s!==d){d=s;continue}if(n[d]==='"'){d=zL(n,d,e.stringError);continue}if(n[d]===r)l++;if(n[d]===a){if(l--,l===0)return d}d++}throw Error(e.bracketError)}function gl(n,t){let e=n.lastIndexOf(`
194
- `,t)+1;return/^[ \t]*/.exec(n.slice(e))?.[0]??""}function bt(n,t){let{start:e,end:r,end:a}=t;while($l(n[a]))a++;if(n[a]===","){if(r=a+1,n[r]===`
195
- `)r++;return`${n.slice(0,e)}${n.slice(r)}`}a=t.start-1;while($l(n[a]))a--;if(n[a]===","){e=a;let l=n.lastIndexOf(`
196
- `,e-1);if(l!==-1&&/^\s*$/.test(n.slice(l+1,e)))e=l}return`${n.slice(0,e)}${n.slice(r)}`}var Qn="npx -y cc-safety-net hook --kimi-code",er=`[[hooks]]
203
+ `)}`.trim());let r=$3(t.stdout),e=(Array.isArray(r)?r:[]).filter((a)=>x(a,"scope")==="user"&&x(a,"exists")===!0&&x(a,"viewerCanWrite")===!0).map((a)=>x(a,"cloneRef")).find((a)=>typeof a==="string"&&a.length>0);if(!e)throw Error('Your Amp account has no writable Personal Plugins repository. Sign in with "amp login", open Amp once to create it, and rerun install --amp.');return e}async function m3(n,t){let r=Zi(R(Xi(),"cc-safety-net-amp-"));try{return await Sn(n,["amp","clone","user-plugins",r]),await t(r)}finally{xt(r,{recursive:!0,force:!0})}}function Lr(n){return`rerun ${n==="overwrite"?"install":"uninstall"} --amp`}function g3(n,t,r){let e=R(n,t),a=F(e);if(!a)return;if(a.isSymbolicLink()||!a.isFile())throw Error(`Refusing to ${r} ${t} in your Amp personal plugins repository: not a regular file. Remove it there and ${Lr(r)}.`);let l=sn(e);if($t(l))return l;throw Error(`Refusing to ${r} unmanaged file ${t} in your Amp personal plugins repository. Remove it there and ${Lr(r)}.`)}function k3(n,t){let r=R(n,Q2),e=F(r);if(!e)return;if(e.isSymbolicLink()||!e.isDirectory())throw Error(`Refusing to ${t} ${Q2} in your Amp personal plugins repository: not a regular directory. Remove it there and ${Lr(t)}.`);return g3(n,X2,t)}function Vi(n){let t=R(n,ln),r=F(t);if(!r||r.isSymbolicLink()||!r.isFile())return;let e=sn(t);return $t(e)?e:void 0}async function q3(n,t,r,e){if(await Sn(n,r,t),(await Sn(n,["git","status","--porcelain"],t)).stdout.trim()==="")return!1;return await Sn(n,["git","-c","commit.gpgsign=false","-c","user.name=cc-safety-net","-c","user.email=cc-safety-net@localhost","commit","-m",e],t),await Sn(n,["git","push","origin","HEAD"],t),!0}function ht(n,t){Ai(n,t),Mi(n,t)}function j3(n,t){if(t==="keep")return;throw Error(`Local Amp plugin ${n} is not a managed copy and masks the personal plugin. Remove it and rerun install --amp.`)}function Ai(n,t){let r=Wi(n),e=F(r);if(!e)return;if(!e.isSymbolicLink()&&e.isFile()&&$t(sn(r))){xt(r);return}j3(r,t)}function Mi(n,t){let r=R(n,".config","amp","plugins",Q2),e=F(r);if(!e)return;if(!e.isSymbolicLink()&&e.isDirectory()&&Gi(r)){xt(r,{recursive:!0});return}j3(r,t)}function Gi(n){let t=Yi(X2);if(Qi(n).join("\x00")!==t)return!1;let r=R(n,t),e=F(r);return!!e&&!e.isSymbolicLink()&&e.isFile()&&$t(sn(r))}function Ui(){let n=wn();if(!x3(n))return"";let t=$3(sn(n,"utf-8"));if(!t||typeof t!=="object"||Array.isArray(t))return"";return`;globalThis.__CC_SAFETY_NET_EMBEDDED_POLICY__ = ${JSON.stringify(wt(t))};
204
+ `}async function z3(n,t=Ri(),r=cr){let e=Buffer.concat([sn(t),Buffer.from(Ui(),"utf-8")]),a=await D3(r);return m3(r,async(l)=>{let s=`${a}/${Q2}`,d=k3(l,"overwrite"),c=g3(l,ln,"overwrite");if(d?.equals(e)&&!c)return ht(n,"fail"),{path:s,alreadyInstalled:!0};if(Ji(R(l,Q2),{recursive:!0}),Q(R(l,X2),e),c)xt(R(l,ln));let L=await q3(r,l,["git","add","--",X2,...c?[ln]:[]],`chore: update cc-safety-net plugin to v${B()}`);return ht(n,"fail"),{path:s,alreadyInstalled:!L}})}async function F3(n,t=cr){let r=await D3(t);return m3(t,async(e)=>{let a=k3(e,"remove"),l=Vi(e),s=`${r}/${l&&!a?ln:Q2}`;if(!a&&!l)return ht(n,"keep"),{path:s,alreadyInstalled:!1};return await q3(t,e,["git","rm","--",...a?[X2]:[],...l?[ln]:[]],`chore: remove cc-safety-net plugin v${B()}`),ht(n,"keep"),{path:s,alreadyInstalled:!0}})}import{existsSync as B3,mkdirSync as Ci,readFileSync as Oi}from"node:fs";import{dirname as Ti}from"node:path";var ir="npx -y cc-safety-net hook --agy-cli",$2="cc-safety-net";function mt(){return{PreToolUse:[{hooks:[{type:"command",command:ir,timeout:30}]}]}}function J3(n){try{let t=JSON.parse(Oi(n,"utf-8"));if(!t||typeof t!=="object"||Array.isArray(t))throw Error("Antigravity hooks config must be a JSON object");return t}catch(t){if(t instanceof SyntaxError)throw Error(`Failed to parse Antigravity hooks config ${n}: ${t.message}`);throw t}}function Z3(n){let t=n[$2];if(t===void 0)return n[$2]=mt(),n[$2];if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`Antigravity hooks config entry "${$2}" must be an object`);if(!Array.isArray(t.PreToolUse))t.PreToolUse=[];return t}function Q3(n){if(!Array.isArray(n.PreToolUse))return!1;return n.PreToolUse.some((t)=>Array.isArray(t.hooks)&&t.hooks.some((r)=>r.command===ir))}function _i(n){return Object.values(n).some((t)=>t.enabled!==!1&&Q3(t))}function Ei(n){if(n[$2]===void 0)return!1;let t=Z3(n);if(t.enabled!==!1||!Q3(t))return!1;return t.enabled=!0,!0}function Pi(n){if(n[$2]===void 0){n[$2]=mt();return}let t=Z3(n);t.PreToolUse??=[],t.enabled=!0,t.PreToolUse.push(mt().PreToolUse?.[0]??{hooks:[]})}function Ii(n){let t=!1;for(let r of Object.values(n)){if(!Array.isArray(r.PreToolUse))continue;r.PreToolUse=r.PreToolUse.flatMap((e)=>{if(!Array.isArray(e.hooks))return[e];let a=e.hooks.filter((l)=>l.command!==ir);if(a.length!==e.hooks.length)t=!0;return a.length===0?[]:[{...e,hooks:a}]})}return t}function Dt(n,t){Q(n,`${JSON.stringify(t,null,2)}
205
+ `)}function X3(n){let t=zn(n);if(Ci(Ti(t),{recursive:!0}),!B3(t))return Dt(t,{[$2]:mt()}),{path:t,alreadyInstalled:!1};let r=J3(t);if(_i(r))return{path:t,alreadyInstalled:!0};if(Ei(r))return Dt(t,r),{path:t,alreadyInstalled:!1};return Pi(r),Dt(t,r),{path:t,alreadyInstalled:!1}}function Y3(n){let t=zn(n);if(!B3(t))return{path:t,alreadyInstalled:!1};let r=J3(t);if(!Ii(r))return{path:t,alreadyInstalled:!1};return Dt(t,r),{path:t,alreadyInstalled:!0}}import{spawn as Ni,spawnSync as n5}from"node:child_process";var T=G.map((n)=>({target:n.id,flag:n.flag,label:j(n.id),probeCommand:n.probeCommand})),S3=new Map(T.map((n)=>[n.flag,n.target]));function pr(n){let t=new Set(n);return T.map((r)=>r.target).filter((r)=>t.has(r))}async function H3(n,t){for(let r of n)await t(r)}var W3=5000;function t5(n){let t=h2([...n],process.env),r=n5(t.cmd,t.args,{env:process.env,stdio:"ignore",timeout:W3});return!r.error&&r.status===0}function ur(n){return new Promise((t)=>{let r=h2([...n],process.env),e=Ni(r.cmd,r.args,{env:process.env,stdio:"ignore"}),a=!1,l=(d)=>{if(a)return;a=!0,clearTimeout(s),t(d)},s=setTimeout(()=>{e.kill(),l(!1)},W3);e.on("error",()=>l(!1)),e.on("close",(d)=>l(d===0))})}function r5(n=t5,t={}){let r=new Set(t.configuredTargets??[]);if(t.async)return Promise.all(T.map(async(a)=>({target:a.target,flag:a.flag,label:a.label,...vr(t.action,await n(a.probeCommand),r.has(a.target))})));let e=n;return T.map((a)=>({target:a.target,flag:a.flag,label:a.label,...vr(t.action,e(a.probeCommand),r.has(a.target))}))}function K3(n=ur,t={}){return r5(n,{...t,async:!0})}function R3(n,t){let r=new Set(t.configuredTargets??[]);return n.map((e)=>({...e,...vr(t.action,e.available,r.has(e.target))}))}function vr(n,t,r){if(n==="uninstall")return r?{available:!0}:{available:!1,unavailableReason:"not installed"};if(n==="install"&&r)return{available:!1,unavailableReason:"already installed"};if(!t)return{available:!1,unavailableReason:"CLI not installed"};return{available:!0}}import{existsSync as V3,readdirSync as e5,rmSync as a5}from"node:fs";import{join as dn}from"node:path";function gt(n,t=process.platform){let r=dn(process.env.npm_config_cache||(t==="win32"?dn(process.env.LOCALAPPDATA||dn(n,"AppData","Local"),"npm-cache"):dn(n,".npm")),"_npx");if(!V3(r))return;e5(r).filter((e)=>V3(dn(r,e,"node_modules","cc-safety-net"))).forEach((e)=>{a5(dn(r,e),{recursive:!0,force:!0})})}import{existsSync as M3,mkdirSync as l5,readFileSync as G3}from"node:fs";import{dirname as s5,join as A3}from"node:path";var Hn="npx -y cc-safety-net hook --kimi-code",br=`[[hooks]]
197
206
  event = "PreToolUse"
198
- command = "${Qn}"`,rr=`{ event = "PreToolUse", command = "${Qn}" }`;function ql(n){return Dl(process.env.KIMI_CODE_HOME??Dl(n,".kimi-code"),"config.toml")}function ZL(n){return n.split(`
199
- `).reduce((e,r)=>{if(/^\s*\[/.test(r))return e.activeTable=!0,e.lines.push(r),e;if(!e.activeTable&&/^\s*hooks\s*=\s*\[\s*]\s*(?:#.*)?$/.test(r))return e;return e.lines.push(r),e},{activeTable:!1,lines:[]}).lines.join(`
200
- `)}function QL(n,t){if(n[t]!=="#")return t;let e=n.indexOf(`
201
- `,t+1);return e===-1?n.length:e+1}function XL(n,t){return vt(n,t,{skipComment:QL,stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"})}function jl(n){let t=!1,e=0;while(e<n.length){let r=n.indexOf(`
202
- `,e),a=r===-1?n.length:r,l=n.slice(e,a);if(/^\s*\[/.test(l))t=!0;if(!t){let d=/^(\s*)hooks\s*=\s*\[/.exec(l);if(d){let s=e+d[0].lastIndexOf("[");return{start:s,end:XL(n,s)}}}e=r===-1?n.length:r+1}return}function YL(n,t){let e=n.slice(0,t.end).trimEnd(),r=gl(n,t.end),a=r===""?" ":`${r} `,l=!e.endsWith("[")&&!e.endsWith(",");return`${e}${l?",":""}
203
- ${a}${rr}${n.slice(t.end)}`}function SL(n){let t=jl(n);if(t&&n.slice(t.start+1,t.end).trim())return YL(n,t);let e=ZL(n).trimEnd();if(e==="")return`${er}
204
- `;return`${e}
205
-
206
- ${er}
207
- `}function HL(n){return n.split(/(?=^\s*\[)/m).filter((e)=>!/^\s*\[\[hooks]]\s*$/m.test(e)||!e.includes(Qn)).join("").trimEnd()}function AL(n,t){let e=n.indexOf(rr,t.start);if(e===-1||e>t.end)return n;return bt(n,{start:e,end:e+rr.length})}function Fl(n){let t=ql(n);if(BL(JL(t),{recursive:!0}),!ml(t))return B(t,`${er}
208
- `),{path:t,alreadyInstalled:!1};let e=kl(t,"utf-8");if(e.includes(Qn))return{path:t,alreadyInstalled:!0};return B(t,SL(e)),{path:t,alreadyInstalled:!1}}function zl(n){let t=ql(n);if(!ml(t))return{path:t,alreadyInstalled:!1};let e=kl(t,"utf-8");if(!e.includes(Qn))return{path:t,alreadyInstalled:!1};let r=jl(e),a=r?AL(e,r):`${HL(e)}
209
- `;return B(t,a),{path:t,alreadyInstalled:!0}}import{existsSync as Bl,readFileSync as WL,rmSync as RL}from"node:fs";import{join as ar}from"node:path";var lr="cc-safety-net",KL=`${lr}@latest`,Zl=["opencode.json","opencode.jsonc"];function ML(n){return ar(n,".config","opencode",Zl[0])}function VL(n){return Zl.map((t)=>ar(n,".config","opencode",t))}function GL(n){return ar(n,".cache","opencode","packages",KL)}function dr(n){RL(GL(n),{recursive:!0,force:!0})}function ft(n,t){if(n[t]==="/"&&n[t+1]==="/"){let e=n.indexOf(`
210
- `,t+2);return e===-1?n.length:e+1}if(n[t]==="/"&&n[t+1]==="*"){let e=n.indexOf("*/",t+2);return e===-1?n.length:e+2}return t}function Jl(n,t){let e=t;while(e<n.length){if(/\s/.test(n[e]??"")){e++;continue}let r=ft(n,e);if(r===e)return e;e=r}return e}function Ql(n,t){let e=t+1,r=!1;while(e<n.length){if(r){r=!1,e++;continue}if(n[e]==="\\"){r=!0,e++;continue}if(n[e]==='"')return e+1;e++}throw Error("Unterminated string in OpenCode config")}function Xl(n,t,e){return JSON.parse(n.slice(t,e))}function CL(n,t){return vt(n,t,{skipComment:ft,stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"})}function UL(n){let t=0,e=0;while(e<n.length){let r=ft(n,e);if(r!==e){e=r;continue}if(n[e]==='"'){let a=Ql(n,e);if(t===1&&Xl(n,e,a)==="plugin"){let l=Jl(n,a),d=Jl(n,l+1);if(n[l]===":"&&n[d]==="[")return{start:d,end:CL(n,d)}}e=a;continue}if(n[e]==="{"||n[e]==="[")t++;if(n[e]==="}"||n[e]==="]")t--;e++}return}function OL(n,t){let e=[],r=t.start+1;while(r<t.end){let a=ft(n,r);if(a!==r){r=a;continue}if(n[r]==='"'){let l=Ql(n,r),d=Xl(n,r,l);if(typeof d==="string"&&d.includes(lr))e.push({start:r,end:l});r=l;continue}r++}return e}function Yl(n,t){try{return JSON.parse(R(n))}catch(e){if(e instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${t}: ${e.message}`);throw e}}function TL(n){if(!n||typeof n!=="object"||Array.isArray(n))return!1;let t=n.plugin;if(!Array.isArray(t))return!1;return t.some((e)=>typeof e==="string"&&e.includes(lr))}function _L(n,t){let e=UL(n);if(!e)throw Error(`Failed to locate OpenCode plugin array in ${t}`);let r=[...OL(n,e)].reverse().reduce(bt,n);return Yl(r,t),r}function Sl(n){dr(n);let t=VL(n),e=t.find((a)=>Bl(a)),r=[];for(let a of t){if(!Bl(a))continue;try{let l=WL(a,"utf-8");if(!TL(Yl(l,a)))continue;return B(a,_L(l,a)),{path:a,alreadyInstalled:!0}}catch(l){r.push(l instanceof Error?l.message:String(l))}}if(r.length>0)throw Error(r.join(`
211
- `));return{path:e??ML(n),alreadyInstalled:!1}}var cr="safety-net@cc-marketplace",Hl=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),Al=new Set(["antigravity-cli","cursor","hermes-agent","kimi-code"]);function Lr(n){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(n??"")}function Vl(n){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(n??"")}function PL(n){return/^Marketplace `cc-marketplace`\s*$/m.test(n??"")}var Gl={"claude-code":{installCommands:(n)=>{let t=Pn(n,"cc-safety-net@cc-marketplace");return{commands:[...t?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...we(n).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Pn(n,cr)?[["claude","plugin","uninstall",cr]]:[],update:t}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(n,t)=>{let e=t??await e2(["codex","plugin","list"]),r=Vl(e);return{commands:[r||PL(e)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:Lr(e)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:r}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:"Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."},"copilot-cli":{installCommands:async()=>{let n=await e2(["copilot","plugin","list"]),t=[...Ra(n)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...Ka(n)?[["copilot","plugin","uninstall",Ha]]:[]];if(Aa(n))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",t2]],cleanupCommands:t,update:!0};return{commands:[Wa(await e2(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",t2]],cleanupCommands:t}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(n)=>{let t=je(n);if(t.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(t.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:We,installCommands:()=>({commands:x0()}),uninstallCommands:[["openclaw","plugins","uninstall",q,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
212
- `)},opencode:{beforeInstall:dr,installCommands:[["opencode","plugin","-g","-f","cc-safety-net@latest"]]},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]}};function wt(){return process.env.HOME??EL()}function Cl(n,t=(e)=>e){try{let e=JSON.parse(t(Ml(n,"utf-8")));if(!e||typeof e!=="object"||Array.isArray(e))throw Error(`Settings file ${n} must be a JSON object`);return e}catch(e){if(e instanceof SyntaxError)throw Error(`Failed to parse ${n}: ${e.message}`);throw e}}function IL(n){let t=sr(kn(n),"settings.json");if(!ir(t))return;let e=Cl(t,R),r=e.enabledPlugins;if(!r||typeof r!=="object"||Array.isArray(r))return;if(r[t2]!==!1)return;let a=Ml(t,"utf-8"),l=a.replace(new RegExp(`("${t2}"\\s*:\\s*)false`),"$1true");return r[t2]=!0,B(t,l!==a?l:`${JSON.stringify(e,null,2)}
213
- `),`Enabled ${t2} plugin in ${t}`}function NL(n){let t=Ke(n);if(!ir(t))return;let e=Cl(t);if(!Array.isArray(e.packages))return;let r=e.packages.find((a)=>!!a&&typeof a==="object"&&!Array.isArray(a)&&Me(a.source)&&("extensions"in a));if(!r)return;return delete r.extensions,B(t,`${JSON.stringify(e,null,2)}
214
- `),`Enabled npm:cc-safety-net extensions in ${t}`}function Wl(n,t){let e=F({label:t,booleans:Object.fromEntries(C.map((l)=>[l.target,[l.flag]]))},n),r=e.errors[0];if(r)throw Error(r);let a=C.filter((l)=>e.flags[l.target]).map((l)=>l.target);if(a.length!==1)throw Error(`Choose exactly one ${t} target: ${[...bl.keys()].join(", ")}`);return a[0]}async function Ul(n=wt(),t=_2){let[e,r,a]=await Promise.all([t(["amp","plugins","list"],30000),t(["codex","plugin","list"],30000),t(["copilot","--binary-version"])]);return{codexPluginListOutput:r,hooks:tn(process.cwd(),{homeDir:n,ampPluginListOutput:e,codexPluginListOutput:r,copilotCliVersion:a})}}async function n5(n,t=_2){let e=await Ul(wt(),t);return e.hooks.filter((r)=>n==="install"?r.configured:r.detected||r.inspectionStatus==="not-inspected").filter((r)=>r.platform!=="codex"||!Lr(e.codexPluginListOutput)||Vl(e.codexPluginListOutput)).map((r)=>r.platform)}function t5(n,t,e){if(t.length>0)return{finish:async()=>[Wl(t,n)]};if(!e.selectTargets&&!_e(e.input,e.output))return{finish:async()=>[Wl(t,n)]};let r=e.detectConfiguredTargets??(()=>n5(n,e.fetchVersion)),a=Promise.all([yl(e.probeTargets),r()]);return{ready:a,finish:async()=>{let[l,d]=await a,s=wl(l,{action:n,configuredTargets:d}),c=e.selectTargets?await e.selectTargets(n,Kl(n,s)):await _0(n,Kl(n,s),{input:e.input,output:e.output});if(c==="update")return c;if(!c||c.length===0)return null;return Ne(c)}}}async function B2(n,t,e=!1,r){let a=Gl[n];a.beforeInstall?.(t);let l=typeof a.installCommands==="function"?await a.installCommands(t,r):{commands:a.installCommands};return await He(l.commands),await v0(l.cleanupCommands??[]),[`${l.update||e?"Updated":"Installed"} ${b2(n)} integration`,a.postInstallMessage].filter(Boolean).join(`
215
- `)}async function rn(n){let t=Gl[n];if(!t.uninstallCommands)throw Error(`${b2(n)} uninstall is not supported`);return await He(t.uninstallCommands),`Uninstalled ${b2(n)} integration`}function e5(n){let t=Sl(n);return t.alreadyInstalled?`Uninstalled OpenCode plugin from ${t.path}`:`OpenCode plugin not installed in ${t.path}`}var r5={"antigravity-cli":{install:ol,uninstall:vl},cursor:{install:Pa,uninstall:Ia},"kimi-code":{install:Fl,uninstall:zl}};function an(n,t,e,r=!1){if(n==="install"&&!r)ot(e);let a=r5[t][n](e),l=b2(t),d=n!=="install"?"Uninstalled":r?"Updated":"Installed";return n==="install"&&a.alreadyInstalled?r?`${l} hook up to date in ${a.path}`:`${l} hook already installed in ${a.path}`:n==="uninstall"&&!a.alreadyInstalled?`${l} hook not installed in ${a.path}`:`${d} ${l} hook ${n==="install"?"in":"from"} ${a.path}`}var a5={amp:{install:sl,uninstall:cl,restartNote:'Amp personal plugins apply to every Amp session, including Orb threads. Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:a0,uninstall:l0,afterInstall:async(n)=>{let t=Xe(n);return await e2(["hermes","plugins","enable",M,"--no-allow-tool-override"]),!t},beforeUninstall:async(n)=>{Qe(n);try{await e2(["hermes","plugins","disable",M])}catch(t){console.warn(`${t instanceof Error?t.message:String(t)}
216
- Removing the plugin files anyway; ${M} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function ht(n,t,e,r=!1){let a=a5[t];if(n==="uninstall")await a.beforeUninstall?.(e);let l=n==="install"?await a.install(e):await a.uninstall(e),d=n==="install"&&await a.afterInstall?.(e),s=b2(t),c=!d&&(n==="install"&&l.alreadyInstalled||n==="uninstall"&&!l.alreadyInstalled);return[c?n==="install"?`${s} plugin ${r?"up to date":"already installed"} at ${l.path}`:`${s} plugin not installed at ${l.path}`:`${n!=="install"?"Uninstalled":r?"Updated":"Installed"} ${s} plugin ${n==="install"?"at":"from"} ${l.path}`,c?void 0:a.restartNote].filter(Boolean).join(`
217
- `)}var l5={amp:{install:(n,t)=>ht("install","amp",n,t),uninstall:(n)=>ht("uninstall","amp",n)},"antigravity-cli":{install:(n,t)=>an("install","antigravity-cli",n,t),uninstall:(n)=>an("uninstall","antigravity-cli",n)},"claude-code":{install:(n,t)=>B2("claude-code",n,t),uninstall:()=>rn("claude-code")},codex:{install:(n,t,e)=>B2("codex",n,t,e),uninstall:()=>rn("codex")},"copilot-cli":{install:async(n,t)=>[await B2("copilot-cli",n,t),IL(n)].filter(Boolean).join(`
218
- `),uninstall:()=>rn("copilot-cli")},cursor:{install:(n,t)=>an("install","cursor",n,t),uninstall:(n)=>an("uninstall","cursor",n)},"gemini-cli":{install:(n,t)=>B2("gemini-cli",n,t),uninstall:()=>rn("gemini-cli")},"hermes-agent":{install:(n,t)=>{if(!t)ot(n);return ht("install","hermes-agent",n,t)},uninstall:(n)=>ht("uninstall","hermes-agent",n)},"kimi-code":{install:(n,t)=>an("install","kimi-code",n,t),uninstall:(n)=>an("uninstall","kimi-code",n)},openclaw:{install:async(n,t)=>{let e=await B2("openclaw",n,t);return await $0(),e},uninstall:(n)=>{return We(n),rn("openclaw")}},opencode:{install:(n,t)=>B2("opencode",n,t),uninstall:(n)=>e5(n)},pi:{install:async(n,t)=>[await B2("pi",n,t),NL(n)].filter(Boolean).join(`
219
- `),uninstall:()=>rn("pi")}},Rl=["Install CC Safety Net as a native Kimi Code plugin:",""," 1. Start Kimi Code and run: /plugins install https://github.com/kenryu42/cc-safety-net"," Confirm the trust prompt; it defaults to cancel."," 2. Run /reload, or start a new session.","","Note: Kimi Code hooks are fail-open. When the hook process cannot start, crashes, or times","out, Kimi Code allows the tool call."].join(`
220
- `);function d5(n){if(Fn({homeDir:n,cwd:process.cwd()}).status!=="configured")return Rl;return[Rl,"",b.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
207
+ command = "${Hn}"`,or=`{ event = "PreToolUse", command = "${Hn}" }`;function U3(n){return A3(process.env.KIMI_CODE_HOME??A3(n,".kimi-code"),"config.toml")}function d5(n){return n.split(`
208
+ `).reduce((r,e)=>{if(/^\s*\[/.test(e))return r.activeTable=!0,r.lines.push(e),r;if(!r.activeTable&&/^\s*hooks\s*=\s*\[\s*]\s*(?:#.*)?$/.test(e))return r;return r.lines.push(e),r},{activeTable:!1,lines:[]}).lines.join(`
209
+ `)}function c5(n,t){if(n[t]!=="#")return t;let r=n.indexOf(`
210
+ `,t+1);return r===-1?n.length:r+1}function L5(n,t){return pt(n,t,{skipComment:c5,stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"})}function C3(n){let t=!1,r=0;while(r<n.length){let e=n.indexOf(`
211
+ `,r),a=e===-1?n.length:e,l=n.slice(r,a);if(/^\s*\[/.test(l))t=!0;if(!t){let s=/^(\s*)hooks\s*=\s*\[/.exec(l);if(s){let d=r+s[0].lastIndexOf("[");return{start:d,end:L5(n,d)}}}r=e===-1?n.length:e+1}return}function i5(n,t){let r=n.slice(0,t.end).trimEnd(),e=H0(n,t.end),a=e===""?" ":`${e} `,l=!r.endsWith("[")&&!r.endsWith(",");return`${r}${l?",":""}
212
+ ${a}${or}${n.slice(t.end)}`}function p5(n){let t=C3(n);if(t&&n.slice(t.start+1,t.end).trim())return i5(n,t);let r=d5(n).trimEnd();if(r==="")return`${br}
213
+ `;return`${r}
214
+
215
+ ${br}
216
+ `}function v5(n){return n.split(/(?=^\s*\[)/m).filter((r)=>!/^\s*\[\[hooks]]\s*$/m.test(r)||!r.includes(Hn)).join("").trimEnd()}function u5(n,t){let r=n.indexOf(or,t.start);if(r===-1||r>t.end)return n;return vt(n,{start:r,end:r+or.length})}function O3(n){let t=U3(n);if(l5(s5(t),{recursive:!0}),!M3(t))return Q(t,`${br}
217
+ `),{path:t,alreadyInstalled:!1};let r=G3(t,"utf-8");if(r.includes(Hn))return{path:t,alreadyInstalled:!0};return Q(t,p5(r)),{path:t,alreadyInstalled:!1}}function T3(n){let t=U3(n);if(!M3(t))return{path:t,alreadyInstalled:!1};let r=G3(t,"utf-8");if(!r.includes(Hn))return{path:t,alreadyInstalled:!1};let e=C3(r),a=e?u5(r,e):`${v5(r)}
218
+ `;return Q(t,a),{path:t,alreadyInstalled:!0}}var yr="safety-net@cc-marketplace",_3=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]),E3=new Set(["antigravity-cli","cursor","hermes-agent","kimi-code"]);function wr(n){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(n??"")}function tl(n){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(n??"")}function o5(n){return/^Marketplace `cc-marketplace`\s*$/m.test(n??"")}var rl={"claude-code":{installCommands:(n)=>{let t=rt(n,"cc-safety-net@cc-marketplace");return{commands:[...t?[["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","update","cc-safety-net@cc-marketplace"]]:[["claude","plugin","marketplace","add","kenryu42/cc-marketplace"],["claude","plugin","marketplace","update","cc-marketplace"],["claude","plugin","install","cc-safety-net@cc-marketplace"]],...z1(n).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:rt(n,yr)?[["claude","plugin","uninstall",yr]]:[],update:t}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:async(n,t)=>{let r=t??await l2(["codex","plugin","list"]),e=tl(r);return{commands:[e||o5(r)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:wr(r)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:e}},uninstallCommands:[["codex","plugin","remove","cc-safety-net@cc-marketplace"],["codex","plugin","marketplace","remove","cc-marketplace"]],postInstallMessage:"Start Codex, open `/hooks`, select the cc-safety-net PreToolUse hook, and press `t` to trust it."},"copilot-cli":{installCommands:async()=>{let n=await l2(["copilot","plugin","list"]),t=[..._a(n)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...Ea(n)?[["copilot","plugin","uninstall",Ca]]:[]];if(Oa(n))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",a2]],cleanupCommands:t,update:!0};return{commands:[Ta(await l2(["copilot","plugin","marketplace","list"]))?["copilot","plugin","marketplace","update","cc-marketplace"]:["copilot","plugin","marketplace","add","kenryu42/cc-marketplace"],["copilot","plugin","install",a2]],cleanupCommands:t}},uninstallCommands:[["copilot","plugin","uninstall","cc-safety-net@cc-marketplace"],["copilot","plugin","marketplace","remove","cc-marketplace"]]},"gemini-cli":{installCommands:(n)=>{let t=Y1(n);if(t.status==="configured")return{commands:[["gemini","extensions","update","gemini-safety-net"]],update:!0};if(t.status==="disabled")return{commands:[["gemini","extensions","update","gemini-safety-net"],["gemini","extensions","enable","gemini-safety-net"]],update:!0};return{commands:[["gemini","extensions","install","https://github.com/kenryu42/gemini-safety-net","--consent"]]}},uninstallCommands:[["gemini","extensions","uninstall","gemini-safety-net"]]},openclaw:{beforeInstall:T1,installCommands:()=>({commands:F0()}),uninstallCommands:[["openclaw","plugins","uninstall",z,"--force"]],postInstallMessage:["Restart the OpenClaw Gateway to apply the change.","If plugins.allow is set in openclaw.json, it must also list cc-safety-net."].join(`
219
+ `)},opencode:{beforeInstall:P1,installCommands:[["opencode","plugin","-g","-f","cc-safety-net@latest"]]},pi:{installCommands:[["pi","install","npm:cc-safety-net"]],uninstallCommands:[["pi","uninstall","npm:cc-safety-net"]]}};function jt(){return process.env.HOME??b5()}function el(n,t=(r)=>r){try{let r=JSON.parse(t(nl(n,"utf-8")));if(!r||typeof r!=="object"||Array.isArray(r))throw Error(`Settings file ${n} must be a JSON object`);return r}catch(r){if(r instanceof SyntaxError)throw Error(`Failed to parse ${n}: ${r.message}`);throw r}}function f5(n){let t=fr(Fn(n),"settings.json");if(!hr(t))return;let r=el(t,M),e=r.enabledPlugins;if(!e||typeof e!=="object"||Array.isArray(e))return;if(e[a2]!==!1)return;let a=nl(t,"utf-8"),l=a.replace(new RegExp(`("${a2}"\\s*:\\s*)false`),"$1true");return e[a2]=!0,Q(t,l!==a?l:`${JSON.stringify(r,null,2)}
220
+ `),`Enabled ${a2} plugin in ${t}`}function y5(n){let t=I1(n);if(!hr(t))return;let r=el(t);if(!Array.isArray(r.packages))return;let e=r.packages.find((a)=>!!a&&typeof a==="object"&&!Array.isArray(a)&&N1(a.source)&&("extensions"in a));if(!e)return;return delete e.extensions,Q(t,`${JSON.stringify(r,null,2)}
221
+ `),`Enabled npm:cc-safety-net extensions in ${t}`}function P3(n,t){let r=J({label:t,booleans:Object.fromEntries(T.map((l)=>[l.target,[l.flag]]))},n),e=r.errors[0];if(e)throw Error(e);let a=T.filter((l)=>r.flags[l.target]).map((l)=>l.target);if(a.length!==1)throw Error(`Choose exactly one ${t} target: ${[...S3.keys()].join(", ")}`);return a[0]}async function al(n=jt(),t=P2){let[r,e,a]=await Promise.all([t(["amp","plugins","list"],30000),t(["codex","plugin","list"],30000),t(["copilot","--binary-version"])]);return{codexPluginListOutput:e,hooks:an(process.cwd(),{homeDir:n,ampPluginListOutput:r,codexPluginListOutput:e,copilotCliVersion:a})}}async function h5(n,t=P2){let r=await al(jt(),t);return r.hooks.filter((e)=>n==="install"?e.configured:e.detected||e.inspectionStatus==="not-inspected").filter((e)=>e.platform!=="codex"||!wr(r.codexPluginListOutput)||tl(r.codexPluginListOutput)).map((e)=>e.platform)}function w5(n,t,r){if(t.length>0)return{finish:async()=>[P3(t,n)]};if(!r.selectTargets&&!sr(r.input,r.output))return{finish:async()=>[P3(t,n)]};let e=r.detectConfiguredTargets??(()=>h5(n,r.fetchVersion)),a=Promise.all([K3(r.probeTargets),e()]);return{ready:a,finish:async()=>{let[l,s]=await a,d=R3(l,{action:n,configuredTargets:s}),c=r.selectTargets?await r.selectTargets(n,N3(n,d)):await h3(n,N3(n,d),{input:r.input,output:r.output});if(c==="update")return c;if(!c||c.length===0)return null;return pr(c)}}}async function Y2(n,t,r=!1,e){let a=rl[n];a.beforeInstall?.(t);let l=typeof a.installCommands==="function"?await a.installCommands(t,e):{commands:a.installCommands};return await U1(l.commands),await m0(l.cleanupCommands??[]),[`${l.update||r?"Updated":"Installed"} ${j(n)} integration`,a.postInstallMessage].filter(Boolean).join(`
222
+ `)}async function cn(n){let t=rl[n];if(!t.uninstallCommands)throw Error(`${j(n)} uninstall is not supported`);return await U1(t.uninstallCommands),`Uninstalled ${j(n)} integration`}function x5(n){let t=T0(n);return t.alreadyInstalled?`Uninstalled OpenCode plugin from ${t.path}`:`OpenCode plugin not installed in ${t.path}`}var $5={"antigravity-cli":{install:X3,uninstall:Y3},cursor:{install:s0,uninstall:d0},"kimi-code":{install:O3,uninstall:T3}};function Ln(n,t,r,e=!1){if(n==="install"&&!e)gt(r);let a=$5[t][n](r),l=j(t),s=n!=="install"?"Uninstalled":e?"Updated":"Installed";return n==="install"&&a.alreadyInstalled?e?`${l} hook up to date in ${a.path}`:`${l} hook already installed in ${a.path}`:n==="uninstall"&&!a.alreadyInstalled?`${l} hook not installed in ${a.path}`:`${s} ${l} hook ${n==="install"?"in":"from"} ${a.path}`}var D5={amp:{install:z3,uninstall:F3,restartNote:'Amp personal plugins apply to every Amp session, including Orb threads. Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:u0,uninstall:b0,afterInstall:async(n)=>{let t=A1(n);return await l2(["hermes","plugins","enable",U,"--no-allow-tool-override"]),!t},beforeUninstall:async(n)=>{V1(n);try{await l2(["hermes","plugins","disable",U])}catch(t){console.warn(`${t instanceof Error?t.message:String(t)}
223
+ Removing the plugin files anyway; ${U} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};async function kt(n,t,r,e=!1){let a=D5[t];if(n==="uninstall")await a.beforeUninstall?.(r);let l=n==="install"?await a.install(r):await a.uninstall(r),s=n==="install"&&await a.afterInstall?.(r),d=j(t),c=!s&&(n==="install"&&l.alreadyInstalled||n==="uninstall"&&!l.alreadyInstalled);return[c?n==="install"?`${d} plugin ${e?"up to date":"already installed"} at ${l.path}`:`${d} plugin not installed at ${l.path}`:`${n!=="install"?"Uninstalled":e?"Updated":"Installed"} ${d} plugin ${n==="install"?"at":"from"} ${l.path}`,c?void 0:a.restartNote].filter(Boolean).join(`
224
+ `)}var m5={amp:{install:(n,t)=>kt("install","amp",n,t),uninstall:(n)=>kt("uninstall","amp",n)},"antigravity-cli":{install:(n,t)=>Ln("install","antigravity-cli",n,t),uninstall:(n)=>Ln("uninstall","antigravity-cli",n)},"claude-code":{install:(n,t)=>Y2("claude-code",n,t),uninstall:()=>cn("claude-code")},codex:{install:(n,t,r)=>Y2("codex",n,t,r),uninstall:()=>cn("codex")},"copilot-cli":{install:async(n,t)=>[await Y2("copilot-cli",n,t),f5(n)].filter(Boolean).join(`
225
+ `),uninstall:()=>cn("copilot-cli")},cursor:{install:(n,t)=>Ln("install","cursor",n,t),uninstall:(n)=>Ln("uninstall","cursor",n)},"gemini-cli":{install:(n,t)=>Y2("gemini-cli",n,t),uninstall:()=>cn("gemini-cli")},"hermes-agent":{install:(n,t)=>{if(!t)gt(n);return kt("install","hermes-agent",n,t)},uninstall:(n)=>kt("uninstall","hermes-agent",n)},"kimi-code":{install:(n,t)=>Ln("install","kimi-code",n,t),uninstall:(n)=>Ln("uninstall","kimi-code",n)},openclaw:{install:async(n,t)=>{let r=await Y2("openclaw",n,t);return await B0(),r},uninstall:(n)=>{return T1(n),cn("openclaw")}},opencode:{install:async(n,t)=>{let r=await Y2("opencode",n,t);return await G0(n),r},uninstall:(n)=>x5(n)},pi:{install:async(n,t)=>[await Y2("pi",n,t),y5(n)].filter(Boolean).join(`
226
+ `),uninstall:()=>cn("pi")}},I3=["Install CC Safety Net as a native Kimi Code plugin:",""," 1. Start Kimi Code and run: /plugins install https://github.com/kenryu42/cc-safety-net"," Confirm the trust prompt; it defaults to cancel."," 2. Run /reload, or start a new session.","","Note: Kimi Code hooks are fail-open. When the hook process cannot start, crashes, or times","out, Kimi Code allows the tool call."].join(`
227
+ `);function g5(n){if(Zn({homeDir:n,cwd:process.cwd()}).status!=="configured")return I3;return[I3,"",o.red(["CAUTION: the global Kimi Code hook is installed and will run alongside the plugin.","After the plugin is active, remove it with: cc-safety-net uninstall --kimi-code"].join(`
221
228
  `))].join(`
222
- `)}function Kl(n,t){return t.map((e)=>n==="install"&&e.target==="kimi-code"&&e.unavailableReason==="already installed"?{...e,available:!0,unavailableReason:void 0,label:`${e.label} (global hook installed)`}:e)}function s5(n,t){if(n.selectKimiInstallMethod)return n.selectKimiInstallMethod();if(!_e(n.input,n.output))return Promise.resolve("global-hook");return T0({input:n.input,output:n.output,globalHookInstalled:Fn({homeDir:t,cwd:process.cwd()}).status==="configured"})}async function Ol(n,t,e,r=!1,a){return l5[t][n](e,r,a)}function c5(n){let t=F({label:"update"},n).errors[0];if(t)throw Error(t)}async function i5(n,t=_2){let e=await Ul(n,t),r=sr(kn(n),"installed-plugins");return{targets:Ne([...e.hooks.filter((l)=>l.platform!=="copilot-cli"&&l.detected).map((l)=>l.platform),...[In,Sa,Ya].flatMap((l)=>ir(sr(r,...l))?["copilot-cli"]:[]),...Pn(n,cr)?["claude-code"]:[],...Lr(e.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:e.codexPluginListOutput}}async function L5(n){let t=wt(),e=n.output??process.stdout,r=i5(t,n.fetchVersion??_2).then(async(s)=>{let c=new Set(s.targets);return{targets:s.targets,codexPluginListOutput:s.codexPluginListOutput,available:new Map(await Promise.all(C.filter((i)=>c.has(i.target)&&Hl.has(i.target)).map(async(i)=>[i.target,await tr(i.probeCommand)])))}}),a=await Dn(n.showBanner??!0,()=>({ready:r,finish:()=>r}),()=>gn({input:n.input??process.stdin,output:e}),{loadingMessage:"Checking installed integrations…",output:e});if(a.targets.length===0)return e.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),0;let l=a.targets.some((s)=>Al.has(s))?await Promise.resolve().then(()=>{return ot(t),null}).catch((s)=>yt(s)):null,d=await Tn(Promise.all(a.targets.map((s)=>{if(Hl.has(s)&&!a.available.get(s))return Promise.resolve({message:`${b2(s)} not found; skipped`,failed:!1});if(l!==null&&Al.has(s))return Promise.resolve({message:l,failed:!0});return Ol("install",s,t,!0,a.codexPluginListOutput).then((c)=>({message:c,failed:!1}),(c)=>({message:yt(c),failed:!0}))})),{loadingMessage:`Updating ${a.targets.length} integration${a.targets.length===1?"":"s"}…`,output:e});return d.forEach((s)=>{s.failed?console.error(s.message):e.write(`${s.message}
223
- `)}),d.some((s)=>s.failed)?1:0}function pr(n,t={}){return Promise.resolve().then(()=>c5(n)).then(()=>L5(t)).catch((e)=>{return console.error(yt(e)),1})}async function Xn(n,t,e={}){try{let r=await Dn(!0,()=>t5(n,t,e),()=>gn({input:e.input??process.stdin,output:e.output??process.stdout}),{loadingMessage:n==="install"?"Checking available integrations…":"Checking installed integrations…",output:e.output??process.stdout});if(!r)return(e.output??process.stdout).write(`Cancelled: nothing was ${n}ed.
224
- `),0;if(r==="update")return(e.runUpdate??(()=>pr([],{fetchVersion:e.fetchVersion,input:e.input,output:e.output,showBanner:!1})))();let a=wt(),l=e.output??process.stdout;return await fl(r,async(d)=>{if(d==="kimi-code"&&n==="install"){let c=await s5(e,a);if(c===null){l.write(`Cancelled: Kimi Code integration was not installed.
225
- `);return}if(c==="plugin"){l.write(`${d5(a)}
226
- `);return}}let s=await Tn(Ol(n,d,a),{loadingMessage:`${n==="install"?"Installing":"Uninstalling"} ${b2(d)} integration…`,output:l});l.write(`${s}
227
- `)}),0}catch(r){return console.error(yt(r)),1}}function yt(n){let t=n instanceof Error?n.message:String(n),e=typeof n==="object"&&n!==null&&"code"in n?n.code:null;if(e==="EACCES"||e==="EPERM")return`${t}
228
- Check file permissions for the target config file and parent directory.`;if(e==="ENOENT")return`${t}
229
- Check that the target config path and parent directory exist.`;if(e==="ENOTDIR")return`${t}
230
- Check that every parent path component is a directory.`;return t}import{join as T5}from"node:path";var Tl="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Cache path | Priority |\n|-------|-------------|---------------|------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | `~/.cc-safety-net/cache/rulebooks/` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | `.cc-safety-net/cache/rulebooks/` | Second |\n| GitHub source | Listed in a local `rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` in the source repository | Consumer local cache | Source order |\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule sync`/`rule verify` report the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- Transparent wrappers have no built-in defaults. Configure only wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n\n## Rulebook Sources\n\n- Local sources are bare rulebook names such as `project-rules`; the rulebook file is `.cc-safety-net/rules/project-rules/rulebook.json`.\n- GitHub sources use `owner/repo#ref/<rulebook-name>`.\n- GitHub refs must be one path segment, such as a tag, SHA, or branch name without `/`.\n- The GitHub source name, the repository directory name, and the rulebook `name` must match exactly.\n- Rulebook source strings must be unique in a config.\n\n## rulebook.json Schema\n\n```json\n{\n \"rulebook_version\": 1,\n \"name\": \"project-rules\",\n \"version\": \"1.0.0\",\n \"description\": \"Project-specific CC Safety Net rules.\",\n \"author\": \"project\",\n \"allowed_commands\": [\"docker\"],\n \"rules\": [\n {\n \"name\": \"block-docker-system-prune\",\n \"command\": \"docker\",\n \"subcommand\": \"system\",\n \"block_args\": [\"prune\"],\n \"reason\": \"Use targeted cleanup instead.\"\n }\n ],\n \"tests\": [\n {\n \"command\": \"docker system prune\",\n \"expect\": \"blocked\",\n \"rule\": \"block-docker-system-prune\"\n },\n {\n \"command\": \"docker ps\",\n \"expect\": \"allowed\"\n }\n ]\n}\n```\n\n### Rulebook Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `rulebook_version` | Yes | Must be `1` |\n| `name` | Yes | `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` |\n| `version` | Yes | Non-empty string |\n| `description` | No | Free text; not type-checked at runtime |\n| `author` | No | Free text; not type-checked at runtime |\n| `allowed_commands` | Yes | Unique command names matching `^[a-zA-Z][a-zA-Z0-9_-]*$` |\n| `rules` | Yes | Array of rule objects |\n| `tests` | No | Array of fixtures |\n\n### Rule Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Unique within the rulebook (case-insensitive); same pattern as rulebook `name` |\n| `command` | Yes | Must be listed in `allowed_commands`; basename only, not path |\n| `subcommand` | No | Same pattern as `command`; omit to match any subcommand |\n| `intent` | No | One of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain` |\n| `block_args` | Yes | Non-empty array of non-empty strings |\n| `reason` | Yes | Non-empty string, max 256 chars |\n\n### Test Fixture Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `command` | Yes | Non-empty shell command string |\n| `expect` | Yes | `\"blocked\"` or `\"allowed\"` |\n| `rule` | Required for blocked fixtures | Rule name expected to block the command |\n\nFixtures are optional documentation of intended behavior. Fixtures are shape-validated only; CC Safety Net does not execute them.\n\n## Matching Behavior\n\n- **Command**: Normalized to lowercase basename with any trailing `.exe` removed (`/usr/bin/git` → `git`).\n- **Subcommand**: The first command token after recognized Git and Docker global options and their values; `--` ends option parsing. An unrecognized option without `=` may consume the following token as its value.\n- **Arguments**: Each `block_args` value is compared literally against every command token, including expanded short options. The command is blocked if **any** item matches.\n- **Short options**: Expanded (`-Ap` matches `-A`).\n- **Long options**: Exact match (`--all-files` does not match `--all`).\n- **Execution order**: Built-in rules first, then custom rulebooks. Custom rules only add restrictions.\n- **Transparent wrappers**: A configured wrapper such as `rtk` lets `rtk git commit` be analyzed as `git commit` only when `git` is protected by built-in analyzers or active custom rules. `rtk -- git commit` is also supported.\n\n## Workflow\n\n1. Run `cc-safety-net rule init` or create `rule.json` manually.\n2. Optionally run `cc-safety-net rule init --example` to create an inactive example rulebook.\n3. Use `cc-safety-net rule wrapper add rtk` for trusted transparent wrappers.\n4. Run `cc-safety-net rule add <source>` after creating or choosing a rulebook source; it adds the source and syncs it.\n5. Run `cc-safety-net rule sync` after manual `rule.json` changes or local rulebook edits.\n6. Run `cc-safety-net rule verify` to validate config, lock/cache state, local rulebooks, and shareable GitHub-source rulebook directories in the current repository (it does not fetch remote content).\n7. Run `cc-safety-net rule list` to inspect active rulebooks and transparent wrappers.\n\nAn edited or invalid local rulebook keeps its last synced, digest-verified cached version enforced until `cc-safety-net rule sync` validates the edit. A missing lock entry or cache, a cache digest mismatch, or an invalid cached rulebook makes that source inactive; a missing lockfile or an unreadable or invalid `rule.json` makes every source in its scope inactive. Inactive sources stop applying their rules while other custom rules and all built-in protections stay active. Repair the reported condition, then run `cc-safety-net rule sync`. Run `cc-safety-net status` to see degraded sources.\n";function Yn(n,t){if(!n.ok){v5(n);return}b5(n),console.log(t),console.log("Rule config synced."),console.log(""),p5(n.entries)}function p5(n){if(n.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${n.length}):`);for(let t of n)console.log(` - ${t.name} ${t.version} (${u5(t.ruleCount??0)})`),console.log(` Source: ${Ot(t)}`)}function u5(n){return`${n} ${n===1?"rule":"rules"}`}function El(n,t){J2("Active sources",n.rulebooks,(e)=>[`[${e.source}] ${e.name} ${e.version}`,` Source: ${t[e.source].get(e.spec)??e.spec}`]),J2("Active rules",n.rules,(e)=>[`[${o5(n,e.name)}] ${e.name}`,` Command: ${e.subcommand?`${e.command} ${e.subcommand}`:e.command}`,` Block args: ${e.block_args.join(", ")}`,` Reason: ${e.reason}`]),J2("Disabled rules",_l(n,"off"),(e)=>[e.key]),J2("Reason overrides",_l(n,"reason"),(e)=>[e.key,` Reason: ${e.value.reason}`]),J2("Transparent wrappers",n.transparent_wrappers,(e)=>[e]),J2("Issues",n.errors,(e)=>[e]),J2("Warnings",n.warnings,(e)=>[e])}function J2(n,t,e){if(t.length===0){console.log(`${n}: (none)`);return}console.log(`${n} (${t.length}):`);for(let r of t){let[a,...l]=e(r);console.log(` - ${a}`);for(let d of l)console.log(` ${d}`)}}function o5(n,t){return n.rulebooks.find((e)=>e.rules.includes(t))?.source??"project"}function _l(n,t){return Object.entries({...n.userConfig?.overrides??{},...n.projectConfig?.overrides??{}}).filter((e)=>{if(t==="off")return e[1]==="off";return!!e[1]&&typeof e[1]==="object"}).map(([e,r])=>({key:e,value:r}))}function v5(n){for(let t of n.errors)console.error(t)}function b5(n){if(!n.warnings||n.warnings.length===0)return;for(let t of n.warnings)console.warn(t)}import{dirname as Pl,join as xt}from"node:path";var f5=".safety-net.json",h5="~/.cc-safety-net/config.json";async function n3(n){return[await Il({legacyPath:Nl({cwd:n.cwd}),configPath:_(n.cwd),defaultRulebookName:"project-rules",migratedFrom:f5,cleanup:n.cleanup,syncOptions:{cwd:n.cwd}}),await Il({legacyPath:pn(),configPath:E(),defaultRulebookName:"user-rules",migratedFrom:h5,cleanup:n.cleanup,syncOptions:{cwd:n.cwd,global:!0}})].every((e)=>e)?0:1}async function Il(n){let t=U(n.syncOptions),e=D(t.filesystemScope,n.legacyPath),r=g(e);if(r===null)return console.log(`No legacy config found at ${n.legacyPath}`),!0;let a=w5(r);if(!a.ok){for(let v of a.errors)console.error(v);return!1}let l=O(t.configTarget);if(l.errors.length>0){for(let v of l.errors)console.error(v);return!1}let d=l.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},s=x5(Pl(n.configPath),d.rules,n.defaultRulebookName,n.migratedFrom,t.filesystemScope),c=xt(Pl(n.configPath),s,"rulebook.json"),i=D(t.filesystemScope,c),L=[ur(t.configTarget),ur(i),ur(t.lockTarget)],u=await y5(n,t.configTarget,i,s,a.config.rules,d.rules.includes(s)?d.rules:[...d.rules,s],d.overrides??{},d.transparent_wrappers??[]);if(!u.ok){D5(L);for(let v of u.errors)console.error(v);return!1}if(!n.cleanup)return console.log(`Migrated legacy config at ${n.legacyPath}. Legacy file is no longer used.`),!0;if(!g5(t.configTarget,i,s,n.migratedFrom,a.config.rules))return console.error(`Migration cleanup verification failed for ${n.legacyPath}`),!1;return cn(e),console.log(`Deleted legacy config at ${n.legacyPath}`),!0}async function y5(n,t,e,r,a,l,d,s){try{return T(t,{version:1,rules:l,overrides:d,transparent_wrappers:s}),T(e,$5(r,n.migratedFrom,a)),await W2(n.syncOptions)}catch(c){return{ok:!1,errors:[c instanceof Error?c.message:String(c)]}}}function w5(n){try{let t=JSON.parse(n),e=Xt(t);if(e.errors.length>0)return{ok:!1,errors:e.errors};return{ok:!0,config:{version:1,rules:t.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function x5(n,t,e,r,a){let l=t.find((d)=>m5(D(a,xt(n,d,"rulebook.json")))===r);if(l)return l;if(g(D(a,xt(n,e,"rulebook.json")))===null)return e;for(let d=2;;d++){let s=`${e}-${d}`;if(g(D(a,xt(n,s,"rulebook.json")))===null)return s}}function $5(n,t,e){return{rulebook_version:1,name:n,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:t,allowed_commands:[...new Set(e.map((r)=>r.command))],rules:e,tests:e.map((r)=>({command:[r.command,r.subcommand,r.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:r.name}))}}function g5(n,t,e,r,a){if(!O(n).config?.rules.includes(e))return!1;try{let d=g(t);if(d===null)return!1;let s=JSON.parse(d);return s.migrated_from===r&&JSON.stringify(s.rules)===JSON.stringify(a)}catch{return!1}}function ur(n){return{target:n,content:g(n)}}function D5(n){for(let t of n){if(t.content===null){cn(t.target);continue}w2(t.target,t.content)}}function m5(n){let t=g(n);if(t===null)return null;try{let e=JSON.parse(t);return typeof e.migrated_from==="string"?e.migrated_from:null}catch{return null}}import{mkdir as k5,readFile as q5,writeFile as j5}from"node:fs/promises";import{dirname as F5,join as z5}from"node:path";var B5=86400000,J5=604800000;async function e3(n=Date.now()){if(process.env.CC_SAFETY_NET_NO_UPDATE_CHECK)return null;let t=Et();if(!t)return null;let e=z5(t,".cc-safety-net","update-check.json"),r=await Z5(e,n);if(!r.lastCheck||n-r.lastCheck>B5){let d=await E2();if(r.lastCheck=n,d.latestVersion)r.latestVersion=d.latestVersion;if(!await t3(e,r))return null;if(d.error)return null}let a=r.latestVersion,l=j();if(!a||!ve(a,l))return null;if(r.notifiedVersion===a&&r.notifiedAt!==void 0&&n-r.notifiedAt<J5)return null;if(r.notifiedVersion=a,r.notifiedAt=n,!await t3(e,r))return null;return`UPDATE_AVAILABLE: cc-safety-net v${a} is available (running v${l}). Ask the user once whether to run \`npx -y cc-safety-net@latest update\`; continue the current task either way and do not raise this again.`}async function Z5(n,t){let e=await q5(n,"utf8").then((l)=>JSON.parse(l)).catch(()=>{return});if(!e||typeof e!=="object"||Array.isArray(e))return{};let r=e,a=(l)=>typeof l==="number"&&Number.isFinite(l)&&l<=t?l:void 0;return{lastCheck:a(r.lastCheck),latestVersion:typeof r.latestVersion==="string"?r.latestVersion:void 0,notifiedVersion:typeof r.notifiedVersion==="string"?r.notifiedVersion:void 0,notifiedAt:a(r.notifiedAt)}}async function t3(n,t){return k5(F5(n),{recursive:!0,mode:448}).then(()=>j5(n,JSON.stringify(t),{mode:384})).then(()=>!0).catch(()=>!1)}import{dirname as Q5,join as X5,resolve as or}from"node:path";var a3="CC Safety Net Config",Y5="═".repeat(a3.length),S5="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",H5=new Set(["rule.json","rule.lock","cache"]);function l3(n={}){try{return A5(n)}catch(t){if(t instanceof Z)return console.error(t.message),1;throw t}}function A5(n){let t=n.cwd??process.cwd(),e=n.userConfigPath??E(),r=n.projectConfigPath??_(t),a=n.legacyUserConfigPath??pn(),l=n.legacyProjectConfigPath??Sr(t),d=or(t,Ut),s=Q5(e),c=P({cwd:t,userConfigPath:e,projectConfigPath:r}),i=P({cwd:t}),L=D(c.userScope,e),u=D(c.projectScope,r),v=n.legacyUserConfigPath?sn(n.legacyUserConfigPath,"user policy"):D(i.userScope,a),p=n.legacyProjectConfigPath?sn(n.legacyProjectConfigPath,"project policy"):D(i.projectScope,l),f=!1,o=!1,h=[],x=[],w=W5(D(i.projectScope,d));if(K5(),g(L)!==null){let y=a2(L);if(y.errors.push(...l2(e,R2({userConfigDir:s}),{userConfigDir:s},c.userScope)),h.push({scope:"User",path:e,result:y,schema:"rules",sourceDisplayMap:x2(e,c.userScope),target:L}),y.errors.length>0)f=!0}if(g(v)!==null)if(o=!0,g(L)!==null)x.push($t("user","cleanup"));else{let y=Yt(v);if(h.push({scope:"User",path:a,result:y,schema:"legacy",sourceDisplayMap:new Map,inactive:!0,target:v}),x.push($t("user",y.errors.length>0?"fix-or-delete":"migrate")),y.errors.length>0)f=!0}if(g(u)!==null){let y=a2(u);if(y.errors.push(...l2(r,K2(r),{userConfigDir:s},c.projectScope)),h.push({scope:"Project",path:or(r),result:y,schema:"rules",sourceDisplayMap:x2(r,c.projectScope),target:u}),y.errors.length>0)f=!0;if(g(p)!==null)o=!0,x.push($t("project","cleanup"))}else if(g(p)!==null){o=!0,f=!0;let y=Yt(p);h.push({scope:"Project",path:or(l),result:y,schema:"legacy",sourceDisplayMap:new Map,inactive:!0,target:p}),x.push($t("project",y.errors.length>0?"fix-or-delete":"migrate"))}if(w?.result.errors.length)f=!0;if(h.length===0&&!w)return console.log(`
231
- No config files found. Using built-in rules only.`),0;for(let y of h)if(y.inactive)V5(y.scope,y.path,y.result,y.sourceDisplayMap);else if(y.result.errors.length>0)G5(y.scope,y.path,y.result.errors);else{if(y.schema==="rules"&&O5(y.target))console.log(`
232
- Added $schema to ${y.scope.toLowerCase()} config.`);M5(y.scope,y.path,y.result,y.schema,y.sourceDisplayMap)}for(let y of x)console.error(`
233
- ${b.red(y)}`);if(w)if(w.result.errors.length>0)U5(w.path,w.result.errors);else C5(w.path,w.result);if(f)return console.error(`
234
- Config validation failed.`),1;return console.log(o?`
229
+ `)}function N3(n,t){return t.map((r)=>n==="install"&&r.target==="kimi-code"&&r.unavailableReason==="already installed"?{...r,available:!0,unavailableReason:void 0,label:`${r.label} (global hook installed)`}:r)}function k5(n,t){if(n.selectKimiInstallMethod)return n.selectKimiInstallMethod();if(!sr(n.input,n.output))return Promise.resolve("global-hook");return y3({input:n.input,output:n.output,globalHookInstalled:Zn({homeDir:t,cwd:process.cwd()}).status==="configured"})}async function ll(n,t,r,e=!1,a){return m5[t][n](r,e,a)}function q5(n){let t=J({label:"update"},n).errors[0];if(t)throw Error(t)}async function j5(n,t=P2){let r=await al(n,t),e=fr(Fn(n),"installed-plugins");return{targets:pr([...r.hooks.filter((l)=>l.platform!=="copilot-cli"&&l.detected).map((l)=>l.platform),...[et,Ua,Ga].flatMap((l)=>hr(fr(e,...l))?["copilot-cli"]:[]),...rt(n,yr)?["claude-code"]:[],...wr(r.codexPluginListOutput)?["codex"]:[]]),codexPluginListOutput:r.codexPluginListOutput}}async function z5(n){let t=jt(),r=n.output??process.stdout,e=j5(t,n.fetchVersion??P2).then(async(d)=>{let c=new Set(d.targets);return{targets:d.targets,codexPluginListOutput:d.codexPluginListOutput,available:new Map(await Promise.all(T.filter((L)=>c.has(L.target)&&_3.has(L.target)).map(async(L)=>[L.target,await ur(L.probeCommand)])))}}),a=await jn(n.showBanner??!0,()=>({ready:e,finish:()=>e}),()=>qn({input:n.input??process.stdin,output:r}),{loadingMessage:"Checking installed integrations…",output:r});if(a.targets.length===0)return r.write("No installed integrations found. Run `cc-safety-net install` to set one up.\n"),0;let l=a.targets.some((d)=>E3.has(d))?await Promise.resolve().then(()=>{return gt(t),null}).catch((d)=>qt(d)):null,s=await Nn(Promise.all(a.targets.map((d)=>{if(_3.has(d)&&!a.available.get(d))return Promise.resolve({message:`${j(d)} not found; skipped`,failed:!1});if(l!==null&&E3.has(d))return Promise.resolve({message:l,failed:!0});return ll("install",d,t,!0,a.codexPluginListOutput).then((c)=>({message:c,failed:!1}),(c)=>({message:qt(c),failed:!0}))})),{loadingMessage:`Updating ${a.targets.length} integration${a.targets.length===1?"":"s"}…`,output:r});return s.forEach((d)=>{d.failed?console.error(d.message):r.write(`${d.message}
230
+ `)}),s.some((d)=>d.failed)?1:0}function xr(n,t={}){return Promise.resolve().then(()=>q5(n)).then(()=>z5(t)).catch((r)=>{return console.error(qt(r)),1})}async function Wn(n,t,r={}){try{let e=await jn(!0,()=>w5(n,t,r),()=>qn({input:r.input??process.stdin,output:r.output??process.stdout}),{loadingMessage:n==="install"?"Checking available integrations…":"Checking installed integrations…",output:r.output??process.stdout});if(!e)return(r.output??process.stdout).write(`Cancelled: nothing was ${n}ed.
231
+ `),0;if(e==="update")return(r.runUpdate??(()=>xr([],{fetchVersion:r.fetchVersion,input:r.input,output:r.output,showBanner:!1})))();let a=jt(),l=r.output??process.stdout;return await H3(e,async(s)=>{if(s==="kimi-code"&&n==="install"){let c=await k5(r,a);if(c===null){l.write(`Cancelled: Kimi Code integration was not installed.
232
+ `);return}if(c==="plugin"){l.write(`${g5(a)}
233
+ `);return}}let d=await Nn(ll(n,s,a),{loadingMessage:`${n==="install"?"Installing":"Uninstalling"} ${j(s)} integration…`,output:l});l.write(`${d}
234
+ `)}),0}catch(e){return console.error(qt(e)),1}}function qt(n){let t=n instanceof Error?n.message:String(n),r=typeof n==="object"&&n!==null&&"code"in n?n.code:null;if(r==="EACCES"||r==="EPERM")return`${t}
235
+ Check file permissions for the target config file and parent directory.`;if(r==="ENOENT")return`${t}
236
+ Check that the target config path and parent directory exist.`;if(r==="ENOTDIR")return`${t}
237
+ Check that every parent path component is a directory.`;return t}import{join as v8}from"node:path";var sl="# Custom Rules Reference\n\nAgent reference for generating CC Safety Net rulebook configuration.\n\n## Config Locations\n\n| Scope | Config path | Rulebook path | Cache path | Priority |\n|-------|-------------|---------------|------------|----------|\n| User | `~/.cc-safety-net/rules/rule.json` | `~/.cc-safety-net/rules/<rulebook-name>/rulebook.json` | `~/.cc-safety-net/cache/rulebooks/` | First |\n| Project | `.cc-safety-net/rules/rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` | `.cc-safety-net/cache/rulebooks/` | Second |\n| GitHub source | Listed in a local `rule.json` | `.cc-safety-net/rules/<rulebook-name>/rulebook.json` in the source repository | Consumer local cache | Source order |\n\nUser scope is evaluated before project scope; within a scope, sources apply in `rules` array order. A duplicate active rulebook name keeps the first claim and ignores the later rulebook with a warning, so a user-scoped name shadows a project-scoped one.\n\nUse `cc-safety-net rule init` to create an inert local config. Use `--global` for user scope. Use `cc-safety-net rule init --example` to also create an inactive example rulebook. `CC_SAFETY_NET_HOME` overrides the `~/.cc-safety-net` user root.\n\nLegacy inline `.safety-net.json` and `~/.cc-safety-net/config.json` files are not loaded at runtime. Convert them with `cc-safety-net rule migrate`.\n\n## rule.json Schema\n\n```json\n{\n \"version\": 1,\n \"rules\": [\"project-rules\", \"owner/repo#main/team-rules\"],\n \"overrides\": {\n \"project-rules/block-docker-system-prune\": {\n \"reason\": \"Use targeted Docker cleanup commands.\"\n },\n \"team-rules/block-npm-global\": \"off\"\n },\n \"transparent_wrappers\": [\"rtk\"]\n}\n```\n\n- `version`: Required. Must be `1`.\n- `$schema`: Optional. `cc-safety-net rule verify` inserts it into a valid `rule.json` that lacks it.\n- `rules`: Optional array of rulebook source strings. Missing `rules` is treated as `[]`.\n- `overrides`: Optional object keyed by `<rulebook-name>/<rule-name>`.\n- `overrides` values are either `\"off\"` to disable a rule or an object with a required `reason` (replacement block reason) and an optional `intent` (one of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain`).\n- A project override cannot target a user-scoped rule: only that override is ignored, the user rule keeps its configured state, and `rule sync`/`rule verify` report the diagnostic as a failure.\n- `transparent_wrappers`: Optional array of command names that transparently execute a visible child command.\n- Transparent wrappers have no built-in defaults. Configure only wrappers you intentionally trust, such as `\"rtk\"`.\n- Use `cc-safety-net rule wrapper add rtk` to configure RTK without manually editing `rule.json`.\n\n## Rulebook Sources\n\n- Local sources are bare rulebook names such as `project-rules`; the rulebook file is `.cc-safety-net/rules/project-rules/rulebook.json`.\n- GitHub sources use `owner/repo#ref/<rulebook-name>`.\n- GitHub refs must be one path segment, such as a tag, SHA, or branch name without `/`.\n- The GitHub source name, the repository directory name, and the rulebook `name` must match exactly.\n- Rulebook source strings must be unique in a config.\n\n## rulebook.json Schema\n\n```json\n{\n \"rulebook_version\": 1,\n \"name\": \"project-rules\",\n \"version\": \"1.0.0\",\n \"description\": \"Project-specific CC Safety Net rules.\",\n \"author\": \"project\",\n \"allowed_commands\": [\"docker\"],\n \"rules\": [\n {\n \"name\": \"block-docker-system-prune\",\n \"command\": \"docker\",\n \"subcommand\": \"system\",\n \"block_args\": [\"prune\"],\n \"reason\": \"Use targeted cleanup instead.\"\n }\n ],\n \"tests\": [\n {\n \"command\": \"docker system prune\",\n \"expect\": \"blocked\",\n \"rule\": \"block-docker-system-prune\"\n },\n {\n \"command\": \"docker ps\",\n \"expect\": \"allowed\"\n }\n ]\n}\n```\n\n### Rulebook Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `rulebook_version` | Yes | Must be `1` |\n| `name` | Yes | `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$` |\n| `version` | Yes | Non-empty string |\n| `description` | No | Free text; not type-checked at runtime |\n| `author` | No | Free text; not type-checked at runtime |\n| `allowed_commands` | Yes | Unique command names matching `^[a-zA-Z][a-zA-Z0-9_-]*$` |\n| `rules` | Yes | Array of rule objects |\n| `tests` | No | Array of fixtures |\n\n### Rule Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `name` | Yes | Unique within the rulebook (case-insensitive); same pattern as rulebook `name` |\n| `command` | Yes | Must be listed in `allowed_commands`; basename only, not path |\n| `subcommand` | No | Same pattern as `command`; omit to match any subcommand |\n| `intent` | No | One of `hard_stop`, `use_alternative`, `scope_down`, `manual_only`, `stop_and_explain` |\n| `block_args` | Yes | Non-empty array of non-empty strings |\n| `reason` | Yes | Non-empty string, max 256 chars |\n\n### Test Fixture Fields\n\n| Field | Required | Constraints |\n|-------|----------|-------------|\n| `command` | Yes | Non-empty shell command string |\n| `expect` | Yes | `\"blocked\"` or `\"allowed\"` |\n| `rule` | Required for blocked fixtures | Rule name expected to block the command |\n\nFixtures are optional documentation of intended behavior. Fixtures are shape-validated only; CC Safety Net does not execute them.\n\n## Matching Behavior\n\n- **Command**: Normalized to lowercase basename with any trailing `.exe` removed (`/usr/bin/git` → `git`).\n- **Subcommand**: The first command token after recognized Git and Docker global options and their values; `--` ends option parsing. An unrecognized option without `=` may consume the following token as its value.\n- **Arguments**: Each `block_args` value is compared literally against every command token, including expanded short options. The command is blocked if **any** item matches.\n- **Short options**: Expanded (`-Ap` matches `-A`).\n- **Long options**: Exact match (`--all-files` does not match `--all`).\n- **Execution order**: Built-in rules first, then custom rulebooks. Custom rules only add restrictions.\n- **Transparent wrappers**: A configured wrapper such as `rtk` lets `rtk git commit` be analyzed as `git commit` only when `git` is protected by built-in analyzers or active custom rules. `rtk -- git commit` is also supported.\n\n## Workflow\n\n1. Run `cc-safety-net rule init` or create `rule.json` manually.\n2. Optionally run `cc-safety-net rule init --example` to create an inactive example rulebook.\n3. Use `cc-safety-net rule wrapper add rtk` for trusted transparent wrappers.\n4. Run `cc-safety-net rule add <source>` after creating or choosing a rulebook source; it adds the source and syncs it.\n5. Run `cc-safety-net rule sync` after manual `rule.json` changes or local rulebook edits.\n6. Run `cc-safety-net rule verify` to validate config, lock/cache state, local rulebooks, and shareable GitHub-source rulebook directories in the current repository (it does not fetch remote content).\n7. Run `cc-safety-net rule list` to inspect active rulebooks and transparent wrappers.\n\nAn edited or invalid local rulebook keeps its last synced, digest-verified cached version enforced until `cc-safety-net rule sync` validates the edit. A missing lock entry or cache, a cache digest mismatch, or an invalid cached rulebook makes that source inactive; a missing lockfile or an unreadable or invalid `rule.json` makes every source in its scope inactive. Inactive sources stop applying their rules while other custom rules and all built-in protections stay active. Repair the reported condition, then run `cc-safety-net rule sync`. Run `cc-safety-net status` to see degraded sources.\n";function Kn(n,t){if(!n.ok){Z5(n);return}Q5(n),console.log(t),console.log("Rule config synced."),console.log(""),F5(n.entries)}function F5(n){if(n.length===0){console.log("Active rulebooks: (none)");return}console.log(`Active rulebooks (${n.length}):`);for(let t of n)console.log(` - ${t.name} ${t.version} (${B5(t.ruleCount??0)})`),console.log(` Source: ${t1(t)}`)}function B5(n){return`${n} ${n===1?"rule":"rules"}`}function cl(n,t){S2("Active sources",n.rulebooks,(r)=>[`[${r.source}] ${r.name} ${r.version}`,` Source: ${t[r.source].get(r.spec)??r.spec}`]),S2("Active rules",n.rules,(r)=>[`[${J5(n,r.name)}] ${r.name}`,` Command: ${r.subcommand?`${r.command} ${r.subcommand}`:r.command}`,` Block args: ${r.block_args.join(", ")}`,` Reason: ${r.reason}`]),S2("Disabled rules",dl(n,"off"),(r)=>[r.key]),S2("Reason overrides",dl(n,"reason"),(r)=>[r.key,` Reason: ${r.value.reason}`]),S2("Transparent wrappers",n.transparent_wrappers,(r)=>[r]),S2("Issues",n.errors,(r)=>[r]),S2("Warnings",n.warnings,(r)=>[r])}function S2(n,t,r){if(t.length===0){console.log(`${n}: (none)`);return}console.log(`${n} (${t.length}):`);for(let e of t){let[a,...l]=r(e);console.log(` - ${a}`);for(let s of l)console.log(` ${s}`)}}function J5(n,t){return n.rulebooks.find((r)=>r.rules.includes(t))?.source??"project"}function dl(n,t){return Object.entries({...n.userConfig?.overrides??{},...n.projectConfig?.overrides??{}}).filter((r)=>{if(t==="off")return r[1]==="off";return!!r[1]&&typeof r[1]==="object"}).map(([r,e])=>({key:r,value:e}))}function Z5(n){for(let t of n.errors)console.error(t)}function Q5(n){if(!n.warnings||n.warnings.length===0)return;for(let t of n.warnings)console.warn(t)}import{dirname as Ll,join as zt}from"node:path";var X5=".safety-net.json",Y5="~/.cc-safety-net/config.json";async function vl(n){return[await il({legacyPath:pl({cwd:n.cwd}),configPath:I(n.cwd),defaultRulebookName:"project-rules",migratedFrom:X5,cleanup:n.cleanup,syncOptions:{cwd:n.cwd}}),await il({legacyPath:on(),configPath:N(),defaultRulebookName:"user-rules",migratedFrom:Y5,cleanup:n.cleanup,syncOptions:{cwd:n.cwd,global:!0}})].every((r)=>r)?0:1}async function il(n){let t=_(n.syncOptions),r=g(t.filesystemScope,n.legacyPath),e=D(r);if(e===null)return console.log(`No legacy config found at ${n.legacyPath}`),!0;let a=H5(e);if(!a.ok){for(let b of a.errors)console.error(b);return!1}let l=E(t.configTarget);if(l.errors.length>0){for(let b of l.errors)console.error(b);return!1}let s=l.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},d=W5(Ll(n.configPath),s.rules,n.defaultRulebookName,n.migratedFrom,t.filesystemScope),c=zt(Ll(n.configPath),d,"rulebook.json"),L=g(t.filesystemScope,c),i=[$r(t.configTarget),$r(L),$r(t.lockTarget)],v=await S5(n,t.configTarget,L,d,a.config.rules,s.rules.includes(d)?s.rules:[...s.rules,d],s.overrides??{},s.transparent_wrappers??[]);if(!v.ok){V5(i);for(let b of v.errors)console.error(b);return!1}if(!n.cleanup)return console.log(`Migrated legacy config at ${n.legacyPath}. Legacy file is no longer used.`),!0;if(!R5(t.configTarget,L,d,n.migratedFrom,a.config.rules))return console.error(`Migration cleanup verification failed for ${n.legacyPath}`),!1;return un(r),console.log(`Deleted legacy config at ${n.legacyPath}`),!0}async function S5(n,t,r,e,a,l,s,d){try{return P(t,{version:1,rules:l,overrides:s,transparent_wrappers:d}),P(r,K5(e,n.migratedFrom,a)),await M2(n.syncOptions)}catch(c){return{ok:!1,errors:[c instanceof Error?c.message:String(c)]}}}function H5(n){try{let t=JSON.parse(n),r=At(t);if(r.errors.length>0)return{ok:!1,errors:r.errors};return{ok:!0,config:{version:1,rules:t.rules??[]}}}catch{return{ok:!1,errors:["Invalid JSON"]}}}function W5(n,t,r,e,a){let l=t.find((s)=>A5(g(a,zt(n,s,"rulebook.json")))===e);if(l)return l;if(D(g(a,zt(n,r,"rulebook.json")))===null)return r;for(let s=2;;s++){let d=`${r}-${s}`;if(D(g(a,zt(n,d,"rulebook.json")))===null)return d}}function K5(n,t,r){return{rulebook_version:1,name:n,version:"1.0.0",description:"Migrated CC Safety Net rules.",author:"project",migrated_from:t,allowed_commands:[...new Set(r.map((e)=>e.command))],rules:r,tests:r.map((e)=>({command:[e.command,e.subcommand,e.block_args[0]].filter(Boolean).join(" "),expect:"blocked",rule:e.name}))}}function R5(n,t,r,e,a){if(!E(n).config?.rules.includes(r))return!1;try{let s=D(t);if(s===null)return!1;let d=JSON.parse(s);return d.migrated_from===e&&JSON.stringify(d.rules)===JSON.stringify(a)}catch{return!1}}function $r(n){return{target:n,content:D(n)}}function V5(n){for(let t of n){if(t.content===null){un(t.target);continue}D2(t.target,t.content)}}function A5(n){let t=D(n);if(t===null)return null;try{let r=JSON.parse(t);return typeof r.migrated_from==="string"?r.migrated_from:null}catch{return null}}import{mkdir as M5,readFile as G5,writeFile as U5}from"node:fs/promises";import{dirname as C5,join as O5}from"node:path";var T5=86400000,_5=604800000;async function bl(n=Date.now()){if(process.env.CC_SAFETY_NET_NO_UPDATE_CHECK)return null;let t=a1();if(!t)return null;let r=O5(t,".cc-safety-net","update-check.json"),e=await E5(r,n);if(!e.lastCheck||n-e.lastCheck>T5){let s=await I2();if(e.lastCheck=n,s.latestVersion)e.latestVersion=s.latestVersion;if(!await ul(r,e))return null;if(s.error)return null}let a=e.latestVersion,l=B();if(!a||!m1(a,l))return null;if(e.notifiedVersion===a&&e.notifiedAt!==void 0&&n-e.notifiedAt<_5)return null;if(e.notifiedVersion=a,e.notifiedAt=n,!await ul(r,e))return null;return`UPDATE_AVAILABLE: cc-safety-net v${a} is available (running v${l}). Ask the user once whether to run \`npx -y cc-safety-net@latest update\`; continue the current task either way and do not raise this again.`}async function E5(n,t){let r=await G5(n,"utf8").then((l)=>JSON.parse(l)).catch(()=>{return});if(!r||typeof r!=="object"||Array.isArray(r))return{};let e=r,a=(l)=>typeof l==="number"&&Number.isFinite(l)&&l<=t?l:void 0;return{lastCheck:a(e.lastCheck),latestVersion:typeof e.latestVersion==="string"?e.latestVersion:void 0,notifiedVersion:typeof e.notifiedVersion==="string"?e.notifiedVersion:void 0,notifiedAt:a(e.notifiedAt)}}async function ul(n,t){return M5(C5(n),{recursive:!0,mode:448}).then(()=>U5(n,JSON.stringify(t),{mode:384})).then(()=>!0).catch(()=>!1)}import{dirname as P5,join as I5,resolve as Dr}from"node:path";var fl="CC Safety Net Config",N5="═".repeat(fl.length),n8="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",t8=new Set(["rule.json","rule.lock","cache"]);function yl(n={}){try{return r8(n)}catch(t){if(t instanceof Y)return console.error(t.message),1;throw t}}function r8(n){let t=n.cwd??process.cwd(),r=n.userConfigPath??N(),e=n.projectConfigPath??I(t),a=n.legacyUserConfigPath??on(),l=n.legacyProjectConfigPath??Ur(t),s=Dr(t,n1),d=P5(r),c=n2({cwd:t,userConfigPath:r,projectConfigPath:e}),L=n2({cwd:t}),i=g(c.userScope,r),v=g(c.projectScope,e),b=n.legacyUserConfigPath?vn(n.legacyUserConfigPath,"user policy"):g(L.userScope,a),p=n.legacyProjectConfigPath?vn(n.legacyProjectConfigPath,"project policy"):g(L.projectScope,l),f=!1,u=!1,h=[],w=[],$=e8(g(L.projectScope,s));if(l8(),D(i)!==null){let y=d2(i);if(y.errors.push(...c2(r,G2({userConfigDir:d}),{userConfigDir:d},c.userScope)),h.push({scope:"User",path:r,result:y,schema:"rules",sourceDisplayMap:m2(r,c.userScope),target:i}),y.errors.length>0)f=!0}if(D(b)!==null)if(u=!0,D(i)!==null)w.push(Ft("user","cleanup"));else{let y=Mt(b);if(h.push({scope:"User",path:a,result:y,schema:"legacy",sourceDisplayMap:new Map,inactive:!0,target:b}),w.push(Ft("user",y.errors.length>0?"fix-or-delete":"migrate")),y.errors.length>0)f=!0}if(D(v)!==null){let y=d2(v);if(y.errors.push(...c2(e,U2(e),{userConfigDir:d},c.projectScope)),h.push({scope:"Project",path:Dr(e),result:y,schema:"rules",sourceDisplayMap:m2(e,c.projectScope),target:v}),y.errors.length>0)f=!0;if(D(p)!==null)u=!0,w.push(Ft("project","cleanup"))}else if(D(p)!==null){u=!0,f=!0;let y=Mt(p);h.push({scope:"Project",path:Dr(l),result:y,schema:"legacy",sourceDisplayMap:new Map,inactive:!0,target:p}),w.push(Ft("project",y.errors.length>0?"fix-or-delete":"migrate"))}if($?.result.errors.length)f=!0;if(h.length===0&&!$)return console.log(`
238
+ No config files found. Using built-in rules only.`),0;for(let y of h)if(y.inactive)d8(y.scope,y.path,y.result,y.sourceDisplayMap);else if(y.result.errors.length>0)c8(y.scope,y.path,y.result.errors);else{if(y.schema==="rules"&&p8(y.target))console.log(`
239
+ Added $schema to ${y.scope.toLowerCase()} config.`);s8(y.scope,y.path,y.result,y.schema,y.sourceDisplayMap)}for(let y of w)console.error(`
240
+ ${o.red(y)}`);if($)if($.result.errors.length>0)i8($.path,$.result.errors);else L8($.path,$.result);if(f)return console.error(`
241
+ Config validation failed.`),1;return console.log(u?`
235
242
  Configs valid with warnings.`:`
236
- All configs valid.`),0}function $t(n,t){let e=`legacy ${n} config`;if(t==="cleanup")return`Warning: Legacy ${n} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(t==="migrate")return`Warning: Legacy ${n} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${n} config is no longer supported. Fix or delete the ${e}, then run \`npx -y cc-safety-net rule migrate\`.`}function W5(n){if(A2(n)===null)return null;let t=R5(n);if(t.ruleNames.size===0&&t.errors.length===0)return null;return{path:n.path,result:t}}function R5(n){let t=[],e=new Set,r=(A2(n)??[]).filter((a)=>!H5.has(a.name)).sort((a,l)=>a.name.localeCompare(l.name));if(r.length===0)return{errors:t,ruleNames:e};for(let a of r){if(!Ln.test(a.name)){t.push(`rulebook directory names must match ${Ln}: ${a.name}`);continue}if(a.kind!=="directory"){t.push(`${a.name} must be a rulebook directory`);continue}let l=D(n.scope,X5(n.path,a.name,"rulebook.json")),d=g(l);if(d===null){t.push(`${a.name}/rulebook.json is required`);continue}try{let s;try{s=JSON.parse(d)}catch{t.push(`${a.name}/rulebook.json: invalid JSON`);continue}let c=r3(s);if(c.name!==a.name){t.push(`rulebook name "${c.name}" must match folder "${a.name}"`);continue}e.add(a.name)}catch(s){t.push(s instanceof Error?`${a.name}/rulebook.json: ${s.message}`:`${a.name}/rulebook.json: ${String(s)}`)}}return{errors:t,ruleNames:e}}function K5(){console.log(a3),console.log(Y5)}function M5(n,t,e,r,a){if(console.log(`
237
- ✓ ${n} config: ${t}`),console.log(` Schema: ${r==="rules"?"rulebook sources":"legacy inline rules"}`),e.ruleNames.size>0){console.log(` ${r==="rules"?"Sources":"Rules"}:`);let l=1;for(let d of e.ruleNames)console.log(` ${l}. ${a.get(d)??d}`),l++}else console.log(` ${r==="rules"?"Sources":"Rules"}: (none)`)}function V5(n,t,e,r){if(console.error(`
238
- ✗ Legacy ${n.toLowerCase()} config: ${t}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),e.errors.length>0){console.error(" Errors:");let a=1;for(let l of e.errors)for(let d of l.split("; "))console.error(` ${a}. ${d}`),a++;return}if(e.ruleNames.size>0){console.error(" Rules:");let a=1;for(let l of e.ruleNames)console.error(` ${a}. ${r.get(l)??l}`),a++;return}console.error(" Rules: (none)")}function G5(n,t,e){d3(`${n} config`,t,e)}function C5(n,t){console.log(`
239
- ✓ GitHub source rules: ${n}`),console.log(" Rulebooks:");let e=1;for(let r of t.ruleNames)console.log(` ${e}. ${r}`),e++}function U5(n,t){d3("GitHub source rules",n,t)}function d3(n,t,e){console.error(`
240
- ✗ ${n}: ${t}`),console.error(" Errors:");let r=1;for(let a of e)for(let l of a.split("; "))console.error(` ${r}. ${l}`),r++}function O5(n){try{let t=g(n);if(t===null)return!1;let e=JSON.parse(t);if(e.$schema)return!1;return w2(n,JSON.stringify({$schema:S5,...e},null,2)),!0}catch(t){if(t instanceof Z)throw t;return!1}}var s3=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),_5=new Set(["add","remove","list"]);async function i3(n){try{return await E5(n)}catch(t){if(t instanceof Z)return console.error(t.message),1;throw t}}async function E5(n){let t=I5(n),e=t.help?P5(t.positionals):null;if(e)return st(e),0;if(t.errors.length>0){for(let d of t.errors)console.error(d);return 1}let r=t.positionals[0];if(!r)return st(T2,console.error),1;let a=t.positionals[1],l={global:t.global,check:t.check};if(r==="init"){let d=U(l),s=d.configDir;t8(d.configTarget),c3(D(d.filesystemScope,Wn({...l,cacheConfigDir:s})));let c=T5(s,"example-rules","rulebook.json"),i=D(d.filesystemScope,c);if(t.example&&g(i)===null)_t(i,"example-rules");let L=await W2(l);return Yn(L,"Rule config initialized."),L.ok?0:1}if(r==="add"){if(!a)return console.error("rule add requires a source"),1;let d=await Vt(a,l);return Yn(d,`Added rulebook source: ${a}`),d.ok?0:1}if(r==="remove"){if(!a)return console.error("rule remove requires a source"),1;let d=await Ct(a,{...l,deleteSource:t.deleteSource});return Yn(d,`Removed rulebook source: ${a}`),d.ok?0:1}if(r==="update"||r==="sync"){let d=await W2({...l,only:r==="update"?a:void 0});return Yn(d,t.check?"Rule config checked.":"Rule config synced."),d.ok?0:1}if(r==="list"){let d=o2(),s=P({});return El(d,{user:x2(d.userConfigPath,s.userScope),project:x2(d.projectConfigPath,s.projectScope)}),d.errors.length>0?1:0}if(r==="wrapper")return e8(t);if(r==="migrate")return n3({cleanup:t.cleanup,cwd:process.cwd()});if(r==="doc"){console.log(Tl);let d=await e3();if(d)console.error(d);return 0}if(r==="verify")return l3();return 1}function P5(n){if(n.length===0)return T2;let t=T2.subcommands.filter((r)=>r.usage.split(" ")[0]===n[0]);if(t.length===0)return null;if(n.length===1&&t.length>1)return{name:`rule ${n[0]}`,description:`Subcommands of rule ${n[0]}`,usage:`rule ${n[0]} <subcommand>`,subcommands:t,options:[]};let e=n.length===1?t[0]:t.find((r)=>r.usage.split(" ")[1]===n[1]);if(!e)return null;return{name:`rule ${n[0]}`,description:e.description,usage:`rule ${e.usage}`,options:[]}}function I5(n){let t=F({label:"rule",booleans:{global:["-g","--global"],check:["--check"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},positionals:"list"},n),e={...t.flags,help:t.help,positionals:t.positionals,errors:t.errors};return N5(e),e}function N5(n){let[t]=n.positionals;if(t&&!s3.has(t))n.errors.push(`Unknown rule subcommand: ${t}`);if(n.deleteSource&&t!=="remove")if(t&&s3.has(t))n.errors.push(`Unknown option for rule ${t}: --delete-source`);else n.errors.push("--delete-source is only valid with 'rule remove'");if(n.cleanup&&t!=="migrate")n.errors.push(gt(t,"--cleanup"));if(n.example&&t!=="init")n.errors.push(gt(t,"--example"));if(t==="migrate"){if(n.global)n.errors.push(gt(t,"--global"));if(n.check)n.errors.push(gt(t,"--check"));if(n.positionals.length>1)n.errors.push(`Unexpected rule migrate argument: ${n.positionals[1]}`)}else if(t==="wrapper")n8(n);else if(n.positionals.length>2)n.errors.push(`Unexpected rule argument: ${n.positionals[2]}`);if(t==="list"&&n.global)n.errors.push("Unknown option for rule list: --global")}function gt(n,t){return n?`Unknown option for rule ${n}: ${t}`:`Unknown option for rule: ${t}`}function n8(n){let t=n.positionals[1],e=n.positionals[2];if(!t){n.errors.push("rule wrapper requires add, remove, or list");return}if(!_5.has(t)){n.errors.push(`Unknown rule wrapper action: ${t}`);return}if(t==="list"){if(e)n.errors.push(`Unexpected rule wrapper argument: ${e}`);return}if(!e){n.errors.push(`rule wrapper ${t} requires a command`);return}if(n.positionals.length>3)n.errors.push(`Unexpected rule wrapper argument: ${n.positionals[3]}`)}function t8(n){if(g(n)===null){Tt(n);return}let t=O(n);if(!t.config)return;T(n,{version:1,rules:t.config.rules,overrides:t.config.overrides??{},transparent_wrappers:t.config.transparent_wrappers??[]})}async function e8(n){let t=n.positionals[1],e=n.positionals[2],r=U({global:n.global}).configTarget;if(t==="list"){let s=O(r);if(s.errors.length>0){for(let c of s.errors)console.error(c);return 1}return r8(s.config?.transparent_wrappers??[]),0}if(!e||!Pt.test(e))return console.error("transparent wrapper must match command pattern"),1;if(It(e))return console.error(`reserved command "${e}" cannot be a wrapper`),1;let a=O(r);if(a.errors.length>0){for(let s of a.errors)console.error(s);return 1}let l=a.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},d=t==="add"?[...new Set([...l.transparent_wrappers??[],e])]:(l.transparent_wrappers??[]).filter((s)=>s!==e);return T(r,{version:1,rules:l.rules,overrides:l.overrides??{},transparent_wrappers:d}),console.log(t==="add"?`Added transparent wrapper: ${e}`:`Removed transparent wrapper: ${e}`),0}function r8(n){if(n.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${n.length}):`);for(let t of n)console.log(` - ${t}`)}import{homedir as L3}from"node:os";import{existsSync as a8,readFileSync as l8}from"node:fs";import{homedir as d8}from"node:os";import{join as s8}from"node:path";async function c8(n){if(n.isTTY)return null;return(await le(n).catch(()=>null))?.trim()||null}function i8(){if(process.env.CLAUDE_SETTINGS_PATH)return process.env.CLAUDE_SETTINGS_PATH;return s8(d8(),".claude","settings.json")}function vr(){let n=i8();if(!a8(n))return!1;try{let t=l8(n,"utf-8"),e=JSON.parse(t);if(!e.enabledPlugins)return!1;let r="cc-safety-net@cc-marketplace";if(!(r in e.enabledPlugins))return!1;return e.enabledPlugins[r]===!0}catch(t){if(vn(m.debug))console.error(`CC Safety Net debug: failed to read Claude settings: ${n}: ${t instanceof Error?t.message:String(t)}`);return!1}}async function br(n=process.stdin){let t=vr(),e;if(!t)e="\uD83D\uDEE1️ CC Safety Net ❌";else{let a=W({cwd:process.cwd()}),l=a.policy,d=d2(l),s=Object.values(g2(l,d.capabilities)).some((i)=>i.changesInherited);e=`\uD83D\uDEE1️ CC Safety Net ${{standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[s?"custom":d.effectiveLevel]}${d.worktreeMode?"\uD83C\uDF33":""}${a.state==="degraded"?"⚠️":""}`}let r=await c8(n);if(r&&!r.startsWith("{"))console.log(`${r} | ${e}`);else console.log(e)}function p3(){let n=W({cwd:process.cwd()}),t=n.policy,e=d2(t),r=!!process.env.NO_COLOR||!process.stdout.isTTY,a=Math.min(process.stdout.columns||80,100),l=r?"ok":"✔",d=r?"OFF":"✘",s=(p,f)=>{let o=` ${p.padEnd(13)}${f}`;return(o.length>a?`${o.slice(0,a-1)}…`:o).replaceAll(d,b.red(d))},c=Object.values(g2(t,e.capabilities)).some((p)=>p.changesInherited),i=bn(),L={ready:b.green,degraded:b.yellow}[n.state],u=[...vr()?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...n.diagnostics],v=r?"-":"·";console.log([`${r?"":"\uD83D\uDEE1️ "}CC Safety Net — ${L(n.state)}`,"",s("Protection",`destructive ${t.destructiveCommandProtectionEnabled?l:d} secrets ${t.secretProtection.enabled?l:d}`),s("Level",c?`${e.effectiveLevel} (customised)`:e.effectiveLevel),s("Rules",t.rules.length===0?"none active":`${t.rules.length} active`),s("Policy",i.startsWith(L3())?`~${i.slice(L3().length)}`:i),...e.worktreeMode?[s("Worktree","relaxations active")]:[],"",...u.length===0?[" Everything configured is active."]:[" Not active",...u.flatMap((p)=>dt(p," ",a-6).map((f,o)=>o===0?` ${v} ${f}`:f)),""," Full report: cc-safety-net doctor"]].join(`
241
- `))}import{spawn as B3}from"node:child_process";import{randomBytes as x8}from"node:crypto";import{createServer as $8}from"node:http";import{Writable as g8}from"node:stream";import{homedir as L8}from"node:os";var Dt=500;function p8(n){let t=n.filter((a)=>a.decision!=="allow"),e=n.filter((a)=>a.decision==="allow"),r=Math.min(t.length,Math.max(Dt-e.length,Math.ceil(Dt/2)));return[...t.slice(0,r),...e.slice(0,Dt-r)]}function u3(n,t=s2()){if(t)$2(t);let e=(o)=>new Date(o.getFullYear(),o.getMonth(),o.getDate()).getTime(),r=e(new Date),a=new Date(r);a.setDate(a.getDate()-(n-1));let l=a.getTime(),d=[],s={count:0};for(let o of t?u2(t,s):[])for(let h of dn(o,s)){if(!h||typeof h.ts!=="string"||typeof h.command!=="string")continue;let x=new Date(h.ts).getTime();if(!Number.isFinite(x))continue;if(x>=l)d.push(h)}d.sort((o,h)=>new Date(h.ts).getTime()-new Date(o.ts).getTime());let c=Array.from({length:n},()=>0),i=Array.from({length:n},()=>0),L={},u={},v={},p=0,f=0;for(let o of d){let h=o.agent||"unknown";L[h]=(L[h]??0)+1;let x=Math.round((r-e(new Date(o.ts)))/86400000),w=n-1-x,y=x>=0&&x<n;if(y)i[w]=(i[w]??0)+1;if(o.decision!=="allow"){if(p++,o.ruleId)u[o.ruleId]=(u[o.ruleId]??0)+1;let J=Q2(o.segment||o.command);if(J)v[J]=(v[J]??0)+1;if(o.failureStage)f++;if(y)c[w]=(c[w]??0)+1}}return{days:n,logsDir:t,homeDir:L8(),totalInWindow:d.length,truncated:d.length>Dt,unreadable:s.count,counts:{blocked:p,allowed:d.length-p,agents:L,blockedByDay:c,analyzedByDay:i,rules:u,commands:v,errors:f},entries:p8(d).sort((o,h)=>new Date(h.ts).getTime()-new Date(o.ts).getTime())}}import{spawn as u8}from"node:child_process";import{existsSync as o3,statSync as o8}from"node:fs";import{delimiter as v8,join as b8}from"node:path";var f8=120000,mt="Choose the project folder",h8=`try
242
- return POSIX path of (choose folder with prompt "${mt}")
243
+ All configs valid.`),0}function Ft(n,t){let r=`legacy ${n} config`;if(t==="cleanup")return`Warning: Legacy ${n} config is no longer needed. Run \`npx -y cc-safety-net rule migrate --cleanup\` to clean it up safely.`;if(t==="migrate")return`Warning: Legacy ${n} config is ignored by CC Safety Net. Run \`npx -y cc-safety-net rule migrate\`.`;return`Warning: Legacy ${n} config is no longer supported. Fix or delete the ${r}, then run \`npx -y cc-safety-net rule migrate\`.`}function e8(n){if(A2(n)===null)return null;let t=a8(n);if(t.ruleNames.size===0&&t.errors.length===0)return null;return{path:n.path,result:t}}function a8(n){let t=[],r=new Set,e=(A2(n)??[]).filter((a)=>!t8.has(a.name)).sort((a,l)=>a.name.localeCompare(l.name));if(e.length===0)return{errors:t,ruleNames:r};for(let a of e){if(!bn.test(a.name)){t.push(`rulebook directory names must match ${bn}: ${a.name}`);continue}if(a.kind!=="directory"){t.push(`${a.name} must be a rulebook directory`);continue}let l=g(n.scope,I5(n.path,a.name,"rulebook.json")),s=D(l);if(s===null){t.push(`${a.name}/rulebook.json is required`);continue}try{let d;try{d=JSON.parse(s)}catch{t.push(`${a.name}/rulebook.json: invalid JSON`);continue}let c=ol(d);if(c.name!==a.name){t.push(`rulebook name "${c.name}" must match folder "${a.name}"`);continue}r.add(a.name)}catch(d){t.push(d instanceof Error?`${a.name}/rulebook.json: ${d.message}`:`${a.name}/rulebook.json: ${String(d)}`)}}return{errors:t,ruleNames:r}}function l8(){console.log(fl),console.log(N5)}function s8(n,t,r,e,a){if(console.log(`
244
+ ✓ ${n} config: ${t}`),console.log(` Schema: ${e==="rules"?"rulebook sources":"legacy inline rules"}`),r.ruleNames.size>0){console.log(` ${e==="rules"?"Sources":"Rules"}:`);let l=1;for(let s of r.ruleNames)console.log(` ${l}. ${a.get(s)??s}`),l++}else console.log(` ${e==="rules"?"Sources":"Rules"}: (none)`)}function d8(n,t,r,e){if(console.error(`
245
+ ✗ Legacy ${n.toLowerCase()} config: ${t}`),console.error(" Schema: legacy inline rules"),console.error(" Status: ignored by CC Safety Net"),r.errors.length>0){console.error(" Errors:");let a=1;for(let l of r.errors)for(let s of l.split("; "))console.error(` ${a}. ${s}`),a++;return}if(r.ruleNames.size>0){console.error(" Rules:");let a=1;for(let l of r.ruleNames)console.error(` ${a}. ${e.get(l)??l}`),a++;return}console.error(" Rules: (none)")}function c8(n,t,r){hl(`${n} config`,t,r)}function L8(n,t){console.log(`
246
+ ✓ GitHub source rules: ${n}`),console.log(" Rulebooks:");let r=1;for(let e of t.ruleNames)console.log(` ${r}. ${e}`),r++}function i8(n,t){hl("GitHub source rules",n,t)}function hl(n,t,r){console.error(`
247
+ ✗ ${n}: ${t}`),console.error(" Errors:");let e=1;for(let a of r)for(let l of a.split("; "))console.error(` ${e}. ${l}`),e++}function p8(n){try{let t=D(n);if(t===null)return!1;let r=JSON.parse(t);if(r.$schema)return!1;return D2(n,JSON.stringify({$schema:n8,...r},null,2)),!0}catch(t){if(t instanceof Y)throw t;return!1}}var wl=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),u8=new Set(["add","remove","list"]);async function $l(n){try{return await b8(n)}catch(t){if(t instanceof Y)return console.error(t.message),1;throw t}}async function b8(n){let t=f8(n),r=t.help?o8(t.positionals):null;if(r)return yt(r),0;if(t.errors.length>0){for(let s of t.errors)console.error(s);return 1}let e=t.positionals[0];if(!e)return yt(E2,console.error),1;let a=t.positionals[1],l={global:t.global,check:t.check};if(e==="init"){let s=_(l),d=s.configDir;w8(s.configTarget),xl(g(s.filesystemScope,Mn({...l,cacheConfigDir:d})));let c=v8(d,"example-rules","rulebook.json"),L=g(s.filesystemScope,c);if(t.example&&D(L)===null)e1(L,"example-rules");let i=await M2(l);return Kn(i,"Rule config initialized."),i.ok?0:1}if(e==="add"){if(!a)return console.error("rule add requires a source"),1;let s=await Pt(a,l);return Kn(s,`Added rulebook source: ${a}`),s.ok?0:1}if(e==="remove"){if(!a)return console.error("rule remove requires a source"),1;let s=await Nt(a,{...l,deleteSource:t.deleteSource});return Kn(s,`Removed rulebook source: ${a}`),s.ok?0:1}if(e==="update"||e==="sync"){let s=await M2({...l,only:e==="update"?a:void 0});return Kn(s,t.check?"Rule config checked.":"Rule config synced."),s.ok?0:1}if(e==="list"){let s=y2(),d=n2({});return cl(s,{user:m2(s.userConfigPath,d.userScope),project:m2(s.projectConfigPath,d.projectScope)}),s.errors.length>0?1:0}if(e==="wrapper")return x8(t);if(e==="migrate")return vl({cleanup:t.cleanup,cwd:process.cwd()});if(e==="doc"){console.log(sl);let s=await bl();if(s)console.error(s);return 0}if(e==="verify")return yl();return 1}function o8(n){if(n.length===0)return E2;let t=E2.subcommands.filter((e)=>e.usage.split(" ")[0]===n[0]);if(t.length===0)return null;if(n.length===1&&t.length>1)return{name:`rule ${n[0]}`,description:`Subcommands of rule ${n[0]}`,usage:`rule ${n[0]} <subcommand>`,subcommands:t,options:[]};let r=n.length===1?t[0]:t.find((e)=>e.usage.split(" ")[1]===n[1]);if(!r)return null;return{name:`rule ${n[0]}`,description:r.description,usage:`rule ${r.usage}`,options:[]}}function f8(n){let t=J({label:"rule",booleans:{global:["-g","--global"],check:["--check"],cleanup:["--cleanup"],deleteSource:["--delete-source"],example:["--example"]},positionals:"list"},n),r={...t.flags,help:t.help,positionals:t.positionals,errors:t.errors};return y8(r),r}function y8(n){let[t]=n.positionals;if(t&&!wl.has(t))n.errors.push(`Unknown rule subcommand: ${t}`);if(n.deleteSource&&t!=="remove")if(t&&wl.has(t))n.errors.push(`Unknown option for rule ${t}: --delete-source`);else n.errors.push("--delete-source is only valid with 'rule remove'");if(n.cleanup&&t!=="migrate")n.errors.push(Bt(t,"--cleanup"));if(n.example&&t!=="init")n.errors.push(Bt(t,"--example"));if(t==="migrate"){if(n.global)n.errors.push(Bt(t,"--global"));if(n.check)n.errors.push(Bt(t,"--check"));if(n.positionals.length>1)n.errors.push(`Unexpected rule migrate argument: ${n.positionals[1]}`)}else if(t==="wrapper")h8(n);else if(n.positionals.length>2)n.errors.push(`Unexpected rule argument: ${n.positionals[2]}`);if(t==="list"&&n.global)n.errors.push("Unknown option for rule list: --global")}function Bt(n,t){return n?`Unknown option for rule ${n}: ${t}`:`Unknown option for rule: ${t}`}function h8(n){let t=n.positionals[1],r=n.positionals[2];if(!t){n.errors.push("rule wrapper requires add, remove, or list");return}if(!u8.has(t)){n.errors.push(`Unknown rule wrapper action: ${t}`);return}if(t==="list"){if(r)n.errors.push(`Unexpected rule wrapper argument: ${r}`);return}if(!r){n.errors.push(`rule wrapper ${t} requires a command`);return}if(n.positionals.length>3)n.errors.push(`Unexpected rule wrapper argument: ${n.positionals[3]}`)}function w8(n){if(D(n)===null){r1(n);return}let t=E(n);if(!t.config)return;P(n,{version:1,rules:t.config.rules,overrides:t.config.overrides??{},transparent_wrappers:t.config.transparent_wrappers??[]})}async function x8(n){let t=n.positionals[1],r=n.positionals[2],e=_({global:n.global}).configTarget;if(t==="list"){let d=E(e);if(d.errors.length>0){for(let c of d.errors)console.error(c);return 1}return $8(d.config?.transparent_wrappers??[]),0}if(!r||!l1.test(r))return console.error("transparent wrapper must match command pattern"),1;if(d1(r))return console.error(`reserved command "${r}" cannot be a wrapper`),1;let a=E(e);if(a.errors.length>0){for(let d of a.errors)console.error(d);return 1}let l=a.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},s=t==="add"?[...new Set([...l.transparent_wrappers??[],r])]:(l.transparent_wrappers??[]).filter((d)=>d!==r);return P(e,{version:1,rules:l.rules,overrides:l.overrides??{},transparent_wrappers:s}),console.log(t==="add"?`Added transparent wrapper: ${r}`:`Removed transparent wrapper: ${r}`),0}function $8(n){if(n.length===0){console.log("Transparent wrappers: (none)");return}console.log(`Transparent wrappers (${n.length}):`);for(let t of n)console.log(` - ${t}`)}import{homedir as Dl}from"node:os";import{existsSync as D8,readFileSync as m8}from"node:fs";import{homedir as g8}from"node:os";import{join as k8}from"node:path";async function q8(n){if(n.isTTY)return null;return(await b1(n).catch(()=>null))?.trim()||null}function j8(){if(process.env.CLAUDE_SETTINGS_PATH)return process.env.CLAUDE_SETTINGS_PATH;return k8(g8(),".claude","settings.json")}function mr(){let n=j8();if(!D8(n))return!1;try{let t=m8(n,"utf-8"),r=JSON.parse(t);if(!r.enabledPlugins)return!1;let e="cc-safety-net@cc-marketplace";if(!(e in r.enabledPlugins))return!1;return r.enabledPlugins[e]===!0}catch(t){if(hn(k.debug))console.error(`CC Safety Net debug: failed to read Claude settings: ${n}: ${t instanceof Error?t.message:String(t)}`);return!1}}async function gr(n=process.stdin){let t=mr(),r;if(!t)r="\uD83D\uDEE1️ CC Safety Net ❌";else{let a=A({cwd:process.cwd()}),l=a.policy,s=L2(l),d=Object.values(q2(l,s.capabilities)).some((L)=>L.changesInherited);r=`\uD83D\uDEE1️ CC Safety Net ${{standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[d?"custom":s.effectiveLevel]}${s.worktreeMode?"\uD83C\uDF33":""}${a.state==="degraded"?"⚠️":""}`}let e=await q8(n);if(e&&!e.startsWith("{"))console.log(`${e} | ${r}`);else console.log(r)}function ml(){let n=A({cwd:process.cwd()}),t=n.policy,r=L2(t),e=!!process.env.NO_COLOR||!process.stdout.isTTY,a=Math.min(process.stdout.columns||80,100),l=e?"ok":"✔",s=e?"OFF":"✘",d=(p,f)=>{let u=` ${p.padEnd(13)}${f}`;return(u.length>a?`${u.slice(0,a-1)}…`:u).replaceAll(s,o.red(s))},c=Object.values(q2(t,r.capabilities)).some((p)=>p.changesInherited),L=wn(),i={ready:o.green,degraded:o.yellow}[n.state],v=[...mr()?[]:["plugin cc-safety-net@cc-marketplace is disabled in Claude Code; nothing is enforced in Claude Code until it is re-enabled. Other integrations are not affected."],...n.diagnostics],b=e?"-":"·";console.log([`${e?"":"\uD83D\uDEE1️ "}CC Safety Net — ${i(n.state)}`,"",d("Protection",`destructive ${t.destructiveCommandProtectionEnabled?l:s} secrets ${t.secretProtection.enabled?l:s}`),d("Level",c?`${r.effectiveLevel} (customised)`:r.effectiveLevel),d("Rules",t.rules.length===0?"none active":`${t.rules.length} active`),d("Policy",L.startsWith(Dl())?`~${L.slice(Dl().length)}`:L),...r.worktreeMode?[d("Worktree","relaxations active")]:[],"",...v.length===0?[" Everything configured is active."]:[" Not active",...v.flatMap((p)=>ft(p," ",a-6).map((f,u)=>u===0?` ${b} ${f}`:f)),""," Full report: cc-safety-net doctor"]].join(`
248
+ `))}import{spawn as Al}from"node:child_process";import{randomBytes as W8}from"node:crypto";import{createServer as K8}from"node:http";import{Writable as R8}from"node:stream";import{homedir as z8}from"node:os";var Jt=500;function F8(n){let t=n.filter((a)=>a.decision!=="allow"),r=n.filter((a)=>a.decision==="allow"),e=Math.min(t.length,Math.max(Jt-r.length,Math.ceil(Jt/2)));return[...t.slice(0,e),...r.slice(0,Jt-e)]}function gl(n,t=i2()){if(t)g2(t);let r=(u)=>new Date(u.getFullYear(),u.getMonth(),u.getDate()).getTime(),e=r(new Date),a=new Date(e);a.setDate(a.getDate()-(n-1));let l=a.getTime(),s=[],d={count:0};for(let u of t?f2(t,d):[])for(let h of pn(u,d)){if(!h||typeof h.ts!=="string"||typeof h.command!=="string")continue;let w=new Date(h.ts).getTime();if(!Number.isFinite(w))continue;if(w>=l)s.push(h)}s.sort((u,h)=>new Date(h.ts).getTime()-new Date(u.ts).getTime());let c=Array.from({length:n},()=>0),L=Array.from({length:n},()=>0),i={},v={},b={},p=0,f=0;for(let u of s){let h=u.agent||"unknown";i[h]=(i[h]??0)+1;let w=Math.round((e-r(new Date(u.ts)))/86400000),$=n-1-w,y=w>=0&&w<n;if(y)L[$]=(L[$]??0)+1;if(u.decision!=="allow"){if(p++,u.ruleId)v[u.ruleId]=(v[u.ruleId]??0)+1;let m=H2(u.segment||u.command);if(m)b[m]=(b[m]??0)+1;if(u.failureStage)f++;if(y)c[$]=(c[$]??0)+1}}return{days:n,logsDir:t,homeDir:z8(),totalInWindow:s.length,truncated:s.length>Jt,unreadable:d.count,counts:{blocked:p,allowed:s.length-p,agents:i,blockedByDay:c,analyzedByDay:L,rules:v,commands:b,errors:f},entries:F8(s).sort((u,h)=>new Date(h.ts).getTime()-new Date(u.ts).getTime())}}import{spawn as B8}from"node:child_process";import{existsSync as kl,statSync as J8}from"node:fs";import{delimiter as Z8,join as Q8}from"node:path";var X8=120000,Zt="Choose the project folder",Y8=`try
249
+ return POSIX path of (choose folder with prompt "${Zt}")
243
250
  on error number -128
244
251
  return ""
245
- end try`,y8=`Add-Type -AssemblyName System.Windows.Forms
252
+ end try`,S8=`Add-Type -AssemblyName System.Windows.Forms
246
253
  $dialog = New-Object System.Windows.Forms.FolderBrowserDialog
247
- $dialog.Description = '${mt}'
248
- if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,v3=[{binary:"zenity",args:["--file-selection","--directory",`--title=${mt}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",mt]}],b3=(n,t)=>(t.PATH??"").split(v8).some((e)=>e.length>0&&o3(b8(e,n)));function f3(n,t){if(n==="darwin"||n==="win32")return!0;if(n!=="linux")return!1;if(!t.DISPLAY&&!t.WAYLAND_DISPLAY)return!1;return v3.some((e)=>b3(e.binary,t))}function w8(n,t){if(n==="darwin")return{cmd:"osascript",args:["-e",h8]};if(n==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",y8]};let e=v3.find((r)=>b3(r.binary,t));return e?{cmd:e.binary,args:e.args}:null}function h3(n=process.platform,t=process.env){let e=w8(n,t);if(!e)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((r)=>{let a=u8(e.cmd,e.args,{env:t,stdio:["ignore","pipe","pipe"]}),l="",d=!1,s=(i)=>{if(d)return;d=!0,clearTimeout(c),r(i)},c=setTimeout(()=>{a.kill(),s({error:"The folder dialog timed out"})},f8);a.stdout.on("data",(i)=>{l+=i.toString()}),a.on("error",()=>s({error:`Could not open the folder dialog (${e.cmd})`})),a.on("close",()=>{let i=l.trim().replace(/\/+$/,"");if(!i)return s({cancelled:!0});if(!o3(i)||!o8(i).isDirectory())return s({error:"That selection is not a folder on disk"});s({path:i})})})}var y3=`<!doctype html>
254
+ $dialog.Description = '${Zt}'
255
+ if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,ql=[{binary:"zenity",args:["--file-selection","--directory",`--title=${Zt}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",Zt]}],jl=(n,t)=>(t.PATH??"").split(Z8).some((r)=>r.length>0&&kl(Q8(r,n)));function zl(n,t){if(n==="darwin"||n==="win32")return!0;if(n!=="linux")return!1;if(!t.DISPLAY&&!t.WAYLAND_DISPLAY)return!1;return ql.some((r)=>jl(r.binary,t))}function H8(n,t){if(n==="darwin")return{cmd:"osascript",args:["-e",Y8]};if(n==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",S8]};let r=ql.find((e)=>jl(e.binary,t));return r?{cmd:r.binary,args:r.args}:null}function Fl(n=process.platform,t=process.env){let r=H8(n,t);if(!r)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((e)=>{let a=B8(r.cmd,r.args,{env:t,stdio:["ignore","pipe","pipe"]}),l="",s=!1,d=(L)=>{if(s)return;s=!0,clearTimeout(c),e(L)},c=setTimeout(()=>{a.kill(),d({error:"The folder dialog timed out"})},X8);a.stdout.on("data",(L)=>{l+=L.toString()}),a.on("error",()=>d({error:`Could not open the folder dialog (${r.cmd})`})),a.on("close",()=>{let L=l.trim().replace(/\/+$/,"");if(!L)return d({cancelled:!0});if(!kl(L)||!J8(L).isDirectory())return d({error:"That selection is not a folder on disk"});d({path:L})})})}var Bl=`<!doctype html>
249
256
  <html lang="en">
250
257
  <head>
251
258
  <meta charset="utf-8">
@@ -3077,8 +3084,7 @@ var catalog = [
3077
3084
  install: {
3078
3085
  order: 2,
3079
3086
  flag: "--agy-cli",
3080
- installLabel: "Antigravity CLI",
3081
- helpTarget: "Antigravity CLI hook config",
3087
+ artifactKind: "hook config",
3082
3088
  probeCommand: ["agy", "--version"]
3083
3089
  }
3084
3090
  },
@@ -3097,8 +3103,7 @@ var catalog = [
3097
3103
  install: {
3098
3104
  order: 3,
3099
3105
  flag: "--claude-code",
3100
- installLabel: "Claude Code",
3101
- helpTarget: "Claude Code plugin",
3106
+ artifactKind: "plugin",
3102
3107
  probeCommand: ["claude", "--version"]
3103
3108
  }
3104
3109
  },
@@ -3109,8 +3114,7 @@ var catalog = [
3109
3114
  install: {
3110
3115
  order: 4,
3111
3116
  flag: "--codex",
3112
- installLabel: "Codex",
3113
- helpTarget: "Codex plugin",
3117
+ artifactKind: "plugin",
3114
3118
  probeCommand: ["codex", "--version"]
3115
3119
  }
3116
3120
  },
@@ -3127,8 +3131,7 @@ var catalog = [
3127
3131
  install: {
3128
3132
  order: 7,
3129
3133
  flag: "--copilot-cli",
3130
- installLabel: "GitHub Copilot CLI",
3131
- helpTarget: "GitHub Copilot CLI plugin",
3134
+ artifactKind: "plugin",
3132
3135
  probeCommand: ["copilot", "--binary-version"]
3133
3136
  }
3134
3137
  },
@@ -3145,8 +3148,7 @@ var catalog = [
3145
3148
  install: {
3146
3149
  order: 6,
3147
3150
  flag: "--gemini-cli",
3148
- installLabel: "Gemini CLI",
3149
- helpTarget: "Gemini CLI extension",
3151
+ artifactKind: "extension",
3150
3152
  probeCommand: ["gemini", "--version"]
3151
3153
  }
3152
3154
  },
@@ -3163,8 +3165,7 @@ var catalog = [
3163
3165
  install: {
3164
3166
  order: 8,
3165
3167
  flag: "--hermes-agent",
3166
- installLabel: "Hermes Agent",
3167
- helpTarget: "Hermes Agent plugin",
3168
+ artifactKind: "plugin",
3168
3169
  probeCommand: ["hermes", "--version"]
3169
3170
  }
3170
3171
  },
@@ -3181,8 +3182,7 @@ var catalog = [
3181
3182
  install: {
3182
3183
  order: 9,
3183
3184
  flag: "--kimi-code",
3184
- installLabel: "Kimi Code",
3185
- helpTarget: "Kimi Code hook config",
3185
+ artifactKind: "hook config",
3186
3186
  probeCommand: ["kimi", "--version"]
3187
3187
  }
3188
3188
  },
@@ -3193,8 +3193,7 @@ var catalog = [
3193
3193
  install: {
3194
3194
  order: 10,
3195
3195
  flag: "--openclaw",
3196
- installLabel: "OpenClaw",
3197
- helpTarget: "OpenClaw plugin",
3196
+ artifactKind: "plugin",
3198
3197
  probeCommand: ["openclaw", "--version"]
3199
3198
  }
3200
3199
  },
@@ -3205,8 +3204,7 @@ var catalog = [
3205
3204
  install: {
3206
3205
  order: 11,
3207
3206
  flag: "--opencode",
3208
- installLabel: "OpenCode",
3209
- helpTarget: "OpenCode plugin",
3207
+ artifactKind: "plugin",
3210
3208
  probeCommand: ["opencode", "--version"]
3211
3209
  }
3212
3210
  },
@@ -3217,8 +3215,7 @@ var catalog = [
3217
3215
  install: {
3218
3216
  order: 12,
3219
3217
  flag: "--pi",
3220
- installLabel: "Pi",
3221
- helpTarget: "Pi package",
3218
+ artifactKind: "package",
3222
3219
  probeCommand: ["pi", "--version"]
3223
3220
  }
3224
3221
  },
@@ -3235,8 +3232,7 @@ var catalog = [
3235
3232
  install: {
3236
3233
  order: 5,
3237
3234
  flag: "--cursor",
3238
- installLabel: "Cursor",
3239
- helpTarget: "Cursor hook config",
3235
+ artifactKind: "hook config",
3240
3236
  probeCommand: ["cursor", "--version"]
3241
3237
  }
3242
3238
  },
@@ -3247,8 +3243,7 @@ var catalog = [
3247
3243
  install: {
3248
3244
  order: 1,
3249
3245
  flag: "--amp",
3250
- installLabel: "Amp Code",
3251
- helpTarget: "Amp Code plugin",
3246
+ artifactKind: "plugin",
3252
3247
  probeCommand: ["amp", "--version"]
3253
3248
  }
3254
3249
  }
@@ -5366,5 +5361,5 @@ load().then((loaded) => {
5366
5361
  </script>
5367
5362
  </body>
5368
5363
  </html>
5369
- `;var w3='<script id="ccsn-data" type="application/json">';function x3(n){return y3.replace(w3,()=>w3+JSON.stringify({token:n}).replaceAll("<","\\u003c"))}var qt="kenryu42/cc-safety-net",D8=`https://github.com/${qt}`,yr=1e4,m8=7;async function J3(n,t={}){let e=F({label:"gui",booleans:{noOpen:["--no-open"]}},n),r=t.log??console.log,a=t.error??console.error;if(e.errors.length>0){for(let d of e.errors)a(d);return a("Usage: cc-safety-net gui [--no-open]"),1}let l=await k8(t);if(r(`CC Safety Net policy GUI: ${l.url}`),!e.flags.noOpen)try{await(t.openBrowser??Q8)(l.url)}catch(d){a(`Failed to open browser: ${d instanceof Error?d.message:String(d)}`),a(`Open this URL manually: ${l.url}`)}if(t.keepAlive===!1)return await l.close(),0;return await Z8(l),0}async function k8(n={}){let t=n.token??x8(24).toString("base64url"),e=$8((l,d)=>{q8(l,d,t,n)});await new Promise((l,d)=>{e.once("error",d),e.listen(0,"127.0.0.1",()=>{e.off("error",d),l()})});let a=`http://127.0.0.1:${e.address().port}`;return{origin:a,token:t,url:`${a}/?token=${encodeURIComponent(t)}`,close:()=>J8(e)}}async function q8(n,t,e,r){let a=new URL(n.url??"/","http://127.0.0.1");if(n.method==="GET"&&a.pathname==="/favicon.ico"){t.writeHead(204,{"cache-control":"no-store"}),t.end();return}if(!z8(n,a,e)){k(t,403,{error:"Forbidden"});return}if(n.method==="GET"&&a.pathname==="/"){B8(t,x3(e));return}if(n.method==="GET"&&a.pathname==="/api/policy"){let l=m3(r);k(t,200,{...l,configState:fn(W(r)),destructiveCommandRules:un,secretPatterns:g3,version:j(),preview:l.errors.length>0?null:q3(l.policy)});return}if(n.method==="POST"&&a.pathname==="/api/policy/preview"){let l=await kt(n);if(!l.ok){k(t,400,{errors:[l.error]});return}let d=k3(l.value);k(t,d.errors.length>0?400:200,d);return}if(n.method==="POST"&&a.pathname==="/api/policy/explain"){let l=await kt(n);if(!l.ok){k(t,400,{errors:[l.error]});return}let d=l.value;if(d===null||typeof d.command!=="string"){k(t,400,{errors:["command must be a string"]});return}let s=ee(d.policy);if(s.length>0){k(t,400,{errors:s});return}k(t,200,j8(d.command,d.policy,r));return}if(n.method==="POST"&&a.pathname==="/api/policy"){let l=await kt(n);if(!l.ok){k(t,400,{errors:[l.error]});return}let d=fr(l.value,r);k(t,d.errors.length>0?400:200,d);return}if(n.method==="POST"&&a.pathname==="/api/reset"){k(t,200,fr(D3,r));return}if(n.method==="POST"&&a.pathname==="/api/repair"){k(t,200,j3(r));return}if(n.method==="GET"&&a.pathname==="/api/activity"){let l=G2(r),d=F8(a.searchParams.get("days"),l);if(d===null){k(t,400,{error:`days must be an integer between 1 and ${l}`});return}k(t,200,u3(d,r.activityLogsDir));return}if(n.method==="POST"&&a.pathname==="/api/rules/choose-directory"){k(t,200,await h3());return}if(n.method==="GET"&&a.pathname==="/api/rules"){let l=o2(r),d=new Map(l.rules.map((s)=>[s.name,s]));k(t,200,{projectPath:r.cwd??process.cwd(),canPickDirectory:f3(process.platform,process.env),rulebooks:l.rulebooks.map((s)=>({source:s.source,spec:s.spec,name:s.name,version:s.version,rules:s.rules.flatMap((c)=>{let i=d.get(c);if(!i)return[];return[{name:i.name,command:i.command,subcommand:i.subcommand,block_args:i.block_args,reason:i.reason}]})})),errors:l.errors,warnings:l.warnings});return}if(n.method==="GET"&&a.pathname==="/api/star/context"){k(t,200,await(r.fetchStarContext??(()=>W8({logsDir:r.activityLogsDir})))());return}if(n.method==="POST"&&a.pathname==="/api/star"){let l=await(r.starRepo??X8)();k(t,200,l.ok?{ok:!0}:{ok:!1,fallbackUrl:D8});return}if(n.method==="GET"&&a.pathname==="/api/integrations"){k(t,200,await(r.fetchIntegrations??S8)());return}if(n.method==="GET"&&a.pathname==="/api/health"){k(t,200,await(r.fetchHealth??H8)());return}if(n.method==="POST"&&(a.pathname==="/api/install"||a.pathname==="/api/uninstall")){let l=await kt(n);if(!l.ok){k(t,400,{errors:[l.error]});return}let d=l.value?.target;if(typeof d!=="string"||!C.some((c)=>c.target===d)){k(t,400,{error:"unknown target"});return}let s=a.pathname==="/api/install"?"install":"uninstall";k(t,200,await(r.runIntegration??A8)(s,d));return}k(t,404,{error:"Not found"})}function j8(n,t,e){let r=it(t),a=W(e),l=on({rules:a.policy.rules,transparentWrappers:a.policy.transparentWrappers,safety:z3(r.safety),worktreeMode:r.workflow.worktree_mode,destructiveCommandProtectionEnabled:r.destructive_command_protection.enabled,destructiveCommandRuleOverrides:r.destructive_command_protection.overrides,destructiveCommandAllowPaths:r.destructive_command_protection.allow_paths,secretProtection:{enabled:r.secret_protection.enabled,disabledRules:[...F3(r.secret_protection.overrides)],denyPaths:r.secret_protection.deny_paths,allowPaths:r.secret_protection.allow_paths}});return V2(n,{policySnapshot:l,cwd:e.cwd,userConfigDir:e.userConfigDir})}function F8(n,t){if(n===null)return Math.min(m8,t);let e=Number(n);if(!Number.isInteger(e)||e<1||e>t)return null;return e}function z8(n,t,e){if(t.searchParams.get("token")!==e)return!1;if(n.method!=="POST")return!0;return n.headers["x-cc-safety-net-token"]===e}async function kt(n){let t=[];for await(let e of n)t.push(e);try{return{ok:!0,value:JSON.parse(Buffer.concat(t).toString("utf-8")||"{}")}}catch(e){return{ok:!1,error:`Invalid JSON: ${e instanceof Error?e.message:String(e)}`}}}function B8(n,t){n.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),n.end(t)}function k(n,t,e){n.writeHead(t,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),n.end(JSON.stringify(e))}function J8(n){return new Promise((t,e)=>{n.close((r)=>r?e(r):t())})}function Z8(n){return new Promise((t)=>{let e=()=>{process.off("SIGINT",r),process.off("SIGTERM",r)},r=()=>{e(),n.close().then(t)};process.once("SIGINT",r),process.once("SIGTERM",r)})}function Q8(n){let t=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",e=process.platform==="win32"?["/c","start","",n]:[n];return new Promise((r,a)=>{let l=B3(t,e,{detached:!0,stdio:"ignore"}),d=(c)=>{l.off("spawn",s),a(c)},s=()=>{l.off("error",d),l.unref(),r()};l.once("error",d),l.once("spawn",s)})}async function X8(n="gh",t=yr){return{ok:await hr(n,["api","-X","PUT",`/user/starred/${qt}`],t)===0}}var Y8={amp:"ampVersion","antigravity-cli":"antigravityCliVersion","claude-code":"claudeCodeVersion",codex:"codexCliVersion","copilot-cli":"copilotCliVersion",cursor:"cursorVersion","gemini-cli":"geminiCliVersion","hermes-agent":"hermesAgentVersion","kimi-code":"kimiCodeVersion",openclaw:"openClawVersion",opencode:"openCodeVersion",pi:"piCliVersion"};async function S8(n={}){let t=await xn(n.fetcher),e=Z3(t,n.homeDir);return{targets:i2.map((r)=>{let a=e.find((l)=>l.platform===r.id);return{target:r.id,label:v2(r.id),version:t[Y8[r.id]],status:a?.configured?"active":a?.detected?"disabled":a?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:t.version,nodeVersion:t.nodeVersion,platform:t.platform}}}function Z3(n,t){return tn(process.cwd(),{homeDir:t,ampPluginListOutput:n.ampPluginListOutput,codexPluginListOutput:n.codexPluginListOutput,copilotCliVersion:n.copilotCliVersion})}async function H8(n={}){let[t,e]=await Promise.all([xn(n.fetcher),(n.checkUpdates??E2)()]);return{hooks:Z3(t,n.homeDir).filter((r)=>r.detected).map((r)=>({platform:r.platform,label:v2(r.platform),configured:r.configured})),update:{currentVersion:e.currentVersion,latestVersion:e.latestVersion??null,updateAvailable:e.updateAvailable}}}var $3=Promise.resolve();function A8(n,t,e={}){let r=async()=>{let l=[],d=console.log,s=console.error;console.log=(...c)=>l.push(c.map(String).join(" ")),console.error=console.log;try{return{ok:await Xn(n,[],{selectTargets:async()=>[t],output:new g8({write(i,L,u){u()}}),...e})===0,output:l.join(`
5370
- `)}}finally{console.log=d,console.error=s}},a=$3.then(r);return $3=a.then(()=>{return},()=>{return}),a}async function W8(n={}){let[t,e,r]=await Promise.all([R8(n.command),K8(n.fetchRepo),Promise.resolve(Cn(G2(),n.logsDir).totalBlocked)]);return{starred:t,starCount:e,blockedTotal:r}}async function R8(n="gh",t=yr){if(await hr(n,["auth","status"],t)!==0)return null;let e=await hr(n,["api",`/user/starred/${qt}`],t);if(e===0)return!0;if(e===null)return null;return!1}function hr(n,t,e){return new Promise((r)=>{let a=B3(n,t,{stdio:"ignore",windowsHide:!0}),l=!1,d,s=(c)=>{if(l)return;if(l=!0,d)clearTimeout(d);r(c)};a.once("error",()=>s(null)),a.once("close",s),d=setTimeout(()=>{a.kill(),s(null)},e)})}async function K8(n=fetch){try{let t=await n(`https://api.github.com/repos/${qt}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(yr)});if(!t.ok)return null;let e=await t.json();return typeof e.stargazers_count==="number"?e.stargazers_count:null}catch{return null}}function M8(n){if(n[0]!=="help")return!1;let t=n[1];if(!t)Te(),process.exit(0);if(Jn(t))process.exit(0);console.error(`Unknown command: ${t}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var V8={hook:async(n)=>{let t=R1(n);if(t){await t.run();return}console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),Jn("hook",console.error),process.exit(1)},install:async(n)=>{process.exit(await Xn("install",n))},update:async(n)=>{process.exit(await pr(n))},uninstall:async(n)=>{process.exit(await Xn("uninstall",n))},rule:async(n)=>{process.exit(await i3(n))},status:async(n)=>{if(r2(F({label:"status"},n).errors))process.exit(1);p3()},statusline:async(n)=>{let t=F({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},n);if(t.errors.length===0&&t.flags.claudeCode){await br();return}if(r2(t.errors),!t.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");Jn("statusline",console.error),process.exit(1)},doctor:async(n)=>{let t=Ve(n);if(!t)process.exit(1);let e=await J0({json:t.json,skipUpdateCheck:t.skipUpdateCheck});process.exit(e)},logs:async(n)=>{process.exit(await i1(n))},gui:async(n)=>{process.exit(await J3(n))},explain:async(n)=>{let t=Ge(n);if(!t)process.exit(1);let e=V2(t.command,{cwd:t.cwd}),r=!!process.env.NO_COLOR||!process.stdout.isTTY;if(t.json)console.log(Oe(e));else console.log(Ue(e,{asciiOnly:r}));process.exit(0)}};async function G8(){let n=process.argv.slice(2),t=F({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},n);if(M8(n))return;let e=n[0],r=e?Gn(e):void 0;if(t.help&&r&&r.name!=="rule")Jn(r.name),process.exit(0);if(!e||t.help&&!r)Te(),process.exit(0);if(t.flags.version)W0(),process.exit(0);if(r){await V8[r.name](n.slice(1));return}let a=K1(e);if(a){await a.run();return}if(e==="--statusline"){await br();return}console.error(e.startsWith("-")?`Unknown option: ${e}`:`Unknown command: ${e}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}G8().catch((n)=>{console.error("CC Safety Net error:",n),process.exit(1)});
5364
+ `;var Jl='<script id="ccsn-data" type="application/json">';function Zl(n){return Bl.replace(Jl,()=>Jl+JSON.stringify({token:n}).replaceAll("<","\\u003c"))}var Xt="kenryu42/cc-safety-net",V8=`https://github.com/${Xt}`,jr=1e4,A8=7;async function Ml(n,t={}){let r=J({label:"gui",booleans:{noOpen:["--no-open"]}},n),e=t.log??console.log,a=t.error??console.error;if(r.errors.length>0){for(let s of r.errors)a(s);return a("Usage: cc-safety-net gui [--no-open]"),1}let l=await M8(t);if(e(`CC Safety Net policy GUI: ${l.url}`),!r.flags.noOpen)try{await(t.openBrowser??P8)(l.url)}catch(s){a(`Failed to open browser: ${s instanceof Error?s.message:String(s)}`),a(`Open this URL manually: ${l.url}`)}if(t.keepAlive===!1)return await l.close(),0;return await E8(l),0}async function M8(n={}){let t=n.token??W8(24).toString("base64url"),r=K8((l,s)=>{G8(l,s,t,n)});await new Promise((l,s)=>{r.once("error",s),r.listen(0,"127.0.0.1",()=>{r.off("error",s),l()})});let a=`http://127.0.0.1:${r.address().port}`;return{origin:a,token:t,url:`${a}/?token=${encodeURIComponent(t)}`,close:()=>_8(r)}}async function G8(n,t,r,e){let a=new URL(n.url??"/","http://127.0.0.1");if(n.method==="GET"&&a.pathname==="/favicon.ico"){t.writeHead(204,{"cache-control":"no-store"}),t.end();return}if(!O8(n,a,r)){q(t,403,{error:"Forbidden"});return}if(n.method==="GET"&&a.pathname==="/"){T8(t,Zl(r));return}if(n.method==="GET"&&a.pathname==="/api/policy"){let l=Sl(e);q(t,200,{...l,configState:xn(A(e)),destructiveCommandRules:fn,secretPatterns:Xl,version:B(),preview:l.errors.length>0?null:Wl(l.policy)});return}if(n.method==="POST"&&a.pathname==="/api/policy/preview"){let l=await Qt(n);if(!l.ok){q(t,400,{errors:[l.error]});return}let s=Hl(l.value);q(t,s.errors.length>0?400:200,s);return}if(n.method==="POST"&&a.pathname==="/api/policy/explain"){let l=await Qt(n);if(!l.ok){q(t,400,{errors:[l.error]});return}let s=l.value;if(s===null||typeof s.command!=="string"){q(t,400,{errors:["command must be a string"]});return}let d=p1(s.policy);if(d.length>0){q(t,400,{errors:d});return}q(t,200,U8(s.command,s.policy,e));return}if(n.method==="POST"&&a.pathname==="/api/policy"){let l=await Qt(n);if(!l.ok){q(t,400,{errors:[l.error]});return}let s=kr(l.value,e);q(t,s.errors.length>0?400:200,s);return}if(n.method==="POST"&&a.pathname==="/api/reset"){q(t,200,kr(Yl,e));return}if(n.method==="POST"&&a.pathname==="/api/repair"){q(t,200,Kl(e));return}if(n.method==="GET"&&a.pathname==="/api/activity"){let l=T2(e),s=C8(a.searchParams.get("days"),l);if(s===null){q(t,400,{error:`days must be an integer between 1 and ${l}`});return}q(t,200,gl(s,e.activityLogsDir));return}if(n.method==="POST"&&a.pathname==="/api/rules/choose-directory"){q(t,200,await Fl());return}if(n.method==="GET"&&a.pathname==="/api/rules"){let l=y2(e),s=new Map(l.rules.map((d)=>[d.name,d]));q(t,200,{projectPath:e.cwd??process.cwd(),canPickDirectory:zl(process.platform,process.env),rulebooks:l.rulebooks.map((d)=>({source:d.source,spec:d.spec,name:d.name,version:d.version,rules:d.rules.flatMap((c)=>{let L=s.get(c);if(!L)return[];return[{name:L.name,command:L.command,subcommand:L.subcommand,block_args:L.block_args,reason:L.reason}]})})),errors:l.errors,warnings:l.warnings});return}if(n.method==="GET"&&a.pathname==="/api/star/context"){q(t,200,await(e.fetchStarContext??(()=>r4({logsDir:e.activityLogsDir})))());return}if(n.method==="POST"&&a.pathname==="/api/star"){let l=await(e.starRepo??I8)();q(t,200,l.ok?{ok:!0}:{ok:!1,fallbackUrl:V8});return}if(n.method==="GET"&&a.pathname==="/api/integrations"){q(t,200,await(e.fetchIntegrations??N8)());return}if(n.method==="GET"&&a.pathname==="/api/health"){q(t,200,await(e.fetchHealth??n4)());return}if(n.method==="POST"&&(a.pathname==="/api/install"||a.pathname==="/api/uninstall")){let l=await Qt(n);if(!l.ok){q(t,400,{errors:[l.error]});return}let s=l.value?.target;if(typeof s!=="string"||!T.some((c)=>c.target===s)){q(t,400,{error:"unknown target"});return}let d=a.pathname==="/api/install"?"install":"uninstall";q(t,200,await(e.runIntegration??t4)(d,s));return}q(t,404,{error:"Not found"})}function U8(n,t,r){let e=wt(t),a=A(r),l=yn({rules:a.policy.rules,transparentWrappers:a.policy.transparentWrappers,safety:Vl(e.safety),worktreeMode:e.workflow.worktree_mode,destructiveCommandProtectionEnabled:e.destructive_command_protection.enabled,destructiveCommandRuleOverrides:e.destructive_command_protection.overrides,destructiveCommandAllowPaths:e.destructive_command_protection.allow_paths,secretProtection:{enabled:e.secret_protection.enabled,disabledRules:[...Rl(e.secret_protection.overrides)],denyPaths:e.secret_protection.deny_paths,allowPaths:e.secret_protection.allow_paths}});return O2(n,{policySnapshot:l,cwd:r.cwd,userConfigDir:r.userConfigDir})}function C8(n,t){if(n===null)return Math.min(A8,t);let r=Number(n);if(!Number.isInteger(r)||r<1||r>t)return null;return r}function O8(n,t,r){if(t.searchParams.get("token")!==r)return!1;if(n.method!=="POST")return!0;return n.headers["x-cc-safety-net-token"]===r}async function Qt(n){let t=[];for await(let r of n)t.push(r);try{return{ok:!0,value:JSON.parse(Buffer.concat(t).toString("utf-8")||"{}")}}catch(r){return{ok:!1,error:`Invalid JSON: ${r instanceof Error?r.message:String(r)}`}}}function T8(n,t){n.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-store"}),n.end(t)}function q(n,t,r){n.writeHead(t,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),n.end(JSON.stringify(r))}function _8(n){return new Promise((t,r)=>{n.close((e)=>e?r(e):t())})}function E8(n){return new Promise((t)=>{let r=()=>{process.off("SIGINT",e),process.off("SIGTERM",e)},e=()=>{r(),n.close().then(t)};process.once("SIGINT",e),process.once("SIGTERM",e)})}function P8(n){let t=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open",r=process.platform==="win32"?["/c","start","",n]:[n];return new Promise((e,a)=>{let l=Al(t,r,{detached:!0,stdio:"ignore"}),s=(c)=>{l.off("spawn",d),a(c)},d=()=>{l.off("error",s),l.unref(),e()};l.once("error",s),l.once("spawn",d)})}async function I8(n="gh",t=jr){return{ok:await qr(n,["api","-X","PUT",`/user/starred/${Xt}`],t)===0}}async function N8(n={}){let t=await gn(n.fetcher),r=Gl(t,n.homeDir);return{targets:G.map((e)=>{let a=r.find((l)=>l.platform===e.id);return{target:e.id,label:j(e.id),version:t.versions[e.id]??null,status:a?.configured?"active":a?.detected?"disabled":a?.inspectionStatus==="not-inspected"?"not-inspected":"not-installed"}}),system:{version:t.version,nodeVersion:t.nodeVersion,platform:t.platform}}}function Gl(n,t){return an(process.cwd(),{homeDir:t,ampPluginListOutput:n.ampPluginListOutput,codexPluginListOutput:n.codexPluginListOutput,copilotCliVersion:n.versions["copilot-cli"]})}async function n4(n={}){let[t,r]=await Promise.all([gn(n.fetcher),(n.checkUpdates??I2)()]);return{hooks:Gl(t,n.homeDir).filter((e)=>e.detected).map((e)=>({platform:e.platform,label:j(e.platform),configured:e.configured})),update:{currentVersion:r.currentVersion,latestVersion:r.latestVersion??null,updateAvailable:r.updateAvailable}}}var Ql=Promise.resolve();function t4(n,t,r={}){let e=async()=>{let l=[],s=console.log,d=console.error;console.log=(...c)=>l.push(c.map(String).join(" ")),console.error=console.log;try{return{ok:await Wn(n,[],{selectTargets:async()=>[t],output:new R8({write(L,i,v){l.push(String(L).replace(/\n$/,"")),v()}}),...r})===0,output:l.join(`
5365
+ `)}}finally{console.log=s,console.error=d}},a=Ql.then(e);return Ql=a.then(()=>{return},()=>{return}),a}async function r4(n={}){let[t,r,e]=await Promise.all([e4(n.command),a4(n.fetchRepo),Promise.resolve(_n(T2(),n.logsDir).totalBlocked)]);return{starred:t,starCount:r,blockedTotal:e}}async function e4(n="gh",t=jr){if(await qr(n,["auth","status"],t)!==0)return null;let r=await qr(n,["api",`/user/starred/${Xt}`],t);if(r===0)return!0;if(r===null)return null;return!1}function qr(n,t,r){return new Promise((e)=>{let a=Al(n,t,{stdio:"ignore",windowsHide:!0}),l=!1,s,d=(c)=>{if(l)return;if(l=!0,s)clearTimeout(s);e(c)};a.once("error",()=>d(null)),a.once("close",d),s=setTimeout(()=>{a.kill(),d(null)},r)})}async function a4(n=fetch){try{let t=await n(`https://api.github.com/repos/${Xt}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(jr)});if(!t.ok)return null;let r=await t.json();return typeof r.stargazers_count==="number"?r.stargazers_count:null}catch{return null}}function l4(n){if(n[0]!=="help")return!1;let t=n[1];if(!t)lr(),process.exit(0);if(Yn(t))process.exit(0);console.error(`Unknown command: ${t}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var s4={hook:async(n)=>{let t=_e(n);if(t){await t.run();return}console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),Yn("hook",console.error),process.exit(1)},install:async(n)=>{process.exit(await Wn("install",n))},update:async(n)=>{process.exit(await xr(n))},uninstall:async(n)=>{process.exit(await Wn("uninstall",n))},rule:async(n)=>{process.exit(await $l(n))},status:async(n)=>{if(s2(J({label:"status"},n).errors))process.exit(1);ml()},statusline:async(n)=>{let t=J({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},n);if(t.errors.length===0&&t.flags.claudeCode){await gr();return}if(s2(t.errors),!t.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");Yn("statusline",console.error),process.exit(1)},doctor:async(n)=>{let t=nr(n);if(!t)process.exit(1);let r=await I0({json:t.json,skipUpdateCheck:t.skipUpdateCheck});process.exit(r)},logs:async(n)=>{process.exit(await he(n))},gui:async(n)=>{process.exit(await Ml(n))},explain:async(n)=>{process.exit(await l3(n))}};async function d4(){let n=process.argv.slice(2),t=J({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},n);if(l4(n))return;let r=n[0],e=r?Tn(r):void 0;if(t.help&&e&&e.name!=="rule")Yn(e.name),process.exit(0);if(!r||t.help&&!e)lr(),process.exit(0);if(t.flags.version)c3(),process.exit(0);if(e){await s4[e.name](n.slice(1));return}let a=Ee(r);if(a){await a.run();return}if(r==="--statusline"){await gr();return}console.error(r.startsWith("-")?`Unknown option: ${r}`:`Unknown command: ${r}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}d4().catch((n)=>{console.error("CC Safety Net error:",n),process.exit(1)});