@complexthings/superpowers-agent 9.0.1 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,13 @@
1
1
  #!/bin/sh
2
2
  // 2>/dev/null; exec "$(command -v bun 2>/dev/null || echo node)" "$0" "$@"
3
- import{relative as B1,dirname as _1,join as w2}from"path";import{existsSync as x$}from"fs";import{homedir as r$,platform as e1}from"os";import{join as A,parse as $2,dirname as l$}from"path";import{existsSync as d}from"fs";import{fileURLToPath as Q2}from"url";var X2=Q2(import.meta.url),E$=l$(X2),Y2=()=>{let $=r$();switch(e1()){case"darwin":return A($,"Library","Application Support","Code","User");case"win32":return A($,"AppData","Roaming","Code","User");case"linux":return A($,".config","Code","User");default:return A($,".config","Code","User")}},Z2=()=>{let $=process.cwd(),Q=$2($).root;while($!==Q){if(d(A($,".agents")))return $;$=l$($)}return process.cwd()},E={home:r$(),vscodeUserDir:Y2(),projectRoot:Z2(),get projectClaudeSkills(){return A(this.projectRoot,".claude","skills")},get projectAgentsSkills(){return A(this.projectRoot,".agents","skills")},get projectCopilotSkills(){return A(this.projectRoot,".copilot","skills")},get projectOpencodeSkills(){return A(this.projectRoot,".opencode","skill")},get projectSkillsDir(){return A(this.projectRoot,"skills")},get homePersonalSkills(){return A(this.home,".agents","skills")},get homeClaudeSkills(){return A(this.home,".claude","skills")},get homeCopilotSkills(){return A(this.home,".copilot","skills")},get homeOpencodeSkills(){return A(this.home,".config","opencode","skill")},get bootstrap(){return A(this.projectRoot,".agents","superpowers-bootstrap.md")},get superpowersRepo(){let $=A(E$,"..","..","..");if(d(A($,"skills"))&&d(A($,".agents","superpowers-agent")))return $;let Q=A(E$,"..");if(d(A(Q,"skills"))&&d(A(Q,".agents","superpowers-agent")))return Q;return A(this.home,".agents","superpowers")},get homeSuperpowersSkills(){return A(this.superpowersRepo,"skills")},get isSuperpowersRepo(){let $=A(E$,"..","..","..");if(d(A($,"skills"))&&d(A($,".agents","superpowers-agent")))return!0;let Q=A(E$,"..");return d(A(Q,"skills"))&&d(A(Q,".agents","superpowers-agent"))}};import{readFileSync as a$}from"fs";var $$=($)=>{try{let X=a$($,"utf8").split(`
4
- `),Z={name:"",description:"",whenToUse:""},Y=!1;for(let H of X){if(H.trim()==="---"){if(Y)break;Y=!0;continue}if(Y){let W=H.match(/^(\w+):\s*(.*)$/);if(W){let[,q,K]=W,z={name:"name",description:"description",when_to_use:"whenToUse"};if(z[q])Z[z[q]]=K.trim()}}}return Z}catch{return{name:"",description:"",whenToUse:""}}},s$=($)=>{try{let Q=a$($,"utf8"),X=$$($),Z=Q.split(`
5
- `),Y=!1,H=!1,W=[];for(let q of Z){if(q.trim()==="---"){if(Y){H=!0;continue}Y=!0;continue}if(H||!Y)W.push(q)}return{content:W.join(`
6
- `).trim(),frontmatter:X}}catch(Q){throw Error(`Error reading skill file: ${Q.message}`)}};import{existsSync as A$,readdirSync as $1,statSync as Q1}from"fs";import{join as M$,relative as v3}from"path";import{readFileSync as H2,existsSync as q2}from"fs";import{join as t$}from"path";var Q$=($)=>{let Q=t$($,"skill.json");if(!q2(Q))return null;try{let X=H2(Q,"utf8");return JSON.parse(X)}catch(X){return null}};var J$=($)=>{if($.startsWith("superpowers:"))return{type:"superpowers",path:$.substring(12).replace(/^skills\//,"")};if($.startsWith("claude:"))return{type:"claude",path:$.substring(7).replace(/^skills\//,"")};if($.startsWith("copilot:"))return{type:"copilot",path:$.substring(8).replace(/^skills\//,"")};if($.startsWith("opencode:"))return{type:"opencode",path:$.substring(9).replace(/^skills\//,"")};return{type:null,path:$.replace(/^skills\//,"")}},e$=($,Q)=>{let X=Q$($);if(!X||!X.helpers||!Array.isArray(X.helpers))return null;let Z=X.helpers,Y=Q.toLowerCase(),H=null,W=0;for(let q of Z){let K=q.toLowerCase();if(K===Y){H=q;break}if(K.includes(Y)){let _=Y.length/K.length;if(_>W)W=_,H=q}let z=q.split("/").pop().split(".")[0].toLowerCase();if(Y.includes(z)){let _=z.length/Y.length;if(_>W)W=_,H=q}}return H?t$($,H):null},X$={project:{dir:"projectAgentsSkills",prefix:""},claude:{dir:"projectClaudeSkills",prefix:"claude:"},copilot:{dir:"projectCopilotSkills",prefix:"copilot:"},opencode:{dir:"projectOpencodeSkills",prefix:"opencode:"},personal:{dir:"homePersonalSkills",prefix:""},personalClaude:{dir:"homeClaudeSkills",prefix:"claude:"},personalCopilot:{dir:"homeCopilotSkills",prefix:"copilot:"},personalOpencode:{dir:"homeOpencodeSkills",prefix:"opencode:"},superpowers:{dir:"homeSuperpowersSkills",prefix:"superpowers:"}};var K$=($,Q,X=null)=>{let Z=[];if(!A$($))return Z;let Y=(H,W)=>{if(X!==null&&W>X)return;try{let q=$1(H,{withFileTypes:!0});for(let K of q){if(K.name==="node_modules"||K.name===".git"||K.name.startsWith("."))continue;let z=M$(H,K.name),_=K.isDirectory();if(K.isSymbolicLink())try{_=Q1(z).isDirectory()}catch{continue}if(!_)continue;let B=M$(z,"SKILL.md");if(A$(B))Z.push(z);if(X===null||W<X)Y(z,W+1)}}catch{}};return Y($,0),Z};var X1=($,Q)=>{if(!A$($))return[];let X=[],Z=Q.toLowerCase().replace(/\\/g,"/"),Y=(H,W="")=>{try{let q=$1(H,{withFileTypes:!0});for(let K of q){let z=M$(H,K.name),_=W?`${W}/${K.name}`:K.name,B=K.isDirectory();if(K.isSymbolicLink())try{B=Q1(z).isDirectory()}catch{continue}if(B&&(K.name==="node_modules"||K.name===".git"||K.name.startsWith(".")))continue;if(B)Y(z,_);else if(K.name==="SKILL.md"){let G=W.toLowerCase().replace(/\\/g,"/");if(G===Z||G.endsWith("/"+Z)||G.endsWith(Z))X.push({file:z,path:W})}}}catch(q){}};return Y($),X},Y1=($,Q,X)=>{let Z={project:"project skills (.agents/skills/)",claude:"claude skills (.claude/skills/)",copilot:"copilot skills (.copilot/skills/)",opencode:"opencode skills (.opencode/skill/)",personal:"personal skills (~/.agents/skills/)",personalClaude:"personal claude skills (~/.claude/skills/)",personalCopilot:"personal copilot skills (~/.copilot/skills/)",personalOpencode:"personal opencode skills (~/.config/opencode/skill/)",superpowers:"superpowers skills (~/.agents/superpowers/skills/)"}[X];console.log(`Error: Multiple skills match "${$}" in ${Z}:
7
- `);for(let Y of Q){let W=X$[X].prefix+Y.path;try{let q=$$(Y.file),K=q.description||q.whenToUse||"(no description)";console.log(` ${W}`),console.log(` ${K}
8
- `)}catch(q){console.log(` ${W}`),console.log(` (unable to read description)
9
- `)}}console.log("Please be more specific. Examples:");for(let Y of Q.slice(0,2)){let H=X$[X].prefix;console.log(` superpowers-agent execute ${H}${Y.path}`)}};import{existsSync as T$}from"fs";import{join as W2,relative as z2}from"path";var E2=($)=>{let{type:Q,path:X}=J$($),Z={superpowers:[E.homeSuperpowersSkills],claude:[E.projectClaudeSkills,E.homeClaudeSkills],copilot:[E.projectCopilotSkills,E.homeCopilotSkills],opencode:[E.projectOpencodeSkills,E.homeOpencodeSkills],project:[E.projectAgentsSkills],personal:[E.homePersonalSkills]},Y;if(Q)Y=(Z[Q]||[]).map((W)=>({type:Q,dir:W}));else if(E.isSuperpowersRepo&&T$(E.projectSkillsDir))Y=[{type:"project",dir:E.projectSkillsDir},{type:"project",dir:E.projectAgentsSkills},{type:"claude",dir:E.projectClaudeSkills},{type:"copilot",dir:E.projectCopilotSkills},{type:"opencode",dir:E.projectOpencodeSkills},{type:"personal",dir:E.homePersonalSkills},{type:"personalClaude",dir:E.homeClaudeSkills},{type:"personalCopilot",dir:E.homeCopilotSkills},{type:"personalOpencode",dir:E.homeOpencodeSkills},{type:"superpowers",dir:E.homeSuperpowersSkills}];else Y=[{type:"project",dir:E.projectAgentsSkills},{type:"claude",dir:E.projectClaudeSkills},{type:"copilot",dir:E.projectCopilotSkills},{type:"opencode",dir:E.projectOpencodeSkills},{type:"personal",dir:E.homePersonalSkills},{type:"personalClaude",dir:E.homeClaudeSkills},{type:"personalCopilot",dir:E.homeCopilotSkills},{type:"personalOpencode",dir:E.homeOpencodeSkills},{type:"superpowers",dir:E.homeSuperpowersSkills}];for(let{type:H,dir:W}of Y){let q=X1(W,X);if(q.length===1)return{skillFile:q[0].file,sourceType:H,actualSkillPath:q[0].path};if(q.length>1)Y1(X,q,H)}return null},i=($)=>{let Q=E2($);if(Q)return Q;let{type:X,path:Z}=J$($),Y={superpowers:[E.homeSuperpowersSkills],claude:[E.projectClaudeSkills,E.homeClaudeSkills],copilot:[E.projectCopilotSkills,E.homeCopilotSkills],opencode:[E.projectOpencodeSkills,E.homeOpencodeSkills],project:[E.projectAgentsSkills],personal:[E.homePersonalSkills]},H;if(X)H=(Y[X]||[]).map((q)=>({type:X,dir:q}));else if(E.isSuperpowersRepo&&T$(E.projectSkillsDir))H=[{type:"project",dir:E.projectSkillsDir},{type:"project",dir:E.projectAgentsSkills},{type:"claude",dir:E.projectClaudeSkills},{type:"copilot",dir:E.projectCopilotSkills},{type:"opencode",dir:E.projectOpencodeSkills},{type:"personal",dir:E.homePersonalSkills},{type:"personalClaude",dir:E.homeClaudeSkills},{type:"personalCopilot",dir:E.homeCopilotSkills},{type:"personalOpencode",dir:E.homeOpencodeSkills},{type:"superpowers",dir:E.homeSuperpowersSkills}];else H=[{type:"project",dir:E.projectAgentsSkills},{type:"claude",dir:E.projectClaudeSkills},{type:"copilot",dir:E.projectCopilotSkills},{type:"opencode",dir:E.projectOpencodeSkills},{type:"personal",dir:E.homePersonalSkills},{type:"personalClaude",dir:E.homeClaudeSkills},{type:"personalCopilot",dir:E.homeCopilotSkills},{type:"personalOpencode",dir:E.homeOpencodeSkills},{type:"superpowers",dir:E.homeSuperpowersSkills}];for(let{type:W,dir:q}of H){if(!T$(q))continue;let K=K$(q,W,null);for(let z of K){let _=Q$(z);if(_&&_.aliases&&Array.isArray(_.aliases)){let B=Z.toLowerCase();for(let G of _.aliases)if(G.toLowerCase()===B){let V=W2(z,"SKILL.md"),I=z2(q,z);return{skillFile:V,sourceType:W,actualSkillPath:I}}}}}return null};import{readFileSync as Z1,writeFileSync as H1,existsSync as v$}from"fs";import{join as r}from"path";import{execSync as K2}from"child_process";var C$=()=>({auto_update:!0,last_update_check:null,last_updated_commit:null}),Y$=()=>{let $=r(E.superpowersRepo,".config.json");try{if(!v$($))return C$();let Q=Z1($,"utf8");return{...C$(),...JSON.parse(Q)}}catch{return C$()}},q1=($)=>{let Q=r(E.superpowersRepo,".config.json"),Z={...Y$(),...$};try{H1(Q,JSON.stringify(Z,null,2))}catch(Y){console.log(`Warning: couldn't save config: ${Y.message}`)}},y=($)=>{let Q=$?r(E.home,".agents","config.json"):r(process.cwd(),".agents","config.json");if(!v$(Q))return{};try{let X=Z1(Q,"utf8");return JSON.parse(X)}catch(X){return{}}},m=($,Q)=>{let X=Q?r(E.home,".agents"):r(process.cwd(),".agents"),Z=r(X,"config.json");try{if(!v$(X))K2(`mkdir -p "${X}"`,{stdio:"pipe"});return H1(Z,JSON.stringify($,null,2),"utf8"),!0}catch(Y){throw Error(`Failed to write config: ${Y.message}`)}},P=($=!1)=>{return y($).repositories||{}},W1=($,Q,X)=>{let Z=y(X);if(!Z.repositories)Z.repositories={};Z.repositories[$]=Q,m(Z,X)};function z1($=!0){return y($).installedSkills||{}}function b$($,Q=!0){let X=y(Q);if(X.installedSkills)delete X.installedSkills[$];m(X,Q)}function E1(){return y(!0).installedAgents||{}}import{readFileSync as B2}from"fs";import{join as N$,dirname as _2}from"path";import{fileURLToPath as G2}from"url";import{existsSync as K1}from"fs";import{execSync as V2}from"child_process";var L2=G2(import.meta.url),F$=_2(L2),g=()=>{try{let $=N$(F$,"package.json");if(!K1($))$=N$(F$,"..","package.json");if(!K1($))$=N$(F$,"..","..","package.json");return JSON.parse(B2($,"utf8")).version||"0.0.0"}catch{return"0.0.0"}},k=()=>{let $=g();console.log(`^^SAV:${$}^^`)},B$=async()=>{try{let Q=V2('curl -sS "https://registry.npmjs.org/@complexthings/superpowers-agent/latest"',{encoding:"utf8",timeout:1e4}),X=JSON.parse(Q);if(!X.version)return g();return X.version}catch($){throw Error(`Failed to fetch remote version: ${$.message}`)}},_$=($,Q)=>{let X=$.split(".").map(Number),Z=Q.split(".").map(Number);for(let Y=0;Y<3;Y++){let H=X[Y]||0,W=Z[Y]||0;if(H>W)return!0;if(H<W)return!1}return!1};var U2={project:{dir:"projectAgentsSkills",prefix:""},claude:{dir:"projectClaudeSkills",prefix:"claude:"},copilot:{dir:"projectCopilotSkills",prefix:"copilot:"},opencode:{dir:"projectOpencodeSkills",prefix:"opencode:"},personal:{dir:"homePersonalSkills",prefix:""},personalClaude:{dir:"homeClaudeSkills",prefix:"claude:"},personalCopilot:{dir:"homeCopilotSkills",prefix:"copilot:"},personalOpencode:{dir:"homeOpencodeSkills",prefix:"opencode:"},superpowers:{dir:"homeSuperpowersSkills",prefix:"superpowers:"}},I2=($,Q)=>{let X=w2($,"SKILL.md"),{dir:Z,prefix:Y}=U2[Q],H=B1(E[Z],$).replace(/\\/g,"/");console.log(`${Y}${H}`);let{description:W,whenToUse:q}=$$(X);if(W)console.log(` ${W}`);if(q)console.log(` When to use: ${q}`);console.log("")},a=()=>{k();let $=new Set,Q=[{type:"project",dir:E.projectAgentsSkills,maxDepth:null},{type:"claude",dir:E.projectClaudeSkills,maxDepth:null},{type:"copilot",dir:E.projectCopilotSkills,maxDepth:null},{type:"opencode",dir:E.projectOpencodeSkills,maxDepth:null},{type:"personal",dir:E.homePersonalSkills,maxDepth:null},{type:"personalClaude",dir:E.homeClaudeSkills,maxDepth:null},{type:"personalCopilot",dir:E.homeCopilotSkills,maxDepth:null},{type:"personalOpencode",dir:E.homeOpencodeSkills,maxDepth:null},{type:"superpowers",dir:E.homeSuperpowersSkills,maxDepth:null}];for(let{type:X,dir:Z,maxDepth:Y}of Q){let H=K$(Z,X,Y);for(let W of H){let q=B1(Z,W);if(!$.has(q))$.add(q),I2(W,X)}}console.log(`Usage:
10
- superpowers-agent execute <skill-name> # Load a specific skill`)},G1=()=>{k();let $=process.argv[3];if(!$){console.log(`Usage: superpowers-agent execute <skill-name-or-alias>
3
+ import{relative as _Q,dirname as GQ,join as TX}from"path";import{existsSync as D$}from"fs";import{homedir as r$,platform as WX}from"os";import{join as M,parse as zX,dirname as s$}from"path";import{existsSync as d}from"fs";import{fileURLToPath as HX}from"url";var EX=HX(import.meta.url),K$=s$(EX),KX=()=>{let $=r$();switch(WX()){case"darwin":return M($,"Library","Application Support","Code","User");case"win32":return M($,"AppData","Roaming","Code","User");case"linux":return M($,".config","Code","User");default:return M($,".config","Code","User")}},BX=()=>{let $=process.cwd(),Q=zX($).root;while($!==Q){if(d(M($,".agents")))return $;$=s$($)}return process.cwd()},H={home:r$(),vscodeUserDir:KX(),projectRoot:BX(),get projectClaudeSkills(){return M(this.projectRoot,".claude","skills")},get projectAgentsSkills(){return M(this.projectRoot,".agents","skills")},get projectCopilotSkills(){return M(this.projectRoot,".copilot","skills")},get projectOpencodeSkills(){return M(this.projectRoot,".opencode","skill")},get projectSkillsDir(){return M(this.projectRoot,"skills")},get homePersonalSkills(){return M(this.home,".agents","skills")},get homeClaudeSkills(){return M(this.home,".claude","skills")},get homeCopilotSkills(){return M(this.home,".copilot","skills")},get claudeSettings(){return M(this.home,".claude","settings.json")},get copilotHooksDir(){return process.env.COPILOT_HOME?M(process.env.COPILOT_HOME,"hooks"):M(this.home,".copilot","hooks")},get homeOpencodeSkills(){return M(this.home,".config","opencode","skill")},get bootstrap(){return M(this.projectRoot,".agents","superpowers-bootstrap.md")},get superpowersRepo(){let $=M(K$,"..","..","..");if(d(M($,"skills"))&&d(M($,".agents","superpowers-agent")))return $;let Q=M(K$,"..");if(d(M(Q,"skills"))&&d(M(Q,".agents","superpowers-agent")))return Q;return M(this.home,".agents","superpowers")},get homeSuperpowersSkills(){return M(this.superpowersRepo,"skills")},get isSuperpowersRepo(){let $=M(K$,"..","..","..");if(d(M($,"skills"))&&d(M($,".agents","superpowers-agent")))return!0;let Q=M(K$,"..");return d(M(Q,"skills"))&&d(M(Q,".agents","superpowers-agent"))}};import{readFileSync as t$}from"fs";var X$=($)=>{try{let X=t$($,"utf8").split(`
4
+ `),Z={name:"",description:"",whenToUse:""},Y=!1;for(let q of X){if(q.trim()==="---"){if(Y)break;Y=!0;continue}if(Y){let z=q.match(/^(\w+):\s*(.*)$/);if(z){let[,W,K]=z,E={name:"name",description:"description",when_to_use:"whenToUse"};if(E[W])Z[E[W]]=K.trim()}}}return Z}catch{return{name:"",description:"",whenToUse:""}}},M$=($)=>{try{let Q=t$($,"utf8"),X=X$($),Z=Q.split(`
5
+ `),Y=!1,q=!1,z=[];for(let W of Z){if(W.trim()==="---"){if(Y){q=!0;continue}Y=!0;continue}if(q||!Y)z.push(W)}return{content:z.join(`
6
+ `).trim(),frontmatter:X}}catch(Q){throw Error(`Error reading skill file: ${Q.message}`)}};import{existsSync as T$,readdirSync as QQ,statSync as XQ}from"fs";import{join as v$,relative as aY}from"path";import{readFileSync as _X,existsSync as GX}from"fs";import{join as e$}from"path";var Y$=($)=>{let Q=e$($,"skill.json");if(!GX(Q))return null;try{let X=_X(Q,"utf8");return JSON.parse(X)}catch(X){return null}};var A$=($)=>{if($.startsWith("superpowers:"))return{type:"superpowers",path:$.substring(12).replace(/^skills\//,"")};if($.startsWith("claude:"))return{type:"claude",path:$.substring(7).replace(/^skills\//,"")};if($.startsWith("copilot:"))return{type:"copilot",path:$.substring(8).replace(/^skills\//,"")};if($.startsWith("opencode:"))return{type:"opencode",path:$.substring(9).replace(/^skills\//,"")};return{type:null,path:$.replace(/^skills\//,"")}},$Q=($,Q)=>{let X=Y$($);if(!X||!X.helpers||!Array.isArray(X.helpers))return null;let Z=X.helpers,Y=Q.toLowerCase(),q=null,z=0;for(let W of Z){let K=W.toLowerCase();if(K===Y){q=W;break}if(K.includes(Y)){let _=Y.length/K.length;if(_>z)z=_,q=W}let E=W.split("/").pop().split(".")[0].toLowerCase();if(Y.includes(E)){let _=E.length/Y.length;if(_>z)z=_,q=W}}return q?e$($,q):null},r={project:{dir:"projectAgentsSkills",prefix:""},claude:{dir:"projectClaudeSkills",prefix:"claude:"},copilot:{dir:"projectCopilotSkills",prefix:"copilot:"},opencode:{dir:"projectOpencodeSkills",prefix:"opencode:"},personal:{dir:"homePersonalSkills",prefix:""},personalClaude:{dir:"homeClaudeSkills",prefix:"claude:"},personalCopilot:{dir:"homeCopilotSkills",prefix:"copilot:"},personalOpencode:{dir:"homeOpencodeSkills",prefix:"opencode:"},superpowers:{dir:"homeSuperpowersSkills",prefix:"superpowers:"}};var B$=($,Q,X=null)=>{let Z=[];if(!T$($))return Z;let Y=(q,z)=>{if(X!==null&&z>X)return;try{let W=QQ(q,{withFileTypes:!0});for(let K of W){if(K.name==="node_modules"||K.name===".git"||K.name.startsWith("."))continue;let E=v$(q,K.name),_=K.isDirectory();if(K.isSymbolicLink())try{_=XQ(E).isDirectory()}catch{continue}if(!_)continue;let B=v$(E,"SKILL.md");if(T$(B))Z.push(E);if(X===null||z<X)Y(E,z+1)}}catch{}};return Y($,0),Z};var YQ=($,Q)=>{if(!T$($))return[];let X=[],Z=Q.toLowerCase().replace(/\\/g,"/"),Y=(q,z="")=>{try{let W=QQ(q,{withFileTypes:!0});for(let K of W){let E=v$(q,K.name),_=z?`${z}/${K.name}`:K.name,B=K.isDirectory();if(K.isSymbolicLink())try{B=XQ(E).isDirectory()}catch{continue}if(B&&(K.name==="node_modules"||K.name===".git"||K.name.startsWith(".")))continue;if(B)Y(E,_);else if(K.name==="SKILL.md"){let G=z.toLowerCase().replace(/\\/g,"/");if(G===Z||G.endsWith("/"+Z)||G.endsWith(Z))X.push({file:E,path:z})}}}catch(W){}};return Y($),X},ZQ=($,Q,X)=>{let Z={project:"project skills (.agents/skills/)",claude:"claude skills (.claude/skills/)",copilot:"copilot skills (.copilot/skills/)",opencode:"opencode skills (.opencode/skill/)",personal:"personal skills (~/.agents/skills/)",personalClaude:"personal claude skills (~/.claude/skills/)",personalCopilot:"personal copilot skills (~/.copilot/skills/)",personalOpencode:"personal opencode skills (~/.config/opencode/skill/)",superpowers:"superpowers skills (~/.agents/superpowers/skills/)"}[X];console.log(`Error: Multiple skills match "${$}" in ${Z}:
7
+ `);for(let Y of Q){let z=r[X].prefix+Y.path;try{let W=X$(Y.file),K=W.description||W.whenToUse||"(no description)";console.log(` ${z}`),console.log(` ${K}
8
+ `)}catch(W){console.log(` ${z}`),console.log(` (unable to read description)
9
+ `)}}console.log("Please be more specific. Examples:");for(let Y of Q.slice(0,2)){let q=r[X].prefix;console.log(` superpowers-agent execute ${q}${Y.path}`)}};import{existsSync as N$}from"fs";import{join as VX,relative as LX}from"path";var UX=($)=>{let{type:Q,path:X}=A$($),Z={superpowers:[H.homeSuperpowersSkills],claude:[H.projectClaudeSkills,H.homeClaudeSkills],copilot:[H.projectCopilotSkills,H.homeCopilotSkills],opencode:[H.projectOpencodeSkills,H.homeOpencodeSkills],project:[H.projectAgentsSkills],personal:[H.homePersonalSkills]},Y;if(Q)Y=(Z[Q]||[]).map((z)=>({type:Q,dir:z}));else if(H.isSuperpowersRepo&&N$(H.projectSkillsDir))Y=[{type:"project",dir:H.projectSkillsDir},{type:"project",dir:H.projectAgentsSkills},{type:"claude",dir:H.projectClaudeSkills},{type:"copilot",dir:H.projectCopilotSkills},{type:"opencode",dir:H.projectOpencodeSkills},{type:"personal",dir:H.homePersonalSkills},{type:"personalClaude",dir:H.homeClaudeSkills},{type:"personalCopilot",dir:H.homeCopilotSkills},{type:"personalOpencode",dir:H.homeOpencodeSkills},{type:"superpowers",dir:H.homeSuperpowersSkills}];else Y=[{type:"project",dir:H.projectAgentsSkills},{type:"claude",dir:H.projectClaudeSkills},{type:"copilot",dir:H.projectCopilotSkills},{type:"opencode",dir:H.projectOpencodeSkills},{type:"personal",dir:H.homePersonalSkills},{type:"personalClaude",dir:H.homeClaudeSkills},{type:"personalCopilot",dir:H.homeCopilotSkills},{type:"personalOpencode",dir:H.homeOpencodeSkills},{type:"superpowers",dir:H.homeSuperpowersSkills}];for(let{type:q,dir:z}of Y){let W=YQ(z,X);if(W.length===1)return{skillFile:W[0].file,sourceType:q,actualSkillPath:W[0].path};if(W.length>1)ZQ(X,W,q)}return null},m=($)=>{let Q=UX($);if(Q)return Q;let{type:X,path:Z}=A$($),Y={superpowers:[H.homeSuperpowersSkills],claude:[H.projectClaudeSkills,H.homeClaudeSkills],copilot:[H.projectCopilotSkills,H.homeCopilotSkills],opencode:[H.projectOpencodeSkills,H.homeOpencodeSkills],project:[H.projectAgentsSkills],personal:[H.homePersonalSkills]},q;if(X)q=(Y[X]||[]).map((W)=>({type:X,dir:W}));else if(H.isSuperpowersRepo&&N$(H.projectSkillsDir))q=[{type:"project",dir:H.projectSkillsDir},{type:"project",dir:H.projectAgentsSkills},{type:"claude",dir:H.projectClaudeSkills},{type:"copilot",dir:H.projectCopilotSkills},{type:"opencode",dir:H.projectOpencodeSkills},{type:"personal",dir:H.homePersonalSkills},{type:"personalClaude",dir:H.homeClaudeSkills},{type:"personalCopilot",dir:H.homeCopilotSkills},{type:"personalOpencode",dir:H.homeOpencodeSkills},{type:"superpowers",dir:H.homeSuperpowersSkills}];else q=[{type:"project",dir:H.projectAgentsSkills},{type:"claude",dir:H.projectClaudeSkills},{type:"copilot",dir:H.projectCopilotSkills},{type:"opencode",dir:H.projectOpencodeSkills},{type:"personal",dir:H.homePersonalSkills},{type:"personalClaude",dir:H.homeClaudeSkills},{type:"personalCopilot",dir:H.homeCopilotSkills},{type:"personalOpencode",dir:H.homeOpencodeSkills},{type:"superpowers",dir:H.homeSuperpowersSkills}];for(let{type:z,dir:W}of q){if(!N$(W))continue;let K=B$(W,z,null);for(let E of K){let _=Y$(E);if(_&&_.aliases&&Array.isArray(_.aliases)){let B=Z.toLowerCase();for(let G of _.aliases)if(G.toLowerCase()===B){let V=VX(E,"SKILL.md"),J=LX(W,E);return{skillFile:V,sourceType:z,actualSkillPath:J}}}}}return null};import{readFileSync as qQ,writeFileSync as WQ,existsSync as C$}from"fs";import{join as l}from"path";import{execSync as IX}from"child_process";var b$=()=>({auto_update:!0,last_update_check:null,last_updated_commit:null}),Z$=()=>{let $=l(H.superpowersRepo,".config.json");try{if(!C$($))return b$();let Q=qQ($,"utf8");return{...b$(),...JSON.parse(Q)}}catch{return b$()}},zQ=($)=>{let Q=l(H.superpowersRepo,".config.json"),Z={...Z$(),...$};try{WQ(Q,JSON.stringify(Z,null,2))}catch(Y){console.log(`Warning: couldn't save config: ${Y.message}`)}},y=($)=>{let Q=$?l(H.home,".agents","config.json"):l(process.cwd(),".agents","config.json");if(!C$(Q))return{};try{let X=qQ(Q,"utf8");return JSON.parse(X)}catch(X){return{}}},h=($,Q)=>{let X=Q?l(H.home,".agents"):l(process.cwd(),".agents"),Z=l(X,"config.json");try{if(!C$(X))IX(`mkdir -p "${X}"`,{stdio:"pipe"});return WQ(Z,JSON.stringify($,null,2),"utf8"),!0}catch(Y){throw Error(`Failed to write config: ${Y.message}`)}},k=($=!1)=>{return y($).repositories||{}},HQ=($,Q,X)=>{let Z=y(X);if(!Z.repositories)Z.repositories={};Z.repositories[$]=Q,h(Z,X)};function EQ($=!0){return y($).installedSkills||{}}function F$($,Q=!0){let X=y(Q);if(X.installedSkills)delete X.installedSkills[$];h(X,Q)}function KQ(){return y(!0).installedAgents||{}}import{readFileSync as JX}from"fs";import{join as j$,dirname as OX}from"path";import{fileURLToPath as wX}from"url";import{existsSync as BQ}from"fs";import{execSync as MX}from"child_process";var AX=wX(import.meta.url),x$=OX(AX),P=()=>{try{let $=j$(x$,"package.json");if(!BQ($))$=j$(x$,"..","package.json");if(!BQ($))$=j$(x$,"..","..","package.json");return JSON.parse(JX($,"utf8")).version||"0.0.0"}catch{return"0.0.0"}},u=()=>{let $=P();console.log(`^^SAV:${$}^^`)},_$=async()=>{try{let Q=MX('curl -sS "https://registry.npmjs.org/@complexthings/superpowers-agent/latest"',{encoding:"utf8",timeout:1e4}),X=JSON.parse(Q);if(!X.version)return P();return X.version}catch($){throw Error(`Failed to fetch remote version: ${$.message}`)}},G$=($,Q)=>{let X=$.split(".").map(Number),Z=Q.split(".").map(Number);for(let Y=0;Y<3;Y++){let q=X[Y]||0,z=Z[Y]||0;if(q>z)return!0;if(q<z)return!1}return!1};var vX={project:{dir:"projectAgentsSkills",prefix:""},claude:{dir:"projectClaudeSkills",prefix:"claude:"},copilot:{dir:"projectCopilotSkills",prefix:"copilot:"},opencode:{dir:"projectOpencodeSkills",prefix:"opencode:"},personal:{dir:"homePersonalSkills",prefix:""},personalClaude:{dir:"homeClaudeSkills",prefix:"claude:"},personalCopilot:{dir:"homeCopilotSkills",prefix:"copilot:"},personalOpencode:{dir:"homeOpencodeSkills",prefix:"opencode:"},superpowers:{dir:"homeSuperpowersSkills",prefix:"superpowers:"}},NX=($,Q)=>{let X=TX($,"SKILL.md"),{dir:Z,prefix:Y}=vX[Q],q=_Q(H[Z],$).replace(/\\/g,"/");console.log(`${Y}${q}`);let{description:z,whenToUse:W}=X$(X);if(z)console.log(` ${z}`);if(W)console.log(` When to use: ${W}`);console.log("")},s=()=>{u();let $=new Set,Q=[{type:"project",dir:H.projectAgentsSkills,maxDepth:null},{type:"claude",dir:H.projectClaudeSkills,maxDepth:null},{type:"copilot",dir:H.projectCopilotSkills,maxDepth:null},{type:"opencode",dir:H.projectOpencodeSkills,maxDepth:null},{type:"personal",dir:H.homePersonalSkills,maxDepth:null},{type:"personalClaude",dir:H.homeClaudeSkills,maxDepth:null},{type:"personalCopilot",dir:H.homeCopilotSkills,maxDepth:null},{type:"personalOpencode",dir:H.homeOpencodeSkills,maxDepth:null},{type:"superpowers",dir:H.homeSuperpowersSkills,maxDepth:null}];for(let{type:X,dir:Z,maxDepth:Y}of Q){let q=B$(Z,X,Y);for(let z of q){let W=_Q(Z,z);if(!$.has(W))$.add(W),NX(z,X)}}console.log(`Usage:
10
+ superpowers-agent execute <skill-name> # Load a specific skill`)},VQ=()=>{u();let $=process.argv[3];if(!$){console.log(`Usage: superpowers-agent execute <skill-name-or-alias>
11
11
 
12
12
  Examples:
13
13
  superpowers-agent execute brainstorming
@@ -17,13 +17,13 @@ Examples:
17
17
 
18
18
  Description:
19
19
  Instructs the agent to execute the specified skill.
20
- Supports skill aliases defined in skill.json files.`);return}let Q=i($);if(!Q){console.log(`Error: Skill not found: ${$}
20
+ Supports skill aliases defined in skill.json files.`);return}let Q=m($);if(!Q){console.log(`Error: Skill not found: ${$}
21
21
 
22
- Available skills:`),a();return}let{skillFile:X,sourceType:Z}=Q,Y=process.cwd(),H=X.startsWith(Y),W=x$(E.projectAgentsSkills)||x$(E.projectClaudeSkills);if(H)console.log(`Open this file with your Read Tool: ${X}
22
+ Available skills:`),s();return}let{skillFile:X,sourceType:Z}=Q,Y=process.cwd(),q=X.startsWith(Y),z=D$(H.projectAgentsSkills)||D$(H.projectClaudeSkills);if(q)console.log(`Open this file with your Read Tool: ${X}
23
23
 
24
24
  <IMPORTANT>
25
25
  USE YOUR Read Tool to process this file. DO NOT use \`cat\` or print commands.
26
- </IMPORTANT>`);else if(W&&Z!=="project")console.log(`Open this file with your Read Tool: ${X}
26
+ </IMPORTANT>`);else if(z&&Z!=="project")console.log(`Open this file with your Read Tool: ${X}
27
27
 
28
28
  <IMPORTANT>
29
29
  1. Try using your Read Tool first
@@ -36,7 +36,7 @@ USE YOUR Read Tool to process this file. DO NOT use \`cat\` or print commands.
36
36
  1. Try using your Read Tool first
37
37
  2. If your Read tool fails (file outside workspace), use: cat "${X}"
38
38
  3. NEVER skip loading the skill content
39
- </IMPORTANT>`)},V1=()=>{let $=process.argv[3];if(!$){console.log(`Usage: superpowers-agent path <skill-name-or-alias>
39
+ </IMPORTANT>`)},LQ=()=>{let $=process.argv[3];if(!$){console.log(`Usage: superpowers-agent path <skill-name-or-alias>
40
40
 
41
41
  Examples:
42
42
  superpowers-agent path brainstorming
@@ -46,9 +46,9 @@ Examples:
46
46
 
47
47
  Description:
48
48
  Outputs the file system path of the specified SKILL.md file.
49
- Supports skill aliases defined in skill.json files.`);return}let Q=i($);if(!Q){console.log(`Error: Skill not found: ${$}
49
+ Supports skill aliases defined in skill.json files.`);return}let Q=m($);if(!Q){console.log(`Error: Skill not found: ${$}
50
50
 
51
- Available skills:`),a();return}let{skillFile:X}=Q;console.log(X)},L1=()=>{let $=process.argv[3];if(!$){console.log(`Usage: superpowers-agent dir <skill-name>
51
+ Available skills:`),s();return}let{skillFile:X}=Q;console.log(X)},UQ=()=>{let $=process.argv[3];if(!$){console.log(`Usage: superpowers-agent dir <skill-name>
52
52
 
53
53
  Examples:
54
54
  superpowers-agent dir brainstorming
@@ -58,9 +58,9 @@ Examples:
58
58
 
59
59
  Description:
60
60
  Returns the directory path where the specified skill is located.
61
- Supports skill aliases defined in skill.json files.`);return}let Q=i($);if(!Q){console.log(`Error: Skill not found: ${$}
61
+ Supports skill aliases defined in skill.json files.`);return}let Q=m($);if(!Q){console.log(`Error: Skill not found: ${$}
62
62
 
63
- Available skills:`),a();return}let{skillFile:X}=Q,Z=_1(X);console.log(Z)},w1=()=>{k();let $=process.argv[3],Q=process.argv[4];if(!$||!Q){console.log(`Usage: superpowers-agent get-helpers <skill-name> <helper-search-term>
63
+ Available skills:`),s();return}let{skillFile:X}=Q,Z=GQ(X);console.log(Z)},IQ=()=>{u();let $=process.argv[3],Q=process.argv[4];if(!$||!Q){console.log(`Usage: superpowers-agent get-helpers <skill-name> <helper-search-term>
64
64
 
65
65
  Examples:
66
66
  superpowers-agent get-helpers block-collection search-block
@@ -72,116 +72,118 @@ Description:
72
72
  Returns the full path to the best matching helper file.
73
73
 
74
74
  The command uses the skill's aliases if available, so you can use
75
- short names like "block-collection" instead of the full path.`);return}let X=i($);if(!X){console.log(`Error: Skill not found: ${$}
75
+ short names like "block-collection" instead of the full path.`);return}let X=m($);if(!X){console.log(`Error: Skill not found: ${$}
76
76
 
77
- Available skills:`),a();return}let{skillFile:Z}=X,Y=_1(Z),H=Q$(Y);if(!H){console.log(`Error: No skill.json found for skill: ${$}
78
- Location: ${Y}`);return}if(!H.helpers||!Array.isArray(H.helpers)||H.helpers.length===0){console.log(`Error: No helpers defined in skill.json for skill: ${$}
79
- Location: ${Y}`);return}let W=e$(Y,Q);if(!W){console.log(`Error: No helper found matching "${Q}" in skill: ${$}`),console.log(`
80
- Available helpers:`);for(let q of H.helpers)console.log(` - ${q}`);return}if(!x$(W)){console.log(`Error: Helper file not found: ${W}
81
- Defined in skill.json but missing from filesystem`);return}console.log(W)},U1=()=>{let $=Y$();console.log("Current configuration:"),console.log(JSON.stringify($,null,2))},I1=()=>{let $=process.argv[3],Q=process.argv[4];if(!$||Q===void 0){console.log(`Usage: .agents/superpowers-agent config-set <key> <value>
77
+ Available skills:`),s();return}let{skillFile:Z}=X,Y=GQ(Z),q=Y$(Y);if(!q){console.log(`Error: No skill.json found for skill: ${$}
78
+ Location: ${Y}`);return}if(!q.helpers||!Array.isArray(q.helpers)||q.helpers.length===0){console.log(`Error: No helpers defined in skill.json for skill: ${$}
79
+ Location: ${Y}`);return}let z=$Q(Y,Q);if(!z){console.log(`Error: No helper found matching "${Q}" in skill: ${$}`),console.log(`
80
+ Available helpers:`);for(let W of q.helpers)console.log(` - ${W}`);return}if(!D$(z)){console.log(`Error: Helper file not found: ${z}
81
+ Defined in skill.json but missing from filesystem`);return}console.log(z)},JQ=()=>{let $=Z$();console.log("Current configuration:"),console.log(JSON.stringify($,null,2))},OQ=()=>{let $=process.argv[3],Q=process.argv[4];if(!$||Q===void 0){console.log(`Usage: .agents/superpowers-agent config-set <key> <value>
82
82
 
83
83
  Available keys:
84
84
  auto_update (true/false) - Enable/disable automatic updates during bootstrap
85
85
 
86
86
  Examples:
87
87
  .agents/superpowers-agent config-set auto_update false
88
- .agents/superpowers-agent config-set auto_update true`);return}let X=Q;if(Q==="true")X=!0;else if(Q==="false")X=!1;let Z={};Z[$]=X,q1(Z),console.log(`✓ Set ${$} = ${X}`)},O1=()=>{k();let $=P(!0),Q=P(!1),X=[];for(let[H,W]of Object.entries($))X.push({alias:H,url:W,source:"global"});for(let[H,W]of Object.entries(Q)){let q=X.findIndex((K)=>K.alias===H);if(q>=0)X[q]={alias:H,url:W,source:"project"};else X.push({alias:H,url:W,source:"project"})}if(X.length===0){console.log(`No repository aliases configured.
88
+ .agents/superpowers-agent config-set auto_update true`);return}let X=Q;if(Q==="true")X=!0;else if(Q==="false")X=!1;let Z={};Z[$]=X,zQ(Z),console.log(`✓ Set ${$} = ${X}`)},wQ=()=>{u();let $=k(!0),Q=k(!1),X=[];for(let[q,z]of Object.entries($))X.push({alias:q,url:z,source:"global"});for(let[q,z]of Object.entries(Q)){let W=X.findIndex((K)=>K.alias===q);if(W>=0)X[W]={alias:q,url:z,source:"project"};else X.push({alias:q,url:z,source:"project"})}if(X.length===0){console.log(`No repository aliases configured.
89
89
 
90
90
  Add a repository using:
91
- superpowers-agent add-repository <git-url> [--as=@alias]`);return}let Z=Math.max(5,...X.map((H)=>H.alias.length)),Y=Math.max(3,...X.map((H)=>H.url.length));console.log(`Repositories:
92
- `),console.log(`${"Alias".padEnd(Z)} ${"URL".padEnd(Y)} Source`);for(let H of X)console.log(`${H.alias.padEnd(Z)} ${H.url.padEnd(Y)} (${H.source})`);console.log(`
93
- Total: ${X.length} repository alias(es)`)};var G$=async()=>{try{let $=g(),Q=await B$();return{hasUpdates:_$(Q,$),localVersion:$,remoteVersion:Q}}catch{return{hasUpdates:!1,localVersion:g(),remoteVersion:"",error:!0}}};import{execSync as J1}from"child_process";var D$=async({skipReinstall:$=!1}={})=>{console.log(`# Checking for Superpowers updates...
94
- `);let Q=await G$();if(Q.error){console.log("⚠️ Could not check for updates (network issue)");return}if(!Q.hasUpdates){console.log(`✓ Already up to date (v${Q.localVersion})`);return}if(console.log(`\uD83D\uDCE6 Update available: v${Q.localVersion} → v${Q.remoteVersion}
91
+ superpowers-agent add-repository <git-url> [--as=@alias]`);return}let Z=Math.max(5,...X.map((q)=>q.alias.length)),Y=Math.max(3,...X.map((q)=>q.url.length));console.log(`Repositories:
92
+ `),console.log(`${"Alias".padEnd(Z)} ${"URL".padEnd(Y)} Source`);for(let q of X)console.log(`${q.alias.padEnd(Z)} ${q.url.padEnd(Y)} (${q.source})`);console.log(`
93
+ Total: ${X.length} repository alias(es)`)};var V$=async()=>{try{let $=P(),Q=await _$();return{hasUpdates:G$(Q,$),localVersion:$,remoteVersion:Q}}catch{return{hasUpdates:!1,localVersion:P(),remoteVersion:"",error:!0}}};import{execSync as MQ}from"child_process";var R$=async({skipReinstall:$=!1}={})=>{console.log(`# Checking for Superpowers updates...
94
+ `);let Q=await V$();if(Q.error){console.log("⚠️ Could not check for updates (network issue)");return}if(!Q.hasUpdates){console.log(`✓ Already up to date (v${Q.localVersion})`);return}if(console.log(`\uD83D\uDCE6 Update available: v${Q.localVersion} → v${Q.remoteVersion}
95
95
  `),$){console.log(" Skipping install (--no-reinstall flag set)"),console.log(` Run manually: npm install -g @complexthings/superpowers-agent
96
96
  `);return}console.log(` Installing update...
97
- `);try{J1("npm install -g @complexthings/superpowers-agent",{stdio:"inherit"}),console.log(`
97
+ `);try{MQ("npm install -g @complexthings/superpowers-agent",{stdio:"inherit"}),console.log(`
98
98
  ✓ Update complete!`)}catch(X){console.log(`
99
99
  ✗ Update failed: ${X.message}`),console.log(" Try running manually: npm install -g @complexthings/superpowers-agent"),process.exit(1)}console.log(`
100
100
  Running bootstrap to complete setup...
101
- `);try{J1("superpowers-agent bootstrap --no-update",{stdio:"inherit"}),console.log(`
101
+ `);try{MQ("superpowers-agent bootstrap --no-update",{stdio:"inherit"}),console.log(`
102
102
  ✓ Bootstrap complete!`)}catch(X){console.log(`
103
- ⚠️ Bootstrap step failed: ${X.message}`),console.log(" The update installed successfully. Run manually to finish setup:"),console.log(" superpowers-agent bootstrap")}},A1=async()=>{k();let $=g();console.log(`Current version: ${$}`);try{let Q=await B$();if(console.log(`Latest version: ${Q}`),_$(Q,$))console.log("Update available: Yes"),process.exit(1);else console.log("You are up to date"),process.exit(0)}catch(Q){console.log(`Error checking for updates: ${Q.message}`),process.exit(1)}},M1=()=>{let $=g();console.log($)};import{existsSync as M,readFileSync as o,writeFileSync as t,rmSync as u1,lstatSync as p2}from"fs";import{join as C,dirname as P1,parse as Z$}from"path";import{execSync as R}from"child_process";import{platform as h2}from"os";import{execSync as O2}from"child_process";var j$=($)=>{try{return O2(`which ${$}`,{stdio:"pipe",timeout:2000}),!0}catch{return!1}};var D={opencode:{check:()=>j$("opencode"),cli:!0,name:"OpenCode",installUrl:"https://opencode.ai/docs/installation",bootstrapCommand:"install-opencode-commands"},claude:{check:()=>j$("claude"),cli:!0,name:"Claude Code",installUrl:"https://code.claude.com/docs/en/installation",bootstrapCommand:"install-claude-commands"},copilot:{check:()=>!0,cli:!1,name:"GitHub Copilot",bootstrapCommand:"install-copilot-prompts"}},T1=()=>{let $=[];if(D.copilot.check())$.push("github-copilot");if(D.claude.check())$.push("claude-code");if(D.opencode.check())$.push("opencode");return $};import{existsSync as R$,readdirSync as VQ,lstatSync as J2,symlinkSync as C1,unlinkSync as A2,mkdirSync as M2,readlinkSync as T2}from"fs";import{join as S$,dirname as wQ}from"path";import{platform as C2}from"os";var y$=($)=>{try{return J2($).isSymbolicLink()}catch{return!1}},v2=($,Q)=>{try{if(!y$($))return!1;return T2($)===Q}catch{return!1}},v1=()=>{let $=S$(E.superpowersRepo,".opencode","plugins","superpowers-agent.js"),Q=S$(E.home,".config","opencode","plugins"),X=S$(Q,"superpowers-agent.js");if(console.log("Installing OpenCode plugin symlink..."),!R$($))return console.log("⚠️ Source plugin not found, skipping symlink creation"),console.log(` Expected at: ${$}`),{created:!1,error:"Source plugin not found"};if(v2(X,$))return console.log("✓ Plugin symlink already exists and is correct"),{created:!1,existed:!0};if(R$(X)&&!y$(X))return console.log("⚠️ Warning: A file already exists at the destination path"),console.log(` Path: ${X}`),console.log(" Skipping symlink creation to avoid overwriting existing file"),console.log(" To use superpowers-agent plugin, manually remove or rename the existing file"),{created:!1,error:"File already exists at destination"};if(!R$(Q))try{M2(Q,{recursive:!0}),console.log(`✓ Created ${Q.replace(E.home,"~")}`)}catch(Y){return console.log(`⚠️ Failed to create plugins directory: ${Y.message}`),{created:!1,error:`Failed to create directory: ${Y.message}`}}if(y$(X))try{A2(X)}catch(Y){return console.log(`⚠️ Failed to remove existing symlink: ${Y.message}`),{created:!1,error:`Failed to remove existing symlink: ${Y.message}`}}let Z=C2();try{if(Z==="win32")C1($,X,"file");else C1($,X);let Y=$.replace(E.home,"~"),H=X.replace(E.home,"~");return console.log(`✓ Created symlink: ${H}`),console.log(` -> ${Y}`),{created:!0}}catch(Y){if(Z==="win32"&&Y.code==="EPERM")return console.log("⚠️ Windows requires Developer Mode or admin privileges for symlinks"),console.log(" Enable Developer Mode: Settings > Update & Security > For developers"),{created:!1,error:"Windows symlink permission denied"};return console.log(`⚠️ Failed to create symlink: ${Y.message}`),{created:!1,error:`Failed to create symlink: ${Y.message}`}}};import{existsSync as l,readdirSync as b2,lstatSync as N2,symlinkSync as V$,unlinkSync as f$,mkdirSync as b1,readlinkSync as F2}from"fs";import{join as c,dirname as x2,basename as D2}from"path";import{homedir as n,platform as N1}from"os";var L$=[{name:"claude",parentDir:()=>c(n(),".claude"),skillsDir:()=>c(n(),".claude","skills")},{name:"copilot",parentDir:()=>c(n(),".copilot"),skillsDir:()=>c(n(),".copilot","skills")},{name:"opencode",parentDir:()=>c(n(),".config","opencode"),skillsDir:()=>c(n(),".config","opencode","skill")}],s=($)=>{try{return N2($).isSymbolicLink()}catch{return!1}},F1=($,Q)=>{try{if(!s($))return!1;return F2($)===Q}catch{return!1}},x1=($,Q)=>{if(!l($))return{created:!1,existed:!1,error:`Source does not exist: ${$}`};if(F1(Q,$))return{created:!1,existed:!0};if(l(Q)||s(Q))if(s(Q))try{f$(Q)}catch(Y){return{created:!1,existed:!1,error:`Failed to remove existing symlink: ${Y.message}`}}else return{created:!1,existed:!1,error:`Target exists and is not a symlink: ${Q}`};let X=x2(Q);if(!l(X))try{b1(X,{recursive:!0})}catch(Y){return{created:!1,existed:!1,error:`Failed to create parent directory: ${Y.message}`}}let Z=N1();try{if(Z==="win32")V$($,Q,"junction");else V$($,Q,"dir");return{created:!0,existed:!1}}catch(Y){if(Z==="win32"&&Y.code==="EPERM")return{created:!1,existed:!1,error:"Windows requires Developer Mode or admin privileges for symlinks. Enable Developer Mode: Settings > Update & Security > For developers"};return{created:!1,existed:!1,error:`Failed to create symlink: ${Y.message}`}}},g$=($)=>{if(!l($)&&!s($))return{removed:!1,error:"Symlink does not exist"};if(!s($))return{removed:!1,error:"Target is not a symlink"};try{return f$($),{removed:!0}}catch(Q){return{removed:!1,error:`Failed to remove symlink: ${Q.message}`}}};var D1=($,Q,X="skills")=>{let Z=y(!0);if(!Z.symlinks||!Z.symlinks[$])return;if(X==="superpowers")Z.symlinks[$].superpowers=null;else{let Y=Z.symlinks[$].skills||[];Z.symlinks[$].skills=Y.filter((H)=>H!==Q)}m(Z,!0)};var j1=($,Q=[])=>{let X;try{X=b2($,{withFileTypes:!0})}catch{return Q}let Z=!1,Y=[];for(let H of X){if(!H.isDirectory()&&H.name==="SKILL.md")Z=!0;if(H.isDirectory()&&!H.name.startsWith("."))Y.push(c($,H.name))}if(Z)Q.push($);for(let H of Y)j1(H,Q);return Q},R1=()=>{let $=E.homeSuperpowersSkills,Q=E.homePersonalSkills;if(!l($))return{created:0,existed:0,updated:0,errors:[`Skills directory not found: ${$}`]};if(!l(Q))try{b1(Q,{recursive:!0})}catch(Y){return{created:0,existed:0,updated:0,errors:[`Failed to create ${Q}: ${Y.message}`]}}let X=j1($),Z={created:0,existed:0,updated:0,errors:[]};for(let Y of X){let H=D2(Y),W=c(Q,H);if(F1(W,Y)){Z.existed++;continue}if(s(W))try{f$(W),Z.updated++}catch(K){Z.errors.push(`Failed to remove stale symlink ${W}: ${K.message}`);continue}else if(l(W)){Z.errors.push(`Skipped ${W}: path exists and is not a symlink`);continue}let q=N1();try{if(q==="win32")V$(Y,W,"junction");else V$(Y,W,"dir");let K=W.replace(n(),"~"),z=Y.replace(n(),"~");console.log(` ✓ ${K} -> ${z}`),Z.created++}catch(K){Z.errors.push(`Failed to create symlink ${W}: ${K.message}`)}}return Z};import{existsSync as S1,readdirSync as j2,lstatSync as R2,unlinkSync as S2,realpathSync as y1}from"fs";import{join as j}from"path";import{homedir as f1}from"os";var y2=($)=>{try{return y1($)}catch{return $}},f2=($)=>{try{return R2($).isSymbolicLink()}catch{return!1}},g2=($)=>{try{return y1($)}catch{return null}},u2=($,Q)=>{let X=Q.endsWith("/")?Q:Q+"/";return $.startsWith(X)||$===Q},P2=($,Q)=>Q.some((X)=>u2($,X)),k2=($)=>{try{return S1(j($,"skill.json"))}catch{return!1}},d2=({platformDirs:$,managedSkillRoots:Q})=>{let X=[],Z=0,Y=Q.map(y2);for(let H of $){if(!S1(H))continue;let W;try{W=j2(H)}catch{continue}for(let q of W){let K=j(H,q);if(!f2(K))continue;let z=g2(K);if(!z||!P2(z,Y)){Z++;continue}if(!k2(z)){Z++;continue}try{S2(K),X.push(K)}catch{Z++}}}return{removed:X,skipped:Z}},m2=($)=>{let Q=f1(),X=[j(Q,".claude","skills"),j(Q,".copilot","skills"),j(Q,".config","opencode","skill"),j(Q,".cursor","skills"),j(Q,".gemini","skills"),j(Q,".codex","skills")];if(!$)return X;let Z=[j($,".claude","skills"),j($,".github","skills"),j($,".opencode","skill"),j($,".cursor","skills"),j($,".gemini","skills"),j($,".codex","skills")];return[...X,...Z]},g1=($={})=>{let Q=f1(),X=[j(Q,".agents","skills"),...$.projectRoot?[j($.projectRoot,".agents","skills")]:[]],Z=m2($.projectRoot);return d2({platformDirs:Z,managedSkillRoots:X})};var c2=()=>{let $=C(E.superpowersRepo,".agents","templates","TOOLS.md.template");if(M($))try{return o($,"utf8").trim()}catch(Q){return"### Using Tools\n\nUse your native skill tool. Fallback: `superpowers-agent find-skills`"}return""},w$=($,Q,X,Z=!0)=>{let Y=M($);if(!Y&&!Z)return{updated:!1,created:!1,skipped:!0};let H=c2(),W=Q.replace(/\{\{TOOL_MAPPINGS\}\}/g,H),q=new Date().toISOString().split("T")[0];W=W.replace(/\{\{DATE\}\}/g,q),W=W.replace(/\{\{SUPERPOWERS_PATH\}\}/g,E.superpowersRepo);let K=`<!-- SUPERPOWERS_SKILLS_START -->
104
- ${W}
105
- <!-- SUPERPOWERS_SKILLS_END -->`;if(Y){let z=new Date().toISOString().split("T")[0],_=`${$}.backup-${z}`;try{R(`cp "${$}" "${_}"`,{stdio:"pipe"})}catch(w){return{updated:!1,error:!0,message:`Failed to backup: ${w.message}`}}let B;try{B=o($,"utf8")}catch(w){return{updated:!1,error:!0,message:`Failed to read: ${w.message}`}}let G="<!-- SUPERPOWERS_SKILLS_START -->",V="<!-- SUPERPOWERS_SKILLS_END -->",I;if(B.includes(G)&&B.includes(V)){let w=new RegExp(`${G}[\\s\\S]*?${V}`,"g");I=B.replace(w,K)}else{let w=B.match(/^#\s+.+$/m);if(w){let J=B.indexOf(`
106
- `,w.index)+1;I=B.slice(0,J)+`
103
+ ⚠️ Bootstrap step failed: ${X.message}`),console.log(" The update installed successfully. Run manually to finish setup:"),console.log(" superpowers-agent bootstrap")}},AQ=async()=>{u();let $=P();console.log(`Current version: ${$}`);try{let Q=await _$();if(console.log(`Latest version: ${Q}`),G$(Q,$))console.log("Update available: Yes"),process.exit(1);else console.log("You are up to date"),process.exit(0)}catch(Q){console.log(`Error checking for updates: ${Q.message}`),process.exit(1)}},TQ=()=>{let $=P();console.log($)};import{existsSync as A,readFileSync as i,writeFileSync as $$,rmSync as mQ,lstatSync as EY}from"fs";import{join as T,dirname as hQ,parse as e}from"path";import{execSync as R}from"child_process";import{platform as KY}from"os";import{execSync as bX}from"child_process";var q$=($)=>{try{return bX(`which ${$}`,{stdio:"pipe",timeout:2000}),!0}catch{return!1}};var D={opencode:{check:()=>q$("opencode"),cli:!0,name:"OpenCode",installUrl:"https://opencode.ai/docs/installation",bootstrapCommand:"install-opencode-commands"},claude:{check:()=>q$("claude"),cli:!0,name:"Claude Code",installUrl:"https://code.claude.com/docs/en/installation",bootstrapCommand:"install-claude-commands"},copilot:{check:()=>!0,cli:!1,name:"GitHub Copilot",bootstrapCommand:"install-copilot-prompts"}},vQ=()=>{let $=[];if(D.copilot.check())$.push("github-copilot");if(D.claude.check())$.push("claude-code");if(D.opencode.check())$.push("opencode");return $};import{existsSync as f$,readdirSync as kZ,lstatSync as CX,symlinkSync as NQ,unlinkSync as FX,mkdirSync as jX,readlinkSync as xX}from"fs";import{join as y$,dirname as dZ}from"path";import{platform as DX}from"os";var S$=($)=>{try{return CX($).isSymbolicLink()}catch{return!1}},RX=($,Q)=>{try{if(!S$($))return!1;return xX($)===Q}catch{return!1}},bQ=()=>{let $=y$(H.superpowersRepo,".opencode","plugins","superpowers-agent.js"),Q=y$(H.home,".config","opencode","plugins"),X=y$(Q,"superpowers-agent.js");if(console.log("Installing OpenCode plugin symlink..."),!f$($))return console.log("⚠️ Source plugin not found, skipping symlink creation"),console.log(` Expected at: ${$}`),{created:!1,error:"Source plugin not found"};if(RX(X,$))return console.log("✓ Plugin symlink already exists and is correct"),{created:!1,existed:!0};if(f$(X)&&!S$(X))return console.log("⚠️ Warning: A file already exists at the destination path"),console.log(` Path: ${X}`),console.log(" Skipping symlink creation to avoid overwriting existing file"),console.log(" To use superpowers-agent plugin, manually remove or rename the existing file"),{created:!1,error:"File already exists at destination"};if(!f$(Q))try{jX(Q,{recursive:!0}),console.log(`✓ Created ${Q.replace(H.home,"~")}`)}catch(Y){return console.log(`⚠️ Failed to create plugins directory: ${Y.message}`),{created:!1,error:`Failed to create directory: ${Y.message}`}}if(S$(X))try{FX(X)}catch(Y){return console.log(`⚠️ Failed to remove existing symlink: ${Y.message}`),{created:!1,error:`Failed to remove existing symlink: ${Y.message}`}}let Z=DX();try{if(Z==="win32")NQ($,X,"file");else NQ($,X);let Y=$.replace(H.home,"~"),q=X.replace(H.home,"~");return console.log(`✓ Created symlink: ${q}`),console.log(` -> ${Y}`),{created:!0}}catch(Y){if(Z==="win32"&&Y.code==="EPERM")return console.log("⚠️ Windows requires Developer Mode or admin privileges for symlinks"),console.log(" Enable Developer Mode: Settings > Update & Security > For developers"),{created:!1,error:"Windows symlink permission denied"};return console.log(`⚠️ Failed to create symlink: ${Y.message}`),{created:!1,error:`Failed to create symlink: ${Y.message}`}}};import{existsSync as CQ,readdirSync as nZ,readFileSync as fX,writeFileSync as yX,mkdirSync as SX,copyFileSync as PX}from"fs";import{join as iZ,dirname as gX}from"path";var kX="superpowers-agent session-context",uX="superpowers-agent session-context --format=claude 2>/dev/null || true",dX="startup|resume|clear|compact",FQ=($=H.claudeSettings)=>{let Q={},X=!1,Z;if(CQ($)){X=!0;let _;try{_=fX($,"utf8")}catch(G){return{error:!0,message:`Failed to read settings.json: ${G.message}`}}try{Q=_.trim()?JSON.parse(_):{}}catch(G){return{error:!0,message:`settings.json is not valid JSON, leaving it untouched: ${G.message}`}}let B=new Date().toISOString().split("T")[0];Z=`${$}.backup-${B}`;try{PX($,Z)}catch(G){return{error:!0,message:`Failed to back up settings.json: ${G.message}`}}}if(typeof Q!=="object"||Q===null||Array.isArray(Q))return{error:!0,message:"settings.json root is not an object"};Q.hooks=Q.hooks||{};let Y=Array.isArray(Q.hooks.SessionStart)?Q.hooks.SessionStart:[],q=(_)=>{try{return JSON.stringify(_).includes(kX)}catch{return!1}},z=Y.some(q),W=Y.filter((_)=>!q(_)),K={matcher:dX,hooks:[{type:"command",command:uX}]};Q.hooks.SessionStart=[...W,K];let E=gX($);if(!CQ(E))try{SX(E,{recursive:!0})}catch(_){return{error:!0,message:`Failed to create ${E}: ${_.message}`}}try{yX($,JSON.stringify(Q,null,2)+`
104
+ `,"utf8")}catch(_){return{error:!0,message:`Failed to write settings.json: ${_.message}`}}if(!X)return{created:!0};if(z)return{existed:!0,updated:!0,backup:Z};return{updated:!0,backup:Z}};import{existsSync as P$,readdirSync as sZ,readFileSync as mX,writeFileSync as hX,mkdirSync as pX}from"fs";import{join as cX}from"path";var nX="superpowers.json",oX=()=>({version:1,hooks:{sessionStart:[{type:"command",bash:"superpowers-agent session-context --format=copilot 2>/dev/null || true",powershell:"superpowers-agent session-context --format=copilot 2>$null; exit 0",timeoutSec:15}]}}),jQ=($=H.copilotHooksDir)=>{let Q=cX($,nX),X=JSON.stringify(oX(),null,2)+`
105
+ `;if(P$(Q)){let Y;try{Y=mX(Q,"utf8")}catch(q){return{error:!0,message:`Failed to read ${Q}: ${q.message}`}}if(Y===X)return{existed:!0,path:Q}}if(!P$($))try{pX($,{recursive:!0})}catch(Y){return{error:!0,message:`Failed to create ${$}: ${Y.message}`}}let Z=P$(Q);try{hX(Q,X,"utf8")}catch(Y){return{error:!0,message:`Failed to write ${Q}: ${Y.message}`}}return Z?{updated:!0,path:Q}:{created:!0,path:Q}};import{existsSync as a,readdirSync as iX,lstatSync as lX,symlinkSync as L$,unlinkSync as g$,mkdirSync as xQ,readlinkSync as aX}from"fs";import{join as n,dirname as rX,basename as sX}from"path";import{homedir as o,platform as DQ}from"os";var U$=[{name:"claude",parentDir:()=>n(o(),".claude"),skillsDir:()=>n(o(),".claude","skills")},{name:"copilot",parentDir:()=>n(o(),".copilot"),skillsDir:()=>n(o(),".copilot","skills")},{name:"opencode",parentDir:()=>n(o(),".config","opencode"),skillsDir:()=>n(o(),".config","opencode","skill")}],t=($)=>{try{return lX($).isSymbolicLink()}catch{return!1}},RQ=($,Q)=>{try{if(!t($))return!1;return aX($)===Q}catch{return!1}},fQ=($,Q)=>{if(!a($))return{created:!1,existed:!1,error:`Source does not exist: ${$}`};if(RQ(Q,$))return{created:!1,existed:!0};if(a(Q)||t(Q))if(t(Q))try{g$(Q)}catch(Y){return{created:!1,existed:!1,error:`Failed to remove existing symlink: ${Y.message}`}}else return{created:!1,existed:!1,error:`Target exists and is not a symlink: ${Q}`};let X=rX(Q);if(!a(X))try{xQ(X,{recursive:!0})}catch(Y){return{created:!1,existed:!1,error:`Failed to create parent directory: ${Y.message}`}}let Z=DQ();try{if(Z==="win32")L$($,Q,"junction");else L$($,Q,"dir");return{created:!0,existed:!1}}catch(Y){if(Z==="win32"&&Y.code==="EPERM")return{created:!1,existed:!1,error:"Windows requires Developer Mode or admin privileges for symlinks. Enable Developer Mode: Settings > Update & Security > For developers"};return{created:!1,existed:!1,error:`Failed to create symlink: ${Y.message}`}}},k$=($)=>{if(!a($)&&!t($))return{removed:!1,error:"Symlink does not exist"};if(!t($))return{removed:!1,error:"Target is not a symlink"};try{return g$($),{removed:!0}}catch(Q){return{removed:!1,error:`Failed to remove symlink: ${Q.message}`}}};var yQ=($,Q,X="skills")=>{let Z=y(!0);if(!Z.symlinks||!Z.symlinks[$])return;if(X==="superpowers")Z.symlinks[$].superpowers=null;else{let Y=Z.symlinks[$].skills||[];Z.symlinks[$].skills=Y.filter((q)=>q!==Q)}h(Z,!0)};var SQ=($,Q=[])=>{let X;try{X=iX($,{withFileTypes:!0})}catch{return Q}let Z=!1,Y=[];for(let q of X){if(!q.isDirectory()&&q.name==="SKILL.md")Z=!0;if(q.isDirectory()&&!q.name.startsWith("."))Y.push(n($,q.name))}if(Z)Q.push($);for(let q of Y)SQ(q,Q);return Q},PQ=()=>{let $=H.homeSuperpowersSkills,Q=H.homePersonalSkills;if(!a($))return{created:0,existed:0,updated:0,errors:[`Skills directory not found: ${$}`]};if(!a(Q))try{xQ(Q,{recursive:!0})}catch(Y){return{created:0,existed:0,updated:0,errors:[`Failed to create ${Q}: ${Y.message}`]}}let X=SQ($),Z={created:0,existed:0,updated:0,errors:[]};for(let Y of X){let q=sX(Y),z=n(Q,q);if(RQ(z,Y)){Z.existed++;continue}if(t(z))try{g$(z),Z.updated++}catch(K){Z.errors.push(`Failed to remove stale symlink ${z}: ${K.message}`);continue}else if(a(z)){Z.errors.push(`Skipped ${z}: path exists and is not a symlink`);continue}let W=DQ();try{if(W==="win32")L$(Y,z,"junction");else L$(Y,z,"dir");let K=z.replace(o(),"~"),E=Y.replace(o(),"~");console.log(` ✓ ${K} -> ${E}`),Z.created++}catch(K){Z.errors.push(`Failed to create symlink ${z}: ${K.message}`)}}return Z};import{existsSync as gQ,readdirSync as tX,lstatSync as eX,unlinkSync as $Y,realpathSync as kQ}from"fs";import{join as x}from"path";import{homedir as uQ}from"os";var QY=($)=>{try{return kQ($)}catch{return $}},XY=($)=>{try{return eX($).isSymbolicLink()}catch{return!1}},YY=($)=>{try{return kQ($)}catch{return null}},ZY=($,Q)=>{let X=Q.endsWith("/")?Q:Q+"/";return $.startsWith(X)||$===Q},qY=($,Q)=>Q.some((X)=>ZY($,X)),WY=($)=>{try{return gQ(x($,"skill.json"))}catch{return!1}},zY=({platformDirs:$,managedSkillRoots:Q})=>{let X=[],Z=0,Y=Q.map(QY);for(let q of $){if(!gQ(q))continue;let z;try{z=tX(q)}catch{continue}for(let W of z){let K=x(q,W);if(!XY(K))continue;let E=YY(K);if(!E||!qY(E,Y)){Z++;continue}if(!WY(E)){Z++;continue}try{$Y(K),X.push(K)}catch{Z++}}}return{removed:X,skipped:Z}},HY=($)=>{let Q=uQ(),X=[x(Q,".claude","skills"),x(Q,".copilot","skills"),x(Q,".config","opencode","skill"),x(Q,".cursor","skills"),x(Q,".gemini","skills"),x(Q,".codex","skills")];if(!$)return X;let Z=[x($,".claude","skills"),x($,".github","skills"),x($,".opencode","skill"),x($,".cursor","skills"),x($,".gemini","skills"),x($,".codex","skills")];return[...X,...Z]},dQ=($={})=>{let Q=uQ(),X=[x(Q,".agents","skills"),...$.projectRoot?[x($.projectRoot,".agents","skills")]:[]],Z=HY($.projectRoot);return zY({platformDirs:Z,managedSkillRoots:X})};var BY=()=>{let $=T(H.superpowersRepo,".agents","templates","TOOLS.md.template");if(A($))try{return i($,"utf8").trim()}catch(Q){return"### Using Tools\n\nUse your native skill tool. Fallback: `superpowers-agent find-skills`"}return""},I$=($,Q,X,Z=!0)=>{let Y=A($);if(!Y&&!Z)return{updated:!1,created:!1,skipped:!0};let q=BY(),z=Q.replace(/\{\{TOOL_MAPPINGS\}\}/g,q),W=new Date().toISOString().split("T")[0];z=z.replace(/\{\{DATE\}\}/g,W),z=z.replace(/\{\{SUPERPOWERS_PATH\}\}/g,H.superpowersRepo);let K=`<!-- SUPERPOWERS_SKILLS_START -->
106
+ ${z}
107
+ <!-- SUPERPOWERS_SKILLS_END -->`;if(Y){let E=new Date().toISOString().split("T")[0],_=`${$}.backup-${E}`;try{R(`cp "${$}" "${_}"`,{stdio:"pipe"})}catch(U){return{updated:!1,error:!0,message:`Failed to backup: ${U.message}`}}let B;try{B=i($,"utf8")}catch(U){return{updated:!1,error:!0,message:`Failed to read: ${U.message}`}}let G="<!-- SUPERPOWERS_SKILLS_START -->",V="<!-- SUPERPOWERS_SKILLS_END -->",J;if(B.includes(G)&&B.includes(V)){let U=new RegExp(`${G}[\\s\\S]*?${V}`,"g");J=B.replace(U,K)}else{let U=B.match(/^#\s+.+$/m);if(U){let w=B.indexOf(`
108
+ `,U.index)+1;J=B.slice(0,w)+`
107
109
  `+K+`
108
- `+B.slice(J)}else I=K+`
110
+ `+B.slice(w)}else J=K+`
109
111
 
110
- `+B}try{return t($,I,"utf8"),{updated:!0,created:!1,backup:_}}catch(w){return{updated:!1,error:!0,message:`Failed to write: ${w.message}`}}}else try{let z=P1($);if(!M(z))R(`mkdir -p "${z}"`,{stdio:"pipe"});let G=`# ${Z$($).base.toUpperCase()}
112
+ `+B}try{return $$($,J,"utf8"),{updated:!0,created:!1,backup:_}}catch(U){return{updated:!1,error:!0,message:`Failed to write: ${U.message}`}}}else try{let E=hQ($);if(!A(E))R(`mkdir -p "${E}"`,{stdio:"pipe"});let G=`# ${e($).base.toUpperCase()}
111
113
 
112
- `+K;return t($,G,"utf8"),{updated:!1,created:!0}}catch(z){return{updated:!1,created:!1,error:!0,message:`Failed to create: ${z.message}`}}},n2=()=>{console.log("Installing Unix aliases...");let $=C(E.superpowersRepo,".agents","superpowers-agent"),Q=C(E.home,".local","bin"),X=C(Q,"superpowers-agent"),Z=C(Q,"superpowers");if(!M($)){console.log("⚠️ superpowers-agent executable not found");return}if(!M(Q))try{R(`mkdir -p "${Q}"`,{stdio:"pipe"}),console.log(`✓ Created ${Q}`)}catch(H){console.log(`⚠️ Failed to create ${Q}: ${H.message}`);return}try{if(M(X))R(`rm "${X}"`,{stdio:"pipe"});R(`ln -s "${$}" "${X}"`,{stdio:"pipe"}),console.log(`✓ Created symlink: superpowers-agent -> ${$}`)}catch(H){console.log(`⚠️ Failed to create superpowers-agent symlink: ${H.message}`)}try{if(M(Z))R(`rm "${Z}"`,{stdio:"pipe"});R(`ln -s "${$}" "${Z}"`,{stdio:"pipe"}),console.log(`✓ Created symlink: superpowers -> ${$}`)}catch(H){console.log(`⚠️ Failed to create superpowers symlink: ${H.message}`)}if(!(process.env.PATH||"").includes(Q))console.log(`
114
+ `+K;return $$($,G,"utf8"),{updated:!1,created:!0}}catch(E){return{updated:!1,created:!1,error:!0,message:`Failed to create: ${E.message}`}}},_Y=()=>{console.log("Installing Unix aliases...");let $=T(H.superpowersRepo,".agents","superpowers-agent"),Q=T(H.home,".local","bin"),X=T(Q,"superpowers-agent"),Z=T(Q,"superpowers");if(!A($)){console.log("⚠️ superpowers-agent executable not found");return}if(!A(Q))try{R(`mkdir -p "${Q}"`,{stdio:"pipe"}),console.log(`✓ Created ${Q}`)}catch(q){console.log(`⚠️ Failed to create ${Q}: ${q.message}`);return}try{if(A(X))R(`rm "${X}"`,{stdio:"pipe"});R(`ln -s "${$}" "${X}"`,{stdio:"pipe"}),console.log(`✓ Created symlink: superpowers-agent -> ${$}`)}catch(q){console.log(`⚠️ Failed to create superpowers-agent symlink: ${q.message}`)}try{if(A(Z))R(`rm "${Z}"`,{stdio:"pipe"});R(`ln -s "${$}" "${Z}"`,{stdio:"pipe"}),console.log(`✓ Created symlink: superpowers -> ${$}`)}catch(q){console.log(`⚠️ Failed to create superpowers symlink: ${q.message}`)}if(!(process.env.PATH||"").includes(Q))console.log(`
113
115
  ⚠️ Warning: ${Q} is not in your PATH`),console.log(" Add this to your shell profile (~/.bashrc, ~/.zshrc, etc.):"),console.log(` export PATH="$HOME/.local/bin:$PATH"
114
- `)},o2=()=>{console.log("Installing Windows aliases..."),console.log("✓ Windows alias installation (implementation pending)")},u$=()=>{let $=h2();if(console.log(`## Installing Universal Aliases
115
- `),$==="win32")return o2();else return n2()},i2=($)=>{let Q=C(E.superpowersRepo,".github","copilot-instructions.md"),X=C(E.superpowersRepo,"skills","meta","using-superpowers","SKILL.md"),Z=C($,".github","copilot-instructions.md"),Y="<!-- SUPERPOWERS_-_INSTRUCTIONS_START -->",H="<!-- SUPERPOWERS_-_INSTRUCTIONS_END -->";if(!M(Q))return{error:!0,message:"Source template not found"};if(!M(X))return{error:!0,message:"using-superpowers SKILL.md not found"};let W,q;try{W=o(Q,"utf8"),q=o(X,"utf8")}catch(_){return{error:!0,message:`Failed to read source files: ${_.message}`}}let K=W.replace("${content}",q);if(!K.includes("<!-- SUPERPOWERS_-_INSTRUCTIONS_START -->")||!K.includes("<!-- SUPERPOWERS_-_INSTRUCTIONS_END -->"))return{error:!0,message:"Template is missing required markers"};let z=P1(Z);try{if(!M(z))R(`mkdir -p "${z}"`,{stdio:"pipe"})}catch(_){return{error:!0,message:`Failed to create .github directory: ${_.message}`}}if(M(Z)){let _;try{_=o(Z,"utf8")}catch(V){return{error:!0,message:`Failed to read existing file: ${V.message}`}}let B=new Date().toISOString().replace(/[:.]/g,"-"),G=`${Z}.backup-${B}`;try{R(`cp "${Z}" "${G}"`,{stdio:"pipe"})}catch(V){return{error:!0,message:`Failed to backup: ${V.message}`}}if(_.includes("<!-- SUPERPOWERS_-_INSTRUCTIONS_START -->")&&_.includes("<!-- SUPERPOWERS_-_INSTRUCTIONS_END -->")){let V=new RegExp("<!-- SUPERPOWERS_-_INSTRUCTIONS_START -->[\\s\\S]*?<!-- SUPERPOWERS_-_INSTRUCTIONS_END -->","g"),I=_.replace(V,K.trim());try{return t(Z,I,"utf8"),{updated:!0,backup:G}}catch(w){return{error:!0,message:`Failed to update: ${w.message}`}}}else{let V=_.trimEnd()+`
116
+ `)},GY=()=>{console.log("Installing Windows aliases..."),console.log("✓ Windows alias installation (implementation pending)")},u$=()=>{let $=KY();if(console.log(`## Installing Universal Aliases
117
+ `),$==="win32")return GY();else return _Y()},VY=($)=>{let Q=T(H.superpowersRepo,".github","copilot-instructions.md"),X=T(H.superpowersRepo,"skills","meta","using-superpowers","SKILL.md"),Z=T($,".github","copilot-instructions.md"),Y="<!-- SUPERPOWERS_-_INSTRUCTIONS_START -->",q="<!-- SUPERPOWERS_-_INSTRUCTIONS_END -->";if(!A(Q))return{error:!0,message:"Source template not found"};if(!A(X))return{error:!0,message:"using-superpowers SKILL.md not found"};let z,W;try{z=i(Q,"utf8"),W=i(X,"utf8")}catch(_){return{error:!0,message:`Failed to read source files: ${_.message}`}}let K=z.replace("${content}",W);if(!K.includes("<!-- SUPERPOWERS_-_INSTRUCTIONS_START -->")||!K.includes("<!-- SUPERPOWERS_-_INSTRUCTIONS_END -->"))return{error:!0,message:"Template is missing required markers"};let E=hQ(Z);try{if(!A(E))R(`mkdir -p "${E}"`,{stdio:"pipe"})}catch(_){return{error:!0,message:`Failed to create .github directory: ${_.message}`}}if(A(Z)){let _;try{_=i(Z,"utf8")}catch(V){return{error:!0,message:`Failed to read existing file: ${V.message}`}}let B=new Date().toISOString().replace(/[:.]/g,"-"),G=`${Z}.backup-${B}`;try{R(`cp "${Z}" "${G}"`,{stdio:"pipe"})}catch(V){return{error:!0,message:`Failed to backup: ${V.message}`}}if(_.includes("<!-- SUPERPOWERS_-_INSTRUCTIONS_START -->")&&_.includes("<!-- SUPERPOWERS_-_INSTRUCTIONS_END -->")){let V=new RegExp("<!-- SUPERPOWERS_-_INSTRUCTIONS_START -->[\\s\\S]*?<!-- SUPERPOWERS_-_INSTRUCTIONS_END -->","g"),J=_.replace(V,K.trim());try{return $$(Z,J,"utf8"),{updated:!0,backup:G}}catch(U){return{error:!0,message:`Failed to update: ${U.message}`}}}else{let V=_.trimEnd()+`
116
118
 
117
119
  `+K.trim()+`
118
- `;try{return t(Z,V,"utf8"),{updated:!0,backup:G}}catch(I){return{error:!0,message:`Failed to append: ${I.message}`}}}}else try{return t(Z,K,"utf8"),{created:!0}}catch(_){return{error:!0,message:`Failed to create: ${_.message}`}}},k1=()=>{k(),console.log(`# Setting up Superpowers skills for this project
119
- `);let $=process.cwd(),Q=C($,".agents"),X=C(Q,"skills"),Z=C($,"AGENTS.md"),Y=C(Q,"AGENTS.md"),H=M(Z)?Z:Y,W=C(E.superpowersRepo,".agents","templates","AGENTS.md.template");if(!M(W)){console.log(`✗ Error: AGENTS.md template not found
120
- Expected at: ${W}
121
- Please update your Superpowers installation`);return}if(!M(Q))try{R(`mkdir -p "${Q}"`,{stdio:"pipe"}),console.log("✓ Created .agents/ directory")}catch(O){console.log(`✗ Failed to create .agents/ directory: ${O.message}`);return}else console.log("✓ .agents/ directory exists");if(!M(X))try{R(`mkdir -p "${X}"`,{stdio:"pipe"}),R(`touch "${C(X,".gitkeep")}"`,{stdio:"pipe"}),console.log("✓ Created .agents/skills/ directory")}catch(O){console.log(`✗ Failed to create skills directory: ${O.message}`);return}else console.log("✓ .agents/skills/ directory exists");let q=C(Q,"docs"),K=C(q,"SUPERPOWERS.md"),z=C(E.superpowersRepo,".agents","templates","SUPERPOWERS.md.template");if(!M(q))try{R(`mkdir -p "${q}"`,{stdio:"pipe"}),console.log("✓ Created .agents/docs/ directory")}catch(O){console.log(`⚠️ Failed to create docs directory: ${O.message}`)}else console.log("✓ .agents/docs/ directory exists");let _=M(H);if(_){let O=new Date().toISOString().split("T")[0],h=`${H}.backup-${O}`;try{R(`cp "${H}" "${h}"`,{stdio:"pipe"}),console.log(`✓ Backed up existing AGENTS.md to ${Z$(h).base}`)}catch(z$){console.log(`✗ Failed to backup AGENTS.md: ${z$.message}`);return}}let B;try{B=o(W,"utf8")}catch(O){console.log(`✗ Failed to read template: ${O.message}`);return}let G=g();if(B=B.replace(/\{\{VERSION\}\}/g,G),M(z))try{let O=o(z,"utf8"),h=new Date().toISOString().split("T")[0];O=O.replace(/\{\{VERSION\}\}/g,G),O=O.replace(/\{\{DATE\}\}/g,h),t(K,O,"utf8"),console.log("✓ Created .agents/docs/SUPERPOWERS.md")}catch(O){console.log(`⚠️ Failed to create SUPERPOWERS.md: ${O.message}`)}else console.log("⚠️ SUPERPOWERS.md.template not found");let V=[],I=C($,".github","copilot-instructions.md"),w=C(E.home,".github","copilot-instructions.md");if(M(I)||M(w)||D.copilot.check())V.push("github-copilot");let J=C($,"CLAUDE.md"),N=C(Q,"CLAUDE.md");if(M(J)||M(N)||D.claude.check())V.push("claude-code");if(D.opencode.check())V.push("opencode");console.log(`
120
+ `;try{return $$(Z,V,"utf8"),{updated:!0,backup:G}}catch(J){return{error:!0,message:`Failed to append: ${J.message}`}}}}else try{return $$(Z,K,"utf8"),{created:!0}}catch(_){return{error:!0,message:`Failed to create: ${_.message}`}}},pQ=()=>{u(),console.log(`# Setting up Superpowers skills for this project
121
+ `);let $=process.cwd(),Q=T($,".agents"),X=T(Q,"skills"),Z=T($,"AGENTS.md"),Y=T(Q,"AGENTS.md"),q=A(Z)?Z:Y,z=T(H.superpowersRepo,".agents","templates","AGENTS.md.template");if(!A(z)){console.log(`✗ Error: AGENTS.md template not found
122
+ Expected at: ${z}
123
+ Please update your Superpowers installation`);return}if(!A(Q))try{R(`mkdir -p "${Q}"`,{stdio:"pipe"}),console.log("✓ Created .agents/ directory")}catch(O){console.log(`✗ Failed to create .agents/ directory: ${O.message}`);return}else console.log("✓ .agents/ directory exists");if(!A(X))try{R(`mkdir -p "${X}"`,{stdio:"pipe"}),R(`touch "${T(X,".gitkeep")}"`,{stdio:"pipe"}),console.log("✓ Created .agents/skills/ directory")}catch(O){console.log(`✗ Failed to create skills directory: ${O.message}`);return}else console.log("✓ .agents/skills/ directory exists");let W=T(Q,"docs"),K=T(W,"SUPERPOWERS.md"),E=T(H.superpowersRepo,".agents","templates","SUPERPOWERS.md.template");if(!A(W))try{R(`mkdir -p "${W}"`,{stdio:"pipe"}),console.log("✓ Created .agents/docs/ directory")}catch(O){console.log(`⚠️ Failed to create docs directory: ${O.message}`)}else console.log("✓ .agents/docs/ directory exists");let _=A(q);if(_){let O=new Date().toISOString().split("T")[0],c=`${q}.backup-${O}`;try{R(`cp "${q}" "${c}"`,{stdio:"pipe"}),console.log(`✓ Backed up existing AGENTS.md to ${e(c).base}`)}catch(E$){console.log(`✗ Failed to backup AGENTS.md: ${E$.message}`);return}}let B;try{B=i(z,"utf8")}catch(O){console.log(`✗ Failed to read template: ${O.message}`);return}let G=P();if(B=B.replace(/\{\{VERSION\}\}/g,G),A(E))try{let O=i(E,"utf8"),c=new Date().toISOString().split("T")[0];O=O.replace(/\{\{VERSION\}\}/g,G),O=O.replace(/\{\{DATE\}\}/g,c),$$(K,O,"utf8"),console.log("✓ Created .agents/docs/SUPERPOWERS.md")}catch(O){console.log(`⚠️ Failed to create SUPERPOWERS.md: ${O.message}`)}else console.log("⚠️ SUPERPOWERS.md.template not found");let V=[],J=T($,".github","copilot-instructions.md"),U=T(H.home,".github","copilot-instructions.md");if(A(J)||A(U)||D.copilot.check())V.push("github-copilot");let w=T($,"CLAUDE.md"),C=T(Q,"CLAUDE.md");if(A(w)||A(C)||D.claude.check())V.push("claude-code");if(D.opencode.check())V.push("opencode");console.log(`
122
124
  Detected platforms for project: ${V.join(", ")||"none"}
123
- `);let S=V.filter((O)=>["github-copilot","opencode"].includes(O)),v=w$(H,B,S,!_);if(v.created)console.log(`✓ Created AGENTS.md with platform tool mappings (${H===Z?"root":".agents/"})`);else if(v.updated)console.log(`✓ Updated AGENTS.md with platform tool mappings (${H===Z?"root":".agents/"})`);else if(v.error)console.log("⚠️ Failed to update AGENTS.md");let W$=M(J)?J:N,L=w$(W$,B,["claude-code"],!1);if(L.created)console.log(`✓ Created CLAUDE.md with Claude Code tool mappings (${W$===J?"root":".agents/"})`);else if(L.updated){if(console.log(`✓ Updated CLAUDE.md with Claude Code tool mappings (${W$===J?"root":".agents/"})`),L.backup)console.log(` Backed up to ${Z$(L.backup).base}`)}else if(L.skipped)console.log("ℹ️ Skipped CLAUDE.md (does not exist)");else if(L.error)console.log("⚠️ Failed to update CLAUDE.md");let U=C($,".github","copilot-instructions.md"),F={skipped:!0};if(V.includes("github-copilot")){if(F=i2($),F.created)console.log("✓ Created .github/copilot-instructions.md with Superpowers instructions");else if(F.updated){if(console.log("✓ Updated .github/copilot-instructions.md with Superpowers instructions"),F.backup)console.log(` Backed up to ${Z$(F.backup).base}`)}else if(F.error)console.log(`⚠️ Failed to update .github/copilot-instructions.md: ${F.message||""}`)}else console.log("ℹ️ Skipped .github/copilot-instructions.md (GitHub Copilot not detected)");let f=!M(Z)&&!M(Y);if(M(U)&&f){let O=w$(U,B,["github-copilot"],!1);if(O.updated){if(console.log("✓ Updated .github/copilot-instructions.md with GitHub Copilot tool mappings"),O.backup)console.log(` Backed up to ${Z$(O.backup).base}`)}else if(O.error)console.log("⚠️ Failed to update .github/copilot-instructions.md with tool mappings")}else if(M(U)&&!f)console.log("ℹ️ Skipped .github/copilot-instructions.md tool mappings (AGENTS.md exists, using that instead)");else if(!M(U)&&!V.includes("github-copilot"))console.log("ℹ️ Skipped .github/copilot-instructions.md tool mappings (does not exist)");let u=`
125
+ `);let f=V.filter((O)=>["github-copilot","opencode"].includes(O)),N=I$(q,B,f,!_);if(N.created)console.log(`✓ Created AGENTS.md with platform tool mappings (${q===Z?"root":".agents/"})`);else if(N.updated)console.log(`✓ Updated AGENTS.md with platform tool mappings (${q===Z?"root":".agents/"})`);else if(N.error)console.log("⚠️ Failed to update AGENTS.md");let H$=A(w)?w:C,L=I$(H$,B,["claude-code"],!1);if(L.created)console.log(`✓ Created CLAUDE.md with Claude Code tool mappings (${H$===w?"root":".agents/"})`);else if(L.updated){if(console.log(`✓ Updated CLAUDE.md with Claude Code tool mappings (${H$===w?"root":".agents/"})`),L.backup)console.log(` Backed up to ${e(L.backup).base}`)}else if(L.skipped)console.log("ℹ️ Skipped CLAUDE.md (does not exist)");else if(L.error)console.log("⚠️ Failed to update CLAUDE.md");let I=T($,".github","copilot-instructions.md"),F={skipped:!0};if(V.includes("github-copilot")){if(F=VY($),F.created)console.log("✓ Created .github/copilot-instructions.md with Superpowers instructions");else if(F.updated){if(console.log("✓ Updated .github/copilot-instructions.md with Superpowers instructions"),F.backup)console.log(` Backed up to ${e(F.backup).base}`)}else if(F.error)console.log(`⚠️ Failed to update .github/copilot-instructions.md: ${F.message||""}`)}else console.log("ℹ️ Skipped .github/copilot-instructions.md (GitHub Copilot not detected)");let S=!A(Z)&&!A(Y);if(A(I)&&S){let O=I$(I,B,["github-copilot"],!1);if(O.updated){if(console.log("✓ Updated .github/copilot-instructions.md with GitHub Copilot tool mappings"),O.backup)console.log(` Backed up to ${e(O.backup).base}`)}else if(O.error)console.log("⚠️ Failed to update .github/copilot-instructions.md with tool mappings")}else if(A(I)&&!S)console.log("ℹ️ Skipped .github/copilot-instructions.md tool mappings (AGENTS.md exists, using that instead)");else if(!A(I)&&!V.includes("github-copilot"))console.log("ℹ️ Skipped .github/copilot-instructions.md tool mappings (does not exist)");let g=`
124
126
  # Setup complete!
125
127
 
126
128
  Your project now has:
127
- - .agents/ directory structure`;if(v.updated||v.created)u+=`
128
- - AGENTS.md with universal skills instructions`;if(L.updated||L.created)u+=`
129
- - CLAUDE.md with Claude Code skills instructions`;if(F.updated||F.created)u+=`
130
- - .github/copilot-instructions.md with Superpowers instructions`;u+=`
131
- - .agents/skills/ ready for project-specific skills`,u+=`
129
+ - .agents/ directory structure`;if(N.updated||N.created)g+=`
130
+ - AGENTS.md with universal skills instructions`;if(L.updated||L.created)g+=`
131
+ - CLAUDE.md with Claude Code skills instructions`;if(F.updated||F.created)g+=`
132
+ - .github/copilot-instructions.md with Superpowers instructions`;g+=`
133
+ - .agents/skills/ ready for project-specific skills`,g+=`
132
134
  - .agents/docs/SUPERPOWERS.md for detailed reference
133
- `,console.log(u)},r2=()=>{let $=[...["brainstorming.prompt.md","execute-plan.prompt.md","write-plan.prompt.md","setup-skills.prompt.md","create-meta-prompt.md","finding-skills.prompt.md","skills.prompt.md","use-skill.prompt.md","using-a-skill.prompt.md"].map((X)=>C(E.vscodeUserDir,"prompts",X)),...["brainstorm.md","create-meta-prompt.md","execute-plan.md","finding-skills.md","skills.md","use-skill.md","using-a-skill.md","write-plan.md","setup-skills.md"].map((X)=>C(E.home,".claude","commands",X)),...["brainstorm.md","create-meta-prompt.md","execute-plan.md","finding-skills.md","skills.md","use-skill.md","using-a-skill.md","write-plan.md","setup-skills.md"].map((X)=>C(E.home,".config","opencode","command",X))],Q=0;for(let X of $)if(M(X))try{u1(X),Q++}catch(Z){console.log(` ⚠️ Could not remove ${X}: ${Z.message}`)}if(Q>0)console.log(`✓ Removed ${Q} legacy prompt/command file${Q!==1?"s":""}`);else console.log("✓ No legacy prompt/command files found")},l2=()=>{let $=0;for(let Q of L$){let X=Q.skillsDir(),Z=C(X,"superpowers");try{if(p2(Z).isSymbolicLink())u1(Z),console.log(`✓ Removed legacy superpowers symlink from ${X.replace(E.home,"~")}`),$++}catch{}}if($===0)console.log("✓ No legacy superpowers directory symlinks found")},d1=async()=>{k(),console.log(`# Superpowers Bootstrap for Agents
135
+ `,console.log(g)},LY=()=>{let $=[...["brainstorming.prompt.md","execute-plan.prompt.md","write-plan.prompt.md","setup-skills.prompt.md","create-meta-prompt.md","finding-skills.prompt.md","skills.prompt.md","use-skill.prompt.md","using-a-skill.prompt.md"].map((X)=>T(H.vscodeUserDir,"prompts",X)),...["brainstorm.md","create-meta-prompt.md","execute-plan.md","finding-skills.md","skills.md","use-skill.md","using-a-skill.md","write-plan.md","setup-skills.md"].map((X)=>T(H.home,".claude","commands",X)),...["brainstorm.md","create-meta-prompt.md","execute-plan.md","finding-skills.md","skills.md","use-skill.md","using-a-skill.md","write-plan.md","setup-skills.md"].map((X)=>T(H.home,".config","opencode","command",X))],Q=0;for(let X of $)if(A(X))try{mQ(X),Q++}catch(Z){console.log(` ⚠️ Could not remove ${X}: ${Z.message}`)}if(Q>0)console.log(`✓ Removed ${Q} legacy prompt/command file${Q!==1?"s":""}`);else console.log("✓ No legacy prompt/command files found")},UY=()=>{let $=0;for(let Q of U$){let X=Q.skillsDir(),Z=T(X,"superpowers");try{if(EY(Z).isSymbolicLink())mQ(Z),console.log(`✓ Removed legacy superpowers symlink from ${X.replace(H.home,"~")}`),$++}catch{}}if($===0)console.log("✓ No legacy superpowers directory symlinks found")},cQ=async()=>{u(),console.log(`# Superpowers Bootstrap for Agents
134
136
  # ==================================
135
- `);let $=process.argv.includes("--no-update"),X=new Set(["copilot","claude","opencode"].filter((W)=>process.argv.includes(`--force-${W}`))),Z=X.size>0;if(!$){let W=Y$(),q=await G$();if(q.error)console.log(`## Update Check
137
+ `);let $=process.argv.includes("--no-update"),X=new Set(["copilot","claude","opencode"].filter((z)=>process.argv.includes(`--force-${z}`))),Z=X.size>0;if(!$){let z=Z$(),W=await V$();if(W.error)console.log(`## Update Check
136
138
 
137
139
  ⚠️ Could not check for updates (network issue)
138
140
 
139
141
  ---
140
- `);else if(q.hasUpdates)console.log(`## Update Available
141
- `),console.log(`⚠️ Update available: v${q.localVersion} → v${q.remoteVersion}
142
+ `);else if(W.hasUpdates)console.log(`## Update Available
143
+ `),console.log(`⚠️ Update available: v${W.localVersion} → v${W.remoteVersion}
142
144
  To update, run: \`npm install -g @complexthings/superpowers-agent\``),console.log(`
143
145
  ---
144
146
  `)}if(!Z)u$(),console.log(`---
145
147
  `);if(!Z)console.log(`## Cleaning Up Legacy Files
146
- `),r2(),console.log(`
148
+ `),LY(),console.log(`
147
149
  ---
148
- `);if(!Z||X.has("copilot"))console.log(`## GitHub Copilot Integration
149
- `),console.log("✓ Skill symlinks handled in sync step below"),console.log(`
150
+ `);if(!Z||X.has("copilot")){if(console.log(`## GitHub Copilot Integration
151
+ `),console.log("✓ Skill symlinks handled in sync step below"),q$("copilot")||A(T(H.home,".copilot"))||X.has("copilot")){let W=jQ();if(W.created)console.log(`✓ Installed Copilot sessionStart hook -> ${W.path.replace(H.home,"~")}`);else if(W.updated)console.log(`✓ Updated Copilot sessionStart hook -> ${W.path.replace(H.home,"~")}`);else if(W.existed)console.log("✓ Copilot sessionStart hook already up to date");else if(W.error)console.log(`⚠️ Failed to install Copilot sessionStart hook: ${W.message}`)}else console.log("ℹ️ Skipped Copilot sessionStart hook (Copilot CLI not detected; run with --force-copilot to install anyway)");console.log(`
150
152
  ---
151
- `);if(!Z||X.has("claude")){if(console.log(`## Claude Code Integration
152
- `),!D.claude.check())console.log(`⚠️ Skipped (${D.claude.name} CLI not detected)
153
+ `)}if(!Z||X.has("claude")){if(console.log(`## Claude Code Integration
154
+ `),!D.claude.check()&&!X.has("claude"))console.log(`⚠️ Skipped (${D.claude.name} CLI not detected)
153
155
  \uD83D\uDCA1 To enable Claude Code integration:
154
156
  1. Install Claude Code: ${D.claude.installUrl}
155
- 2. Run: superpowers-agent ${D.claude.bootstrapCommand}`);else console.log("✓ Skill symlinks handled in sync step below");console.log(`
157
+ 2. Run: superpowers-agent bootstrap --force-claude`);else{console.log("✓ Skill symlinks handled in sync step below");let W=FQ();if(W.created)console.log(`✓ Installed SessionStart hook -> ${H.claudeSettings.replace(H.home,"~")}`);else if(W.updated){if(console.log(`✓ ${W.existed?"Refreshed":"Added"} SessionStart hook in ${H.claudeSettings.replace(H.home,"~")}`),W.backup)console.log(` Backed up to ${e(W.backup).base}`)}else if(W.error)console.log(`⚠️ Failed to install SessionStart hook: ${W.message}`)}console.log(`
156
158
  ---
157
159
  `)}if(!Z||X.has("opencode")){if(console.log(`## OpenCode Integration
158
- `),D.opencode.check())v1();else console.log(`⚠️ Skipped (${D.opencode.name} CLI not detected)
160
+ `),D.opencode.check())bQ();else console.log(`⚠️ Skipped (${D.opencode.name} CLI not detected)
159
161
  \uD83D\uDCA1 To enable OpenCode integration:
160
162
  1. Install OpenCode: ${D.opencode.installUrl}
161
163
  2. Run: superpowers-agent ${D.opencode.bootstrapCommand}`);console.log(`
162
164
  ---
163
165
  `)}if(!Z){console.log(`## Generating Platform-Specific Files
164
- `);let W=T1();console.log(`Detected platforms: ${W.join(", ")||"none"}
165
- `);let q=C(E.superpowersRepo,".agents","templates","AGENTS.md.template"),K="";try{K=o(q,"utf8")}catch(z){console.log(`⚠️ Could not read AGENTS.md template: ${z.message}
166
- `)}if(K){let z=g();K=K.replace(/\{\{VERSION\}\}/g,z);let _=C(E.home,".agents","AGENTS.md"),B=w$(_,K,W,!0);if(B.created)console.log(`✓ Created ${_}`);else if(B.updated)console.log(`✓ Updated ${_}`)}console.log(`
166
+ `);let z=vQ();console.log(`Detected platforms: ${z.join(", ")||"none"}
167
+ `);let W=T(H.superpowersRepo,".agents","templates","AGENTS.md.template"),K="";try{K=i(W,"utf8")}catch(E){console.log(`⚠️ Could not read AGENTS.md template: ${E.message}
168
+ `)}if(K){let E=P();K=K.replace(/\{\{VERSION\}\}/g,E);let _=T(H.home,".agents","AGENTS.md"),B=I$(_,K,z,!0);if(B.created)console.log(`✓ Created ${_}`);else if(B.updated)console.log(`✓ Updated ${_}`)}console.log(`
167
169
  ---
168
170
  `)}console.log(`## Cleaning Up Legacy Superpowers Dir Symlinks
169
- `),l2(),console.log(`
171
+ `),UY(),console.log(`
170
172
  ---
171
173
  `),console.log(`## Syncing Repo Skills -> ~/.agents/skills/
172
- `);let Y=R1();if(Y.created>0||Y.updated>0)console.log(` ✓ ${Y.created} created, ${Y.updated} updated, ${Y.existed} already current`);else if(Y.errors.length>0)for(let W of Y.errors)console.log(` ⚠️ ${W}`);else console.log(` ✓ ${Y.existed} skill symlinks already up to date`);console.log(`
174
+ `);let Y=PQ();if(Y.created>0||Y.updated>0)console.log(` ✓ ${Y.created} created, ${Y.updated} updated, ${Y.existed} already current`);else if(Y.errors.length>0)for(let z of Y.errors)console.log(` ⚠️ ${z}`);else console.log(` ✓ ${Y.existed} skill symlinks already up to date`);console.log(`
173
175
  ---
174
176
  `),console.log(`## Cleaning Up Stale Platform Skill Symlinks
175
- `);let H=g1({projectRoot:process.cwd()});if(H.removed.length>0){console.log(` ✓ Removed ${H.removed.length} stale skill symlink(s):`);for(let W of H.removed)console.log(` - ${W}`)}else console.log(" ✓ No stale platform skill symlinks found");console.log(`
177
+ `);let q=dQ({projectRoot:process.cwd()});if(q.removed.length>0){console.log(` ✓ Removed ${q.removed.length} stale skill symlink(s):`);for(let z of q.removed)console.log(` - ${z}`)}else console.log(" ✓ No stale platform skill symlinks found");console.log(`
176
178
  ---
177
179
  `),console.log(`# Bootstrap Complete!
178
180
  `),console.log("✓ All integrations installed"),console.log("✓ Skills system ready"),console.log(`✓ Skill symlinks synced
179
- `),console.log("Next steps:"),console.log(" - Run `superpowers-agent find-skills` to see available skills"),console.log(" - Run `superpowers-agent setup-skills` in your project directory")};import{existsSync as b,readFileSync as I$,mkdirSync as Z3,rmSync as h$,cpSync as H3,lstatSync as q3}from"fs";import{join as T,dirname as O$,parse as q$,sep as W3}from"path";import{execSync as x}from"child_process";import{homedir as p}from"os";import{createInterface as z3}from"readline";import{readFileSync as a2,existsSync as d$,unlinkSync as s2,lstatSync as t2,mkdirSync as e2}from"fs";import{join as $3,dirname as Q3}from"path";import{join as H$}from"path";import{homedir as m1}from"os";var P$={github:{name:"github",sourceDir:".github/agents",sourceExt:".agent.md",getDestDir:()=>H$(E.vscodeUserDir,"prompts"),destExt:".agent.md"},opencode:{name:"opencode",sourceDir:".opencode/agents",sourceExt:".md",getDestDir:()=>H$(m1(),".config","opencode","agents"),destExt:".md"},claude:{name:"claude",sourceDir:".claude/agents",sourceExt:".md",getDestDir:()=>H$(m1(),".claude","agents"),destExt:".md"}};function p1($,Q,X){let Z=P$[Q];if(!Z)return null;return H$($,Z.sourceDir,`${X}${Z.sourceExt}`)}function h1($,Q){let X=P$[$];if(!X)return null;return H$(X.getDestDir(),`${Q}${X.destExt}`)}function k$(){return Object.keys(P$)}function X3($){if(!$||typeof $!=="object")return{valid:!1,error:"agents.json must be a JSON object"};if(!$.version||typeof $.version!=="string")return{valid:!1,error:'agents.json must have a "version" string field'};if(!$.agents||typeof $.agents!=="object")return{valid:!1,error:'agents.json must have an "agents" object field'};let Q=k$(),X=[];for(let[Z,Y]of Object.entries($.agents)){if(!Q.includes(Z)){X.push(Z);continue}if(!Array.isArray(Y))return{valid:!1,error:`agents.${Z} must be an array of agent names`};for(let H of Y)if(typeof H!=="string")return{valid:!1,error:`agents.${Z} must contain only string agent names`}}return{valid:!0,data:$,skippedPlatforms:X}}function Y3($,Q){if(!d$($))return{installed:!1,error:`Source file not found: ${$}`};if(d$(Q))try{if(!t2(Q).isSymbolicLink())s2(Q)}catch(Z){}e2(Q3(Q),{recursive:!0});let X=x1($,Q);if(X.error)return{installed:!1,error:X.error};return{installed:!0}}function m$($,Q={}){let X=$3($,"agents.json");if(!d$(X))return;let Z;try{Z=JSON.parse(a2(X,"utf8"))}catch(V){console.log(`
180
- ⚠ Could not parse agents.json: ${V.message}`);return}let Y=X3(Z);if(!Y.valid){console.log(`
181
- ⚠ Invalid agents.json: ${Y.error}`);return}for(let V of Y.skippedPlatforms)console.log(` ⚠ Skipping unknown platform: ${V}`);let H=Z.repository||"unknown",W=Z.version,q=Q.isUpdate?"Updating":"Installing",K=Q.isUpdate?"Updated":"Installed";console.log(`
182
- \uD83D\uDCE6 Found agents.json (${H} v${W})`);let z=k$(),_=0,B=0,G=[];for(let[V,I]of Object.entries(Z.agents)){if(!z.includes(V))continue;console.log(`
183
- ${q} ${V} agents:`);for(let w of I){let J=p1($,V,w),N=h1(V,w),S=Y3(J,N);if(S.installed)console.log(` ✓ ${w}`),G.push({platformKey:V,agentName:w,sourcePath:J,destPath:N}),_++;else console.log(` ✗ ${w}: ${S.error}`),B++}}if(G.length>0){let V=y(!0);if(!V.installedAgents)V.installedAgents={};if(!V.installedAgents[H])V.installedAgents[H]={version:W,agents:{}};V.installedAgents[H].version=W;for(let{platformKey:I,agentName:w,sourcePath:J,destPath:N}of G){if(!V.installedAgents[H].agents[I])V.installedAgents[H].agents[I]={};V.installedAgents[H].agents[I][w]={source:J,destination:N,installedAt:new Date().toISOString()}}m(V,!0)}if(_>0)console.log(`
184
- ${K} ${_} agent(s)${B>0?` (${B} failed)`:""}`)}var c1=($,Q)=>{if(Q.type==="local"){let Z=$;for(let Y=0;Y<10;Y++){if(b(T(Z,"agents.json")))return Z;let H=O$(Z);if(H===Z)break;Z=H}return $}let X=T(".agents","tmp");if($.includes(X)){let Z=$.indexOf(X),H=$.substring(Z+X.length+1).split(W3)[0];return T($.substring(0,Z),".agents","tmp",H)}return $},n1=($,Q)=>{let X=T(p(),".agents","repos"),Z=Q.replace(/^@/,"").replace(/[^a-zA-Z0-9_-]/g,"_"),Y=T(X,Z);try{if(Z3(X,{recursive:!0}),b(Y))h$(Y,{recursive:!0,force:!0});return H3($,Y,{recursive:!0}),Y}catch(H){return console.log(` Warning: Could not persist repository for agents: ${H.message}`),null}},c$=($)=>{let Q=$.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)$/);if(Q){let[,Y,H,W,q]=Q;return{type:"git-tree",repoUrl:`https://github.com/${Y}/${H}.git`,branch:W,path:q,original:$}}let X=$.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/);if(X){let[,Y,H]=X;return{type:"git-repo",repoUrl:`git@github.com:${Y}/${H}.git`,branch:null,path:null,original:$}}let Z=$.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);if(Z){let[,Y,H]=Z;return{type:"git-repo",repoUrl:`https://github.com/${Y}/${H}.git`,branch:null,path:null,original:$}}if(b($))return{type:"local",path:$,original:$};return null},n$=($)=>{let Q=$.includes("--global")||$.includes("-g"),X=$.includes("--project")||$.includes("-p");if(Q)return T(p(),".agents","skills");if(X)return T(process.cwd(),".agents","skills");let Z=T(process.cwd(),".agents","config.json"),Y=T(p(),".agents","config.json");for(let H of[Z,Y])if(b(H))try{if(JSON.parse(I$(H,"utf8")).installLocation==="project")return T(process.cwd(),".agents","skills")}catch(W){}return T(p(),".agents","skills")},o$=($,Q)=>{let X=T(p(),".agents","tmp",`skill-install-${Date.now()}`);try{if(x(`mkdir -p "${X}"`,{stdio:"pipe"}),Q)x(`git clone --branch ${Q} --depth 1 "${$}" "${X}"`,{stdio:"pipe",timeout:30000});else x(`git clone --depth 1 "${$}" "${X}"`,{stdio:"pipe",timeout:30000});return X}catch(Z){try{x(`rm -rf "${X}"`,{stdio:"pipe"})}catch{}throw Error(`Failed to clone repository: ${Z.message}`)}},e=($)=>{let Q=T($,"skill.json");if(!b(Q))return null;try{let X=I$(Q,"utf8");return JSON.parse(X)}catch(X){throw Error(`Failed to read skill.json: ${X.message}`)}},U$=($,Q,X,Z)=>{let Y=T($,Q);if(!b(Y)){Z.errors.push(`Skill directory not found: ${Q}`);return}let H=e(Y);if(!H){Z.errors.push(`No skill.json found in: ${Q}`);return}let W=H.name||Q,q=W.split("/").pop()||W,K=T(X,q),z=O$(K);try{x(`mkdir -p "${z}"`,{stdio:"pipe"})}catch(_){Z.errors.push(`Failed to create directory ${z}: ${_.message}`);return}try{if(b(K))x(`rm -rf "${K}"`,{stdio:"pipe"});x(`cp -R "${Y}" "${K}"`,{stdio:"pipe"}),Z.installed.push({name:q,path:K,title:H.title||H.description||q})}catch(_){Z.errors.push(`Failed to install ${Q}: ${_.message}`)}},o1=($,Q,X,Z,Y=null)=>{let H=y(Z);if(!H.installedSkills)H.installedSkills={};let W={source:$,installBase:Q,installedAt:new Date().toISOString(),skills:X.installed.map((q)=>({name:q.name,path:q.path}))};if(H.installedSkills[$]=W,Y&&Y!==$)H.installedSkills[Y]=W;m(H,Z)},i1=()=>{let $=process.argv.slice(3),Q=$.find((B)=>!B.startsWith("-")),X=$.filter((B)=>B.startsWith("-"));if(!Q){console.log(`Usage: superpowers-agent add <url-or-path|@alias> [skill-path] [options]
181
+ `),console.log("Next steps:"),console.log(" - Run `superpowers-agent find-skills` to see available skills"),console.log(" - Run `superpowers-agent setup-skills` in your project directory")};import{existsSync as b,readFileSync as O$,mkdirSync as NY,rmSync as n$,cpSync as bY,lstatSync as CY}from"fs";import{join as v,dirname as w$,parse as z$,sep as FY}from"path";import{execSync as j}from"child_process";import{homedir as p}from"os";import{createInterface as jY}from"readline";import{readFileSync as IY,existsSync as h$,unlinkSync as JY,lstatSync as OY,mkdirSync as wY}from"fs";import{join as MY,dirname as AY}from"path";import{join as W$}from"path";import{homedir as nQ}from"os";var d$={github:{name:"github",sourceDir:".github/agents",sourceExt:".agent.md",getDestDir:()=>W$(H.vscodeUserDir,"prompts"),destExt:".agent.md"},opencode:{name:"opencode",sourceDir:".opencode/agents",sourceExt:".md",getDestDir:()=>W$(nQ(),".config","opencode","agents"),destExt:".md"},claude:{name:"claude",sourceDir:".claude/agents",sourceExt:".md",getDestDir:()=>W$(nQ(),".claude","agents"),destExt:".md"}};function oQ($,Q,X){let Z=d$[Q];if(!Z)return null;return W$($,Z.sourceDir,`${X}${Z.sourceExt}`)}function iQ($,Q){let X=d$[$];if(!X)return null;return W$(X.getDestDir(),`${Q}${X.destExt}`)}function m$(){return Object.keys(d$)}function TY($){if(!$||typeof $!=="object")return{valid:!1,error:"agents.json must be a JSON object"};if(!$.version||typeof $.version!=="string")return{valid:!1,error:'agents.json must have a "version" string field'};if(!$.agents||typeof $.agents!=="object")return{valid:!1,error:'agents.json must have an "agents" object field'};let Q=m$(),X=[];for(let[Z,Y]of Object.entries($.agents)){if(!Q.includes(Z)){X.push(Z);continue}if(!Array.isArray(Y))return{valid:!1,error:`agents.${Z} must be an array of agent names`};for(let q of Y)if(typeof q!=="string")return{valid:!1,error:`agents.${Z} must contain only string agent names`}}return{valid:!0,data:$,skippedPlatforms:X}}function vY($,Q){if(!h$($))return{installed:!1,error:`Source file not found: ${$}`};if(h$(Q))try{if(!OY(Q).isSymbolicLink())JY(Q)}catch(Z){}wY(AY(Q),{recursive:!0});let X=fQ($,Q);if(X.error)return{installed:!1,error:X.error};return{installed:!0}}function p$($,Q={}){let X=MY($,"agents.json");if(!h$(X))return;let Z;try{Z=JSON.parse(IY(X,"utf8"))}catch(V){console.log(`
182
+ ⚠ Could not parse agents.json: ${V.message}`);return}let Y=TY(Z);if(!Y.valid){console.log(`
183
+ ⚠ Invalid agents.json: ${Y.error}`);return}for(let V of Y.skippedPlatforms)console.log(` ⚠ Skipping unknown platform: ${V}`);let q=Z.repository||"unknown",z=Z.version,W=Q.isUpdate?"Updating":"Installing",K=Q.isUpdate?"Updated":"Installed";console.log(`
184
+ \uD83D\uDCE6 Found agents.json (${q} v${z})`);let E=m$(),_=0,B=0,G=[];for(let[V,J]of Object.entries(Z.agents)){if(!E.includes(V))continue;console.log(`
185
+ ${W} ${V} agents:`);for(let U of J){let w=oQ($,V,U),C=iQ(V,U),f=vY(w,C);if(f.installed)console.log(` ✓ ${U}`),G.push({platformKey:V,agentName:U,sourcePath:w,destPath:C}),_++;else console.log(` ✗ ${U}: ${f.error}`),B++}}if(G.length>0){let V=y(!0);if(!V.installedAgents)V.installedAgents={};if(!V.installedAgents[q])V.installedAgents[q]={version:z,agents:{}};V.installedAgents[q].version=z;for(let{platformKey:J,agentName:U,sourcePath:w,destPath:C}of G){if(!V.installedAgents[q].agents[J])V.installedAgents[q].agents[J]={};V.installedAgents[q].agents[J][U]={source:w,destination:C,installedAt:new Date().toISOString()}}h(V,!0)}if(_>0)console.log(`
186
+ ${K} ${_} agent(s)${B>0?` (${B} failed)`:""}`)}var lQ=($,Q)=>{if(Q.type==="local"){let Z=$;for(let Y=0;Y<10;Y++){if(b(v(Z,"agents.json")))return Z;let q=w$(Z);if(q===Z)break;Z=q}return $}let X=v(".agents","tmp");if($.includes(X)){let Z=$.indexOf(X),q=$.substring(Z+X.length+1).split(FY)[0];return v($.substring(0,Z),".agents","tmp",q)}return $},aQ=($,Q)=>{let X=v(p(),".agents","repos"),Z=Q.replace(/^@/,"").replace(/[^a-zA-Z0-9_-]/g,"_"),Y=v(X,Z);try{if(NY(X,{recursive:!0}),b(Y))n$(Y,{recursive:!0,force:!0});return bY($,Y,{recursive:!0}),Y}catch(q){return console.log(` Warning: Could not persist repository for agents: ${q.message}`),null}},o$=($)=>{let Q=$.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)$/);if(Q){let[,Y,q,z,W]=Q;return{type:"git-tree",repoUrl:`https://github.com/${Y}/${q}.git`,branch:z,path:W,original:$}}let X=$.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/);if(X){let[,Y,q]=X;return{type:"git-repo",repoUrl:`git@github.com:${Y}/${q}.git`,branch:null,path:null,original:$}}let Z=$.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);if(Z){let[,Y,q]=Z;return{type:"git-repo",repoUrl:`https://github.com/${Y}/${q}.git`,branch:null,path:null,original:$}}if(b($))return{type:"local",path:$,original:$};return null},i$=($)=>{let Q=$.includes("--global")||$.includes("-g"),X=$.includes("--project")||$.includes("-p");if(Q)return v(p(),".agents","skills");if(X)return v(process.cwd(),".agents","skills");let Z=v(process.cwd(),".agents","config.json"),Y=v(p(),".agents","config.json");for(let q of[Z,Y])if(b(q))try{if(JSON.parse(O$(q,"utf8")).installLocation==="project")return v(process.cwd(),".agents","skills")}catch(z){}return v(p(),".agents","skills")},l$=($,Q)=>{let X=v(p(),".agents","tmp",`skill-install-${Date.now()}`);try{if(j(`mkdir -p "${X}"`,{stdio:"pipe"}),Q)j(`git clone --branch ${Q} --depth 1 "${$}" "${X}"`,{stdio:"pipe",timeout:30000});else j(`git clone --depth 1 "${$}" "${X}"`,{stdio:"pipe",timeout:30000});return X}catch(Z){try{j(`rm -rf "${X}"`,{stdio:"pipe"})}catch{}throw Error(`Failed to clone repository: ${Z.message}`)}},Q$=($)=>{let Q=v($,"skill.json");if(!b(Q))return null;try{let X=O$(Q,"utf8");return JSON.parse(X)}catch(X){throw Error(`Failed to read skill.json: ${X.message}`)}},J$=($,Q,X,Z)=>{let Y=v($,Q);if(!b(Y)){Z.errors.push(`Skill directory not found: ${Q}`);return}let q=Q$(Y);if(!q){Z.errors.push(`No skill.json found in: ${Q}`);return}let z=q.name||Q,W=z.split("/").pop()||z,K=v(X,W),E=w$(K);try{j(`mkdir -p "${E}"`,{stdio:"pipe"})}catch(_){Z.errors.push(`Failed to create directory ${E}: ${_.message}`);return}try{if(b(K))j(`rm -rf "${K}"`,{stdio:"pipe"});j(`cp -R "${Y}" "${K}"`,{stdio:"pipe"}),Z.installed.push({name:W,path:K,title:q.title||q.description||W})}catch(_){Z.errors.push(`Failed to install ${Q}: ${_.message}`)}},rQ=($,Q,X,Z,Y=null)=>{let q=y(Z);if(!q.installedSkills)q.installedSkills={};let z={source:$,installBase:Q,installedAt:new Date().toISOString(),skills:X.installed.map((W)=>({name:W.name,path:W.path}))};if(q.installedSkills[$]=z,Y&&Y!==$)q.installedSkills[Y]=z;h(q,Z)},sQ=()=>{let $=process.argv.slice(3),Q=$.find((B)=>!B.startsWith("-")),X=$.filter((B)=>B.startsWith("-"));if(!Q){console.log(`Usage: superpowers-agent add <url-or-path|@alias> [skill-path] [options]
185
187
 
186
188
  Options:
187
189
  --global, -g Install skills globally in ~/.agents/skills/ (default)
@@ -203,18 +205,18 @@ Description:
203
205
 
204
206
  Repository aliases can be added using:
205
207
  superpowers-agent add-repository <git-url> [--as=@alias]`);return}console.log(`Installing skill(s)...
206
- `);let Z=!X.includes("--project")&&!X.includes("-p"),Y=null,H=null,W=null;if(Q.startsWith("@")){let B=Q;W=B,H=$.find((w,J)=>J>0&&!w.startsWith("-")&&w!==B);let G=P(!1),V=P(!0);if(G[B])Y=G[B],console.log(`Using project repository alias: ${B}`);else if(V[B])Y=V[B],console.log(`Using global repository alias: ${B}`);else{console.log(`Error: Repository alias not found: ${B}`),console.log(`
207
- Available aliases:`);let w={...V,...G};if(Object.keys(w).length===0)console.log(" (none)"),console.log(`
208
- Add a repository using:`),console.log(" superpowers-agent add-repository <git-url>");else for(let[J,N]of Object.entries(w))console.log(` ${J} -> ${N}`);return}let I=b(Y);if(H)if(I)Q=T(Y,H),console.log(`Repository path: ${Y}`),console.log(`Skill path: ${H}
209
- `);else Q=Y,console.log(`Repository URL: ${Y}`),console.log(`Skill path: ${H}
210
- `);else if(Q=Y,I)console.log(`Repository path: ${Y}
208
+ `);let Z=!X.includes("--project")&&!X.includes("-p"),Y=null,q=null,z=null;if(Q.startsWith("@")){let B=Q;z=B,q=$.find((U,w)=>w>0&&!U.startsWith("-")&&U!==B);let G=k(!1),V=k(!0);if(G[B])Y=G[B],console.log(`Using project repository alias: ${B}`);else if(V[B])Y=V[B],console.log(`Using global repository alias: ${B}`);else{console.log(`Error: Repository alias not found: ${B}`),console.log(`
209
+ Available aliases:`);let U={...V,...G};if(Object.keys(U).length===0)console.log(" (none)"),console.log(`
210
+ Add a repository using:`),console.log(" superpowers-agent add-repository <git-url>");else for(let[w,C]of Object.entries(U))console.log(` ${w} -> ${C}`);return}let J=b(Y);if(q)if(J)Q=v(Y,q),console.log(`Repository path: ${Y}`),console.log(`Skill path: ${q}
211
+ `);else Q=Y,console.log(`Repository URL: ${Y}`),console.log(`Skill path: ${q}
212
+ `);else if(Q=Y,J)console.log(`Repository path: ${Y}
211
213
  `);else console.log(`Repository URL: ${Y}
212
- `)}let q=c$(Q);if(!q){console.log(`Error: Invalid URL or path not found: ${Q}`);return}if(H&&q.type==="git-repo"&&!q.path)q.path=H;let K=n$(X);console.log(`Install location: ${K}
213
- `);let z,_=!1;try{if(q.type==="git-repo"||q.type==="git-tree"){if(console.log(`Cloning repository: ${q.repoUrl}`),q.branch)console.log(`Branch: ${q.branch}`);if(z=o$(q.repoUrl,q.branch),_=!0,q.path){if(z=T(z,q.path),!b(z))throw Error(`Path not found in repository: ${q.path}`)}console.log("")}else z=q.path;let B=e(z);if(!B)throw Error("No skill.json found in source directory");let G={installed:[],errors:[],source:q.original};if(B.skills&&Array.isArray(B.skills)){console.log(`Found ${B.skills.length} skill(s) to install
214
- `);for(let w of B.skills)U$(z,w,K,G)}else{let w=B.name||q$(z).base;U$(O$(z),q$(z).base,K,G)}let V=c1(z,q),I=T(V,"agents.json");if(b(I)){let w=V;if(_){let J;try{J=JSON.parse(I$(I,"utf8"))}catch{}let N=J?.repository||q.original,S=n1(V,N);if(S)w=S}m$(w,{isUpdate:!1})}if(_&&z)try{let w=z.split("/.agents/tmp/")[0]+"/.agents/tmp/"+z.split("/.agents/tmp/")[1].split("/")[0];x(`rm -rf "${w}"`,{stdio:"pipe"})}catch{}if(console.log(`
215
- **Successfully installed skills:**`),console.log(`- Source: ${G.source}`),G.installed.length>0)for(let w of G.installed)console.log(` - Installed: ${w.name} at ${w.path}`),console.log(` ${w.title}`);if(G.errors.length>0){console.log(`
216
- **Errors:**`);for(let w of G.errors)console.log(` - ${w}`)}if(G.installed.length===0&&G.errors.length===0)console.log(" No skills were installed");if(G.installed.length>0)o1(q.original,K,G,Z,W)}catch(B){if(_&&z)try{let G=z.split("/.agents/tmp/")[0]+"/.agents/tmp/"+z.split("/.agents/tmp/")[1].split("/")[0];x(`rm -rf "${G}"`,{stdio:"pipe"})}catch{}console.log(`
217
- Error: ${B.message}`)}},r1=()=>{let $=process.argv.slice(3),Q=$.find((B)=>!B.startsWith("-")),X=$.filter((B)=>B.startsWith("-"));if(!Q){console.log(`Usage: superpowers-agent pull <url-or-path|@alias> [skill-path] [options]
214
+ `)}let W=o$(Q);if(!W){console.log(`Error: Invalid URL or path not found: ${Q}`);return}if(q&&W.type==="git-repo"&&!W.path)W.path=q;let K=i$(X);console.log(`Install location: ${K}
215
+ `);let E,_=!1;try{if(W.type==="git-repo"||W.type==="git-tree"){if(console.log(`Cloning repository: ${W.repoUrl}`),W.branch)console.log(`Branch: ${W.branch}`);if(E=l$(W.repoUrl,W.branch),_=!0,W.path){if(E=v(E,W.path),!b(E))throw Error(`Path not found in repository: ${W.path}`)}console.log("")}else E=W.path;let B=Q$(E);if(!B)throw Error("No skill.json found in source directory");let G={installed:[],errors:[],source:W.original};if(B.skills&&Array.isArray(B.skills)){console.log(`Found ${B.skills.length} skill(s) to install
216
+ `);for(let U of B.skills)J$(E,U,K,G)}else{let U=B.name||z$(E).base;J$(w$(E),z$(E).base,K,G)}let V=lQ(E,W),J=v(V,"agents.json");if(b(J)){let U=V;if(_){let w;try{w=JSON.parse(O$(J,"utf8"))}catch{}let C=w?.repository||W.original,f=aQ(V,C);if(f)U=f}p$(U,{isUpdate:!1})}if(_&&E)try{let U=E.split("/.agents/tmp/")[0]+"/.agents/tmp/"+E.split("/.agents/tmp/")[1].split("/")[0];j(`rm -rf "${U}"`,{stdio:"pipe"})}catch{}if(console.log(`
217
+ **Successfully installed skills:**`),console.log(`- Source: ${G.source}`),G.installed.length>0)for(let U of G.installed)console.log(` - Installed: ${U.name} at ${U.path}`),console.log(` ${U.title}`);if(G.errors.length>0){console.log(`
218
+ **Errors:**`);for(let U of G.errors)console.log(` - ${U}`)}if(G.installed.length===0&&G.errors.length===0)console.log(" No skills were installed");if(G.installed.length>0)rQ(W.original,K,G,Z,z)}catch(B){if(_&&E)try{let G=E.split("/.agents/tmp/")[0]+"/.agents/tmp/"+E.split("/.agents/tmp/")[1].split("/")[0];j(`rm -rf "${G}"`,{stdio:"pipe"})}catch{}console.log(`
219
+ Error: ${B.message}`)}},tQ=()=>{let $=process.argv.slice(3),Q=$.find((B)=>!B.startsWith("-")),X=$.filter((B)=>B.startsWith("-"));if(!Q){console.log(`Usage: superpowers-agent pull <url-or-path|@alias> [skill-path] [options]
218
220
 
219
221
  Options:
220
222
  --global, -g Update skills globally in ~/.agents/skills/ (default)
@@ -239,18 +241,18 @@ Description:
239
241
 
240
242
  Repository aliases can be added using:
241
243
  superpowers-agent add-repository <git-url> [--as=@alias]`);return}console.log(`Updating skill(s)...
242
- `);let Z=!X.includes("--project")&&!X.includes("-p"),Y=null,H=null,W=null;if(Q.startsWith("@")){let B=Q;W=B,H=$.find((w,J)=>J>0&&!w.startsWith("-")&&w!==B);let G=P(!1),V=P(!0);if(G[B])Y=G[B],console.log(`Using project repository alias: ${B}`);else if(V[B])Y=V[B],console.log(`Using global repository alias: ${B}`);else{console.log(`Error: Repository alias not found: ${B}`),console.log(`
243
- Available aliases:`);let w={...V,...G};if(Object.keys(w).length===0)console.log(" (none)"),console.log(`
244
- Add a repository using:`),console.log(" superpowers-agent add-repository <git-url>");else for(let[J,N]of Object.entries(w))console.log(` ${J} -> ${N}`);return}let I=b(Y);if(H)if(I)Q=T(Y,H),console.log(`Repository path: ${Y}`),console.log(`Skill path: ${H}
245
- `);else Q=Y,console.log(`Repository URL: ${Y}`),console.log(`Skill path: ${H}
246
- `);else if(Q=Y,I)console.log(`Repository path: ${Y}
244
+ `);let Z=!X.includes("--project")&&!X.includes("-p"),Y=null,q=null,z=null;if(Q.startsWith("@")){let B=Q;z=B,q=$.find((U,w)=>w>0&&!U.startsWith("-")&&U!==B);let G=k(!1),V=k(!0);if(G[B])Y=G[B],console.log(`Using project repository alias: ${B}`);else if(V[B])Y=V[B],console.log(`Using global repository alias: ${B}`);else{console.log(`Error: Repository alias not found: ${B}`),console.log(`
245
+ Available aliases:`);let U={...V,...G};if(Object.keys(U).length===0)console.log(" (none)"),console.log(`
246
+ Add a repository using:`),console.log(" superpowers-agent add-repository <git-url>");else for(let[w,C]of Object.entries(U))console.log(` ${w} -> ${C}`);return}let J=b(Y);if(q)if(J)Q=v(Y,q),console.log(`Repository path: ${Y}`),console.log(`Skill path: ${q}
247
+ `);else Q=Y,console.log(`Repository URL: ${Y}`),console.log(`Skill path: ${q}
248
+ `);else if(Q=Y,J)console.log(`Repository path: ${Y}
247
249
  `);else console.log(`Repository URL: ${Y}
248
- `)}let q=c$(Q);if(!q){console.log(`Error: Invalid URL or path not found: ${Q}`);return}if(H&&q.type==="git-repo"&&!q.path)q.path=H;let K=n$(X);console.log(`Install location: ${K}
249
- `);let z,_=!1;try{if(q.type==="git-repo"||q.type==="git-tree"){if(console.log(`Cloning repository: ${q.repoUrl}`),q.branch)console.log(`Branch: ${q.branch}`);if(z=o$(q.repoUrl,q.branch),_=!0,q.path){if(z=T(z,q.path),!b(z))throw Error(`Path not found in repository: ${q.path}`)}console.log("")}else z=q.path;let B=e(z);if(!B)throw Error("No skill.json found in source directory");let G={installed:[],errors:[],source:q.original};if(B.skills&&Array.isArray(B.skills)){console.log(`Found ${B.skills.length} skill(s) to update
250
- `);for(let w of B.skills)U$(z,w,K,G)}else{let w=B.name||q$(z).base;U$(O$(z),q$(z).base,K,G)}let V=c1(z,q),I=T(V,"agents.json");if(b(I)){let w=V;if(_){let J;try{J=JSON.parse(I$(I,"utf8"))}catch{}let N=J?.repository||q.original,S=n1(V,N);if(S)w=S}m$(w,{isUpdate:!0})}if(_&&z)try{let w=z.split("/.agents/tmp/")[0]+"/.agents/tmp/"+z.split("/.agents/tmp/")[1].split("/")[0];x(`rm -rf "${w}"`,{stdio:"pipe"})}catch{}if(console.log(`
251
- **Successfully updated skills:**`),console.log(`- Source: ${G.source}`),G.installed.length>0)for(let w of G.installed)console.log(` - Updated: ${w.name} at ${w.path}`),console.log(` ${w.title}`);if(G.errors.length>0){console.log(`
252
- **Errors:**`);for(let w of G.errors)console.log(` - ${w}`)}if(G.installed.length===0&&G.errors.length===0)console.log(" No skills were updated");if(G.installed.length>0)o1(q.original,K,G,Z,W)}catch(B){if(_&&z)try{let G=z.split("/.agents/tmp/")[0]+"/.agents/tmp/"+z.split("/.agents/tmp/")[1].split("/")[0];x(`rm -rf "${G}"`,{stdio:"pipe"})}catch{}console.log(`
253
- Error: ${B.message}`)}},E3=($)=>new Promise((Q)=>{let X=z3({input:process.stdin,output:process.stdout});X.question($,(Z)=>{X.close(),Q(Z.trim())})}),p$=($)=>{try{return q3($).isSymbolicLink()}catch{return!1}},l1=async()=>{let $=process.argv.slice(3),Q=$.find((L)=>!L.startsWith("-")),X=$.filter((L)=>L.startsWith("-"));if(!Q){console.log(`Usage: superpowers-agent rm <url-or-path|@alias> [options]
250
+ `)}let W=o$(Q);if(!W){console.log(`Error: Invalid URL or path not found: ${Q}`);return}if(q&&W.type==="git-repo"&&!W.path)W.path=q;let K=i$(X);console.log(`Install location: ${K}
251
+ `);let E,_=!1;try{if(W.type==="git-repo"||W.type==="git-tree"){if(console.log(`Cloning repository: ${W.repoUrl}`),W.branch)console.log(`Branch: ${W.branch}`);if(E=l$(W.repoUrl,W.branch),_=!0,W.path){if(E=v(E,W.path),!b(E))throw Error(`Path not found in repository: ${W.path}`)}console.log("")}else E=W.path;let B=Q$(E);if(!B)throw Error("No skill.json found in source directory");let G={installed:[],errors:[],source:W.original};if(B.skills&&Array.isArray(B.skills)){console.log(`Found ${B.skills.length} skill(s) to update
252
+ `);for(let U of B.skills)J$(E,U,K,G)}else{let U=B.name||z$(E).base;J$(w$(E),z$(E).base,K,G)}let V=lQ(E,W),J=v(V,"agents.json");if(b(J)){let U=V;if(_){let w;try{w=JSON.parse(O$(J,"utf8"))}catch{}let C=w?.repository||W.original,f=aQ(V,C);if(f)U=f}p$(U,{isUpdate:!0})}if(_&&E)try{let U=E.split("/.agents/tmp/")[0]+"/.agents/tmp/"+E.split("/.agents/tmp/")[1].split("/")[0];j(`rm -rf "${U}"`,{stdio:"pipe"})}catch{}if(console.log(`
253
+ **Successfully updated skills:**`),console.log(`- Source: ${G.source}`),G.installed.length>0)for(let U of G.installed)console.log(` - Updated: ${U.name} at ${U.path}`),console.log(` ${U.title}`);if(G.errors.length>0){console.log(`
254
+ **Errors:**`);for(let U of G.errors)console.log(` - ${U}`)}if(G.installed.length===0&&G.errors.length===0)console.log(" No skills were updated");if(G.installed.length>0)rQ(W.original,K,G,Z,z)}catch(B){if(_&&E)try{let G=E.split("/.agents/tmp/")[0]+"/.agents/tmp/"+E.split("/.agents/tmp/")[1].split("/")[0];j(`rm -rf "${G}"`,{stdio:"pipe"})}catch{}console.log(`
255
+ Error: ${B.message}`)}},xY=($)=>new Promise((Q)=>{let X=jY({input:process.stdin,output:process.stdout});X.question($,(Z)=>{X.close(),Q(Z.trim())})}),c$=($)=>{try{return CY($).isSymbolicLink()}catch{return!1}},eQ=async()=>{let $=process.argv.slice(3),Q=$.find((L)=>!L.startsWith("-")),X=$.filter((L)=>L.startsWith("-"));if(!Q){console.log(`Usage: superpowers-agent rm <url-or-path|@alias> [options]
254
256
 
255
257
  Options:
256
258
  --global, -g Remove globally installed skills (default)
@@ -259,10 +261,10 @@ Options:
259
261
  Examples:
260
262
  superpowers-agent rm https://github.com/example/skills
261
263
  superpowers-agent rm @myrepo
262
- superpowers-agent rm ~/my-local-skills`);return}let Z=!X.includes("--project")&&!X.includes("-p"),Y=Q,H=null;if(Q.startsWith("@")){H=Q;let L=P(!1),U=P(!0);if(L[Q])Y=L[Q];else if(U[Q])Y=U[Q];else{console.log(`Error: Repository alias not found: ${Q}`);return}}let W=z1(Z),q=W[Q]||W[Y],K=q?.installBase||n$(X),z=[];if(q)z=q.skills;else{console.log(`No tracking data found. Attempting to re-resolve skills from source...
263
- `);let L=c$(Y);if(!L){console.log(`Error: Invalid URL or path not found: ${Y}`);return}let U,F=!1;try{if(L.type==="git-repo"||L.type==="git-tree"){if(console.log(`Cloning repository: ${L.repoUrl}`),U=o$(L.repoUrl,L.branch),F=!0,L.path){if(U=T(U,L.path),!b(U))throw Error(`Path not found in repository: ${L.path}`)}}else U=L.path;let f=e(U);if(!f)throw Error("No skill.json found in source");let u=f.skills&&Array.isArray(f.skills)?f.skills:[f.name||q$(U).base];for(let O of u){let h=O;if(f.skills){let z$=T(U,O);if(b(z$)){let i$=e(z$);if(i$?.name)h=i$.name}}z.push({name:h,path:T(K,h)})}if(F)try{let O=U.split("/.agents/tmp/")[0]+"/.agents/tmp/"+U.split("/.agents/tmp/")[1].split("/")[0];x(`rm -rf "${O}"`,{stdio:"pipe"})}catch{}}catch(f){if(F&&U)try{let u=U.split("/.agents/tmp/")[0]+"/.agents/tmp/"+U.split("/.agents/tmp/")[1].split("/")[0];x(`rm -rf "${u}"`,{stdio:"pipe"})}catch{}console.log(`Error resolving source: ${f.message}`);return}}let _=z.filter((L)=>b(L.path)||p$(L.path)),B=[];for(let L of z)for(let U of L$){let F=T(U.skillsDir(),L.name);if(b(F)||p$(F))B.push({platform:U.name,path:F})}let G=E1(),V=H||Y,I=[];if(G[V]){for(let[,L]of Object.entries(G[V].agents||{}))for(let[,U]of Object.entries(L))if(U.destination&&(b(U.destination)||p$(U.destination)))I.push({path:U.destination})}let w=V.replace(/^@/,"").replace(/[^a-zA-Z0-9_-]/g,"_"),J=T(p(),".agents","repos",w),N=b(J),S=p(),v=(L)=>L.replace(S,"~");if(_.length===0&&B.length===0&&I.length===0&&!N){console.log("Nothing to remove.");return}if(console.log("Will remove:"),_.length>0){console.log(" Skills:");for(let L of _)console.log(` ${v(L.path)}`)}if(B.length>0){console.log(" Platform symlinks:");for(let L of B)console.log(` ${v(L.path)}`)}if(I.length>0){console.log(" Agents:");for(let L of I)console.log(` ${v(L.path)}`)}if(N)console.log(" Persisted repo:"),console.log(` ${v(J)}`);if((await E3(`
264
- Proceed? [y/N] `)).toLowerCase()!=="y"){console.log("Aborted.");return}for(let L of B){let U=g$(L.path);if(U.removed)console.log(`Removed symlink: ${v(L.path)}`),D1(L.platform,L.path,"skills");else if(U.error==="Symlink does not exist")console.log(`Already removed: ${v(L.path)}`);else console.log(`Warning: ${v(L.path)}: ${U.error}`)}for(let L of I){let U=g$(L.path);if(U.removed)console.log(`Removed agent: ${v(L.path)}`);else if(U.error==="Symlink does not exist")console.log(`Already removed: ${v(L.path)}`);else console.log(`Warning: ${v(L.path)}: ${U.error}`)}if(N)try{h$(J,{recursive:!0,force:!0}),console.log(`Removed persisted repo: ${v(J)}`)}catch(L){console.log(`Warning: Failed to remove persisted repo: ${L.message}`)}for(let L of _){if(!b(L.path)){console.log(`Already removed: ${v(L.path)}`);continue}try{h$(L.path,{recursive:!0,force:!0}),console.log(`Removed skill: ${v(L.path)}`)}catch(U){console.log(`Warning: Failed to remove ${v(L.path)}: ${U.message}`)}}if(b$(Q,Z),Y!==Q)b$(Y,Z);if(G[V]){let L=y(!0);if(L.installedAgents)delete L.installedAgents[V],m(L,!0)}console.log(`
265
- Done.`)},a1=()=>{let $=process.argv.slice(3),Q=$.find((z)=>!z.startsWith("-")),X=$.filter((z)=>z.startsWith("-"));if(!Q){console.log(`Usage: superpowers-agent add-repository <git-url> [options]
264
+ superpowers-agent rm ~/my-local-skills`);return}let Z=!X.includes("--project")&&!X.includes("-p"),Y=Q,q=null;if(Q.startsWith("@")){q=Q;let L=k(!1),I=k(!0);if(L[Q])Y=L[Q];else if(I[Q])Y=I[Q];else{console.log(`Error: Repository alias not found: ${Q}`);return}}let z=EQ(Z),W=z[Q]||z[Y],K=W?.installBase||i$(X),E=[];if(W)E=W.skills;else{console.log(`No tracking data found. Attempting to re-resolve skills from source...
265
+ `);let L=o$(Y);if(!L){console.log(`Error: Invalid URL or path not found: ${Y}`);return}let I,F=!1;try{if(L.type==="git-repo"||L.type==="git-tree"){if(console.log(`Cloning repository: ${L.repoUrl}`),I=l$(L.repoUrl,L.branch),F=!0,L.path){if(I=v(I,L.path),!b(I))throw Error(`Path not found in repository: ${L.path}`)}}else I=L.path;let S=Q$(I);if(!S)throw Error("No skill.json found in source");let g=S.skills&&Array.isArray(S.skills)?S.skills:[S.name||z$(I).base];for(let O of g){let c=O;if(S.skills){let E$=v(I,O);if(b(E$)){let a$=Q$(E$);if(a$?.name)c=a$.name}}E.push({name:c,path:v(K,c)})}if(F)try{let O=I.split("/.agents/tmp/")[0]+"/.agents/tmp/"+I.split("/.agents/tmp/")[1].split("/")[0];j(`rm -rf "${O}"`,{stdio:"pipe"})}catch{}}catch(S){if(F&&I)try{let g=I.split("/.agents/tmp/")[0]+"/.agents/tmp/"+I.split("/.agents/tmp/")[1].split("/")[0];j(`rm -rf "${g}"`,{stdio:"pipe"})}catch{}console.log(`Error resolving source: ${S.message}`);return}}let _=E.filter((L)=>b(L.path)||c$(L.path)),B=[];for(let L of E)for(let I of U$){let F=v(I.skillsDir(),L.name);if(b(F)||c$(F))B.push({platform:I.name,path:F})}let G=KQ(),V=q||Y,J=[];if(G[V]){for(let[,L]of Object.entries(G[V].agents||{}))for(let[,I]of Object.entries(L))if(I.destination&&(b(I.destination)||c$(I.destination)))J.push({path:I.destination})}let U=V.replace(/^@/,"").replace(/[^a-zA-Z0-9_-]/g,"_"),w=v(p(),".agents","repos",U),C=b(w),f=p(),N=(L)=>L.replace(f,"~");if(_.length===0&&B.length===0&&J.length===0&&!C){console.log("Nothing to remove.");return}if(console.log("Will remove:"),_.length>0){console.log(" Skills:");for(let L of _)console.log(` ${N(L.path)}`)}if(B.length>0){console.log(" Platform symlinks:");for(let L of B)console.log(` ${N(L.path)}`)}if(J.length>0){console.log(" Agents:");for(let L of J)console.log(` ${N(L.path)}`)}if(C)console.log(" Persisted repo:"),console.log(` ${N(w)}`);if((await xY(`
266
+ Proceed? [y/N] `)).toLowerCase()!=="y"){console.log("Aborted.");return}for(let L of B){let I=k$(L.path);if(I.removed)console.log(`Removed symlink: ${N(L.path)}`),yQ(L.platform,L.path,"skills");else if(I.error==="Symlink does not exist")console.log(`Already removed: ${N(L.path)}`);else console.log(`Warning: ${N(L.path)}: ${I.error}`)}for(let L of J){let I=k$(L.path);if(I.removed)console.log(`Removed agent: ${N(L.path)}`);else if(I.error==="Symlink does not exist")console.log(`Already removed: ${N(L.path)}`);else console.log(`Warning: ${N(L.path)}: ${I.error}`)}if(C)try{n$(w,{recursive:!0,force:!0}),console.log(`Removed persisted repo: ${N(w)}`)}catch(L){console.log(`Warning: Failed to remove persisted repo: ${L.message}`)}for(let L of _){if(!b(L.path)){console.log(`Already removed: ${N(L.path)}`);continue}try{n$(L.path,{recursive:!0,force:!0}),console.log(`Removed skill: ${N(L.path)}`)}catch(I){console.log(`Warning: Failed to remove ${N(L.path)}: ${I.message}`)}}if(F$(Q,Z),Y!==Q)F$(Y,Z);if(G[V]){let L=y(!0);if(L.installedAgents)delete L.installedAgents[V],h(L,!0)}console.log(`
267
+ Done.`)},$X=()=>{let $=process.argv.slice(3),Q=$.find((E)=>!E.startsWith("-")),X=$.filter((E)=>E.startsWith("-"));if(!Q){console.log(`Usage: superpowers-agent add-repository <git-url> [options]
266
268
 
267
269
  Options:
268
270
  --global, -g Add repository globally in ~/.agents/config.json (default)
@@ -280,9 +282,15 @@ Description:
280
282
  The repository's skill.json will be read to determine the default alias.
281
283
  Use --as to specify a custom alias.
282
284
  After adding, you can install skills using: superpowers-agent add @alias path/to/skill`);return}console.log(`Adding repository...
283
- `);let Z=X.some((z)=>z==="--global"||z==="-g"),Y=X.some((z)=>z==="--project"||z==="-p"),H=X.find((z)=>z.startsWith("--as=")),W=H?H.split("=")[1]:null,q=Y?!1:!0,K;try{console.log(`Cloning repository: ${Q}`),K=T(p(),".agents","tmp",`repo-add-${Date.now()}`),x(`mkdir -p "${K}"`,{stdio:"pipe"}),x(`git clone --depth 1 "${Q}" "${K}"`,{stdio:"pipe",timeout:30000}),console.log("");let z=e(K);if(!z)throw Error("No skill.json found in repository");let _;if(W)_=W;else if(z.repository)_=z.repository;else{let V=Q.match(/\/([^/]+?)(?:\.git)?$/);if(V)_="@"+V[1];else throw Error("Could not determine repository alias. Use --as=@alias to specify manually.")}W1(_,Q,q),x(`rm -rf "${K}"`,{stdio:"pipe"});let B=q?"globally":"in project",G=q?T(p(),".agents","config.json"):T(process.cwd(),".agents","config.json");console.log(`✓ Repository added ${B}`),console.log(` Alias: ${_}`),console.log(` URL: ${Q}`),console.log(` Config: ${G}`),console.log(`
284
- You can now install skills using:`),console.log(` superpowers-agent add ${_} <path-to-skill>`)}catch(z){if(K)try{x(`rm -rf "${K}"`,{stdio:"pipe"})}catch{}console.log(`
285
- Error: ${z.message}`)}};import{dirname as K3}from"path";var s1=($)=>{if(!$){console.log(`Usage: superpowers-agent use-skill <skill-name>
285
+ `);let Z=X.some((E)=>E==="--global"||E==="-g"),Y=X.some((E)=>E==="--project"||E==="-p"),q=X.find((E)=>E.startsWith("--as=")),z=q?q.split("=")[1]:null,W=Y?!1:!0,K;try{console.log(`Cloning repository: ${Q}`),K=v(p(),".agents","tmp",`repo-add-${Date.now()}`),j(`mkdir -p "${K}"`,{stdio:"pipe"}),j(`git clone --depth 1 "${Q}" "${K}"`,{stdio:"pipe",timeout:30000}),console.log("");let E=Q$(K);if(!E)throw Error("No skill.json found in repository");let _;if(z)_=z;else if(E.repository)_=E.repository;else{let V=Q.match(/\/([^/]+?)(?:\.git)?$/);if(V)_="@"+V[1];else throw Error("Could not determine repository alias. Use --as=@alias to specify manually.")}HQ(_,Q,W),j(`rm -rf "${K}"`,{stdio:"pipe"});let B=W?"globally":"in project",G=W?v(p(),".agents","config.json"):v(process.cwd(),".agents","config.json");console.log(`✓ Repository added ${B}`),console.log(` Alias: ${_}`),console.log(` URL: ${Q}`),console.log(` Config: ${G}`),console.log(`
286
+ You can now install skills using:`),console.log(` superpowers-agent add ${_} <path-to-skill>`)}catch(E){if(K)try{j(`rm -rf "${K}"`,{stdio:"pipe"})}catch{}console.log(`
287
+ Error: ${E.message}`)}};import{dirname as QX}from"path";var XX=($,Q,X)=>{let{content:Z,frontmatter:Y}=M$($),q=r[Q].prefix+X,z=QX($),W=`# ${Y.name||q}`;if(Y.description)W+=`
288
+ # ${Y.description}`;if(Y.whenToUse)W+=`
289
+ # When to use: ${Y.whenToUse}`;return W+=`
290
+ # Supporting tools and docs are in ${z}
291
+ # ============================================
292
+
293
+ ${Z}`,W},YX=($)=>{if(!$){console.log(`Usage: superpowers-agent use-skill <skill-name>
286
294
 
287
295
  Examples (smart matching):
288
296
  superpowers-agent use-skill brainstorming # Matches superpowers:collaboration/brainstorming
@@ -297,15 +305,24 @@ Examples (explicit paths):
297
305
  Smart matching:
298
306
  - Type just the skill name or any suffix of the path
299
307
  - Priority: .agents/skills/ > .claude/skills/ > ~/.agents/skills/ > ~/.agents/superpowers/skills/
300
- - If multiple skills match at same priority, you'll see them with descriptions`);return}let Q=i($);if(!Q){console.log(`Error: Skill not found: ${$}
308
+ - If multiple skills match at same priority, you'll see them with descriptions`);return}let Q=m($);if(!Q){console.log(`Error: Skill not found: ${$}
301
309
 
302
- Available skills:`),console.log("Run: superpowers-agent find-skills");return}let{skillFile:X,sourceType:Z,actualSkillPath:Y}=Q;try{let{content:H,frontmatter:W}=s$(X),q=X$[Z].prefix+Y,K=K3(X),z=`# ${W.name||q}`;if(W.description)z+=`
303
- # ${W.description}`;if(W.whenToUse)z+=`
304
- # When to use: ${W.whenToUse}`;z+=`
310
+ Available skills:`),console.log("Run: superpowers-agent find-skills");return}let{skillFile:X,sourceType:Z,actualSkillPath:Y}=Q;try{let{content:q,frontmatter:z}=M$(X),W=r[Z].prefix+Y,K=QX(X),E=`# ${z.name||W}`;if(z.description)E+=`
311
+ # ${z.description}`;if(z.whenToUse)E+=`
312
+ # When to use: ${z.whenToUse}`;E+=`
305
313
  # Supporting tools and docs are in ${K}
306
314
  # ============================================
307
315
 
308
- ${H}`,console.log(z)}catch(H){console.log(H.message)}};var t1={bootstrap:d1,version:M1,"check-updates":()=>{A1().catch(($)=>{console.error($.message),process.exit(1)})},update:()=>{let $=process.argv.includes("--no-reinstall");D$({skipReinstall:$})},"config-get":U1,"config-set":I1,"setup-skills":k1,"use-skill":()=>s1(process.argv[3]),execute:G1,"find-skills":a,add:i1,"add-repository":a1,"list-repositories":O1,pull:r1,rm:l1,dir:L1,path:V1,"get-helpers":w1,"install-aliases":u$,default:()=>{console.log(`Superpowers for Agents
316
+ ${q}`,console.log(E)}catch(q){console.log(q.message)}};var DY=`You have superpowers.
317
+
318
+ **IMPORTANT: The using-superpowers skill content is included below. It is ALREADY LOADED - you are currently following it. Do NOT use the skill tool to load "using-superpowers" again - that would be redundant.**`,RY="---\n\n**YOU MUST read and use the `leveraging-cli-tools` skill** the moment a task involves searching code, parsing JSON/YAML, finding files, structural refactors, data wrangling, or any command that floods your context with verbose output (logs, CI logs, test runs). Load it with your skill tool BEFORE you reach for grep/find/sed or before you read large command output. It routes you to high-performance tools (rg, jq, fd, yq, ast-grep, gh, sd) and reduces output to just the signal — cutting token cost and latency 5-50x. Skipping it wastes tokens and time on work the right tool does instantly.",fY=()=>{let $=m("using-superpowers");if(!$)return null;let Q;try{Q=XX($.skillFile,$.sourceType,$.actualSkillPath)}catch{return null}return`<EXTREMELY_IMPORTANT>
319
+ ${DY}
320
+
321
+ ${Q}
322
+
323
+ ${RY}
324
+ </EXTREMELY_IMPORTANT>`},yY=($="raw")=>{let Q=fY();if($==="claude")return JSON.stringify({hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:Q||""}});if($==="copilot")return JSON.stringify({additionalContext:Q||""});return Q||""},ZX=()=>{let $=process.argv.find((X)=>X.startsWith("--format=")),Q=$?$.split("=")[1]:"raw";process.stdout.write(yY(Q)+`
325
+ `)};var qX={bootstrap:cQ,version:TQ,"check-updates":()=>{AQ().catch(($)=>{console.error($.message),process.exit(1)})},update:()=>{let $=process.argv.includes("--no-reinstall");R$({skipReinstall:$})},"config-get":JQ,"config-set":OQ,"setup-skills":pQ,"use-skill":()=>YX(process.argv[3]),"session-context":ZX,execute:VQ,"find-skills":s,add:sQ,"add-repository":$X,"list-repositories":wQ,pull:tQ,rm:eQ,dir:UQ,path:LQ,"get-helpers":IQ,"install-aliases":u$,default:()=>{console.log(`Superpowers for Agents
309
326
  Usage:
310
327
  superpowers-agent bootstrap [--no-update] [--force] # Run complete bootstrap
311
328
  superpowers-agent version # Show current version
@@ -315,6 +332,7 @@ Usage:
315
332
  superpowers-agent config-set <key> <value> # Update configuration
316
333
  superpowers-agent setup-skills # Initialize project skills
317
334
  superpowers-agent use-skill <skill-name> # Load a skill
335
+ superpowers-agent session-context [--format=claude|copilot|raw] # Print session-start context (used by hooks)
318
336
  superpowers-agent find-skills # List available skills
319
337
  superpowers-agent add <url-or-path|@alias> [path] [options] # Install skills
320
338
  superpowers-agent add-repository <git-url> [--as=@alias] [opts] # Add repository alias
@@ -328,4 +346,4 @@ Usage:
328
346
  superpowers-agent install-aliases # Install universal aliases (superpowers, superpowers-agent)
329
347
 
330
348
  Documentation: https://github.com/complexthings/superpowers
331
- `)}},B3=process.argv[2]||"default",_3=t1[B3]||t1.default;try{let $=_3();if($&&typeof $.then==="function")$.catch((Q)=>{console.error(`Error: ${Q.message}`),process.exit(1)})}catch($){console.error(`Error: ${$.message}`),process.exit(1)}
349
+ `)}},SY=process.argv[2]||"default",PY=qX[SY]||qX.default;try{let $=PY();if($&&typeof $.then==="function")$.catch((Q)=>{console.error(`Error: ${Q.message}`),process.exit(1)})}catch($){console.error(`Error: ${$.message}`),process.exit(1)}
package/README.md CHANGED
@@ -6,6 +6,12 @@ A comprehensive skills library of proven techniques, patterns, and workflows for
6
6
 
7
7
  ## What's New
8
8
 
9
+ **v9.1.0 (May 30, 2026):**
10
+
11
+ - **Session-start hooks installed by `bootstrap`** — `bootstrap` now installs a Claude Code `SessionStart` hook into `~/.claude/settings.json` and a GitHub Copilot CLI `sessionStart` hook at `~/.copilot/hooks/superpowers.json`, so the Superpowers context is injected at the start of every session. The Claude merge is idempotent and preserves your other hooks/settings. (This replaces the old Claude Code plugin hook, which has been removed.)
12
+ - **`leveraging-cli-tools` in the injected prompt** — the session-start context now also tells agents to use the `leveraging-cli-tools` skill for code search, parsing, file finding, refactors, and verbose output to cut token cost and latency.
13
+ - **New `session-context` command** — `superpowers-agent session-context [--format=claude|copilot|raw]` is the single source of truth for the injected prompt, shared by the Claude hook, the Copilot hook, and the OpenCode plugin so they never drift.
14
+
9
15
  **v9.0.0 (May 28, 2026):**
10
16
 
11
17
  - **Claude persona installation** — `.claude/agents/<name>.md` personas now install into `~/.claude/agents/` via `add`/`pull` (previously silently skipped)
@@ -313,11 +319,11 @@ Skills are available via OpenCode's native `skill` tool. The `.opencode/plugins/
313
319
 
314
320
  ### GitHub Copilot
315
321
 
316
- Skills are available via the native skill tool.
322
+ Skills are available via the native skill tool. `bootstrap` installs a `sessionStart` hook at `~/.copilot/hooks/superpowers.json` (honoring `$COPILOT_HOME`) that injects the Superpowers context — including the `leveraging-cli-tools` directive — at the start of every Copilot CLI session via the hook's `additionalContext` output.
317
323
 
318
324
  ### Claude Code
319
325
 
320
- Skills are available via the native skill tool. Claude agent personas defined in `.claude/agents/<name>.md` are installed into `~/.claude/agents/` via `add`/`pull`.
326
+ Skills are available via the native skill tool. Claude agent personas defined in `.claude/agents/<name>.md` are installed into `~/.claude/agents/` via `add`/`pull`. `bootstrap` also installs a `SessionStart` hook into `~/.claude/settings.json` that injects the Superpowers context every session (idempotent; preserves your other hooks and settings).
321
327
 
322
328
  ## What's Inside
323
329
 
@@ -433,10 +439,18 @@ superpowers-agent get-config <key> # Get specific config value
433
439
  **Project Setup:**
434
440
  ```bash
435
441
  superpowers-agent setup-skills # Initialize project with skills docs
436
- superpowers-agent bootstrap # Run complete bootstrap
442
+ superpowers-agent bootstrap # Run complete bootstrap (installs Claude + Copilot session hooks)
437
443
  superpowers-agent update # Update to latest version
438
444
  ```
439
445
 
446
+ **Session Hooks:**
447
+ ```bash
448
+ superpowers-agent session-context # Print session-start context (raw)
449
+ superpowers-agent session-context --format=claude # Emit Claude Code SessionStart hook JSON
450
+ superpowers-agent session-context --format=copilot # Emit GitHub Copilot sessionStart hook JSON
451
+ ```
452
+ The platform hooks installed by `bootstrap` call this command; it is the single source of truth for the injected prompt (the `using-superpowers` content plus the `leveraging-cli-tools` directive).
453
+
440
454
  ### Skill Metadata with skill.json
441
455
 
442
456
  Skills can include a `skill.json` file to define metadata for the superpowers-agent CLI. This enables powerful features like repository aliases, helper file discovery, and multi-skill repositories.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@complexthings/superpowers-agent",
3
- "version": "9.0.1",
3
+ "version": "9.1.0",
4
4
  "description": "Superpowers agent CLI — skills system for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,7 +16,6 @@
16
16
  ".agents/plans",
17
17
  ".agents/superpowers-bootstrap.md",
18
18
  "skills",
19
- "hooks",
20
19
  ".github",
21
20
  "AGENTS.md",
22
21
  "README.md",
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: leveraging-cli-tools
3
- description: Use when performing code searches, JSON/YAML parsing, file finding, structural refactors, or data wrangling - ensures agents reach for high-performance CLI tools (rg, jq, fd, yq, ast-grep, gh, sd) over slower standard tools like grep/find/sed, cutting token cost and latency 5-50x. Check availability and offer to install a tool when a relevant task arises.
3
+ description: Use when performing code searches, JSON/YAML parsing, file finding, structural refactors, or data wrangling, or when a command floods context with verbose output like logs, CI, or test runs - ensures agents reach for high-performance CLI tools (rg, jq, fd, yq, ast-grep, gh, sd) over slower standard tools like grep/find/sed and use them with discipline, choosing the right output-reducing flags, composing pipelines so raw output never enters context, and using a bundled reducer for output that flags cannot shape, cutting token cost and latency 5-50x. Check availability and offer to install a tool when a relevant task arises.
4
+ compatibility: The bundled scripts/slim.py needs python3 (standard on macOS/Linux). The CLI tools install via the system package manager.
4
5
  ---
5
6
 
6
7
  # Leveraging CLI Tools
@@ -9,6 +10,8 @@ description: Use when performing code searches, JSON/YAML parsing, file finding,
9
10
 
10
11
  Reach for high-performance CLI tools over slower standard tools. The leverage is filtering and transforming with the right tool **before reading**, so tokens and time go to the answer, not the search. On a large tree `rg` is 10-50x faster than `grep` and returns far less noise; across a session that compounds into hours and tens of thousands of tokens saved.
11
12
 
13
+ Picking the faster tool is only half of it. The other half is using it with discipline — two levers that keep raw output out of your context: **ask for less** (the right flags and selectors), and **shrink what you can't shape** (a reducer for inherently verbose output). A fast tool fed a lazy command still floods your context.
14
+
12
15
  ## When a relevant task arises
13
16
 
14
17
  1. Pick the right tool from the table below.
@@ -37,29 +40,56 @@ Check only the tools the current task needs — no upfront session-wide scan.
37
40
  | 5 | `fzf` (`-f`) | manual fuzzy filtering | Non-interactive `-f`/`--filter` mode: fuzzy-rank a candidate list piped from `fd`/`rg`. | `brew install fzf` |
38
41
  | 4 | `watchexec` | `while`+`sleep`, `entr` | Run a command on file change. Useful in build/test loops; non-interactive unlike most watchers. | `brew install watchexec` |
39
42
 
40
- ## Core workflows
43
+ ## Use them with discipline
41
44
 
42
- **Filter before reading** find the matches, then read only those.
43
- ```bash
44
- rg -l "password.*hash" src/auth/ --type ts | xargs rg "TODO"
45
- ```
45
+ Five habits separate a fast, low-noise result from a slow, context-flooding one. The token savings below are measured, not hypothetical.
46
+
47
+ **1 Pick the tool that fits the data, not the one in muscle memory.** JSON → `jq`, YAML/TOML `yq`, structural refactor `ast-grep`, GitHub → `gh`. The reflex to resist is `grep`/`sed`/`awk` on structured data — they treat structure as flat text, so you pay in escaping bugs and noise the format-aware tool never produces.
48
+
49
+ **2 — Ask for less: use the flag or selector that returns the answer's _shape_.** The biggest single win is never pulling raw output into context. Match the request to the question:
50
+
51
+ | Question | Flag / selector | Returns |
52
+ |----------|-----------------|---------|
53
+ | Which files match? | `rg -l` | paths only, no lines |
54
+ | How many files? | `rg -l \| wc -l` | a file count, not a line count |
55
+ | How many hits? | `rg -c` (lines/file) / `rg --count-matches` (matches/file) | counts only |
56
+ | Just the matched bit? | `rg -o` | the substring, not the whole line |
57
+ | Enough to judge a hit? | `rg -A/-B/-C N`, `rg -m N` (cap per file) | bounded context |
58
+ | Only certain fields? | `jq -r '.a, .b'`, `yq`, `mlr --opprint cut -f` | projected values, not the whole doc |
59
+ | First N of a list? | pipe to `head`, or `fd --max-results N` | the slice you need |
46
60
 
47
- **Compose tools** — search, parse, dedup in one pass.
61
+ For the **projection tools** (`jq`, `yq`, `dasel`, `miller`, `htmlq`) the selector *is* the filter `jq` turning a 2,000-record array into one summed number is a ~100% reduction on its own. Shape their output at the selector; never post-filter it (that's what habit 4 is *not* for).
62
+
63
+ **3 — Compose so only the answer comes back.** Do the counting, dedup, and projection *in the pipeline*, not by reading raw output and reasoning over it. One pass keeps every intermediate result out of context:
48
64
  ```bash
49
65
  rg -l '"error"' logs/ --type json | xargs jq -r 'select(.level=="error") | .code' | sort -u
50
66
  ```
51
-
52
- **Structural rewrite, not regex** — refactor by AST so syntax can't trip you.
67
+ This is the lesson of programmatic tool calling (Amazon's PTC benchmarks: ~87-92% fewer tokens): when a task needs several tool calls plus processing, write **one** pipeline or script that does it all and returns only the result — the intermediate data never touches your context. So: filter before reading, and refactor by AST, not regex:
53
68
  ```bash
69
+ rg -l "password.*hash" src/auth/ --type ts | xargs rg "TODO"
54
70
  sg --pattern 'console.log($$$A)' --rewrite 'logger.debug($$$A)' --lang ts
55
71
  ```
56
72
 
57
- In Claude Code the `Grep` and `Glob` tools are themselves built on ripgrepprefer them for in-context searches, and reach for the CLI tools when you need piping, transforms, or rewrites.
73
+ **4 Shrink what you can't shape: the bundled reducer for verbose emitters.** Some output has no projection flag logs, CI output (`gh run view --log`), test runs, stack traces, status dumps. Flags get you part way, but the residual stays repetitive, wide, and noisy. Pipe it through `scripts/slim.py` (relative to this skill; use its absolute path if you're working elsewhere) and ask only for the cuts the task needs:
74
+ ```bash
75
+ gh run view --log | python3 scripts/slim.py --errors --uniq --max-line 200
76
+ cargo test 2>&1 | python3 scripts/slim.py --errors --dedup
77
+ rg -n TODO --no-ignore | python3 scripts/slim.py --group-dir
78
+ ```
79
+ It does dedup (`--dedup`/`--uniq`, repeats collapse to `(xN)`), grouping (`--group-dir` → per-directory counts), truncation (`--head/--tail/--middle/--max-line`), and noise-stripping (`--comments/--errors/--grep`). On a real 1,236-line CI log, `rg` error-filtering alone cut 91% but left ~6,700 tokens; adding `slim` reached 97% — a third the residual. Run `python3 scripts/slim.py -h` for all modes. The cuts are **lossy and opt-in**: ask for what you need, know what you're discarding, and don't reach for it when a projection tool's own selector would do the job.
80
+
81
+ **5 — Read the output critically — it's a claim, not a fact.** A zero or suspiciously low result is the one to distrust: `rg` skips `.gitignore`d and hidden files by default, so a real match in `node_modules/`, `dist/`, or a dotfile is silently absent. Before concluding "none," re-run with `--no-ignore`, `-uu`, or `--hidden` — then decide whether those ignored hits (vendored deps, build output, generated mirrors) actually belong in the answer; surfacing them is the check, keeping them is a judgment call. Mind case (`-i`) and word boundaries (`-w`) so you neither miss `Subagent` nor over-match `tasks` — and when an identifier doubles as a common word (a `Task` tool vs. the word "task"), even `-w` isn't enough: glance at the context to confirm the hit is the symbol, not prose. When a count or list drives a decision, confirm a match means what you think before acting on it.
82
+
83
+ In Claude Code the `Grep` and `Glob` tools are themselves built on ripgrep — prefer them for in-context searches, and reach for the CLI tools when you need piping, transforms, rewrites, or output reduction.
58
84
 
59
85
  ## Red flags
60
86
 
61
87
  - Parsing JSON/YAML with `awk`/`sed`/`grep` instead of `jq`/`yq`.
62
88
  - Reading files before filtering them with `rg`.
89
+ - Piping a tool's full output into context to eyeball it, when `-l`/`-c`/`-o` or a `jq` projection would return just the answer.
90
+ - Letting a verbose command (test run, CI log, `git`/`docker` status dump) land raw in context when `slim` would cut it 90%+.
91
+ - Reaching for `slim` on a projection tool's output — shape it at the `jq`/`yq`/`mlr` selector instead.
92
+ - Concluding "no matches" from a default `rg` run without re-checking `--no-ignore`/`--hidden` — the hit may be sitting in an ignored directory.
63
93
  - Hand-rolling `curl` against the GitHub API instead of `gh`.
64
94
  - Regex codemods with `sed` where `ast-grep` is structurally safe.
65
95
 
@@ -70,6 +100,7 @@ In Claude Code the `Grep` and `Glob` tools are themselves built on ripgrep — p
70
100
  | "grep works fine" | On a big tree it's 10-50x slower and floods context with noise `rg` would have filtered out. |
71
101
  | "I don't know if they have jq" | One `command -v jq` answers it; install is seconds and pays back across the whole session. |
72
102
  | "Not worth the setup" | One install = a speedup on every future task, not just this one. |
103
+ | "The test/CI output is just long, I'll scroll it" | A 1,200-line log is ~75k tokens of mostly noise; `slim --errors --uniq` makes it ~2k without losing the failures. |
73
104
  | "User didn't ask for optimization" | Faster, lower-noise completion *is* better completion. |
74
105
 
75
106
  ## When NOT to use
@@ -77,3 +108,4 @@ In Claude Code the `Grep` and `Glob` tools are themselves built on ripgrep — p
77
108
  - A tiny one-off (a handful of files, well under a megabyte) where the standard tool is already at hand.
78
109
  - The user declined the install — note the cost once, then use the fallback.
79
110
  - A teaching context where the standard tool is the point.
111
+ - Output you already shaped with a selector — don't add a `slim` pass for its own sake.
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env python3
2
+ """slim - reduce noisy command output to signal before it reaches your context.
3
+
4
+ A stdin->stdout filter for output you CAN'T shape with a tool's own flags:
5
+ logs, scan results, status dumps, stack traces, repeated lines. For tools that
6
+ already project output (jq/yq/dasel/miller/htmlq), use their selectors instead;
7
+ piping them through slim is redundant.
8
+
9
+ Pipe a verbose command through it and ask only for the reductions you need:
10
+
11
+ cargo test 2>&1 | slim --errors --dedup
12
+ rg -n TODO --no-ignore | slim --group-dir
13
+ gh run view --log | slim --uniq --max-line 200 --middle 40
14
+ kubectl get events | slim --dedup --stats
15
+
16
+ Reductions (compose freely):
17
+ --comments drop comment-only lines (# // ; -- *) and blank lines
18
+ --errors keep only lines matching error|warn|fail|fatal|panic|exception (-i)
19
+ --grep RE keep only lines matching regex RE (use --invert to drop them)
20
+ --invert invert --grep / --errors (drop matches instead of keeping)
21
+ --dedup collapse ALL repeated lines, first-seen order, annotate " (xN)"
22
+ --uniq collapse only CONSECUTIVE repeats, annotate " (xN)" (log-friendly)
23
+ --group-dir turn a list of file paths into per-directory counts
24
+ --max-line N truncate each line to N chars, append a horizontal ellipsis
25
+ --head N keep first N lines
26
+ --tail N keep last N lines
27
+ --middle N keep first N and last N lines, replace the gap with a marker
28
+ --stats print "lines A->B, bytes A->B (-P%)" to stderr (output unaffected)
29
+
30
+ Always-on, lossless: trailing whitespace is stripped and runs of blank lines
31
+ collapse to one. Everything lossy is opt-in. Order: filter -> transform ->
32
+ dedup -> group -> blank-collapse -> truncate. Reductions are LOSSY by design;
33
+ ask for what the task needs and know what you're discarding.
34
+ """
35
+ import argparse
36
+ import re
37
+ import sys
38
+
39
+ COMMENT_RE = re.compile(r"^\s*(#|//|;|--|\*|/\*|\*/)")
40
+ ERROR_RE = re.compile(r"error|warn|fail|fatal|panic|exception|traceback", re.IGNORECASE)
41
+ ELLIPSIS = "…"
42
+
43
+
44
+ def annotate(line: str, n: int) -> str:
45
+ return line if n == 1 else f"{line} (x{n})"
46
+
47
+
48
+ def dedup_all(lines):
49
+ counts, order = {}, []
50
+ for ln in lines:
51
+ if ln not in counts:
52
+ counts[ln] = 0
53
+ order.append(ln)
54
+ counts[ln] += 1
55
+ return [annotate(ln, counts[ln]) for ln in order]
56
+
57
+
58
+ def dedup_adjacent(lines):
59
+ out, prev, n = [], None, 0
60
+ for ln in lines:
61
+ if ln == prev:
62
+ n += 1
63
+ else:
64
+ if prev is not None:
65
+ out.append(annotate(prev, n))
66
+ prev, n = ln, 1
67
+ if prev is not None:
68
+ out.append(annotate(prev, n))
69
+ return out
70
+
71
+
72
+ def group_dir(lines):
73
+ counts, order = {}, []
74
+ for ln in lines:
75
+ token = ln.split(":", 1)[0].strip() # tolerate rg's path:line: prefix
76
+ d = token.rsplit("/", 1)[0] + "/" if "/" in token else "./"
77
+ if d not in counts:
78
+ counts[d] = 0
79
+ order.append(d)
80
+ counts[d] += 1
81
+ width = max((len(d) for d in order), default=0)
82
+ return [f"{d.ljust(width)} ({counts[d]} file{'s' if counts[d] != 1 else ''})" for d in order]
83
+
84
+
85
+ def collapse_blanks(lines):
86
+ out, blank = [], False
87
+ for ln in lines:
88
+ if ln.strip() == "":
89
+ if not blank:
90
+ out.append("")
91
+ blank = True
92
+ else:
93
+ out.append(ln)
94
+ blank = False
95
+ while out and out[-1] == "":
96
+ out.pop()
97
+ return out
98
+
99
+
100
+ def main() -> int:
101
+ p = argparse.ArgumentParser(add_help=True, description="Reduce noisy stdout to signal.")
102
+ p.add_argument("--comments", action="store_true")
103
+ p.add_argument("--errors", action="store_true")
104
+ p.add_argument("--grep", metavar="RE")
105
+ p.add_argument("--invert", action="store_true")
106
+ p.add_argument("--dedup", action="store_true")
107
+ p.add_argument("--uniq", action="store_true")
108
+ p.add_argument("--group-dir", action="store_true")
109
+ p.add_argument("--max-line", type=int, metavar="N")
110
+ p.add_argument("--head", type=int, metavar="N")
111
+ p.add_argument("--tail", type=int, metavar="N")
112
+ p.add_argument("--middle", type=int, metavar="N")
113
+ p.add_argument("--stats", action="store_true")
114
+ args = p.parse_args()
115
+
116
+ raw = sys.stdin.read()
117
+ in_lines = raw.splitlines()
118
+ in_bytes = len(raw.encode("utf-8", "replace"))
119
+
120
+ lines = [ln.rstrip() for ln in in_lines]
121
+
122
+ if args.comments:
123
+ lines = [ln for ln in lines if ln.strip() and not COMMENT_RE.match(ln)]
124
+
125
+ if args.errors or args.grep:
126
+ pat = re.compile(args.grep) if args.grep else ERROR_RE
127
+ keep = (lambda ln: not pat.search(ln)) if args.invert else (lambda ln: bool(pat.search(ln)))
128
+ lines = [ln for ln in lines if keep(ln)]
129
+
130
+ if args.max_line and args.max_line > 0:
131
+ lines = [ln if len(ln) <= args.max_line else ln[: args.max_line] + ELLIPSIS for ln in lines]
132
+
133
+ if args.dedup:
134
+ lines = dedup_all(lines)
135
+ elif args.uniq:
136
+ lines = dedup_adjacent(lines)
137
+
138
+ if args.group_dir:
139
+ lines = group_dir(lines)
140
+
141
+ lines = collapse_blanks(lines)
142
+
143
+ if args.middle and args.middle > 0 and len(lines) > 2 * args.middle:
144
+ omitted = len(lines) - 2 * args.middle
145
+ lines = lines[: args.middle] + [f"{ELLIPSIS} {omitted} lines omitted {ELLIPSIS}"] + lines[-args.middle :]
146
+ if args.head and args.head > 0:
147
+ lines = lines[: args.head]
148
+ if args.tail and args.tail > 0:
149
+ lines = lines[-args.tail :]
150
+
151
+ out = "\n".join(lines)
152
+ if out:
153
+ out += "\n"
154
+ sys.stdout.write(out)
155
+
156
+ if args.stats:
157
+ out_bytes = len(out.encode("utf-8", "replace"))
158
+ pct = 0 if in_bytes == 0 else round(100 * (1 - out_bytes / in_bytes))
159
+ change = f"-{pct}%" if pct >= 0 else f"+{-pct}% larger"
160
+ sys.stderr.write(
161
+ f"slim: lines {len(in_lines)}->{len(lines)}, bytes {in_bytes}->{out_bytes} ({change})\n"
162
+ )
163
+ return 0
164
+
165
+
166
+ if __name__ == "__main__":
167
+ sys.exit(main())
package/hooks/hooks.json DELETED
@@ -1,15 +0,0 @@
1
- {
2
- "hooks": {
3
- "SessionStart": [
4
- {
5
- "matcher": "startup|resume|clear|compact",
6
- "hooks": [
7
- {
8
- "type": "command",
9
- "command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
10
- }
11
- ]
12
- }
13
- ]
14
- }
15
- }
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SessionStart hook for superpowers plugin
3
-
4
- set -euo pipefail
5
-
6
- # Check if superpowers-agent is available
7
- if ! command -v superpowers-agent &> /dev/null; then
8
- echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": ""}}'
9
- exit 0
10
- fi
11
- # Use superpowers-agent to load the using-a-skill content
12
- using_superpowers_content=$(superpowers-agent use-skill using-superpowers 2>&1 || echo "Error: Unable to load using-superpowers. Run: superpowers-agent bootstrap")
13
-
14
- # Escape outputs for JSON
15
- using_superpowers_escaped=$(echo "$using_superpowers_content" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | awk '{printf "%s\\n", $0}')
16
-
17
- # Output context injection as JSON
18
- cat <<EOF
19
- {
20
- "hookSpecificOutput": {
21
- "hookEventName": "SessionStart",
22
- "additionalContext": "<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**Below is the full content of your 'using-superpowers' skill - your introduction to using skills.:**\n\n${using_superpowers_escaped}\n\n\n</EXTREMELY_IMPORTANT>"
23
- }
24
- }
25
- EOF
26
-
27
- exit 0