agent-skill-manager 1.5.1 → 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 N,c as R,d as A0,e as g,f as E0,g as L0,h as o,i as T0,j as Y,k as n,l as H0,m as y,n as t,o as I0,q as C0,r as R0,s as l}from"./chunk-95dyppsz.js";import{A as F,B as F0,t as L,u as T,v as O0,w as E,x as _0,y as p,z as m}from"./chunk-zh7g5bam.js";import{execFile as N0}from"child_process";import{promisify as S0}from"util";import{mkdtemp as b0,readdir as s,readFile as b,rm as S,cp as D0,access as u,stat as a,lstat as f0,symlink as k0,mkdir as P0}from"fs/promises";import{join as H,relative as h0}from"path";import{tmpdir as v0}from"os";var e=S0(N0),u0=/^[a-zA-Z0-9_-]+$/,m0=/^[a-zA-Z0-9._-]+$/,c0=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/,i=128,d0=/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\/tree\/(.+))?\/?$/;function r($){let Q=d0.exec($);if(Q){let[,M,G,B]=Q,_=G.endsWith(".git")?G.slice(0,-4):G;$=`github:${M}/${_}${B?`#${B}`:""}`}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(!u0.test(z))throw Error(`Invalid source: owner contains invalid characters: "${z}". Allowed: [a-zA-Z0-9_-]`);if(!m0.test(J))throw Error(`Invalid source: repo contains invalid characters: "${J}". Allowed: [a-zA-Z0-9._-]`);let W={owner:z,repo:J,ref:V,cloneUrl:`https://github.com/${z}/${J}.git`};return E(`install: parsed source -> owner=${z} repo=${J} ref=${V}`),W}function D($){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>i)throw Error(`Invalid skill name: exceeds maximum length of ${i} characters`);if(!c0.test($))throw Error(`Invalid skill name: "${$}" does not match allowed pattern [a-zA-Z0-9][a-zA-Z0-9._-]*`);return $}async function $0(){try{await e("git",["--version"]),E("install: git available")}catch{throw Error("git is required for installing skills. Install git from https://git-scm.com")}}async function Q0($){E(`install: cloning ${$.cloneUrl}${$.ref?` (ref: ${$.ref})`:""}`);let Q=await b0(H(v0(),"asm-install-")),K=["clone","--depth","1"];if($.ref)K.push("--branch",$.ref);K.push($.cloneUrl,Q);try{await e("git",K,{timeout:60000})}catch(q){await k(Q);let Z=q.killed?"Clone timed out after 60 seconds":`Clone failed: ${q.stderr||q.message}`;throw Error(Z)}return Q}async function f($){let Q=H($,"SKILL.md"),K;try{K=await b(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",V=q.name||Z,X=q.version||"0.0.0";return E(`install: validated skill "${V}" v${X}`),{name:V,version:X,description:(q.description||"").replace(/\s*\n\s*/g," ").trim()}}async function Z0($,Q=3){let K=[];async function q(Z,V,X){let z;try{z=await s(Z)}catch{return}for(let J of z){if(J===".git"||J==="node_modules")continue;let W=H(Z,J);try{if(!(await a(W)).isDirectory())continue}catch{continue}let M=V?`${V}/${J}`:J,G=X+1,B=H(W,"SKILL.md");try{let _=await b(B,"utf-8"),U=N(_);K.push({relPath:M,name:U.name||J,version:U.version||"0.0.0",description:(U.description||"").replace(/\s*\n\s*/g," ").trim()})}catch{if(G<Q)await q(W,M,G)}}}return await q($,"",0),K.sort((Z,V)=>Z.name.localeCompare(V.name)),K}var p0=[{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?:\/\//}],g0=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 o0($){let Q=[];async function K(q,Z){let V;try{V=await s(q)}catch{return}for(let X of V){if(X===".git")continue;if(X==="node_modules")continue;let z=H(q,X),J=Z?`${Z}/${X}`:X;try{let W=await a(z);if(W.isDirectory())await K(z,J);else if(W.isFile()){let M=X.includes(".")?`.${X.split(".").pop().toLowerCase()}`:"";if(g0.has(M))continue;if(W.size>524288)continue;try{let G=await b(z,"utf-8");Q.push({relPath:J,content:G})}catch{}}}catch{continue}}}return await K($,""),Q}async function K0($){let Q=[],K=await o0($);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 p0)if(J.test(V[X])){let W=V[X].trim();Q.push({category:z,file:q,line:X+1,match:W.length>100?W.slice(0,100)+"…":W})}}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 D0(K,$.targetDir,{recursive:!0})}catch(z){throw Error(`Failed to install: ${z.message}`)}let q=H($.targetDir,".git");try{await S(q,{recursive:!0,force:!0})}catch{}E(`install: copied files to ${$.targetDir}`);let Z=H($.targetDir,"SKILL.md");try{await u(Z)}catch{throw Error("Installation verification failed: SKILL.md not found at target")}let V=await b(Z,"utf-8"),X=N(V);return{success:!0,path:$.targetDir,name:X.name||$.skillName,version:X.version||"0.0.0",provider:$.providerLabel,source:Q}}async function q0($,Q){let K=await c($);for(let q of Q){if(q.name===$.providerName)continue;let Z=m(q.global),V=H(Z,$.skillName);await P0(Z,{recursive:!0});try{if((await f0(V)).isSymbolicLink())await S(V);else{E(`install: skipping ${V} — existing non-symlink directory`);continue}}catch{}let X=h0(Z,$.targetDir);await k0(X,V,"dir"),E(`install: symlinked ${V} -> ${X}`)}return K.provider=`All (${Q.map((q)=>q.label).join(", ")})`,K}async function k($){try{await S($,{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"),process.stdin.pause(),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 V0($,Q,K,q,Z,V){let X=m(Z.global),z=H(X,q);return{source:$,tempDir:Q,sourceDir:K,targetDir:z,skillName:q,force:V,providerName:Z.name,providerLabel:Z.label}}async function X0($,Q){try{if(await u($),E(`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;E(`install: target ${$} — no conflict`)}}import{readFile as n0}from"fs/promises";import{join as t0}from"path";var Y0=500;function l0($){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 z0($){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=t0($.path,"SKILL.md"),Z=await n0(q,"utf-8");if(!l0(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>Y0)Q.push({category:"high-file-count",message:`Skill has ${K} files (threshold: ${Y0})`});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 i0,writeFile as s0,access as a0}from"fs/promises";import{join as e0}from"path";function r0($){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 U0($,Q){await i0(Q,{recursive:!0});let K=e0(Q,"SKILL.md"),q=r0($);await s0(K,q,"utf-8")}async function W0($){try{return await a0($),!0}catch{return!1}}import{readdir as $1,stat as Q1}from"fs/promises";import{join as Z1}from"path";async function K1($){let Q=0;try{let q=(await $1($,{recursive:!0})).map(async(V)=>{try{let X=await Q1(Z1($,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 G0($,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 W=await K1(J.path);return Z[J.path]=W,W}),z=(await Promise.all(V)).reduce((J,W)=>J+W,0);return{totalSkills:$.length,byProvider:K,byScope:q,totalDiskBytes:z,perSkillDiskBytes:Z,duplicateGroups:Q.duplicateGroups.length,duplicateInstances:Q.totalDuplicateInstances}}function q1($){if($<1024)return`${$} B`;if($<1048576)return`${($/1024).toFixed(1)} KB`;if($<1073741824)return`${($/1048576).toFixed(1)} MB`;return`${($/1073741824).toFixed(1)} GB`}function B0($){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",q1($.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 V1,lstat as X1,readFile as Y1,rm as z1,symlink as J1}from"fs/promises";import{join as M0}from"path";async function j0($){let Q;try{Q=await X1($)}catch{throw Error(`Path does not exist: ${$}`)}if(!Q.isDirectory())throw Error(`Path is not a directory: ${$}`);let K=M0($,"SKILL.md"),q;try{q=await Y1(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 h($,Q,K,q){let Z=M0(Q,K),V=!1;try{await V1(Z),V=!0}catch{}if(V){if(!q)throw Error(`Target already exists: ${Z}. Use --force to overwrite.`);await z1(Z,{recursive:!0,force:!0})}await J1($,Z,"dir")}function U1($){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 j(`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 j(`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("-"))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(Y.red(`Error: ${$}`))}function W1(){console.log(`${Y.blueBold("agent-skill-manager")} (${Y.bold("asm")}) ${l}
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 G1(){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 B1(){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 M1(){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 j1(){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 O1(){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 _1(){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 x0($){for(let Q of $)Q.warnings=await z0(Q)}async function F1($){if($.flags.help){G1();return}let Q=await F(),K=await R(Q,$.flags.scope);await x0(K);let q=g(K,$.flags.sort);if($.flags.json)console.log(y(q));else{let Z=n(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 A1($){if($.flags.help){B1();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 F(),q=await R(K,$.flags.scope),Z=A0(q,Q),V=g(Z,$.flags.sort);if($.flags.json)console.log(y(V));else console.log(n(V))}async function E1($){if($.flags.help){M1();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 F(),Z=(await R(K,$.flags.scope)).filter((V)=>V.dirName===Q);if(Z.length===0)j(`Skill "${Q}" not found.`),process.exit(1);if(await x0(Z),$.flags.json)console.log(y(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 H0(Z[V]))}}async function L1($){if($.flags.help){j1();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 F(),q=await R(K,$.flags.scope),Z=L0(Q,q,K),V=await T0(Z);if(V.length===0)j(`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)j("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 w();if(z.toLowerCase()!=="y"&&z.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}let X=await o(Z);for(let z of X)console.error(z);console.error(Y.green(`
124
- Done.`))}function w(){return new Promise(($)=>{let Q="",K=!1;function q(){process.stdin.removeListener("data",V),process.stdin.removeListener("end",X),process.stdin.pause(),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 T1($){if($.flags.help){O1();return}let Q=$.subcommand??"duplicates";if(Q!=="duplicates")j(`Unknown audit subcommand: "${Q}". Use: duplicates`),process.exit(2);let K=await F(),q=await R(K,"both"),Z=t(q);if($.flags.json){console.log(R0(Z));return}if(console.log(C0(Z)),$.flags.yes&&Z.duplicateGroups.length>0){console.error(Y.bold(`
126
- Auto-removing duplicates...`));for(let V of Z.duplicateGroups){let X=I0(V.instances);for(let z=1;z<X.length;z++){let J=X[z],W=E0(J,K),M=await o(W);for(let G of M)console.error(G)}}console.error(Y.green(`
127
- Done.`))}}async function H1($){if($.flags.help){_1();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 F();console.log(y(K));break}case"path":{console.log(p());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(`${Y.bold("Reset config to defaults?")} [y/N] `);let q=await w();if(q.toLowerCase()!=="y"&&q.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}let K=_0();await F0(K),console.error(Y.green("Config reset to defaults."));break}case"edit":{let K=process.env.VISUAL||process.env.EDITOR||"vi",q=p();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:j(`Unknown config subcommand: "${Q}". Use: show, path, reset, or edit.`),process.exit(2)}}function I1(){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,67 +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 d($,Q,K,q,Z,V,X,z,J,W){let M=await f(Z),G=W!==void 0,B=await K0(Z),_=Z===q?null:Z.split("/").pop(),U=V||_||K.repo,A=D(U),I=V0(K,q,Z,A,z,$.flags.force);if(await X0(I.targetDir,I.force),G){let O=`[${W.index}/${W.total}]`,x=B.length>0?` ${Y.yellow(`(${B.length} warning${B.length>1?"s":""})`)}`:"";console.error(`${Y.dim(O)} ${Y.bold(M.name)} v${M.version}${x}`)}else{if(console.error(`Found skill: ${M.name} v${M.version}`),console.error(`
160
- ${Y.bold("Install preview:")}`),console.error(` Name: ${M.name}`),console.error(` Version: ${M.version}`),M.description)console.error(` Description: ${M.description}`);if(console.error(` Source: ${Q}`),J)console.error(` Provider: All (${J.map((O)=>O.label).join(", ")})`),console.error(` Primary: ${z.label} (${z.name})`),console.error(` Symlinks: ${J.filter((O)=>O.name!==z.name).map((O)=>O.label).join(", ")}`);else console.error(` Provider: ${z.label} (${z.name})`);if(console.error(` Target: ${I.targetDir}`),B.length>0){console.error(`
161
- ${Y.yellow(Y.bold("Security warnings:"))}`);let O=new Map;for(let x of B){let C=O.get(x.category)||[];C.push(x),O.set(x.category,C)}for(let[x,C]of O){console.error(`
162
- ${Y.yellow(`[${x}]`)} (${C.length} match${C.length>1?"es":""})`);for(let v of C.slice(0,5))console.error(` ${Y.dim(v.file)}:${v.line} -- ${v.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(`
163
- ${Y.bold("Proceed with installation?")} [y/N] `);let O=await w();if(O.toLowerCase()!=="y"&&O.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}if(!G)console.error(`
164
- Installing to ${I.targetDir}...`);if(J)return await q0(I,J);return await c(I)}async function C1($){if($.flags.help){I1();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)k(K).finally(()=>process.exit(1));else process.exit(1)};process.on("SIGINT",q),process.on("SIGTERM",q);try{let Z=r(Q);console.error(`Parsing source: ${Q}`),await $0(),console.error(`Cloning ${Z.cloneUrl}${Z.ref?` (ref: ${Z.ref})`:""}...`),K=await Q0(Z);let V=await F(),{provider:X,allProviders:z}=await P(V,$.flags.provider,!!process.stdin.isTTY),{join:J}=await import("path"),W=[];if($.flags.path){let M=J(K,$.flags.path);try{await f(M)}catch{throw Error(`No SKILL.md found at path "${$.flags.path}" in the repository.`)}let G=await d($,Q,Z,K,M,$.flags.name,V,X,z);W.push(G)}else{let M=!1;try{await f(K),M=!0}catch{}if(M){let G=await d($,Q,Z,K,K,$.flags.name,V,X,z);W.push(G)}else{console.error("No SKILL.md at repository root. Scanning for skills...");let G=await Z0(K);if(G.length===0)throw Error("No skills found in this repository. Skills must have a SKILL.md file.");console.error(`Found ${G.length} skill(s):
165
- `);for(let U=0;U<G.length;U++)if(console.error(` ${Y.bold(`${U+1})`)} ${G[U].name} v${G[U].version} ${Y.dim(`(${G[U].relPath})`)}`),G[U].description)console.error(` ${G[U].description}`);let B;if($.flags.all){if(B=G.map((U)=>U.relPath),console.error(`
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(`
166
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(`
167
- ${Y.bold(`Install all ${B.length} skills?`)} [y/N] `);let U=await w();if(U.toLowerCase()!=="y"&&U.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}else if(process.stdin.isTTY){process.stderr.write(`
168
- Enter skill number (or "all"): `);let U=await w();if(U.toLowerCase()==="all")B=G.map((A)=>A.relPath);else{let A=parseInt(U,10)-1;if(isNaN(A)||A<0||A>=G.length)throw Error("Invalid selection. Aborting.");B=[G[A].relPath]}}else j(`Repository contains ${G.length} skills. Use --path <subdir> to pick one or --all to install all.
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
- ${G.map((U)=>` --path ${U.relPath}`).join(`
213
+ ${M.map((G)=>` --path ${G.relPath}`).join(`
171
214
  `)}`),process.exit(2);if(B.length>1){if(console.error(`
172
- ${Y.bold("Install settings:")}`),console.error(` Source: ${Q}`),z)console.error(` Provider: All (${z.map((U)=>U.label).join(", ")})`),console.error(` Primary: ${X.label} (${X.name})`),console.error(` Symlinks: ${z.filter((U)=>U.name!==X.name).map((U)=>U.label).join(", ")}`);else console.error(` Provider: ${X.label} (${X.name})`);console.error("")}let _=[];for(let U=0;U<B.length;U++){let A=B[U],I=J(K,A);try{let O=await d($,Q,Z,K,I,B.length===1?$.flags.name:null,V,X,z,B.length>1?{index:U+1,total:B.length}:void 0);W.push(O)}catch(O){if(_.push(A),console.error(Y.red(` x Failed: ${A} -- ${O.message}`)),B.length===1)throw O}}if(B.length>1&&_.length>0){console.error(`
173
- ${Y.yellow(`${_.length} skill(s) failed to install:`)}`);for(let U of _)console.error(` - ${U}`)}}}if(process.removeListener("SIGINT",q),process.removeListener("SIGTERM",q),$.flags.json)console.log(JSON.stringify(W.length===1?W[0]:W,null,2));else if(W.length===1)console.error(Y.green(`
174
- Done! Installed "${W[0].name}" to ${W[0].path}`));else console.error(`
175
- ${Y.green(`Done! Installed ${W.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 k(K)}}function R1(){console.log(`${Y.bold("Usage:")} asm export [options]
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]
176
219
 
177
- Export skill inventory as a portable JSON manifest.
220
+ Export skill inventory as a portable JSON manifest. Useful for backup,
221
+ sharing, or scripting.
178
222
 
179
- ${Y.bold("Options:")}
223
+ ${X.bold("Options:")}
180
224
  -s, --scope <s> Filter: global, project, or both (default: both)
181
225
  --no-color Disable ANSI colors
182
- -V, --verbose Show debug output`)}async function x1($){if($.flags.help){R1();return}let Q=await F(),K=await R(Q,$.flags.scope),q=J0(K);console.log(JSON.stringify(q,null,2))}function w1(){console.log(`${Y.bold("Usage:")} asm init <name> [options]
226
+ -V, --verbose Show debug output
183
227
 
184
- 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]
185
232
 
186
- ${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:")}
187
237
  -p, --provider <name> Target provider (claude, codex, openclaw, agents)
188
238
  --path <dir> Scaffold in specified directory instead of provider path
189
239
  -f, --force Overwrite if skill already exists
190
240
  --no-color Disable ANSI colors
191
- -V, --verbose Show debug output`)}async function y1($){if($.flags.help){w1();return}let Q=$.subcommand;if(!Q)j("Missing required argument: <name>"),console.error('Run "asm init --help" for usage.'),process.exit(2);let K=D(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((W)=>W.name===V.name).global);q=X(J,K)}if(await W0(q)){if(!$.flags.force){if(!process.stdin.isTTY)j(`Directory already exists: ${q}. Use --force to overwrite.`),process.exit(2);process.stderr.write(`${Y.yellow(`Directory already exists: ${q}`)}
192
- ${Y.bold("Overwrite?")} [y/N] `);let Z=await w();if(Z.toLowerCase()!=="y"&&Z.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}await U0(K,q),console.error(Y.green(`Done! Created skill "${K}" at ${q}`))}function N1(){console.log(`${Y.bold("Usage:")} asm stats [options]
241
+ -V, --verbose Show debug output
193
242
 
194
- 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]
195
248
 
196
- ${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:")}
197
253
  --json Output as JSON
198
254
  -s, --scope <s> Filter: global, project, or both (default: both)
199
255
  --no-color Disable ANSI colors
200
- -V, --verbose Show debug output`)}async function S1($){if($.flags.help){N1();return}let Q=await F(),K=await R(Q,$.flags.scope);if(K.length===0){console.log("No skills found.");return}let q=t(K),Z=await G0(K,q);if($.flags.json)console.log(y(Z));else console.log(B0(Z))}function b1(){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]
201
262
 
202
- 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.
203
265
 
204
- ${Y.bold("Options:")}
266
+ ${X.bold("Options:")}
205
267
  -p, --provider <name> Target provider (claude, codex, openclaw, agents)
206
268
  --name <name> Override symlink name (default: directory basename)
207
269
  -f, --force Overwrite if target already exists
208
270
  --json Output as JSON
209
271
  --no-color Disable ANSI colors
210
- -V, --verbose Show debug output`)}async function D1($){if($.flags.help){b1();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),V=await j0(Z),X=$.flags.name?D($.flags.name):q(Z),z=await F(),{provider:J}=await P(z,$.flags.provider,!!process.stdin.isTTY),{resolveProviderPath:W}=await import("./chunk-zh7g5bam.js"),M=W(z.providers.find((_)=>_.name===J.name).global),{join:G}=await import("path"),B=G(M,X);if(!$.flags.force){let _=!1;try{let{access:U}=await import("fs/promises");await U(B),_=!0}catch{}if(_){if(!process.stdin.isTTY)j(`Target already exists: ${B}. Use --force to overwrite.`),process.exit(2);process.stderr.write(`${Y.yellow(`Target already exists: ${B}`)}
211
- ${Y.bold("Overwrite?")} [y/N] `);let U=await w();if(U.toLowerCase()!=="y"&&U.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0);await h(Z,M,X,!0)}else await h(Z,M,X,!1)}else await h(Z,M,X,!0);if($.flags.json)console.log(y({success:!0,name:X,symlinkPath:B,targetPath:Z}));else console.error(Y.green(`Done! Linked "${X}" -> ${Z}`)),console.error(` Symlink: ${B}`),console.error(Y.dim(` If you move or delete the source, run "asm uninstall ${X}" to clean up.`))}async function w0($){let Q=U1($);if(Q.flags.noColor)globalThis.__CLI_NO_COLOR=!0;if(Q.flags.verbose)O0(!0);if(Q.flags.version){console.log(`asm ${l}`);return}if(!Q.command&&Q.flags.help){W1();return}if(!Q.command)return;switch(Q.command){case"list":await F1(Q);break;case"search":await A1(Q);break;case"inspect":await E1(Q);break;case"uninstall":await L1(Q);break;case"audit":await T1(Q);break;case"install":await C1(Q);break;case"config":await H1(Q);break;case"export":await x1(Q);break;case"init":await y1(Q);break;case"stats":await S1(Q);break;case"link":await D1(Q);break;default:j(`Unknown command: "${Q.command}"`),console.error('Run "asm --help" for usage.'),process.exit(2)}}function y0($){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(y0(process.argv))await w0(process.argv);else await import("./chunk-9pkjdwkv.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};