agent-skill-manager 1.5.0 → 1.6.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,15 +1,15 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{a as R,c as I,d as _0,e as d,f as F0,g as A0,h as p,i as E0,j as Y,k as g,l as T0,m as x,n as o,o as L0,q as H0,r as I0,s as n}from"./chunk-sx2p5bqv.js";import{A as F,B as O0,t as E,u as T,v as M0,w as A,x as j0,y as c,z as v}from"./chunk-zh7g5bam.js";import{execFile as w0}from"child_process";import{promisify as y0}from"util";import{mkdtemp as N0,readdir as l,readFile as N,rm as y,cp as S0,access as h,stat as i,lstat as b0,symlink as D0,mkdir as P0}from"fs/promises";import{join as L,relative as f0}from"path";import{tmpdir as k0}from"os";var s=y0(w0),h0=/^[a-zA-Z0-9_-]+$/,v0=/^[a-zA-Z0-9._-]+$/,u0=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/,t=128,m0=/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\/tree\/(.+))?\/?$/;function a($){let Q=m0.exec($);if(Q){let[,j,W,O]=Q,B=W.endsWith(".git")?W.slice(0,-4):W;$=`github:${j}/${B}${O?`#${O}`:""}`}if(!$.startsWith("github:"))throw Error(`Invalid source format. Got: "${$}"
3
+ import{a as N,c as w,d as L0,e as o,f as E0,g as I0,h as n,i as C0,j as X,k as W0,l as R0,m as t,n as w0,o as y0,p as x0,q as R,r as l,s as N0,u as S0,v as D0,w as i}from"./chunk-esvwvw47.js";import{A as H,B as H0,C as g,D as m,E as _,F as T0,x as T,y as L,z as A0}from"./chunk-t7727aqn.js";import{execFile as P0}from"child_process";import{promisify as v0}from"util";import{mkdtemp as h0,readdir as e,readFile as D,rm as S,cp as u0,access as u,stat as a,lstat as m0,symlink as c0,mkdir as d0}from"fs/promises";import{join as E,relative as p0}from"path";import{tmpdir as g0}from"os";var r=v0(P0),o0=/^[a-zA-Z0-9_-]+$/,n0=/^[a-zA-Z0-9._-]+$/,t0=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/,s=128,l0=/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\/tree\/(.+))?\/?$/;function $0($){let Q=l0.exec($);if(Q){let[,W,M,B]=Q,O=M.endsWith(".git")?M.slice(0,-4):M;$=`github:${W}/${O}${B?`#${B}`:""}`}if(!$.startsWith("github:"))throw Error(`Invalid source format. Got: "${$}"
4
4
  Supported formats:
5
5
  github:owner/repo[#ref]
6
- https://github.com/owner/repo`);let K=$.slice(7),q=K.indexOf("#"),Z,V=null;if(q!==-1){if(Z=K.slice(0,q),V=K.slice(q+1),!V)throw Error("Invalid source: ref cannot be empty after #")}else Z=K;let X=Z.indexOf("/");if(X===-1)throw Error(`Invalid source: format must be github:owner/repo. Got: "${$}"`);let z=Z.slice(0,X),J=Z.slice(X+1);if(!z)throw Error("Invalid source: owner cannot be empty");if(!J)throw Error("Invalid source: repo cannot be empty");if(!h0.test(z))throw Error(`Invalid source: owner contains invalid characters: "${z}". Allowed: [a-zA-Z0-9_-]`);if(!v0.test(J))throw Error(`Invalid source: repo contains invalid characters: "${J}". Allowed: [a-zA-Z0-9._-]`);let U={owner:z,repo:J,ref:V,cloneUrl:`https://github.com/${z}/${J}.git`};return A(`install: parsed source owner=${z} repo=${J} ref=${V}`),U}function S($){if(!$)throw Error("Invalid skill name: name cannot be empty");if($.includes("\x00"))throw Error("Invalid skill name: contains unsafe characters (null byte)");if($.includes(".."))throw Error("Invalid skill name: contains unsafe characters (..)");if($.includes("/")||$.includes("\\"))throw Error("Invalid skill name: contains unsafe characters (path separator)");if($.startsWith("."))throw Error("Invalid skill name: must not start with a dot");if($.length>t)throw Error(`Invalid skill name: exceeds maximum length of ${t} characters`);if(!u0.test($))throw Error(`Invalid skill name: "${$}" does not match allowed pattern [a-zA-Z0-9][a-zA-Z0-9._-]*`);return $}async function e(){try{await s("git",["--version"]),A("install: git available")}catch{throw Error("git is required for installing skills. Install git from https://git-scm.com")}}async function r($){A(`install: cloning ${$.cloneUrl}${$.ref?` (ref: ${$.ref})`:""}`);let Q=await N0(L(k0(),"asm-install-")),K=["clone","--depth","1"];if($.ref)K.push("--branch",$.ref);K.push($.cloneUrl,Q);try{await s("git",K,{timeout:60000})}catch(q){await D(Q);let Z=q.killed?"Clone timed out after 60 seconds":`Clone failed: ${q.stderr||q.message}`;throw Error(Z)}return Q}async function b($){let Q=L($,"SKILL.md"),K;try{K=await N(Q,"utf-8")}catch{throw Error("Not a valid skill: SKILL.md not found in repository root")}let q=R(K),Z=$.split("/").pop()||"unknown",V=q.name||Z,X=q.version||"0.0.0";return A(`install: validated skill "${V}" v${X}`),{name:V,version:X,description:(q.description||"").replace(/\s*\n\s*/g," ").trim()}}async function $0($,Q=3){let K=[];async function q(Z,V,X){let z;try{z=await l(Z)}catch{return}for(let J of z){if(J===".git"||J==="node_modules")continue;let U=L(Z,J);try{if(!(await i(U)).isDirectory())continue}catch{continue}let j=V?`${V}/${J}`:J,W=X+1,O=L(U,"SKILL.md");try{let B=await N(O,"utf-8"),G=R(B);K.push({relPath:j,name:G.name||J,version:G.version||"0.0.0",description:(G.description||"").replace(/\s*\n\s*/g," ").trim()})}catch{if(W<Q)await q(U,j,W)}}}return await q($,"",0),K.sort((Z,V)=>Z.name.localeCompare(V.name)),K}var c0=[{category:"Shell commands",pattern:/\b(bash|sh\s+-c)\b/},{category:"Shell commands",pattern:/\bexec\(/},{category:"Shell commands",pattern:/\bchild_process\b/},{category:"Shell commands",pattern:/\bBun\.spawn\b/},{category:"Code execution",pattern:/\beval\(/},{category:"Code execution",pattern:/\bFunction\(/},{category:"Code execution",pattern:/\bnew\s+Function\b/},{category:"Credentials",pattern:/\b(API_KEY|SECRET|TOKEN|PASSWORD)\s*[=:]/},{category:"External URLs",pattern:/https?:\/\//}],d0=new Set([".png",".jpg",".jpeg",".gif",".ico",".bmp",".webp",".mp3",".mp4",".wav",".avi",".mov",".zip",".tar",".gz",".bz2",".7z",".exe",".dll",".so",".dylib",".woff",".woff2",".ttf",".eot",".pdf",".doc",".docx"]);async function p0($){let Q=[];async function K(q,Z){let V;try{V=await l(q)}catch{return}for(let X of V){if(X===".git")continue;if(X==="node_modules")continue;let z=L(q,X),J=Z?`${Z}/${X}`:X;try{let U=await i(z);if(U.isDirectory())await K(z,J);else if(U.isFile()){let j=X.includes(".")?`.${X.split(".").pop().toLowerCase()}`:"";if(d0.has(j))continue;if(U.size>524288)continue;try{let W=await N(z,"utf-8");Q.push({relPath:J,content:W})}catch{}}}catch{continue}}}return await K($,""),Q}async function Q0($){let Q=[],K=await p0($);for(let{relPath:q,content:Z}of K){let V=Z.split(`
7
- `);for(let X=0;X<V.length;X++)for(let{category:z,pattern:J}of c0)if(J.test(V[X])){let U=V[X].trim();Q.push({category:z,file:q,line:X+1,match:U.length>100?U.slice(0,100)+"…":U})}}return Q}async function u($){let Q=`github:${$.source.owner}/${$.source.repo}${$.source.ref?`#${$.source.ref}`:""}`;if($.force)try{await h($.targetDir),await y($.targetDir,{recursive:!0,force:!0})}catch{}let K=$.sourceDir;try{await S0(K,$.targetDir,{recursive:!0})}catch(z){throw Error(`Failed to install: ${z.message}`)}let q=L($.targetDir,".git");try{await y(q,{recursive:!0,force:!0})}catch{}A(`install: copied files to ${$.targetDir}`);let Z=L($.targetDir,"SKILL.md");try{await h(Z)}catch{throw Error("Installation verification failed: SKILL.md not found at target")}let V=await N(Z,"utf-8"),X=R(V);return{success:!0,path:$.targetDir,name:X.name||$.skillName,version:X.version||"0.0.0",provider:$.providerLabel,source:Q}}async function Z0($,Q){let K=await u($);for(let q of Q){if(q.name===$.providerName)continue;let Z=v(q.global),V=L(Z,$.skillName);await P0(Z,{recursive:!0});try{if((await b0(V)).isSymbolicLink())await y(V);else{A(`install: skipping ${V} — existing non-symlink directory`);continue}}catch{}let X=f0(Z,$.targetDir);await D0(X,V,"dir"),A(`install: symlinked ${V} ${X}`)}return K.provider=`All (${Q.map((q)=>q.label).join(", ")})`,K}async function D($){try{await y($,{recursive:!0,force:!0})}catch{}}async function P($,Q,K){let q=$.providers.filter((X)=>X.enabled);if(q.length===0)throw Error("No providers are enabled. Enable a provider in your config.");if(Q==="all")return{provider:q.find((z)=>z.name==="agents")||q[0],allProviders:q};if(Q){let X=$.providers.find((z)=>z.name===Q);if(!X){let z=$.providers.map((J)=>J.name).join(", ");throw Error(`Unknown provider: "${Q}". Valid providers: ${z}, all`)}if(!X.enabled)throw Error(`Provider "${Q}" is disabled. Enable it in your config or choose another provider.`);return{provider:X,allProviders:null}}if(q.length===1)return{provider:q[0],allProviders:null};if(!K){let X=q.map((z)=>z.name).join(", ");throw Error(`--provider is required in non-interactive mode. Available: ${X}, all`)}console.error(`
8
- Select a provider:`);for(let X=0;X<q.length;X++)console.error(` ${X+1}) ${q[X].label} (${q[X].name})`);console.error(` ${q.length+1}) All providers (shared .agents/skills/ + symlinks)`),process.stderr.write(`
9
- Enter number: `);let Z=await new Promise((X)=>{let z="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",(J)=>{if(z+=J,z.includes(`
10
- `))process.stdin.removeAllListeners("data"),X(z.trim())}),process.stdin.resume()}),V=parseInt(Z,10)-1;if(V===q.length)return{provider:q.find((z)=>z.name==="agents")||q[0],allProviders:q};if(isNaN(V)||V<0||V>=q.length)throw Error("Invalid selection. Aborting.");return{provider:q[V],allProviders:null}}function K0($,Q,K,q,Z,V){let X=v(Z.global),z=L(X,q);return{source:$,tempDir:Q,sourceDir:K,targetDir:z,skillName:q,force:V,providerName:Z.name,providerLabel:Z.label}}async function q0($,Q){try{if(await h($),A(`install: target ${$} — conflict (exists)${Q?", force overwrite":""}`),!Q)throw Error(`Skill already exists at: ${$}
11
- Use --force to overwrite.`)}catch(K){if(K.message?.includes("--force"))throw K;A(`install: target ${$} — no conflict`)}}import{readFile as g0}from"fs/promises";import{join as o0}from"path";var V0=500;function n0($){let Q=$.split(`
12
- `),K=!1,q=!1;for(let Z of Q){if(Z.trim()==="---")if(!K){K=!0;continue}else{q=!0;continue}if(q&&Z.trim().length>0)return!0}return!1}async function X0($){let Q=[];if(!$.description||$.description.trim()==="")Q.push({category:"missing-description",message:"Skill has no description in SKILL.md frontmatter"});if(!$.version||$.version==="0.0.0")Q.push({category:"missing-version",message:"Skill has no version (or default 0.0.0) in SKILL.md frontmatter"});try{let q=o0($.path,"SKILL.md"),Z=await g0(q,"utf-8");if(!n0(Z))Q.push({category:"empty-body",message:"SKILL.md contains only frontmatter with no body content"})}catch{}let K=$.fileCount;if(K!==void 0&&K>V0)Q.push({category:"high-file-count",message:`Skill has ${K} files (threshold: ${V0})`});return Q}function Y0($){let Q=$.map((K)=>({name:K.name,version:K.version,dirName:K.dirName,provider:K.provider,scope:K.scope,path:K.path,isSymlink:K.isSymlink,symlinkTarget:K.symlinkTarget}));return{version:1,exportedAt:new Date().toISOString(),skills:Q}}import{mkdir as t0,writeFile as l0,access as i0}from"fs/promises";import{join as s0}from"path";function a0($){return`---
6
+ https://github.com/owner/repo`);let K=$.slice(7),q=K.indexOf("#"),Z,z=null;if(q!==-1){if(Z=K.slice(0,q),z=K.slice(q+1),!z)throw Error("Invalid source: ref cannot be empty after #")}else Z=K;let Y=Z.indexOf("/");if(Y===-1)throw Error(`Invalid source: format must be github:owner/repo. Got: "${$}"`);let U=Z.slice(0,Y),V=Z.slice(Y+1);if(!U)throw Error("Invalid source: owner cannot be empty");if(!V)throw Error("Invalid source: repo cannot be empty");if(!o0.test(U))throw Error(`Invalid source: owner contains invalid characters: "${U}". Allowed: [a-zA-Z0-9_-]`);if(!n0.test(V))throw Error(`Invalid source: repo contains invalid characters: "${V}". Allowed: [a-zA-Z0-9._-]`);let J={owner:U,repo:V,ref:z,cloneUrl:`https://github.com/${U}/${V}.git`};return H(`install: parsed source -> owner=${U} repo=${V} ref=${z}`),J}function b($){if(!$)throw Error("Invalid skill name: name cannot be empty");if($.includes("\x00"))throw Error("Invalid skill name: contains unsafe characters (null byte)");if($.includes(".."))throw Error("Invalid skill name: contains unsafe characters (..)");if($.includes("/")||$.includes("\\"))throw Error("Invalid skill name: contains unsafe characters (path separator)");if($.startsWith("."))throw Error("Invalid skill name: must not start with a dot");if($.length>s)throw Error(`Invalid skill name: exceeds maximum length of ${s} characters`);if(!t0.test($))throw Error(`Invalid skill name: "${$}" does not match allowed pattern [a-zA-Z0-9][a-zA-Z0-9._-]*`);return $}async function Q0(){try{await r("git",["--version"]),H("install: git available")}catch{throw Error("git is required for installing skills. Install git from https://git-scm.com")}}async function Z0($){H(`install: cloning ${$.cloneUrl}${$.ref?` (ref: ${$.ref})`:""}`);let Q=await h0(E(g0(),"asm-install-")),K=["clone","--depth","1"];if($.ref)K.push("--branch",$.ref);K.push($.cloneUrl,Q);try{await r("git",K,{timeout:60000})}catch(q){await f(Q);let Z=q.killed?"Clone timed out after 60 seconds":`Clone failed: ${q.stderr||q.message}`;throw Error(Z)}return Q}async function k($){let Q=E($,"SKILL.md"),K;try{K=await D(Q,"utf-8")}catch{throw Error("Not a valid skill: SKILL.md not found in repository root")}let q=N(K),Z=$.split("/").pop()||"unknown",z=q.name||Z,Y=q.version||"0.0.0";return H(`install: validated skill "${z}" v${Y}`),{name:z,version:Y,description:(q.description||"").replace(/\s*\n\s*/g," ").trim()}}async function K0($,Q=3){let K=[];async function q(Z,z,Y){let U;try{U=await e(Z)}catch{return}for(let V of U){if(V===".git"||V==="node_modules")continue;let J=E(Z,V);try{if(!(await a(J)).isDirectory())continue}catch{continue}let W=z?`${z}/${V}`:V,M=Y+1,B=E(J,"SKILL.md");try{let O=await D(B,"utf-8"),G=N(O);K.push({relPath:W,name:G.name||V,version:G.version||"0.0.0",description:(G.description||"").replace(/\s*\n\s*/g," ").trim()})}catch{if(M<Q)await q(J,W,M)}}}return await q($,"",0),K.sort((Z,z)=>Z.name.localeCompare(z.name)),K}var i0=[{category:"Shell commands",pattern:/\b(bash|sh\s+-c)\b/},{category:"Shell commands",pattern:/\bexec\(/},{category:"Shell commands",pattern:/\bchild_process\b/},{category:"Shell commands",pattern:/\bBun\.spawn\b/},{category:"Code execution",pattern:/\beval\(/},{category:"Code execution",pattern:/\bFunction\(/},{category:"Code execution",pattern:/\bnew\s+Function\b/},{category:"Credentials",pattern:/\b(API_KEY|SECRET|TOKEN|PASSWORD)\s*[=:]/},{category:"External URLs",pattern:/https?:\/\//}],s0=new Set([".png",".jpg",".jpeg",".gif",".ico",".bmp",".webp",".mp3",".mp4",".wav",".avi",".mov",".zip",".tar",".gz",".bz2",".7z",".exe",".dll",".so",".dylib",".woff",".woff2",".ttf",".eot",".pdf",".doc",".docx"]);async function e0($){let Q=[];async function K(q,Z){let z;try{z=await e(q)}catch{return}for(let Y of z){if(Y===".git")continue;if(Y==="node_modules")continue;let U=E(q,Y),V=Z?`${Z}/${Y}`:Y;try{let J=await a(U);if(J.isDirectory())await K(U,V);else if(J.isFile()){let W=Y.includes(".")?`.${Y.split(".").pop().toLowerCase()}`:"";if(s0.has(W))continue;if(J.size>524288)continue;try{let M=await D(U,"utf-8");Q.push({relPath:V,content:M})}catch{}}}catch{continue}}}return await K($,""),Q}async function q0($){let Q=[],K=await e0($);for(let{relPath:q,content:Z}of K){let z=Z.split(`
7
+ `);for(let Y=0;Y<z.length;Y++)for(let{category:U,pattern:V}of i0)if(V.test(z[Y])){let J=z[Y].trim();Q.push({category:U,file:q,line:Y+1,match:J.length>100?J.slice(0,100)+"…":J})}}return Q}async function c($){let Q=`github:${$.source.owner}/${$.source.repo}${$.source.ref?`#${$.source.ref}`:""}`;if($.force)try{await u($.targetDir),await S($.targetDir,{recursive:!0,force:!0})}catch{}let K=$.sourceDir;try{await u0(K,$.targetDir,{recursive:!0})}catch(U){throw Error(`Failed to install: ${U.message}`)}let q=E($.targetDir,".git");try{await S(q,{recursive:!0,force:!0})}catch{}H(`install: copied files to ${$.targetDir}`);let Z=E($.targetDir,"SKILL.md");try{await u(Z)}catch{throw Error("Installation verification failed: SKILL.md not found at target")}let z=await D(Z,"utf-8"),Y=N(z);return{success:!0,path:$.targetDir,name:Y.name||$.skillName,version:Y.version||"0.0.0",provider:$.providerLabel,source:Q}}async function X0($,Q){let K=await c($);for(let q of Q){if(q.name===$.providerName)continue;let Z=m(q.global),z=E(Z,$.skillName);await d0(Z,{recursive:!0});try{if((await m0(z)).isSymbolicLink())await S(z);else{H(`install: skipping ${z} — existing non-symlink directory`);continue}}catch{}let Y=p0(Z,$.targetDir);await c0(Y,z,"dir"),H(`install: symlinked ${z} -> ${Y}`)}return K.provider=`All (${Q.map((q)=>q.label).join(", ")})`,K}async function f($){try{await S($,{recursive:!0,force:!0})}catch{}}async function P($,Q,K){let q=$.providers.filter((Y)=>Y.enabled);if(q.length===0)throw Error("No providers are enabled. Enable a provider in your config.");if(Q==="all")return{provider:q.find((U)=>U.name==="agents")||q[0],allProviders:q};if(Q){let Y=$.providers.find((U)=>U.name===Q);if(!Y){let U=$.providers.map((V)=>V.name).join(", ");throw Error(`Unknown provider: "${Q}". Valid providers: ${U}, all`)}if(!Y.enabled)throw Error(`Provider "${Q}" is disabled. Enable it in your config or choose another provider.`);return{provider:Y,allProviders:null}}if(q.length===1)return{provider:q[0],allProviders:null};if(!K){let Y=q.map((U)=>U.name).join(", ");throw Error(`--provider is required in non-interactive mode. Available: ${Y}, all`)}console.error(`
8
+ Select a provider:`);for(let Y=0;Y<q.length;Y++)console.error(` ${Y+1}) ${q[Y].label} (${q[Y].name})`);console.error(` ${q.length+1}) All providers (shared .agents/skills/ + symlinks)`),process.stderr.write(`
9
+ Enter number: `);let Z=await new Promise((Y)=>{let U="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",(V)=>{if(U+=V,U.includes(`
10
+ `))process.stdin.removeAllListeners("data"),process.stdin.pause(),Y(U.trim())}),process.stdin.resume()}),z=parseInt(Z,10)-1;if(z===q.length)return{provider:q.find((U)=>U.name==="agents")||q[0],allProviders:q};if(isNaN(z)||z<0||z>=q.length)throw Error("Invalid selection. Aborting.");return{provider:q[z],allProviders:null}}function Y0($,Q,K,q,Z,z){let Y=m(Z.global),U=E(Y,q);return{source:$,tempDir:Q,sourceDir:K,targetDir:U,skillName:q,force:z,providerName:Z.name,providerLabel:Z.label}}async function z0($,Q){try{if(await u($),H(`install: target ${$} — conflict (exists)${Q?", force overwrite":""}`),!Q)throw Error(`Skill already exists at: ${$}
11
+ Use --force to overwrite.`)}catch(K){if(K.message?.includes("--force"))throw K;H(`install: target ${$} — no conflict`)}}import{readFile as a0}from"fs/promises";import{join as r0}from"path";var U0=500;function $1($){let Q=$.split(`
12
+ `),K=!1,q=!1;for(let Z of Q){if(Z.trim()==="---")if(!K){K=!0;continue}else{q=!0;continue}if(q&&Z.trim().length>0)return!0}return!1}async function V0($){let Q=[];if(!$.description||$.description.trim()==="")Q.push({category:"missing-description",message:"Skill has no description in SKILL.md frontmatter"});if(!$.version||$.version==="0.0.0")Q.push({category:"missing-version",message:"Skill has no version (or default 0.0.0) in SKILL.md frontmatter"});try{let q=r0($.path,"SKILL.md"),Z=await a0(q,"utf-8");if(!$1(Z))Q.push({category:"empty-body",message:"SKILL.md contains only frontmatter with no body content"})}catch{}let K=$.fileCount;if(K!==void 0&&K>U0)Q.push({category:"high-file-count",message:`Skill has ${K} files (threshold: ${U0})`});return Q}function J0($){let Q=$.map((K)=>({name:K.name,version:K.version,dirName:K.dirName,provider:K.provider,scope:K.scope,path:K.path,isSymlink:K.isSymlink,symlinkTarget:K.symlinkTarget}));return{version:1,exportedAt:new Date().toISOString(),skills:Q}}import{mkdir as Q1,writeFile as Z1,access as K1}from"fs/promises";import{join as q1}from"path";function X1($){return`---
13
13
  name: ${$}
14
14
  version: 0.1.0
15
15
  description: ""
@@ -27,16 +27,16 @@ as instructions for when and how to use this skill.
27
27
  ## Instructions
28
28
 
29
29
  - Step-by-step instructions for the agent
30
- `}async function z0($,Q){await t0(Q,{recursive:!0});let K=s0(Q,"SKILL.md"),q=a0($);await l0(K,q,"utf-8")}async function J0($){try{return await i0($),!0}catch{return!1}}import{readdir as e0,stat as r0}from"fs/promises";import{join as $1}from"path";async function Q1($){let Q=0;try{let q=(await e0($,{recursive:!0})).map(async(V)=>{try{let X=await r0($1($,V));if(X.isFile())return X.size}catch{}return 0});Q=(await Promise.all(q)).reduce((V,X)=>V+X,0)}catch{}return Q}async function U0($,Q){let K={},q={global:0,project:0},Z={},V=$.map(async(J)=>{K[J.provider]=(K[J.provider]||0)+1,q[J.scope]++;let U=await Q1(J.path);return Z[J.path]=U,U}),z=(await Promise.all(V)).reduce((J,U)=>J+U,0);return{totalSkills:$.length,byProvider:K,byScope:q,totalDiskBytes:z,perSkillDiskBytes:Z,duplicateGroups:Q.duplicateGroups.length,duplicateInstances:Q.totalDuplicateInstances}}function Z1($){if($<1024)return`${$} B`;if($<1048576)return`${($/1024).toFixed(1)} KB`;if($<1073741824)return`${($/1048576).toFixed(1)} MB`;return`${($/1073741824).toFixed(1)} GB`}function W0($){let Q=[],K=(q,Z)=>`${Y.bold(q+":")} ${Z}`;Q.push(Y.bold("Skill Statistics")),Q.push(""),Q.push(K("Total Skills",String($.totalSkills))),Q.push(K("Disk Usage",Z1($.totalDiskBytes))),Q.push(""),Q.push(Y.bold("By Provider:"));for(let[q,Z]of Object.entries($.byProvider).sort((V,X)=>X[1]-V[1]))Q.push(` ${q}: ${Z}`);if(Q.push(""),Q.push(Y.bold("By Scope:")),Q.push(` global: ${$.byScope.global}`),Q.push(` project: ${$.byScope.project}`),Q.push(""),Q.push(Y.bold("Duplicates:")),$.duplicateGroups>0)Q.push(` ${Y.yellow(`${$.duplicateGroups} group(s), ${$.duplicateInstances} total instance(s)`)}`);else Q.push(` ${Y.green("None")}`);return Q.join(`
31
- `)}import{access as K1,lstat as q1,readFile as V1,rm as X1,symlink as Y1}from"fs/promises";import{join as B0}from"path";async function G0($){let Q;try{Q=await q1($)}catch{throw Error(`Path does not exist: ${$}`)}if(!Q.isDirectory())throw Error(`Path is not a directory: ${$}`);let K=B0($,"SKILL.md"),q;try{q=await V1(K,"utf-8")}catch{throw Error(`No SKILL.md found in ${$}`)}let Z=R(q);if(!Z.name)throw Error(`Invalid SKILL.md in ${$}: missing "name" in frontmatter`);return{name:Z.name,version:Z.version||"0.0.0"}}async function f($,Q,K,q){let Z=B0(Q,K),V=!1;try{await K1(Z),V=!0}catch{}if(V){if(!q)throw Error(`Target already exists: ${Z}. Use --force to overwrite.`);await X1(Z,{recursive:!0,force:!0})}await Y1($,Z,"dir")}function z1($){let Q=$.slice(2),K={command:null,subcommand:null,positional:[],flags:{help:!1,version:!1,json:!1,yes:!1,noColor:!1,scope:"both",sort:"name",provider:null,name:null,force:!1,path:null,all:!1,verbose:!1}},q=0;while(q<Q.length){let Z=Q[q];if(Z==="--help"||Z==="-h")K.flags.help=!0;else if(Z==="--version"||Z==="-v")K.flags.version=!0;else if(Z==="--json")K.flags.json=!0;else if(Z==="--yes"||Z==="-y")K.flags.yes=!0;else if(Z==="--no-color")K.flags.noColor=!0;else if(Z==="--scope"||Z==="-s"){q++;let V=Q[q];if(V==="global"||V==="project"||V==="both")K.flags.scope=V;else M(`Invalid scope: "${V}". Must be global, project, or both.`),process.exit(2)}else if(Z==="--sort"){q++;let V=Q[q];if(V==="name"||V==="version"||V==="location")K.flags.sort=V;else M(`Invalid sort: "${V}". Must be name, version, or location.`),process.exit(2)}else if(Z==="--provider"||Z==="-p")q++,K.flags.provider=Q[q]||null;else if(Z==="--name")q++,K.flags.name=Q[q]||null;else if(Z==="--force"||Z==="-f")K.flags.force=!0;else if(Z==="--path")q++,K.flags.path=Q[q]||null;else if(Z==="--all")K.flags.all=!0;else if(Z==="--verbose"||Z==="-V")K.flags.verbose=!0;else if(Z.startsWith("-"))M(`Unknown option: ${Z}`),console.error('Run "asm --help" for usage.'),process.exit(2);else if(!K.command)K.command=Z;else if(!K.subcommand)K.subcommand=Z;else K.positional.push(Z);q++}return K}function M($){console.error(Y.red(`Error: ${$}`))}function J1(){console.log(`${Y.blueBold("agent-skill-manager")} (${Y.bold("asm")}) ${n}
30
+ `}async function G0($,Q){await Q1(Q,{recursive:!0});let K=q1(Q,"SKILL.md"),q=X1($);await Z1(K,q,"utf-8")}async function M0($){try{return await K1($),!0}catch{return!1}}import{readdir as Y1,stat as z1}from"fs/promises";import{join as U1}from"path";async function V1($){let Q=0;try{let q=(await Y1($,{recursive:!0})).map(async(z)=>{try{let Y=await z1(U1($,z));if(Y.isFile())return Y.size}catch{}return 0});Q=(await Promise.all(q)).reduce((z,Y)=>z+Y,0)}catch{}return Q}async function j0($,Q){let K={},q={global:0,project:0},Z={},z=$.map(async(V)=>{K[V.provider]=(K[V.provider]||0)+1,q[V.scope]++;let J=await V1(V.path);return Z[V.path]=J,J}),U=(await Promise.all(z)).reduce((V,J)=>V+J,0);return{totalSkills:$.length,byProvider:K,byScope:q,totalDiskBytes:U,perSkillDiskBytes:Z,duplicateGroups:Q.duplicateGroups.length,duplicateInstances:Q.totalDuplicateInstances}}function J1($){if($<1024)return`${$} B`;if($<1048576)return`${($/1024).toFixed(1)} KB`;if($<1073741824)return`${($/1048576).toFixed(1)} MB`;return`${($/1073741824).toFixed(1)} GB`}function d($,Q,K=20){let q=Math.round($/Q*K),Z=K-q;return X.green("█".repeat(q))+X.dim("".repeat(Z))}var B0={claude:"Claude Code",codex:"Codex",openclaw:"OpenClaw",agents:"Agents"};function F0($){let Q=[];Q.push(""),Q.push(X.blueBold(" Skill Statistics")),Q.push(X.dim(" "+"-".repeat(20))),Q.push(""),Q.push(` ${X.bold("Total:")} ${X.cyan(String($.totalSkills))} skills`),Q.push(` ${X.bold("Disk:")} ${X.cyan(J1($.totalDiskBytes))}`),Q.push(""),Q.push(X.bold(" By Provider"));let K=Object.entries($.byProvider).sort((V,J)=>J[1]-V[1]),q=Math.max(...K.map(([,V])=>V)),Z=Math.max(...K.map(([V])=>(B0[V]||V).length));for(let[V,J]of K){let W=B0[V]||V,M=W0(V,W.padEnd(Z)),B=String(J).padStart(4);Q.push(` ${M} ${B} ${d(J,q)}`)}Q.push(""),Q.push(X.bold(" By Scope"));let z=Math.max($.byScope.global,$.byScope.project),Y=String($.byScope.global).padStart(4),U=String($.byScope.project).padStart(4);if(Q.push(` ${"global ".padEnd(Z)} ${Y} ${d($.byScope.global,z)}`),Q.push(` ${"project".padEnd(Z)} ${U} ${d($.byScope.project,z)}`),Q.push(""),Q.push(X.bold(" Duplicates")),$.duplicateGroups>0)Q.push(` ${X.yellow(`${$.duplicateGroups} group(s), ${$.duplicateInstances} total instance(s)`)}`),Q.push(X.dim(` Run ${X.bold("asm audit")} to review`));else Q.push(` ${X.green("None")}`);return Q.push(""),Q.join(`
31
+ `)}import{access as G1,lstat as M1,readFile as B1,rm as W1,symlink as j1}from"fs/promises";import{join as O0}from"path";async function _0($){let Q;try{Q=await M1($)}catch{throw Error(`Path does not exist: ${$}`)}if(!Q.isDirectory())throw Error(`Path is not a directory: ${$}`);let K=O0($,"SKILL.md"),q;try{q=await B1(K,"utf-8")}catch{throw Error(`No SKILL.md found in ${$}`)}let Z=N(q);if(!Z.name)throw Error(`Invalid SKILL.md in ${$}: missing "name" in frontmatter`);return{name:Z.name,version:Z.version||"0.0.0"}}async function v($,Q,K,q){let Z=O0(Q,K),z=!1;try{await G1(Z),z=!0}catch{}if(z){if(!q)throw Error(`Target already exists: ${Z}. Use --force to overwrite.`);await W1(Z,{recursive:!0,force:!0})}await j1($,Z,"dir")}function F1($){let Q=$.slice(2),K={command:null,subcommand:null,positional:[],flags:{help:!1,version:!1,json:!1,yes:!1,noColor:!1,scope:"both",sort:"name",provider:null,name:null,force:!1,path:null,all:!1,verbose:!1,flat:!1}},q=0;while(q<Q.length){let Z=Q[q];if(Z==="--help"||Z==="-h")K.flags.help=!0;else if(Z==="--version"||Z==="-v")K.flags.version=!0;else if(Z==="--json")K.flags.json=!0;else if(Z==="--yes"||Z==="-y")K.flags.yes=!0;else if(Z==="--no-color")K.flags.noColor=!0;else if(Z==="--scope"||Z==="-s"){q++;let z=Q[q];if(z==="global"||z==="project"||z==="both")K.flags.scope=z;else j(`Invalid scope: "${z}". Must be global, project, or both.`),process.exit(2)}else if(Z==="--sort"){q++;let z=Q[q];if(z==="name"||z==="version"||z==="location")K.flags.sort=z;else j(`Invalid sort: "${z}". Must be name, version, or location.`),process.exit(2)}else if(Z==="--provider"||Z==="-p")q++,K.flags.provider=Q[q]||null;else if(Z==="--name")q++,K.flags.name=Q[q]||null;else if(Z==="--force"||Z==="-f")K.flags.force=!0;else if(Z==="--path")q++,K.flags.path=Q[q]||null;else if(Z==="--all")K.flags.all=!0;else if(Z==="--verbose"||Z==="-V")K.flags.verbose=!0;else if(Z==="--flat")K.flags.flat=!0;else if(Z.startsWith("-"))j(`Unknown option: ${Z}`),console.error('Run "asm --help" for usage.'),process.exit(2);else if(!K.command)K.command=Z;else if(!K.subcommand)K.subcommand=Z;else K.positional.push(Z);q++}return K}function j($){console.error(X.red(`Error: ${$}`))}function O1(){console.log(`${X.blueBold("agent-skill-manager")} (${X.bold("asm")}) ${i}
32
32
 
33
33
  Interactive TUI and CLI for managing installed skills for AI coding agents.
34
34
 
35
- ${Y.bold("Usage:")}
35
+ ${X.bold("Usage:")}
36
36
  asm Launch interactive TUI
37
37
  asm <command> [options] Run a CLI command
38
38
 
39
- ${Y.bold("Commands:")}
39
+ ${X.bold("Commands:")}
40
40
  list List all discovered skills
41
41
  search <query> Search skills by name/description/provider
42
42
  inspect <skill-name> Show detailed info for a skill
@@ -52,88 +52,131 @@ ${Y.bold("Commands:")}
52
52
  config reset Reset config to defaults
53
53
  config edit Open config in $EDITOR
54
54
 
55
- ${Y.bold("Global Options:")}
55
+ ${X.bold("Global Options:")}
56
56
  -h, --help Show help for any command
57
57
  -v, --version Print version and exit
58
58
  --json Output as JSON (list, search, inspect)
59
59
  -s, --scope <scope> Filter: global, project, or both (default: both)
60
+ -p, --provider <name> Filter by provider (list, search)
60
61
  --no-color Disable ANSI colors
61
62
  --sort <field> Sort by: name, version, or location (default: name)
63
+ --flat Show one row per provider instance (list, search)
62
64
  -y, --yes Skip confirmation prompts
63
- -V, --verbose Show debug output`)}function U1(){console.log(`${Y.bold("Usage:")} asm list [options]
64
-
65
- List all discovered skills.
66
-
67
- ${Y.bold("Options:")}
68
- --sort <field> Sort by: name, version, or location (default: name)
69
- -s, --scope <s> Filter: global, project, or both (default: both)
70
- --json Output as JSON array
71
- --no-color Disable ANSI colors
72
- -V, --verbose Show debug output`)}function W1(){console.log(`${Y.bold("Usage:")} asm search <query> [options]
73
-
74
- Search skills by name, description, or provider.
75
-
76
- ${Y.bold("Options:")}
77
- --sort <field> Sort by: name, version, or location (default: name)
78
- -s, --scope <s> Filter: global, project, or both (default: both)
79
- --json Output as JSON array
80
- --no-color Disable ANSI colors
81
- -V, --verbose Show debug output`)}function B1(){console.log(`${Y.bold("Usage:")} asm inspect <skill-name> [options]
65
+ -V, --verbose Show debug output`)}function _1(){console.log(`${X.bold("Usage:")} asm list [options]
66
+
67
+ List all discovered skills. By default, skills installed across multiple
68
+ providers are grouped into a single row with provider badges.
69
+
70
+ ${X.bold("Options:")}
71
+ --sort <field> Sort by: name, version, or location (default: name)
72
+ -s, --scope <s> Filter: global, project, or both (default: both)
73
+ -p, --provider <p> Filter by provider (claude, codex, openclaw, agents)
74
+ --flat Show one row per provider instance (ungrouped)
75
+ --json Output as JSON array
76
+ --no-color Disable ANSI colors
77
+ -V, --verbose Show debug output
78
+
79
+ ${X.bold("Examples:")}
80
+ asm list ${X.dim("List all skills (grouped)")}
81
+ asm list --flat ${X.dim("One row per provider instance")}
82
+ asm list -p claude ${X.dim("Only Claude Code skills")}
83
+ asm list -s project ${X.dim("Only project-scoped skills")}
84
+ asm list --sort version ${X.dim("Sort by version")}
85
+ asm list --json ${X.dim("Output as JSON")}`)}function A1(){console.log(`${X.bold("Usage:")} asm search <query> [options]
86
+
87
+ Search skills by name, description, or provider. Matching terms are
88
+ highlighted in the output.
89
+
90
+ ${X.bold("Options:")}
91
+ --sort <field> Sort by: name, version, or location (default: name)
92
+ -s, --scope <s> Filter: global, project, or both (default: both)
93
+ -p, --provider <p> Filter by provider (claude, codex, openclaw, agents)
94
+ --flat Show one row per provider instance (ungrouped)
95
+ --json Output as JSON array
96
+ --no-color Disable ANSI colors
97
+ -V, --verbose Show debug output
98
+
99
+ ${X.bold("Examples:")}
100
+ asm search code ${X.dim("Search for 'code' in all fields")}
101
+ asm search review -p claude ${X.dim("Search within Claude Code only")}
102
+ asm search "test" -s global ${X.dim("Search global skills only")}
103
+ asm search openspec --json ${X.dim("Output matches as JSON")}`)}function H1(){console.log(`${X.bold("Usage:")} asm inspect <skill-name> [options]
82
104
 
83
105
  Show detailed information for a skill. The <skill-name> is the directory name.
106
+ Shows version, description, file count, and all provider installations.
84
107
 
85
- ${Y.bold("Options:")}
108
+ ${X.bold("Options:")}
86
109
  -s, --scope <s> Filter: global, project, or both (default: both)
87
110
  --json Output as JSON object
88
111
  --no-color Disable ANSI colors
89
- -V, --verbose Show debug output`)}function G1(){console.log(`${Y.bold("Usage:")} asm uninstall <skill-name> [options]
112
+ -V, --verbose Show debug output
113
+
114
+ ${X.bold("Examples:")}
115
+ asm inspect code-review ${X.dim("Show details for code-review")}
116
+ asm inspect code-review --json ${X.dim("Output as JSON")}
117
+ asm inspect code-review -s global ${X.dim("Global installations only")}`)}function T1(){console.log(`${X.bold("Usage:")} asm uninstall <skill-name> [options]
90
118
 
91
- Remove a skill and its associated rule files.
119
+ Remove a skill and its associated rule files. Shows a removal plan
120
+ before proceeding and asks for confirmation.
92
121
 
93
- ${Y.bold("Options:")}
122
+ ${X.bold("Options:")}
94
123
  -y, --yes Skip confirmation prompt
95
124
  -s, --scope <s> Filter: global, project, or both (default: both)
96
125
  --no-color Disable ANSI colors
97
- -V, --verbose Show debug output`)}function M1(){console.log(`${Y.bold("Usage:")} asm audit [subcommand] [options]
126
+ -V, --verbose Show debug output
98
127
 
99
- Detect and optionally remove duplicate skills.
128
+ ${X.bold("Examples:")}
129
+ asm uninstall code-review ${X.dim("Remove with confirmation")}
130
+ asm uninstall code-review -y ${X.dim("Remove without confirmation")}
131
+ asm uninstall code-review -s project ${X.dim("Remove project copy only")}`)}function L1(){console.log(`${X.bold("Usage:")} asm audit [subcommand] [options]
100
132
 
101
- ${Y.bold("Subcommands:")}
133
+ Detect and optionally remove duplicate skills. Duplicate detection
134
+ considers both directory names and SKILL.md frontmatter names.
135
+
136
+ ${X.bold("Subcommands:")}
102
137
  duplicates Find duplicate skills (default)
103
138
 
104
- ${Y.bold("Options:")}
139
+ ${X.bold("Options:")}
105
140
  --json Output as JSON
106
141
  -y, --yes Auto-remove duplicates, keeping one instance per group
107
142
  --no-color Disable ANSI colors
108
- -V, --verbose Show debug output`)}function j1(){console.log(`${Y.bold("Usage:")} asm config <subcommand>
143
+ -V, --verbose Show debug output
144
+
145
+ ${X.bold("Examples:")}
146
+ asm audit ${X.dim("Find duplicates")}
147
+ asm audit -y ${X.dim("Auto-remove duplicates")}
148
+ asm audit --json ${X.dim("Output as JSON")}`)}function E1(){console.log(`${X.bold("Usage:")} asm config <subcommand>
109
149
 
110
- Manage configuration.
150
+ Manage configuration. Config is stored at ~/.config/agent-skill-manager/.
111
151
 
112
- ${Y.bold("Subcommands:")}
152
+ ${X.bold("Subcommands:")}
113
153
  show Print current config as JSON
114
154
  path Print config file path
115
155
  reset Reset config to defaults (with confirmation)
116
156
  edit Open config in $EDITOR
117
157
 
118
- ${Y.bold("Options:")}
119
- -V, --verbose Show debug output`)}async function C0($){for(let Q of $)Q.warnings=await X0(Q)}async function O1($){if($.flags.help){U1();return}let Q=await F(),K=await I(Q,$.flags.scope);await C0(K);let q=d(K,$.flags.sort);if($.flags.json)console.log(x(q));else{let Z=g(q),V=q.filter((X)=>X.warnings&&X.warnings.length>0);if(V.length>0)Z+=`
120
- ${Y.yellow(`⚠ ${V.length} skill${V.length===1?"":"s"} with warnings — use --json for details`)}`;console.log(Z)}}async function _1($){if($.flags.help){W1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <query>"),console.error('Run "asm search --help" for usage.'),process.exit(2);let K=await F(),q=await I(K,$.flags.scope),Z=_0(q,Q),V=d(Z,$.flags.sort);if($.flags.json)console.log(x(V));else console.log(g(V))}async function F1($){if($.flags.help){B1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <skill-name>"),console.error('Run "asm inspect --help" for usage.'),process.exit(2);let K=await F(),Z=(await I(K,$.flags.scope)).filter((V)=>V.dirName===Q);if(Z.length===0)M(`Skill "${Q}" not found.`),process.exit(1);if(await C0(Z),$.flags.json)console.log(x(Z.length===1?Z[0]:Z));else for(let V=0;V<Z.length;V++){if(V>0)console.log(`
121
- `+"".repeat(40)+`
122
- `);console.log(await T0(Z[V]))}}async function A1($){if($.flags.help){G1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <skill-name>"),console.error('Run "asm uninstall --help" for usage.'),process.exit(2);let K=await F(),q=await I(K,$.flags.scope),Z=A0(Q,q,K),V=await E0(Z);if(V.length===0)M(`Skill "${Q}" not found or nothing to remove.`),process.exit(1);console.error(Y.bold("Removal plan:"));for(let z of V)console.error(` ${Y.red("•")} ${z}`);if(!$.flags.yes){if(!process.stdin.isTTY)M("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
123
- ${Y.bold("Proceed with removal?")} [y/N] `);let z=await C();if(z.toLowerCase()!=="y"&&z.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}let X=await p(Z);for(let z of X)console.error(z);console.error(Y.green(`
124
- Done.`))}function C(){return new Promise(($)=>{let Q="",K=!1;function q(){process.stdin.removeListener("data",V),process.stdin.removeListener("end",X),clearTimeout(z)}function Z(J){if(K)return;K=!0,q(),$(J)}function V(J){if(Q+=J,Q.includes(`
125
- `))Z(Q.trim())}function X(){Z(Q.trim())}let z=setTimeout(()=>{Z(Q.trim())},30000);process.stdin.setEncoding("utf-8"),process.stdin.on("data",V),process.stdin.on("end",X),process.stdin.resume()})}async function E1($){if($.flags.help){M1();return}let Q=$.subcommand??"duplicates";if(Q!=="duplicates")M(`Unknown audit subcommand: "${Q}". Use: duplicates`),process.exit(2);let K=await F(),q=await I(K,"both"),Z=o(q);if($.flags.json){console.log(I0(Z));return}if(console.log(H0(Z)),$.flags.yes&&Z.duplicateGroups.length>0){console.error(Y.bold(`
126
- Auto-removing duplicates...`));for(let V of Z.duplicateGroups){let X=L0(V.instances);for(let z=1;z<X.length;z++){let J=X[z],U=F0(J,K),j=await p(U);for(let W of j)console.error(W)}}console.error(Y.green(`
127
- Done.`))}}async function T1($){if($.flags.help){j1();return}let Q=$.subcommand;if(!Q)M("Missing subcommand. Use: show, path, reset, or edit."),console.error('Run "asm config --help" for usage.'),process.exit(2);switch(Q){case"show":{let K=await F();console.log(x(K));break}case"path":{console.log(c());break}case"reset":{if(!$.flags.yes){if(!process.stdin.isTTY)M("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`${Y.bold("Reset config to defaults?")} [y/N] `);let q=await C();if(q.toLowerCase()!=="y"&&q.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}let K=j0();await O0(K),console.error(Y.green("Config reset to defaults."));break}case"edit":{let K=process.env.VISUAL||process.env.EDITOR||"vi",q=c();await F();let{spawn:Z}=await import("child_process");await new Promise((V,X)=>{let z=Z(K,[q],{stdio:"inherit"});z.on("close",()=>V()),z.on("error",X)});break}default:M(`Unknown config subcommand: "${Q}". Use: show, path, reset, or edit.`),process.exit(2)}}function L1(){console.log(`${Y.bold("Usage:")} asm install <source> [options]
158
+ ${X.bold("Options:")}
159
+ -V, --verbose Show debug output
160
+
161
+ ${X.bold("Examples:")}
162
+ asm config show ${X.dim("View current config")}
163
+ asm config edit ${X.dim("Edit in $EDITOR")}
164
+ asm config reset -y ${X.dim("Reset without confirmation")}`)}async function b0($){for(let Q of $)Q.warnings=await V0(Q)}async function I1($){if($.flags.help){_1();return}let Q=await _(),K=await w(Q,$.flags.scope);if($.flags.provider&&$.command==="list")K=K.filter((Z)=>Z.provider===$.flags.provider);await b0(K);let q=o(K,$.flags.sort);if($.flags.json)console.log(R(q));else if($.flags.flat){let Z=t(q),z=q.filter((Y)=>Y.warnings&&Y.warnings.length>0);if(z.length>0)Z+=`
165
+ ${X.yellow(`${z.length} skill${z.length===1?"":"s"} with warnings -- use --json for details`)}`;console.log(Z)}else console.log(w0(q))}async function C1($){if($.flags.help){A1();return}let Q=$.subcommand;if(!Q)j("Missing required argument: <query>"),console.error('Run "asm search --help" for usage.'),process.exit(2);let K=await _(),q=await w(K,$.flags.scope);if($.flags.provider)q=q.filter((Y)=>Y.provider===$.flags.provider);let Z=L0(q,Q),z=o(Z,$.flags.sort);if($.flags.json)console.log(R(z));else if($.flags.flat)console.log(t(z));else console.log(y0(z,Q))}async function R1($){if($.flags.help){H1();return}let Q=$.subcommand;if(!Q)j("Missing required argument: <skill-name>"),console.error('Run "asm inspect --help" for usage.'),process.exit(2);let K=await _(),Z=(await w(K,$.flags.scope)).filter((z)=>z.dirName===Q);if(Z.length===0)j(`Skill "${Q}" not found.`),console.error(X.dim(`Try ${X.bold("asm list")} to see all skills or ${X.bold(`asm search "${Q}"`)} to search.`)),process.exit(1);if(await b0(Z),$.flags.json)console.log(R(Z.length===1?Z[0]:Z));else console.log(await x0(Z))}async function w1($){if($.flags.help){T1();return}let Q=$.subcommand;if(!Q)j("Missing required argument: <skill-name>"),console.error('Run "asm uninstall --help" for usage.'),process.exit(2);let K=await _(),q=await w(K,$.flags.scope),Z=I0(Q,q,K),z=await C0(Z);if(z.length===0)j(`Skill "${Q}" not found or nothing to remove.`),process.exit(1);console.error(X.bold("Removal plan:"));for(let U of z)console.error(` ${X.red("•")} ${R0(U)}`);if(!$.flags.yes){if(!process.stdin.isTTY)j("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
166
+ ${X.bold("Proceed with removal?")} [y/N] `);let U=await x();if(U.toLowerCase()!=="y"&&U.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}let Y=await n(Z);for(let U of Y)console.error(U);console.error(X.green(`
167
+ Done.`))}function x(){return new Promise(($)=>{let Q="",K=!1;function q(){process.stdin.removeListener("data",z),process.stdin.removeListener("end",Y),process.stdin.pause(),clearTimeout(U)}function Z(V){if(K)return;K=!0,q(),$(V)}function z(V){if(Q+=V,Q.includes(`
168
+ `))Z(Q.trim())}function Y(){Z(Q.trim())}let U=setTimeout(()=>{Z(Q.trim())},30000);process.stdin.setEncoding("utf-8"),process.stdin.on("data",z),process.stdin.on("end",Y),process.stdin.resume()})}async function y1($){if($.flags.help){L1();return}let Q=$.subcommand??"duplicates";if(Q!=="duplicates")j(`Unknown audit subcommand: "${Q}". Use: duplicates`),process.exit(2);let K=await _(),q=await w(K,"both"),Z=l(q);if($.flags.json){console.log(D0(Z));return}if(console.log(S0(Z)),$.flags.yes&&Z.duplicateGroups.length>0){console.error(X.bold(`
169
+ Auto-removing duplicates...`));for(let z of Z.duplicateGroups){let Y=N0(z.instances);for(let U=1;U<Y.length;U++){let V=Y[U],J=E0(V,K),W=await n(J);for(let M of W)console.error(M)}}console.error(X.green(`
170
+ Done.`))}}async function x1($){if($.flags.help){E1();return}let Q=$.subcommand;if(!Q)j("Missing subcommand. Use: show, path, reset, or edit."),console.error('Run "asm config --help" for usage.'),process.exit(2);switch(Q){case"show":{let K=await _();console.log(R(K));break}case"path":{console.log(g());break}case"reset":{if(!$.flags.yes){if(!process.stdin.isTTY)j("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`${X.bold("Reset config to defaults?")} [y/N] `);let q=await x();if(q.toLowerCase()!=="y"&&q.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}let K=H0();await T0(K),console.error(X.green("Config reset to defaults."));break}case"edit":{let K=process.env.VISUAL||process.env.EDITOR||"vi",q=g();await _();let{spawn:Z}=await import("child_process");await new Promise((z,Y)=>{let U=Z(K,[q],{stdio:"inherit"});U.on("close",()=>z()),U.on("error",Y)});break}default:j(`Unknown config subcommand: "${Q}". Use: show, path, reset, or edit.`),process.exit(2)}}function N1(){console.log(`${X.bold("Usage:")} asm install <source> [options]
128
171
 
129
172
  Install a skill from a GitHub repository.
130
173
 
131
- ${Y.bold("Source Format:")}
174
+ ${X.bold("Source Format:")}
132
175
  github:owner/repo Install from default branch
133
176
  github:owner/repo#ref Install from specific branch or tag
134
177
  https://github.com/owner/repo Install via HTTPS URL
135
178
 
136
- ${Y.bold("Options:")}
179
+ ${X.bold("Options:")}
137
180
  -p, --provider <name> Target provider (claude, codex, openclaw, agents, all)
138
181
  Use "all" to install to all providers (shared + symlinks)
139
182
  --name <name> Override skill directory name
@@ -145,66 +188,91 @@ ${Y.bold("Options:")}
145
188
  --no-color Disable ANSI colors
146
189
  -V, --verbose Show debug output
147
190
 
148
- ${Y.bold("Single-skill repo:")}
191
+ ${X.bold("Single-skill repo:")}
149
192
  asm install github:user/my-skill
150
193
  asm install github:user/my-skill#v1.0.0 -p claude
151
194
  asm install https://github.com/user/my-skill
152
- asm install github:user/my-skill -p all ${Y.dim("(install to all providers)")}
195
+ asm install github:user/my-skill -p all ${X.dim("(install to all providers)")}
153
196
 
154
- ${Y.bold("Multi-skill repo:")}
197
+ ${X.bold("Multi-skill repo:")}
155
198
  asm install github:user/skills --path skills/code-review
156
199
  asm install github:user/skills --all -p claude -y
157
- asm install github:user/skills --all -p all -y ${Y.dim("(all skills, all providers)")}
200
+ asm install github:user/skills --all -p all -y ${X.dim("(all skills, all providers)")}
158
201
  asm install https://github.com/user/skills --all
159
- asm install github:user/skills ${Y.dim("(interactive picker)")}`)}async function m($,Q,K,q,Z,V,X,z,J){let U=await b(Z);console.error(`Found skill: ${U.name} v${U.version}`);let j=await Q0(Z),W=Z===q?null:Z.split("/").pop(),O=V||W||K.repo,B=S(O),G=K0(K,q,Z,B,z,$.flags.force);if(await q0(G.targetDir,G.force),console.error(`
160
- ${Y.bold("Install preview:")}`),console.error(` Name: ${U.name}`),console.error(` Version: ${U.version}`),console.error(` Description: ${U.description||"(none)"}`),console.error(` Source: ${Q}`),J)console.error(` Provider: All (${J.map((_)=>_.label).join(", ")})`),console.error(` Primary: ${z.label} (${z.name})`),console.error(` Symlinks: ${J.filter((_)=>_.name!==z.name).map((_)=>_.label).join(", ")}`);else console.error(` Provider: ${z.label} (${z.name})`);if(console.error(` Target: ${G.targetDir}`),j.length>0){console.error(`
161
- ${Y.yellow(Y.bold("Security warnings:"))}`);let _=new Map;for(let w of j){let H=_.get(w.category)||[];H.push(w),_.set(w.category,H)}for(let[w,H]of _){console.error(`
162
- ${Y.yellow(`[${w}]`)} (${H.length} match${H.length>1?"es":""})`);for(let k of H.slice(0,5))console.error(` ${Y.dim(k.file)}:${k.line} ${k.match}`);if(H.length>5)console.error(` ... and ${H.length-5} more`)}}if(!$.flags.yes&&!$.flags.all){if(!process.stdin.isTTY)M("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
163
- ${Y.bold("Proceed with installation?")} [y/N] `);let _=await C();if(_.toLowerCase()!=="y"&&_.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}if(console.error(`
164
- Installing to ${G.targetDir}...`),J)return await Z0(G,J);return await u(G)}async function H1($){if($.flags.help){L1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <source>"),console.error('Run "asm install --help" for usage.'),process.exit(2);let K=null,q=()=>{if(K)D(K).finally(()=>process.exit(1));else process.exit(1)};process.on("SIGINT",q),process.on("SIGTERM",q);try{let Z=a(Q);console.error(`Parsing source: ${Q}`),await e(),console.error(`Cloning ${Z.cloneUrl}${Z.ref?` (ref: ${Z.ref})`:""}...`),K=await r(Z);let V=await F(),{provider:X,allProviders:z}=await P(V,$.flags.provider,!!process.stdin.isTTY),{join:J}=await import("path"),U=[];if($.flags.path){let j=J(K,$.flags.path);try{await b(j)}catch{throw Error(`No SKILL.md found at path "${$.flags.path}" in the repository.`)}let W=await m($,Q,Z,K,j,$.flags.name,V,X,z);U.push(W)}else{let j=!1;try{await b(K),j=!0}catch{}if(j){let W=await m($,Q,Z,K,K,$.flags.name,V,X,z);U.push(W)}else{console.error("No SKILL.md at repository root. Scanning for skills...");let W=await $0(K);if(W.length===0)throw Error("No skills found in this repository. Skills must have a SKILL.md file.");console.error(`Found ${W.length} skill(s):
165
- `);for(let B=0;B<W.length;B++)if(console.error(` ${Y.bold(`${B+1})`)} ${W[B].name} v${W[B].version} ${Y.dim(`(${W[B].relPath})`)}`),W[B].description)console.error(` ${W[B].description}`);let O;if($.flags.all){if(O=W.map((B)=>B.relPath),console.error(`
166
- Installing all ${O.length} skills...`),!$.flags.yes){if(!process.stdin.isTTY)M("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
167
- ${Y.bold(`Install all ${O.length} skills?`)} [y/N] `);let B=await C();if(B.toLowerCase()!=="y"&&B.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}else if(process.stdin.isTTY){process.stderr.write(`
168
- Enter skill number (or "all"): `);let B=await C();if(B.toLowerCase()==="all")O=W.map((G)=>G.relPath);else{let G=parseInt(B,10)-1;if(isNaN(G)||G<0||G>=W.length)throw Error("Invalid selection. Aborting.");O=[W[G].relPath]}}else M(`Repository contains ${W.length} skills. Use --path <subdir> to pick one or --all to install all.
202
+ asm install github:user/skills ${X.dim("(interactive picker)")}`)}async function p($,Q,K,q,Z,z,Y,U,V,J){let W=await k(Z),M=J!==void 0,B=await q0(Z),O=Z===q?null:Z.split("/").pop(),G=z||O||K.repo,A=b(G),I=Y0(K,q,Z,A,U,$.flags.force);if(await z0(I.targetDir,I.force),M){let F=`[${J.index}/${J.total}]`,y=B.length>0?` ${X.yellow(`(${B.length} warning${B.length>1?"s":""})`)}`:"";console.error(`${X.dim(F)} ${X.bold(W.name)} v${W.version}${y}`)}else{if(console.error(`Found skill: ${W.name} v${W.version}`),console.error(`
203
+ ${X.bold("Install preview:")}`),console.error(` Name: ${W.name}`),console.error(` Version: ${W.version}`),W.description)console.error(` Description: ${W.description}`);if(console.error(` Source: ${Q}`),V)console.error(` Provider: All (${V.map((F)=>F.label).join(", ")})`),console.error(` Primary: ${U.label} (${U.name})`),console.error(` Symlinks: ${V.filter((F)=>F.name!==U.name).map((F)=>F.label).join(", ")}`);else console.error(` Provider: ${U.label} (${U.name})`);if(console.error(` Target: ${I.targetDir}`),B.length>0){console.error(`
204
+ ${X.yellow(X.bold("Security warnings:"))}`);let F=new Map;for(let y of B){let C=F.get(y.category)||[];C.push(y),F.set(y.category,C)}for(let[y,C]of F){console.error(`
205
+ ${X.yellow(`[${y}]`)} (${C.length} match${C.length>1?"es":""})`);for(let h of C.slice(0,5))console.error(` ${X.dim(h.file)}:${h.line} -- ${h.match}`);if(C.length>5)console.error(` ... and ${C.length-5} more`)}}if(!$.flags.yes&&!$.flags.all){if(!process.stdin.isTTY)j("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
206
+ ${X.bold("Proceed with installation?")} [y/N] `);let F=await x();if(F.toLowerCase()!=="y"&&F.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}if(!M)console.error(`
207
+ Installing to ${I.targetDir}...`);if(V)return await X0(I,V);return await c(I)}async function S1($){if($.flags.help){N1();return}let Q=$.subcommand;if(!Q)j("Missing required argument: <source>"),console.error('Run "asm install --help" for usage.'),process.exit(2);let K=null,q=()=>{if(K)f(K).finally(()=>process.exit(1));else process.exit(1)};process.on("SIGINT",q),process.on("SIGTERM",q);try{let Z=$0(Q);console.error(`Parsing source: ${Q}`),await Q0(),console.error(`Cloning ${Z.cloneUrl}${Z.ref?` (ref: ${Z.ref})`:""}...`),K=await Z0(Z);let z=await _(),{provider:Y,allProviders:U}=await P(z,$.flags.provider,!!process.stdin.isTTY),{join:V}=await import("path"),J=[];if($.flags.path){let W=V(K,$.flags.path);try{await k(W)}catch{throw Error(`No SKILL.md found at path "${$.flags.path}" in the repository.`)}let M=await p($,Q,Z,K,W,$.flags.name,z,Y,U);J.push(M)}else{let W=!1;try{await k(K),W=!0}catch{}if(W){let M=await p($,Q,Z,K,K,$.flags.name,z,Y,U);J.push(M)}else{console.error("No SKILL.md at repository root. Scanning for skills...");let M=await K0(K);if(M.length===0)throw Error("No skills found in this repository. Skills must have a SKILL.md file.");console.error(`Found ${M.length} skill(s):
208
+ `);for(let G=0;G<M.length;G++)if(console.error(` ${X.bold(`${G+1})`)} ${M[G].name} v${M[G].version} ${X.dim(`(${M[G].relPath})`)}`),M[G].description)console.error(` ${M[G].description}`);let B;if($.flags.all){if(B=M.map((G)=>G.relPath),console.error(`
209
+ Installing all ${B.length} skills...`),!$.flags.yes){if(!process.stdin.isTTY)j("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
210
+ ${X.bold(`Install all ${B.length} skills?`)} [y/N] `);let G=await x();if(G.toLowerCase()!=="y"&&G.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}else if(process.stdin.isTTY){process.stderr.write(`
211
+ Enter skill number (or "all"): `);let G=await x();if(G.toLowerCase()==="all")B=M.map((A)=>A.relPath);else{let A=parseInt(G,10)-1;if(isNaN(A)||A<0||A>=M.length)throw Error("Invalid selection. Aborting.");B=[M[A].relPath]}}else j(`Repository contains ${M.length} skills. Use --path <subdir> to pick one or --all to install all.
169
212
  Available skills:
170
- ${W.map((B)=>` --path ${B.relPath}`).join(`
171
- `)}`),process.exit(2);for(let B of O){let G=J(K,B);console.error(`
172
- ${"".repeat(40)}`);try{let _=await m($,Q,Z,K,G,O.length===1?$.flags.name:null,V,X,z);U.push(_),console.error(Y.green(`✓ Installed "${_.name}" to ${_.path}`))}catch(_){if(console.error(Y.red(`✗ Failed to install from ${B}: ${_.message}`)),O.length===1)throw _}}}}if(process.removeListener("SIGINT",q),process.removeListener("SIGTERM",q),$.flags.json)console.log(JSON.stringify(U.length===1?U[0]:U,null,2));else if(U.length===1)console.error(Y.green(`
173
- ✓ Installed "${U[0].name}" to ${U[0].path}`));else console.error(`
174
- ${Y.green(`✓ Installed ${U.length} skill(s) successfully.`)}`)}catch(Z){if(process.removeListener("SIGINT",q),process.removeListener("SIGTERM",q),$.flags.json)console.log(JSON.stringify({success:!1,error:Z.message},null,2));else M(Z.message);process.exit(1)}finally{if(K)await D(K)}}function I1(){console.log(`${Y.bold("Usage:")} asm export [options]
213
+ ${M.map((G)=>` --path ${G.relPath}`).join(`
214
+ `)}`),process.exit(2);if(B.length>1){if(console.error(`
215
+ ${X.bold("Install settings:")}`),console.error(` Source: ${Q}`),U)console.error(` Provider: All (${U.map((G)=>G.label).join(", ")})`),console.error(` Primary: ${Y.label} (${Y.name})`),console.error(` Symlinks: ${U.filter((G)=>G.name!==Y.name).map((G)=>G.label).join(", ")}`);else console.error(` Provider: ${Y.label} (${Y.name})`);console.error("")}let O=[];for(let G=0;G<B.length;G++){let A=B[G],I=V(K,A);try{let F=await p($,Q,Z,K,I,B.length===1?$.flags.name:null,z,Y,U,B.length>1?{index:G+1,total:B.length}:void 0);J.push(F)}catch(F){if(O.push(A),console.error(X.red(` x Failed: ${A} -- ${F.message}`)),B.length===1)throw F}}if(B.length>1&&O.length>0){console.error(`
216
+ ${X.yellow(`${O.length} skill(s) failed to install:`)}`);for(let G of O)console.error(` - ${G}`)}}}if(process.removeListener("SIGINT",q),process.removeListener("SIGTERM",q),$.flags.json)console.log(JSON.stringify(J.length===1?J[0]:J,null,2));else if(J.length===1)console.error(X.green(`
217
+ Done! Installed "${J[0].name}" to ${J[0].path}`));else console.error(`
218
+ ${X.green(`Done! Installed ${J.length} skill(s) successfully.`)}`)}catch(Z){if(process.removeListener("SIGINT",q),process.removeListener("SIGTERM",q),$.flags.json)console.log(JSON.stringify({success:!1,error:Z.message},null,2));else j(Z.message);process.exit(1)}finally{if(K)await f(K)}}function D1(){console.log(`${X.bold("Usage:")} asm export [options]
175
219
 
176
- Export skill inventory as a portable JSON manifest.
220
+ Export skill inventory as a portable JSON manifest. Useful for backup,
221
+ sharing, or scripting.
177
222
 
178
- ${Y.bold("Options:")}
223
+ ${X.bold("Options:")}
179
224
  -s, --scope <s> Filter: global, project, or both (default: both)
180
225
  --no-color Disable ANSI colors
181
- -V, --verbose Show debug output`)}async function C1($){if($.flags.help){I1();return}let Q=await F(),K=await I(Q,$.flags.scope),q=Y0(K);console.log(JSON.stringify(q,null,2))}function x1(){console.log(`${Y.bold("Usage:")} asm init <name> [options]
226
+ -V, --verbose Show debug output
182
227
 
183
- Scaffold a new skill directory with a SKILL.md template.
228
+ ${X.bold("Examples:")}
229
+ asm export ${X.dim("Export all skills")}
230
+ asm export -s global ${X.dim("Export global skills only")}
231
+ asm export > skills.json ${X.dim("Save to file")}`)}async function b1($){if($.flags.help){D1();return}let Q=await _(),K=await w(Q,$.flags.scope),q=J0(K);console.log(JSON.stringify(q,null,2))}function k1(){console.log(`${X.bold("Usage:")} asm init <name> [options]
184
232
 
185
- ${Y.bold("Options:")}
233
+ Scaffold a new skill directory with a SKILL.md template. Creates a
234
+ ready-to-edit skill in the target provider's skill folder.
235
+
236
+ ${X.bold("Options:")}
186
237
  -p, --provider <name> Target provider (claude, codex, openclaw, agents)
187
238
  --path <dir> Scaffold in specified directory instead of provider path
188
239
  -f, --force Overwrite if skill already exists
189
240
  --no-color Disable ANSI colors
190
- -V, --verbose Show debug output`)}async function R1($){if($.flags.help){x1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <name>"),console.error('Run "asm init --help" for usage.'),process.exit(2);let K=S(Q),q;if($.flags.path){let{resolve:Z}=await import("path");q=Z($.flags.path)}else{let Z=await F(),{provider:V}=await P(Z,$.flags.provider,!!process.stdin.isTTY),{join:X}=await import("path"),{resolveProviderPath:z}=await import("./chunk-zh7g5bam.js"),J=z(Z.providers.find((U)=>U.name===V.name).global);q=X(J,K)}if(await J0(q)){if(!$.flags.force){if(!process.stdin.isTTY)M(`Directory already exists: ${q}. Use --force to overwrite.`),process.exit(2);process.stderr.write(`${Y.yellow(`Directory already exists: ${q}`)}
191
- ${Y.bold("Overwrite?")} [y/N] `);let Z=await C();if(Z.toLowerCase()!=="y"&&Z.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}await z0(K,q),console.error(Y.green(`✓ Created skill "${K}" at ${q}`))}function w1(){console.log(`${Y.bold("Usage:")} asm stats [options]
241
+ -V, --verbose Show debug output
192
242
 
193
- Show aggregate skill metrics dashboard.
243
+ ${X.bold("Examples:")}
244
+ asm init my-skill ${X.dim("Scaffold (interactive provider)")}
245
+ asm init my-skill -p claude ${X.dim("Scaffold in Claude Code")}
246
+ asm init my-skill --path ./skills ${X.dim("Scaffold in custom directory")}`)}async function f1($){if($.flags.help){k1();return}let Q=$.subcommand;if(!Q)j("Missing required argument: <name>"),console.error('Run "asm init --help" for usage.'),process.exit(2);let K=b(Q),q;if($.flags.path){let{resolve:Z}=await import("path");q=Z($.flags.path)}else{let Z=await _(),{provider:z}=await P(Z,$.flags.provider,!!process.stdin.isTTY),{join:Y}=await import("path"),{resolveProviderPath:U}=await import("./chunk-t7727aqn.js"),V=U(Z.providers.find((J)=>J.name===z.name).global);q=Y(V,K)}if(await M0(q)){if(!$.flags.force){if(!process.stdin.isTTY)j(`Directory already exists: ${q}. Use --force to overwrite.`),process.exit(2);process.stderr.write(`${X.yellow(`Directory already exists: ${q}`)}
247
+ ${X.bold("Overwrite?")} [y/N] `);let Z=await x();if(Z.toLowerCase()!=="y"&&Z.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}await G0(K,q),console.error(X.green(`Done! Created skill "${K}" at ${q}`))}function P1(){console.log(`${X.bold("Usage:")} asm stats [options]
194
248
 
195
- ${Y.bold("Options:")}
249
+ Show aggregate skill metrics with provider distribution charts,
250
+ scope breakdown, disk usage, and duplicate summary.
251
+
252
+ ${X.bold("Options:")}
196
253
  --json Output as JSON
197
254
  -s, --scope <s> Filter: global, project, or both (default: both)
198
255
  --no-color Disable ANSI colors
199
- -V, --verbose Show debug output`)}async function y1($){if($.flags.help){w1();return}let Q=await F(),K=await I(Q,$.flags.scope);if(K.length===0){console.log("No skills found.");return}let q=o(K),Z=await U0(K,q);if($.flags.json)console.log(x(Z));else console.log(W0(Z))}function N1(){console.log(`${Y.bold("Usage:")} asm link <path> [options]
256
+ -V, --verbose Show debug output
257
+
258
+ ${X.bold("Examples:")}
259
+ asm stats ${X.dim("Show full dashboard")}
260
+ asm stats -s global ${X.dim("Global skills only")}
261
+ asm stats --json ${X.dim("Output raw data as JSON")}`)}async function v1($){if($.flags.help){P1();return}let Q=await _(),K=await w(Q,$.flags.scope);if(K.length===0){console.log("No skills found.");return}let q=l(K),Z=await j0(K,q);if($.flags.json)if(!$.flags.verbose){let{perSkillDiskBytes:z,...Y}=Z;console.log(R(Y))}else console.log(R(Z));else console.log(F0(Z))}function h1(){console.log(`${X.bold("Usage:")} asm link <path> [options]
200
262
 
201
- Symlink a local skill directory into an agent's skill folder.
263
+ Symlink a local skill directory into an agent's skill folder. Useful
264
+ for local development — changes to the source are reflected immediately.
202
265
 
203
- ${Y.bold("Options:")}
266
+ ${X.bold("Options:")}
204
267
  -p, --provider <name> Target provider (claude, codex, openclaw, agents)
205
268
  --name <name> Override symlink name (default: directory basename)
206
269
  -f, --force Overwrite if target already exists
207
270
  --json Output as JSON
208
271
  --no-color Disable ANSI colors
209
- -V, --verbose Show debug output`)}async function S1($){if($.flags.help){N1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <path>"),console.error('Run "asm link --help" for usage.'),process.exit(2);let{resolve:K,basename:q}=await import("path"),Z=K(Q),V=await G0(Z),X=$.flags.name?S($.flags.name):q(Z),z=await F(),{provider:J}=await P(z,$.flags.provider,!!process.stdin.isTTY),{resolveProviderPath:U}=await import("./chunk-zh7g5bam.js"),j=U(z.providers.find((B)=>B.name===J.name).global),{join:W}=await import("path"),O=W(j,X);if(!$.flags.force){let B=!1;try{let{access:G}=await import("fs/promises");await G(O),B=!0}catch{}if(B){if(!process.stdin.isTTY)M(`Target already exists: ${O}. Use --force to overwrite.`),process.exit(2);process.stderr.write(`${Y.yellow(`Target already exists: ${O}`)}
210
- ${Y.bold("Overwrite?")} [y/N] `);let G=await C();if(G.toLowerCase()!=="y"&&G.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0);await f(Z,j,X,!0)}else await f(Z,j,X,!1)}else await f(Z,j,X,!0);if($.flags.json)console.log(x({success:!0,name:X,symlinkPath:O,targetPath:Z}));else console.error(Y.green(`✓ Linked "${X}" → ${Z}`)),console.error(` Symlink: ${O}`),console.error(Y.dim(` If you move or delete the source, run "asm uninstall ${X}" to clean up.`))}async function x0($){let Q=z1($);if(Q.flags.noColor)globalThis.__CLI_NO_COLOR=!0;if(Q.flags.verbose)M0(!0);if(Q.flags.version){console.log(`asm ${n}`);return}if(!Q.command&&Q.flags.help){J1();return}if(!Q.command)return;switch(Q.command){case"list":await O1(Q);break;case"search":await _1(Q);break;case"inspect":await F1(Q);break;case"uninstall":await A1(Q);break;case"audit":await E1(Q);break;case"install":await H1(Q);break;case"config":await T1(Q);break;case"export":await C1(Q);break;case"init":await R1(Q);break;case"stats":await y1(Q);break;case"link":await S1(Q);break;default:M(`Unknown command: "${Q.command}"`),console.error('Run "asm --help" for usage.'),process.exit(2)}}function R0($){let Q=$.slice(2);if(Q.length===0)return!1;let K=["list","search","inspect","uninstall","audit","config","install","export","init","stats","link"],q=Q[0];if(K.includes(q))return!0;if(q==="--help"||q==="-h")return!0;if(q==="--version"||q==="-v")return!0;if(q.startsWith("-")||q.length>0)return!0;return!1}if(R0(process.argv))await x0(process.argv);else await import("./chunk-qfn7hb5z.js");
272
+ -V, --verbose Show debug output
273
+
274
+ ${X.bold("Examples:")}
275
+ asm link ./my-skill ${X.dim("Link (interactive provider)")}
276
+ asm link ./my-skill -p claude ${X.dim("Link to Claude Code")}
277
+ asm link ./my-skill --name alias ${X.dim("Link with custom name")}`)}async function u1($){if($.flags.help){h1();return}let Q=$.subcommand;if(!Q)j("Missing required argument: <path>"),console.error('Run "asm link --help" for usage.'),process.exit(2);let{resolve:K,basename:q}=await import("path"),Z=K(Q),z=await _0(Z),Y=$.flags.name?b($.flags.name):q(Z),U=await _(),{provider:V}=await P(U,$.flags.provider,!!process.stdin.isTTY),{resolveProviderPath:J}=await import("./chunk-t7727aqn.js"),W=J(U.providers.find((O)=>O.name===V.name).global),{join:M}=await import("path"),B=M(W,Y);if(!$.flags.force){let O=!1;try{let{access:G}=await import("fs/promises");await G(B),O=!0}catch{}if(O){if(!process.stdin.isTTY)j(`Target already exists: ${B}. Use --force to overwrite.`),process.exit(2);process.stderr.write(`${X.yellow(`Target already exists: ${B}`)}
278
+ ${X.bold("Overwrite?")} [y/N] `);let G=await x();if(G.toLowerCase()!=="y"&&G.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0);await v(Z,W,Y,!0)}else await v(Z,W,Y,!1)}else await v(Z,W,Y,!0);if($.flags.json)console.log(R({success:!0,name:Y,symlinkPath:B,targetPath:Z}));else console.error(X.green(`Done! Linked "${Y}" -> ${Z}`)),console.error(` Symlink: ${B}`),console.error(X.dim(` If you move or delete the source, run "asm uninstall ${Y}" to clean up.`))}async function k0($){let Q=F1($);if(Q.flags.noColor)globalThis.__CLI_NO_COLOR=!0;if(Q.flags.verbose)A0(!0);if(Q.flags.version){console.log(`asm ${i}`);return}if(!Q.command&&Q.flags.help){O1();return}if(!Q.command)return;switch(Q.command){case"list":await I1(Q);break;case"search":await C1(Q);break;case"inspect":await R1(Q);break;case"uninstall":await w1(Q);break;case"audit":await y1(Q);break;case"install":await S1(Q);break;case"config":await x1(Q);break;case"export":await b1(Q);break;case"init":await f1(Q);break;case"stats":await v1(Q);break;case"link":await u1(Q);break;default:j(`Unknown command: "${Q.command}"`),console.error('Run "asm --help" for usage.'),process.exit(2)}}function f0($){let Q=$.slice(2);if(Q.length===0)return!1;let K=["list","search","inspect","uninstall","audit","config","install","export","init","stats","link"],q=Q[0];if(K.includes(q))return!0;if(q==="--help"||q==="-h")return!0;if(q==="--version"||q==="-v")return!0;if(q.startsWith("-")||q.length>0)return!0;return!1}if(f0(process.argv))await k0(process.argv);else await import("./chunk-menf8e4q.js");
@@ -0,0 +1,9 @@
1
+ import{w as o,z as q}from"./chunk-zh7g5bam.js";import{readdir as N,stat as K,lstat as _,readlink as y,readFile as E,realpath as H}from"fs/promises";import{join as D,resolve as M}from"path";function O($){let L={},S=$.split(`
2
+ `),c=!1,t=!1,B=null,z=[],G="none",f=-1;function j(){if(B){let A=z.join(" ").trim();if(A)L[B]=A;B=null,z=[],G="none",f=-1}}for(let A of S){if(A.trim()==="---")if(!t){t=!0,c=!0;continue}else{j();break}if(!c)continue;if(G!=="none"&&B){let Z=A.replace(/^\s*/,""),Y=A.length-Z.length;if(Y>0&&Z.length>0){if(f===-1)f=Y;z.push(Z);continue}else if(Z.length===0)continue;else j()}let X=A.match(/^(\w[\w-]*):\s*(.*?)\s*$/);if(X){j();let Z=X[1],Y=X[2];if(Y==="|"||Y===">")B=Z,z=[],G=Y==="|"?"literal":"folded";else if(Y==="|+"||Y===">+"||Y==="|-"||Y===">-")B=Z,z=[],G=Y.startsWith("|")?"literal":"folded";else{let T=Y.replace(/^["']|["']$/g,"");if(T)L[Z]=T}}}return j(),L}function h($,L){let S=[];for(let c of $.providers){if(!c.enabled){o(`scan: skipping disabled provider "${c.name}"`);continue}if(L==="global"||L==="both"){let t=q(c.global);o(`scan: adding location ${t} (${c.label}, global)`),S.push({dir:t,location:`global-${c.name}`,scope:"global",providerName:c.name,providerLabel:c.label})}if(L==="project"||L==="both"){let t=q(c.project);o(`scan: adding location ${t} (${c.label}, project)`),S.push({dir:t,location:`project-${c.name}`,scope:"project",providerName:c.name,providerLabel:c.label})}}for(let c of $.customPaths)if(L===c.scope||L==="both"){let t=q(c.path);o(`scan: adding custom location ${t} (${c.label}, ${c.scope})`),S.push({dir:t,location:`${c.scope}-custom`,scope:c.scope,providerName:"custom",providerLabel:c.label})}return S}async function v($){try{return(await N($,{recursive:!0})).length}catch{return 0}}async function F($){let L=[];o(`scanning: ${$.dir} (${$.location})`);let S;try{S=await N($.dir)}catch{return o(`scanning: ${$.dir} — not found, skipping`),L}for(let c of S){let t=D($.dir,c);try{if(!(await K(t)).isDirectory()){o(` skip: "${c}" — not a directory`);continue}}catch{o(` skip: "${c}" — stat failed`);continue}let B=D(t,"SKILL.md"),z;try{z=await E(B,"utf-8")}catch{o(` skip: "${c}" — no SKILL.md`);continue}let G=O(z),f=!1,j=null;try{if((await _(t)).isSymbolicLink())f=!0,j=await y(t)}catch{}let A=M(t),X;try{X=await H(t)}catch{X=A}L.push({name:G.name||c,version:G.version||"0.0.0",description:(G.description||"").replace(/\s*\n\s*/g," ").trim(),dirName:c,path:A,originalPath:t,location:$.location,scope:$.scope,provider:$.providerName,providerLabel:$.providerLabel,isSymlink:f,symlinkTarget:j,realPath:X})}return o(`found ${L.length} skill(s) in ${$.dir}`),L}async function I$($,L){let S=h($,L);return(await Promise.all(S.map(F))).flat()}function Q$($,L){if(!L.trim())return $;let S=L.toLowerCase();return $.filter((c)=>c.name.toLowerCase().includes(S)||c.description.toLowerCase().includes(S)||c.location.toLowerCase().includes(S)||c.providerLabel.toLowerCase().includes(S))}function V($,L){let S=$.split("."),c=L.split("."),t=Math.max(S.length,c.length);for(let B=0;B<t;B++){let z=parseInt(S[B]??"0",10),G=parseInt(c[B]??"0",10);if(isNaN(z)||isNaN(G))return $.localeCompare(L);if(z!==G)return z-G}return 0}function X$($,L){let S=[...$];switch(L){case"name":S.sort((c,t)=>c.name.localeCompare(t.name));break;case"version":S.sort((c,t)=>V(c.version,t.version));break;case"location":S.sort((c,t)=>c.location.localeCompare(t.location));break}return S}import{rm as P,readFile as R,writeFile as x,access as C,lstat as w}from"fs/promises";import{join as W,resolve as U,dirname as m}from"path";import{homedir as b}from"os";var d=b();function u($,L){let S={directories:[],ruleFiles:[],agentsBlocks:[]};S.directories.push({path:$.originalPath,isSymlink:$.isSymlink});let c=$.dirName;if($.scope==="project")S.ruleFiles.push(U(".cursor","rules",`${c}.mdc`),U(".windsurf","rules",`${c}.md`),U(".github","instructions",`${c}.instructions.md`)),S.agentsBlocks.push({file:U("AGENTS.md"),skillName:c});if($.scope==="global"){for(let z of L.providers){if(!z.enabled)continue;let G=q(z.global),f=W(m(G),"AGENTS.md");S.agentsBlocks.push({file:f,skillName:c})}let t=W(d,".codex","AGENTS.md");if(!S.agentsBlocks.some((z)=>z.file===t))S.agentsBlocks.push({file:t,skillName:c})}return S}function T$($,L,S){let c=L.filter((f)=>f.dirName===$);if(c.length===0)return{directories:[],ruleFiles:[],agentsBlocks:[]};let t={directories:[],ruleFiles:[],agentsBlocks:[]},B=new Set,z=new Set,G=new Set;for(let f of c){let j=u(f,S);for(let A of j.directories)if(!B.has(A.path))B.add(A.path),t.directories.push(A);for(let A of j.ruleFiles)if(!z.has(A))z.add(A),t.ruleFiles.push(A);for(let A of j.agentsBlocks){let X=`${A.file}::${A.skillName}`;if(!G.has(X))G.add(X),t.agentsBlocks.push(A)}}return t}async function J($){try{return await C($),!0}catch{return!1}}async function n($,L){if(!await J($))return;let S=await R($,"utf-8");for(let c of["agent-skill-manager","skill-manager","pskills"]){let t=`<!-- ${c}: ${L} -->`,B=`<!-- /${c}: ${L} -->`,z=S.indexOf(t),G=S.indexOf(B);if(z===-1||G===-1)continue;let f=z;if(f>0&&S[f-1]===`
3
+ `)f--;let A=G+B.length;if(A<S.length&&S[A]===`
4
+ `)A++;S=S.slice(0,f)+S.slice(A)}await x($,S,"utf-8")}async function U$($){let L=[];for(let S of $.directories)try{if(S.isSymlink)await P(S.path),L.push(`Removed symlink: ${S.path}`);else await P(S.path,{recursive:!0,force:!0}),L.push(`Removed directory: ${S.path}`)}catch(c){L.push(`Failed to remove ${S.path}: ${c.message}`)}for(let S of $.ruleFiles)if(await J(S))try{await P(S),L.push(`Removed rule file: ${S}`)}catch(c){L.push(`Failed to remove ${S}: ${c.message}`)}for(let S of $.agentsBlocks)try{await n(S.file,S.skillName),L.push(`Cleaned AGENTS.md block in: ${S.file}`)}catch(c){L.push(`Failed to clean AGENTS.md block: ${c.message}`)}return L}async function v$($){let L=[];for(let S of $.directories)if(await J(S.path)){let t=(await w(S.path)).isSymbolicLink()?"symlink":"directory";L.push(`${S.path} (${t})`)}for(let S of $.ruleFiles)if(await J(S))L.push(S);for(let S of $.agentsBlocks)if(await J(S.file)){let c=await R(S.file,"utf-8");if(c.includes(`<!-- agent-skill-manager: ${S.skillName} -->`)||c.includes(`<!-- skill-manager: ${S.skillName} -->`)||c.includes(`<!-- pskills: ${S.skillName} -->`))L.push(`${S.file} (AGENTS.md block)`)}return L}var I=()=>{if(process.env.NO_COLOR!==void 0)return!1;if(globalThis.__CLI_NO_COLOR)return!1;if(!process.stdout.isTTY)return!1;return!0},Q={bold:($)=>I()?`\x1B[1m${$}\x1B[0m`:$,cyan:($)=>I()?`\x1B[36m${$}\x1B[0m`:$,green:($)=>I()?`\x1B[32m${$}\x1B[0m`:$,yellow:($)=>I()?`\x1B[33m${$}\x1B[0m`:$,dim:($)=>I()?`\x1B[2m${$}\x1B[0m`:$,red:($)=>I()?`\x1B[31m${$}\x1B[0m`:$,blueBold:($)=>I()?`\x1B[1m\x1B[34m${$}\x1B[0m`:$};function O$($){if($.length===0)return"No skills found.";let L=["Name","Version","Provider","Scope","Type","Path"],S=$.map((f)=>[f.name,f.version,f.providerLabel,f.scope,f.isSymlink?"symlink":"directory",f.path]),c=L.map((f,j)=>Math.max(f.length,...S.map((A)=>A[j].length))),t=(f,j)=>f.padEnd(j),B=L.map((f,j)=>t(f,c[j])).join(" "),z=c.map((f)=>"-".repeat(f)).join("--"),G=S.map((f)=>f.map((j,A)=>t(j,c[A])).join(" "));return[I()?Q.bold(B):B,z,...G].join(`
5
+ `)}async function a($){let L=[],S=(t,B)=>`${I()?Q.bold(t+":"):t+":"} ${B}`;if(L.push(S("Name",$.name)),L.push(S("Version",$.version)),L.push(S("Provider",$.providerLabel)),L.push(S("Scope",$.scope)),L.push(S("Location",$.location)),L.push(S("Path",$.path)),L.push(S("Type",$.isSymlink?"symlink":"directory")),$.isSymlink&&$.symlinkTarget)L.push(S("Symlink Target",$.symlinkTarget));let c=$.fileCount??await v($.path);if(L.push(S("File Count",String(c))),$.description)L.push(""),L.push(S("Description",$.description));if($.warnings&&$.warnings.length>0){L.push(""),L.push(I()?Q.bold("Warnings:"):"Warnings:");for(let t of $.warnings)L.push(` ${I()?Q.yellow("!"):"!"} [${t.category}] ${t.message}`)}return L.join(`
6
+ `)}async function D$($){if($.length===0)return"No skills found.";if($.length===1)return a($[0]);let L=[],S=(j,A)=>`${I()?Q.bold(j+":"):j+":"} ${A}`,c=$[0],t=` ${c.name} `,B="=".repeat(Math.max(t.length,40));L.push(I()?Q.blueBold(B):B),L.push(I()?Q.blueBold(t):t),L.push(I()?Q.blueBold(B):B),L.push(""),L.push(S("Name",c.name)),L.push(S("Version",I()?Q.green(c.version):c.version));let z=c.fileCount??await v(c.path);if(L.push(S("File Count",String(z))),L.push(S("Installed in",I()?Q.cyan(`${$.length} providers`):`${$.length} providers`)),c.description){L.push("");let j="Description";L.push(I()?Q.bold(j+":"):j+":");let A=k(c.description,76);for(let X of A)L.push(" "+X)}L.push("");let G=`Installations (${$.length})`;L.push(I()?Q.bold(G):G),L.push("-".repeat(G.length));for(let j=0;j<$.length;j++){let A=$[j],X=I()?Q.dim(`[${j+1}]`):`[${j+1}]`,Z=I()?Q.cyan(A.providerLabel):A.providerLabel,Y=A.isSymlink?I()?Q.yellow("symlink"):"symlink":I()?Q.green("directory"):"directory",T=I()?Q.dim(A.scope):A.scope;if(L.push(`${X} ${Z} (${T}, ${Y})`),L.push(` ${S("Path",A.path)}`),A.isSymlink&&A.symlinkTarget)L.push(` ${S("Target",A.symlinkTarget)}`);if(j<$.length-1)L.push("")}let f=$.flatMap((j)=>{if(!j.warnings||j.warnings.length===0)return[];return j.warnings.map((A)=>({...A,provider:j.providerLabel}))});if(f.length>0){L.push("");let j=`Warnings (${f.length})`;L.push(I()?Q.bold(j):j),L.push("-".repeat(j.length));for(let A of f){let X=I()?Q.yellow("!"):"!";L.push(` ${X} [${A.category}] ${A.message}`)}}return L.join(`
7
+ `)}function k($,L){let S=$.split(/\s+/),c=[],t="";for(let B of S)if(t.length+B.length+1>L&&t.length>0)c.push(t),t=B;else t=t?t+" "+B:B;if(t)c.push(t);return c}function N$($){return JSON.stringify($,null,2)}function g$($){let L=[],S=new Set,c=new Map,t=[];for(let f of $){let j=c.get(f.realPath);if(j){if(f.isSymlink)continue;if(j.isSymlink)t[t.indexOf(j)]=f,c.set(f.realPath,f);else t.push(f)}else c.set(f.realPath,f),t.push(f)}let B=new Map;for(let f of t){let j=B.get(f.dirName)??[];j.push(f),B.set(f.dirName,j)}for(let[f,j]of B)if(new Set(j.map((X)=>X.location)).size>=2){L.push({key:f,reason:"same-dirName",instances:j});for(let X of j)S.add(X.path)}let z=new Map;for(let f of t){if(!f.name)continue;let j=z.get(f.name)??[];j.push(f),z.set(f.name,j)}for(let[f,j]of z){if(new Set(j.map((Y)=>Y.dirName)).size<2)continue;let X=j.filter((Y)=>!S.has(Y.path));if(X.length<2)continue;if(new Set(X.map((Y)=>Y.dirName)).size<2)continue;L.push({key:f,reason:"same-frontmatterName",instances:X})}L.sort((f,j)=>{if(f.reason!==j.reason)return f.reason==="same-dirName"?-1:1;return f.key.localeCompare(j.key)});let G=L.reduce((f,j)=>f+j.instances.length,0);return{scannedAt:new Date().toISOString(),totalSkills:$.length,duplicateGroups:L,totalDuplicateInstances:G}}function r($){return[...$].sort((L,S)=>{if(L.scope!==S.scope)return L.scope==="global"?-1:1;let c=L.providerLabel.localeCompare(S.providerLabel);if(c!==0)return c;return L.path.localeCompare(S.path)})}function i($){return $==="same-dirName"?"same dirName":"same name"}function K$($){if($.duplicateGroups.length===0)return Q.green("No duplicate skills found.");let L=[];L.push(Q.bold(`Found ${$.duplicateGroups.length} duplicate group(s) (${$.totalDuplicateInstances} total instances):`)),L.push("");for(let S of $.duplicateGroups){L.push(Q.yellow(` Group: "${S.key}" (${i(S.reason)})`));let c=r(S.instances);for(let t=0;t<c.length;t++){let B=c[t],z=t===0?Q.green(" (recommended keep)"):"";L.push(` ${Q.dim("•")} ${B.path} [${B.providerLabel}/${B.scope}]${z}`)}L.push("")}return L.join(`
8
+ `)}function _$($){return JSON.stringify($,null,2)}import{readFileSync as s}from"fs";import{resolve as e,dirname as l}from"path";import{fileURLToPath as $$}from"url";import{execSync as L$}from"child_process";var S$=l($$(import.meta.url)),g="1.5.1";try{let $=s(e(S$,"../../package.json"),"utf-8");g=JSON.parse($).version}catch{}var p="dad0bf2";try{p=L$("git rev-parse --short HEAD",{encoding:"utf-8"}).trim()||p}catch{}var c$=g,t$=p,F$=`v${c$} (${t$})`;
9
+ export{O as a,v as b,I$ as c,Q$ as d,X$ as e,u as f,T$ as g,U$ as h,v$ as i,Q as j,O$ as k,D$ as l,N$ as m,g$ as n,r as o,i as p,K$ as q,_$ as r,F$ as s};
@@ -0,0 +1,8 @@
1
+ import{w as I,z as X}from"./chunk-zh7g5bam.js";import{readdir as P,stat as C,lstat as N,readlink as R,readFile as K,realpath as _}from"fs/promises";import{join as H,resolve as w}from"path";function U(o){let c={},t=o.split(`
2
+ `),$=!1,S=!1,j=null,A=[],B="none",f=-1;function L(){if(j){let p=A.join(" ").trim();if(p)c[j]=p;j=null,A=[],B="none",f=-1}}for(let p of t){if(p.trim()==="---")if(!S){S=!0,$=!0;continue}else{L();break}if(!$)continue;if(B!=="none"&&j){let G=p.replace(/^\s*/,""),z=p.length-G.length;if(z>0&&G.length>0){if(f===-1)f=z;A.push(G);continue}else if(G.length===0)continue;else L()}let v=p.match(/^(\w[\w-]*):\s*(.*?)\s*$/);if(v){L();let G=v[1],z=v[2];if(z==="|"||z===">")j=G,A=[],B=z==="|"?"literal":"folded";else if(z==="|+"||z===">+"||z==="|-"||z===">-")j=G,A=[],B=z.startsWith("|")?"literal":"folded";else{let T=z.replace(/^["']|["']$/g,"");if(T)c[G]=T}}}return L(),c}function E(o,c){let t=[];for(let $ of o.providers){if(!$.enabled){I(`scan: skipping disabled provider "${$.name}"`);continue}if(c==="global"||c==="both"){let S=X($.global);I(`scan: adding location ${S} (${$.label}, global)`),t.push({dir:S,location:`global-${$.name}`,scope:"global",providerName:$.name,providerLabel:$.label})}if(c==="project"||c==="both"){let S=X($.project);I(`scan: adding location ${S} (${$.label}, project)`),t.push({dir:S,location:`project-${$.name}`,scope:"project",providerName:$.name,providerLabel:$.label})}}for(let $ of o.customPaths)if(c===$.scope||c==="both"){let S=X($.path);I(`scan: adding custom location ${S} (${$.label}, ${$.scope})`),t.push({dir:S,location:`${$.scope}-custom`,scope:$.scope,providerName:"custom",providerLabel:$.label})}return t}async function O(o){try{return(await P(o,{recursive:!0})).length}catch{return 0}}async function M(o){let c=[];I(`scanning: ${o.dir} (${o.location})`);let t;try{t=await P(o.dir)}catch{return I(`scanning: ${o.dir} — not found, skipping`),c}for(let $ of t){let S=H(o.dir,$);try{if(!(await C(S)).isDirectory()){I(` skip: "${$}" — not a directory`);continue}}catch{I(` skip: "${$}" — stat failed`);continue}let j=H(S,"SKILL.md"),A;try{A=await K(j,"utf-8")}catch{I(` skip: "${$}" — no SKILL.md`);continue}let B=U(A),f=!1,L=null;try{if((await N(S)).isSymbolicLink())f=!0,L=await R(S)}catch{}let p=w(S),v;try{v=await _(S)}catch{v=p}c.push({name:B.name||$,version:B.version||"0.0.0",description:(B.description||"").replace(/\s*\n\s*/g," ").trim(),dirName:$,path:p,originalPath:S,location:o.location,scope:o.scope,provider:o.providerName,providerLabel:o.providerLabel,isSymlink:f,symlinkTarget:L,realPath:v})}return I(`found ${c.length} skill(s) in ${o.dir}`),c}async function Ao(o,c){let t=E(o,c);return(await Promise.all(t.map(M))).flat()}function Bo(o,c){if(!c.trim())return o;let t=c.toLowerCase();return o.filter(($)=>$.name.toLowerCase().includes(t)||$.description.toLowerCase().includes(t)||$.location.toLowerCase().includes(t)||$.providerLabel.toLowerCase().includes(t))}function h(o,c){let t=o.split("."),$=c.split("."),S=Math.max(t.length,$.length);for(let j=0;j<S;j++){let A=parseInt(t[j]??"0",10),B=parseInt($[j]??"0",10);if(isNaN(A)||isNaN(B))return o.localeCompare(c);if(A!==B)return A-B}return 0}function vo(o,c){let t=[...o];switch(c){case"name":t.sort(($,S)=>$.name.localeCompare(S.name));break;case"version":t.sort(($,S)=>h($.version,S.version));break;case"location":t.sort(($,S)=>$.location.localeCompare(S.location));break}return t}import{rm as q,readFile as D,writeFile as F,access as x,lstat as V}from"fs/promises";import{join as y,resolve as Z,dirname as n}from"path";import{homedir as m}from"os";var r=m();function b(o,c){let t={directories:[],ruleFiles:[],agentsBlocks:[]};t.directories.push({path:o.originalPath,isSymlink:o.isSymlink});let $=o.dirName;if(o.scope==="project")t.ruleFiles.push(Z(".cursor","rules",`${$}.mdc`),Z(".windsurf","rules",`${$}.md`),Z(".github","instructions",`${$}.instructions.md`)),t.agentsBlocks.push({file:Z("AGENTS.md"),skillName:$});if(o.scope==="global"){for(let A of c.providers){if(!A.enabled)continue;let B=X(A.global),f=y(n(B),"AGENTS.md");t.agentsBlocks.push({file:f,skillName:$})}let S=y(r,".codex","AGENTS.md");if(!t.agentsBlocks.some((A)=>A.file===S))t.agentsBlocks.push({file:S,skillName:$})}return t}function Xo(o,c,t){let $=c.filter((f)=>f.dirName===o);if($.length===0)return{directories:[],ruleFiles:[],agentsBlocks:[]};let S={directories:[],ruleFiles:[],agentsBlocks:[]},j=new Set,A=new Set,B=new Set;for(let f of $){let L=b(f,t);for(let p of L.directories)if(!j.has(p.path))j.add(p.path),S.directories.push(p);for(let p of L.ruleFiles)if(!A.has(p))A.add(p),S.ruleFiles.push(p);for(let p of L.agentsBlocks){let v=`${p.file}::${p.skillName}`;if(!B.has(v))B.add(v),S.agentsBlocks.push(p)}}return S}async function Y(o){try{return await x(o),!0}catch{return!1}}async function a(o,c){if(!await Y(o))return;let t=await D(o,"utf-8");for(let $ of["agent-skill-manager","skill-manager","pskills"]){let S=`<!-- ${$}: ${c} -->`,j=`<!-- /${$}: ${c} -->`,A=t.indexOf(S),B=t.indexOf(j);if(A===-1||B===-1)continue;let f=A;if(f>0&&t[f-1]===`
3
+ `)f--;let p=B+j.length;if(p<t.length&&t[p]===`
4
+ `)p++;t=t.slice(0,f)+t.slice(p)}await F(o,t,"utf-8")}async function Yo(o){let c=[];for(let t of o.directories)try{if(t.isSymlink)await q(t.path),c.push(`Removed symlink: ${t.path}`);else await q(t.path,{recursive:!0,force:!0}),c.push(`Removed directory: ${t.path}`)}catch($){c.push(`Failed to remove ${t.path}: ${$.message}`)}for(let t of o.ruleFiles)if(await Y(t))try{await q(t),c.push(`Removed rule file: ${t}`)}catch($){c.push(`Failed to remove ${t}: ${$.message}`)}for(let t of o.agentsBlocks)try{await a(t.file,t.skillName),c.push(`Cleaned AGENTS.md block in: ${t.file}`)}catch($){c.push(`Failed to clean AGENTS.md block: ${$.message}`)}return c}async function Zo(o){let c=[];for(let t of o.directories)if(await Y(t.path)){let S=(await V(t.path)).isSymbolicLink()?"symlink":"directory";c.push(`${t.path} (${S})`)}for(let t of o.ruleFiles)if(await Y(t))c.push(t);for(let t of o.agentsBlocks)if(await Y(t.file)){let $=await D(t.file,"utf-8");if($.includes(`<!-- agent-skill-manager: ${t.skillName} -->`)||$.includes(`<!-- skill-manager: ${t.skillName} -->`)||$.includes(`<!-- pskills: ${t.skillName} -->`))c.push(`${t.file} (AGENTS.md block)`)}return c}var Q=()=>{if(process.env.NO_COLOR!==void 0)return!1;if(globalThis.__CLI_NO_COLOR)return!1;if(!process.stdout.isTTY)return!1;return!0},W={bold:(o)=>Q()?`\x1B[1m${o}\x1B[0m`:o,cyan:(o)=>Q()?`\x1B[36m${o}\x1B[0m`:o,green:(o)=>Q()?`\x1B[32m${o}\x1B[0m`:o,yellow:(o)=>Q()?`\x1B[33m${o}\x1B[0m`:o,dim:(o)=>Q()?`\x1B[2m${o}\x1B[0m`:o,red:(o)=>Q()?`\x1B[31m${o}\x1B[0m`:o,blueBold:(o)=>Q()?`\x1B[1m\x1B[34m${o}\x1B[0m`:o};function To(o){if(o.length===0)return"No skills found.";let c=["Name","Version","Provider","Scope","Type","Path"],t=o.map((f)=>[f.name,f.version,f.providerLabel,f.scope,f.isSymlink?"symlink":"directory",f.path]),$=c.map((f,L)=>Math.max(f.length,...t.map((p)=>p[L].length))),S=(f,L)=>f.padEnd(L),j=c.map((f,L)=>S(f,$[L])).join(" "),A=$.map((f)=>"-".repeat(f)).join("--"),B=t.map((f)=>f.map((L,p)=>S(L,$[p])).join(" "));return[Q()?W.bold(j):j,A,...B].join(`
5
+ `)}async function Uo(o){let c=[],t=(S,j)=>`${Q()?W.bold(S+":"):S+":"} ${j}`;if(c.push(t("Name",o.name)),c.push(t("Version",o.version)),c.push(t("Provider",o.providerLabel)),c.push(t("Scope",o.scope)),c.push(t("Location",o.location)),c.push(t("Path",o.path)),c.push(t("Type",o.isSymlink?"symlink":"directory")),o.isSymlink&&o.symlinkTarget)c.push(t("Symlink Target",o.symlinkTarget));let $=o.fileCount??await O(o.path);if(c.push(t("File Count",String($))),o.description)c.push(""),c.push(t("Description",o.description));if(o.warnings&&o.warnings.length>0){c.push(""),c.push(Q()?W.bold("Warnings:"):"Warnings:");for(let S of o.warnings)c.push(` ${Q()?W.yellow("!"):"!"} [${S.category}] ${S.message}`)}return c.join(`
6
+ `)}function Ho(o){return JSON.stringify(o,null,2)}function yo(o){let c=[],t=new Set,$=new Map,S=[];for(let f of o){let L=$.get(f.realPath);if(L){if(f.isSymlink)continue;if(L.isSymlink)S[S.indexOf(L)]=f,$.set(f.realPath,f);else S.push(f)}else $.set(f.realPath,f),S.push(f)}let j=new Map;for(let f of S){let L=j.get(f.dirName)??[];L.push(f),j.set(f.dirName,L)}for(let[f,L]of j)if(new Set(L.map((v)=>v.location)).size>=2){c.push({key:f,reason:"same-dirName",instances:L});for(let v of L)t.add(v.path)}let A=new Map;for(let f of S){if(!f.name)continue;let L=A.get(f.name)??[];L.push(f),A.set(f.name,L)}for(let[f,L]of A){if(new Set(L.map((z)=>z.dirName)).size<2)continue;let v=L.filter((z)=>!t.has(z.path));if(v.length<2)continue;if(new Set(v.map((z)=>z.dirName)).size<2)continue;c.push({key:f,reason:"same-frontmatterName",instances:v})}c.sort((f,L)=>{if(f.reason!==L.reason)return f.reason==="same-dirName"?-1:1;return f.key.localeCompare(L.key)});let B=c.reduce((f,L)=>f+L.instances.length,0);return{scannedAt:new Date().toISOString(),totalSkills:o.length,duplicateGroups:c,totalDuplicateInstances:B}}function u(o){return[...o].sort((c,t)=>{if(c.scope!==t.scope)return c.scope==="global"?-1:1;let $=c.providerLabel.localeCompare(t.providerLabel);if($!==0)return $;return c.path.localeCompare(t.path)})}function d(o){return o==="same-dirName"?"same dirName":"same name"}function Do(o){if(o.duplicateGroups.length===0)return W.green("No duplicate skills found.");let c=[];c.push(W.bold(`Found ${o.duplicateGroups.length} duplicate group(s) (${o.totalDuplicateInstances} total instances):`)),c.push("");for(let t of o.duplicateGroups){c.push(W.yellow(` Group: "${t.key}" (${d(t.reason)})`));let $=u(t.instances);for(let S=0;S<$.length;S++){let j=$[S],A=S===0?W.green(" (recommended keep)"):"";c.push(` ${W.dim("•")} ${j.path} [${j.providerLabel}/${j.scope}]${A}`)}c.push("")}return c.join(`
7
+ `)}function go(o){return JSON.stringify(o,null,2)}import{readFileSync as i}from"fs";import{resolve as k,dirname as s}from"path";import{fileURLToPath as e}from"url";import{execSync as l}from"child_process";var oo=s(e(import.meta.url)),g="1.5.1";try{let o=i(k(oo,"../../package.json"),"utf-8");g=JSON.parse(o).version}catch{}var J="dad0bf2";try{J=l("git rev-parse --short HEAD",{encoding:"utf-8"}).trim()||J}catch{}var to=g,co=J,wo=`v${to} (${co})`;
8
+ export{U as a,O as b,Ao as c,Bo as d,vo as e,b as f,Xo as g,Yo as h,Zo as i,W as j,To as k,Uo as l,Ho as m,yo as n,u as o,d as p,Do as q,go as r,wo as s};