@crustjs/skills 0.0.13 → 0.0.14
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/README.md +5 -6
- package/dist/index.d.ts +21 -21
- package/dist/index.js +10 -9
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -60,13 +60,14 @@ runMain(app, {
|
|
|
60
60
|
skillPlugin({
|
|
61
61
|
version: "1.0.0",
|
|
62
62
|
// autoUpdate: true (default) — silently updates installed skills
|
|
63
|
-
// command:
|
|
63
|
+
// command: "skill" (default) — registers "my-cli skill" subcommand
|
|
64
|
+
// defaultScope: "global" | "project" — skip scope prompt when set
|
|
64
65
|
}),
|
|
65
66
|
],
|
|
66
67
|
});
|
|
67
68
|
```
|
|
68
69
|
|
|
69
|
-
The plugin automatically updates already-installed skills when the version changes. First-time installation is done via the interactive `skill` subcommand, or programmatically using the exported primitives.
|
|
70
|
+
The plugin automatically updates already-installed skills when the version changes, checking both project and global paths for the current working directory. First-time installation is done via the interactive `skill` subcommand (or `skill update` for update-only flows), or programmatically using the exported primitives.
|
|
70
71
|
|
|
71
72
|
### Programmatic Auto-Install
|
|
72
73
|
|
|
@@ -81,7 +82,7 @@ const app = defineCommand({
|
|
|
81
82
|
meta: { name: "my-cli", description: "My CLI" },
|
|
82
83
|
async run() {
|
|
83
84
|
// Detect agents and install skills if not yet present
|
|
84
|
-
const agents = await detectInstalledAgents(
|
|
85
|
+
const agents = await detectInstalledAgents();
|
|
85
86
|
const status = await skillStatus({ name: "my-cli", agents, scope: "global" });
|
|
86
87
|
|
|
87
88
|
const notInstalled = status.agents
|
|
@@ -107,9 +108,7 @@ runMain(app);
|
|
|
107
108
|
If auto-update does not appear to work:
|
|
108
109
|
|
|
109
110
|
- Ensure plugin is passed to `runMain(..., { plugins: [...] })`.
|
|
110
|
-
- Ensure at least one supported agent is detected
|
|
111
|
-
- `scope: "global"` -> checks supported global agent config roots (for example `~/.claude`, `~/.config/opencode`, `~/.codex`)
|
|
112
|
-
- `scope: "project"` -> checks project roots first (for example `<cwd>/.claude`, `<cwd>/.opencode`) then falls back to global roots
|
|
111
|
+
- Ensure at least one supported agent is detected. Auto-update checks both project and global install paths.
|
|
113
112
|
- Check for existing conflicting skill directories without `crust.json`.
|
|
114
113
|
|
|
115
114
|
## Recommended Export Pattern
|
package/dist/index.d.ts
CHANGED
|
@@ -196,11 +196,7 @@ interface StatusResult {
|
|
|
196
196
|
* The plugin reads `name` and `description` from the root command's `meta`
|
|
197
197
|
* at setup time, so only `version` is required here.
|
|
198
198
|
*
|
|
199
|
-
* Installed agents are detected automatically
|
|
200
|
-
*
|
|
201
|
-
* - `scope: "global"` checks `~/.claude/` and `~/.config/opencode/`
|
|
202
|
-
* - `scope: "project"` checks `<cwd>/.claude/` / `<cwd>/.opencode/`, then
|
|
203
|
-
* falls back to global roots when local roots are missing
|
|
199
|
+
* Installed agents are detected automatically.
|
|
204
200
|
*
|
|
205
201
|
* Only detected agents are managed.
|
|
206
202
|
*
|
|
@@ -211,18 +207,27 @@ interface StatusResult {
|
|
|
211
207
|
* build custom auto-install logic with the exported primitives
|
|
212
208
|
* (`detectInstalledAgents`, `skillStatus`, `generateSkill`).
|
|
213
209
|
*
|
|
214
|
-
* **Interactive command** (default): registers a `skill` subcommand
|
|
210
|
+
* **Interactive command** (default): registers a `skill` subcommand (or the
|
|
211
|
+
* custom `command` name) that
|
|
215
212
|
* presents a single multiselect prompt for toggling agent installations.
|
|
216
|
-
*
|
|
213
|
+
*
|
|
214
|
+
* Scope resolution for interactive commands:
|
|
215
|
+
* - If `defaultScope` is set, that scope is used and no scope prompt is shown.
|
|
216
|
+
* - If `defaultScope` is not set and the terminal is interactive, users are
|
|
217
|
+
* prompted to choose `project` or `global`.
|
|
218
|
+
* - If `defaultScope` is not set and the terminal is non-interactive, scope
|
|
219
|
+
* falls back to `"global"`.
|
|
217
220
|
*/
|
|
218
221
|
interface SkillPluginOptions {
|
|
219
222
|
/** Skill version string — compared against the installed crust.json */
|
|
220
223
|
version: string;
|
|
221
224
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
225
|
+
* Default installation scope for interactive commands.
|
|
226
|
+
*
|
|
227
|
+
* When omitted, interactive commands prompt for scope in TTY mode.
|
|
228
|
+
* Non-interactive mode falls back to "global".
|
|
224
229
|
*/
|
|
225
|
-
|
|
230
|
+
defaultScope?: Scope;
|
|
226
231
|
/**
|
|
227
232
|
* Automatically update skills when the installed version is outdated.
|
|
228
233
|
* @default true
|
|
@@ -237,11 +242,9 @@ interface SkillPluginOptions {
|
|
|
237
242
|
* newly selected agents are installed, deselected agents are uninstalled,
|
|
238
243
|
* and already-correct agents are skipped.
|
|
239
244
|
*
|
|
240
|
-
*
|
|
241
|
-
* - `string`: register with a custom command name
|
|
242
|
-
* @default true
|
|
245
|
+
* @default "skill"
|
|
243
246
|
*/
|
|
244
|
-
command?:
|
|
247
|
+
command?: string;
|
|
245
248
|
}
|
|
246
249
|
/** Returns agents that use the canonical `.agents/skills` layout. */
|
|
247
250
|
declare function getUniversalAgents(): AgentTarget[];
|
|
@@ -381,10 +384,7 @@ import { CrustPlugin } from "@crustjs/core";
|
|
|
381
384
|
* `name` and `description` are read from the root command's `meta` at setup
|
|
382
385
|
* time — only `version` needs to be supplied in the options.
|
|
383
386
|
*
|
|
384
|
-
* Installed agents are detected automatically
|
|
385
|
-
* - `scope: "global"` checks global config roots in the home directory
|
|
386
|
-
* - `scope: "project"` checks project-local config roots in the cwd, then
|
|
387
|
-
* falls back to global roots in the home directory
|
|
387
|
+
* Installed agents are detected automatically.
|
|
388
388
|
*
|
|
389
389
|
* Only detected agents are managed by automatic update and the interactive
|
|
390
390
|
* command.
|
|
@@ -397,13 +397,13 @@ import { CrustPlugin } from "@crustjs/core";
|
|
|
397
397
|
* Detected agents are shown with their current installation status pre-filled.
|
|
398
398
|
* The system reconciles the desired state: newly selected agents are installed,
|
|
399
399
|
* deselected agents are uninstalled, and already-correct agents are skipped.
|
|
400
|
-
*
|
|
400
|
+
* `command` configures the injected command name.
|
|
401
401
|
*
|
|
402
402
|
* For first-time installation, use the interactive command or build custom
|
|
403
403
|
* auto-install logic with the exported primitives (`detectInstalledAgents`,
|
|
404
404
|
* `skillStatus`, `generateSkill`).
|
|
405
405
|
*
|
|
406
|
-
* @param options - Plugin configuration with version and
|
|
406
|
+
* @param options - Plugin configuration with version and defaults
|
|
407
407
|
* @returns A `CrustPlugin` to register in a command's `plugins` array
|
|
408
408
|
*
|
|
409
409
|
* @example
|
|
@@ -414,7 +414,7 @@ import { CrustPlugin } from "@crustjs/core";
|
|
|
414
414
|
* const app = new Crust("my-cli").meta({ description: "My CLI" })
|
|
415
415
|
* .use(skillPlugin({
|
|
416
416
|
* version: "1.0.0",
|
|
417
|
-
* command:
|
|
417
|
+
* command: "skill", // registers "my-cli skill" subcommand
|
|
418
418
|
* }))
|
|
419
419
|
* .run(() => { /* ... */ });
|
|
420
420
|
*
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{spawn as kQ}from"child_process";import{homedir as XQ}from"os";import{join as $}from"path";var G=$(".agents","skills");function QQ(Q){if(Q!==XQ())return $(Q,".config");let Z=process.env.XDG_CONFIG_HOME?.trim();return Z&&Z.length>0?Z:$(Q,".config")}function U(Q){return $(Q,".agents","skills")}var P={amp:{label:"Amp",class:"universal",projectSkillsDir:G,globalSkillsDir:U},adal:{label:"AdaL",class:"additional",projectSkillsDir:$(".adal","skills"),globalSkillsDir:(Q)=>$(Q,".adal","skills"),detectCommands:["adal"]},antigravity:{label:"Antigravity",class:"additional",projectSkillsDir:$(".agent","skills"),globalSkillsDir:(Q)=>$(Q,".gemini","antigravity","skills"),detectCommands:["antigravity"]},augment:{label:"Augment",class:"additional",projectSkillsDir:$(".augment","skills"),globalSkillsDir:(Q)=>$(Q,".augment","skills"),detectCommands:["augment"]},"claude-code":{label:"Claude Code",class:"additional",projectSkillsDir:$(".claude","skills"),globalSkillsDir:(Q)=>$(process.env.CLAUDE_CONFIG_DIR?.trim()||$(Q,".claude"),"skills"),detectCommands:["claude","claude-code"]},cline:{label:"Cline",class:"universal",projectSkillsDir:G,globalSkillsDir:U},codebuddy:{label:"CodeBuddy",class:"additional",projectSkillsDir:$(".codebuddy","skills"),globalSkillsDir:(Q)=>$(Q,".codebuddy","skills"),detectCommands:["codebuddy"]},codex:{label:"Codex",class:"universal",projectSkillsDir:G,globalSkillsDir:U},"command-code":{label:"Command Code",class:"additional",projectSkillsDir:$(".commandcode","skills"),globalSkillsDir:(Q)=>$(Q,".commandcode","skills"),detectCommands:["command-code","commandcode"]},continue:{label:"Continue",class:"additional",projectSkillsDir:$(".continue","skills"),globalSkillsDir:(Q)=>$(Q,".continue","skills"),detectCommands:["continue"]},cortex:{label:"Cortex Code",class:"additional",projectSkillsDir:$(".cortex","skills"),globalSkillsDir:(Q)=>$(Q,".snowflake","cortex","skills"),detectCommands:["cortex"]},crush:{label:"Crush",class:"additional",projectSkillsDir:$(".crush","skills"),globalSkillsDir:(Q)=>$(QQ(Q),"crush","skills"),detectCommands:["crush"]},cursor:{label:"Cursor",class:"universal",projectSkillsDir:G,globalSkillsDir:U},droid:{label:"Droid",class:"additional",projectSkillsDir:$(".factory","skills"),globalSkillsDir:(Q)=>$(Q,".factory","skills"),detectCommands:["droid"]},"gemini-cli":{label:"Gemini CLI",class:"universal",projectSkillsDir:G,globalSkillsDir:U},"github-copilot":{label:"GitHub Copilot",class:"universal",projectSkillsDir:G,globalSkillsDir:U},goose:{label:"Goose",class:"additional",projectSkillsDir:$(".goose","skills"),globalSkillsDir:(Q)=>$(QQ(Q),"goose","skills"),detectCommands:["goose"]},"iflow-cli":{label:"iFlow CLI",class:"additional",projectSkillsDir:$(".iflow","skills"),globalSkillsDir:(Q)=>$(Q,".iflow","skills"),detectCommands:["iflow","iflow-cli"]},junie:{label:"Junie",class:"additional",projectSkillsDir:$(".junie","skills"),globalSkillsDir:(Q)=>$(Q,".junie","skills"),detectCommands:["junie"]},kilo:{label:"Kilo Code",class:"additional",projectSkillsDir:$(".kilocode","skills"),globalSkillsDir:(Q)=>$(Q,".kilocode","skills"),detectCommands:["kilo","kilocode"]},"kimi-cli":{label:"Kimi Code CLI",class:"universal",projectSkillsDir:G,globalSkillsDir:U},"kiro-cli":{label:"Kiro CLI",class:"additional",projectSkillsDir:$(".kiro","skills"),globalSkillsDir:(Q)=>$(Q,".kiro","skills"),detectCommands:["kiro","kiro-cli"]},kode:{label:"Kode",class:"additional",projectSkillsDir:$(".kode","skills"),globalSkillsDir:(Q)=>$(Q,".kode","skills"),detectCommands:["kode"]},mcpjam:{label:"MCPJam",class:"additional",projectSkillsDir:$(".mcpjam","skills"),globalSkillsDir:(Q)=>$(Q,".mcpjam","skills"),detectCommands:["mcpjam"]},"mistral-vibe":{label:"Mistral Vibe",class:"additional",projectSkillsDir:$(".vibe","skills"),globalSkillsDir:(Q)=>$(Q,".vibe","skills"),detectCommands:["mistral-vibe","vibe"]},mux:{label:"Mux",class:"additional",projectSkillsDir:$(".mux","skills"),globalSkillsDir:(Q)=>$(Q,".mux","skills"),detectCommands:["mux"]},neovate:{label:"Neovate",class:"additional",projectSkillsDir:$(".neovate","skills"),globalSkillsDir:(Q)=>$(Q,".neovate","skills"),detectCommands:["neovate"]},opencode:{label:"OpenCode",class:"universal",projectSkillsDir:G,globalSkillsDir:U},openclaw:{label:"OpenClaw",class:"additional",projectSkillsDir:"skills",globalSkillsDir:(Q)=>$(Q,".openclaw","skills"),detectCommands:["openclaw"]},openhands:{label:"OpenHands",class:"additional",projectSkillsDir:$(".openhands","skills"),globalSkillsDir:(Q)=>$(Q,".openhands","skills"),detectCommands:["openhands"]},pi:{label:"Pi",class:"additional",projectSkillsDir:$(".pi","skills"),globalSkillsDir:(Q)=>$(Q,".pi","agent","skills"),detectCommands:["pi"]},pochi:{label:"Pochi",class:"additional",projectSkillsDir:$(".pochi","skills"),globalSkillsDir:(Q)=>$(Q,".pochi","skills"),detectCommands:["pochi"]},qoder:{label:"Qoder",class:"additional",projectSkillsDir:$(".qoder","skills"),globalSkillsDir:(Q)=>$(Q,".qoder","skills"),detectCommands:["qoder"]},"qwen-code":{label:"Qwen Code",class:"additional",projectSkillsDir:$(".qwen","skills"),globalSkillsDir:(Q)=>$(Q,".qwen","skills"),detectCommands:["qwen","qwen-code"]},replit:{label:"Replit",class:"universal",projectSkillsDir:G,globalSkillsDir:U},roo:{label:"Roo Code",class:"additional",projectSkillsDir:$(".roo","skills"),globalSkillsDir:(Q)=>$(Q,".roo","skills"),detectCommands:["roo","roo-code"]},trae:{label:"Trae",class:"additional",projectSkillsDir:$(".trae","skills"),globalSkillsDir:(Q)=>$(Q,".trae","skills"),detectCommands:["trae"]},"trae-cn":{label:"Trae CN",class:"additional",projectSkillsDir:$(".trae","skills"),globalSkillsDir:(Q)=>$(Q,".trae-cn","skills"),detectCommands:["trae-cn","trae"]},windsurf:{label:"Windsurf",class:"additional",projectSkillsDir:$(".windsurf","skills"),globalSkillsDir:(Q)=>$(Q,".codeium","windsurf","skills"),detectCommands:["windsurf"]},zencoder:{label:"Zencoder",class:"additional",projectSkillsDir:$(".zencoder","skills"),globalSkillsDir:(Q)=>$(Q,".zencoder","skills"),detectCommands:["zencoder"]}},s=Object.keys(P),k=Object.fromEntries(s.map((Q)=>[Q,P[Q].label]));function f(){return s.filter((Q)=>P[Q].class==="universal")}function h(){return s.filter((Q)=>P[Q].class==="additional")}function yQ(Q){return P[Q].class==="universal"}async function p(Q){let Z=typeof Q==="string"?{home:Q}:Q??{},X=Z.cwd??process.cwd(),W=Z.commandChecker??PQ,H=[];for(let q of h()){let B=P[q].detectCommands??[],x=!1;for(let z of B)if(await W(z,X)){x=!0;break}if(x)H.push(q)}return H}function u(Q,Z,X){let W=P[Q];if(Z==="project")return $(process.cwd(),W.projectSkillsDir,X);return $(W.globalSkillsDir(XQ()),X)}async function PQ(Q,Z){for(let X of[["--version"],["-v"],["version"]])if(await bQ(Q,X,Z))return!0;return!1}async function bQ(Q,Z,X){return new Promise((W)=>{let H=kQ(Q,Z,{cwd:X,stdio:"ignore",shell:!1}),q=!1,B=(z)=>{if(q)return;q=!0,W(z)},x=setTimeout(()=>{H.kill("SIGTERM"),B(!1)},1000);H.once("error",()=>{clearTimeout(x),B(!1)}),H.once("exit",(z)=>{clearTimeout(x),B(z===0)})})}class b extends Error{name="SkillConflictError";details;constructor(Q){let Z=`Skill conflict for agent "${Q.agent}": directory "${Q.outputDir}" already exists but was not created by Crust (no crust.json found). Delete or rename the conflicting skill to resolve.`;super(Z);this.details=Q}}import{access as MQ,mkdir as gQ,rm as wQ,writeFile as mQ}from"fs/promises";import{dirname as dQ,join as OQ}from"path";function ZQ(Q){return WQ(Q,[])}function WQ(Q,Z){let X=TQ(Q.meta.name),W=[...Z,X],H=CQ(Q.args),q=_Q(Q.effectiveFlags),B=DQ(Q.subCommands,W);return{name:X,path:W,description:Q.meta.description,usage:Q.meta.usage,runnable:typeof Q.run==="function",args:H,flags:q,children:B}}function TQ(Q){return Q.trim().toLowerCase()}function CQ(Q){if(!Q||Q.length===0)return[];return Q.map(IQ)}function IQ(Q){let Z={name:Q.name,type:Q.type,required:Q.required===!0,variadic:Q.variadic===!0};if(Q.description!==void 0)Z.description=Q.description;if(Q.default!==void 0)Z.default=$Q(Q.default);return Z}function _Q(Q){if(!Q)return[];return Object.keys(Q).sort().map((X)=>{return EQ(X,Q[X])})}function EQ(Q,Z){let X={name:Q,type:Z.type,required:Z.required===!0,multiple:Z.multiple===!0,short:Z.short,aliases:Z.aliases?[...Z.aliases].sort():[]};if(Z.description!==void 0)X.description=Z.description;if(Z.default!==void 0)X.default=$Q(Z.default);return X}function DQ(Q,Z){return Object.keys(Q).sort().map((W)=>{return WQ(Q[W],Z)})}function $Q(Q){if(Array.isArray(Q))return JSON.stringify(Q);return String(Q)}function N(Q){if(/[:#[\]{}&*!|>'"`,@?\\]|^\s|\s$|^---|[\n\r]/.test(Q))return`"${Q.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r")}"`;return Q}function HQ(Q){return Q.replace(/(?<!\\)\|/g,"\\|")}function qQ(Q,Z){let X=[],W=YQ(Q);X.push({path:"SKILL.md",content:LQ(Q,Z,W)});for(let H of W){let q=T(H),B=H.children.length>0?vQ(H,Q):SQ(H,Q);X.push({path:q,content:B})}return X}function YQ(Q){let Z=[Q];for(let X of Q.children)Z.push(...YQ(X));return Z}function T(Q){if(Q.path.length<=1)return`commands/${Q.name}.md`;return`commands/${Q.path.slice(1).join("/")}.md`}function c(Q){return Q.path.join(" ")}function t(Q,Z){let X=Q.split("/").slice(0,-1),W=Z.split("/"),H=0;while(H<X.length&&H<W.length&&X[H]===W[H])H++;let q=X.length-H,B=W.slice(H);if(q===0)return B.join("/");return[...Array.from({length:q},()=>".."),...B].join("/")}function LQ(Q,Z,X){let W=[];if(W.push("---"),W.push(`name: ${N(Z.name)}`),W.push(`description: ${N(Z.description)}`),Z.license)W.push(`license: ${N(Z.license)}`);if(Z.compatibility)W.push(`compatibility: ${N(Z.compatibility)}`);if(Z.disableModelInvocation)W.push("disable-model-invocation: true");if(Z.allowedTools)W.push(`allowed-tools: ${N(Z.allowedTools)}`);if(W.push("metadata:"),W.push(` version: "${Z.version}"`),W.push("---"),W.push(""),W.push(`# ${Z.name}`),W.push(""),Q.description)W.push(Q.description),W.push("");let H=Z.name.startsWith("use-")?Z.name.slice(4):Z.name;if(W.push(`Use this skill when working with \`${H}\` commands, or when you need help with \`${H}\` syntax, flags, or subcommands.`),W.push(""),W.push("## Command Reference"),W.push(""),W.push("This table lists all commands and their documentation paths. **Do not read all command files at once.** Instead:"),W.push(""),W.push("1. Use the table below to find the relevant command"),W.push("2. Use the `Type` column to choose what to execute: commands labeled `runnable` (including `runnable, group`) are executable, while `group` commands are not"),W.push("3. Read only the specific file from the `commands/` directory that you need"),W.push(""),W.push(...jQ(X)),W.push(""),Q.runnable){W.push("## Usage"),W.push("");let q=T(Q);W.push(`The root command is directly executable. See [${Q.name}](${q}) for usage details.`),W.push("")}return W.join(`
|
|
3
|
-
`)}function
|
|
4
|
-
`)}function
|
|
5
|
-
`)}function
|
|
6
|
-
`}async function
|
|
7
|
-
${
|
|
8
|
-
${
|
|
9
|
-
Skipped ${
|
|
10
|
-
${
|
|
2
|
+
import{spawn as IQ}from"child_process";import{homedir as WQ}from"os";import{join as H}from"path";var R=H(".agents","skills");function ZQ(Q){if(Q!==WQ())return H(Q,".config");let Z=process.env.XDG_CONFIG_HOME?.trim();return Z&&Z.length>0?Z:H(Q,".config")}function y(Q){return H(Q,".agents","skills")}var _={amp:{label:"Amp",class:"universal",projectSkillsDir:R,globalSkillsDir:y},adal:{label:"AdaL",class:"additional",projectSkillsDir:H(".adal","skills"),globalSkillsDir:(Q)=>H(Q,".adal","skills"),detectCommands:["adal"]},antigravity:{label:"Antigravity",class:"additional",projectSkillsDir:H(".agent","skills"),globalSkillsDir:(Q)=>H(Q,".gemini","antigravity","skills"),detectCommands:["antigravity"]},augment:{label:"Augment",class:"additional",projectSkillsDir:H(".augment","skills"),globalSkillsDir:(Q)=>H(Q,".augment","skills"),detectCommands:["augment"]},"claude-code":{label:"Claude Code",class:"additional",projectSkillsDir:H(".claude","skills"),globalSkillsDir:(Q)=>H(process.env.CLAUDE_CONFIG_DIR?.trim()||H(Q,".claude"),"skills"),detectCommands:["claude","claude-code"]},cline:{label:"Cline",class:"universal",projectSkillsDir:R,globalSkillsDir:y},codebuddy:{label:"CodeBuddy",class:"additional",projectSkillsDir:H(".codebuddy","skills"),globalSkillsDir:(Q)=>H(Q,".codebuddy","skills"),detectCommands:["codebuddy"]},codex:{label:"Codex",class:"universal",projectSkillsDir:R,globalSkillsDir:y},"command-code":{label:"Command Code",class:"additional",projectSkillsDir:H(".commandcode","skills"),globalSkillsDir:(Q)=>H(Q,".commandcode","skills"),detectCommands:["command-code","commandcode"]},continue:{label:"Continue",class:"additional",projectSkillsDir:H(".continue","skills"),globalSkillsDir:(Q)=>H(Q,".continue","skills"),detectCommands:["continue"]},cortex:{label:"Cortex Code",class:"additional",projectSkillsDir:H(".cortex","skills"),globalSkillsDir:(Q)=>H(Q,".snowflake","cortex","skills"),detectCommands:["cortex"]},crush:{label:"Crush",class:"additional",projectSkillsDir:H(".crush","skills"),globalSkillsDir:(Q)=>H(ZQ(Q),"crush","skills"),detectCommands:["crush"]},cursor:{label:"Cursor",class:"universal",projectSkillsDir:R,globalSkillsDir:y},droid:{label:"Droid",class:"additional",projectSkillsDir:H(".factory","skills"),globalSkillsDir:(Q)=>H(Q,".factory","skills"),detectCommands:["droid"]},"gemini-cli":{label:"Gemini CLI",class:"universal",projectSkillsDir:R,globalSkillsDir:y},"github-copilot":{label:"GitHub Copilot",class:"universal",projectSkillsDir:R,globalSkillsDir:y},goose:{label:"Goose",class:"additional",projectSkillsDir:H(".goose","skills"),globalSkillsDir:(Q)=>H(ZQ(Q),"goose","skills"),detectCommands:["goose"]},"iflow-cli":{label:"iFlow CLI",class:"additional",projectSkillsDir:H(".iflow","skills"),globalSkillsDir:(Q)=>H(Q,".iflow","skills"),detectCommands:["iflow","iflow-cli"]},junie:{label:"Junie",class:"additional",projectSkillsDir:H(".junie","skills"),globalSkillsDir:(Q)=>H(Q,".junie","skills"),detectCommands:["junie"]},kilo:{label:"Kilo Code",class:"additional",projectSkillsDir:H(".kilocode","skills"),globalSkillsDir:(Q)=>H(Q,".kilocode","skills"),detectCommands:["kilo","kilocode"]},"kimi-cli":{label:"Kimi Code CLI",class:"universal",projectSkillsDir:R,globalSkillsDir:y},"kiro-cli":{label:"Kiro CLI",class:"additional",projectSkillsDir:H(".kiro","skills"),globalSkillsDir:(Q)=>H(Q,".kiro","skills"),detectCommands:["kiro","kiro-cli"]},kode:{label:"Kode",class:"additional",projectSkillsDir:H(".kode","skills"),globalSkillsDir:(Q)=>H(Q,".kode","skills"),detectCommands:["kode"]},mcpjam:{label:"MCPJam",class:"additional",projectSkillsDir:H(".mcpjam","skills"),globalSkillsDir:(Q)=>H(Q,".mcpjam","skills"),detectCommands:["mcpjam"]},"mistral-vibe":{label:"Mistral Vibe",class:"additional",projectSkillsDir:H(".vibe","skills"),globalSkillsDir:(Q)=>H(Q,".vibe","skills"),detectCommands:["mistral-vibe","vibe"]},mux:{label:"Mux",class:"additional",projectSkillsDir:H(".mux","skills"),globalSkillsDir:(Q)=>H(Q,".mux","skills"),detectCommands:["mux"]},neovate:{label:"Neovate",class:"additional",projectSkillsDir:H(".neovate","skills"),globalSkillsDir:(Q)=>H(Q,".neovate","skills"),detectCommands:["neovate"]},opencode:{label:"OpenCode",class:"universal",projectSkillsDir:R,globalSkillsDir:y},openclaw:{label:"OpenClaw",class:"additional",projectSkillsDir:"skills",globalSkillsDir:(Q)=>H(Q,".openclaw","skills"),detectCommands:["openclaw"]},openhands:{label:"OpenHands",class:"additional",projectSkillsDir:H(".openhands","skills"),globalSkillsDir:(Q)=>H(Q,".openhands","skills"),detectCommands:["openhands"]},pi:{label:"Pi",class:"additional",projectSkillsDir:H(".pi","skills"),globalSkillsDir:(Q)=>H(Q,".pi","agent","skills"),detectCommands:["pi"]},pochi:{label:"Pochi",class:"additional",projectSkillsDir:H(".pochi","skills"),globalSkillsDir:(Q)=>H(Q,".pochi","skills"),detectCommands:["pochi"]},qoder:{label:"Qoder",class:"additional",projectSkillsDir:H(".qoder","skills"),globalSkillsDir:(Q)=>H(Q,".qoder","skills"),detectCommands:["qoder"]},"qwen-code":{label:"Qwen Code",class:"additional",projectSkillsDir:H(".qwen","skills"),globalSkillsDir:(Q)=>H(Q,".qwen","skills"),detectCommands:["qwen","qwen-code"]},replit:{label:"Replit",class:"universal",projectSkillsDir:R,globalSkillsDir:y},roo:{label:"Roo Code",class:"additional",projectSkillsDir:H(".roo","skills"),globalSkillsDir:(Q)=>H(Q,".roo","skills"),detectCommands:["roo","roo-code"]},trae:{label:"Trae",class:"additional",projectSkillsDir:H(".trae","skills"),globalSkillsDir:(Q)=>H(Q,".trae","skills"),detectCommands:["trae"]},"trae-cn":{label:"Trae CN",class:"additional",projectSkillsDir:H(".trae","skills"),globalSkillsDir:(Q)=>H(Q,".trae-cn","skills"),detectCommands:["trae-cn","trae"]},windsurf:{label:"Windsurf",class:"additional",projectSkillsDir:H(".windsurf","skills"),globalSkillsDir:(Q)=>H(Q,".codeium","windsurf","skills"),detectCommands:["windsurf"]},zencoder:{label:"Zencoder",class:"additional",projectSkillsDir:H(".zencoder","skills"),globalSkillsDir:(Q)=>H(Q,".zencoder","skills"),detectCommands:["zencoder"]}},t=Object.keys(_),j=Object.fromEntries(t.map((Q)=>[Q,_[Q].label]));function E(){return t.filter((Q)=>_[Q].class==="universal")}function c(){return t.filter((Q)=>_[Q].class==="additional")}function _Q(Q){return _[Q].class==="universal"}async function v(Q){let Z=typeof Q==="string"?{home:Q}:Q??{},X=Z.cwd??process.cwd(),W=Z.commandChecker??EQ,$=[];for(let q of c()){let B=_[q].detectCommands??[],J=!1;for(let z of B)if(await W(z,X)){J=!0;break}if(J)$.push(q)}return $}function g(Q,Z,X){let W=_[Q];if(Z==="project")return H(process.cwd(),W.projectSkillsDir,X);return H(W.globalSkillsDir(WQ()),X)}async function EQ(Q,Z){for(let X of[["--version"],["-v"],["version"]])if(await bQ(Q,X,Z))return!0;return!1}async function bQ(Q,Z,X){return new Promise((W)=>{let $=IQ(Q,Z,{cwd:X,stdio:"ignore",shell:!1}),q=!1,B=(z)=>{if(q)return;q=!0,W(z)},J=setTimeout(()=>{$.kill("SIGTERM"),B(!1)},1000);$.once("error",()=>{clearTimeout(J),B(!1)}),$.once("exit",(z)=>{clearTimeout(J),B(z===0)})})}class P extends Error{name="SkillConflictError";details;constructor(Q){let Z=`Skill conflict for agent "${Q.agent}": directory "${Q.outputDir}" already exists but was not created by Crust (no crust.json found). Delete or rename the conflicting skill to resolve.`;super(Z);this.details=Q}}import{access as VQ,mkdir as lQ,rm as GQ,writeFile as iQ}from"fs/promises";import{dirname as sQ,join as FQ}from"path";function $Q(Q){return HQ(Q,[])}function HQ(Q,Z){let X=CQ(Q.meta.name),W=[...Z,X],$=DQ(Q.args),q=NQ(Q.effectiveFlags),B=AQ(Q.subCommands,W);return{name:X,path:W,description:Q.meta.description,usage:Q.meta.usage,runnable:typeof Q.run==="function",args:$,flags:q,children:B}}function CQ(Q){return Q.trim().toLowerCase()}function DQ(Q){if(!Q||Q.length===0)return[];return Q.map(LQ)}function LQ(Q){let Z={name:Q.name,type:Q.type,required:Q.required===!0,variadic:Q.variadic===!0};if(Q.description!==void 0)Z.description=Q.description;if(Q.default!==void 0)Z.default=qQ(Q.default);return Z}function NQ(Q){if(!Q)return[];return Object.keys(Q).sort().map((X)=>{return jQ(X,Q[X])})}function jQ(Q,Z){let X={name:Q,type:Z.type,required:Z.required===!0,multiple:Z.multiple===!0,short:Z.short,aliases:Z.aliases?[...Z.aliases].sort():[]};if(Z.description!==void 0)X.description=Z.description;if(Z.default!==void 0)X.default=qQ(Z.default);return X}function AQ(Q,Z){return Object.keys(Q).sort().map((W)=>{return HQ(Q[W],Z)})}function qQ(Q){if(Array.isArray(Q))return JSON.stringify(Q);return String(Q)}function f(Q){if(/[:#[\]{}&*!|>'"`,@?\\]|^\s|\s$|^---|[\n\r]/.test(Q))return`"${Q.replace(/\\/g,"\\\\").replace(/"/g,"\\\"").replace(/\n/g,"\\n").replace(/\r/g,"\\r")}"`;return Q}function BQ(Q){return Q.replace(/(?<!\\)\|/g,"\\|")}function YQ(Q,Z){let X=[],W=zQ(Q);X.push({path:"SKILL.md",content:SQ(Q,Z,W)});for(let $ of W){let q=b($),B=$.children.length>0?pQ($,Q):hQ($,Q);X.push({path:q,content:B})}return X}function zQ(Q){let Z=[Q];for(let X of Q.children)Z.push(...zQ(X));return Z}function b(Q){if(Q.path.length<=1)return`commands/${Q.name}.md`;return`commands/${Q.path.slice(1).join("/")}.md`}function m(Q){return Q.path.join(" ")}function o(Q,Z){let X=Q.split("/").slice(0,-1),W=Z.split("/"),$=0;while($<X.length&&$<W.length&&X[$]===W[$])$++;let q=X.length-$,B=W.slice($);if(q===0)return B.join("/");return[...Array.from({length:q},()=>".."),...B].join("/")}function SQ(Q,Z,X){let W=[];if(W.push("---"),W.push(`name: ${f(Z.name)}`),W.push(`description: ${f(Z.description)}`),Z.license)W.push(`license: ${f(Z.license)}`);if(Z.compatibility)W.push(`compatibility: ${f(Z.compatibility)}`);if(Z.disableModelInvocation)W.push("disable-model-invocation: true");if(Z.allowedTools)W.push(`allowed-tools: ${f(Z.allowedTools)}`);if(W.push("metadata:"),W.push(` version: "${Z.version}"`),W.push("---"),W.push(""),W.push(`# ${Z.name}`),W.push(""),Q.description)W.push(Q.description),W.push("");let $=Z.name.startsWith("use-")?Z.name.slice(4):Z.name;if(W.push(`Use this skill when working with \`${$}\` commands, or when you need help with \`${$}\` syntax, flags, or subcommands.`),W.push(""),W.push("## Command Reference"),W.push(""),W.push("This table lists all commands and their documentation paths. **Do not read all command files at once.** Instead:"),W.push(""),W.push("1. Use the table below to find the relevant command"),W.push("2. Use the `Type` column to choose what to execute: commands labeled `runnable` (including `runnable, group`) are executable, while `group` commands are not"),W.push("3. Read only the specific file from the `commands/` directory that you need"),W.push("4. For any command-specific answer, read that command's documentation file before responding"),W.push("5. Treat the command documentation file as the source of truth for usage, flags, options, aliases, and defaults"),W.push("6. Do not invent or assume undocumented flags/options; if something is missing from the file, say it is not documented"),W.push(""),W.push(...vQ(X)),W.push(""),Q.runnable){W.push("## Usage"),W.push("");let q=b(Q);W.push(`The root command is directly executable. See [${Q.name}](${q}) for usage details.`),W.push("")}return W.join(`
|
|
3
|
+
`)}function vQ(Q){let Z=[];Z.push("| Command | Type | Documentation |"),Z.push("| ------- | ---- | ------------- |");for(let X of Q){let W=m(X),$=b(X),q=fQ(X);Z.push(`| \`${W}\` | ${q} | [${$}](${$}) |`)}return Z}function fQ(Q){if(Q.runnable&&Q.children.length>0)return"runnable, group";if(Q.runnable)return"runnable";return"group"}function hQ(Q,Z){let X=[],W=m(Q);if(X.push(`# \`${W}\``),X.push(""),Q.description)X.push(Q.description),X.push("");if(X.push("## Usage"),X.push(""),Q.usage)X.push("```"),X.push(Q.usage),X.push("```");else X.push("```"),X.push(JQ(Q)),X.push("```");if(X.push(""),Q.args.length>0)X.push("## Arguments"),X.push(""),X.push(...KQ(Q.args)),X.push("");if(Q.flags.length>0)X.push("## Flags"),X.push(""),X.push(...xQ(Q.flags)),X.push("");return X.push("## Command Documentation Authority"),X.push(""),X.push("Only arguments, flags, options, aliases, and defaults documented in this file are supported for this command."),X.push("Do not infer or invent additional command-line options."),X.push(""),X.push(...OQ(Q,Z)),X.join(`
|
|
4
|
+
`)}function pQ(Q,Z){let X=[],W=m(Q),$=b(Q);if(X.push(`# \`${W}\``),X.push(""),Q.description)X.push(Q.description),X.push("");if(Q.runnable){if(X.push("## Usage"),X.push(""),Q.usage)X.push("```"),X.push(Q.usage),X.push("```");else X.push("```"),X.push(JQ(Q)),X.push("```");if(X.push(""),Q.args.length>0)X.push("## Arguments"),X.push(""),X.push(...KQ(Q.args)),X.push("");if(Q.flags.length>0)X.push("## Flags"),X.push(""),X.push(...xQ(Q.flags)),X.push("");X.push("## Command Documentation Authority"),X.push(""),X.push("Only arguments, flags, options, aliases, and defaults documented in this file are supported for this command."),X.push("Do not infer or invent additional command-line options."),X.push("")}X.push("## Subcommands"),X.push("");for(let q of Q.children){let B=b(q),J=o($,B),z=q.description?` - ${q.description}`:"";X.push(`- [\`${q.name}\`](${J})${z}`)}return X.push(""),X.push(...OQ(Q,Z)),X.join(`
|
|
5
|
+
`)}function JQ(Q){let Z=[...Q.path];for(let X of Q.args)if(X.variadic)Z.push(X.required?`<${X.name}...>`:`[${X.name}...]`);else Z.push(X.required?`<${X.name}>`:`[${X.name}]`);if(Q.flags.length>0)Z.push("[options]");return Z.join(" ")}function KQ(Q){let Z=[];Z.push("| Argument | Type | Required | Description |"),Z.push("| -------- | ---- | -------- | ----------- |");for(let X of Q){let W=X.variadic?`${X.name}...`:X.name,$=X.required?"Yes":"No",q=BQ(uQ(X));Z.push(`| \`${W}\` | ${X.type} | ${$} | ${q} |`)}return Z}function uQ(Q){let Z=[];if(Q.description)Z.push(Q.description);if(Q.default!==void 0)Z.push(`Default: \`${Q.default}\``);return Z.join(". ")||"-"}function xQ(Q){let Z=[];Z.push("| Flag | Type | Required | Description |"),Z.push("| ---- | ---- | -------- | ----------- |");for(let X of Q){let W=cQ(X),$=X.required?"Yes":"No",q=BQ(gQ(X));Z.push(`| ${W} | ${X.type} | ${$} | ${q} |`)}return Z}function cQ(Q){let Z=[`\`--${Q.name}\``];if(Q.short)Z.push(`\`-${Q.short}\``);for(let X of Q.aliases)Z.push(`\`--${X}\``);return Z.join(", ")}function gQ(Q){let Z=[];if(Q.description)Z.push(Q.description);if(Q.multiple)Z.push("Can be specified multiple times");if(Q.default!==void 0)Z.push(`Default: \`${Q.default}\``);return Z.join(". ")||"-"}function OQ(Q,Z){let X=[],W=b(Q);if(X.push("---"),X.push(""),Q.path.length>1){let q=Q.path.slice(0,-1),B=MQ(Z,q);if(B){let J=b(B),z=o(W,J),K=m(B);X.push(`Parent: [\`${K}\`](${z})`),X.push("")}}let $=o(W,"SKILL.md");return X.push(`[Skill Overview](${$})`),X.push(""),X}function MQ(Q,Z){if(mQ(Q.path,Z))return Q;for(let X of Q.children){let W=MQ(X,Z);if(W)return W}return}function mQ(Q,Z){if(Q.length!==Z.length)return!1;for(let X=0;X<Q.length;X++)if(Q[X]!==Z[X])return!1;return!0}import{readFile as dQ}from"fs/promises";import{join as rQ}from"path";var a="crust.json";async function n(Q){try{let Z=await dQ(rQ(Q,a),"utf-8"),X=JSON.parse(Z);if(typeof X==="object"&&X!==null&&"version"in X&&typeof X.version==="string")return X.version;return null}catch{return null}}var wQ=/^[a-z0-9]+(-[a-z0-9]+)*$/;function UQ(Q){return Q.length>=1&&Q.length<=64&&wQ.test(Q)}function A(Q){return Q.startsWith("use-")?Q:`use-${Q}`}async function S(Q){let{command:Z,meta:X,agents:W,scope:$="global",clean:q=!0,force:B=!1}=Q,J=A(X.name);if(!UQ(J))throw Error(`Invalid skill name "${J}": must be 1\u201364 lowercase `+`alphanumeric characters and hyphens, no leading/trailing/consecutive hyphens. Pattern: ${wQ.source}`);let z={...X,name:J},K=$Q(Z),x=YQ(K,z),G=tQ(z),F=[...x,...G].sort((O,M)=>O.path<M.path?-1:O.path>M.path?1:0),V=[],D=new Map;for(let O of W){let M=g(O,$,z.name),T=D.get(M);if(T)T.push(O);else D.set(M,[O])}for(let[O,M]of D){let T=M[0];if(!T)continue;let I=await n(O);if(I===null){if(await VQ(O).then(()=>!0).catch(()=>!1)&&!B)throw new P({agent:T,outputDir:O})}let L=I===null?"installed":I===z.version?"up-to-date":"updated";if(L==="up-to-date"){for(let k of M)V.push({agent:k,outputDir:O,files:[],status:"up-to-date"});continue}let u=L==="updated"?I??void 0:void 0;if(q)await aQ(O);await nQ(O,F);for(let k of M)V.push({agent:k,outputDir:O,files:F.map((l)=>l.path),status:L,previousVersion:u})}return{agents:V}}async function e(Q){let{name:Z,agents:X,scope:W="global"}=Q,$=A(Z),q=[],B=new Map;for(let J of X){let z=g(J,W,$),K=B.get(z);if(K)K.push(J);else B.set(z,[J])}for(let[J,z]of B)if(await VQ(J).then(()=>!0).catch(()=>!1)){await GQ(J,{recursive:!0,force:!0});for(let x of z)q.push({agent:x,outputDir:J,status:"removed"})}else for(let x of z)q.push({agent:x,outputDir:J,status:"not-found"});return{agents:q}}async function h(Q){let{name:Z,agents:X,scope:W="global"}=Q,$=A(Z),q=[],B=new Map;for(let J of X){let z=g(J,W,$),K=B.get(z);if(K)K.push(J);else B.set(z,[J])}for(let[J,z]of B){let K=await n(J);for(let x of z)q.push({agent:x,outputDir:J,installed:K!==null,version:K??void 0})}return{agents:q}}function tQ(Q){return[{path:a,content:oQ(Q)}]}function oQ(Q){let Z={name:Q.name,description:Q.description,version:Q.version};return`${JSON.stringify(Z,null,"\t")}
|
|
6
|
+
`}async function aQ(Q){await GQ(Q,{recursive:!0,force:!0})}async function nQ(Q,Z){let X=new Set;for(let $ of Z){let q=FQ(Q,$.path),B=sQ(q);X.add(B)}let W=[...X].sort();for(let $ of W)await lQ($,{recursive:!0});for(let $ of Z){let q=FQ(Q,$.path);await iQ(q,$.content,"utf-8")}}import{Crust as yQ,VALIDATION_MODE_ENV as eQ}from"@crustjs/core";import{confirm as QX,multiselect as XX,select as ZX,spinner as p}from"@crustjs/prompts";import{bold as r,dim as C,yellow as kQ}from"@crustjs/style";var WX="skill",$X="global",d="__universal__";function HX(Q){return Q==="global"||Q==="project"}async function PQ(Q,Z){if(Q!==void 0){if(!HX(Q))throw Error(`Invalid --scope value: ${String(Q)}. Expected "project" or "global".`);return Q}if(Z.defaultScope)return Z.defaultScope;return ZX({message:"Select scope",choices:[{label:"Project",value:"project"},{label:"Global",value:"global"}],default:$X})}function QQ(Q){let Z=new Set(E()),X=[];if(Q.some((W)=>Z.has(W)))X.push("Universal");for(let W of Q){if(Z.has(W))continue;X.push(j[W])}return X}function RQ(Q){let Z=new Set(E()),X=[],W=Q.find(($)=>Z.has($.agent));if(W)X.push({label:"Universal",outputDir:W.outputDir});for(let $ of Q){if(Z.has($.agent))continue;X.push({label:j[$.agent],outputDir:$.outputDir})}return X}function XQ(Q,Z){return{name:Q.meta.name,description:Q.meta.description??"",version:Z}}async function qX(Q,Z){let X=await v(),W=[...E(),...X];if(W.length===0)return;let $=XQ(Q,Z.version),q=["project","global"];for(let B of q){let z=(await h({name:$.name,agents:W,scope:B})).agents.filter((K)=>K.installed&&K.version!==$.version);if(z.length===0)continue;try{await p({message:`Updating ${B} skills...`,task:async({updateMessage:K})=>{let x=await S({command:Q,meta:$,agents:z.map((V)=>V.agent),scope:B}),G=x.agents.filter((V)=>V.status==="updated").map((V)=>V.agent),F=QQ(G);if(F.length>0)K(`Updated skill "${A($.name)}" to v${$.version} for ${F.join(", ")} (${B})`);return x}})}catch(K){if(K instanceof P)console.warn(kQ(`Skill conflict: "${K.details.outputDir}" already exists but was not created by ${$.name}. Skipping auto-update for ${B}. Delete or rename the conflicting skill to resolve.`));else throw K}}}function BX(Q){let Z;return{name:"skills",async setup(X,W){Z=X.rootCommand;let $=Q.command??WX;if(W.addSubCommand(Z,$,YX(Z,Q,$)),process.env[eQ]==="1")return;if(X.argv[0]===$)return;if(Q.autoUpdate!==!1)await qX(Z,Q)}}}function YX(Q,Z,X){let W=zX(Q,Z);return new yQ(X).meta({description:"Manage agent skill installations"}).flags({scope:{type:"string",description:"Install scope (project or global)"}}).run(async($)=>{let q=XQ(Q,Z.version),B=await PQ($.flags.scope,Z),J=await v(),z=E(),K=c(),x=await h({name:q.name,agents:[...z,...K],scope:B}),G=new Set(x.agents.filter((Y)=>Y.installed).map((Y)=>Y.agent)),F=new Set(J),V=new Map(x.agents.map((Y)=>[Y.agent,Y])),D=K.filter((Y)=>{if(F.has(Y))return!0;return V.get(Y)?.installed===!0}),O=D.filter((Y)=>G.has(Y)),M=[];if(z.length>0){let Y=z[0];if(!Y)throw Error("Expected at least one universal agent");let U=V.get(Y)?.outputDir??"path unavailable";M.push({label:"Universal",value:d,hint:U}),console.log(C("Universal installs to the shared .agents/skills directory."))}for(let Y of D){let U=V.get(Y)?.outputDir??"path unavailable";M.push({label:j[Y],value:Y,hint:U})}let T=z.length>0&&z.every((Y)=>G.has(Y)),I=[...O.filter((Y)=>!z.includes(Y))];if(T)I.unshift(d);let L=M.length===0?[]:await XX({message:"Select agents to install skills for",choices:M,default:I,required:!1}),u=new Set(L.filter((Y)=>Y!==d));if(L.includes(d))for(let Y of z)u.add(Y);let k=[...u],l=k.filter((Y)=>!G.has(Y)),TQ=k.filter((Y)=>{let w=x.agents.find((U)=>U.agent===Y);return w?.installed===!0&&w.version!==q.version}),i=[...G].filter((Y)=>!k.includes(Y)),s=[...l,...TQ];if(s.length>0)try{let Y=await p({message:"Installing skills...",task:async()=>S({command:Q,meta:q,agents:s,scope:B})});console.log(`
|
|
7
|
+
${r(`Installed "${q.name}" v${q.version}`)}`);for(let w of RQ(Y.agents))console.log(C(` ${w.label} \u2192 ${w.outputDir}`))}catch(Y){if(Y instanceof P)if(await QX({message:`"${Y.details.outputDir}" already exists but was not created by Crust. Overwrite?`,default:!1})){let U=await p({message:"Overwriting skill...",task:async()=>S({command:Q,meta:q,agents:[Y.details.agent],scope:B,force:!0})});console.log(`
|
|
8
|
+
${r(`Installed "${q.name}" v${q.version}`)}`);for(let N of RQ(U.agents))console.log(C(` ${N.label} \u2192 ${N.outputDir}`))}else console.log(C(`
|
|
9
|
+
Skipped ${j[Y.details.agent]}`));else throw Y}if(i.length>0){let w=(await p({message:"Removing skills...",task:async()=>e({name:q.name,agents:i,scope:B})})).agents.filter((N)=>N.status==="removed").map((N)=>N.agent),U=QQ(w);if(U.length>0)console.log(`
|
|
10
|
+
${r(`Removed from ${U.join(", ")}`)}`)}if(s.length===0&&i.length===0)console.log(C("No changes."))}).command(W)._node}function zX(Q,Z){return new yQ("update").meta({description:"Update installed skills to latest version"}).flags({scope:{type:"string",description:"Update scope (project or global)"}}).run(async(X)=>{let W=await PQ(X.flags.scope,Z),$=await v(),q=[...E(),...$];if(q.length===0){console.log(C("No supported agents detected."));return}let B=XQ(Q,Z.version),z=(await h({name:B.name,agents:q,scope:W})).agents.filter((K)=>K.installed&&K.version!==B.version);if(z.length===0){console.log(C(`No updates needed (${W}).`));return}try{let x=(await p({message:`Updating ${W} skills...`,task:async()=>S({command:Q,meta:B,agents:z.map((F)=>F.agent),scope:W})})).agents.filter((F)=>F.status==="updated").map((F)=>F.agent),G=QQ(x);if(G.length>0)console.log(`
|
|
11
|
+
${r(`Updated "${B.name}" to v${B.version} for ${G.join(", ")} (${W})`)}`)}catch(K){if(K instanceof P)console.warn(kQ(`Skipped ${j[K.details.agent]}: "${K.details.outputDir}" already exists but was not created by ${B.name}. Delete or rename the conflicting directory to resolve.`));else throw K}})}export{e as uninstallSkill,h as skillStatus,BX as skillPlugin,A as resolveSkillName,UQ as isValidSkillName,_Q as isUniversalAgent,E as getUniversalAgents,c as getAdditionalAgents,S as generateSkill,v as detectInstalledAgents,P as SkillConflictError};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crustjs/skills",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Agent skill generation from Crust command definitions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,11 +47,11 @@
|
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@crustjs/config": "0.0.0",
|
|
50
|
-
"@crustjs/core": "0.0.
|
|
50
|
+
"@crustjs/core": "0.0.12",
|
|
51
51
|
"bunup": "^0.16.29"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@crustjs/core": "0.0.
|
|
54
|
+
"@crustjs/core": "0.0.12",
|
|
55
55
|
"typescript": "^5"
|
|
56
56
|
}
|
|
57
57
|
}
|