agent-skill-manager 1.4.0 → 1.5.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 +56 -48
- package/dist/chunk-5d41n7xa.js +90 -0
- package/dist/chunk-e2gf6qhq.js +8 -0
- package/dist/chunk-j1ngzqjc.js +8 -0
- package/dist/chunk-my862t5h.js +90 -0
- package/dist/chunk-pgv8xpxb.js +90 -0
- package/dist/chunk-qfn7hb5z.js +90 -0
- package/dist/chunk-s1gskd5a.js +8 -0
- package/dist/chunk-sx2p5bqv.js +8 -0
- package/package.json +1 -1
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{a as R,c as I,d as
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
`)
|
|
3
|
+
import{a as R,c as I,d as _0,e as d,f as F0,g as A0,h as p,i as E0,j as Y,k as g,l as T0,m as x,n as o,o as L0,q as H0,r as I0,s as n}from"./chunk-sx2p5bqv.js";import{A as F,B as O0,t as E,u as T,v as M0,w as A,x as j0,y as c,z as v}from"./chunk-zh7g5bam.js";import{execFile as w0}from"child_process";import{promisify as y0}from"util";import{mkdtemp as N0,readdir as l,readFile as N,rm as y,cp as S0,access as h,stat as i,lstat as b0,symlink as D0,mkdir as P0}from"fs/promises";import{join as L,relative as f0}from"path";import{tmpdir as k0}from"os";var s=y0(w0),h0=/^[a-zA-Z0-9_-]+$/,v0=/^[a-zA-Z0-9._-]+$/,u0=/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/,t=128,m0=/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\/tree\/(.+))?\/?$/;function a($){let Q=m0.exec($);if(Q){let[,j,W,O]=Q,B=W.endsWith(".git")?W.slice(0,-4):W;$=`github:${j}/${B}${O?`#${O}`:""}`}if(!$.startsWith("github:"))throw Error(`Invalid source format. Got: "${$}"
|
|
4
|
+
Supported formats:
|
|
5
|
+
github:owner/repo[#ref]
|
|
6
|
+
https://github.com/owner/repo`);let K=$.slice(7),q=K.indexOf("#"),Z,V=null;if(q!==-1){if(Z=K.slice(0,q),V=K.slice(q+1),!V)throw Error("Invalid source: ref cannot be empty after #")}else Z=K;let X=Z.indexOf("/");if(X===-1)throw Error(`Invalid source: format must be github:owner/repo. Got: "${$}"`);let z=Z.slice(0,X),J=Z.slice(X+1);if(!z)throw Error("Invalid source: owner cannot be empty");if(!J)throw Error("Invalid source: repo cannot be empty");if(!h0.test(z))throw Error(`Invalid source: owner contains invalid characters: "${z}". Allowed: [a-zA-Z0-9_-]`);if(!v0.test(J))throw Error(`Invalid source: repo contains invalid characters: "${J}". Allowed: [a-zA-Z0-9._-]`);let U={owner:z,repo:J,ref:V,cloneUrl:`https://github.com/${z}/${J}.git`};return A(`install: parsed source → owner=${z} repo=${J} ref=${V}`),U}function S($){if(!$)throw Error("Invalid skill name: name cannot be empty");if($.includes("\x00"))throw Error("Invalid skill name: contains unsafe characters (null byte)");if($.includes(".."))throw Error("Invalid skill name: contains unsafe characters (..)");if($.includes("/")||$.includes("\\"))throw Error("Invalid skill name: contains unsafe characters (path separator)");if($.startsWith("."))throw Error("Invalid skill name: must not start with a dot");if($.length>t)throw Error(`Invalid skill name: exceeds maximum length of ${t} characters`);if(!u0.test($))throw Error(`Invalid skill name: "${$}" does not match allowed pattern [a-zA-Z0-9][a-zA-Z0-9._-]*`);return $}async function e(){try{await s("git",["--version"]),A("install: git available")}catch{throw Error("git is required for installing skills. Install git from https://git-scm.com")}}async function r($){A(`install: cloning ${$.cloneUrl}${$.ref?` (ref: ${$.ref})`:""}`);let Q=await N0(L(k0(),"asm-install-")),K=["clone","--depth","1"];if($.ref)K.push("--branch",$.ref);K.push($.cloneUrl,Q);try{await s("git",K,{timeout:60000})}catch(q){await D(Q);let Z=q.killed?"Clone timed out after 60 seconds":`Clone failed: ${q.stderr||q.message}`;throw Error(Z)}return Q}async function b($){let Q=L($,"SKILL.md"),K;try{K=await N(Q,"utf-8")}catch{throw Error("Not a valid skill: SKILL.md not found in repository root")}let q=R(K),Z=$.split("/").pop()||"unknown",V=q.name||Z,X=q.version||"0.0.0";return A(`install: validated skill "${V}" v${X}`),{name:V,version:X,description:(q.description||"").replace(/\s*\n\s*/g," ").trim()}}async function $0($,Q=3){let K=[];async function q(Z,V,X){let z;try{z=await l(Z)}catch{return}for(let J of z){if(J===".git"||J==="node_modules")continue;let U=L(Z,J);try{if(!(await i(U)).isDirectory())continue}catch{continue}let j=V?`${V}/${J}`:J,W=X+1,O=L(U,"SKILL.md");try{let B=await N(O,"utf-8"),G=R(B);K.push({relPath:j,name:G.name||J,version:G.version||"0.0.0",description:(G.description||"").replace(/\s*\n\s*/g," ").trim()})}catch{if(W<Q)await q(U,j,W)}}}return await q($,"",0),K.sort((Z,V)=>Z.name.localeCompare(V.name)),K}var c0=[{category:"Shell commands",pattern:/\b(bash|sh\s+-c)\b/},{category:"Shell commands",pattern:/\bexec\(/},{category:"Shell commands",pattern:/\bchild_process\b/},{category:"Shell commands",pattern:/\bBun\.spawn\b/},{category:"Code execution",pattern:/\beval\(/},{category:"Code execution",pattern:/\bFunction\(/},{category:"Code execution",pattern:/\bnew\s+Function\b/},{category:"Credentials",pattern:/\b(API_KEY|SECRET|TOKEN|PASSWORD)\s*[=:]/},{category:"External URLs",pattern:/https?:\/\//}],d0=new Set([".png",".jpg",".jpeg",".gif",".ico",".bmp",".webp",".mp3",".mp4",".wav",".avi",".mov",".zip",".tar",".gz",".bz2",".7z",".exe",".dll",".so",".dylib",".woff",".woff2",".ttf",".eot",".pdf",".doc",".docx"]);async function p0($){let Q=[];async function K(q,Z){let V;try{V=await l(q)}catch{return}for(let X of V){if(X===".git")continue;if(X==="node_modules")continue;let z=L(q,X),J=Z?`${Z}/${X}`:X;try{let U=await i(z);if(U.isDirectory())await K(z,J);else if(U.isFile()){let j=X.includes(".")?`.${X.split(".").pop().toLowerCase()}`:"";if(d0.has(j))continue;if(U.size>524288)continue;try{let W=await N(z,"utf-8");Q.push({relPath:J,content:W})}catch{}}}catch{continue}}}return await K($,""),Q}async function Q0($){let Q=[],K=await p0($);for(let{relPath:q,content:Z}of K){let V=Z.split(`
|
|
7
|
+
`);for(let X=0;X<V.length;X++)for(let{category:z,pattern:J}of c0)if(J.test(V[X])){let U=V[X].trim();Q.push({category:z,file:q,line:X+1,match:U.length>100?U.slice(0,100)+"…":U})}}return Q}async function u($){let Q=`github:${$.source.owner}/${$.source.repo}${$.source.ref?`#${$.source.ref}`:""}`;if($.force)try{await h($.targetDir),await y($.targetDir,{recursive:!0,force:!0})}catch{}let K=$.sourceDir;try{await S0(K,$.targetDir,{recursive:!0})}catch(z){throw Error(`Failed to install: ${z.message}`)}let q=L($.targetDir,".git");try{await y(q,{recursive:!0,force:!0})}catch{}A(`install: copied files to ${$.targetDir}`);let Z=L($.targetDir,"SKILL.md");try{await h(Z)}catch{throw Error("Installation verification failed: SKILL.md not found at target")}let V=await N(Z,"utf-8"),X=R(V);return{success:!0,path:$.targetDir,name:X.name||$.skillName,version:X.version||"0.0.0",provider:$.providerLabel,source:Q}}async function Z0($,Q){let K=await u($);for(let q of Q){if(q.name===$.providerName)continue;let Z=v(q.global),V=L(Z,$.skillName);await P0(Z,{recursive:!0});try{if((await b0(V)).isSymbolicLink())await y(V);else{A(`install: skipping ${V} — existing non-symlink directory`);continue}}catch{}let X=f0(Z,$.targetDir);await D0(X,V,"dir"),A(`install: symlinked ${V} → ${X}`)}return K.provider=`All (${Q.map((q)=>q.label).join(", ")})`,K}async function D($){try{await y($,{recursive:!0,force:!0})}catch{}}async function P($,Q,K){let q=$.providers.filter((X)=>X.enabled);if(q.length===0)throw Error("No providers are enabled. Enable a provider in your config.");if(Q==="all")return{provider:q.find((z)=>z.name==="agents")||q[0],allProviders:q};if(Q){let X=$.providers.find((z)=>z.name===Q);if(!X){let z=$.providers.map((J)=>J.name).join(", ");throw Error(`Unknown provider: "${Q}". Valid providers: ${z}, all`)}if(!X.enabled)throw Error(`Provider "${Q}" is disabled. Enable it in your config or choose another provider.`);return{provider:X,allProviders:null}}if(q.length===1)return{provider:q[0],allProviders:null};if(!K){let X=q.map((z)=>z.name).join(", ");throw Error(`--provider is required in non-interactive mode. Available: ${X}, all`)}console.error(`
|
|
8
|
+
Select a provider:`);for(let X=0;X<q.length;X++)console.error(` ${X+1}) ${q[X].label} (${q[X].name})`);console.error(` ${q.length+1}) All providers (shared .agents/skills/ + symlinks)`),process.stderr.write(`
|
|
9
|
+
Enter number: `);let Z=await new Promise((X)=>{let z="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",(J)=>{if(z+=J,z.includes(`
|
|
10
|
+
`))process.stdin.removeAllListeners("data"),X(z.trim())}),process.stdin.resume()}),V=parseInt(Z,10)-1;if(V===q.length)return{provider:q.find((z)=>z.name==="agents")||q[0],allProviders:q};if(isNaN(V)||V<0||V>=q.length)throw Error("Invalid selection. Aborting.");return{provider:q[V],allProviders:null}}function K0($,Q,K,q,Z,V){let X=v(Z.global),z=L(X,q);return{source:$,tempDir:Q,sourceDir:K,targetDir:z,skillName:q,force:V,providerName:Z.name,providerLabel:Z.label}}async function q0($,Q){try{if(await h($),A(`install: target ${$} — conflict (exists)${Q?", force overwrite":""}`),!Q)throw Error(`Skill already exists at: ${$}
|
|
11
|
+
Use --force to overwrite.`)}catch(K){if(K.message?.includes("--force"))throw K;A(`install: target ${$} — no conflict`)}}import{readFile as g0}from"fs/promises";import{join as o0}from"path";var V0=500;function n0($){let Q=$.split(`
|
|
12
|
+
`),K=!1,q=!1;for(let Z of Q){if(Z.trim()==="---")if(!K){K=!0;continue}else{q=!0;continue}if(q&&Z.trim().length>0)return!0}return!1}async function X0($){let Q=[];if(!$.description||$.description.trim()==="")Q.push({category:"missing-description",message:"Skill has no description in SKILL.md frontmatter"});if(!$.version||$.version==="0.0.0")Q.push({category:"missing-version",message:"Skill has no version (or default 0.0.0) in SKILL.md frontmatter"});try{let q=o0($.path,"SKILL.md"),Z=await g0(q,"utf-8");if(!n0(Z))Q.push({category:"empty-body",message:"SKILL.md contains only frontmatter with no body content"})}catch{}let K=$.fileCount;if(K!==void 0&&K>V0)Q.push({category:"high-file-count",message:`Skill has ${K} files (threshold: ${V0})`});return Q}function Y0($){let Q=$.map((K)=>({name:K.name,version:K.version,dirName:K.dirName,provider:K.provider,scope:K.scope,path:K.path,isSymlink:K.isSymlink,symlinkTarget:K.symlinkTarget}));return{version:1,exportedAt:new Date().toISOString(),skills:Q}}import{mkdir as t0,writeFile as l0,access as i0}from"fs/promises";import{join as s0}from"path";function a0($){return`---
|
|
11
13
|
name: ${$}
|
|
12
14
|
version: 0.1.0
|
|
13
15
|
description: ""
|
|
@@ -25,8 +27,8 @@ as instructions for when and how to use this skill.
|
|
|
25
27
|
## Instructions
|
|
26
28
|
|
|
27
29
|
- Step-by-step instructions for the agent
|
|
28
|
-
`}async function
|
|
29
|
-
`)}import{access as
|
|
30
|
+
`}async function z0($,Q){await t0(Q,{recursive:!0});let K=s0(Q,"SKILL.md"),q=a0($);await l0(K,q,"utf-8")}async function J0($){try{return await i0($),!0}catch{return!1}}import{readdir as e0,stat as r0}from"fs/promises";import{join as $1}from"path";async function Q1($){let Q=0;try{let q=(await e0($,{recursive:!0})).map(async(V)=>{try{let X=await r0($1($,V));if(X.isFile())return X.size}catch{}return 0});Q=(await Promise.all(q)).reduce((V,X)=>V+X,0)}catch{}return Q}async function U0($,Q){let K={},q={global:0,project:0},Z={},V=$.map(async(J)=>{K[J.provider]=(K[J.provider]||0)+1,q[J.scope]++;let U=await Q1(J.path);return Z[J.path]=U,U}),z=(await Promise.all(V)).reduce((J,U)=>J+U,0);return{totalSkills:$.length,byProvider:K,byScope:q,totalDiskBytes:z,perSkillDiskBytes:Z,duplicateGroups:Q.duplicateGroups.length,duplicateInstances:Q.totalDuplicateInstances}}function Z1($){if($<1024)return`${$} B`;if($<1048576)return`${($/1024).toFixed(1)} KB`;if($<1073741824)return`${($/1048576).toFixed(1)} MB`;return`${($/1073741824).toFixed(1)} GB`}function W0($){let Q=[],K=(q,Z)=>`${Y.bold(q+":")} ${Z}`;Q.push(Y.bold("Skill Statistics")),Q.push(""),Q.push(K("Total Skills",String($.totalSkills))),Q.push(K("Disk Usage",Z1($.totalDiskBytes))),Q.push(""),Q.push(Y.bold("By Provider:"));for(let[q,Z]of Object.entries($.byProvider).sort((V,X)=>X[1]-V[1]))Q.push(` ${q}: ${Z}`);if(Q.push(""),Q.push(Y.bold("By Scope:")),Q.push(` global: ${$.byScope.global}`),Q.push(` project: ${$.byScope.project}`),Q.push(""),Q.push(Y.bold("Duplicates:")),$.duplicateGroups>0)Q.push(` ${Y.yellow(`${$.duplicateGroups} group(s), ${$.duplicateInstances} total instance(s)`)}`);else Q.push(` ${Y.green("None")}`);return Q.join(`
|
|
31
|
+
`)}import{access as K1,lstat as q1,readFile as V1,rm as X1,symlink as Y1}from"fs/promises";import{join as B0}from"path";async function G0($){let Q;try{Q=await q1($)}catch{throw Error(`Path does not exist: ${$}`)}if(!Q.isDirectory())throw Error(`Path is not a directory: ${$}`);let K=B0($,"SKILL.md"),q;try{q=await V1(K,"utf-8")}catch{throw Error(`No SKILL.md found in ${$}`)}let Z=R(q);if(!Z.name)throw Error(`Invalid SKILL.md in ${$}: missing "name" in frontmatter`);return{name:Z.name,version:Z.version||"0.0.0"}}async function f($,Q,K,q){let Z=B0(Q,K),V=!1;try{await K1(Z),V=!0}catch{}if(V){if(!q)throw Error(`Target already exists: ${Z}. Use --force to overwrite.`);await X1(Z,{recursive:!0,force:!0})}await Y1($,Z,"dir")}function z1($){let Q=$.slice(2),K={command:null,subcommand:null,positional:[],flags:{help:!1,version:!1,json:!1,yes:!1,noColor:!1,scope:"both",sort:"name",provider:null,name:null,force:!1,path:null,all:!1,verbose:!1}},q=0;while(q<Q.length){let Z=Q[q];if(Z==="--help"||Z==="-h")K.flags.help=!0;else if(Z==="--version"||Z==="-v")K.flags.version=!0;else if(Z==="--json")K.flags.json=!0;else if(Z==="--yes"||Z==="-y")K.flags.yes=!0;else if(Z==="--no-color")K.flags.noColor=!0;else if(Z==="--scope"||Z==="-s"){q++;let V=Q[q];if(V==="global"||V==="project"||V==="both")K.flags.scope=V;else M(`Invalid scope: "${V}". Must be global, project, or both.`),process.exit(2)}else if(Z==="--sort"){q++;let V=Q[q];if(V==="name"||V==="version"||V==="location")K.flags.sort=V;else M(`Invalid sort: "${V}". Must be name, version, or location.`),process.exit(2)}else if(Z==="--provider"||Z==="-p")q++,K.flags.provider=Q[q]||null;else if(Z==="--name")q++,K.flags.name=Q[q]||null;else if(Z==="--force"||Z==="-f")K.flags.force=!0;else if(Z==="--path")q++,K.flags.path=Q[q]||null;else if(Z==="--all")K.flags.all=!0;else if(Z==="--verbose"||Z==="-V")K.flags.verbose=!0;else if(Z.startsWith("-"))M(`Unknown option: ${Z}`),console.error('Run "asm --help" for usage.'),process.exit(2);else if(!K.command)K.command=Z;else if(!K.subcommand)K.subcommand=Z;else K.positional.push(Z);q++}return K}function M($){console.error(Y.red(`Error: ${$}`))}function J1(){console.log(`${Y.blueBold("agent-skill-manager")} (${Y.bold("asm")}) ${n}
|
|
30
32
|
|
|
31
33
|
Interactive TUI and CLI for managing installed skills for AI coding agents.
|
|
32
34
|
|
|
@@ -58,7 +60,7 @@ ${Y.bold("Global Options:")}
|
|
|
58
60
|
--no-color Disable ANSI colors
|
|
59
61
|
--sort <field> Sort by: name, version, or location (default: name)
|
|
60
62
|
-y, --yes Skip confirmation prompts
|
|
61
|
-
-V, --verbose Show debug output`)}function
|
|
63
|
+
-V, --verbose Show debug output`)}function U1(){console.log(`${Y.bold("Usage:")} asm list [options]
|
|
62
64
|
|
|
63
65
|
List all discovered skills.
|
|
64
66
|
|
|
@@ -67,7 +69,7 @@ ${Y.bold("Options:")}
|
|
|
67
69
|
-s, --scope <s> Filter: global, project, or both (default: both)
|
|
68
70
|
--json Output as JSON array
|
|
69
71
|
--no-color Disable ANSI colors
|
|
70
|
-
-V, --verbose Show debug output`)}function
|
|
72
|
+
-V, --verbose Show debug output`)}function W1(){console.log(`${Y.bold("Usage:")} asm search <query> [options]
|
|
71
73
|
|
|
72
74
|
Search skills by name, description, or provider.
|
|
73
75
|
|
|
@@ -76,7 +78,7 @@ ${Y.bold("Options:")}
|
|
|
76
78
|
-s, --scope <s> Filter: global, project, or both (default: both)
|
|
77
79
|
--json Output as JSON array
|
|
78
80
|
--no-color Disable ANSI colors
|
|
79
|
-
-V, --verbose Show debug output`)}function
|
|
81
|
+
-V, --verbose Show debug output`)}function B1(){console.log(`${Y.bold("Usage:")} asm inspect <skill-name> [options]
|
|
80
82
|
|
|
81
83
|
Show detailed information for a skill. The <skill-name> is the directory name.
|
|
82
84
|
|
|
@@ -84,7 +86,7 @@ ${Y.bold("Options:")}
|
|
|
84
86
|
-s, --scope <s> Filter: global, project, or both (default: both)
|
|
85
87
|
--json Output as JSON object
|
|
86
88
|
--no-color Disable ANSI colors
|
|
87
|
-
-V, --verbose Show debug output`)}function
|
|
89
|
+
-V, --verbose Show debug output`)}function G1(){console.log(`${Y.bold("Usage:")} asm uninstall <skill-name> [options]
|
|
88
90
|
|
|
89
91
|
Remove a skill and its associated rule files.
|
|
90
92
|
|
|
@@ -92,7 +94,7 @@ ${Y.bold("Options:")}
|
|
|
92
94
|
-y, --yes Skip confirmation prompt
|
|
93
95
|
-s, --scope <s> Filter: global, project, or both (default: both)
|
|
94
96
|
--no-color Disable ANSI colors
|
|
95
|
-
-V, --verbose Show debug output`)}function
|
|
97
|
+
-V, --verbose Show debug output`)}function M1(){console.log(`${Y.bold("Usage:")} asm audit [subcommand] [options]
|
|
96
98
|
|
|
97
99
|
Detect and optionally remove duplicate skills.
|
|
98
100
|
|
|
@@ -103,7 +105,7 @@ ${Y.bold("Options:")}
|
|
|
103
105
|
--json Output as JSON
|
|
104
106
|
-y, --yes Auto-remove duplicates, keeping one instance per group
|
|
105
107
|
--no-color Disable ANSI colors
|
|
106
|
-
-V, --verbose Show debug output`)}function
|
|
108
|
+
-V, --verbose Show debug output`)}function j1(){console.log(`${Y.bold("Usage:")} asm config <subcommand>
|
|
107
109
|
|
|
108
110
|
Manage configuration.
|
|
109
111
|
|
|
@@ -114,24 +116,26 @@ ${Y.bold("Subcommands:")}
|
|
|
114
116
|
edit Open config in $EDITOR
|
|
115
117
|
|
|
116
118
|
${Y.bold("Options:")}
|
|
117
|
-
-V, --verbose Show debug output`)}async function
|
|
118
|
-
${Y.yellow(`⚠ ${V.length} skill${V.length===1?"":"s"} with warnings — use --json for details`)}`;console.log(Z)}}async function
|
|
119
|
+
-V, --verbose Show debug output`)}async function C0($){for(let Q of $)Q.warnings=await X0(Q)}async function O1($){if($.flags.help){U1();return}let Q=await F(),K=await I(Q,$.flags.scope);await C0(K);let q=d(K,$.flags.sort);if($.flags.json)console.log(x(q));else{let Z=g(q),V=q.filter((X)=>X.warnings&&X.warnings.length>0);if(V.length>0)Z+=`
|
|
120
|
+
${Y.yellow(`⚠ ${V.length} skill${V.length===1?"":"s"} with warnings — use --json for details`)}`;console.log(Z)}}async function _1($){if($.flags.help){W1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <query>"),console.error('Run "asm search --help" for usage.'),process.exit(2);let K=await F(),q=await I(K,$.flags.scope),Z=_0(q,Q),V=d(Z,$.flags.sort);if($.flags.json)console.log(x(V));else console.log(g(V))}async function F1($){if($.flags.help){B1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <skill-name>"),console.error('Run "asm inspect --help" for usage.'),process.exit(2);let K=await F(),Z=(await I(K,$.flags.scope)).filter((V)=>V.dirName===Q);if(Z.length===0)M(`Skill "${Q}" not found.`),process.exit(1);if(await C0(Z),$.flags.json)console.log(x(Z.length===1?Z[0]:Z));else for(let V=0;V<Z.length;V++){if(V>0)console.log(`
|
|
119
121
|
`+"─".repeat(40)+`
|
|
120
|
-
`);console.log(await
|
|
121
|
-
${Y.bold("Proceed with removal?")} [y/N] `);let
|
|
122
|
-
Done.`))}function
|
|
123
|
-
`))Z(Q.trim())}function X(){Z(Q.trim())}let
|
|
124
|
-
Auto-removing duplicates...`));for(let V of Z.duplicateGroups){let X=
|
|
125
|
-
Done.`))}}async function
|
|
122
|
+
`);console.log(await T0(Z[V]))}}async function A1($){if($.flags.help){G1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <skill-name>"),console.error('Run "asm uninstall --help" for usage.'),process.exit(2);let K=await F(),q=await I(K,$.flags.scope),Z=A0(Q,q,K),V=await E0(Z);if(V.length===0)M(`Skill "${Q}" not found or nothing to remove.`),process.exit(1);console.error(Y.bold("Removal plan:"));for(let z of V)console.error(` ${Y.red("•")} ${z}`);if(!$.flags.yes){if(!process.stdin.isTTY)M("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
|
|
123
|
+
${Y.bold("Proceed with removal?")} [y/N] `);let z=await C();if(z.toLowerCase()!=="y"&&z.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}let X=await p(Z);for(let z of X)console.error(z);console.error(Y.green(`
|
|
124
|
+
Done.`))}function C(){return new Promise(($)=>{let Q="",K=!1;function q(){process.stdin.removeListener("data",V),process.stdin.removeListener("end",X),clearTimeout(z)}function Z(J){if(K)return;K=!0,q(),$(J)}function V(J){if(Q+=J,Q.includes(`
|
|
125
|
+
`))Z(Q.trim())}function X(){Z(Q.trim())}let z=setTimeout(()=>{Z(Q.trim())},30000);process.stdin.setEncoding("utf-8"),process.stdin.on("data",V),process.stdin.on("end",X),process.stdin.resume()})}async function E1($){if($.flags.help){M1();return}let Q=$.subcommand??"duplicates";if(Q!=="duplicates")M(`Unknown audit subcommand: "${Q}". Use: duplicates`),process.exit(2);let K=await F(),q=await I(K,"both"),Z=o(q);if($.flags.json){console.log(I0(Z));return}if(console.log(H0(Z)),$.flags.yes&&Z.duplicateGroups.length>0){console.error(Y.bold(`
|
|
126
|
+
Auto-removing duplicates...`));for(let V of Z.duplicateGroups){let X=L0(V.instances);for(let z=1;z<X.length;z++){let J=X[z],U=F0(J,K),j=await p(U);for(let W of j)console.error(W)}}console.error(Y.green(`
|
|
127
|
+
Done.`))}}async function T1($){if($.flags.help){j1();return}let Q=$.subcommand;if(!Q)M("Missing subcommand. Use: show, path, reset, or edit."),console.error('Run "asm config --help" for usage.'),process.exit(2);switch(Q){case"show":{let K=await F();console.log(x(K));break}case"path":{console.log(c());break}case"reset":{if(!$.flags.yes){if(!process.stdin.isTTY)M("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`${Y.bold("Reset config to defaults?")} [y/N] `);let q=await C();if(q.toLowerCase()!=="y"&&q.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}let K=j0();await O0(K),console.error(Y.green("Config reset to defaults."));break}case"edit":{let K=process.env.VISUAL||process.env.EDITOR||"vi",q=c();await F();let{spawn:Z}=await import("child_process");await new Promise((V,X)=>{let z=Z(K,[q],{stdio:"inherit"});z.on("close",()=>V()),z.on("error",X)});break}default:M(`Unknown config subcommand: "${Q}". Use: show, path, reset, or edit.`),process.exit(2)}}function L1(){console.log(`${Y.bold("Usage:")} asm install <source> [options]
|
|
126
128
|
|
|
127
129
|
Install a skill from a GitHub repository.
|
|
128
130
|
|
|
129
131
|
${Y.bold("Source Format:")}
|
|
130
|
-
github:owner/repo
|
|
131
|
-
github:owner/repo#ref
|
|
132
|
+
github:owner/repo Install from default branch
|
|
133
|
+
github:owner/repo#ref Install from specific branch or tag
|
|
134
|
+
https://github.com/owner/repo Install via HTTPS URL
|
|
132
135
|
|
|
133
136
|
${Y.bold("Options:")}
|
|
134
|
-
-p, --provider <name> Target provider (claude, codex, openclaw, agents)
|
|
137
|
+
-p, --provider <name> Target provider (claude, codex, openclaw, agents, all)
|
|
138
|
+
Use "all" to install to all providers (shared + symlinks)
|
|
135
139
|
--name <name> Override skill directory name
|
|
136
140
|
--path <subdir> Install skill from a subdirectory of the repo
|
|
137
141
|
--all Install all skills found in the repo
|
|
@@ -144,33 +148,37 @@ ${Y.bold("Options:")}
|
|
|
144
148
|
${Y.bold("Single-skill repo:")}
|
|
145
149
|
asm install github:user/my-skill
|
|
146
150
|
asm install github:user/my-skill#v1.0.0 -p claude
|
|
151
|
+
asm install https://github.com/user/my-skill
|
|
152
|
+
asm install github:user/my-skill -p all ${Y.dim("(install to all providers)")}
|
|
147
153
|
|
|
148
154
|
${Y.bold("Multi-skill repo:")}
|
|
149
155
|
asm install github:user/skills --path skills/code-review
|
|
150
156
|
asm install github:user/skills --all -p claude -y
|
|
151
|
-
asm install github:user/skills
|
|
152
|
-
|
|
153
|
-
${Y.
|
|
154
|
-
|
|
155
|
-
${Y.bold("
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
Installing
|
|
159
|
-
${Y.bold(`
|
|
160
|
-
|
|
157
|
+
asm install github:user/skills --all -p all -y ${Y.dim("(all skills, all providers)")}
|
|
158
|
+
asm install https://github.com/user/skills --all
|
|
159
|
+
asm install github:user/skills ${Y.dim("(interactive picker)")}`)}async function m($,Q,K,q,Z,V,X,z,J){let U=await b(Z);console.error(`Found skill: ${U.name} v${U.version}`);let j=await Q0(Z),W=Z===q?null:Z.split("/").pop(),O=V||W||K.repo,B=S(O),G=K0(K,q,Z,B,z,$.flags.force);if(await q0(G.targetDir,G.force),console.error(`
|
|
160
|
+
${Y.bold("Install preview:")}`),console.error(` Name: ${U.name}`),console.error(` Version: ${U.version}`),console.error(` Description: ${U.description||"(none)"}`),console.error(` Source: ${Q}`),J)console.error(` Provider: All (${J.map((_)=>_.label).join(", ")})`),console.error(` Primary: ${z.label} (${z.name})`),console.error(` Symlinks: ${J.filter((_)=>_.name!==z.name).map((_)=>_.label).join(", ")}`);else console.error(` Provider: ${z.label} (${z.name})`);if(console.error(` Target: ${G.targetDir}`),j.length>0){console.error(`
|
|
161
|
+
${Y.yellow(Y.bold("Security warnings:"))}`);let _=new Map;for(let w of j){let H=_.get(w.category)||[];H.push(w),_.set(w.category,H)}for(let[w,H]of _){console.error(`
|
|
162
|
+
${Y.yellow(`[${w}]`)} (${H.length} match${H.length>1?"es":""})`);for(let k of H.slice(0,5))console.error(` ${Y.dim(k.file)}:${k.line} — ${k.match}`);if(H.length>5)console.error(` ... and ${H.length-5} more`)}}if(!$.flags.yes&&!$.flags.all){if(!process.stdin.isTTY)M("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
|
|
163
|
+
${Y.bold("Proceed with installation?")} [y/N] `);let _=await C();if(_.toLowerCase()!=="y"&&_.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}if(console.error(`
|
|
164
|
+
Installing to ${G.targetDir}...`),J)return await Z0(G,J);return await u(G)}async function H1($){if($.flags.help){L1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <source>"),console.error('Run "asm install --help" for usage.'),process.exit(2);let K=null,q=()=>{if(K)D(K).finally(()=>process.exit(1));else process.exit(1)};process.on("SIGINT",q),process.on("SIGTERM",q);try{let Z=a(Q);console.error(`Parsing source: ${Q}`),await e(),console.error(`Cloning ${Z.cloneUrl}${Z.ref?` (ref: ${Z.ref})`:""}...`),K=await r(Z);let V=await F(),{provider:X,allProviders:z}=await P(V,$.flags.provider,!!process.stdin.isTTY),{join:J}=await import("path"),U=[];if($.flags.path){let j=J(K,$.flags.path);try{await b(j)}catch{throw Error(`No SKILL.md found at path "${$.flags.path}" in the repository.`)}let W=await m($,Q,Z,K,j,$.flags.name,V,X,z);U.push(W)}else{let j=!1;try{await b(K),j=!0}catch{}if(j){let W=await m($,Q,Z,K,K,$.flags.name,V,X,z);U.push(W)}else{console.error("No SKILL.md at repository root. Scanning for skills...");let W=await $0(K);if(W.length===0)throw Error("No skills found in this repository. Skills must have a SKILL.md file.");console.error(`Found ${W.length} skill(s):
|
|
165
|
+
`);for(let B=0;B<W.length;B++)if(console.error(` ${Y.bold(`${B+1})`)} ${W[B].name} v${W[B].version} ${Y.dim(`(${W[B].relPath})`)}`),W[B].description)console.error(` ${W[B].description}`);let O;if($.flags.all){if(O=W.map((B)=>B.relPath),console.error(`
|
|
166
|
+
Installing all ${O.length} skills...`),!$.flags.yes){if(!process.stdin.isTTY)M("Cannot prompt for confirmation in non-interactive mode. Use --yes to skip."),process.exit(2);process.stderr.write(`
|
|
167
|
+
${Y.bold(`Install all ${O.length} skills?`)} [y/N] `);let B=await C();if(B.toLowerCase()!=="y"&&B.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}else if(process.stdin.isTTY){process.stderr.write(`
|
|
168
|
+
Enter skill number (or "all"): `);let B=await C();if(B.toLowerCase()==="all")O=W.map((G)=>G.relPath);else{let G=parseInt(B,10)-1;if(isNaN(G)||G<0||G>=W.length)throw Error("Invalid selection. Aborting.");O=[W[G].relPath]}}else M(`Repository contains ${W.length} skills. Use --path <subdir> to pick one or --all to install all.
|
|
161
169
|
Available skills:
|
|
162
|
-
${
|
|
163
|
-
`)}`),process.exit(2);for(let
|
|
164
|
-
${"─".repeat(40)}`);try{let
|
|
165
|
-
✓ Installed "${
|
|
166
|
-
${Y.green(`✓ Installed ${
|
|
170
|
+
${W.map((B)=>` --path ${B.relPath}`).join(`
|
|
171
|
+
`)}`),process.exit(2);for(let B of O){let G=J(K,B);console.error(`
|
|
172
|
+
${"─".repeat(40)}`);try{let _=await m($,Q,Z,K,G,O.length===1?$.flags.name:null,V,X,z);U.push(_),console.error(Y.green(`✓ Installed "${_.name}" to ${_.path}`))}catch(_){if(console.error(Y.red(`✗ Failed to install from ${B}: ${_.message}`)),O.length===1)throw _}}}}if(process.removeListener("SIGINT",q),process.removeListener("SIGTERM",q),$.flags.json)console.log(JSON.stringify(U.length===1?U[0]:U,null,2));else if(U.length===1)console.error(Y.green(`
|
|
173
|
+
✓ Installed "${U[0].name}" to ${U[0].path}`));else console.error(`
|
|
174
|
+
${Y.green(`✓ Installed ${U.length} skill(s) successfully.`)}`)}catch(Z){if(process.removeListener("SIGINT",q),process.removeListener("SIGTERM",q),$.flags.json)console.log(JSON.stringify({success:!1,error:Z.message},null,2));else M(Z.message);process.exit(1)}finally{if(K)await D(K)}}function I1(){console.log(`${Y.bold("Usage:")} asm export [options]
|
|
167
175
|
|
|
168
176
|
Export skill inventory as a portable JSON manifest.
|
|
169
177
|
|
|
170
178
|
${Y.bold("Options:")}
|
|
171
179
|
-s, --scope <s> Filter: global, project, or both (default: both)
|
|
172
180
|
--no-color Disable ANSI colors
|
|
173
|
-
-V, --verbose Show debug output`)}async function
|
|
181
|
+
-V, --verbose Show debug output`)}async function C1($){if($.flags.help){I1();return}let Q=await F(),K=await I(Q,$.flags.scope),q=Y0(K);console.log(JSON.stringify(q,null,2))}function x1(){console.log(`${Y.bold("Usage:")} asm init <name> [options]
|
|
174
182
|
|
|
175
183
|
Scaffold a new skill directory with a SKILL.md template.
|
|
176
184
|
|
|
@@ -179,8 +187,8 @@ ${Y.bold("Options:")}
|
|
|
179
187
|
--path <dir> Scaffold in specified directory instead of provider path
|
|
180
188
|
-f, --force Overwrite if skill already exists
|
|
181
189
|
--no-color Disable ANSI colors
|
|
182
|
-
-V, --verbose Show debug output`)}async function
|
|
183
|
-
${Y.bold("Overwrite?")} [y/N] `);let Z=await
|
|
190
|
+
-V, --verbose Show debug output`)}async function R1($){if($.flags.help){x1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <name>"),console.error('Run "asm init --help" for usage.'),process.exit(2);let K=S(Q),q;if($.flags.path){let{resolve:Z}=await import("path");q=Z($.flags.path)}else{let Z=await F(),{provider:V}=await P(Z,$.flags.provider,!!process.stdin.isTTY),{join:X}=await import("path"),{resolveProviderPath:z}=await import("./chunk-zh7g5bam.js"),J=z(Z.providers.find((U)=>U.name===V.name).global);q=X(J,K)}if(await J0(q)){if(!$.flags.force){if(!process.stdin.isTTY)M(`Directory already exists: ${q}. Use --force to overwrite.`),process.exit(2);process.stderr.write(`${Y.yellow(`Directory already exists: ${q}`)}
|
|
191
|
+
${Y.bold("Overwrite?")} [y/N] `);let Z=await C();if(Z.toLowerCase()!=="y"&&Z.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0)}}await z0(K,q),console.error(Y.green(`✓ Created skill "${K}" at ${q}`))}function w1(){console.log(`${Y.bold("Usage:")} asm stats [options]
|
|
184
192
|
|
|
185
193
|
Show aggregate skill metrics dashboard.
|
|
186
194
|
|
|
@@ -188,7 +196,7 @@ ${Y.bold("Options:")}
|
|
|
188
196
|
--json Output as JSON
|
|
189
197
|
-s, --scope <s> Filter: global, project, or both (default: both)
|
|
190
198
|
--no-color Disable ANSI colors
|
|
191
|
-
-V, --verbose Show debug output`)}async function
|
|
199
|
+
-V, --verbose Show debug output`)}async function y1($){if($.flags.help){w1();return}let Q=await F(),K=await I(Q,$.flags.scope);if(K.length===0){console.log("No skills found.");return}let q=o(K),Z=await U0(K,q);if($.flags.json)console.log(x(Z));else console.log(W0(Z))}function N1(){console.log(`${Y.bold("Usage:")} asm link <path> [options]
|
|
192
200
|
|
|
193
201
|
Symlink a local skill directory into an agent's skill folder.
|
|
194
202
|
|
|
@@ -198,5 +206,5 @@ ${Y.bold("Options:")}
|
|
|
198
206
|
-f, --force Overwrite if target already exists
|
|
199
207
|
--json Output as JSON
|
|
200
208
|
--no-color Disable ANSI colors
|
|
201
|
-
-V, --verbose Show debug output`)}async function
|
|
202
|
-
${Y.bold("Overwrite?")} [y/N] `);let
|
|
209
|
+
-V, --verbose Show debug output`)}async function S1($){if($.flags.help){N1();return}let Q=$.subcommand;if(!Q)M("Missing required argument: <path>"),console.error('Run "asm link --help" for usage.'),process.exit(2);let{resolve:K,basename:q}=await import("path"),Z=K(Q),V=await G0(Z),X=$.flags.name?S($.flags.name):q(Z),z=await F(),{provider:J}=await P(z,$.flags.provider,!!process.stdin.isTTY),{resolveProviderPath:U}=await import("./chunk-zh7g5bam.js"),j=U(z.providers.find((B)=>B.name===J.name).global),{join:W}=await import("path"),O=W(j,X);if(!$.flags.force){let B=!1;try{let{access:G}=await import("fs/promises");await G(O),B=!0}catch{}if(B){if(!process.stdin.isTTY)M(`Target already exists: ${O}. Use --force to overwrite.`),process.exit(2);process.stderr.write(`${Y.yellow(`Target already exists: ${O}`)}
|
|
210
|
+
${Y.bold("Overwrite?")} [y/N] `);let G=await C();if(G.toLowerCase()!=="y"&&G.toLowerCase()!=="yes")console.error("Aborted."),process.exit(0);await f(Z,j,X,!0)}else await f(Z,j,X,!1)}else await f(Z,j,X,!0);if($.flags.json)console.log(x({success:!0,name:X,symlinkPath:O,targetPath:Z}));else console.error(Y.green(`✓ Linked "${X}" → ${Z}`)),console.error(` Symlink: ${O}`),console.error(Y.dim(` If you move or delete the source, run "asm uninstall ${X}" to clean up.`))}async function x0($){let Q=z1($);if(Q.flags.noColor)globalThis.__CLI_NO_COLOR=!0;if(Q.flags.verbose)M0(!0);if(Q.flags.version){console.log(`asm ${n}`);return}if(!Q.command&&Q.flags.help){J1();return}if(!Q.command)return;switch(Q.command){case"list":await O1(Q);break;case"search":await _1(Q);break;case"inspect":await F1(Q);break;case"uninstall":await A1(Q);break;case"audit":await E1(Q);break;case"install":await H1(Q);break;case"config":await T1(Q);break;case"export":await C1(Q);break;case"init":await R1(Q);break;case"stats":await y1(Q);break;case"link":await S1(Q);break;default:M(`Unknown command: "${Q.command}"`),console.error('Run "asm --help" for usage.'),process.exit(2)}}function R0($){let Q=$.slice(2);if(Q.length===0)return!1;let K=["list","search","inspect","uninstall","audit","config","install","export","init","stats","link"],q=Q[0];if(K.includes(q))return!0;if(q==="--help"||q==="-h")return!0;if(q==="--version"||q==="-v")return!0;if(q.startsWith("-")||q.length>0)return!0;return!1}if(R0(process.argv))await x0(process.argv);else await import("./chunk-qfn7hb5z.js");
|