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.
- package/dist/agent-skill-manager.js +154 -87
- package/dist/chunk-4kqabmv7.js +9 -0
- package/dist/chunk-d474xtc4.js +90 -0
- package/dist/chunk-esvwvw47.js +12 -0
- package/dist/chunk-k7hzkvr5.js +12 -0
- package/dist/chunk-menf8e4q.js +90 -0
- package/dist/chunk-nyqzfjgs.js +12 -0
- package/dist/chunk-t7727aqn.js +3 -0
- package/dist/chunk-v02nhegz.js +90 -0
- package/dist/chunk-xrprkm42.js +90 -0
- package/package.json +1 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{a as N,c as
|
|
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,
|
|
7
|
-
`);for(let
|
|
8
|
-
Select a provider:`);for(let
|
|
9
|
-
Enter number: `);let Z=await new Promise((
|
|
10
|
-
`))process.stdin.removeAllListeners("data"),process.stdin.pause(),
|
|
11
|
-
Use --force to overwrite.`)}catch(K){if(K.message?.includes("--force"))throw K;
|
|
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
|
|
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
|
|
31
|
-
`)}import{access as
|
|
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
|
-
${
|
|
35
|
+
${X.bold("Usage:")}
|
|
36
36
|
asm Launch interactive TUI
|
|
37
37
|
asm <command> [options] Run a CLI command
|
|
38
38
|
|
|
39
|
-
${
|
|
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
|
-
${
|
|
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
|
|
64
|
-
|
|
65
|
-
List all discovered skills.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
--
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
--
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
${
|
|
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
|
|
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
|
-
${
|
|
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
|
|
126
|
+
-V, --verbose Show debug output
|
|
98
127
|
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
${
|
|
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
|
|
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
|
-
${
|
|
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
|
-
${
|
|
119
|
-
-V, --verbose Show debug output
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
${
|
|
124
|
-
|
|
125
|
-
`))
|
|
126
|
-
|
|
127
|
-
Done.`))}
|
|
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
|
-
${
|
|
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
|
-
${
|
|
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
|
-
${
|
|
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 ${
|
|
195
|
+
asm install github:user/my-skill -p all ${X.dim("(install to all providers)")}
|
|
153
196
|
|
|
154
|
-
${
|
|
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 ${
|
|
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 ${
|
|
160
|
-
${
|
|
161
|
-
${
|
|
162
|
-
${
|
|
163
|
-
${
|
|
164
|
-
Installing to ${I.targetDir}...`);if(
|
|
165
|
-
`);for(let
|
|
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
|
-
${
|
|
168
|
-
Enter skill number (or "all"): `);let
|
|
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
|
-
${
|
|
213
|
+
${M.map((G)=>` --path ${G.relPath}`).join(`
|
|
171
214
|
`)}`),process.exit(2);if(B.length>1){if(console.error(`
|
|
172
|
-
${
|
|
173
|
-
${
|
|
174
|
-
Done! Installed "${
|
|
175
|
-
${
|
|
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
|
-
${
|
|
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
|
|
226
|
+
-V, --verbose Show debug output
|
|
183
227
|
|
|
184
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
${
|
|
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
|
|
211
|
-
|
|
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};
|