cc-safety-net 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/amp/cc-safety-net.ts +2 -2
- package/dist/bin/cc-safety-net.js +74 -74
- package/dist/chunks/{index-9s8cwhj0.js → index-mf3j7fqk.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/openclaw/cc-safety-net/index.js +2 -2
- package/dist/openclaw/cc-safety-net/openclaw.plugin.json +1 -1
- package/dist/openclaw/cc-safety-net/package.json +1 -1
- package/dist/pi/index.js +1 -1
- package/package.json +2 -2
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{$ as
|
|
3
|
-
${B2(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 en(n,t){try{return
|
|
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 Hd}from"node:path";var pd=["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 pr(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 vr(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(xt(vd(s,r,d)))}catch{a++}},finish(s){if(l)return l;try{l=xt({events:Object.freeze(t),droppedEvents:a,terminal:bd(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 vd(n,t,e){if(n.kind!=="step")throw TypeError("invalid trace event");let{scope:r,step:a}=n;Fn(a,e,t);let l=J2(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 bd(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:J2(n.reason,t,e),segment:J2(n.segment,t,e),...a?{ruleId:J2(a,t,e)}:{}})}function Fn(n,t,e,r=0,a=new WeakSet){if(typeof n==="string"){let s=n.slice(0,e.maxTextLength);if(!mt(s))return;for(let i of ur(s))for(let c of i.match(/[^\s"'()$]+/g)??[])t.add(br(c));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 i=0;i<s;i++)Fn(n[i],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++,Fn(s,t,e);let i=wt(s,e,t);if(d.has(i))continue;d.add(i),Fn(n[s],t,e,r+1,a)}}function J2(n,t,e,r=0,a=new WeakSet){if(typeof n==="string")return wt(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=[],i=Math.min(n.length,t.maxListLength);for(let c=0;c<i;c++)s.push(J2(n[c],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 i=wt(s,t,e);if(Object.hasOwn(l,i))continue;Object.defineProperty(l,i,{value:J2(n[s],t,e,r+1,a),enumerable:!0,configurable:!0,writable:!0})}return l}function wt(n,t,e){let r=n.slice(0,t.maxTextLength),a=mt(r)?or(r):r,l=e.size>0?hd(a,e):a;return(fd(l)?Lr(l):l).slice(0,t.maxTextLength)}function fd(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&&pd.some((t)=>n.includes(t))||n.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(n)}function hd(n,t){return n.replace(/[^\s"'()$]+/g,(e)=>t.has(br(e))?"<redacted>":e)}function br(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 xt(n){if(n&&typeof n==="object"&&!Object.isFrozen(n)){for(let t of Object.values(n))xt(t);Object.freeze(n)}return n}function wr(n,t,e,r){let a=r??fr(),l=e??a.getCommandProgram(n,t.shell??"auto"),d=vr(),s=pr(d),i=l.dialect==="powershell"?a.getCommandProgram(n,"posix"):l,c=hr(i);s.recordGlobal({type:"parse",input:n,segments:c.map((p)=>[...p])});let L=yr(n,{...t,analyzePartialProgram:!0,trace:s},l,a),u=s.getNextSegmentIndex();if(L&&u>0&&u<c.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((p)=>p.kind==="command")?.segment??n,...L.ruleId?{ruleId:L.ruleId}:{}}:{result:"allowed"}),program:l})}import{resolve as yd}from"node:path";function gt(n){let t=xr().safeParse(n);return{errors:t.success?[]:gr(t.error.issues),ruleNames:new Set(mr(n).map((e)=>e.toLowerCase()))}}function $t(n){let t=Dr(n);if(!t.ok)return t.result;return gt(t.parsed)}function Dr(n){let t=[],e=new Set;try{let r=typeof n==="string"?rn(n):n,a=m(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){return t.push(r instanceof S?r.message:"Invalid JSON"),{ok:!1,result:{errors:t,ruleNames:e}}}}function kr(n){return yd(n??process.cwd(),".safety-net.json")}function r2(n){let t=Dr(n);if(!t.ok)return t.result;let e=$r(t.parsed);return{errors:e.errors,ruleNames:e.sources}}import{isAbsolute as wd,join as zn,relative as xd,resolve as qr,sep as md}from"node:path";async function R2(n={}){let t=St(n);return gd(t,await Bn(t,Z2()))}function gd(n,t){if(!t.ok)return t;let e=U(n),r=[...new Set(a2(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 Bn(n,t,e,r={}){let a=null,l=!1;try{let d=U(n),s=zt(d.configTarget);if(!s.ok)return s.result;let i=s.config;if(n.check)return Fd(i,d,n);a={target:d.lockTarget,content:m(d.lockTarget)};let c=Bt(d.lockTarget);if(c.errors.some((f)=>f.startsWith("Unable to access ")))return{ok:!1,errors:c.errors,warnings:[],entries:[]};if(n.only&&c.errors.length>0)return{ok:!1,errors:c.errors,warnings:[],entries:[]};let L=c.errors.length>0?null:c.lock,u=n.only?Zr(i,L,n.only):{ok:!0,specs:i.rules};if(!u.ok)return u.result;if(n.only&&!L&&u.specs.length<i.rules.length)return{ok:!1,errors:[`No lockfile available for partial update; run ${Jr}`],warnings:[],entries:[]};let p=(await Dd(u.specs,(f)=>Xr(f,d.configDir,n,L,d.filesystemScope,t),t)).map((f)=>zd(f,L,e));for(let f of p)Sd(f.content,f.entry,d.configDir,n,d.filesystemScope);let o=n.only?Bd(i,L,p):p.map((f)=>f.entry);l=!0,T(d.lockTarget,{version:1,rulebooks:o},void 0,r._testAfterPolicyRename);let b=new Map(p.map((f)=>[f.entry.spec,f.rulebook.rules.length])),v=Zd(o,d.configDir,n,d.filesystemScope,r);return{ok:!0,errors:[],warnings:v,entries:o.map((f)=>Jd(f,b))}}catch(d){if(l&&a)try{S2(a.target,a.content)}catch(s){return Q2(s)}return Q2(d)}}async function Jt(n,t={}){return $d(n,St(t),Z2())}async function $d(n,t,e,r={}){let a=null,l=!1;try{let d=U(t),s=m(d.configTarget);a={target:d.configTarget,content:s};let i=zt(d.configTarget);if(!i.ok)return i.result;let c=i.config,L=Br(n)?await Rr(n,e):[{spec:n}],u=L.map((b)=>b.spec),p=[...new Set([...c.rules,...u])];if(p.length>jt)return kd();if(p.length!==c.rules.length)l=!0,T(d.configTarget,{version:1,rules:p,overrides:c.overrides??{},transparent_wrappers:c.transparent_wrappers??[]},void 0,r._testAfterPolicyRename);let o=await Bn(t,e,new Map(L.filter((b)=>!!b.display_ref).map((b)=>[b.spec,b.display_ref])),r);if(!o.ok)S2(d.configTarget,s);return o}catch(d){if(l&&a)try{S2(a.target,a.content)}catch(s){return Q2(s)}return Q2(d)}}async function Dd(n,t,e=Z2()){if(n.length>jt)throw Error(Ft);let r=Array(n.length),a=0,l,d=Array.from({length:Math.min(n.length,Sr.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(i){if(!l)l={value:i},a=n.length,e.controller.abort(i);return}}});if(await Promise.all(d),l)throw l.value;return r}function kd(){return{ok:!1,errors:[Ft],warnings:[],entries:[]}}function St(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 qd(n){return{...St(n),deleteSource:n.deleteSource}}async function Zt(n,t={}){try{return await jd(n,qd(t),{})}catch(e){return Q2(e)}}async function jd(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=Bt(r.lockTarget);if(l.errors.length>0)return{ok:!1,errors:l.errors,warnings:[],entries:[]};let d=Qr(a.config.rules,l.lock,n);if(!d.ok)return d.result;let s=t.deleteSource?Qd(r.configDir,d.specs,l.lock,r.filesystemScope):{ok:!0,dirs:[]};if(!s.ok)return s.result;let i=m(r.configTarget);if(i===null)return Q2(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 S2(r.configTarget,i),u}let c=await Bn(t,Z2(),void 0,e);if(!c.ok)return S2(r.configTarget,i),c;let L=Rd(s.dirs,e,r.filesystemScope);if(!L.ok){S2(r.configTarget,i);let u=await Bn(t,Z2(),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 c}async function Fd(n,t,e){let r=Yr(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 zd(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 Bd(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 Jd(n,t){return{...n,ruleCount:t.get(n.spec)}}function Sd(n,t,e,r,a){let l=kt(t,qt(e,r));f2($(a,l),n)}function Zd(n,t,e,r,a){let l=qt(t,e),d=Jn(l),s=$(r,d),i=X2(s);if(!i)return[];let c=n.map((u)=>$(r,kt(u,l))),L=i.filter((u)=>u.kind==="directory").map((u)=>({directory:$(r,zn(d,u.name)),identity:$(r,zn(d,u.name,zr))})).filter((u)=>!c.some((p)=>jr(u.identity,p))).map((u)=>u.directory);for(let u of L)Fr(u);return L.flatMap((u)=>{try{return Yd(u,a),[]}catch{return["Unable to prune rules policy cache safely."]}})}function Qd(n,t,e,r){let a=new Map(e?.rulebooks.map((c)=>[c.spec,c])??[]),l=t.flatMap((c)=>{let L=a.get(c);if(!L)return ln.test(c)?[]:["--delete-source can only delete local rulebook sources"];return L.kind==="local-directory"?[]:["--delete-source can only delete local rulebook sources"]}),d=t.map((c)=>{let L=a.get(c);return zn(n,L?.kind==="local-directory"?L.path:c)}),s=l.length>0?[]:d.flatMap((c)=>Xd(n,c,r)),i=[...l,...s];return i.length>0?{ok:!1,result:{ok:!1,errors:i,warnings:[],entries:[]}}:{ok:!0,dirs:d}}function Xd(n,t,e){let r=qr(n),a=qr(t),l=xd(r,a);if(l===""||l===".."||l.startsWith(`..${md}`)||wd(l))return[`Refusing to delete local rulebook source outside ${n}: ${t}`];let d=$(e,a),s=X2(d);if(!s)return[`Local rulebook source directory not found: ${t}`];let i=s.find((c)=>c.name==="rulebook.json");if(!i)return[`Local rulebook source directory is missing rulebook.json: ${t}`];if(i.kind!=="file")throw new S(e.label);if(m($(e,zn(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 Rd(n,t,e){let r=n.flatMap((a)=>{try{return Ad($(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 Yd(n,t){if(t._testPruneRulebookCacheDir){t._testPruneRulebookCacheDir(n.path);return}Dt(n)}function Ad(n,t){if(t._testDeleteLocalSourceDir){t._testDeleteLocalSourceDir(n.path);return}Dt(n)}function S2(n,t){if(t===null){an(n);return}f2(n,t)}function Q2(n){return{ok:!1,errors:[n instanceof Error?n.message:String(n)],warnings:[],entries:[]}}function C2(n,t){let e=Md(t),r=Kr(e),a={effectiveLevel:r.effectiveLevel,selectedPreset:e.policySnapshot.policy.safety.level??"standard",effectiveCapabilities:r.effectiveCapabilities,destructiveCommandRuleOverrides:e.policySnapshot.policy.destructiveCommandRuleOverrides},{configSource:l,configValid:d}=Cd({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=Wd(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 i=wr(n,e),c=i.decision,L=c?.ruleId??Kd(n,e),u=sn.find((o)=>o.id===L&&o.activationCapability),p=u?r.policy.effectiveDestructiveCommandRules[u.id]:void 0;return{trace:Gd(i.trace),result:c?"blocked":"allowed",reason:c?A(c.reason):void 0,segment:c?A(c.evidence.find((o)=>o.kind==="command")?.segment??n):void 0,ruleId:c?.ruleId?A(c.ruleId):void 0,customRule:Vd(Ud(c?.ruleId,e.policySnapshot)),configSource:l,configValid:d,...a,...u&&p?{ruleActivation:{id:u.id,...p}}:{}}}function Cd(n){let t=_(n?.cwd),e=n?.userConfigPath??E(n),r=P({cwd:n?.cwd,userConfigDir:n?.userConfigDir,userConfigPath:n?.userConfigPath});try{if(m(r.projectConfigTarget)!==null){if(r2(r.projectConfigTarget).errors.length===0)return{configSource:t,configValid:!0};return{configSource:t,configValid:!1}}}catch(a){if(a instanceof S)return{configSource:t,configValid:!1};throw a}try{if(m(r.userConfigTarget)!==null){let a=r2(r.userConfigTarget);return{configSource:e,configValid:a.errors.length===0}}return{configSource:null,configValid:!0}}catch(a){if(a instanceof S)return{configSource:e,configValid:!1};throw a}}function Md(n){let t=Hd(n?.cwd??process.cwd()),e=n?.policySnapshot??H({cwd:t,userConfigDir:n?.userConfigDir}),r=l2(e.policy);return{cwd:t,effectiveCwd:t,policySnapshot:e,environment:Ar(),protectedGitMetadata:Wr(t),effectiveCapabilities:r.capabilities,strict:n?.strict??r.strict,paranoidRm:r.paranoidRm,paranoidInterpreters:r.paranoidInterpreters,worktreeMode:r.worktreeMode}}function Wd(n,t){let e=t.cwd??process.cwd(),r=Hr(H2("",{command:n},{kind:"command",shell:"posix"},{executionCwd:e,configCwd:e},n)),a=Ur(r);if(a)return{reason:Gr,target:a.target,ruleId:"policy-protection",ruleModule:"policy-protection",ruleFunction:"findPolicyConfigMutationTarget"};let l=Mr(r,t.protectedGitMetadata);if(l)return{reason:Cr,target:l.target,ruleId:"git-metadata-protection",ruleModule:"git-metadata-protection",ruleFunction:"findGitMetadataMutationTarget"};let d=t.policySnapshot.policy,s=d.secretProtection.enabled===!1?null:Tr(r,d.secretProtection,{strict:t.strict});if(s)return{reason:Or,target:s.target,ruleId:s.ruleId,ruleModule:"secret-protection",ruleFunction:"findSensitiveTarget"};return null}function Kd(n,t){let e=t.policySnapshot.policy,r=cn({...e,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...e.destructiveCommandRuleOverrides,...Object.fromEntries(sn.flatMap((a)=>a.activationCapability?[[a.id,"on"]]:[]))}},t.policySnapshot.state==="degraded"?{diagnostics:t.policySnapshot.diagnostics,reason:t.policySnapshot.reason}:void 0);return Vr(n,{...t,policySnapshot:r,strict:!0,paranoidRm:!0,paranoidInterpreters:!0})?.ruleId}function Vd(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 Gd(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 Ud(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 Id(n){let t=M2(),e=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(e2(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:_r(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):_r(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:Pd(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 Ir(n,t={}){let e=Id(n);if(!e)return 1;let r=t.logsDir??d2();if(e.pruneLegacy)return Nd(r,e.json,e.dryRun);if(!r)return console.log(e.json?"[]":e.id?`No retained audit log entry found for id ${F(e.id)}.`:"No audit log entries found."),0;y2(r);let a={count:0},l=o2(r,a).flatMap((L)=>en(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 rs(l,e,t.timeZone);let d=Date.now()-e.since*24*60*60*1000,s=l.filter((L)=>as(L,e,r,d)),i=e.suspect?yt(s.map((L)=>L.entry)):null,c=(i?s.filter((L)=>i.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(c.map((L)=>L.entry),null,2)),0;if(c.length===0)return console.log("No audit log entries found."),0;for(let L of c)console.log(ss(L.entry,t.timeZone));return 0}function Nd(n,t,e){let r=n?ts(n).map((s)=>Ed(n,s)):[];if(e)return ns(r,t);let a=[],l=0,d=0;for(let s of r){let i=Er(s,{throwIfNoEntry:!1})?.size??0,c=es(s);if(c){a.push(`${Pr(s)}: ${c}`);continue}l++,d+=i}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"} (${Nr(d)}).`);for(let s of a)console.error(`Could not remove ${F(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 ns(n,t){let e=n.reduce((r,a)=>r+(Er(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"} (${Nr(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 ts(n){try{return Od(n,{withFileTypes:!0}).filter((t)=>t.isFile()&&t.name.endsWith(".jsonl")).map((t)=>t.name)}catch{return[]}}function es(n){try{return Td(n),null}catch(t){return t instanceof Error?t.message:String(t)}}function Nr(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 rs(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 ${F(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 ${F(t.id??"")}.`),0;return console.log(is(a.entry,e)),0}function as(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&&!ls(n,e,t.session))return!1;if(t.project!==void 0&&!ds(n.entry.cwd,t.project))return!1;return!0}function ls(n,t,e){if(n.entry.sessionId===e)return!0;return _d(n.file)===t&&Pr(n.file,".jsonl")===e}function ds(n,t){if(!n)return!1;return n===t||n.startsWith(`${t}/`)}function ss(n,t){let e=F(n.id??"-"),r=F(n.decision??"deny"),a=n.cwd?` [${F(n.cwd)}]`:"",l=n.segment||n.command,d=l===n.command?"":"↳ ",s=l.length>50?`${l.slice(0,50)}…`:l;return`${e.padEnd(16)} ${F(na(n.ts,t))} ${r.padEnd(5)} ${F(n.agent??"-").padEnd(15)} ${F(n.ruleId??"-").padEnd(20)} ${d}${F(s)}${a}`}function is(n,t){let e=(a)=>F(a===void 0||a===null||a===""?"-":a),r=n.shape?`${n.agent??"-"} (shape: ${n.shape})`:n.agent??"-";return[`id: ${e(n.id)}`,`ts: ${e(na(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 na(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 _r(n){let t=Number(n);return Number.isFinite(t)&&t>0?t:null}var ta={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 ea={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 ra={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 ua,relative as ws}from"node:path";var cs=8388608;function Ls(n,t){console.log(JSON.stringify(n(la(t))))}async function os(n){let t;try{t=(await Tt(process.stdin)).trim()}catch{n({reason:"Failed to parse hook input JSON."});return}if(!t){n({reason:"Missing hook input JSON."});return}return _t(t,n,"Failed to parse hook input JSON.")}async function Tt(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>cs)throw us(n),Error("hook input byte limit exceeded");t.push(a)}return Buffer.concat(t,e).toString("utf-8")}function us(n){let t=n.destroy??n.cancel;if(!t)return;try{Promise.resolve(t.call(n)).catch(()=>{})}catch{}}function _t(n,t,e){try{return JSON.parse(n)}catch{t({reason:e});return}}function Q(n,t){let e=t.get(n);return e?{kind:"command",shell:e}:{kind:sa(n)}}function I(n,t,e,r){let a=n===void 0?process.cwd():n,l=typeof a==="string"&&a.trim()!==""?s2([a]):void 0;if(l)return{configCwd:l,executionCwd:l};return Y(r,t,e,fs(a)),null}function Y(n,t,e,r){let a;try{a=Ot(t)}catch(l){if(!(l instanceof W2))throw l}n(Sn({command:a,segment:r,toolName:e}))}async function ps(n){let t=await os(n.outputDeny);if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t)){Y(n.outputDeny);return}if(!n.isSupported(t))return;let e=n.getAgent?.(t)??n.agent,r=n.agent===e?void 0:n.agent,a=ys(t),l=(o,b)=>{aa(o,()=>n.getSessionId(t),{agent:e,shape:r,toolName:b,cwd:a}),n.outputDeny(o)},d=n.getToolName(t);if(typeof d!=="string"||d.trim()===""){Y((o)=>l(o),hs(t));return}let s=d,i=(o)=>l(o,s),c;try{c=n.getToolInput(t,s,i)}catch(o){if(!(o instanceof W2))throw o;Y(i,void 0,s);return}if(!c.ok)return;let L=n.getContext(t,c.input,s,i);if(!L)return;let u;try{u=Ot(c.input)}catch(o){if(!(o instanceof W2))throw o;Y(i,void 0,s);return}let p=H2(s,c.input,c.route,L,u??null);try{let o=Zn(p,{guard:{auditAllowed:ia(),dependencies:n.guardDependencies},audit:{agent:e,shape:r,getSessionId:()=>n.getSessionId(t)}}),b=Ut(o,{includeEvidence:!0,toolName:o.stage==="command-analysis"?void 0:s});if(b){n.outputDeny(b);return}n.outputAllow?.()}catch(o){if(!(o instanceof ca))throw o;vs(o);let b=Ut(o.evaluation,{includeEvidence:!0,toolName:o.evaluation.stage==="command-analysis"?void 0:s});if(b)n.outputDeny(b);return}}function vs(n){if(!Ln(D.debug))return;console.error(`CC Safety Net debug: ${bs(n.stage)}: ${da(n.cause)}`)}function bs(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 fs(n){return typeof n==="string"?n:void 0}function hs(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 ys(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 X(n){let t=(a)=>Ls(n.createDenyOutput,a),e=n.createAllowOutput;await ps({...n,outputDeny:t,outputAllow:e?()=>console.log(JSON.stringify(e())):void 0})}var xs=new Map([["run_command","auto"]]),ms=new Set(["absolutepath","directorypath","file_path","filepath","path","searchdirectory","searchpath","target_file","targetfile"]);function pa(n){return Q(n,xs)}async function va(){await X({agent:"antigravity-cli",createDenyOutput:(n)=>({decision:"deny",reason:n}),isSupported:()=>!0,getToolName:(n)=>n.toolCall?.name,getToolInput:(n,t)=>({ok:!0,input:qs(n.toolCall?.args,t),route:pa(t)}),getContext:gs,getSessionId:(n)=>n.conversationId})}function gs(n,t,e,r){let l=ks(n).flatMap((c)=>{let L=s2([c]);return L?[L]:[]});if(!l[0])return x2(r,t,e),null;if(e!=="run_command"){let c;try{c=$s(t,e,l)}catch(L){if(L instanceof W2)return x2(r,void 0,e),null;if(!(L instanceof Qn))throw L;return x2(r,t,e),null}if(!c)return x2(r,t,e),null;return{configCwd:c,executionCwd:c,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 x2(r,t,e),null;let i=vn(s,l);if(i){let c=ba(i,l);if(!c)return x2(r,t,e,s),null;return{configCwd:c,executionCwd:i,policyConfigCwds:l}}return x2(r,t,e,s),null}function $s(n,t,e){let r=pa(t),a=[...La(n,ms),...r.kind==="patch"?oa(n):[]].filter(ua),l=Xn(),d=new Set(a.flatMap((s)=>{let i=ba(un(s,pn,l),e);return i?[i]:[]}));if(d.size>1)return null;return[...d][0]??e[0]??null}function ba(n,t){return t.filter((e)=>Ds(n,e)).reduce((e,r)=>r.length>e.length?r:e,"")||null}function Ds(n,t){let e=ws(t,n);return e===""||!e.startsWith("..")&&!ua(e)}function x2(n,t,e,r){let a=t&&typeof t==="object"?t.command:void 0;n(Sn({command:typeof a==="string"?a:void 0,segment:r,toolName:e}))}function ks(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 s2(t)?t:[]}function qs(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 K2=[{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"]}}],fa=K2.slice().sort((n,t)=>n.doctorOrder-t.doctorOrder).map((n)=>n.id),ha=K2.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=K2.slice().sort((n,t)=>n.install.order-t.install.order).map((n)=>({id:n.id,...n.install})).map(({order:n,...t})=>t),ap=Object.fromEntries(K2.map((n)=>[n.id,n.displayName]));function p2(n){return K2.find((t)=>t.id===n)?.displayName??n}function m2(n){return K2.find((t)=>t.id===n)?.install.installLabel??n}import{homedir as js}from"node:os";import{isAbsolute as ya,join as Et}from"node:path";function xa(n){if(n!==void 0&&n!==null&&!ya(n))return"unknown";try{let t=Xn(),e=n?un(n,pn,t):void 0,r=process.env.HOME||js(),a=[["codex",process.env.CODEX_HOME||Et(r,".codex")],["copilot-cli",process.env.COPILOT_HOME||Et(r,".copilot")],["claude-code",process.env.CLAUDE_CONFIG_DIR||Et(r,".claude")]],l=e?a.flatMap(([d,s])=>{if(!ya(s))return[];return wa(e,un(s,pn,t))?[d]:[]}):[];if(l.length===1)return l[0]??"unknown";if(l.length>1)return"unknown"}catch(t){if(t instanceof Qn)return"unknown";return"unknown"}if(process.env.CLAUDECODE==="1"||Boolean(process.env.CLAUDE_CODE_ENTRYPOINT))return"claude-code";return"unknown"}var Pt="PreToolUse",ma="BeforeTool",ga="pre_tool_call",It="PreToolUse";var Fs=new Map([["Bash","posix"],["PowerShell","powershell"]]);function zs(n){return Q(n,Fs)}async function $a(){await X({agent:"claude-code",getAgent:(n)=>xa(n.transcript_path),createDenyOutput:(n)=>({hookSpecificOutput:{hookEventName:Pt,permissionDecision:"deny",permissionDecisionReason:n}}),isSupported:(n)=>n.hook_event_name===Pt,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:zs(t)}),getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>n.session_id})}var Bs=new Map([["bash","auto"],["Bash","auto"]]);function Js(n){return Q(n,Bs)}async function Da(){await X({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=_t(n.toolArgs,e,"Failed to parse toolArgs JSON.");if(r===void 0)return{ok:!1};return{ok:!0,input:r,route:Js(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 Ss=new Map([["Shell","auto"]]);function Zs(n){return Q(n,Ss)}async function ka(){await X({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:Zs(t)}),getContext:Qs,getSessionId:(n)=>n.conversation_id})}function Qs(n,t,e,r){let a=Xs(n);if(!a[0])return Y(r,t,e),null;let l=vn(Ys(n.cwd),a);if(!l)return Y(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 Y(r,t,e),null;let s=vn(d,a);if(!s)return Y(r,t,e,d),null;return{configCwd:l,executionCwd:s,policyConfigCwds:a}}function Xs(n){return Rs(n).flatMap((t)=>{let e=s2([t]);return e?[e]:[]})}function Rs(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 Ys(n){return typeof n==="string"&&n.trim()!==""?n:"."}var As=new Map([["run_shell_command","auto"]]);function Hs(n){return Q(n,As)}async function qa(){await X({agent:"gemini-cli",createDenyOutput:(n)=>({decision:"deny",reason:n,systemMessage:n}),isSupported:(n)=>n.hook_event_name===ma,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})}import{resolve as Cs}from"node:path";var Ms=new Map([["terminal","posix"]]);async function ja(){await X({agent:"hermes-agent",createDenyOutput:(n)=>({action:"block",message:n}),isSupported:(n)=>n.hook_event_name===ga,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:Q(t,Ms)}),getContext:Ws,getSessionId:(n)=>n.session_id})}function Ws(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 Y(r,t,e),null;let d=s2([Cs(a.configCwd,l)]);if(!d)return Y(r,t,e,l),null;return{...a,executionCwd:d}}var Ks=new Map([["Bash","posix"]]);function Vs(n){return Q(n,Ks)}async function Fa(){await X({agent:"kimi-code",createDenyOutput:(n)=>({hookSpecificOutput:{hookEventName:It,permissionDecision:"deny",permissionDecisionReason:n}}),isSupported:(n)=>n.hook_event_name===It,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:Vs(t)}),getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>n.session_id})}var Gs={"antigravity-cli":va,"claude-code":$a,"copilot-cli":Da,cursor:ka,"gemini-cli":qa,"hermes-agent":ja,"kimi-code":Fa},V2=ha.map((n)=>({...n,run:Gs[n.id]}));function za(n){let t=j({label:"hook",booleans:Object.fromEntries(V2.map((r)=>[r.id,[...r.flags,...r.legacyFlags]]))},n);if(t.errors.length>0)return;let e=V2.filter((r)=>t.flags[r.id]);return e.length===1?e[0]:void 0}function Ba(n){return V2.find((t)=>t.legacyTopLevelFlags.some((e)=>e===n))}var Us=V2.map((n)=>({flags:n.flags.join(", "),description:n.description})),Os=V2.flatMap((n)=>n.flags.map((t)=>`cc-safety-net hook ${t}`)),Ja={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[...Us,{flags:"-h, --help",description:"Show this help"}],examples:Os};var Sa={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}`)]},Za={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}`)]},Qa={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 Xa={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 G2={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 Ya={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,ta,Xa,ea,G2,Sa,Qa,Za,Ja,ra,Ya];function Ts(n){return n.aliases??[]}function _s(n){return!n.hidden}function Rn(n){let t=n.toLowerCase();return Aa.find((e)=>e.name.toLowerCase()===t||Ts(e).some((r)=>r.toLowerCase()===t))}function Ha(){return Aa.filter(_s)}import{readFileSync as Es}from"node:fs";import{basename as Ps}from"node:path";function Yn(n=7,t=d2()){let e=Date.now()-n*24*60*60*1000,r=[],a=new Set,l=0,d,s,i,c;if(t)y2(t);let L={count:0},u=t?o2(t,L):[];for(let o of u)try{let v=Es(o,"utf-8").trim().split(`
|
|
6
|
-
`).filter(Boolean);for(let f of v)try{let w=JSON.parse(f);if(w.decision==="allow")continue;let x=new Date(w.ts).getTime();if(x>=e){if(l++,a.add(w.sessionId??
|
|
7
|
-
`)}function Ua(n){let t=[];t.push("Hook Integration"),t.push(
|
|
8
|
-
`)}function
|
|
9
|
-
`)}function
|
|
10
|
-
`)}function
|
|
11
|
-
`)}function
|
|
2
|
+
import{$ as Tt,$a as Xr,A as dn,Aa as mr,B as zl,Ba as Gt,C as P,Ca as gr,D as U,Da as $r,E as Yt,Ea as O,F as qt,Fa as Bt,G as Jn,Ga as Rt,H as jt,Ha as At,I as W2,Ia as T,J as y2,Ja as Nl,K as Ht,Ka as Ut,L as s2,La as nd,M as aa,Ma as lr,N as Ot,Na as td,O as Sn,Oa as ed,P as la,Pa as rd,Q as da,Qa as ad,R as Qn,Ra as ld,S as Xn,Sa as dd,T as un,Ta as Gr,U as pn,Ua as Ur,V as Ar,Va as Or,W as sn,Wa as Tr,X as w2,Xa as Zl,Y as Mt,Ya as Zr,Z as V2,Za as Qr,_ as sa,_a as Jt,aa as La,ab as Yr,b as Lr,ba as oa,bb as u2,c as or,ca as Hr,cb as h2,d as A,da as fr,db as l2,e as ur,ea as Mr,eb as Rr,f as gt,fa as Wr,fb as H,g as S,ga as Vr,gb as on,h as $,ha as Wt,hb as cn,i as rn,ia as hr,ib as ia,j as m,ja as D,jb as vn,k as f2,ka as Vt,kb as c2,l as jr,la as ca,lb as wa,m as X2,ma as d2,mb as Zn,n as an,na as Ln,o as Al,oa as Kt,p as kt,pa as Ct,q as Fr,qa as Kr,r as ln,ra as Cr,s as zr,sa as yr,t as Xt,ta as H2,u as Br,ua as Ft,v as Jr,va as zt,w as E,wa as Sr,x as _,xa as Z2,y as R2,ya as Il,z as A2,za as xr}from"../chunks/index-mf3j7fqk.js";var ud=["-h","--help"];function j(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(ud.includes(u)){c=!0;continue}let p=e.find(([,b])=>b.includes(u));if(p){a[p[0]]=!0;continue}let o=r.find(([,b])=>b.includes(u));if(o){let b=t[L+1];if(b===void 0||b.startsWith("-")){s.push(`${u} requires a value`);continue}l[o[0]]=b,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 Pd,statSync as _r,unlinkSync as Id}from"node:fs";import{basename as Pr,dirname as Nd,join as ns,resolve as ts}from"node:path";function F(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 yt=(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"},B2=(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 pd,readdirSync as vd,readFileSync as bd}from"node:fs";import{join as fd}from"node:path";function o2(n,t){try{return vd(n,{withFileTypes:!0,encoding:"utf8"}).flatMap((e)=>{let r=fd(n,e.name);if(e.isDirectory())return o2(r,t);if(e.name.endsWith(".jsonl"))return[r];return[]})}catch{if(t&&pd(n))t.count++;return[]}}function wt(n){let t=(a)=>`${a.sessionId}
|
|
3
|
+
${B2(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 en(n,t){try{return bd(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 Kd}from"node:path";var hd=["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 pr(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 vr(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(mt(yd(s,r,d)))}catch{a++}},finish(s){if(l)return l;try{l=mt({events:Object.freeze(t),droppedEvents:a,terminal:wd(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 yd(n,t,e){if(n.kind!=="step")throw TypeError("invalid trace event");let{scope:r,step:a}=n;Fn(a,e,t);let l=J2(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 wd(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:J2(n.reason,t,e),segment:J2(n.segment,t,e),...a?{ruleId:J2(a,t,e)}:{}})}function Fn(n,t,e,r=0,a=new WeakSet){if(typeof n==="string"){let s=n.slice(0,e.maxTextLength);if(!gt(s))return;for(let c of ur(s))for(let i of c.match(/[^\s"'()$]+/g)??[])t.add(br(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++)Fn(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++,Fn(s,t,e);let c=xt(s,e,t);if(d.has(c))continue;d.add(c),Fn(n[s],t,e,r+1,a)}}function J2(n,t,e,r=0,a=new WeakSet){if(typeof n==="string")return xt(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(J2(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=xt(s,t,e);if(Object.hasOwn(l,c))continue;Object.defineProperty(l,c,{value:J2(n[s],t,e,r+1,a),enumerable:!0,configurable:!0,writable:!0})}return l}function xt(n,t,e){let r=n.slice(0,t.maxTextLength),a=gt(r)?or(r):r,l=e.size>0?md(a,e):a;return(xd(l)?Lr(l):l).slice(0,t.maxTextLength)}function xd(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&&hd.some((t)=>n.includes(t))||n.length>=49&&/\b[a-f0-9]{32}\.[A-Za-z0-9]{16}\b/.test(n)}function md(n,t){return n.replace(/[^\s"'()$]+/g,(e)=>t.has(br(e))?"<redacted>":e)}function br(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 mt(n){if(n&&typeof n==="object"&&!Object.isFrozen(n)){for(let t of Object.values(n))mt(t);Object.freeze(n)}return n}function wr(n,t,e,r){let a=r??fr(),l=e??a.getCommandProgram(n,t.shell??"auto"),d=vr(),s=pr(d),c=l.dialect==="powershell"?a.getCommandProgram(n,"posix"):l,i=hr(c);s.recordGlobal({type:"parse",input:n,segments:i.map((p)=>[...p])});let L=yr(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((p)=>p.kind==="command")?.segment??n,...L.ruleId?{ruleId:L.ruleId}:{}}:{result:"allowed"}),program:l})}import{resolve as gd}from"node:path";function $t(n){let t=xr().safeParse(n);return{errors:t.success?[]:gr(t.error.issues),ruleNames:new Set(mr(n).map((e)=>e.toLowerCase()))}}function Dt(n){let t=Dr(n);if(!t.ok)return t.result;return $t(t.parsed)}function Dr(n){let t=[],e=new Set;try{let r=typeof n==="string"?rn(n):n,a=m(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){return t.push(r instanceof S?r.message:"Invalid JSON"),{ok:!1,result:{errors:t,ruleNames:e}}}}function kr(n){return gd(n??process.cwd(),".safety-net.json")}function a2(n){let t=Dr(n);if(!t.ok)return t.result;let e=$r(t.parsed);return{errors:e.errors,ruleNames:e.sources}}import{isAbsolute as $d,join as zn,relative as Dd,resolve as qr,sep as kd}from"node:path";async function Y2(n={}){let t=Zt(n);return qd(t,await Bn(t,Z2()))}function qd(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 Bn(n,t,e,r={}){let a=null,l=!1;try{let d=U(n),s=Bt(d.configTarget);if(!s.ok)return s.result;let c=s.config;if(n.check)return Sd(c,d,n);a={target:d.lockTarget,content:m(d.lockTarget)};let i=Jt(d.lockTarget);if(i.errors.some((f)=>f.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?Zr(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 ${Jr}`],warnings:[],entries:[]};let p=(await Fd(u.specs,(f)=>Xr(f,d.configDir,n,L,d.filesystemScope,t),t)).map((f)=>Zd(f,L,e));for(let f of p)Yd(f.content,f.entry,d.configDir,n,d.filesystemScope);let o=n.only?Qd(c,L,p):p.map((f)=>f.entry);l=!0,T(d.lockTarget,{version:1,rulebooks:o},void 0,r._testAfterPolicyRename);let b=new Map(p.map((f)=>[f.entry.spec,f.rulebook.rules.length])),v=Rd(o,d.configDir,n,d.filesystemScope,r);return{ok:!0,errors:[],warnings:v,entries:o.map((f)=>Xd(f,b))}}catch(d){if(l&&a)try{S2(a.target,a.content)}catch(s){return Q2(s)}return Q2(d)}}async function St(n,t={}){return jd(n,Zt(t),Z2())}async function jd(n,t,e,r={}){let a=null,l=!1;try{let d=U(t),s=m(d.configTarget);a={target:d.configTarget,content:s};let c=Bt(d.configTarget);if(!c.ok)return c.result;let i=c.config,L=Br(n)?await Yr(n,e):[{spec:n}],u=L.map((b)=>b.spec),p=[...new Set([...i.rules,...u])];if(p.length>Ft)return zd();if(p.length!==i.rules.length)l=!0,T(d.configTarget,{version:1,rules:p,overrides:i.overrides??{},transparent_wrappers:i.transparent_wrappers??[]},void 0,r._testAfterPolicyRename);let o=await Bn(t,e,new Map(L.filter((b)=>!!b.display_ref).map((b)=>[b.spec,b.display_ref])),r);if(!o.ok)S2(d.configTarget,s);return o}catch(d){if(l&&a)try{S2(a.target,a.content)}catch(s){return Q2(s)}return Q2(d)}}async function Fd(n,t,e=Z2()){if(n.length>Ft)throw Error(zt);let r=Array(n.length),a=0,l,d=Array.from({length:Math.min(n.length,Sr.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 zd(){return{ok:!1,errors:[zt],warnings:[],entries:[]}}function Zt(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 Bd(n){return{...Zt(n),deleteSource:n.deleteSource}}async function Qt(n,t={}){try{return await Jd(n,Bd(t),{})}catch(e){return Q2(e)}}async function Jd(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=Jt(r.lockTarget);if(l.errors.length>0)return{ok:!1,errors:l.errors,warnings:[],entries:[]};let d=Qr(a.config.rules,l.lock,n);if(!d.ok)return d.result;let s=t.deleteSource?Ad(r.configDir,d.specs,l.lock,r.filesystemScope):{ok:!0,dirs:[]};if(!s.ok)return s.result;let c=m(r.configTarget);if(c===null)return Q2(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 S2(r.configTarget,c),u}let i=await Bn(t,Z2(),void 0,e);if(!i.ok)return S2(r.configTarget,c),i;let L=Md(s.dirs,e,r.filesystemScope);if(!L.ok){S2(r.configTarget,c);let u=await Bn(t,Z2(),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 Sd(n,t,e){let r=Rr(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 Zd(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 Qd(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 Xd(n,t){return{...n,ruleCount:t.get(n.spec)}}function Yd(n,t,e,r,a){let l=qt(t,jt(e,r));f2($(a,l),n)}function Rd(n,t,e,r,a){let l=jt(t,e),d=Jn(l),s=$(r,d),c=X2(s);if(!c)return[];let i=n.map((u)=>$(r,qt(u,l))),L=c.filter((u)=>u.kind==="directory").map((u)=>({directory:$(r,zn(d,u.name)),identity:$(r,zn(d,u.name,zr))})).filter((u)=>!i.some((p)=>jr(u.identity,p))).map((u)=>u.directory);for(let u of L)Fr(u);return L.flatMap((u)=>{try{return Wd(u,a),[]}catch{return["Unable to prune rules policy cache safely."]}})}function Ad(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 zn(n,L?.kind==="local-directory"?L.path:i)}),s=l.length>0?[]:d.flatMap((i)=>Hd(n,i,r)),c=[...l,...s];return c.length>0?{ok:!1,result:{ok:!1,errors:c,warnings:[],entries:[]}}:{ok:!0,dirs:d}}function Hd(n,t,e){let r=qr(n),a=qr(t),l=Dd(r,a);if(l===""||l===".."||l.startsWith(`..${kd}`)||$d(l))return[`Refusing to delete local rulebook source outside ${n}: ${t}`];let d=$(e,a),s=X2(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 S(e.label);if(m($(e,zn(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 Md(n,t,e){let r=n.flatMap((a)=>{try{return Vd($(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 Wd(n,t){if(t._testPruneRulebookCacheDir){t._testPruneRulebookCacheDir(n.path);return}kt(n)}function Vd(n,t){if(t._testDeleteLocalSourceDir){t._testDeleteLocalSourceDir(n.path);return}kt(n)}function S2(n,t){if(t===null){an(n);return}f2(n,t)}function Q2(n){return{ok:!1,errors:[n instanceof Error?n.message:String(n)],warnings:[],entries:[]}}function M2(n,t){let e=Gd(t),r=Kr(e),a={effectiveLevel:r.effectiveLevel,selectedPreset:e.policySnapshot.policy.safety.level??"standard",effectiveCapabilities:r.effectiveCapabilities,destructiveCommandRuleOverrides:e.policySnapshot.policy.destructiveCommandRuleOverrides},{configSource:l,configValid:d}=Cd({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=Ud(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=wr(n,e),i=c.decision,L=i?.ruleId??Od(n,e),u=sn.find((o)=>o.id===L&&o.activationCapability),p=u?r.policy.effectiveDestructiveCommandRules[u.id]:void 0;return{trace:Ed(c.trace),result:i?"blocked":"allowed",reason:i?A(i.reason):void 0,segment:i?A(i.evidence.find((o)=>o.kind==="command")?.segment??n):void 0,ruleId:i?.ruleId?A(i.ruleId):void 0,customRule:Td(_d(i?.ruleId,e.policySnapshot)),configSource:l,configValid:d,...a,...u&&p?{ruleActivation:{id:u.id,...p}}:{}}}function Cd(n){let t=E(n?.cwd),e=n?.userConfigPath??_(n),r=P({cwd:n?.cwd,userConfigDir:n?.userConfigDir,userConfigPath:n?.userConfigPath});try{if(m(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 S)return{configSource:t,configValid:!1};throw a}try{if(m(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 S)return{configSource:e,configValid:!1};throw a}}function Gd(n){let t=Kd(n?.cwd??process.cwd()),e=n?.policySnapshot??H({cwd:t,userConfigDir:n?.userConfigDir}),r=d2(e.policy);return{cwd:t,effectiveCwd:t,policySnapshot:e,environment:Ar(),protectedGitMetadata:Vr(t),effectiveCapabilities:r.capabilities,strict:n?.strict??r.strict,paranoidRm:r.paranoidRm,paranoidInterpreters:r.paranoidInterpreters,worktreeMode:r.worktreeMode}}function Ud(n,t){let e=t.cwd??process.cwd(),r=Hr(H2("",{command:n},{kind:"command",shell:"posix"},{executionCwd:e,configCwd:e},n)),a=Ur(r);if(a)return{reason:Gr,target:a.target,ruleId:"policy-protection",ruleModule:"policy-protection",ruleFunction:"findPolicyConfigMutationTarget"};let l=Wr(r,t.protectedGitMetadata);if(l)return{reason:Mr,target:l.target,ruleId:"git-metadata-protection",ruleModule:"git-metadata-protection",ruleFunction:"findGitMetadataMutationTarget"};let d=t.policySnapshot.policy,s=d.secretProtection.enabled===!1?null:Tr(r,d.secretProtection,{strict:t.strict});if(s)return{reason:Or,target:s.target,ruleId:s.ruleId,ruleModule:"secret-protection",ruleFunction:"findSensitiveTarget"};return null}function Od(n,t){let e=t.policySnapshot.policy,r=cn({...e,destructiveCommandProtectionEnabled:!0,destructiveCommandRuleOverrides:{...e.destructiveCommandRuleOverrides,...Object.fromEntries(sn.flatMap((a)=>a.activationCapability?[[a.id,"on"]]:[]))}},t.policySnapshot.state==="degraded"?{diagnostics:t.policySnapshot.diagnostics,reason:t.policySnapshot.reason}:void 0);return Cr(n,{...t,policySnapshot:r,strict:!0,paranoidRm:!0,paranoidInterpreters:!0})?.ruleId}function Td(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 Ed(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 _d(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 es(n){let t=W2(),e=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(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:Er(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):Er(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:ts(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 Ir(n,t={}){let e=es(n);if(!e)return 1;let r=t.logsDir??s2();if(e.pruneLegacy)return rs(r,e.json,e.dryRun);if(!r)return console.log(e.json?"[]":e.id?`No retained audit log entry found for id ${F(e.id)}.`:"No audit log entries found."),0;y2(r);let a={count:0},l=o2(r,a).flatMap((L)=>en(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 ss(l,e,t.timeZone);let d=Date.now()-e.since*24*60*60*1000,s=l.filter((L)=>cs(L,e,r,d)),c=e.suspect?wt(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(os(L.entry,t.timeZone));return 0}function rs(n,t,e){let r=n?ls(n).map((s)=>ns(n,s)):[];if(e)return as(r,t);let a=[],l=0,d=0;for(let s of r){let c=_r(s,{throwIfNoEntry:!1})?.size??0,i=ds(s);if(i){a.push(`${Pr(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"} (${Nr(d)}).`);for(let s of a)console.error(`Could not remove ${F(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 as(n,t){let e=n.reduce((r,a)=>r+(_r(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"} (${Nr(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 ls(n){try{return Pd(n,{withFileTypes:!0}).filter((t)=>t.isFile()&&t.name.endsWith(".jsonl")).map((t)=>t.name)}catch{return[]}}function ds(n){try{return Id(n),null}catch(t){return t instanceof Error?t.message:String(t)}}function Nr(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 ss(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 ${F(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 ${F(t.id??"")}.`),0;return console.log(us(a.entry,e)),0}function cs(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&&!is(n,e,t.session))return!1;if(t.project!==void 0&&!Ls(n.entry.cwd,t.project))return!1;return!0}function is(n,t,e){if(n.entry.sessionId===e)return!0;return Nd(n.file)===t&&Pr(n.file,".jsonl")===e}function Ls(n,t){if(!n)return!1;return n===t||n.startsWith(`${t}/`)}function os(n,t){let e=F(n.id??"-"),r=F(n.decision??"deny"),a=n.cwd?` [${F(n.cwd)}]`:"",l=n.segment||n.command,d=l===n.command?"":"↳ ",s=l.length>50?`${l.slice(0,50)}…`:l;return`${e.padEnd(16)} ${F(na(n.ts,t))} ${r.padEnd(5)} ${F(n.agent??"-").padEnd(15)} ${F(n.ruleId??"-").padEnd(20)} ${d}${F(s)}${a}`}function us(n,t){let e=(a)=>F(a===void 0||a===null||a===""?"-":a),r=n.shape?`${n.agent??"-"} (shape: ${n.shape})`:n.agent??"-";return[`id: ${e(n.id)}`,`ts: ${e(na(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 na(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 Er(n){let t=Number(n);return Number.isFinite(t)&&t>0?t:null}var ta={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 ea={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 ra={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 ua,relative as $s}from"node:path";var ps=8388608;function vs(n,t){console.log(JSON.stringify(n(la(t))))}async function bs(n){let t;try{t=(await Et(process.stdin)).trim()}catch{n({reason:"Failed to parse hook input JSON."});return}if(!t){n({reason:"Missing hook input JSON."});return}return _t(t,n,"Failed to parse hook input JSON.")}async function Et(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>ps)throw fs(n),Error("hook input byte limit exceeded");t.push(a)}return Buffer.concat(t,e).toString("utf-8")}function fs(n){let t=n.destroy??n.cancel;if(!t)return;try{Promise.resolve(t.call(n)).catch(()=>{})}catch{}}function _t(n,t,e){try{return JSON.parse(n)}catch{t({reason:e});return}}function Q(n,t){let e=t.get(n);return e?{kind:"command",shell:e}:{kind:sa(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 R(r,t,e,xs(a)),null}function R(n,t,e,r){let a;try{a=Tt(t)}catch(l){if(!(l instanceof V2))throw l}n(Sn({command:a,segment:r,toolName:e}))}async function hs(n){let t=await bs(n.outputDeny);if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t)){R(n.outputDeny);return}if(!n.isSupported(t))return;let e=n.getAgent?.(t)??n.agent,r=n.agent===e?void 0:n.agent,a=gs(t),l=(o,b)=>{aa(o,()=>n.getSessionId(t),{agent:e,shape:r,toolName:b,cwd:a}),n.outputDeny(o)},d=n.getToolName(t);if(typeof d!=="string"||d.trim()===""){R((o)=>l(o),ms(t));return}let s=d,c=(o)=>l(o,s),i;try{i=n.getToolInput(t,s,c)}catch(o){if(!(o instanceof V2))throw o;R(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=Tt(i.input)}catch(o){if(!(o instanceof V2))throw o;R(c,void 0,s);return}let p=H2(s,i.input,i.route,L,u??null);try{let o=Zn(p,{guard:{auditAllowed:ca(),dependencies:n.guardDependencies},audit:{agent:e,shape:r,getSessionId:()=>n.getSessionId(t)}}),b=Ot(o,{includeEvidence:!0,toolName:o.stage==="command-analysis"?void 0:s});if(b){n.outputDeny(b);return}n.outputAllow?.()}catch(o){if(!(o instanceof ia))throw o;ys(o);let b=Ot(o.evaluation,{includeEvidence:!0,toolName:o.evaluation.stage==="command-analysis"?void 0:s});if(b)n.outputDeny(b);return}}function ys(n){if(!Ln(D.debug))return;console.error(`CC Safety Net debug: ${ws(n.stage)}: ${da(n.cause)}`)}function ws(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 xs(n){return typeof n==="string"?n:void 0}function ms(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 gs(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 X(n){let t=(a)=>vs(n.createDenyOutput,a),e=n.createAllowOutput;await hs({...n,outputDeny:t,outputAllow:e?()=>console.log(JSON.stringify(e())):void 0})}var Ds=new Map([["run_command","auto"]]),ks=new Set(["absolutepath","directorypath","file_path","filepath","path","searchdirectory","searchpath","target_file","targetfile"]);function pa(n){return Q(n,Ds)}async function va(){await X({agent:"antigravity-cli",createDenyOutput:(n)=>({decision:"deny",reason:n}),isSupported:()=>!0,getToolName:(n)=>n.toolCall?.name,getToolInput:(n,t)=>({ok:!0,input:Bs(n.toolCall?.args,t),route:pa(t)}),getContext:qs,getSessionId:(n)=>n.conversationId})}function qs(n,t,e,r){let l=zs(n).flatMap((i)=>{let L=c2([i]);return L?[L]:[]});if(!l[0])return x2(r,t,e),null;if(e!=="run_command"){let i;try{i=js(t,e,l)}catch(L){if(L instanceof V2)return x2(r,void 0,e),null;if(!(L instanceof Qn))throw L;return x2(r,t,e),null}if(!i)return x2(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 x2(r,t,e),null;let c=vn(s,l);if(c){let i=ba(c,l);if(!i)return x2(r,t,e,s),null;return{configCwd:i,executionCwd:c,policyConfigCwds:l}}return x2(r,t,e,s),null}function js(n,t,e){let r=pa(t),a=[...La(n,ks),...r.kind==="patch"?oa(n):[]].filter(ua),l=Xn(),d=new Set(a.flatMap((s)=>{let c=ba(un(s,pn,l),e);return c?[c]:[]}));if(d.size>1)return null;return[...d][0]??e[0]??null}function ba(n,t){return t.filter((e)=>Fs(n,e)).reduce((e,r)=>r.length>e.length?r:e,"")||null}function Fs(n,t){let e=$s(t,n);return e===""||!e.startsWith("..")&&!ua(e)}function x2(n,t,e,r){let a=t&&typeof t==="object"?t.command:void 0;n(Sn({command:typeof a==="string"?a:void 0,segment:r,toolName:e}))}function zs(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 Bs(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 K2=[{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"]}}],fa=K2.slice().sort((n,t)=>n.doctorOrder-t.doctorOrder).map((n)=>n.id),ha=K2.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=K2.slice().sort((n,t)=>n.install.order-t.install.order).map((n)=>({id:n.id,...n.install})).map(({order:n,...t})=>t),ip=Object.fromEntries(K2.map((n)=>[n.id,n.displayName]));function p2(n){return K2.find((t)=>t.id===n)?.displayName??n}function m2(n){return K2.find((t)=>t.id===n)?.install.installLabel??n}import{homedir as Js}from"node:os";import{isAbsolute as ya,join as Pt}from"node:path";function xa(n){if(n!==void 0&&n!==null&&!ya(n))return"unknown";try{let t=Xn(),e=n?un(n,pn,t):void 0,r=process.env.HOME||Js(),a=[["codex",process.env.CODEX_HOME||Pt(r,".codex")],["copilot-cli",process.env.COPILOT_HOME||Pt(r,".copilot")],["claude-code",process.env.CLAUDE_CONFIG_DIR||Pt(r,".claude")]],l=e?a.flatMap(([d,s])=>{if(!ya(s))return[];return wa(e,un(s,pn,t))?[d]:[]}):[];if(l.length===1)return l[0]??"unknown";if(l.length>1)return"unknown"}catch(t){if(t instanceof Qn)return"unknown";return"unknown"}if(process.env.CLAUDECODE==="1"||Boolean(process.env.CLAUDE_CODE_ENTRYPOINT))return"claude-code";return"unknown"}var It="PreToolUse",ma="BeforeTool",ga="pre_tool_call",Nt="PreToolUse";var Ss=new Map([["Bash","posix"],["PowerShell","powershell"]]);function Zs(n){return Q(n,Ss)}async function $a(){await X({agent:"claude-code",getAgent:(n)=>xa(n.transcript_path),createDenyOutput:(n)=>({hookSpecificOutput:{hookEventName:It,permissionDecision:"deny",permissionDecisionReason:n}}),isSupported:(n)=>n.hook_event_name===It,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:Zs(t)}),getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>n.session_id})}var Qs=new Map([["bash","auto"],["Bash","auto"]]);function Xs(n){return Q(n,Qs)}async function Da(){await X({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=_t(n.toolArgs,e,"Failed to parse toolArgs JSON.");if(r===void 0)return{ok:!1};return{ok:!0,input:r,route:Xs(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 Ys=new Map([["Shell","auto"]]);function Rs(n){return Q(n,Ys)}async function ka(){await X({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:Rs(t)}),getContext:As,getSessionId:(n)=>n.conversation_id})}function As(n,t,e,r){let a=Hs(n);if(!a[0])return R(r,t,e),null;let l=vn(Ws(n.cwd),a);if(!l)return R(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 R(r,t,e),null;let s=vn(d,a);if(!s)return R(r,t,e,d),null;return{configCwd:l,executionCwd:s,policyConfigCwds:a}}function Hs(n){return Ms(n).flatMap((t)=>{let e=c2([t]);return e?[e]:[]})}function Ms(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 Ws(n){return typeof n==="string"&&n.trim()!==""?n:"."}var Vs=new Map([["run_shell_command","auto"]]);function Ks(n){return Q(n,Vs)}async function qa(){await X({agent:"gemini-cli",createDenyOutput:(n)=>({decision:"deny",reason:n,systemMessage:n}),isSupported:(n)=>n.hook_event_name===ma,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:Ks(t)}),getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>n.session_id})}import{resolve as Cs}from"node:path";var Gs=new Map([["terminal","posix"]]);async function ja(){await X({agent:"hermes-agent",createDenyOutput:(n)=>({action:"block",message:n}),isSupported:(n)=>n.hook_event_name===ga,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:Q(t,Gs)}),getContext:Us,getSessionId:(n)=>n.session_id})}function Us(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 R(r,t,e),null;let d=c2([Cs(a.configCwd,l)]);if(!d)return R(r,t,e,l),null;return{...a,executionCwd:d}}var Os=new Map([["Bash","posix"]]);function Ts(n){return Q(n,Os)}async function Fa(){await X({agent:"kimi-code",createDenyOutput:(n)=>({hookSpecificOutput:{hookEventName:Nt,permissionDecision:"deny",permissionDecisionReason:n}}),isSupported:(n)=>n.hook_event_name===Nt,getToolName:(n)=>n.tool_name,getToolInput:(n,t)=>({ok:!0,input:n.tool_input,route:Ts(t)}),getContext:(n,t,e,r)=>I(n.cwd,t,e,r),getSessionId:(n)=>n.session_id})}var Es={"antigravity-cli":va,"claude-code":$a,"copilot-cli":Da,cursor:ka,"gemini-cli":qa,"hermes-agent":ja,"kimi-code":Fa},C2=ha.map((n)=>({...n,run:Es[n.id]}));function za(n){let t=j({label:"hook",booleans:Object.fromEntries(C2.map((r)=>[r.id,[...r.flags,...r.legacyFlags]]))},n);if(t.errors.length>0)return;let e=C2.filter((r)=>t.flags[r.id]);return e.length===1?e[0]:void 0}function Ba(n){return C2.find((t)=>t.legacyTopLevelFlags.some((e)=>e===n))}var _s=C2.map((n)=>({flags:n.flags.join(", "),description:n.description})),Ps=C2.flatMap((n)=>n.flags.map((t)=>`cc-safety-net hook ${t}`)),Ja={name:"hook",description:"Run as an agent CLI hook (reads JSON from stdin)",usage:"hook INTEGRATION_FLAG",options:[..._s,{flags:"-h, --help",description:"Show this help"}],examples:Ps};var Sa={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}`)]},Za={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}`)]},Qa={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 Xa={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 G2={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 Ya={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 Ra={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=[Ya,ta,Xa,ea,G2,Sa,Qa,Za,Ja,ra,Ra];function Is(n){return n.aliases??[]}function Ns(n){return!n.hidden}function Yn(n){let t=n.toLowerCase();return Aa.find((e)=>e.name.toLowerCase()===t||Is(e).some((r)=>r.toLowerCase()===t))}function Ha(){return Aa.filter(Ns)}import{readFileSync as n3}from"node:fs";import{basename as t3}from"node:path";function Rn(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)y2(t);let L={count:0},u=t?o2(t,L):[];for(let o of u)try{let v=n3(o,"utf-8").trim().split(`
|
|
6
|
+
`).filter(Boolean);for(let f of v)try{let w=JSON.parse(f);if(w.decision==="allow")continue;let x=new Date(w.ts).getTime();if(x>=e){if(l++,a.add(w.sessionId??t3(o,".jsonl")),s===void 0||x<=s)d=w.ts,s=x;if(i===void 0||x>i)c=w.ts,i=x;e3(r,w,x)}}catch{L.count++}}catch{L.count++}let p=r.map((o)=>({timestamp:o.ts,command:o.command,reason:o.reason,relativeTime:yt(new Date(o.ts))}));return{totalBlocked:l,sessionCount:a.size,recentEntries:p,oldestEntry:d,newestEntry:c,unreadable:L.count}}function e3(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 r3}from"node:path";function Ma(n,t,e,r,a){let l;try{if(m(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 S))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 a3(n,t){return{source:t,name:n.name,command:n.command,subcommand:n.subcommand,blockArgs:[...n.block_args],reason:n.reason}}function Wa(n,t){let e=t?.userConfigPath??_(),r=t?.projectConfigPath??E(n),a=r3(e),l=u2({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:Ma(e,R2({userConfigPath:e}),a,d.userConfigTarget,d.userScope),projectConfig:Ma(r,A2(r),a,d.projectConfigTarget,d.projectScope),effectiveRules:l.rules.map((c)=>a3(c,s.get(c.name)??"project")),shadowedRules:[]}}var l3=[{flag:D.level,description:"Safety level preset: standard, strict, or paranoid",defaultBehavior:"standard"},{flag:D.strict,description:"Legacy; equivalent to safety.overrides.fail_closed",defaultBehavior:"permissive"},{flag:D.paranoid,description:"Legacy; equivalent to safety.overrides.paranoid_rm and paranoid_interpreters",defaultBehavior:"off"},{flag:D.paranoidRm,description:"Legacy; equivalent to safety.overrides.paranoid_rm",defaultBehavior:"off"},{flag:D.paranoidInterpreters,description:"Legacy; equivalent to safety.overrides.paranoid_interpreters",defaultBehavior:"off"},{flag:D.worktree,description:"Allow local git discards in linked worktrees",defaultBehavior:"off"},{flag:D.debug,description:"Print diagnostic messages to stderr",defaultBehavior:"off"},{flag:D.auditScope,description:"Command decisions recorded: all, or blocked (privacy-minimizing, denials only)",defaultBehavior:"all"}];function Va(){return[...l3.map((n)=>({name:n.flag.name,value:Kt(n.flag),isSet:Ct(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 Ka={error:0,warning:1,info:2},d3=["policy","config","audit"];function s3(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 c3=[{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=p2(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 Vt(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."}]:[]}},...d3.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 ${s3(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 Ca(n){return c3.flatMap((t,e)=>t.derive(n).map((r,a)=>({finding:r,catalogOrder:e,occurrence:a}))).sort((t,e)=>Ka[t.finding.severity]-Ka[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 i3=(n)=>N()?`\x1B[32m${n}\x1B[0m`:n,L3=(n)=>N()?`\x1B[33m${n}\x1B[0m`:n,o3=(n)=>N()?`\x1B[34m${n}\x1B[0m`:n,u3=(n)=>N()?`\x1B[35m${n}\x1B[0m`:n,p3=(n)=>N()?`\x1B[36m${n}\x1B[0m`:n,v3=(n)=>N()?`\x1B[31m${n}\x1B[0m`:n,b3=(n)=>N()?`\x1B[2m${n}\x1B[0m`:n,f3=(n)=>N()?`\x1B[1m${n}\x1B[0m`:n,h={green:i3,yellow:L3,blue:o3,magenta:u3,cyan:p3,red:v3,dim:b3,bold:f3},h3="\x1B[0m",y3=[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 w3(n){let t=n;return()=>{return t=(t*1664525+1013904223)%4294967296,t/4294967296}}function x3(n){let t=[...y3],e=w3(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 m3(n,t=0){if(!N())return"";let e=x3(t);return`\x1B[38;5;${e[n%e.length]}m`}function Ga(n,t,e=0){if(!N())return`"${n}"`;return`${m3(t,e)}"${n}"${h3}`}var g3=new RegExp("\x1B\\[[0-9;]*m","g"),ne=(n)=>n.replace(g3,"").length;function g2(n){let t=(n.headers??n.rows[0]??[]).map((d,s)=>{let c=Math.max(...n.rows.map((i)=>ne(i[s]??"")));return Math.max(ne(d),c)}),e=(d,s)=>d+" ".repeat(Math.max(0,s-ne(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 Ua(n){let t=[];t.push("Hook Integration"),t.push($3(n));let e=[],r=[];for(let a of n){let l=p2(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(h.red(` Error (${a.platform}): ${a.message}`));return t.join(`
|
|
8
|
+
`)}function $3(n){let t=["Platform","Discovery","Configuration","Inspection"],e=n.map((r)=>{let a=p2(r.platform);if(r.inspectionStatus==="not-inspected"){let c=h.dim("Not inspected");return[a,c,c,c]}let l=r.detected?h.green("Detected"):r.inspectionStatus==="failed"?h.red("Unknown"):h.dim("Not detected"),d=r.configured?h.green("Configured"):r.detected?h.yellow("Not configured"):r.inspectionStatus==="failed"?h.red("Unknown"):h.dim("Not applicable"),s=r.inspectionStatus==="verified"?h.green("Verified"):r.inspectionStatus==="failed"?h.red("Failed"):h.dim("Not applicable");return[a,l,d,s]});return g2({headers:t,rows:e})}function Oa(n){let e=["Guard Engine Verification",` Synthetic self-test: ${n.failed>0?h.red(`${n.passed}/${n.total} FAIL`):h.green(`${n.passed}/${n.total} passed`)}`],r=n.results.filter((a)=>!a.passed);if(r.length>0){e.push(""),e.push(h.red(" Failures:"));for(let a of r)e.push(h.red(` • ${a.description}`)),e.push(h.red(` expected ${a.expected}, got ${a.actual}`))}return e.join(`
|
|
9
|
+
`)}function D3(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 g2({headers:t,rows:e})}function Ta(n){let t=[];if(t.push("Configuration"),t.push(k3(n.userConfig,n.projectConfig)),t.push(""),n.effectiveRules.length>0)t.push(` Effective rules (${n.effectiveRules.length} total):`),t.push(D3(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 k3(n,t){let e=["Scope","Status"],r=(l)=>{if(!l.exists)return h.dim("N/A");if(!l.valid)return h.red(`Invalid (${l.errors?.[0]??"unknown error"})`);return h.green("Configured")},a=[["User",r(n)],["Project",r(t)]];return g2({headers:e,rows:a})}function Ea(n){let t=[];return t.push("Environment"),t.push(q3(n)),t.join(`
|
|
11
|
+
`)}function _a(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?h.green("ON"):h.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
12
|
`)}function Pa(n){let t=["Findings"];if(n.length===0)return t.push(" No findings from inspected doctor facts."),t.join(`
|
|
13
13
|
`);for(let e of n){let r=`[${e.severity.toUpperCase()}] ${e.checkId}: ${F(e.title)}`,a=e.severity==="error"?h.red:e.severity==="warning"?h.yellow:h.blue;if(t.push(` ${a(r)}`),t.push(` ${F(e.detail)}`),e.path)t.push(` Path: ${F(e.path)}`);if(e.fixHint)t.push(` Fix: ${F(e.fixHint)}`)}return t.join(`
|
|
14
|
-
`)}function
|
|
15
|
-
`)}function
|
|
14
|
+
`)}function q3(n){let t=["Variable","Status","Legacy"],e=n.map((r)=>{let a=r.isSet?h.green("✓"):h.dim("✗"),l=r.legacyName&&r.legacyIsSet?`${r.legacyName} ${h.green("✓")}`:r.legacyName??"";return[r.name,a,l]});return g2({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(j3(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 j3(n){let t=["Time","Command"],e=n.map((r)=>{let a=F(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 g2({headers:t,rows:e})}function Na(n){let t=[];if(t.push("Update Check"),n.latestVersion===null&&!n.error)return t.push(An([["Status",h.dim("Skipped")],["Installed",n.currentVersion]])),t.join(`
|
|
16
16
|
`);if(n.error)return t.push(An([["Status",`${h.yellow("⚠")} Error`],["Installed",n.currentVersion],["Error",h.dim(n.error)]])),t.join(`
|
|
17
17
|
`);if(n.updateAvailable)return t.push(An([["Status",`${h.yellow("⚠")} Update Available`],["Current",n.currentVersion],["Latest",h.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
18
|
`);return t.push(An([["Status",`${h.green("✓")} Up to date`],["Version",n.currentVersion]])),t.join(`
|
|
19
|
-
`)}function An(n){return g2({rows:n})}function n1(n){let t=[];return t.push("System Info"),t.push(
|
|
20
|
-
`)}function
|
|
19
|
+
`)}function An(n){return g2({rows:n})}function n1(n){let t=[];return t.push("System Info"),t.push(F3(n)),t.join(`
|
|
20
|
+
`)}function F3(n){let t=["Component","Version"],e=(l)=>{if(l===null)return h.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 g2({headers:t,rows:a})}function t1(n){if(n.findings.length===0)return h.green(`
|
|
21
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 h.red(a);if(t.warning>0)return h.yellow(a);return h.blue(a)}import{lstatSync as
|
|
23
|
-
`)[0]?.trim()||null}async function bn(n=Hn){let[t,e,r,a,l,d,s,i,
|
|
24
|
-
`).map((v)=>Array.from(v)),u=Math.max(...L.map((v)=>v.length)),p=1000*
|
|
25
|
-
`.repeat(L.length-1)}${
|
|
22
|
+
${n.findings.length} ${r}: ${e.join(", ")}.`;if(t.error>0)return h.red(a);if(t.warning>0)return h.yellow(a);return h.blue(a)}import{lstatSync as z3}from"node:fs";import{dirname as te}from"node:path";function ee(n,t){try{let e=z3(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 e1(n){let t=s2();return{directories:[ee("policy",te(te(n))),ee("config",te(n)),...t?[ee("audit",t)]:[{kind:"audit",status:"unknown",issues:[]}]]}}import{spawn as B3}from"node:child_process";import{existsSync as r1}from"node:fs";import{delimiter as J3,extname as S3,join as Z3}from"node:path";import{stripVTControlCharacters as a1}from"node:util";var d1="2.0.1",Q3=5000,X3="_CC_SAFETY_NET_TEST_SPAWN_PLATFORM";function z(){return d1}function re(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 Y3(n){return(re(n,"PATHEXT")||".COM;.EXE;.BAT;.CMD").split(";").filter((t)=>t.length>0)}function R3(n,t){let e=S3(n)?[n]:[...Y3(t).map((r)=>`${n}${r}`),n];if(n.includes("/")||n.includes("\\"))return e.find((r)=>r1(r))??n;return(re(t,"PATH")??"").split(J3).flatMap((r)=>e.map((a)=>Z3(r,a))).find((r)=>r1(r))??n}function l1(n){if(!/[\s"&|<>^]/.test(n))return n;return`"${n.replace(/"/g,'""')}"`}function A3(n,t){let[e,...r]=n,a=t[X3]==="win32"?"win32":process.platform;if(!e||a!=="win32")return{cmd:e??"",args:r};let l=R3(e,t);if(!/\.(?:bat|cmd)$/i.test(l))return{cmd:l,args:r};return{cmd:re(t,"COMSPEC")??"cmd.exe",args:["/d","/c",["call",l1(l),...r.map(l1)].join(" ")]}}var Hn=async(n,t=Q3)=>{let e=await H3(n,{timeoutMs:t});if(e.code!==0)return null;return a1(e.stdout).trim()||a1(e.stderr).trim()||null};function H3(n,t){let[e,...r]=n;if(!e)return Promise.resolve({code:null,stdout:"",stderr:""});return new Promise((a)=>{try{let l=A3([e,...r],process.env),d=B3(l.cmd,l.args,{stdio:["ignore","pipe","pipe"]}),s=!1,c="",i="";d.stdout.on("data",(p)=>{c+=p.toString()}),d.stderr.on("data",(p)=>{i+=p.toString()});let L=(p)=>{if(s)return;s=!0,clearTimeout(u),a(p)},u=setTimeout(()=>{d.kill(),L({code:null,stdout:c,stderr:i})},t.timeoutMs);d.on("close",(p)=>{L({code:p,stdout:c,stderr:i})}),d.on("error",()=>{L({code:null,stdout:c,stderr:i})})}catch{a({code:null,stdout:"",stderr:""})}})}function Z(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 bn(n=Hn){let[t,e,r,a,l,d,s,c,i,L,u,p,o,b,v,f]=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(["node","--version"]),n(["npm","--version"]),n(["bun","--version"])]);return{version:d1,claudeCodeVersion:Z(t),antigravityCliVersion:Z(e),openCodeVersion:Z(r),codexCliVersion:Z(a),codexPluginListOutput:l,geminiCliVersion:Z(d),copilotCliVersion:Z(s),hermesAgentVersion:Z(c),kimiCodeVersion:Z(i),openClawVersion:Z(L),piCliVersion:Z(u),cursorVersion:Z(p),ampVersion:Z(o),nodeVersion:Z(b),npmVersion:Z(v),bunVersion:Z(f),platform:`${process.platform} ${process.arch}`}}function ae(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 U2(){let n=z(),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=ae(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 v1 from"node:readline";var L1=(n)=>`\x1B[${n}B`,M3=(n)=>`\x1B[${n}A`;var s1=["░","▒","▓","╱","╲","┃","━","┏","┓","┗","┛","╋"];function W3(n){return new Promise((t)=>setTimeout(t,n))}function V3(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 fn(n,t){return n&&n>0?n:t}function Mn(n){return Math.max(0,Math.min(1,n))}function O2(n){return Math.max(0,Math.min(255,Math.round(n)))}function le(n){return n<=0.0031308?12.92*n:1.055*n**0.4166666666666667-0.055}function K3(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:O2(le(Mn(-0.0041960863*d-0.7034186147*s+1.707614701*c))*255),green:O2(le(Mn(-1.2684380046*d+2.6097574011*s-0.3413193965*c))*255),red:O2(le(Mn(4.0767416621*d-3.3077115913*s+0.2309699292*c))*255)}}function de(n,t){let e=(t*n*180/Math.PI%360+360)%360;return K3(0.72,0.15,e)}function o1(n,t=0.1){let e=de(t,n);return`\x1B[38;2;${e.red};${e.green};${e.blue}m`}function C3(n,t){return{blue:O2(n.blue+(255-n.blue)*t),green:O2(n.green+(255-n.green)*t),red:O2(n.red+(255-n.red)*t)}}function u1(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 G3(n,t,e){let r=Math.floor(u1(n,t,e)*s1.length);return s1[r]??"░"}function c1(n){let t=Mn(n);return t*t*t*(t*(t*6-15)+10)}function U3(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 O3(n,t,e,r,a){return n.map((l,d)=>({...de(e,r+t+d/a),bold:!1,character:l}))}function T3(n,t,e,r,a,l,d,s){let c=Math.max(1,r*0.75),i=Math.min(1,e/c),L=a*c1(i),u=Math.max(0,(e-c)/Math.max(1,r-c)),p=(1-c1(e/r))*s*2,o=0.35*Math.max(0,1-u*2),b=i>=1,v=Math.min(n.length,Math.ceil(L+2+1));return n.slice(0,v).map((f,w)=>{let x=de(l,d+t+w/s+p),y=w+u1(t,w,7919)*2-1;if(y>L+2)return{...x,bold:!1,character:" "};let J=L-y,z2=0.8*Math.exp(-(J*J)/12.5),tn=Math.min(0.9,z2+o),ft=!b&&y>L-4;return{...C3(x,tn),bold:tn>0.3,character:ft?G3(t,w,e):f}})}function i1(n){return`\x1B[?2026h${n.map((t,e)=>`\x1B8${e>0?L1(e):""}${U3(t)}`).join("")}\x1B[?2026l`}async function se(n,t={}){if(!n)return;let e=t.output??process.stdout,r=t.sleep??W3,a=fn(t.frequency,0.1),l=t.seed??0,d=fn(t.speed,40),s=fn(t.spread,3),c=fn(t.frameRate,60),i=Math.max(1,Math.floor(fn(t.duration,12))),L=n.split(`
|
|
24
|
+
`).map((v)=>Array.from(v)),u=Math.max(...L.map((v)=>v.length)),p=1000*i*L.filter((v)=>v.length>0).length/d,o=u>0?Math.max(1,Math.ceil(p/(1000/c))):0,b=o>0?p/o:0;e.write(`\x1B[?25l${L.length>1?`${`
|
|
25
|
+
`.repeat(L.length-1)}${M3(L.length-1)}`:""}\x1B7`);try{for(let v=1;v<=o;v+=1){if(t.signal?.aborted)break;e.write(i1(L.map((f,w)=>T3(f,w,v,o,u,a,l,s)))),await V3(b,r,t.signal)}}finally{if(e.write(i1(L.map((v,f)=>O3(v,f,a,l,s)))),e.write("\x1B8"),L.length>1)e.write(L1(L.length-1));e.write(`
|
|
26
26
|
\x1B[0m\x1B[?25h`)}}var p1=["┏━┛┏━┛ ┏━┛┏━┃┏━┛┏━┛━┏┛┃ ┃ ┏━ ┏━┛━┏┛","┃ ┃ ━━┃┏━┃┏━┛┏━┛ ┃ ━┏┛ ┃ ┃┏━┛ ┃ ","━━┛━━┛ ━━┛┛ ┛┛ ━━┛ ┛ ┛ ┛ ┛━━┛ ┛ "].join(`
|
|
27
|
-
`);function
|
|
28
|
-
`).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
|
|
29
|
-
`)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
|
|
30
|
-
`)}function
|
|
31
|
-
`),{path:t,alreadyInstalled:!1};let e=
|
|
27
|
+
`);function E3(n){return Boolean(n.isTTY)}async function Wn(n={}){let t=n.output??process.stdout;if(!E3(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 se(p1,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()};v1.emitKeypressEvents(e),e.on("keypress",c),e.setRawMode(!0),e.resume();try{await se(p1,{...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 b1="\r\x1B[2K",_3="\x1B[?25l",P3="\x1B[39m",I3="\x1B[?25h",N3=100,nc=0.55,tc=80,f1=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];function ec(n){return new Promise((t)=>setTimeout(t,n))}async function rc(n,t){let e=t.output??process.stdout;if(!e.isTTY){await n;return}let r=t.sleep??ec,a=!1,l=n.then((s)=>{return a=!0,s},(s)=>{throw a=!0,s});if(await Promise.race([l.then(()=>!0),r(N3).then(()=>!1)]))return;e.write(_3);try{for(let s=0;!a;s+=1)e.write(`${b1}${o1(s*nc)}${f1[s%f1.length]}${P3} ${t.loadingMessage??"Loading…"}`),await Promise.race([l,r(tc)]);await l}finally{e.write(`${b1}${I3}`)}}async function Vn(n,t,e,r={}){let a=t();if(n)await e();if(n&&a.ready)await rc(a.ready,r);return a.finish()}import{homedir as mi}from"node:os";import{lstatSync as uc,readFileSync as pc}from"node:fs";var hn="// cc-safety-net managed Amp plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --amp";import{existsSync as dc,lstatSync as y1,mkdirSync as sc,readFileSync as ce,rmSync as cc}from"node:fs";import{dirname as w1,join as Kn}from"node:path";import{fileURLToPath as ic}from"node:url";import{renameSync as ac,writeFileSync as lc}from"node:fs";function B(n,t){let e=`${n}.${process.pid}.tmp`;lc(e,t),ac(e,n)}var h1=Kn("amp","cc-safety-net.ts");function Cn(n){return Kn(n,".config","amp","plugins","cc-safety-net.ts")}function Lc(){let n=w1(ic(import.meta.url));return[Kn(n,"..",h1),Kn(n,"..","..","..","dist",h1)]}function oc(n=Lc()){let t=n.find((e)=>dc(e)&&y1(e).isFile());if(!t)throw Error("Packaged Amp plugin artifact not found. Reinstall cc-safety-net and try again.");return t}function x1(n){try{return y1(n)}catch{return}}function m1(n){return n.subarray(0,Buffer.byteLength(hn)).toString("utf-8")===hn}function g1(n,t=oc()){let e=ce(t),r=Cn(n),a=x1(r);if(!a)return sc(w1(r),{recursive:!0}),B(r,e),{path:r,alreadyInstalled:!1};if(a.isSymbolicLink()||!a.isFile())throw Error(`Refusing to overwrite ${r}: not a regular file. Move or remove it and rerun install --amp.`);let l=ce(r);if(l.equals(e))return{path:r,alreadyInstalled:!0};if(m1(l))return B(r,e),{path:r,alreadyInstalled:!1};throw Error(`Refusing to overwrite unmanaged file at ${r}. Move or remove it and rerun install --amp.`)}function $1(n){let t=Cn(n),e=x1(t);if(!e)return{path:t,alreadyInstalled:!1};if(e.isSymbolicLink()||!e.isFile())throw Error(`Refusing to remove ${t}: not a regular file. Move or remove it manually.`);if(!m1(ce(t)))throw Error(`Refusing to remove unmanaged file at ${t}. Move or remove it manually.`);return cc(t),{path:t,alreadyInstalled:!0}}function vc(n){return/^\/\/ version:\s*(.+)$/m.exec(n)?.[1]?.trim()}function D1(n){let t=Cn(n.homeDir),e=(()=>{try{return uc(t)}catch{return}})();if(!e)return{platform:"amp",status:"n/a",configPath:t};if(e.isSymbolicLink()||!e.isFile())return{platform:"amp",status:"n/a",configPath:t,errors:[`${t} is a symlink or not a regular file; move or remove it before installing`]};let r;try{r=pc(t,"utf-8")}catch(l){return{platform:"amp",status:"n/a",configPath:t,errors:[`Failed to read ${t}: ${l instanceof Error?l.message:String(l)}`]}}if(!r.startsWith(hn))return{platform:"amp",status:"n/a",configPath:t,errors:[`Unmanaged file occupies ${t}; move or remove it before installing`]};let a=vc(r)!==z();return{platform:"amp",status:"configured",method:"plugin file",configPath:t,errors:a?["Installed Amp plugin is outdated; run install --amp to update"]:void 0}}import{existsSync as fc,readFileSync as hc}from"node:fs";import{join as bc}from"node:path";function yn(n){return bc(n,".gemini","config","hooks.json")}var yc=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*(?:--agy-cli|-ac)(\s|["']|$)/;function wc(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"||!yc.test(s))return[];return[{command:s,enabled:e.enabled!==!1}]})})})}function k1(n){let t=yn(n.homeDir);if(!fc(t))return{platform:"antigravity-cli",status:"n/a",configPath:t};let e;try{e=wc(JSON.parse(hc(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 q1}from"node:path";import{existsSync as xc,lstatSync as mc,readFileSync as gc}from"node:fs";function n2(n,t=(e)=>e){if(!xc(n))return{kind:"missing"};try{return{kind:"ok",value:JSON.parse(t(gc(n,"utf-8")))}}catch{return{kind:"unreadable"}}}function Y(n){try{return mc(n)}catch{return}}function Gn(n,t){let e=Y(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 g(n,t){return typeof n==="object"&&n!==null?n[t]:void 0}var ie="cc-safety-net@cc-marketplace";function j1(n){return q1(n,".claude","plugins","installed_plugins.json")}function F1(n,t){let e=g(g(n,"plugins"),t);return Array.isArray(e)&&e.length>0}function Un(n,t){let e=n2(j1(n));return e.kind==="ok"&&F1(e.value,t)}function Le(n){let t=j1(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(!F1(e.value,ie))return{platform:"claude-code",status:"n/a"};let r=q1(n,".claude","settings.json"),a=n2(r);if(a.kind==="unreadable")return{platform:"claude-code",status:"not-inspected"};if(!(a.kind==="ok"&&g(g(a.value,"enabledPlugins"),ie)===!0))return{platform:"claude-code",status:"disabled",method:"plugin config",configPath:r,errors:[`${ie} is installed but not enabled in Claude Code`]};return{platform:"claude-code",status:"configured",method:"plugin config",configPath:t}}function z1(n){return Le(n.homeDir)}function B1(n){if(!n.codexPluginListOutput)return{platform:"codex",status:"n/a"};let t=n.codexPluginListOutput.split(`
|
|
28
|
+
`).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 En,readdirSync as $c,readFileSync as Dc}from"node:fs";import{join as W}from"node:path";var t2="cc-safety-net@cc-marketplace",On=["cc-marketplace","cc-safety-net"],J1=["_direct","copilot-safety-net"],S1=["cc-marketplace","safety-net"],Z1="safety-net@cc-marketplace";function Tn(n,t){let e=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`(^|[^a-z0-9-])${e}([^a-z0-9-]|$)`,"m").test(n??"")}function Q1(n){return Tn(n,"cc-safety-net@cc-marketplace")}function X1(n){return Tn(n,"cc-marketplace")}function Y1(n){return Tn(n,"copilot-safety-net")}function R1(n){return Tn(n,"safety-net@cc-marketplace")}function M(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]!==`
|
|
29
|
+
`)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 oe(n){if(!n?.includes("cc-safety-net"))return!1;return/(^|\s)hook\s+(?:[^\s]+\s+)*(--copilot-cli|-cp)(\s|$)/.test(n)}function H1(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 kc(n){return H1(n,[0,0,422])}function qc(n){return H1(n,[1,0,8])}function wn(n){return process.env.COPILOT_HOME||W(n,".copilot")}function pe(n){return(n.hooks?.preToolUse??[]).some((e)=>{if(e.type!=="command")return!1;return oe(e.command)||oe(e.bash)||oe(e.powershell)})}function ve(n,t){try{return JSON.parse(M(Dc(n,"utf-8")))}catch(e){t?.push(`Failed to parse ${n}: ${e instanceof Error?e.message:String(e)}`);return}}function M1(n,t){try{return $c(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 jc(n,t){if(!En(n))return[];let e=[];for(let r of M1(n,t)){let a=W(n,r),l=ve(a,t);if(l&&pe(l))e.push(a)}return e}function ue(n,t){if(!En(n))return;let e=ve(n,t);if(!e)return;return{path:n,config:e}}function A1(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 Fc(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 zc(n,t,e,r){let a=wn(n),l=W(t,".github","hooks"),d=W(a,"hooks"),s=W(t,".github","copilot"),c=qc(e),i=c===!0?r:void 0,L={userConfig:ue(W(a,"config.json"),i),repoSettings:ue(W(s,"settings.json"),i),localSettings:ue(W(s,"settings.local.json"),i)};if(c!==!1){let x=Fc(L);if(x){if(c===null)r.push(`GitHub Copilot CLI version unavailable; treating disableAllHooks in ${x} as active`);return{activeConfigPaths:[],disabledBy:x}}}let u=jc(l,r),p=kc(e),o=p===!0?r:void 0,b=En(d)?M1(d,o):[],v=[];for(let x of b){let y=W(d,x),J=ve(y,o);if(J&&pe(J))v.push(y)}if(p!==!0&&v.length>0)A1(r,e,`user hook files in ${d}`,"0.0.422"),v.length=0;let f=[],w=[L.localSettings,L.repoSettings,L.userConfig];for(let x of w){if(!x)continue;if(!pe(x.config))continue;if(c===!0){f.push(x.path);continue}A1(r,e,"inline hook definitions in Copilot config files","1.0.8");break}return{activeConfigPaths:[...f.filter((x)=>x.endsWith("settings.local.json")),...f.filter((x)=>x.endsWith("settings.json")),...u,...f.filter((x)=>x.endsWith("config.json")),...v]}}function W1(n){let t=[],e=zc(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=wn(n.homeDir),a=W(r,"installed-plugins",...On),l=En(a),d=W(r,"settings.json"),s=n2(d,M);if(l&&s.kind==="unreadable")return{platform:"copilot-cli",status:"not-inspected"};if(l&&s.kind==="ok"&&g(g(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 Rc,readFileSync as Ac}from"node:fs";import{existsSync as V1,mkdirSync as Bc,readFileSync as Jc}from"node:fs";import{dirname as Sc,join as Zc}from"node:path";var xn="npx -y cc-safety-net hook --cursor",K1=30;function Pn(n){return Zc(n,".cursor","hooks.json")}function $2(n){return typeof n==="object"&&n!==null&&!Array.isArray(n)}function be(){return{command:xn,timeout:K1,failClosed:!0}}function _n(n){return $2(n)&&n.command===xn}function Qc(n){return Object.keys(n).length===3&&n.command===xn&&n.timeout===K1&&n.failClosed===!0}function Xc(n){try{return JSON.parse(Jc(n,"utf-8"))}catch(t){if(t instanceof SyntaxError)throw Error(`Failed to parse Cursor hooks config ${n}: ${t.message}`);throw t}}function C1(n){let t=Xc(n);if(!$2(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&&!$2(t.hooks))throw Error(`Cursor hooks config ${n} "hooks" must be an object`);let e=$2(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 G1(n){let t=$2(n.hooks)?n.hooks.preToolUse:void 0;return Array.isArray(t)?t:[]}function Yc(n){if(!n.some(_n))return[...n,be()];return n.reduce((t,e)=>{if(!_n(e))return t.result.push(e),t;if(!t.inserted)t.result.push(be()),t.inserted=!0;return t},{result:[],inserted:!1}).result}function U1(n,t,e){let r=$2(t.hooks)?t.hooks:{},a={...t,hooks:{...r,preToolUse:e}};B(n,`${JSON.stringify(a,null,2)}
|
|
30
|
+
`)}function O1(n){let t=Pn(n);if(!V1(t))return Bc(Sc(t),{recursive:!0}),B(t,`${JSON.stringify({version:1,hooks:{preToolUse:[be()]}},null,2)}
|
|
31
|
+
`),{path:t,alreadyInstalled:!1};let e=C1(t),r=G1(e),a=r.filter(_n);if($2(e.hooks)&&Array.isArray(e.hooks.preToolUse)&&a.length===1&&a[0]!==void 0&&Qc(a[0]))return{path:t,alreadyInstalled:!0};return U1(t,e,Yc(r)),{path:t,alreadyInstalled:!1}}function T1(n){let t=Pn(n);if(!V1(t))return{path:t,alreadyInstalled:!1};let e=C1(t),r=G1(e),a=r.filter((l)=>!_n(l));if(a.length===r.length)return{path:t,alreadyInstalled:!1};return U1(t,e,a),{path:t,alreadyInstalled:!0}}function Hc(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===xn)}function Mc(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 E1(n){let t=Pn(n.homeDir);if(!Rc(t))return{platform:"cursor",status:"n/a",configPath:t};let e;try{e=JSON.parse(Ac(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=Hc(e);if(r.length===0)return{platform:"cursor",status:"n/a",configPath:t};let a=Mc(r);return{platform:"cursor",status:"configured",method:"hook config",configPath:t,errors:a.length>0?a:void 0}}import{existsSync as Wc}from"node:fs";import{join as fe}from"node:path";var he="gemini-safety-net";function ye(n){let t=fe(n,".gemini","extensions"),e=fe(t,he);if(!Wc(e))return{platform:"gemini-cli",status:"n/a"};let r=fe(t,"extension-enablement.json"),a=n2(r);if(a.kind==="unreadable")return{platform:"gemini-cli",status:"not-inspected"};let l=a.kind==="ok"?g(g(a.value,he),"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:[`${he} is disabled in Gemini CLI`]};return{platform:"gemini-cli",status:"configured",method:"extension config",configPath:e}}function _1(n){return ye(n.homeDir)}import{readFileSync as l0}from"node:fs";import{join as d0}from"node:path";var V="cc-safety-net",P1="# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent";function I1(n){return`# cc-safety-net managed Hermes Agent plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --hermes-agent
|
|
32
32
|
# version: ${n}
|
|
33
|
-
`}function
|
|
33
|
+
`}function Vc(n){return`${I1(n)}name: cc-safety-net
|
|
34
34
|
version: "${n}"
|
|
35
35
|
description: "Block destructive commands and secret-file access before Hermes runs a tool."
|
|
36
36
|
author: "cc-safety-net"
|
|
37
37
|
provides_hooks:
|
|
38
38
|
- pre_tool_call
|
|
39
|
-
`}function
|
|
39
|
+
`}function Kc(n){return`${I1(n)}"""CC Safety Net guard for Hermes Agent.
|
|
40
40
|
|
|
41
41
|
Registers pre_tool_call and forwards the tool call to the packaged CC Safety Net
|
|
42
42
|
adapter (cc-safety-net hook --hermes-agent) over JSON stdin. The adapter prints nothing
|
|
@@ -168,65 +168,65 @@ def _pre_tool_call(tool_name="", args=None, session_id="", task_id="", **_):
|
|
|
168
168
|
|
|
169
169
|
def register(ctx):
|
|
170
170
|
ctx.register_hook("pre_tool_call", _pre_tool_call)
|
|
171
|
-
`}function mn(n){return[{name:"__init__.py",content:
|
|
172
|
-
`)}function
|
|
173
|
-
`);if(e.error)throw Error(
|
|
174
|
-
${r}`.trim()));if(e.status!==0)throw Error(i0(n,e.status,r));return t?.stdoutOnly?e.stdout:r}function qe(n){n.forEach((t)=>{c2(t)})}var c0=k2("openclaw",q),dc=[K,T2,_2];function o0(n){let t=process.env.OPENCLAW_STATE_DIR?.trim();if(t)return t;let e=process.env.OPENCLAW_CONFIG_PATH?.trim();return e?L0(e):k2(n,".openclaw")}function u0(n){let t=process.env.OPENCLAW_CONFIG_PATH?.trim();return t?t:k2(o0(n),"openclaw.json")}function je(n){return k2(o0(n),"extensions",q)}function sc(n){let t=rc(n);if(t.length===0)return!0;if(t.some((a)=>!dc.includes(a)))return!1;let e=k2(n,K),r=R(e);return r!==void 0&&!r.isSymbolicLink()&&r.isFile()&&ac(e,"utf-8").startsWith(In)}function Fe(n){let t=je(n),e=R(t);if(!e)return;if(!e.isSymbolicLink()&&e.isDirectory()&&sc(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 p0(){let n=L0(lc(import.meta.url));return[k2(n,"..",c0),k2(n,"..","..","..","dist",c0)]}function ze(n=p0()){return n.find((t)=>tc(t)&&ec(t).isDirectory())}function ic(n=p0()){let t=ze(n);if(!t)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return t}function v0(n=ic()){return[["openclaw","plugins","install",n,"--force"],["openclaw","plugins","enable",q]]}function cc(n){let t=(()=>{try{return JSON.parse(n)}catch{return}})(),e=g(g(t,"plugin"),"status");return typeof e==="string"?e:void 0}function b0(){let n=cc(c2(["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 Nn="openclaw",gn=`run \`openclaw plugins enable ${q}\``;function E2(n,t){let e=$n(n,t),r=R(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:h0(e,"utf-8")}}catch(a){return{error:`Failed to read ${e}: ${a instanceof Error?a.message:String(a)}`}}}function y0(n){try{return JSON.parse(C(n))}catch{return}}function Lc(n){let t=E2(n,T2);if("error"in t)return t.error;if(g(y0(t.content),"id")===q)return;return`${$n(n,T2)} is not a valid ${q} manifest; run install --openclaw`}function oc(n){let t=E2(n,_2);if("error"in t)return t.error;let e=g(g(y0(t.content),"openclaw"),"extensions");if(Array.isArray(e)&&e.includes(`./${K}`))return;return`${$n(n,_2)} does not point OpenClaw at ${K}; run install --openclaw`}function f0(n){return Array.isArray(n)?n.filter((t)=>typeof t==="string"):[]}function uc(n){let t=u0(n);if(!R(t))return`${q} is not enabled; ${gn}`;let e=(()=>{try{return JSON.parse(C(h0(t,"utf-8")))}catch{return}})();if(e===void 0)return`Failed to read ${t}; fix it, then ${gn}`;let r=g(e,"plugins");if(g(r,"enabled")===!1)return`plugins.enabled is false in ${t}; no OpenClaw plugin loads`;let a=g(g(g(r,"entries"),q),"enabled");if(f0(g(r,"deny")).includes(q)||a===!1)return`${q} is disabled in ${t}; ${gn}`;let l=f0(g(r,"allow"));if(l.length>0&&!l.includes(q))return`plugins.allow in ${t} does not list ${q}; add it, then ${gn}`;if(l.includes(q)||a===!0)return;return`${q} is not enabled; ${gn}`}function w0(n){return/^\/\/ version:\s*(.+)$/m.exec(n)?.[1]?.trim()}function pc(n,t,e){if(e===void 0)return[];let r=E2(e,K);if("error"in r||w0(r.content)!==t)return[];return[K,T2,_2].flatMap((a)=>{let l=E2(n,a),d=E2(e,a);if("error"in l||"error"in d||l.content===d.content)return[];return[`Modified ${a} occupies ${$n(n,a)}; run install --openclaw to restore it`]})}function x0(n){let t=je(n.homeDir),e=Gn(Nn,t);if(e)return e;let r=E2(t,K),l=["error"in r?r.error:r.content.startsWith(In)?void 0:`Unmanaged ${K} occupies ${$n(t,K)}; move or remove it`,Lc(t),oc(t)].filter((L)=>L!==void 0),d="content"in r?w0(r.content):void 0,s=l.length>0?l:pc(t,d,ze());if(s.length>0)return{platform:Nn,status:"n/a",configPath:t,errors:s};let i=d===z()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],c=uc(n.homeDir);if(c)return{platform:Nn,status:"disabled",method:"plugin directory",configPath:t,errors:[c,...i]};return{platform:Nn,status:"configured",method:"plugin directory",configPath:t,errors:i.length>0?i:void 0}}import{existsSync as vc,readFileSync as bc}from"node:fs";import{join as m0}from"node:path";function g0(n){let t=[],e=m0(n.homeDir,".config","opencode"),r=["opencode.json","opencode.jsonc"];for(let a of r){let l=m0(e,a);if(vc(l))try{let d=bc(l,"utf-8"),s=C(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 fc}from"node:path";function Be(n){return fc(n,".pi","agent","settings.json")}function Je(n){if(typeof n!=="string")return!1;return n==="npm:cc-safety-net"||n.startsWith("npm:cc-safety-net@")}function $0(n){let t=Be(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=g(e.value,"packages");if(!Array.isArray(r))return{platform:"pi",status:"n/a"};let a=r.find((s)=>Je(typeof s==="string"?s:g(s,"source")));if(a===void 0)return{platform:"pi",status:"n/a"};let l=g(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 yc={amp:D1,"antigravity-cli":k1,"claude-code":z1,codex:B1,"copilot-cli":A1,cursor:U1,"gemini-cli":O1,"hermes-agent":l0,"kimi-code":s0,openclaw:x0,opencode:g0,pi:$0};function P2(n,t){let e={...t,cwd:n,homeDir:t?.homeDir??hc()};return fa.map((r)=>wc(yc[r](e)))}function wc(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 xc}from"node:os";import{join as mc}from"node:path";var gc=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}]),$c=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([])})})}),Dc={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 D0(){let n=mc(xc(),"cc-safety-net-self-test"),t=gc.map((e)=>{let r=Zn(H2("self-test",{command:e.command},{kind:"command",shell:"auto"},{configCwd:n,executionCwd:n},e.command),{guard:{dependencies:{loadPolicySnapshot:()=>$c,getModes:()=>Dc,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 Se(n){let t=j({label:"doctor",booleans:{json:["--json"],skipUpdateCheck:["--skip-update-check"]}},n);if(e2(t.errors))return null;return{json:t.flags.json,skipUpdateCheck:t.flags.skipUpdateCheck}}async function k0(n={}){let t=await Wn(!n.json,()=>{let e=kc(n);return{ready:e,finish:()=>e}},()=>Mn(),{loadingMessage:"Checking system status…"});if(n.json)console.log(JSON.stringify(t,null,2));else jc(t);return qc(t.hooks,t.engineSelfTest,{userConfig:t.userConfig,projectConfig:t.projectConfig})?1:0}async function kc(n){let t=n.cwd??process.cwd(),e=await bn(),r=P2(t,{codexPluginListOutput:e.codexPluginListOutput,copilotCliVersion:e.copilotCliVersion}),a=Ma(t),l=Wa(),d=H({cwd:t}),s=d.policy,i=l2(s),c=w2(s,i.capabilities),L=Yn(7),u=n.skipUpdateCheck?{currentVersion:z(),latestVersion:null,updateAvailable:!1}:await U2(),p={hooks:r,engineSelfTest:D0(),userConfig:a.userConfig,projectConfig:a.projectConfig,configState:on(d),effectiveRules:a.effectiveRules,shadowedRules:a.shadowedRules,environment:l,effectiveSafety:{selectedPreset:s.safety.level??"standard",level:i.effectiveLevel,capabilities:i.capabilities,ruleOverrides:s.destructiveCommandRuleOverrides,weakenedRuleOverrides:Object.entries(c).filter(([,o])=>o.source==="rule_override"&&o.override==="off"&&o.inheritedEnabled&&o.changesInherited).map(([o])=>o),ruleCounts:{stored:Object.keys(s.destructiveCommandRuleOverrides).length,effective:Object.values(c).filter((o)=>o.changesInherited).length}},posture:e1(a.userConfig.path),activity:L,update:u,system:e};return{...p,findings:Va(p)}}function qc(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 jc(n){console.log(),console.log(Ua(n.hooks)),console.log(),console.log(Oa(n.engineSelfTest)),console.log(),console.log(Ta(n)),console.log(),console.log(_a(n.environment)),console.log(),console.log(Ea(n)),console.log(),console.log(Pa(n.findings)),console.log(),console.log(Ia(n.activity)),console.log(),console.log(n1(n.system)),console.log(),console.log(Na(n.update)),console.log(t1(n))}import{existsSync as Fc}from"node:fs";var zc=/^[A-Za-z0-9_@%+=:,./-]+$/,q0="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Ze(n){let t=j({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},n);if(e2(t.errors))return console.error(q0),console.error("Pass -- before a command that starts with dashes."),null;if(t.values.cwd!==void 0&&!Fc(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)=>zc.test(r)?r:`'${r.replaceAll("'","'\\''")}'`).join(" ");if(!e)return console.error("Error: No command provided"),console.error(q0),null;return{json:t.flags.json,cwd:t.values.cwd,command:e}}function j0(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 F0(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 Qe(n){return JSON.stringify(n)}function z0(n,t=0){return`[${n.map((r,a)=>Ga(r,a,t)).join(",")}]`}function nt(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 B0(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: ${Qe(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: ${Qe(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: ${Qe(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: ${D.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 Xe(n,t){let e=j0(t?.asciiOnly??!1),r=58,a=[],l=1;a.push(...F0(e,58)),a.push("");let d=n.trace.steps.find((o)=>o.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"?h.red("BLOCKED"):h.green("ALLOWED")}`),a.push(""),a.push("CONFIG");let o=n.configSource??"none";return a.push(` Path: ${o}`),a.join(`
|
|
175
|
-
`)}let s=n.trace.steps.find((o)=>o.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 o=0;o<s.segments.length;o++){let b=s.segments[o];if(b){let v=Math.random();a.push(` Segment ${o+1}: ${
|
|
176
|
-
`)}function
|
|
177
|
-
`))}function
|
|
178
|
-
`))}function
|
|
179
|
-
`)}function
|
|
171
|
+
`}function mn(n){return[{name:"__init__.py",content:Kc(n)},{name:"plugin.yaml",content:Vc(n)}]}import{mkdirSync as Cc,readdirSync as Gc,readFileSync as Uc,rmSync as we}from"node:fs";import{join as D2}from"node:path";var Oc="__pycache__";function xe(n){let t=process.env.HERMES_HOME?.trim();return t?t:D2(n,".hermes")}function me(n){return D2(xe(n),"plugins",V)}function ge(n){return n.startsWith(P1)}function $e(n,t){let e=me(n),r=Y(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 N1(n,t){let e=Y(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=Uc(n,"utf-8");if(!ge(r))throw Error(`Refusing to ${t} unmanaged file at ${n}. Move or remove it.`);return r}function n0(n){let t=$e(n,"install"),e=mn(z());if(e.map((a)=>N1(D2(t,a.name),"overwrite")).every((a,l)=>a===e[l]?.content))return{path:t,alreadyInstalled:!0};return Cc(t,{recursive:!0}),e.forEach((a)=>{B(D2(t,a.name),a.content)}),{path:t,alreadyInstalled:!1}}function De(n){let t=$e(n,"remove");if(!Y(t))return[];return mn(z()).filter((e)=>N1(D2(t,e.name),"remove")!==void 0)}function t0(n){let t=$e(n,"remove");if(!Y(t))return{path:t,alreadyInstalled:!1};let e=De(n);if(e.forEach((r)=>{we(D2(t,r.name))}),we(D2(t,Oc),{recursive:!0,force:!0}),Gc(t).length===0)we(t,{recursive:!0});return{path:t,alreadyInstalled:e.length>0}}var In="hermes-agent",e0=/^([^\s#][^:]*):/,Tc=/^\s+([A-Za-z_][\w-]*):/,r0=/^\s+-\s*(.*)$/;function Ec(n){return n.trim().replace(/^(["'])(.*)\1$/,"$2")}function _c(n){let t=n.split(/\r?\n/),e=t.findIndex((l)=>e0.exec(l)?.[1]?.trim()==="plugins");if(e===-1)return[];let r=t.slice(e+1),a=r.findIndex((l)=>e0.test(l));return a===-1?r:r.slice(0,a)}function a0(n,t){let e=_c(n),r=e.findIndex((d)=>Tc.exec(d)?.[1]===t);if(r===-1)return[];let a=e.slice(r+1),l=a.findIndex((d)=>!r0.test(d));return(l===-1?a:a.slice(0,l)).map((d)=>Ec(r0.exec(d)?.[1]??""))}function Pc(n){try{return l0(d0(xe(n),"config.yaml"),"utf-8")}catch{return}}function ke(n){let t=Pc(n)??"";return a0(t,"enabled").includes(V)&&!a0(t,"disabled").includes(V)}function s0(n){return/^# version:\s*(.+)$/m.exec(n)?.[1]?.trim()}function Ic(n,t){let e=Y(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=l0(n,"utf-8");if(!ge(r))return{error:`Unmanaged ${t.name} occupies ${n}; move or remove it`};if(s0(r)===z()&&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 c0(n){let t=me(n.homeDir),e=Gn(In,t);if(e)return e;let r=mn(z()).map((s)=>Ic(d0(t,s.name),s)),a=r.flatMap((s)=>("error"in s)?[s.error]:[]);if(a.length>0)return{platform:In,status:"n/a",configPath:t,errors:a};let l=r.some((s)=>("content"in s)&&s0(s.content)!==z()),d=l?["Installed Hermes Agent plugin is outdated; run install --hermes-agent to update"]:[];if(!ke(n.homeDir))return{platform:In,status:"disabled",method:"plugin directory",configPath:t,errors:[`${V} is not enabled in Hermes; run \`hermes plugins enable ${V}\``,...d]};return{platform:In,status:"configured",method:"plugin directory",configPath:t,errors:l?d:void 0}}import{existsSync as Nc,readFileSync as ni}from"node:fs";import{join as i0}from"node:path";var ti=/cc-safety-net\s+hook\s+(?:[^\s]+\s+)*--kimi-code(\s|["']|$)/;function ei(n){return i0(process.env.KIMI_CODE_HOME||i0(n,".kimi-code"),"config.toml")}function L0(n){let t=ei(n.homeDir);if(!Nc(t))return{platform:"kimi-code",status:"n/a",configPath:t};try{if(!ti.test(ni(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 m0}from"node:fs";import{join as $n}from"node:path";var q="cc-safety-net",K="index.js",T2="openclaw.plugin.json",E2="package.json";var Nn="// cc-safety-net managed OpenClaw plugin. Do not edit. Reinstall with: npx -y cc-safety-net install --openclaw";import{existsSync as li,lstatSync as di,readdirSync as si,readFileSync as ci}from"node:fs";import{dirname as v0,join as k2}from"node:path";import{fileURLToPath as ii}from"node:url";import{spawnSync as ri}from"node:child_process";function ai(n){return n.join(" ")}function o0(n,t,e){return[`Failed to run ${ai(n)}${t===null?"":` (exit ${t})`}.`,e.trim()].filter(Boolean).join(`
|
|
172
|
+
`)}function e2(n,t){let e=ri(n[0],n.slice(1),{encoding:"utf-8",stdio:"pipe"}),r=[e.stdout,e.stderr].filter(Boolean).join(`
|
|
173
|
+
`);if(e.error)throw Error(o0(n,null,`${e.error.message}
|
|
174
|
+
${r}`.trim()));if(e.status!==0)throw Error(o0(n,e.status,r));return t?.stdoutOnly?e.stdout:r}function qe(n){n.forEach((t)=>{e2(t)})}function u0(n){n.forEach((t)=>{try{e2(t)}catch(e){console.warn(e instanceof Error?e.message:String(e))}})}var p0=k2("openclaw",q),Li=[K,T2,E2];function b0(n){let t=process.env.OPENCLAW_STATE_DIR?.trim();if(t)return t;let e=process.env.OPENCLAW_CONFIG_PATH?.trim();return e?v0(e):k2(n,".openclaw")}function f0(n){let t=process.env.OPENCLAW_CONFIG_PATH?.trim();return t?t:k2(b0(n),"openclaw.json")}function je(n){return k2(b0(n),"extensions",q)}function oi(n){let t=si(n);if(t.length===0)return!0;if(t.some((a)=>!Li.includes(a)))return!1;let e=k2(n,K),r=Y(e);return r!==void 0&&!r.isSymbolicLink()&&r.isFile()&&ci(e,"utf-8").startsWith(Nn)}function Fe(n){let t=je(n),e=Y(t);if(!e)return;if(!e.isSymbolicLink()&&e.isDirectory()&&oi(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 h0(){let n=v0(ii(import.meta.url));return[k2(n,"..",p0),k2(n,"..","..","..","dist",p0)]}function ze(n=h0()){return n.find((t)=>li(t)&&di(t).isDirectory())}function ui(n=h0()){let t=ze(n);if(!t)throw Error("Packaged OpenClaw plugin directory not found. Reinstall cc-safety-net and try again.");return t}function y0(n=ui()){return[["openclaw","plugins","install",n,"--force"],["openclaw","plugins","enable",q]]}function pi(n){let t=(()=>{try{return JSON.parse(n)}catch{return}})(),e=g(g(t,"plugin"),"status");return typeof e==="string"?e:void 0}function w0(){let n=pi(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 nt="openclaw",gn=`run \`openclaw plugins enable ${q}\``;function _2(n,t){let e=$n(n,t),r=Y(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:m0(e,"utf-8")}}catch(a){return{error:`Failed to read ${e}: ${a instanceof Error?a.message:String(a)}`}}}function g0(n){try{return JSON.parse(M(n))}catch{return}}function vi(n){let t=_2(n,T2);if("error"in t)return t.error;if(g(g0(t.content),"id")===q)return;return`${$n(n,T2)} is not a valid ${q} manifest; run install --openclaw`}function bi(n){let t=_2(n,E2);if("error"in t)return t.error;let e=g(g(g0(t.content),"openclaw"),"extensions");if(Array.isArray(e)&&e.includes(`./${K}`))return;return`${$n(n,E2)} does not point OpenClaw at ${K}; run install --openclaw`}function x0(n){return Array.isArray(n)?n.filter((t)=>typeof t==="string"):[]}function fi(n){let t=f0(n);if(!Y(t))return`${q} is not enabled; ${gn}`;let e=(()=>{try{return JSON.parse(M(m0(t,"utf-8")))}catch{return}})();if(e===void 0)return`Failed to read ${t}; fix it, then ${gn}`;let r=g(e,"plugins");if(g(r,"enabled")===!1)return`plugins.enabled is false in ${t}; no OpenClaw plugin loads`;let a=g(g(g(r,"entries"),q),"enabled");if(x0(g(r,"deny")).includes(q)||a===!1)return`${q} is disabled in ${t}; ${gn}`;let l=x0(g(r,"allow"));if(l.length>0&&!l.includes(q))return`plugins.allow in ${t} does not list ${q}; add it, then ${gn}`;if(l.includes(q)||a===!0)return;return`${q} is not enabled; ${gn}`}function $0(n){return/^\/\/ version:\s*(.+)$/m.exec(n)?.[1]?.trim()}function hi(n,t,e){if(e===void 0)return[];let r=_2(e,K);if("error"in r||$0(r.content)!==t)return[];return[K,T2,E2].flatMap((a)=>{let l=_2(n,a),d=_2(e,a);if("error"in l||"error"in d||l.content===d.content)return[];return[`Modified ${a} occupies ${$n(n,a)}; run install --openclaw to restore it`]})}function D0(n){let t=je(n.homeDir),e=Gn(nt,t);if(e)return e;let r=_2(t,K),l=["error"in r?r.error:r.content.startsWith(Nn)?void 0:`Unmanaged ${K} occupies ${$n(t,K)}; move or remove it`,vi(t),bi(t)].filter((L)=>L!==void 0),d="content"in r?$0(r.content):void 0,s=l.length>0?l:hi(t,d,ze());if(s.length>0)return{platform:nt,status:"n/a",configPath:t,errors:s};let c=d===z()?[]:["Installed OpenClaw plugin is outdated; run install --openclaw to update"],i=fi(n.homeDir);if(i)return{platform:nt,status:"disabled",method:"plugin directory",configPath:t,errors:[i,...c]};return{platform:nt,status:"configured",method:"plugin directory",configPath:t,errors:c.length>0?c:void 0}}import{existsSync as yi,readFileSync as wi}from"node:fs";import{join as k0}from"node:path";function q0(n){let t=[],e=k0(n.homeDir,".config","opencode"),r=["opencode.json","opencode.jsonc"];for(let a of r){let l=k0(e,a);if(yi(l))try{let d=wi(l,"utf-8"),s=M(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 Be(n){return xi(n,".pi","agent","settings.json")}function Je(n){if(typeof n!=="string")return!1;return n==="npm:cc-safety-net"||n.startsWith("npm:cc-safety-net@")}function j0(n){let t=Be(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=g(e.value,"packages");if(!Array.isArray(r))return{platform:"pi",status:"n/a"};let a=r.find((s)=>Je(typeof s==="string"?s:g(s,"source")));if(a===void 0)return{platform:"pi",status:"n/a"};let l=g(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 gi={amp:D1,"antigravity-cli":k1,"claude-code":z1,codex:B1,"copilot-cli":W1,cursor:E1,"gemini-cli":_1,"hermes-agent":c0,"kimi-code":L0,openclaw:D0,opencode:q0,pi:j0};function P2(n,t){let e={...t,cwd:n,homeDir:t?.homeDir??mi()};return fa.map((r)=>$i(gi[r](e)))}function $i(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 Di}from"node:os";import{join as ki}from"node:path";var qi=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}]),ji=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([])})})}),Fi={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 F0(){let n=ki(Di(),"cc-safety-net-self-test"),t=qi.map((e)=>{let r=Zn(H2("self-test",{command:e.command},{kind:"command",shell:"auto"},{configCwd:n,executionCwd:n},e.command),{guard:{dependencies:{loadPolicySnapshot:()=>ji,getModes:()=>Fi,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 Se(n){let t=j({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 z0(n={}){let t=await Vn(!n.json,()=>{let e=zi(n);return{ready:e,finish:()=>e}},()=>Wn(),{loadingMessage:"Checking system status…"});if(n.json)console.log(JSON.stringify(t,null,2));else Ji(t);return Bi(t.hooks,t.engineSelfTest,{userConfig:t.userConfig,projectConfig:t.projectConfig})?1:0}async function zi(n){let t=n.cwd??process.cwd(),e=await bn(),r=P2(t,{codexPluginListOutput:e.codexPluginListOutput,copilotCliVersion:e.copilotCliVersion}),a=Wa(t),l=Va(),d=H({cwd:t}),s=d.policy,c=d2(s),i=w2(s,c.capabilities),L=Rn(7),u=n.skipUpdateCheck?{currentVersion:z(),latestVersion:null,updateAvailable:!1}:await U2(),p={hooks:r,engineSelfTest:F0(),userConfig:a.userConfig,projectConfig:a.projectConfig,configState:on(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(([,o])=>o.source==="rule_override"&&o.override==="off"&&o.inheritedEnabled&&o.changesInherited).map(([o])=>o),ruleCounts:{stored:Object.keys(s.destructiveCommandRuleOverrides).length,effective:Object.values(i).filter((o)=>o.changesInherited).length}},posture:e1(a.userConfig.path),activity:L,update:u,system:e};return{...p,findings:Ca(p)}}function Bi(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 Ji(n){console.log(),console.log(Ua(n.hooks)),console.log(),console.log(Oa(n.engineSelfTest)),console.log(),console.log(Ta(n)),console.log(),console.log(Ea(n.environment)),console.log(),console.log(_a(n)),console.log(),console.log(Pa(n.findings)),console.log(),console.log(Ia(n.activity)),console.log(),console.log(n1(n.system)),console.log(),console.log(Na(n.update)),console.log(t1(n))}import{existsSync as Si}from"node:fs";var Zi=/^[A-Za-z0-9_@%+=:,./-]+$/,B0="Usage: cc-safety-net explain [--json] [--cwd <path>] <command>";function Ze(n){let t=j({label:"explain",booleans:{json:["--json"]},values:{cwd:["--cwd"]},positionals:"tail"},n);if(r2(t.errors))return console.error(B0),console.error("Pass -- before a command that starts with dashes."),null;if(t.values.cwd!==void 0&&!Si(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)=>Zi.test(r)?r:`'${r.replaceAll("'","'\\''")}'`).join(" ");if(!e)return console.error("Error: No command provided"),console.error(B0),null;return{json:t.flags.json,cwd:t.values.cwd,command:e}}function J0(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 S0(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 Qe(n){return JSON.stringify(n)}function Z0(n,t=0){return`[${n.map((r,a)=>Ga(r,a,t)).join(",")}]`}function tt(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 Q0(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: ${Qe(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: ${Qe(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: ${Qe(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: ${D.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 Xe(n,t){let e=J0(t?.asciiOnly??!1),r=58,a=[],l=1;a.push(...S0(e,58)),a.push("");let d=n.trace.steps.find((o)=>o.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"?h.red("BLOCKED"):h.green("ALLOWED")}`),a.push(""),a.push("CONFIG");let o=n.configSource??"none";return a.push(` Path: ${o}`),a.join(`
|
|
175
|
+
`)}let s=n.trace.steps.find((o)=>o.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 o=0;o<s.segments.length;o++){let b=s.segments[o];if(b){let v=Math.random();a.push(` Segment ${o+1}: ${Z0(b,v)}`)}}}let c=n.trace.segments,i=c.length>1;for(let o of c){if(i){a.push("");let w="";if(s&&s.type==="parse"){let ht=s.segments[o.index];if(ht)w=ht.join(" ")}let x=54,y=w,J=` Segment ${o.index+1}: `,z2=" ";if(w){if(J.length+w.length+z2.length>x){let od=x-J.length-z2.length;y=`${w.substring(0,od-1)}…`}}let tn=w?`${J}${y}${z2}`:` Segment ${o.index+1} `,ft=w?`${J}${h.cyan(y)}${z2}`:tn,cr=58-tn.length,ir=Math.floor(cr/2),Ld=cr-ir;a.push(`${e.sh.repeat(ir)}${ft}${e.sh.repeat(Ld)}`)}if(o.steps.find((w)=>w.type==="segment-skipped")){a.push(""),a.push(" (skipped — prior segment blocked)");continue}let v=!1,f=!1;for(let w of o.steps){let x=Q0(w,l,e);if(x){if(f=!0,w.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}`),v=!0;continue}for(let y of x.lines)if(v)a.push(` ${e.v} ${y}`);else a.push(y);if(x.incrementStep)l++}}if(v)a.push(` ${e.v}`),a.push(` ${e.bl}${e.h.repeat(56)}`),v=!1;if(!f)a.push(""),a.push(` ${h.green("✓")} Allowed (no matching rules)`)}if(a.push(""),a.push("RESULT"),n.result==="blocked"){if(a.push(` Status: ${h.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 o=tt(n.reason," ");a.push(` Reason: ${o[0]}`);for(let b=1;b<o.length;b++)a.push(o[b]??"")}}else a.push(` Status: ${h.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 p=Object.entries(n.destructiveCommandRuleOverrides??{});if(a.push(` Rule customizations: ${p.length}`),n.ruleActivation)a.push(` Rule activation: ${n.ruleActivation.id} — ${n.ruleActivation.enabled?"on":"off"} via ${n.ruleActivation.source}`);return a.join(`
|
|
176
|
+
`)}function Ye(n){return JSON.stringify(n,null,2)}var X0="2.0.1",C=" ",q2="cc-safety-net";function Y0(n){return n.argument?`${n.flags} ${n.argument}`:n.flags}function Qi(n){return Math.max(...n.map((t)=>Y0(t).length))}function Xi(n){return Math.max(...n.map((t)=>t.usage.length))}function Yi(n){return Math.max(...n.map((t)=>`${q2} ${t.usage}`.length))}function Ri(n,t){let e=`${q2} ${n.usage}`;return`${C}${e.padEnd(t+2)}${n.description}`}function L2(n,t){return`${C}${n.padEnd(Math.max(40,n.length+2))}${t}`}function et(n,t=console.log){let e=[];if(e.push(`${q2} ${n.name}`),e.push(""),e.push(`${C}${n.description}`),e.push(""),e.push("USAGE:"),e.push(`${C}${q2} ${n.usage}`),e.push(""),n.subcommands&&n.subcommands.length>0){e.push("SUBCOMMANDS:");let r=Xi(n.subcommands);for(let a of n.subcommands)e.push(`${C}${a.usage.padEnd(r+2)}${a.description}`);e.push("")}if(n.options.length>0){e.push("OPTIONS:");let r=Qi(n.options);for(let a of n.options){let l=Y0(a),d=a.default?`${a.description} (default: ${a.default})`:a.description;e.push(`${C}${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(`${C}${r}`)}t(e.join(`
|
|
177
|
+
`))}function Re(){let n=Ha(),t=Yi(n),e=[];e.push(`${q2} v${X0}`),e.push(""),e.push("Blocks destructive commands and secret access."),e.push(""),e.push("COMMANDS:");for(let r of n)e.push(Ri(r,t));e.push(""),e.push("GLOBAL OPTIONS:"),e.push(`${C}-h, --help Show help (use with command for command-specific help)`),e.push(`${C}-V, --version Show version`),e.push(""),e.push("HELP:"),e.push(`${C}${q2} help <command> Show help for a specific command`),e.push(`${C}${q2} <command> --help Show help for a specific command`),e.push(""),e.push("ENVIRONMENT VARIABLES:"),e.push(L2(`${D.level.name}=standard|strict|paranoid`,"Set session safety level")),e.push(L2(`${D.worktree.name}=1`,"Allow local git discards in linked worktrees")),e.push(L2(`${D.debug.name}=1`,"Print diagnostic messages to stderr")),e.push(L2(`${D.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(`${D.strict.name}=1`,"Force safety.overrides.fail_closed on")),e.push(L2(`${D.paranoid.name}=1`,"Force paranoid_rm and paranoid_interpreters on")),e.push(L2(`${D.paranoidRm.name}=1`,"Force safety.overrides.paranoid_rm on")),e.push(L2(`${D.paranoidInterpreters.name}=1`,"Force safety.overrides.paranoid_interpreters on")),e.push(""),e.push("Documentation: https://ccsafetynet.com/docs"),console.log(e.join(`
|
|
178
|
+
`))}function R0(){console.log(X0)}function Dn(n,t=console.log){let e=Yn(n);if(!e)return!1;if(e.hidden||e.name.toLowerCase()!==n.toLowerCase())return!1;return et(e,t),!0}import{existsSync as _e,readFileSync as yl}from"node:fs";import{homedir as BL}from"node:os";import{join as Te}from"node:path";import*as v2 from"node:readline";function Ai(n){return n==="install"?"Install":"Uninstall"}function Hi(n){return n==="install"?"Installing":"Uninstalling"}function Mi(n){return n==="install"?"into":"from"}function H0(n){return n?.available===!0}function Wi(n,t){let e=new Set(t);return n.filter((r)=>e.has(r.target)).map((r)=>r.target)}function A0(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)=>H0(n[r]))}function Vi(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 Ki(n){return{cursor:n.findIndex((t)=>t.available),selected:[]}}function Ci(n,t,e){if(e==="confirm"||e==="update"||e==="abort"||e==="interrupt")return{state:n,done:e};if(e==="up")return{state:{...n,cursor:A0(t,n.cursor,-1)}};if(e==="down")return{state:{...n,cursor:A0(t,n.cursor,1)}};let r=t[n.cursor];if(!H0(r))return{state:n};let a=n.selected.includes(r.target)?n.selected.filter((l)=>l!==r.target):Wi(t,[...n.selected,r.target]);return{state:{...n,selected:a}}}var Gi="◉",Ui="◯",Oi=">",Ti=" ";function Ei(n,t,e,r={}){let a=r.color!==!1,l=a?h.dim:(c)=>c,d=a?h.green:(c)=>c,s=a?h.bold:(c)=>c;return["",`${Ai(n)} CC Safety Net ${Mi(n)}:`,"",...t.map((c,i)=>{let L=e.selected.includes(c.target),u=i===e.cursor,p=L?Gi:Ui,o=u?Oi:Ti,b=c.available?"":` (${c.unavailableReason??"not installed"})`,v=`${p} ${c.label}${b}`,f=!c.available?l(v):L?d(v):u?s(v):v;return`${o} ${f}`}),"",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(`
|
|
179
|
+
`)}function M0(n=process.stdin,t=process.stdout){return Boolean(n.isTTY&&t.isTTY&&typeof n.setRawMode==="function")}function W0(n,t,e={}){let r=e.input??process.stdin,a=e.output??process.stdout,l=Ki(t);v2.emitKeypressEvents(r);let d=r.isRaw===!0;r.setRawMode(!0),r.resume();let s=0,c=()=>{if(s===0)return;v2.moveCursor(a,0,-s),v2.cursorTo(a,0),v2.clearScreenDown(a)},i=()=>{c();let L=Ei(n,t,l);a.write(`${L}
|
|
180
180
|
`),s=L.split(`
|
|
181
|
-
`).length};return new Promise((L)=>{let u=()=>{r.off("keypress",o),r.setRawMode(d),r.pause(),
|
|
182
|
-
`);L(b)};function o(b,v){let f=
|
|
183
|
-
`)}function
|
|
184
|
-
`,t)+1;return/^[ \t]*/.exec(n.slice(e))?.[0]??""}function
|
|
185
|
-
`)r++;return`${n.slice(0,e)}${n.slice(r)}`}a=t.start-1;while(
|
|
186
|
-
`,e-1);if(l!==-1&&/^\s*$/.test(n.slice(l+1,e)))e=l}return`${n.slice(0,e)}${n.slice(r)}`}var kn="npx -y cc-safety-net hook --kimi-code",
|
|
181
|
+
`).length};return new Promise((L)=>{let u=()=>{r.off("keypress",o),r.setRawMode(d),r.pause(),c()},p=(b)=>{if(u(),b!=="update"&&b&&b.length>0)a.write(`${Hi(n)} selected integrations...
|
|
182
|
+
`);L(b)};function o(b,v){let f=Vi(n,b,v);if(!f)return;let w=Ci(l,t,f);if(l=w.state,w.done==="interrupt"){p(null),(e.onInterrupt??(()=>process.kill(process.pid,"SIGINT")))();return}if(w.done==="abort"){p(null);return}if(w.done==="update"){p("update");return}if(w.done==="confirm"){if(l.selected.length===0){a.write("\x07"),i();return}p([...l.selected]);return}i()}r.on("keypress",o),i()})}import{existsSync as V0,mkdirSync as _i,readFileSync as Pi}from"node:fs";import{dirname as Ii}from"node:path";var Ae="npx -y cc-safety-net hook --agy-cli",b2="cc-safety-net";function at(){return{PreToolUse:[{hooks:[{type:"command",command:Ae,timeout:30}]}]}}function K0(n){try{let t=JSON.parse(Pi(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 C0(n){let t=n[b2];if(t===void 0)return n[b2]=at(),n[b2];if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`Antigravity hooks config entry "${b2}" must be an object`);if(!Array.isArray(t.PreToolUse))t.PreToolUse=[];return t}function G0(n){if(!Array.isArray(n.PreToolUse))return!1;return n.PreToolUse.some((t)=>Array.isArray(t.hooks)&&t.hooks.some((e)=>e.command===Ae))}function Ni(n){return Object.values(n).some((t)=>t.enabled!==!1&&G0(t))}function nL(n){if(n[b2]===void 0)return!1;let t=C0(n);if(t.enabled!==!1||!G0(t))return!1;return t.enabled=!0,!0}function tL(n){if(n[b2]===void 0){n[b2]=at();return}let t=C0(n);t.PreToolUse??=[],t.enabled=!0,t.PreToolUse.push(at().PreToolUse?.[0]??{hooks:[]})}function eL(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!==Ae);if(a.length!==r.hooks.length)t=!0;return a.length===0?[]:[{...r,hooks:a}]})}return t}function rt(n,t){B(n,`${JSON.stringify(t,null,2)}
|
|
183
|
+
`)}function U0(n){let t=yn(n);if(_i(Ii(t),{recursive:!0}),!V0(t))return rt(t,{[b2]:at()}),{path:t,alreadyInstalled:!1};let e=K0(t);if(Ni(e))return{path:t,alreadyInstalled:!0};if(nL(e))return rt(t,e),{path:t,alreadyInstalled:!1};return tL(e),rt(t,e),{path:t,alreadyInstalled:!1}}function O0(n){let t=yn(n);if(!V0(t))return{path:t,alreadyInstalled:!1};let e=K0(t);if(!eL(e))return{path:t,alreadyInstalled:!1};return rt(t,e),{path:t,alreadyInstalled:!0}}import{spawn as rL,spawnSync as aL}from"node:child_process";var G=i2.map((n)=>({target:n.id,flag:n.flag,label:n.installLabel,probeCommand:n.probeCommand})),T0=new Map(G.map((n)=>[n.flag,n.target]));function He(n){let t=new Set(n);return G.map((e)=>e.target).filter((e)=>t.has(e))}function E0(n,t){n.forEach(t)}var _0=5000;function lL(n){let t=aL(n[0],n.slice(1),{env:process.env,stdio:"ignore",timeout:_0});return!t.error&&t.status===0}function We(n){return new Promise((t)=>{let e=rL(n[0],n.slice(1),{env:process.env,stdio:"ignore"}),r=!1,a=(d)=>{if(r)return;r=!0,clearTimeout(l),t(d)},l=setTimeout(()=>{e.kill(),a(!1)},_0);e.on("error",()=>a(!1)),e.on("close",(d)=>a(d===0))})}function dL(n=lL,t={}){let e=new Set(t.configuredTargets??[]);if(t.async)return Promise.all(G.map(async(a)=>({target:a.target,flag:a.flag,label:a.label,...Me(t.action,await n(a.probeCommand),e.has(a.target))})));let r=n;return G.map((a)=>({target:a.target,flag:a.flag,label:a.label,...Me(t.action,r(a.probeCommand),e.has(a.target))}))}function P0(n=We,t={}){return dL(n,{...t,async:!0})}function I0(n,t){let e=new Set(t.configuredTargets??[]);return n.map((r)=>({...r,...Me(t.action,r.available,e.has(r.target))}))}function Me(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 N0,readdirSync as sL,rmSync as cL}from"node:fs";import{join as I2}from"node:path";function Ve(n,t=process.platform){let e=I2(process.env.npm_config_cache||(t==="win32"?I2(process.env.LOCALAPPDATA||I2(n,"AppData","Local"),"npm-cache"):I2(n,".npm")),"_npx");if(!N0(e))return;sL(e).filter((r)=>N0(I2(e,r,"node_modules","cc-safety-net"))).forEach((r)=>{cL(I2(e,r),{recursive:!0,force:!0})})}import{existsSync as rl,mkdirSync as LL,readFileSync as al}from"node:fs";import{dirname as oL,join as el}from"node:path";function nl(n){return n!==void 0&&/\s/.test(n)}function iL(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 lt(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=iL(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 tl(n,t){let e=n.lastIndexOf(`
|
|
184
|
+
`,t)+1;return/^[ \t]*/.exec(n.slice(e))?.[0]??""}function dt(n,t){let{start:e,end:r,end:a}=t;while(nl(n[a]))a++;if(n[a]===","){if(r=a+1,n[r]===`
|
|
185
|
+
`)r++;return`${n.slice(0,e)}${n.slice(r)}`}a=t.start-1;while(nl(n[a]))a--;if(n[a]===","){e=a;let l=n.lastIndexOf(`
|
|
186
|
+
`,e-1);if(l!==-1&&/^\s*$/.test(n.slice(l+1,e)))e=l}return`${n.slice(0,e)}${n.slice(r)}`}var kn="npx -y cc-safety-net hook --kimi-code",Ke=`[[hooks]]
|
|
187
187
|
event = "PreToolUse"
|
|
188
|
-
command = "${kn}"`,
|
|
188
|
+
command = "${kn}"`,Ce=`{ event = "PreToolUse", command = "${kn}" }`;function ll(n){return el(process.env.KIMI_CODE_HOME??el(n,".kimi-code"),"config.toml")}function uL(n){return n.split(`
|
|
189
189
|
`).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(`
|
|
190
|
-
`)}function
|
|
191
|
-
`,t+1);return e===-1?n.length:e+1}function
|
|
192
|
-
`,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:
|
|
193
|
-
${a}${
|
|
190
|
+
`)}function pL(n,t){if(n[t]!=="#")return t;let e=n.indexOf(`
|
|
191
|
+
`,t+1);return e===-1?n.length:e+1}function vL(n,t){return lt(n,t,{skipComment:pL,stringError:"Unterminated string in Kimi Code config",bracketError:"Unmatched hooks array in Kimi Code config"})}function dl(n){let t=!1,e=0;while(e<n.length){let r=n.indexOf(`
|
|
192
|
+
`,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:vL(n,s)}}}e=r===-1?n.length:r+1}return}function bL(n,t){let e=n.slice(0,t.end).trimEnd(),r=tl(n,t.end),a=r===""?" ":`${r} `,l=!e.endsWith("[")&&!e.endsWith(",");return`${e}${l?",":""}
|
|
193
|
+
${a}${Ce}${n.slice(t.end)}`}function fL(n){let t=dl(n);if(t&&n.slice(t.start+1,t.end).trim())return bL(n,t);let e=uL(n).trimEnd();if(e==="")return`${Ke}
|
|
194
194
|
`;return`${e}
|
|
195
195
|
|
|
196
|
-
${
|
|
197
|
-
`}function
|
|
198
|
-
`),{path:t,alreadyInstalled:!1};let e=
|
|
199
|
-
`;return B(t,a),{path:t,alreadyInstalled:!0}}import{existsSync as
|
|
200
|
-
`,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
|
|
201
|
-
`));return{path:e??
|
|
202
|
-
`)},opencode:{beforeInstall:
|
|
203
|
-
`),console.log(`Enabled ${t2} plugin in ${t}`)}function
|
|
204
|
-
`),console.log(`Enabled npm:cc-safety-net extensions in ${t}`)}function
|
|
205
|
-
`))}function N2(n){let t=
|
|
206
|
-
Removing the plugin files anyway; ${
|
|
207
|
-
`))}var
|
|
208
|
-
`),0;if(r==="update")return(e.runUpdate??(()=>
|
|
196
|
+
${Ke}
|
|
197
|
+
`}function hL(n){return n.split(/(?=^\s*\[)/m).filter((e)=>!/^\s*\[\[hooks]]\s*$/m.test(e)||!e.includes(kn)).join("").trimEnd()}function yL(n,t){let e=n.indexOf(Ce,t.start);if(e===-1||e>t.end)return n;return dt(n,{start:e,end:e+Ce.length})}function sl(n){let t=ll(n);if(LL(oL(t),{recursive:!0}),!rl(t))return B(t,`${Ke}
|
|
198
|
+
`),{path:t,alreadyInstalled:!1};let e=al(t,"utf-8");if(e.includes(kn))return{path:t,alreadyInstalled:!0};return B(t,fL(e)),{path:t,alreadyInstalled:!1}}function cl(n){let t=ll(n);if(!rl(t))return{path:t,alreadyInstalled:!1};let e=al(t,"utf-8");if(!e.includes(kn))return{path:t,alreadyInstalled:!1};let r=dl(e),a=r?yL(e,r):`${hL(e)}
|
|
199
|
+
`;return B(t,a),{path:t,alreadyInstalled:!0}}import{existsSync as il,readFileSync as wL,rmSync as xL}from"node:fs";import{join as Ge}from"node:path";var Ue="cc-safety-net",mL=`${Ue}@latest`,ol=["opencode.json","opencode.jsonc"];function gL(n){return Ge(n,".config","opencode",ol[0])}function $L(n){return ol.map((t)=>Ge(n,".config","opencode",t))}function DL(n){return Ge(n,".cache","opencode","packages",mL)}function Oe(n){xL(DL(n),{recursive:!0,force:!0})}function st(n,t){if(n[t]==="/"&&n[t+1]==="/"){let e=n.indexOf(`
|
|
200
|
+
`,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 Ll(n,t){let e=t;while(e<n.length){if(/\s/.test(n[e]??"")){e++;continue}let r=st(n,e);if(r===e)return e;e=r}return e}function ul(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 pl(n,t,e){return JSON.parse(n.slice(t,e))}function kL(n,t){return lt(n,t,{skipComment:st,stringError:"Unterminated string in OpenCode config",bracketError:"Unmatched plugin array in OpenCode config"})}function qL(n){let t=0,e=0;while(e<n.length){let r=st(n,e);if(r!==e){e=r;continue}if(n[e]==='"'){let a=ul(n,e);if(t===1&&pl(n,e,a)==="plugin"){let l=Ll(n,a),d=Ll(n,l+1);if(n[l]===":"&&n[d]==="[")return{start:d,end:kL(n,d)}}e=a;continue}if(n[e]==="{"||n[e]==="[")t++;if(n[e]==="}"||n[e]==="]")t--;e++}return}function jL(n,t){let e=[],r=t.start+1;while(r<t.end){let a=st(n,r);if(a!==r){r=a;continue}if(n[r]==='"'){let l=ul(n,r),d=pl(n,r,l);if(typeof d==="string"&&d.includes(Ue))e.push({start:r,end:l});r=l;continue}r++}return e}function vl(n,t){try{return JSON.parse(M(n))}catch(e){if(e instanceof SyntaxError)throw Error(`Failed to parse OpenCode config ${t}: ${e.message}`);throw e}}function FL(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(Ue))}function zL(n,t){let e=qL(n);if(!e)throw Error(`Failed to locate OpenCode plugin array in ${t}`);let r=[...jL(n,e)].reverse().reduce(dt,n);return vl(r,t),r}function bl(n){Oe(n);let t=$L(n),e=t.find((a)=>il(a)),r=[];for(let a of t){if(!il(a))continue;try{let l=wL(a,"utf-8");if(!FL(vl(l,a)))continue;return B(a,zL(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(`
|
|
201
|
+
`));return{path:e??gL(n),alreadyInstalled:!1}}var Ee="safety-net@cc-marketplace",fl=new Set(["claude-code","codex","copilot-cli","gemini-cli","hermes-agent","openclaw","opencode","pi"]);function Pe(n){return/^\s*safety-net@cc-marketplace[^a-z0-9-][^\n]*installed,/m.test(n??"")}function wl(n){return/^\s*cc-safety-net[^a-z0-9-][^\n]*installed,/m.test(n??"")}function JL(n){return/^Marketplace `cc-marketplace`\s*$/m.test(n??"")}var xl={"claude-code":{installCommands:(n)=>{let t=Un(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"]],...Le(n).status==="disabled"?[["claude","plugin","enable","cc-safety-net@cc-marketplace"]]:[]],cleanupCommands:Un(n,Ee)?[["claude","plugin","uninstall",Ee]]:[],update:t}},uninstallCommands:[["claude","plugin","uninstall","cc-safety-net@cc-marketplace"],["claude","plugin","marketplace","remove","cc-marketplace"]]},codex:{installCommands:()=>{let n=e2(["codex","plugin","list"]),t=wl(n);return{commands:[t||JL(n)?["codex","plugin","marketplace","upgrade","cc-marketplace"]:["codex","plugin","marketplace","add","kenryu42/cc-marketplace"],["codex","plugin","add","cc-safety-net@cc-marketplace"]],cleanupCommands:Pe(n)?[["codex","plugin","remove","safety-net@cc-marketplace"]]:[],update:t}},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:()=>{let n=e2(["copilot","plugin","list"]),t=[...Y1(n)?[["copilot","plugin","uninstall","copilot-safety-net"]]:[],...R1(n)?[["copilot","plugin","uninstall",Z1]]:[]];if(Q1(n))return{commands:[["copilot","plugin","marketplace","update","cc-marketplace"],["copilot","plugin","update",t2]],cleanupCommands:t,update:!0};return{commands:[X1(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=ye(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:Fe,installCommands:()=>({commands:y0()}),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(`
|
|
202
|
+
`)},opencode:{beforeInstall:Oe,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 Ie(){return process.env.HOME??BL()}function ml(n,t=(e)=>e){try{let e=JSON.parse(t(yl(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 SL(n){let t=Te(wn(n),"settings.json");if(!_e(t))return;let e=ml(t,M),r=e.enabledPlugins;if(!r||typeof r!=="object"||Array.isArray(r))return;if(r[t2]!==!1)return;let a=yl(t,"utf-8"),l=a.replace(new RegExp(`("${t2}"\\s*:\\s*)false`),"$1true");r[t2]=!0,B(t,l!==a?l:`${JSON.stringify(e,null,2)}
|
|
203
|
+
`),console.log(`Enabled ${t2} plugin in ${t}`)}function ZL(n){let t=Be(n);if(!_e(t))return;let e=ml(t);if(!Array.isArray(e.packages))return;let r=e.packages.find((a)=>!!a&&typeof a==="object"&&!Array.isArray(a)&&Je(a.source)&&("extensions"in a));if(!r)return;delete r.extensions,B(t,`${JSON.stringify(e,null,2)}
|
|
204
|
+
`),console.log(`Enabled npm:cc-safety-net extensions in ${t}`)}function hl(n,t){let e=j({label:t,booleans:Object.fromEntries(G.map((l)=>[l.target,[l.flag]]))},n),r=e.errors[0];if(r)throw Error(r);let a=G.filter((l)=>e.flags[l.target]).map((l)=>l.target);if(a.length!==1)throw Error(`Choose exactly one ${t} target: ${[...T0.keys()].join(", ")}`);return a[0]}async function gl(n=Ie()){let[t,e]=await Promise.all([Hn(["codex","plugin","list"],30000),Hn(["copilot","--binary-version"])]);return{codexPluginListOutput:t,hooks:P2(process.cwd(),{homeDir:n,codexPluginListOutput:t,copilotCliVersion:e})}}async function QL(n){let t=await gl();return t.hooks.filter((e)=>n==="install"?e.configured:e.detected||e.inspectionStatus==="not-inspected").filter((e)=>e.platform!=="codex"||!Pe(t.codexPluginListOutput)||wl(t.codexPluginListOutput)).map((e)=>e.platform)}function XL(n,t,e){if(t.length>0)return{finish:async()=>[hl(t,n)]};if(!e.selectTargets&&!M0(e.input,e.output))return{finish:async()=>[hl(t,n)]};let r=e.detectConfiguredTargets??(()=>QL(n)),a=Promise.all([P0(e.probeTargets),r()]);return{ready:a,finish:async()=>{let[l,d]=await a,s=I0(l,{action:n,configuredTargets:d}),c=e.selectTargets?await e.selectTargets(n,s):await W0(n,s,{input:e.input,output:e.output});if(c==="update")return c;if(!c||c.length===0)return null;return He(c)}}}function j2(n,t,e=!1){let r=xl[n];r.beforeInstall?.(t);let a=typeof r.installCommands==="function"?r.installCommands(t):{commands:r.installCommands};qe(a.commands),u0(a.cleanupCommands??[]),console.log([`${a.update||e?"Updated":"Installed"} ${m2(n)} integration`,r.postInstallMessage].filter(Boolean).join(`
|
|
205
|
+
`))}function N2(n){let t=xl[n];if(!t.uninstallCommands)throw Error(`${m2(n)} uninstall is not supported`);qe(t.uninstallCommands),console.log(`Uninstalled ${m2(n)} integration`)}function YL(n){let t=bl(n);console.log(t.alreadyInstalled?`Uninstalled OpenCode plugin from ${t.path}`:`OpenCode plugin not installed in ${t.path}`)}var RL={"antigravity-cli":{install:U0,uninstall:O0},cursor:{install:O1,uninstall:T1},"kimi-code":{install:sl,uninstall:cl}};function nn(n,t,e,r=!1){if(n==="install")Ve(e);let a=RL[t][n](e),l=m2(t),d=n!=="install"?"Uninstalled":r?"Updated":"Installed";console.log(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 AL={amp:{install:g1,uninstall:$1,restartNote:'Restart Amp or run "plugins: reload" to apply the change.'},"hermes-agent":{install:n0,uninstall:t0,afterInstall:(n)=>{let t=ke(n);return e2(["hermes","plugins","enable",V,"--no-allow-tool-override"]),!t},beforeUninstall:(n)=>{De(n);try{e2(["hermes","plugins","disable",V])}catch(t){console.warn(`${t instanceof Error?t.message:String(t)}
|
|
206
|
+
Removing the plugin files anyway; ${V} may still be listed in the Hermes config.`)}},restartNote:"Restart Hermes to apply the change."}};function ct(n,t,e,r=!1){let a=AL[t];if(n==="uninstall")a.beforeUninstall?.(e);let l=n==="install"?a.install(e):a.uninstall(e),d=n==="install"&&a.afterInstall?.(e),s=m2(t),c=!d&&(n==="install"&&l.alreadyInstalled||n==="uninstall"&&!l.alreadyInstalled),L=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}`;console.log([L,c?void 0:a.restartNote].filter(Boolean).join(`
|
|
207
|
+
`))}var HL={amp:{install:(n,t)=>ct("install","amp",n,t),uninstall:(n)=>ct("uninstall","amp",n)},"antigravity-cli":{install:(n,t)=>nn("install","antigravity-cli",n,t),uninstall:(n)=>nn("uninstall","antigravity-cli",n)},"claude-code":{install:(n,t)=>j2("claude-code",n,t),uninstall:()=>N2("claude-code")},codex:{install:(n,t)=>j2("codex",n,t),uninstall:()=>N2("codex")},"copilot-cli":{install:(n,t)=>{j2("copilot-cli",n,t),SL(n)},uninstall:()=>N2("copilot-cli")},cursor:{install:(n,t)=>nn("install","cursor",n,t),uninstall:(n)=>nn("uninstall","cursor",n)},"gemini-cli":{install:(n,t)=>j2("gemini-cli",n,t),uninstall:()=>N2("gemini-cli")},"hermes-agent":{install:(n,t)=>{Ve(n),ct("install","hermes-agent",n,t)},uninstall:(n)=>ct("uninstall","hermes-agent",n)},"kimi-code":{install:(n,t)=>nn("install","kimi-code",n,t),uninstall:(n)=>nn("uninstall","kimi-code",n)},openclaw:{install:(n,t)=>{j2("openclaw",n,t),w0()},uninstall:(n)=>{Fe(n),N2("openclaw")}},opencode:{install:(n,t)=>j2("opencode",n,t),uninstall:(n)=>YL(n)},pi:{install:(n,t)=>{j2("pi",n,t),ZL(n)},uninstall:()=>N2("pi")}};function $l(n,t,e,r=!1){HL[t][n](e,r)}function ML(n){let t=j({label:"update"},n).errors[0];if(t)throw Error(t)}async function WL(n){let t=await gl(n),e=Te(wn(n),"installed-plugins");return He([...t.hooks.filter((r)=>r.platform!=="copilot-cli"&&r.detected).map((r)=>r.platform),...[On,S1,J1].flatMap((r)=>_e(Te(e,...r))?["copilot-cli"]:[]),...Un(n,Ee)?["claude-code"]:[],...Pe(t.codexPluginListOutput)?["codex"]:[]])}async function VL(){let n=Ie(),t=await WL(n);if(t.length===0)return console.log("No installed integrations found. Run `cc-safety-net install` to set one up."),0;let e=new Set(t),r=new Map(await Promise.all(G.filter((l)=>e.has(l.target)&&fl.has(l.target)).map(async(l)=>[l.target,await We(l.probeCommand)])));return t.filter((l)=>{if(fl.has(l)&&!r.get(l))return console.log(`${m2(l)} not found; skipped`),!1;try{return $l("install",l,n,!0),!1}catch(d){return console.error(nr(d)),!0}}).length>0?1:0}function Ne(n){return Promise.resolve().then(()=>ML(n)).then(VL).catch((t)=>{return console.error(nr(t)),1})}async function qn(n,t,e={}){try{let r=await Vn(!0,()=>XL(n,t,e),()=>Wn({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.
|
|
208
|
+
`),0;if(r==="update")return(e.runUpdate??(()=>Ne([])))();let a=Ie();return E0(r,(l)=>$l(n,l,a)),0}catch(r){return console.error(nr(r)),1}}function nr(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}
|
|
209
209
|
Check file permissions for the target config file and parent directory.`;if(e==="ENOENT")return`${t}
|
|
210
210
|
Check that the target config path and parent directory exist.`;if(e==="ENOTDIR")return`${t}
|
|
211
|
-
Check that every parent path component is a directory.`;return t}import{join as go}from"node:path";var xl="# 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 jn(n,t){if(!n.ok){ML(n);return}WL(n),console.log(t),console.log("Rule config synced."),console.log(""),AL(n.entries)}function AL(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} (${HL(t.ruleCount??0)})`),console.log(` Source: ${Xt(t)}`)}function HL(n){return`${n} ${n===1?"rule":"rules"}`}function gl(n,t){F2("Active sources",n.rulebooks,(e)=>[`[${e.source}] ${e.name} ${e.version}`,` Source: ${t[e.source].get(e.spec)??e.spec}`]),F2("Active rules",n.rules,(e)=>[`[${CL(n,e.name)}] ${e.name}`,` Command: ${e.subcommand?`${e.command} ${e.subcommand}`:e.command}`,` Block args: ${e.block_args.join(", ")}`,` Reason: ${e.reason}`]),F2("Disabled rules",ml(n,"off"),(e)=>[e.key]),F2("Reason overrides",ml(n,"reason"),(e)=>[e.key,` Reason: ${e.value.reason}`]),F2("Transparent wrappers",n.transparent_wrappers,(e)=>[e]),F2("Issues",n.errors,(e)=>[e]),F2("Warnings",n.warnings,(e)=>[e])}function F2(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 CL(n,t){return n.rulebooks.find((e)=>e.rules.includes(t))?.source??"project"}function ml(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 ML(n){for(let t of n.errors)console.error(t)}function WL(n){if(!n.warnings||n.warnings.length===0)return;for(let t of n.warnings)console.warn(t)}import{dirname as $l,join as it}from"node:path";var KL=".safety-net.json",VL="~/.cc-safety-net/config.json";async function ql(n){return[await Dl({legacyPath:kl({cwd:n.cwd}),configPath:_(n.cwd),defaultRulebookName:"project-rules",migratedFrom:KL,cleanup:n.cleanup,syncOptions:{cwd:n.cwd}}),await Dl({legacyPath:dn(),configPath:E(),defaultRulebookName:"user-rules",migratedFrom:VL,cleanup:n.cleanup,syncOptions:{cwd:n.cwd,global:!0}})].every((e)=>e)?0:1}async function Dl(n){let t=U(n.syncOptions),e=$(t.filesystemScope,n.legacyPath),r=m(e);if(r===null)return console.log(`No legacy config found at ${n.legacyPath}`),!0;let a=UL(r);if(!a.ok){for(let p of a.errors)console.error(p);return!1}let l=O(t.configTarget);if(l.errors.length>0){for(let p of l.errors)console.error(p);return!1}let d=l.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},s=OL($l(n.configPath),d.rules,n.defaultRulebookName,n.migratedFrom,t.filesystemScope),i=it($l(n.configPath),s,"rulebook.json"),c=$(t.filesystemScope,i),L=[tr(t.configTarget),tr(c),tr(t.lockTarget)],u=await GL(n,t.configTarget,c,s,a.config.rules,d.rules.includes(s)?d.rules:[...d.rules,s],d.overrides??{},d.transparent_wrappers??[]);if(!u.ok){EL(L);for(let p of u.errors)console.error(p);return!1}if(!n.cleanup)return console.log(`Migrated legacy config at ${n.legacyPath}. Legacy file is no longer used.`),!0;if(!_L(t.configTarget,c,s,n.migratedFrom,a.config.rules))return console.error(`Migration cleanup verification failed for ${n.legacyPath}`),!1;return an(e),console.log(`Deleted legacy config at ${n.legacyPath}`),!0}async function GL(n,t,e,r,a,l,d,s){try{return T(t,{version:1,rules:l,overrides:d,transparent_wrappers:s}),T(e,TL(r,n.migratedFrom,a)),await R2(n.syncOptions)}catch(i){return{ok:!1,errors:[i instanceof Error?i.message:String(i)]}}}function UL(n){try{let t=JSON.parse(n),e=gt(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 OL(n,t,e,r,a){let l=t.find((d)=>PL($(a,it(n,d,"rulebook.json")))===r);if(l)return l;if(m($(a,it(n,e,"rulebook.json")))===null)return e;for(let d=2;;d++){let s=`${e}-${d}`;if(m($(a,it(n,s,"rulebook.json")))===null)return s}}function TL(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 _L(n,t,e,r,a){if(!O(n).config?.rules.includes(e))return!1;try{let d=m(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 tr(n){return{target:n,content:m(n)}}function EL(n){for(let t of n){if(t.content===null){an(t.target);continue}f2(t.target,t.content)}}function PL(n){let t=m(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 IL,readFile as NL,writeFile as no}from"node:fs/promises";import{dirname as to,join as eo}from"node:path";var ro=86400000,ao=604800000;async function Fl(n=Date.now()){if(process.env.CC_SAFETY_NET_NO_UPDATE_CHECK)return null;let t=At();if(!t)return null;let e=eo(t,".cc-safety-net","update-check.json"),r=await lo(e,n);if(!r.lastCheck||n-r.lastCheck>ro){let d=await U2();if(r.lastCheck=n,d.latestVersion)r.latestVersion=d.latestVersion;if(!await jl(e,r))return null;if(d.error)return null}let a=r.latestVersion,l=z();if(!a||!re(a,l))return null;if(r.notifiedVersion===a&&r.notifiedAt!==void 0&&n-r.notifiedAt<ao)return null;if(r.notifiedVersion=a,r.notifiedAt=n,!await jl(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 lo(n,t){let e=await NL(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 jl(n,t){return IL(to(n),{recursive:!0,mode:448}).then(()=>no(n,JSON.stringify(t),{mode:384})).then(()=>!0).catch(()=>!1)}import{dirname as so,join as io,resolve as er}from"node:path";var Bl="CC Safety Net Config",co="═".repeat(Bl.length),Lo="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",oo=new Set(["rule.json","rule.lock","cache"]);function Jl(n={}){try{return uo(n)}catch(t){if(t instanceof S)return console.error(t.message),1;throw t}}function uo(n){let t=n.cwd??process.cwd(),e=n.userConfigPath??E(),r=n.projectConfigPath??_(t),a=n.legacyUserConfigPath??dn(),l=n.legacyProjectConfigPath??kr(t),d=er(t,Qt),s=so(e),i=P({cwd:t,userConfigPath:e,projectConfigPath:r}),c=P({cwd:t}),L=$(i.userScope,e),u=$(i.projectScope,r),p=n.legacyUserConfigPath?rn(n.legacyUserConfigPath,"user policy"):$(c.userScope,a),o=n.legacyProjectConfigPath?rn(n.legacyProjectConfigPath,"project policy"):$(c.projectScope,l),b=!1,v=!1,f=[],w=[],x=po($(c.projectScope,d));if(bo(),m(L)!==null){let y=r2(L);if(y.errors.push(...a2(e,Y2({userConfigDir:s}),{userConfigDir:s},i.userScope)),f.push({scope:"User",path:e,result:y,schema:"rules",sourceDisplayMap:h2(e,i.userScope),target:L}),y.errors.length>0)b=!0}if(m(p)!==null)if(v=!0,m(L)!==null)w.push(ct("user","cleanup"));else{let y=$t(p);if(f.push({scope:"User",path:a,result:y,schema:"legacy",sourceDisplayMap:new Map,inactive:!0,target:p}),w.push(ct("user",y.errors.length>0?"fix-or-delete":"migrate")),y.errors.length>0)b=!0}if(m(u)!==null){let y=r2(u);if(y.errors.push(...a2(r,A2(r),{userConfigDir:s},i.projectScope)),f.push({scope:"Project",path:er(r),result:y,schema:"rules",sourceDisplayMap:h2(r,i.projectScope),target:u}),y.errors.length>0)b=!0;if(m(o)!==null)v=!0,w.push(ct("project","cleanup"))}else if(m(o)!==null){v=!0,b=!0;let y=$t(o);f.push({scope:"Project",path:er(l),result:y,schema:"legacy",sourceDisplayMap:new Map,inactive:!0,target:o}),w.push(ct("project",y.errors.length>0?"fix-or-delete":"migrate"))}if(x?.result.errors.length)b=!0;if(f.length===0&&!x)return console.log(`
|
|
212
|
-
No config files found. Using built-in rules only.`),0;for(let y of f)if(y.inactive)
|
|
213
|
-
Added $schema to ${y.scope.toLowerCase()} config.`);
|
|
214
|
-
${h.red(y)}`);if(x)if(x.result.errors.length>0)
|
|
211
|
+
Check that every parent path component is a directory.`;return t}import{join as jo}from"node:path";var Dl="# 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 jn(n,t){if(!n.ok){UL(n);return}OL(n),console.log(t),console.log("Rule config synced."),console.log(""),KL(n.entries)}function KL(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} (${CL(t.ruleCount??0)})`),console.log(` Source: ${Yt(t)}`)}function CL(n){return`${n} ${n===1?"rule":"rules"}`}function ql(n,t){F2("Active sources",n.rulebooks,(e)=>[`[${e.source}] ${e.name} ${e.version}`,` Source: ${t[e.source].get(e.spec)??e.spec}`]),F2("Active rules",n.rules,(e)=>[`[${GL(n,e.name)}] ${e.name}`,` Command: ${e.subcommand?`${e.command} ${e.subcommand}`:e.command}`,` Block args: ${e.block_args.join(", ")}`,` Reason: ${e.reason}`]),F2("Disabled rules",kl(n,"off"),(e)=>[e.key]),F2("Reason overrides",kl(n,"reason"),(e)=>[e.key,` Reason: ${e.value.reason}`]),F2("Transparent wrappers",n.transparent_wrappers,(e)=>[e]),F2("Issues",n.errors,(e)=>[e]),F2("Warnings",n.warnings,(e)=>[e])}function F2(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 GL(n,t){return n.rulebooks.find((e)=>e.rules.includes(t))?.source??"project"}function kl(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 UL(n){for(let t of n.errors)console.error(t)}function OL(n){if(!n.warnings||n.warnings.length===0)return;for(let t of n.warnings)console.warn(t)}import{dirname as jl,join as it}from"node:path";var TL=".safety-net.json",EL="~/.cc-safety-net/config.json";async function Bl(n){return[await Fl({legacyPath:zl({cwd:n.cwd}),configPath:E(n.cwd),defaultRulebookName:"project-rules",migratedFrom:TL,cleanup:n.cleanup,syncOptions:{cwd:n.cwd}}),await Fl({legacyPath:dn(),configPath:_(),defaultRulebookName:"user-rules",migratedFrom:EL,cleanup:n.cleanup,syncOptions:{cwd:n.cwd,global:!0}})].every((e)=>e)?0:1}async function Fl(n){let t=U(n.syncOptions),e=$(t.filesystemScope,n.legacyPath),r=m(e);if(r===null)return console.log(`No legacy config found at ${n.legacyPath}`),!0;let a=PL(r);if(!a.ok){for(let p of a.errors)console.error(p);return!1}let l=O(t.configTarget);if(l.errors.length>0){for(let p of l.errors)console.error(p);return!1}let d=l.config??{version:1,rules:[],overrides:{},transparent_wrappers:[]},s=IL(jl(n.configPath),d.rules,n.defaultRulebookName,n.migratedFrom,t.filesystemScope),c=it(jl(n.configPath),s,"rulebook.json"),i=$(t.filesystemScope,c),L=[tr(t.configTarget),tr(i),tr(t.lockTarget)],u=await _L(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){to(L);for(let p of u.errors)console.error(p);return!1}if(!n.cleanup)return console.log(`Migrated legacy config at ${n.legacyPath}. Legacy file is no longer used.`),!0;if(!no(t.configTarget,i,s,n.migratedFrom,a.config.rules))return console.error(`Migration cleanup verification failed for ${n.legacyPath}`),!1;return an(e),console.log(`Deleted legacy config at ${n.legacyPath}`),!0}async function _L(n,t,e,r,a,l,d,s){try{return T(t,{version:1,rules:l,overrides:d,transparent_wrappers:s}),T(e,NL(r,n.migratedFrom,a)),await Y2(n.syncOptions)}catch(c){return{ok:!1,errors:[c instanceof Error?c.message:String(c)]}}}function PL(n){try{let t=JSON.parse(n),e=$t(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 IL(n,t,e,r,a){let l=t.find((d)=>eo($(a,it(n,d,"rulebook.json")))===r);if(l)return l;if(m($(a,it(n,e,"rulebook.json")))===null)return e;for(let d=2;;d++){let s=`${e}-${d}`;if(m($(a,it(n,s,"rulebook.json")))===null)return s}}function NL(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 no(n,t,e,r,a){if(!O(n).config?.rules.includes(e))return!1;try{let d=m(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 tr(n){return{target:n,content:m(n)}}function to(n){for(let t of n){if(t.content===null){an(t.target);continue}f2(t.target,t.content)}}function eo(n){let t=m(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 ro,readFile as ao,writeFile as lo}from"node:fs/promises";import{dirname as so,join as co}from"node:path";var io=86400000,Lo=604800000;async function Sl(n=Date.now()){if(process.env.CC_SAFETY_NET_NO_UPDATE_CHECK)return null;let t=Ht();if(!t)return null;let e=co(t,".cc-safety-net","update-check.json"),r=await oo(e,n);if(!r.lastCheck||n-r.lastCheck>io){let d=await U2();if(r.lastCheck=n,d.latestVersion)r.latestVersion=d.latestVersion;if(!await Jl(e,r))return null;if(d.error)return null}let a=r.latestVersion,l=z();if(!a||!ae(a,l))return null;if(r.notifiedVersion===a&&r.notifiedAt!==void 0&&n-r.notifiedAt<Lo)return null;if(r.notifiedVersion=a,r.notifiedAt=n,!await Jl(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 oo(n,t){let e=await ao(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 Jl(n,t){return ro(so(n),{recursive:!0,mode:448}).then(()=>lo(n,JSON.stringify(t),{mode:384})).then(()=>!0).catch(()=>!1)}import{dirname as uo,join as po,resolve as er}from"node:path";var Ql="CC Safety Net Config",vo="═".repeat(Ql.length),bo="https://raw.githubusercontent.com/kenryu42/cc-safety-net/main/assets/cc-safety-net.schema.json",fo=new Set(["rule.json","rule.lock","cache"]);function Xl(n={}){try{return ho(n)}catch(t){if(t instanceof S)return console.error(t.message),1;throw t}}function ho(n){let t=n.cwd??process.cwd(),e=n.userConfigPath??_(),r=n.projectConfigPath??E(t),a=n.legacyUserConfigPath??dn(),l=n.legacyProjectConfigPath??kr(t),d=er(t,Xt),s=uo(e),c=P({cwd:t,userConfigPath:e,projectConfigPath:r}),i=P({cwd:t}),L=$(c.userScope,e),u=$(c.projectScope,r),p=n.legacyUserConfigPath?rn(n.legacyUserConfigPath,"user policy"):$(i.userScope,a),o=n.legacyProjectConfigPath?rn(n.legacyProjectConfigPath,"project policy"):$(i.projectScope,l),b=!1,v=!1,f=[],w=[],x=yo($(i.projectScope,d));if(xo(),m(L)!==null){let y=a2(L);if(y.errors.push(...l2(e,R2({userConfigDir:s}),{userConfigDir:s},c.userScope)),f.push({scope:"User",path:e,result:y,schema:"rules",sourceDisplayMap:h2(e,c.userScope),target:L}),y.errors.length>0)b=!0}if(m(p)!==null)if(v=!0,m(L)!==null)w.push(Lt("user","cleanup"));else{let y=Dt(p);if(f.push({scope:"User",path:a,result:y,schema:"legacy",sourceDisplayMap:new Map,inactive:!0,target:p}),w.push(Lt("user",y.errors.length>0?"fix-or-delete":"migrate")),y.errors.length>0)b=!0}if(m(u)!==null){let y=a2(u);if(y.errors.push(...l2(r,A2(r),{userConfigDir:s},c.projectScope)),f.push({scope:"Project",path:er(r),result:y,schema:"rules",sourceDisplayMap:h2(r,c.projectScope),target:u}),y.errors.length>0)b=!0;if(m(o)!==null)v=!0,w.push(Lt("project","cleanup"))}else if(m(o)!==null){v=!0,b=!0;let y=Dt(o);f.push({scope:"Project",path:er(l),result:y,schema:"legacy",sourceDisplayMap:new Map,inactive:!0,target:o}),w.push(Lt("project",y.errors.length>0?"fix-or-delete":"migrate"))}if(x?.result.errors.length)b=!0;if(f.length===0&&!x)return console.log(`
|
|
212
|
+
No config files found. Using built-in rules only.`),0;for(let y of f)if(y.inactive)go(y.scope,y.path,y.result,y.sourceDisplayMap);else if(y.result.errors.length>0)$o(y.scope,y.path,y.result.errors);else{if(y.schema==="rules"&&qo(y.target))console.log(`
|
|
213
|
+
Added $schema to ${y.scope.toLowerCase()} config.`);mo(y.scope,y.path,y.result,y.schema,y.sourceDisplayMap)}for(let y of w)console.error(`
|
|
214
|
+
${h.red(y)}`);if(x)if(x.result.errors.length>0)ko(x.path,x.result.errors);else Do(x.path,x.result);if(b)return console.error(`
|
|
215
215
|
Config validation failed.`),1;return console.log(v?`
|
|
216
216
|
Configs valid with warnings.`:`
|
|
217
|
-
All configs valid.`),0}function
|
|
218
|
-
✓ ${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
|
|
219
|
-
✗ 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
|
|
220
|
-
✓ GitHub source rules: ${n}`),console.log(" Rulebooks:");let e=1;for(let r of t.ruleNames)console.log(` ${e}. ${r}`),e++}function
|
|
221
|
-
✗ ${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
|
|
222
|
-
`))}import{spawn as
|
|
223
|
-
return POSIX path of (choose folder with prompt "${
|
|
217
|
+
All configs valid.`),0}function Lt(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 yo(n){if(X2(n)===null)return null;let t=wo(n);if(t.ruleNames.size===0&&t.errors.length===0)return null;return{path:n.path,result:t}}function wo(n){let t=[],e=new Set,r=(X2(n)??[]).filter((a)=>!fo.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=$(n.scope,po(n.path,a.name,"rulebook.json")),d=m(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=Zl(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 xo(){console.log(Ql),console.log(vo)}function mo(n,t,e,r,a){if(console.log(`
|
|
218
|
+
✓ ${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 go(n,t,e,r){if(console.error(`
|
|
219
|
+
✗ 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 $o(n,t,e){Yl(`${n} config`,t,e)}function Do(n,t){console.log(`
|
|
220
|
+
✓ GitHub source rules: ${n}`),console.log(" Rulebooks:");let e=1;for(let r of t.ruleNames)console.log(` ${e}. ${r}`),e++}function ko(n,t){Yl("GitHub source rules",n,t)}function Yl(n,t,e){console.error(`
|
|
221
|
+
✗ ${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 qo(n){try{let t=m(n);if(t===null)return!1;let e=JSON.parse(t);if(e.$schema)return!1;return f2(n,JSON.stringify({$schema:bo,...e},null,2)),!0}catch(t){if(t instanceof S)throw t;return!1}}var Rl=new Set(["init","add","remove","update","sync","list","wrapper","migrate","doc","verify"]),Fo=new Set(["add","remove","list"]);async function Hl(n){try{return await zo(n)}catch(t){if(t instanceof S)return console.error(t.message),1;throw t}}async function zo(n){let t=Jo(n),e=t.help?Bo(t.positionals):null;if(e)return et(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 et(G2,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;Qo(d.configTarget),Al($(d.filesystemScope,Jn({...l,cacheConfigDir:s})));let c=jo(s,"example-rules","rulebook.json"),i=$(d.filesystemScope,c);if(t.example&&m(i)===null)At(i,"example-rules");let L=await Y2(l);return jn(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 St(a,l);return jn(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 Qt(a,{...l,deleteSource:t.deleteSource});return jn(d,`Removed rulebook source: ${a}`),d.ok?0:1}if(r==="update"||r==="sync"){let d=await Y2({...l,only:r==="update"?a:void 0});return jn(d,t.check?"Rule config checked.":"Rule config synced."),d.ok?0:1}if(r==="list"){let d=u2(),s=P({});return ql(d,{user:h2(d.userConfigPath,s.userScope),project:h2(d.projectConfigPath,s.projectScope)}),d.errors.length>0?1:0}if(r==="wrapper")return Xo(t);if(r==="migrate")return Bl({cleanup:t.cleanup,cwd:process.cwd()});if(r==="doc"){console.log(Dl);let d=await Sl();if(d)console.error(d);return 0}if(r==="verify")return Xl();return 1}function Bo(n){if(n.length===0)return G2;let t=G2.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 Jo(n){let t=j({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 So(e),e}function So(n){let[t]=n.positionals;if(t&&!Rl.has(t))n.errors.push(`Unknown rule subcommand: ${t}`);if(n.deleteSource&&t!=="remove")if(t&&Rl.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(ot(t,"--cleanup"));if(n.example&&t!=="init")n.errors.push(ot(t,"--example"));if(t==="migrate"){if(n.global)n.errors.push(ot(t,"--global"));if(n.check)n.errors.push(ot(t,"--check"));if(n.positionals.length>1)n.errors.push(`Unexpected rule migrate argument: ${n.positionals[1]}`)}else if(t==="wrapper")Zo(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 ot(n,t){return n?`Unknown option for rule ${n}: ${t}`:`Unknown option for rule: ${t}`}function Zo(n){let t=n.positionals[1],e=n.positionals[2];if(!t){n.errors.push("rule wrapper requires add, remove, or list");return}if(!Fo.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 Qo(n){if(m(n)===null){Rt(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 Xo(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 Yo(s.config?.transparent_wrappers??[]),0}if(!e||!Mt.test(e))return console.error("transparent wrapper must match command pattern"),1;if(Wt(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 Yo(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 Ml}from"node:os";import{existsSync as Ro,readFileSync as Ao}from"node:fs";import{homedir as Ho}from"node:os";import{join as Mo}from"node:path";async function Wo(){if(process.stdin.isTTY)return null;return(await Et(process.stdin).catch(()=>null))?.trim()||null}function Vo(){if(process.env.CLAUDE_SETTINGS_PATH)return process.env.CLAUDE_SETTINGS_PATH;return Mo(Ho(),".claude","settings.json")}function rr(){let n=Vo();if(!Ro(n))return!1;try{let t=Ao(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(Ln(D.debug))console.error(`CC Safety Net debug: failed to read Claude settings: ${n}: ${t instanceof Error?t.message:String(t)}`);return!1}}async function ar(){let n=rr(),t;if(!n)t="\uD83D\uDEE1️ CC Safety Net ❌";else{let r=H({cwd:process.cwd()}),a=r.policy,l=d2(a),d=Object.values(w2(a,l.capabilities)).some((c)=>c.changesInherited);t=`\uD83D\uDEE1️ CC Safety Net ${{standard:"✅",strict:"\uD83D\uDD12",paranoid:"\uD83D\uDC41️",custom:"\uD83D\uDD27"}[d?"custom":l.effectiveLevel]}${l.worktreeMode?"\uD83C\uDF33":""}${r.state==="degraded"?"⚠️":""}`}let e=await Wo();if(e&&!e.startsWith("{"))console.log(`${e} | ${t}`);else console.log(t)}function Wl(){let n=H({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=(o,b)=>{let v=` ${o.padEnd(13)}${b}`;return(v.length>a?`${v.slice(0,a-1)}…`:v).replaceAll(d,h.red(d))},c=Object.values(w2(t,e.capabilities)).some((o)=>o.changesInherited),i=Ut(),L={ready:h.green,degraded:h.yellow}[n.state],u=[...rr()?[]:["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],p=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(Ml())?`~${i.slice(Ml().length)}`:i),...e.worktreeMode?[s("Worktree","relaxations active")]:[],"",...u.length===0?[" Everything configured is active."]:[" Not active",...u.flatMap((o)=>tt(o," ",a-6).map((b,v)=>v===0?` ${p} ${b}`:b)),""," Full report: cc-safety-net doctor"]].join(`
|
|
222
|
+
`))}import{spawn as sd}from"node:child_process";import{randomBytes as No}from"node:crypto";import{createServer as n5}from"node:http";import{Writable as t5}from"node:stream";import{homedir as Ko}from"node:os";var ut=500;function Co(n){let t=n.filter((a)=>a.decision!=="allow"),e=n.filter((a)=>a.decision==="allow"),r=Math.min(t.length,Math.max(ut-e.length,Math.ceil(ut/2)));return[...t.slice(0,r),...e.slice(0,ut-r)]}function Vl(n,t=s2()){if(t)y2(t);let e=(v)=>new Date(v.getFullYear(),v.getMonth(),v.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 v of t?o2(t,s):[])for(let f of en(v,s)){if(!f||typeof f.ts!=="string"||typeof f.command!=="string")continue;let w=new Date(f.ts).getTime();if(!Number.isFinite(w))continue;if(w>=l)d.push(f)}d.sort((v,f)=>new Date(f.ts).getTime()-new Date(v.ts).getTime());let c=Array.from({length:n},()=>0),i=Array.from({length:n},()=>0),L={},u={},p={},o=0,b=0;for(let v of d){let f=v.agent||"unknown";L[f]=(L[f]??0)+1;let w=Math.round((r-e(new Date(v.ts)))/86400000),x=n-1-w,y=w>=0&&w<n;if(y)i[x]=(i[x]??0)+1;if(v.decision!=="allow"){if(o++,v.ruleId)u[v.ruleId]=(u[v.ruleId]??0)+1;let J=B2(v.segment||v.command);if(J)p[J]=(p[J]??0)+1;if(v.failureStage)b++;if(y)c[x]=(c[x]??0)+1}}return{days:n,logsDir:t,homeDir:Ko(),totalInWindow:d.length,truncated:d.length>ut,unreadable:s.count,counts:{blocked:o,allowed:d.length-o,agents:L,blockedByDay:c,analyzedByDay:i,rules:u,commands:p,errors:b},entries:Co(d).sort((v,f)=>new Date(f.ts).getTime()-new Date(v.ts).getTime())}}import{spawn as Go}from"node:child_process";import{existsSync as Kl,statSync as Uo}from"node:fs";import{delimiter as Oo,join as To}from"node:path";var Eo=120000,pt="Choose the project folder",_o=`try
|
|
223
|
+
return POSIX path of (choose folder with prompt "${pt}")
|
|
224
224
|
on error number -128
|
|
225
225
|
return ""
|
|
226
|
-
end try`,
|
|
226
|
+
end try`,Po=`Add-Type -AssemblyName System.Windows.Forms
|
|
227
227
|
$dialog = New-Object System.Windows.Forms.FolderBrowserDialog
|
|
228
|
-
$dialog.Description = '${
|
|
229
|
-
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,Cl=[{binary:"zenity",args:["--file-selection","--directory",`--title=${
|
|
228
|
+
$dialog.Description = '${pt}'
|
|
229
|
+
if ($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) { [Console]::Out.Write($dialog.SelectedPath) }`,Cl=[{binary:"zenity",args:["--file-selection","--directory",`--title=${pt}`]},{binary:"kdialog",args:["--getexistingdirectory",".","--title",pt]}],Gl=(n,t)=>(t.PATH??"").split(Oo).some((e)=>e.length>0&&Kl(To(e,n)));function Ul(n,t){if(n==="darwin"||n==="win32")return!0;if(n!=="linux")return!1;if(!t.DISPLAY&&!t.WAYLAND_DISPLAY)return!1;return Cl.some((e)=>Gl(e.binary,t))}function Io(n,t){if(n==="darwin")return{cmd:"osascript",args:["-e",_o]};if(n==="win32")return{cmd:"powershell.exe",args:["-NoProfile","-STA","-Command",Po]};let e=Cl.find((r)=>Gl(r.binary,t));return e?{cmd:e.binary,args:e.args}:null}function Ol(n=process.platform,t=process.env){let e=Io(n,t);if(!e)return Promise.resolve({error:"No folder dialog is available on this system"});return new Promise((r)=>{let a=Go(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"})},Eo);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(!Kl(i)||!Uo(i).isDirectory())return s({error:"That selection is not a folder on disk"});s({path:i})})})}var Tl=`<!doctype html>
|
|
230
230
|
<html lang="en">
|
|
231
231
|
<head>
|
|
232
232
|
<meta charset="utf-8">
|
|
@@ -5323,5 +5323,5 @@ load().then((loaded) => {
|
|
|
5323
5323
|
</script>
|
|
5324
5324
|
</body>
|
|
5325
5325
|
</html>
|
|
5326
|
-
`;var
|
|
5327
|
-
`)}}finally{console.log=d,console.error=s}},a=
|
|
5326
|
+
`;var El='<script id="ccsn-data" type="application/json">';function _l(n){return Tl.replace(El,()=>El+JSON.stringify({token:n}).replaceAll("<","\\u003c"))}var bt="kenryu42/cc-safety-net",e5=`https://github.com/${bt}`,sr=1e4,r5=7;async function cd(n,t={}){let e=j({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 a5(t);if(r(`CC Safety Net policy GUI: ${l.url}`),!e.flags.noOpen)try{await(t.openBrowser??u5)(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 o5(l),0}async function a5(n={}){let t=n.token??No(24).toString("base64url"),e=n5((l,d)=>{l5(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:()=>L5(e)}}async function l5(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(!c5(n,a,e)){k(t,403,{error:"Forbidden"});return}if(n.method==="GET"&&a.pathname==="/"){i5(t,_l(e));return}if(n.method==="GET"&&a.pathname==="/api/policy"){let l=nd(r);k(t,200,{...l,configState:on(H(r)),destructiveCommandRules:sn,secretPatterns:Il,version:z(),preview:l.errors.length>0?null:ed(l.policy)});return}if(n.method==="POST"&&a.pathname==="/api/policy/preview"){let l=await vt(n);if(!l.ok){k(t,400,{errors:[l.error]});return}let d=td(l.value);k(t,d.errors.length>0?400:200,d);return}if(n.method==="POST"&&a.pathname==="/api/policy/explain"){let l=await vt(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=Gt(d.policy);if(s.length>0){k(t,400,{errors:s});return}k(t,200,d5(d.command,d.policy,r));return}if(n.method==="POST"&&a.pathname==="/api/policy"){let l=await vt(n);if(!l.ok){k(t,400,{errors:[l.error]});return}let d=lr(l.value,r);k(t,d.errors.length>0?400:200,d);return}if(n.method==="POST"&&a.pathname==="/api/reset"){k(t,200,lr(Nl,r));return}if(n.method==="POST"&&a.pathname==="/api/repair"){k(t,200,rd(r));return}if(n.method==="GET"&&a.pathname==="/api/activity"){let l=W2(r),d=s5(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,Vl(d,r.activityLogsDir));return}if(n.method==="POST"&&a.pathname==="/api/rules/choose-directory"){k(t,200,await Ol());return}if(n.method==="GET"&&a.pathname==="/api/rules"){let l=u2(r),d=new Map(l.rules.map((s)=>[s.name,s]));k(t,200,{projectPath:r.cwd??process.cwd(),canPickDirectory:Ul(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??(()=>y5({logsDir:r.activityLogsDir})))());return}if(n.method==="POST"&&a.pathname==="/api/star"){let l=await(r.starRepo??p5)();k(t,200,l.ok?{ok:!0}:{ok:!1,fallbackUrl:e5});return}if(n.method==="GET"&&a.pathname==="/api/integrations"){k(t,200,await(r.fetchIntegrations??b5)());return}if(n.method==="GET"&&a.pathname==="/api/health"){k(t,200,await(r.fetchHealth??f5)());return}if(n.method==="POST"&&(a.pathname==="/api/install"||a.pathname==="/api/uninstall")){let l=await vt(n);if(!l.ok){k(t,400,{errors:[l.error]});return}let d=l.value?.target;if(typeof d!=="string"||!G.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??h5)(s,d));return}k(t,404,{error:"Not found"})}function d5(n,t,e){let r=ad(t),a=H(e),l=cn({rules:a.policy.rules,transparentWrappers:a.policy.transparentWrappers,safety:dd(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:[...ld(r.secret_protection.overrides)],denyPaths:r.secret_protection.deny_paths}});return M2(n,{policySnapshot:l,cwd:e.cwd,userConfigDir:e.userConfigDir})}function s5(n,t){if(n===null)return Math.min(r5,t);let e=Number(n);if(!Number.isInteger(e)||e<1||e>t)return null;return e}function c5(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 vt(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 i5(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 L5(n){return new Promise((t,e)=>{n.close((r)=>r?e(r):t())})}function o5(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 u5(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=sd(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 p5(n="gh",t=sr){return{ok:await dr(n,["api","-X","PUT",`/user/starred/${bt}`],t)===0}}var v5={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 b5(n={}){let t=await bn(n.fetcher),e=id(t,n.homeDir);return{targets:i2.map((r)=>{let a=e.find((l)=>l.platform===r.id);return{target:r.id,label:p2(r.id),version:t[v5[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 id(n,t){return P2(process.cwd(),{homeDir:t,codexPluginListOutput:n.codexPluginListOutput,copilotCliVersion:n.copilotCliVersion})}async function f5(n={}){let[t,e]=await Promise.all([bn(n.fetcher),(n.checkUpdates??U2)()]);return{hooks:id(t,n.homeDir).filter((r)=>r.detected).map((r)=>({platform:r.platform,label:p2(r.platform),configured:r.configured})),update:{currentVersion:e.currentVersion,latestVersion:e.latestVersion??null,updateAvailable:e.updateAvailable}}}var Pl=Promise.resolve();function h5(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 qn(n,[],{selectTargets:async()=>[t],output:new t5({write(i,L,u){u()}}),...e})===0,output:l.join(`
|
|
5327
|
+
`)}}finally{console.log=d,console.error=s}},a=Pl.then(r);return Pl=a.then(()=>{return},()=>{return}),a}async function y5(n={}){let[t,e,r]=await Promise.all([w5(n.command),x5(n.fetchRepo),Promise.resolve(Rn(W2(),n.logsDir).totalBlocked)]);return{starred:t,starCount:e,blockedTotal:r}}async function w5(n="gh",t=sr){if(await dr(n,["auth","status"],t)!==0)return null;let e=await dr(n,["api",`/user/starred/${bt}`],t);if(e===0)return!0;if(e===null)return null;return!1}function dr(n,t,e){return new Promise((r)=>{let a=sd(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 x5(n=fetch){try{let t=await n(`https://api.github.com/repos/${bt}`,{headers:{accept:"application/vnd.github+json"},signal:AbortSignal.timeout(sr)});if(!t.ok)return null;let e=await t.json();return typeof e.stargazers_count==="number"?e.stargazers_count:null}catch{return null}}function m5(n){if(n[0]!=="help")return!1;let t=n[1];if(!t)Re(),process.exit(0);if(Dn(t))process.exit(0);console.error(`Unknown command: ${t}`),console.error("Run 'cc-safety-net --help' for available commands."),process.exit(1)}var g5={hook:async(n)=>{let t=za(n);if(t){await t.run();return}console.error("hook requires exactly one integration flag. Try: cc-safety-net hook --kimi-code"),Dn("hook",console.error),process.exit(1)},install:async(n)=>{process.exit(await qn("install",n))},update:async(n)=>{process.exit(await Ne(n))},uninstall:async(n)=>{process.exit(await qn("uninstall",n))},rule:async(n)=>{process.exit(await Hl(n))},status:async(n)=>{if(r2(j({label:"status"},n).errors))process.exit(1);Wl()},statusline:async(n)=>{let t=j({label:"statusline",booleans:{claudeCode:["-cc","--claude-code"]}},n);if(t.errors.length===0&&t.flags.claudeCode){await ar();return}if(r2(t.errors),!t.flags.claudeCode)console.error("statusline requires --claude-code (-cc)");Dn("statusline",console.error),process.exit(1)},doctor:async(n)=>{let t=Se(n);if(!t)process.exit(1);let e=await z0({json:t.json,skipUpdateCheck:t.skipUpdateCheck});process.exit(e)},logs:async(n)=>{process.exit(await Ir(n))},gui:async(n)=>{process.exit(await cd(n))},explain:async(n)=>{let t=Ze(n);if(!t)process.exit(1);let e=M2(t.command,{cwd:t.cwd}),r=!!process.env.NO_COLOR||!process.stdout.isTTY;if(t.json)console.log(Ye(e));else console.log(Xe(e,{asciiOnly:r}));process.exit(0)}};async function $5(){let n=process.argv.slice(2),t=j({label:"cc-safety-net",booleans:{version:["-V","--version"]},positionals:"list"},n);if(m5(n))return;let e=n[0],r=e?Yn(e):void 0;if(t.help&&r&&r.name!=="rule")Dn(r.name),process.exit(0);if(!e||t.help&&!r)Re(),process.exit(0);if(t.flags.version)R0(),process.exit(0);if(r){await g5[r.name](n.slice(1));return}let a=Ba(e);if(a){await a.run();return}if(e==="--statusline"){await ar();return}console.error(e.startsWith("-")?`Unknown option: ${e}`:`Unknown command: ${e}`),console.error("Run 'cc-safety-net --help' for usage."),process.exit(1)}$5().catch((n)=>{console.error("CC Safety Net error:",n),process.exit(1)});
|