@crustjs/skills 0.0.15 → 0.0.17

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 CHANGED
@@ -59,6 +59,13 @@ runMain(app, {
59
59
  plugins: [
60
60
  skillPlugin({
61
61
  version: "1.0.0",
62
+ instructions: `
63
+ Prefer readonly commands before mutating project state.
64
+
65
+ ## Response Policy
66
+
67
+ - Read the relevant command doc before suggesting flags.
68
+ `,
62
69
  // autoUpdate: true (default) — silently updates installed skills
63
70
  // command: "skill" (default) — registers "my-cli skill" subcommand
64
71
  // defaultScope: "global" | "project" — skip scope prompt when set
@@ -135,6 +142,53 @@ if (import.meta.main) {
135
142
  }
136
143
  ```
137
144
 
145
+ ### Custom Instructions
146
+
147
+ Use plugin-level `instructions` to add top-level guidance to the generated
148
+ `SKILL.md`, and `annotate()` to add prompt guidance to specific
149
+ command docs under `commands/`.
150
+
151
+ - `instructions: string` renders as a raw markdown block.
152
+ - `instructions: string[]` renders as bullet list items.
153
+ - Empty or whitespace-only instruction input is ignored.
154
+ - `annotate()` always renders command guidance as bullets.
155
+
156
+ ```ts
157
+ import { Crust } from "@crustjs/core";
158
+ import { annotate, skillPlugin } from "@crustjs/skills";
159
+
160
+ const deploy = annotate(
161
+ new Crust("deploy")
162
+ .meta({ description: "Deploy the application" })
163
+ .flags({
164
+ "dry-run": { type: "boolean", description: "Preview changes only" },
165
+ })
166
+ .run(() => {
167
+ // ...
168
+ }),
169
+ [
170
+ "Prefer `--dry-run` before executing deployment changes.",
171
+ "Ask for confirmation before production deployments.",
172
+ ],
173
+ );
174
+
175
+ const app = new Crust("my-cli")
176
+ .meta({ description: "My CLI" })
177
+ .use(
178
+ skillPlugin({
179
+ version: "1.0.0",
180
+ instructions: `
181
+ Read command docs before suggesting exact flags.
182
+
183
+ ## Answer Style
184
+
185
+ - Prefer exact syntax copied from the relevant command file.
186
+ `,
187
+ }),
188
+ )
189
+ .command(deploy);
190
+ ```
191
+
138
192
  This pattern lets `crust skills generate` import the command definition without triggering `runMain`.
139
193
 
140
194
  ## CLI Usage
@@ -191,7 +245,12 @@ import { generateSkill } from "@crustjs/skills";
191
245
 
192
246
  const result = await generateSkill({
193
247
  command: rootCommand,
194
- meta: { name: "my-cli", description: "My CLI tool", version: "1.0.0" },
248
+ meta: {
249
+ name: "my-cli",
250
+ description: "My CLI tool",
251
+ version: "1.0.0",
252
+ instructions: ["Prefer readonly commands before making changes."],
253
+ },
195
254
  agents: ["opencode"],
196
255
  scope: "project", // default: "global"
197
256
  installMode: "auto", // default: "auto" — symlink first, fallback to copy
package/dist/index.d.ts CHANGED
@@ -67,6 +67,18 @@ interface SkillMeta {
67
67
  * @example "Bash(my-cli *) Read Grep"
68
68
  */
69
69
  allowedTools?: string;
70
+ /**
71
+ * Additional top-level instructions rendered into `SKILL.md`.
72
+ *
73
+ * Use this for plugin- or product-specific guidance that should be visible
74
+ * before agents inspect individual command documentation files.
75
+ *
76
+ * **Note:** When a `string` value contains markdown headings (e.g. `## Foo`),
77
+ * they are rendered at the same level as `## General Guidance`, not nested
78
+ * under it. Use a `string[]` of plain instructions to avoid unintended
79
+ * heading hierarchy.
80
+ */
81
+ instructions?: string | string[];
70
82
  }
71
83
  /** Supported agent targets for skill installation. */
72
84
  type AgentTarget = "amp" | "adal" | "antigravity" | "augment" | "claude-code" | "cline" | "codebuddy" | "codex" | "command-code" | "continue" | "cortex" | "crush" | "cursor" | "droid" | "gemini-cli" | "github-copilot" | "goose" | "iflow-cli" | "junie" | "kilo" | "kimi-cli" | "kiro-cli" | "kode" | "mcpjam" | "mistral-vibe" | "mux" | "neovate" | "opencode" | "openclaw" | "openhands" | "pi" | "pochi" | "qoder" | "qwen-code" | "replit" | "roo" | "trae" | "trae-cn" | "windsurf" | "zencoder";
@@ -254,6 +266,30 @@ interface SkillPluginOptions {
254
266
  */
255
267
  autoUpdate?: boolean;
256
268
  /**
269
+ * Additional top-level instructions rendered into the generated `SKILL.md`.
270
+ *
271
+ * **Note:** When a `string` value contains markdown headings (e.g. `## Foo`),
272
+ * they are rendered at the same level as `## General Guidance`, not nested
273
+ * under it. Use a `string[]` of plain instructions to avoid unintended
274
+ * heading hierarchy.
275
+ */
276
+ instructions?: string | string[];
277
+ /** License name or reference emitted in SKILL.md frontmatter. */
278
+ license?: string;
279
+ /**
280
+ * Space-delimited list of pre-approved tools the skill may use.
281
+ *
282
+ * @example "Bash(my-cli *) Read Grep"
283
+ */
284
+ allowedTools?: string;
285
+ /** Environment requirements or compatibility notes (max 500 chars). */
286
+ compatibility?: string;
287
+ /**
288
+ * When `true`, prevents agents from automatically loading this skill.
289
+ * @default false
290
+ */
291
+ disableModelInvocation?: boolean;
292
+ /**
257
293
  * Register an interactive skill management subcommand on the root command.
258
294
  *
259
295
  * The command presents a single multiselect prompt listing all detected
@@ -293,6 +329,27 @@ declare function detectInstalledAgents(options?: string | DetectInstalledAgentsO
293
329
  * Resolves the canonical skill bundle path used by Crust.
294
330
  */
295
331
  declare function resolveCanonicalSkillPath(scope: Scope, name: string): string;
332
+ import { CommandNode as CommandNode2 } from "@crustjs/core";
333
+ import { Crust } from "@crustjs/core";
334
+ /**
335
+ * Agent-oriented instructions attached to a command for skills rendering.
336
+ */
337
+ interface SkillCommandAnnotations {
338
+ /** Additional prompt guidance rendered into the command's markdown file */
339
+ instructions?: string[];
340
+ }
341
+ type SkillCommandTarget = CommandNode2 | Crust<any, any, any>;
342
+ /**
343
+ * Attaches agent-facing instructions to a command definition without changing
344
+ * the public `@crustjs/core` API surface.
345
+ *
346
+ * The instructions are stored on the internal command node using an enumerable
347
+ * symbol so they survive Crust's immutable clone/spread builder operations.
348
+ *
349
+ * Duplicate instructions are silently deduplicated — calling `annotate()` again
350
+ * with the same text is a safe no-op.
351
+ */
352
+ declare function annotate<T extends SkillCommandTarget>(target: T, annotations: string | string[] | SkillCommandAnnotations): T;
296
353
  /** Details about the conflict between an existing skill and an incoming one. */
297
354
  interface SkillConflictDetails {
298
355
  /** The agent where the conflict was detected */
@@ -436,10 +493,10 @@ import { CrustPlugin } from "@crustjs/core";
436
493
  * version: "1.0.0",
437
494
  * command: "skill", // registers "my-cli skill" subcommand
438
495
  * }))
439
- * .run(() => { /* ... *​/ });
496
+ * .run(() => { /* ... *�/ });
440
497
  *
441
498
  * await app.execute();
442
499
  * ```
443
500
  */
444
501
  declare function skillPlugin(options: SkillPluginOptions): CrustPlugin;
445
- export { uninstallSkill, skillStatus, skillPlugin, resolveSkillName, resolveCanonicalSkillPath, isValidSkillName, isUniversalAgent, getUniversalAgents, getAdditionalAgents, generateSkill, detectInstalledAgents, UninstallStatus, UninstallResult, UninstallOptions, StatusResult, StatusOptions, SkillPluginOptions, SkillMeta, SkillInstallMode, SkillConflictError, SkillConflictDetails, Scope, InstallStatus, GenerateResult, GenerateOptions, AgentTarget, AgentResult, AgentClass };
502
+ export { uninstallSkill, skillStatus, skillPlugin, resolveSkillName, resolveCanonicalSkillPath, isValidSkillName, isUniversalAgent, getUniversalAgents, getAdditionalAgents, generateSkill, detectInstalledAgents, annotate, UninstallStatus, UninstallResult, UninstallOptions, StatusResult, StatusOptions, SkillPluginOptions, SkillMeta, SkillInstallMode, SkillConflictError, SkillConflictDetails, SkillCommandAnnotations, Scope, InstallStatus, GenerateResult, GenerateOptions, AgentTarget, AgentResult, AgentClass };
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // @bun
2
- import{accessSync as fQ,constants as hQ}from"fs";import{homedir as n}from"os";import{delimiter as uQ,join as B}from"path";var y=B(".agents","skills"),cQ=B(".crust","skills");function YQ(Q){if(Q!==n())return B(Q,".config");let X=process.env.XDG_CONFIG_HOME?.trim();return X&&X.length>0?X:B(Q,".config")}function k(Q){return B(Q,".agents","skills")}function pQ(Q){return B(Q,".crust","skills")}var E={amp:{label:"Amp",class:"universal",projectSkillsDir:y,globalSkillsDir:k},adal:{label:"AdaL",class:"additional",projectSkillsDir:B(".adal","skills"),globalSkillsDir:(Q)=>B(Q,".adal","skills"),detectCommands:["adal"]},antigravity:{label:"Antigravity",class:"additional",projectSkillsDir:B(".agent","skills"),globalSkillsDir:(Q)=>B(Q,".gemini","antigravity","skills"),detectCommands:["antigravity"]},augment:{label:"Augment",class:"additional",projectSkillsDir:B(".augment","skills"),globalSkillsDir:(Q)=>B(Q,".augment","skills"),detectCommands:["augment"]},"claude-code":{label:"Claude Code",class:"additional",projectSkillsDir:B(".claude","skills"),globalSkillsDir:(Q)=>B(process.env.CLAUDE_CONFIG_DIR?.trim()||B(Q,".claude"),"skills"),detectCommands:["claude","claude-code"]},cline:{label:"Cline",class:"universal",projectSkillsDir:y,globalSkillsDir:k},codebuddy:{label:"CodeBuddy",class:"additional",projectSkillsDir:B(".codebuddy","skills"),globalSkillsDir:(Q)=>B(Q,".codebuddy","skills"),detectCommands:["codebuddy"]},codex:{label:"Codex",class:"universal",projectSkillsDir:y,globalSkillsDir:k},"command-code":{label:"Command Code",class:"additional",projectSkillsDir:B(".commandcode","skills"),globalSkillsDir:(Q)=>B(Q,".commandcode","skills"),detectCommands:["command-code","commandcode"]},continue:{label:"Continue",class:"additional",projectSkillsDir:B(".continue","skills"),globalSkillsDir:(Q)=>B(Q,".continue","skills"),detectCommands:["continue"]},cortex:{label:"Cortex Code",class:"additional",projectSkillsDir:B(".cortex","skills"),globalSkillsDir:(Q)=>B(Q,".snowflake","cortex","skills"),detectCommands:["cortex"]},crush:{label:"Crush",class:"additional",projectSkillsDir:B(".crush","skills"),globalSkillsDir:(Q)=>B(YQ(Q),"crush","skills"),detectCommands:["crush"]},cursor:{label:"Cursor",class:"universal",projectSkillsDir:y,globalSkillsDir:k},droid:{label:"Droid",class:"additional",projectSkillsDir:B(".factory","skills"),globalSkillsDir:(Q)=>B(Q,".factory","skills"),detectCommands:["droid"]},"gemini-cli":{label:"Gemini CLI",class:"universal",projectSkillsDir:y,globalSkillsDir:k},"github-copilot":{label:"GitHub Copilot",class:"universal",projectSkillsDir:y,globalSkillsDir:k},goose:{label:"Goose",class:"additional",projectSkillsDir:B(".goose","skills"),globalSkillsDir:(Q)=>B(YQ(Q),"goose","skills"),detectCommands:["goose"]},"iflow-cli":{label:"iFlow CLI",class:"additional",projectSkillsDir:B(".iflow","skills"),globalSkillsDir:(Q)=>B(Q,".iflow","skills"),detectCommands:["iflow","iflow-cli"]},junie:{label:"Junie",class:"additional",projectSkillsDir:B(".junie","skills"),globalSkillsDir:(Q)=>B(Q,".junie","skills"),detectCommands:["junie"]},kilo:{label:"Kilo Code",class:"additional",projectSkillsDir:B(".kilocode","skills"),globalSkillsDir:(Q)=>B(Q,".kilocode","skills"),detectCommands:["kilo","kilocode"]},"kimi-cli":{label:"Kimi Code CLI",class:"universal",projectSkillsDir:y,globalSkillsDir:k},"kiro-cli":{label:"Kiro CLI",class:"additional",projectSkillsDir:B(".kiro","skills"),globalSkillsDir:(Q)=>B(Q,".kiro","skills"),detectCommands:["kiro","kiro-cli"]},kode:{label:"Kode",class:"additional",projectSkillsDir:B(".kode","skills"),globalSkillsDir:(Q)=>B(Q,".kode","skills"),detectCommands:["kode"]},mcpjam:{label:"MCPJam",class:"additional",projectSkillsDir:B(".mcpjam","skills"),globalSkillsDir:(Q)=>B(Q,".mcpjam","skills"),detectCommands:["mcpjam"]},"mistral-vibe":{label:"Mistral Vibe",class:"additional",projectSkillsDir:B(".vibe","skills"),globalSkillsDir:(Q)=>B(Q,".vibe","skills"),detectCommands:["mistral-vibe","vibe"]},mux:{label:"Mux",class:"additional",projectSkillsDir:B(".mux","skills"),globalSkillsDir:(Q)=>B(Q,".mux","skills"),detectCommands:["mux"]},neovate:{label:"Neovate",class:"additional",projectSkillsDir:B(".neovate","skills"),globalSkillsDir:(Q)=>B(Q,".neovate","skills"),detectCommands:["neovate"]},opencode:{label:"OpenCode",class:"universal",projectSkillsDir:y,globalSkillsDir:k},openclaw:{label:"OpenClaw",class:"additional",projectSkillsDir:"skills",globalSkillsDir:(Q)=>B(Q,".openclaw","skills"),detectCommands:["openclaw"]},openhands:{label:"OpenHands",class:"additional",projectSkillsDir:B(".openhands","skills"),globalSkillsDir:(Q)=>B(Q,".openhands","skills"),detectCommands:["openhands"]},pi:{label:"Pi",class:"additional",projectSkillsDir:B(".pi","skills"),globalSkillsDir:(Q)=>B(Q,".pi","agent","skills"),detectCommands:["pi"]},pochi:{label:"Pochi",class:"additional",projectSkillsDir:B(".pochi","skills"),globalSkillsDir:(Q)=>B(Q,".pochi","skills"),detectCommands:["pochi"]},qoder:{label:"Qoder",class:"additional",projectSkillsDir:B(".qoder","skills"),globalSkillsDir:(Q)=>B(Q,".qoder","skills"),detectCommands:["qoder"]},"qwen-code":{label:"Qwen Code",class:"additional",projectSkillsDir:B(".qwen","skills"),globalSkillsDir:(Q)=>B(Q,".qwen","skills"),detectCommands:["qwen","qwen-code"]},replit:{label:"Replit",class:"universal",projectSkillsDir:y,globalSkillsDir:k},roo:{label:"Roo Code",class:"additional",projectSkillsDir:B(".roo","skills"),globalSkillsDir:(Q)=>B(Q,".roo","skills"),detectCommands:["roo","roo-code"]},trae:{label:"Trae",class:"additional",projectSkillsDir:B(".trae","skills"),globalSkillsDir:(Q)=>B(Q,".trae","skills"),detectCommands:["trae"]},"trae-cn":{label:"Trae CN",class:"additional",projectSkillsDir:B(".trae","skills"),globalSkillsDir:(Q)=>B(Q,".trae-cn","skills"),detectCommands:["trae-cn","trae"]},windsurf:{label:"Windsurf",class:"additional",projectSkillsDir:B(".windsurf","skills"),globalSkillsDir:(Q)=>B(Q,".codeium","windsurf","skills"),detectCommands:["windsurf"]},zencoder:{label:"Zencoder",class:"additional",projectSkillsDir:B(".zencoder","skills"),globalSkillsDir:(Q)=>B(Q,".zencoder","skills"),detectCommands:["zencoder"]}},p=Object.keys(E),j=Object.fromEntries(p.map((Q)=>[Q,E[Q].label]));function P(){return p.filter((Q)=>E[Q].class==="universal")}function D(){return p.filter((Q)=>E[Q].class==="additional")}function gQ(Q){return E[Q].class==="universal"}async function e(Q){let X=typeof Q==="string"?{home:Q}:Q??{},Z=X.cwd??process.cwd(),$=X.commandChecker??((W)=>Promise.resolve(mQ(W))),H=[];for(let W of D()){let z=E[W].detectCommands??[],J=!1;for(let q of z)if(await $(q,Z)){J=!0;break}if(J)H.push(W)}return H}function v(Q,X,Z){let $=E[Q];if(X==="project")return B(process.cwd(),$.projectSkillsDir,Z);return B($.globalSkillsDir(n()),Z)}function s(Q,X){if(Q==="project")return B(process.cwd(),cQ,X);return B(pQ(n()),X)}function mQ(Q){let Z=(process.env.PATH??"").split(uQ).filter((W)=>W.length>0),$=process.platform==="win32",H=$?(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";").filter((W)=>W.length>0):[];for(let W of Z){if(!$&&qQ(B(W,Q)))return!0;if($){for(let z of H)if(qQ(B(W,Q+z)))return!0}}return!1}function qQ(Q){try{return fQ(Q,hQ.X_OK),!0}catch{return!1}}class b extends Error{name="SkillConflictError";details;constructor(Q){let X=`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(X);this.details=Q}}import{lstat as kQ,mkdir as bQ,readlink as YZ,realpath as qZ,rm as XQ,symlink as zZ,writeFile as JZ}from"fs/promises";import{dirname as IQ,join as RQ}from"path";function zQ(Q){return JQ(Q,[])}function JQ(Q,X){let Z=dQ(Q.meta.name),$=[...X,Z],H=rQ(Q.args),W=sQ(Q.effectiveFlags),z=oQ(Q.subCommands,$);return{name:Z,path:$,description:Q.meta.description,usage:Q.meta.usage,runnable:typeof Q.run==="function",args:H,flags:W,children:z}}function dQ(Q){return Q.trim().toLowerCase()}function rQ(Q){if(!Q||Q.length===0)return[];return Q.map(lQ)}function lQ(Q){let X={name:Q.name,type:Q.type,required:Q.required===!0,variadic:Q.variadic===!0};if(Q.description!==void 0)X.description=Q.description;if(Q.default!==void 0)X.default=KQ(Q.default);return X}function sQ(Q){if(!Q)return[];return Object.keys(Q).sort().map((Z)=>{return iQ(Z,Q[Z])})}function iQ(Q,X){let Z={name:Q,type:X.type,required:X.required===!0,multiple:X.multiple===!0,short:X.short,aliases:X.aliases?[...X.aliases].sort():[]};if(X.description!==void 0)Z.description=X.description;if(X.default!==void 0)Z.default=KQ(X.default);return Z}function oQ(Q,X){return Object.keys(Q).sort().map(($)=>{return JQ(Q[$],X)})}function KQ(Q){if(Array.isArray(Q))return JSON.stringify(Q);return String(Q)}function g(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 xQ(Q){return Q.replace(/(?<!\\)\|/g,"\\|")}function MQ(Q,X){let Z=[],$=GQ(Q);Z.push({path:"SKILL.md",content:tQ(Q,X,$)});for(let H of $){let W=L(H),z=H.children.length>0?QZ(H,Q):eQ(H,Q);Z.push({path:W,content:z})}return Z}function GQ(Q){let X=[Q];for(let Z of Q.children)X.push(...GQ(Z));return X}function L(Q){if(Q.path.length<=1)return`commands/${Q.name}.md`;return`commands/${Q.path.slice(1).join("/")}.md`}function i(Q){return Q.path.join(" ")}function QQ(Q,X){let Z=Q.split("/").slice(0,-1),$=X.split("/"),H=0;while(H<Z.length&&H<$.length&&Z[H]===$[H])H++;let W=Z.length-H,z=$.slice(H);if(W===0)return z.join("/");return[...Array.from({length:W},()=>".."),...z].join("/")}function tQ(Q,X,Z){let $=[];if($.push("---"),$.push(`name: ${g(X.name)}`),$.push(`description: ${g(X.description)}`),X.license)$.push(`license: ${g(X.license)}`);if(X.compatibility)$.push(`compatibility: ${g(X.compatibility)}`);if(X.disableModelInvocation)$.push("disable-model-invocation: true");if(X.allowedTools)$.push(`allowed-tools: ${g(X.allowedTools)}`);if($.push("metadata:"),$.push(` version: "${X.version}"`),$.push("---"),$.push(""),$.push(`# ${X.name}`),$.push(""),Q.description)$.push(Q.description),$.push("");let H=X.name.startsWith("use-")?X.name.slice(4):X.name;if($.push(`Use this skill when working with \`${H}\` commands, or when you need help with \`${H}\` syntax, flags, or subcommands.`),$.push(""),$.push("## Command Reference"),$.push(""),$.push("This table lists all commands and their documentation paths. **Do not read all command files at once.** Instead:"),$.push(""),$.push("1. Use the table below to find the relevant command"),$.push("2. Use the `Type` column to choose what to execute: commands labeled `runnable` (including `runnable, group`) are executable, while `group` commands are not"),$.push("3. Read only the specific file from the `commands/` directory that you need"),$.push("4. For any command-specific answer, read that command's documentation file before responding"),$.push("5. Treat the command documentation file as the source of truth for usage, flags, options, aliases, and defaults"),$.push("6. Do not invent or assume undocumented flags/options; if something is missing from the file, say it is not documented"),$.push(""),$.push(...aQ(Z)),$.push(""),Q.runnable){$.push("## Usage"),$.push("");let W=L(Q);$.push(`The root command is directly executable. See [${Q.name}](${W}) for usage details.`),$.push("")}return $.join(`
3
- `)}function aQ(Q){let X=[];X.push("| Command | Type | Documentation |"),X.push("| ------- | ---- | ------------- |");for(let Z of Q){let $=i(Z),H=L(Z),W=nQ(Z);X.push(`| \`${$}\` | ${W} | [${H}](${H}) |`)}return X}function nQ(Q){if(Q.runnable&&Q.children.length>0)return"runnable, group";if(Q.runnable)return"runnable";return"group"}function eQ(Q,X){let Z=[],$=i(Q);if(Z.push(`# \`${$}\``),Z.push(""),Q.description)Z.push(Q.description),Z.push("");if(Z.push("## Usage"),Z.push(""),Q.usage)Z.push("```"),Z.push(Q.usage),Z.push("```");else Z.push("```"),Z.push(wQ(Q)),Z.push("```");if(Z.push(""),Q.args.length>0)Z.push("## Arguments"),Z.push(""),Z.push(...FQ(Q.args)),Z.push("");if(Q.flags.length>0)Z.push("## Flags"),Z.push(""),Z.push(...OQ(Q.flags)),Z.push("");return Z.push("## Command Documentation Authority"),Z.push(""),Z.push("Only arguments, flags, options, aliases, and defaults documented in this file are supported for this command."),Z.push("Do not infer or invent additional command-line options."),Z.push(""),Z.push(...UQ(Q,X)),Z.join(`
4
- `)}function QZ(Q,X){let Z=[],$=i(Q),H=L(Q);if(Z.push(`# \`${$}\``),Z.push(""),Q.description)Z.push(Q.description),Z.push("");if(Q.runnable){if(Z.push("## Usage"),Z.push(""),Q.usage)Z.push("```"),Z.push(Q.usage),Z.push("```");else Z.push("```"),Z.push(wQ(Q)),Z.push("```");if(Z.push(""),Q.args.length>0)Z.push("## Arguments"),Z.push(""),Z.push(...FQ(Q.args)),Z.push("");if(Q.flags.length>0)Z.push("## Flags"),Z.push(""),Z.push(...OQ(Q.flags)),Z.push("");Z.push("## Command Documentation Authority"),Z.push(""),Z.push("Only arguments, flags, options, aliases, and defaults documented in this file are supported for this command."),Z.push("Do not infer or invent additional command-line options."),Z.push("")}Z.push("## Subcommands"),Z.push("");for(let W of Q.children){let z=L(W),J=QQ(H,z),q=W.description?` - ${W.description}`:"";Z.push(`- [\`${W.name}\`](${J})${q}`)}return Z.push(""),Z.push(...UQ(Q,X)),Z.join(`
5
- `)}function wQ(Q){let X=[...Q.path];for(let Z of Q.args)if(Z.variadic)X.push(Z.required?`<${Z.name}...>`:`[${Z.name}...]`);else X.push(Z.required?`<${Z.name}>`:`[${Z.name}]`);if(Q.flags.length>0)X.push("[options]");return X.join(" ")}function FQ(Q){let X=[];X.push("| Argument | Type | Required | Description |"),X.push("| -------- | ---- | -------- | ----------- |");for(let Z of Q){let $=Z.variadic?`${Z.name}...`:Z.name,H=Z.required?"Yes":"No",W=xQ(ZZ(Z));X.push(`| \`${$}\` | ${Z.type} | ${H} | ${W} |`)}return X}function ZZ(Q){let X=[];if(Q.description)X.push(Q.description);if(Q.default!==void 0)X.push(`Default: \`${Q.default}\``);return X.join(". ")||"-"}function OQ(Q){let X=[];X.push("| Flag | Type | Required | Description |"),X.push("| ---- | ---- | -------- | ----------- |");for(let Z of Q){let $=XZ(Z),H=Z.required?"Yes":"No",W=xQ($Z(Z));X.push(`| ${$} | ${Z.type} | ${H} | ${W} |`)}return X}function XZ(Q){let X=[`\`--${Q.name}\``];if(Q.short)X.push(`\`-${Q.short}\``);for(let Z of Q.aliases)X.push(`\`--${Z}\``);return X.join(", ")}function $Z(Q){let X=[];if(Q.description)X.push(Q.description);if(Q.multiple)X.push("Can be specified multiple times");if(Q.default!==void 0)X.push(`Default: \`${Q.default}\``);return X.join(". ")||"-"}function UQ(Q,X){let Z=[],$=L(Q);if(Z.push("---"),Z.push(""),Q.path.length>1){let W=Q.path.slice(0,-1),z=VQ(X,W);if(z){let J=L(z),q=QQ($,J),K=i(z);Z.push(`Parent: [\`${K}\`](${q})`),Z.push("")}}let H=QQ($,"SKILL.md");return Z.push(`[Skill Overview](${H})`),Z.push(""),Z}function VQ(Q,X){if(HZ(Q.path,X))return Q;for(let Z of Q.children){let $=VQ(Z,X);if($)return $}return}function HZ(Q,X){if(Q.length!==X.length)return!1;for(let Z=0;Z<Q.length;Z++)if(Q[Z]!==X[Z])return!1;return!0}import{readFile as WZ}from"fs/promises";import{join as BZ}from"path";var ZQ="crust.json";async function m(Q){try{let X=await WZ(BZ(Q,ZQ),"utf-8"),Z=JSON.parse(X);if(typeof Z==="object"&&Z!==null&&"version"in Z&&typeof Z.version==="string")return Z.version;return null}catch{return null}}var KZ="auto",EQ=/^[a-z0-9]+(-[a-z0-9]+)*$/;function PQ(Q){return Q.length>=1&&Q.length<=64&&EQ.test(Q)}function A(Q){return Q.startsWith("use-")?Q:`use-${Q}`}async function S(Q){let{command:X,meta:Z,agents:$,scope:H="global",clean:W=!0,force:z=!1,installMode:J=KZ}=Q,q=A(Z.name);if(!PQ(q))throw Error(`Invalid skill name "${q}": must be 1\u201364 lowercase `+`alphanumeric characters and hyphens, no leading/trailing/consecutive hyphens. Pattern: ${EQ.source}`);let K=$[0];if(!K)return{agents:[]};let x={...Z,name:q},G=zQ(X),w=MQ(G,x),h=OZ(x),C=[...w,...h].sort((M,U)=>M.path<U.path?-1:M.path>U.path?1:0),a=C.map((M)=>M.path),R=new Map;for(let M of $){let U=v(M,H,x.name),T=R.get(U);if(T)T.push(M);else R.set(U,[M])}let l=new Map;for(let M of R.keys())l.set(M,await m(M));let _=s(H,x.name),u=await m(_);if(u===null){if(await CQ(_)&&!z)throw new b({agent:K,outputDir:v(K,H,x.name)})}let c=u!==x.version;if(c){if(W)await HQ(_);await NQ(_,C)}let N=[];for(let[M,U]of R){let T=U[0];if(!T)continue;let I=l.get(M)??null,Y=await LQ(M,_),F=I!==null||Y.exists&&Y.isSymlink&&Y.pointsToCanonical;if(Y.exists&&!F&&!z)throw new b({agent:T,outputDir:M});let O=await MZ({outputDir:M,canonicalOutputDir:_,allFiles:C,clean:W,installMode:J,inspection:Y,installedVersion:I,currentVersion:x.version}),V=xZ({installedVersion:I,currentVersion:x.version,canonicalChanged:c,pathChanged:O});for(let SQ of U)N.push({agent:SQ,outputDir:M,files:V==="up-to-date"?[]:a,status:V,previousVersion:V==="updated"?I??void 0:void 0})}return{agents:N}}async function $Q(Q){let{name:X,agents:Z,scope:$="global"}=Q,H=A(X),W=s($,H),z=[],J=new Map;for(let K of Z){let x=v(K,$,H),G=J.get(x);if(G)G.push(K);else J.set(x,[K])}for(let[K,x]of J)if(await CQ(K)){await XQ(K,{recursive:!0,force:!0});for(let w of x)z.push({agent:w,outputDir:K,status:"removed"})}else for(let w of x)z.push({agent:w,outputDir:K,status:"not-found"});if(!await FZ(H,$))await XQ(W,{recursive:!0,force:!0});return{agents:z}}async function d(Q){let{name:X,agents:Z,scope:$="global"}=Q,H=A(X),W=[],z=new Map;for(let J of Z){let q=v(J,$,H),K=z.get(q);if(K)K.push(J);else z.set(q,[J])}for(let[J,q]of z){let K=await m(J);for(let x of q)W.push({agent:x,outputDir:J,installed:K!==null,version:K??void 0})}return{agents:W}}function xZ(Q){let{installedVersion:X,currentVersion:Z,canonicalChanged:$,pathChanged:H}=Q;if(X===null)return"installed";if(X===Z&&!$&&!H)return"up-to-date";return"updated"}async function MZ(Q){let{outputDir:X,canonicalOutputDir:Z,allFiles:$,clean:H,installMode:W,inspection:z,installedVersion:J,currentVersion:q}=Q;if(W==="copy")return _Q({outputDir:X,allFiles:$,clean:H,inspection:z,installedVersion:J,currentVersion:q});try{return await GZ({outputDir:X,canonicalOutputDir:Z,inspection:z})}catch(K){if(W==="symlink")throw Error(`Failed to create symlink at "${X}" (installMode: symlink).`,{cause:K});let x=await LQ(X,Z);return _Q({outputDir:X,allFiles:$,clean:H,inspection:x,installedVersion:J,currentVersion:q})}}async function _Q(Q){let{outputDir:X,allFiles:Z,clean:$,inspection:H,installedVersion:W,currentVersion:z}=Q;if(!(!H.exists||H.isSymlink||W!==z))return!1;if(H.isSymlink||$)await HQ(X);return await NQ(X,Z),!0}async function GZ(Q){let{outputDir:X,canonicalOutputDir:Z,inspection:$}=Q;if($.exists&&$.isSymlink&&$.pointsToCanonical)return!1;if($.exists)await HQ(X);return await wZ(Z,X),!0}async function LQ(Q,X){let Z;try{Z=await kQ(Q)}catch{return{exists:!1,isSymlink:!1,pointsToCanonical:!1}}let $=process.platform==="win32"&&Z.isDirectory()&&await yQ(Q)!==null;if(!(Z.isSymbolicLink()||$))return{exists:!0,isSymlink:!1,pointsToCanonical:!1};let[W,z,J]=await Promise.all([TQ(Q),TQ(X),yQ(Q)]);return{exists:!0,isSymlink:!0,pointsToCanonical:W!==null&&z!==null&&W===z||J===X}}async function TQ(Q){try{return await qZ(Q)}catch{return null}}async function yQ(Q){try{return await YZ(Q)}catch{return null}}async function wZ(Q,X){await bQ(IQ(X),{recursive:!0});let Z=process.platform==="win32"?"junction":"dir";await zZ(Q,X,Z)}async function CQ(Q){try{return await kQ(Q),!0}catch{return!1}}async function FZ(Q,X){let Z=new Set;for(let $ of p)Z.add(v($,X,Q));for(let $ of Z)if(await m($)!==null)return!0;return!1}function OZ(Q){let X={name:Q.name,description:Q.description,version:Q.version};return[{path:ZQ,content:`${JSON.stringify(X,null,"\t")}
6
- `}]}async function HQ(Q){await XQ(Q,{recursive:!0,force:!0})}async function NQ(Q,X){let Z=new Set;for(let H of X){let W=RQ(Q,H.path),z=IQ(W);Z.add(z)}let $=[...Z].sort();for(let H of $)await bQ(H,{recursive:!0});for(let H of X){let W=RQ(Q,H.path);await JZ(W,H.content,"utf-8")}}import{Crust as DQ,VALIDATION_MODE_ENV as UZ}from"@crustjs/core";import{confirm as VZ,multiselect as RZ,select as _Z,spinner as r}from"@crustjs/prompts";import{bold as t,dim as f,yellow as vQ}from"@crustjs/style";var TZ="skill",yZ="global",o="__universal__";function kZ(Q){return Q==="global"||Q==="project"}async function AQ(Q,X){if(Q!==void 0){if(!kZ(Q))throw Error(`Invalid --scope value: ${String(Q)}. Expected "project" or "global".`);return Q}if(X.defaultScope)return X.defaultScope;return _Z({message:"Select scope",choices:[{label:"Project",value:"project"},{label:"Global",value:"global"}],default:yZ})}function WQ(Q){let X=new Set(P()),Z=[];if(Q.some(($)=>X.has($)))Z.push("Universal");for(let $ of Q){if(X.has($))continue;Z.push(j[$])}return Z}function jQ(Q){let X=new Set(P()),Z=[],$=Q.find((H)=>X.has(H.agent));if($)Z.push({label:"Universal",outputDir:$.outputDir});for(let H of Q){if(X.has(H.agent))continue;Z.push({label:j[H.agent],outputDir:H.outputDir})}return Z}function BQ(Q,X){return{name:Q.meta.name,description:Q.meta.description??"",version:X}}async function bZ(Q,X){let Z=[...P(),...D()];if(Z.length===0)return;let $=BQ(Q,X.version),H=["project","global"];for(let W of H){let J=(await d({name:$.name,agents:Z,scope:W})).agents.filter((q)=>q.installed&&q.version!==$.version);if(J.length===0)continue;try{await r({message:`Updating ${W} skills...`,task:async({updateMessage:q})=>{let K=await S({command:Q,meta:$,agents:J.map((w)=>w.agent),scope:W,installMode:X.installMode}),x=K.agents.filter((w)=>w.status==="updated").map((w)=>w.agent),G=WQ(x);if(G.length>0)q(`Updated skill "${A($.name)}" to v${$.version} for ${G.join(", ")} (${W})`);return K}})}catch(q){if(q instanceof b)console.warn(vQ(`Skill conflict: "${q.details.outputDir}" already exists but was not created by ${$.name}. Skipping auto-update for ${W}. Delete or rename the conflicting skill to resolve.`));else throw q}}}function IZ(Q){let X;return{name:"skills",async setup(Z,$){X=Z.rootCommand;let H=Q.command??TZ;if($.addSubCommand(X,H,EZ(X,Q,H)),process.env[UZ]==="1")return;if(Z.argv[0]===H)return;if(Q.autoUpdate!==!1)await bZ(X,Q)}}}function EZ(Q,X,Z){let $=PZ(Q,X);return new DQ(Z).meta({description:"Manage agent skill installations"}).flags({scope:{type:"string",description:"Install scope (project or global)"}}).run(async(H)=>{let W=BQ(Q,X.version),z=await AQ(H.flags.scope,X),J=await e(),q=P(),K=D(),x=await d({name:W.name,agents:[...q,...K],scope:z}),G=new Set(x.agents.filter((Y)=>Y.installed).map((Y)=>Y.agent)),w=new Set(J),h=new Map(x.agents.map((Y)=>[Y.agent,Y])),C=K.filter((Y)=>{if(w.has(Y))return!0;return h.get(Y)?.installed===!0}),a=C.filter((Y)=>G.has(Y)),R=[];if(q.length>0){let Y=q[0];if(!Y)throw Error("Expected at least one universal agent");let O=h.get(Y)?.outputDir??"path unavailable";R.push({label:"Universal",value:o,hint:O}),console.log(f("Universal installs to the shared .agents/skills directory."))}for(let Y of C){let O=h.get(Y)?.outputDir??"path unavailable";R.push({label:j[Y],value:Y,hint:O})}let l=q.length>0&&q.every((Y)=>G.has(Y)),_=[...a.filter((Y)=>!q.includes(Y))];if(l)_.unshift(o);let u=R.length===0?[]:await RZ({message:"Select agents to install skills for",choices:R,default:_,required:!1}),c=new Set(u.filter((Y)=>Y!==o));if(u.includes(o))for(let Y of q)c.add(Y);let N=[...c],M=N.filter((Y)=>!G.has(Y)),U=N.filter((Y)=>{let F=x.agents.find((O)=>O.agent===Y);return F?.installed===!0&&F.version!==W.version}),T=[...G].filter((Y)=>!N.includes(Y)),I=[...M,...U];if(I.length>0)try{let Y=await r({message:"Installing skills...",task:async()=>S({command:Q,meta:W,agents:I,scope:z,installMode:X.installMode})});console.log(`
7
- ${t(`Installed "${W.name}" v${W.version}`)}`);for(let F of jQ(Y.agents))console.log(f(` ${F.label} \u2192 ${F.outputDir}`))}catch(Y){if(Y instanceof b)if(await VZ({message:`"${Y.details.outputDir}" already exists but was not created by Crust. Overwrite?`,default:!1})){let O=await r({message:"Overwriting skill...",task:async()=>S({command:Q,meta:W,agents:[Y.details.agent],scope:z,force:!0,installMode:X.installMode})});console.log(`
8
- ${t(`Installed "${W.name}" v${W.version}`)}`);for(let V of jQ(O.agents))console.log(f(` ${V.label} \u2192 ${V.outputDir}`))}else console.log(f(`
9
- Skipped ${j[Y.details.agent]}`));else throw Y}if(T.length>0){let F=(await r({message:"Removing skills...",task:async()=>$Q({name:W.name,agents:T,scope:z})})).agents.filter((V)=>V.status==="removed").map((V)=>V.agent),O=WQ(F);if(O.length>0)console.log(`
10
- ${t(`Removed from ${O.join(", ")}`)}`)}if(I.length===0&&T.length===0)console.log(f("No changes."))}).command($)._node}function PZ(Q,X){return new DQ("update").meta({description:"Update installed skills to latest version"}).flags({scope:{type:"string",description:"Update scope (project or global)"}}).run(async(Z)=>{let $=await AQ(Z.flags.scope,X),H=[...P(),...D()],W=BQ(Q,X.version),J=(await d({name:W.name,agents:H,scope:$})).agents.filter((q)=>q.installed&&q.version!==W.version);if(J.length===0){console.log(f(`No updates needed (${$}).`));return}try{let K=(await r({message:`Updating ${$} skills...`,task:async()=>S({command:Q,meta:W,agents:J.map((G)=>G.agent),scope:$,installMode:X.installMode})})).agents.filter((G)=>G.status==="updated").map((G)=>G.agent),x=WQ(K);if(x.length>0)console.log(`
11
- ${t(`Updated "${W.name}" to v${W.version} for ${x.join(", ")} (${$})`)}`)}catch(q){if(q instanceof b)console.warn(vQ(`Skipped ${j[q.details.agent]}: "${q.details.outputDir}" already exists but was not created by ${W.name}. Delete or rename the conflicting directory to resolve.`));else throw q}})}export{$Q as uninstallSkill,d as skillStatus,IZ as skillPlugin,A as resolveSkillName,s as resolveCanonicalSkillPath,PQ as isValidSkillName,gQ as isUniversalAgent,P as getUniversalAgents,D as getAdditionalAgents,S as generateSkill,e as detectInstalledAgents,b as SkillConflictError};
2
+ import{accessSync as mQ,constants as dQ}from"fs";import{homedir as e}from"os";import{delimiter as rQ,join as Y}from"path";var _=Y(".agents","skills"),lQ=Y(".crust","skills");function KQ(Q){if(Q!==e())return Y(Q,".config");let Z=process.env.XDG_CONFIG_HOME?.trim();return Z&&Z.length>0?Z:Y(Q,".config")}function k(Q){return Y(Q,".agents","skills")}function sQ(Q){return Y(Q,".crust","skills")}var P={amp:{label:"Amp",class:"universal",projectSkillsDir:_,globalSkillsDir:k},adal:{label:"AdaL",class:"additional",projectSkillsDir:Y(".adal","skills"),globalSkillsDir:(Q)=>Y(Q,".adal","skills"),detectCommands:["adal"]},antigravity:{label:"Antigravity",class:"additional",projectSkillsDir:Y(".agent","skills"),globalSkillsDir:(Q)=>Y(Q,".gemini","antigravity","skills"),detectCommands:["antigravity"]},augment:{label:"Augment",class:"additional",projectSkillsDir:Y(".augment","skills"),globalSkillsDir:(Q)=>Y(Q,".augment","skills"),detectCommands:["augment"]},"claude-code":{label:"Claude Code",class:"additional",projectSkillsDir:Y(".claude","skills"),globalSkillsDir:(Q)=>Y(process.env.CLAUDE_CONFIG_DIR?.trim()||Y(Q,".claude"),"skills"),detectCommands:["claude","claude-code"]},cline:{label:"Cline",class:"universal",projectSkillsDir:_,globalSkillsDir:k},codebuddy:{label:"CodeBuddy",class:"additional",projectSkillsDir:Y(".codebuddy","skills"),globalSkillsDir:(Q)=>Y(Q,".codebuddy","skills"),detectCommands:["codebuddy"]},codex:{label:"Codex",class:"universal",projectSkillsDir:_,globalSkillsDir:k},"command-code":{label:"Command Code",class:"additional",projectSkillsDir:Y(".commandcode","skills"),globalSkillsDir:(Q)=>Y(Q,".commandcode","skills"),detectCommands:["command-code","commandcode"]},continue:{label:"Continue",class:"additional",projectSkillsDir:Y(".continue","skills"),globalSkillsDir:(Q)=>Y(Q,".continue","skills"),detectCommands:["continue"]},cortex:{label:"Cortex Code",class:"additional",projectSkillsDir:Y(".cortex","skills"),globalSkillsDir:(Q)=>Y(Q,".snowflake","cortex","skills"),detectCommands:["cortex"]},crush:{label:"Crush",class:"additional",projectSkillsDir:Y(".crush","skills"),globalSkillsDir:(Q)=>Y(KQ(Q),"crush","skills"),detectCommands:["crush"]},cursor:{label:"Cursor",class:"universal",projectSkillsDir:_,globalSkillsDir:k},droid:{label:"Droid",class:"additional",projectSkillsDir:Y(".factory","skills"),globalSkillsDir:(Q)=>Y(Q,".factory","skills"),detectCommands:["droid"]},"gemini-cli":{label:"Gemini CLI",class:"universal",projectSkillsDir:_,globalSkillsDir:k},"github-copilot":{label:"GitHub Copilot",class:"universal",projectSkillsDir:_,globalSkillsDir:k},goose:{label:"Goose",class:"additional",projectSkillsDir:Y(".goose","skills"),globalSkillsDir:(Q)=>Y(KQ(Q),"goose","skills"),detectCommands:["goose"]},"iflow-cli":{label:"iFlow CLI",class:"additional",projectSkillsDir:Y(".iflow","skills"),globalSkillsDir:(Q)=>Y(Q,".iflow","skills"),detectCommands:["iflow","iflow-cli"]},junie:{label:"Junie",class:"additional",projectSkillsDir:Y(".junie","skills"),globalSkillsDir:(Q)=>Y(Q,".junie","skills"),detectCommands:["junie"]},kilo:{label:"Kilo Code",class:"additional",projectSkillsDir:Y(".kilocode","skills"),globalSkillsDir:(Q)=>Y(Q,".kilocode","skills"),detectCommands:["kilo","kilocode"]},"kimi-cli":{label:"Kimi Code CLI",class:"universal",projectSkillsDir:_,globalSkillsDir:k},"kiro-cli":{label:"Kiro CLI",class:"additional",projectSkillsDir:Y(".kiro","skills"),globalSkillsDir:(Q)=>Y(Q,".kiro","skills"),detectCommands:["kiro","kiro-cli"]},kode:{label:"Kode",class:"additional",projectSkillsDir:Y(".kode","skills"),globalSkillsDir:(Q)=>Y(Q,".kode","skills"),detectCommands:["kode"]},mcpjam:{label:"MCPJam",class:"additional",projectSkillsDir:Y(".mcpjam","skills"),globalSkillsDir:(Q)=>Y(Q,".mcpjam","skills"),detectCommands:["mcpjam"]},"mistral-vibe":{label:"Mistral Vibe",class:"additional",projectSkillsDir:Y(".vibe","skills"),globalSkillsDir:(Q)=>Y(Q,".vibe","skills"),detectCommands:["mistral-vibe","vibe"]},mux:{label:"Mux",class:"additional",projectSkillsDir:Y(".mux","skills"),globalSkillsDir:(Q)=>Y(Q,".mux","skills"),detectCommands:["mux"]},neovate:{label:"Neovate",class:"additional",projectSkillsDir:Y(".neovate","skills"),globalSkillsDir:(Q)=>Y(Q,".neovate","skills"),detectCommands:["neovate"]},opencode:{label:"OpenCode",class:"universal",projectSkillsDir:_,globalSkillsDir:k},openclaw:{label:"OpenClaw",class:"additional",projectSkillsDir:"skills",globalSkillsDir:(Q)=>Y(Q,".openclaw","skills"),detectCommands:["openclaw"]},openhands:{label:"OpenHands",class:"additional",projectSkillsDir:Y(".openhands","skills"),globalSkillsDir:(Q)=>Y(Q,".openhands","skills"),detectCommands:["openhands"]},pi:{label:"Pi",class:"additional",projectSkillsDir:Y(".pi","skills"),globalSkillsDir:(Q)=>Y(Q,".pi","agent","skills"),detectCommands:["pi"]},pochi:{label:"Pochi",class:"additional",projectSkillsDir:Y(".pochi","skills"),globalSkillsDir:(Q)=>Y(Q,".pochi","skills"),detectCommands:["pochi"]},qoder:{label:"Qoder",class:"additional",projectSkillsDir:Y(".qoder","skills"),globalSkillsDir:(Q)=>Y(Q,".qoder","skills"),detectCommands:["qoder"]},"qwen-code":{label:"Qwen Code",class:"additional",projectSkillsDir:Y(".qwen","skills"),globalSkillsDir:(Q)=>Y(Q,".qwen","skills"),detectCommands:["qwen","qwen-code"]},replit:{label:"Replit",class:"universal",projectSkillsDir:_,globalSkillsDir:k},roo:{label:"Roo Code",class:"additional",projectSkillsDir:Y(".roo","skills"),globalSkillsDir:(Q)=>Y(Q,".roo","skills"),detectCommands:["roo","roo-code"]},trae:{label:"Trae",class:"additional",projectSkillsDir:Y(".trae","skills"),globalSkillsDir:(Q)=>Y(Q,".trae","skills"),detectCommands:["trae"]},"trae-cn":{label:"Trae CN",class:"additional",projectSkillsDir:Y(".trae","skills"),globalSkillsDir:(Q)=>Y(Q,".trae-cn","skills"),detectCommands:["trae-cn","trae"]},windsurf:{label:"Windsurf",class:"additional",projectSkillsDir:Y(".windsurf","skills"),globalSkillsDir:(Q)=>Y(Q,".codeium","windsurf","skills"),detectCommands:["windsurf"]},zencoder:{label:"Zencoder",class:"additional",projectSkillsDir:Y(".zencoder","skills"),globalSkillsDir:(Q)=>Y(Q,".zencoder","skills"),detectCommands:["zencoder"]}},c=Object.keys(P),j=Object.fromEntries(c.map((Q)=>[Q,P[Q].label]));function I(){return c.filter((Q)=>P[Q].class==="universal")}function D(){return c.filter((Q)=>P[Q].class==="additional")}function iQ(Q){return P[Q].class==="universal"}async function QQ(Q){let Z=typeof Q==="string"?{home:Q}:Q??{},X=Z.cwd??process.cwd(),$=Z.commandChecker??((H)=>Promise.resolve(oQ(H))),W=[];for(let H of D()){let B=P[H].detectCommands??[],z=!1;for(let J of B)if(await $(J,X)){z=!0;break}if(z)W.push(H)}return W}function v(Q,Z,X){let $=P[Q];if(Z==="project")return Y(process.cwd(),$.projectSkillsDir,X);return Y($.globalSkillsDir(e()),X)}function s(Q,Z){if(Q==="project")return Y(process.cwd(),lQ,Z);return Y(sQ(e()),Z)}function oQ(Q){let X=(process.env.PATH??"").split(rQ).filter((H)=>H.length>0),$=process.platform==="win32",W=$?(process.env.PATHEXT??".EXE;.CMD;.BAT;.COM").split(";").filter((H)=>H.length>0):[];for(let H of X){if(!$&&xQ(Y(H,Q)))return!0;if($){for(let B of W)if(xQ(Y(H,Q+B)))return!0}}return!1}function xQ(Q){try{return mQ(Q,dQ.X_OK),!0}catch{return!1}}import{Crust as aQ}from"@crustjs/core";function i(Q){if(Q===void 0)return[];return(Array.isArray(Q)?Q:[Q]).flatMap((X)=>X.split(/\r?\n/)).map((X)=>X.trim()).filter((X)=>X.length>0)}function GQ(Q){let Z=Q?.trim();if(!Z)return[];return Z.split(/\r?\n/)}function ZQ(Q){return Q.length>0}var FQ=Symbol("crust.skill.commandAnnotations");function tQ(Q){return Q instanceof aQ?Q._node:Q}function nQ(Q,Z){let X=tQ(Q),$=i(typeof Z==="string"||Array.isArray(Z)?Z:Z.instructions??[]);if($.length===0)return Q;let W=XQ(X)?.instructions??[],H=[...new Set([...W,...$])];return Object.defineProperty(X,FQ,{value:{instructions:H},enumerable:!0,configurable:!0}),Q}function XQ(Q){let Z=Q[FQ];if(!Z?.instructions||Z.instructions.length===0)return;return{instructions:[...Z.instructions]}}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{lstat as NQ,mkdir as LQ,readlink as yZ,realpath as TZ,rm as YQ,symlink as _Z,writeFile as kZ}from"fs/promises";import{dirname as DQ,join as PQ}from"path";function MQ(Q){return wQ(Q,[])}function wQ(Q,Z){let X=eQ(Q.meta.name),$=[...Z,X],W=QZ(Q.args),H=XZ(Q.effectiveFlags),B=WZ(Q.subCommands,$),z=XQ(Q);return{name:X,path:$,description:Q.meta.description,usage:Q.meta.usage,instructions:z?.instructions,runnable:typeof Q.run==="function",args:W,flags:H,children:B}}function eQ(Q){return Q.trim().toLowerCase()}function QZ(Q){if(!Q||Q.length===0)return[];return Q.map(ZZ)}function ZZ(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=UQ(Q.default);return Z}function XZ(Q){if(!Q)return[];return Object.keys(Q).sort().map((X)=>{return $Z(X,Q[X])})}function $Z(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=UQ(Z.default);return X}function WZ(Q,Z){return Object.keys(Q).sort().map(($)=>{return wQ(Q[$],Z)})}function UQ(Q){if(Array.isArray(Q))return JSON.stringify(Q);return String(Q)}function u(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 OQ(Q){return Q.replace(/(?<!\\)\|/g,"\\|")}function VQ(Q,Z){let X=[],$=RQ(Q);X.push({path:"SKILL.md",content:HZ(Q,Z,$)});for(let W of $){let H=C(W),B=W.children.length>0?JZ(W,Q):BZ(W,Q);X.push({path:H,content:B})}return X}function RQ(Q){let Z=[Q];for(let X of Q.children)Z.push(...RQ(X));return Z}function C(Q){if(Q.path.length<=1)return`commands/${Q.name}.md`;return`commands/${Q.path.slice(1).join("/")}.md`}function WQ(Q){return Q.path.join(" ")}function $Q(Q,Z){let X=Q.split("/").slice(0,-1),$=Z.split("/"),W=0;while(W<X.length&&W<$.length&&X[W]===$[W])W++;let H=X.length-W,B=$.slice(W);if(H===0)return B.join("/");return[...Array.from({length:H},()=>".."),...B].join("/")}function HZ(Q,Z,X){let $=[];if($.push("---"),$.push(`name: ${u(Z.name)}`),$.push(`description: ${u(Z.description)}`),Z.license)$.push(`license: ${u(Z.license)}`);if(Z.compatibility)$.push(`compatibility: ${u(Z.compatibility)}`);if(Z.disableModelInvocation)$.push("disable-model-invocation: true");if(Z.allowedTools)$.push(`allowed-tools: ${u(Z.allowedTools)}`);if($.push("metadata:"),$.push(` version: "${Z.version}"`),$.push("---"),$.push(""),$.push(`# ${Z.name}`),$.push(""),Q.description)$.push(Q.description),$.push("");let W=Z.name.startsWith("use-")?Z.name.slice(4):Z.name;$.push(`Use this skill when you need accurate help with \`${W}\` commands, including command selection, syntax, arguments, flags, defaults, and subcommands.`),$.push("");let H=UZ(Z.instructions);if($.push("## How to Use This Skill"),$.push(""),$.push("1. Find the command that best matches the user's task from the Command Reference below"),$.push("2. Check the `Type` column before suggesting execution: `runnable` and `runnable, group` commands can be executed, while `group` commands are organizational only"),$.push("3. Read only the linked file or files you need from `commands/`"),$.push("4. Before answering a command-specific question or suggesting a command, read that command's file"),$.push("5. Treat the command file as the source of truth for usage, arguments, flags, aliases, and defaults"),$.push("6. If a flag, argument, alias, or default is not documented there, say it is not documented instead of guessing"),$.push(""),ZQ(H))$.push("## General Guidance"),$.push(""),$.push(...H),$.push("");if($.push("## Command Reference"),$.push(""),$.push("Use this table to locate the command file you need."),$.push(""),$.push(...YZ(X)),$.push(""),Q.runnable){$.push("## Usage"),$.push("");let B=C(Q);$.push(`The root command is directly executable. See [${Q.name}](${B}) for usage details.`),$.push("")}return $.join(`
3
+ `)}function YZ(Q){let Z=[];Z.push("| Command | Type | Documentation |"),Z.push("| ------- | ---- | ------------- |");for(let X of Q){let $=WQ(X),W=C(X),H=qZ(X);Z.push(`| \`${$}\` | ${H} | [${W}](${W}) |`)}return Z}function qZ(Q){if(Q.runnable&&Q.children.length>0)return"runnable, group";if(Q.runnable)return"runnable";return"group"}function BZ(Q,Z){let X=[];return X.push(...yQ(Q)),X.push(...TQ(Q)),X.push(..._Q(Q)),X.push(...bQ(Q,Z)),X.join(`
4
+ `)}function JZ(Q,Z){let X=[],$=C(Q);if(X.push(...yQ(Q)),X.push(...TQ(Q)),Q.runnable)X.push(..._Q(Q));return X.push(...KZ(Q,$)),X.push(...bQ(Q,Z)),X.join(`
5
+ `)}function zZ(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 yQ(Q){let Z=[`# \`${WQ(Q)}\``,""];if(Q.description)Z.push(Q.description,"");return Z}function TQ(Q){let Z=Q.instructions??[];if(!ZQ(Z))return[];return["## Command Instructions","",...kQ(Z),""]}function _Q(Q){let Z=["## Usage","","```",Q.usage??zZ(Q),"```",""];if(Q.args.length>0)Z.push("## Arguments","",...xZ(Q.args),"");if(Q.flags.length>0)Z.push("## Flags","",...FZ(Q.flags),"");return Z.push("## Command Documentation Authority","","Only arguments, flags, options, aliases, and defaults documented in this file are supported for this command.","Do not infer or invent additional command-line options.",""),Z}function KZ(Q,Z){let X=["## Subcommands",""];for(let $ of Q.children){let W=C($),H=$Q(Z,W),B=$.description?` - ${$.description}`:"";X.push(`- [\`${$.name}\`](${H})${B}`)}return X.push(""),X}function xZ(Q){let Z=[];Z.push("| Argument | Type | Required | Description |"),Z.push("| -------- | ---- | -------- | ----------- |");for(let X of Q){let $=X.variadic?`${X.name}...`:X.name,W=X.required?"Yes":"No",H=OQ(GZ(X));Z.push(`| \`${$}\` | ${X.type} | ${W} | ${H} |`)}return Z}function GZ(Q){let Z=[];if(Q.description)Z.push(Q.description);if(Q.default!==void 0)Z.push(`Default: \`${Q.default}\``);return Z.join(". ")||"-"}function FZ(Q){let Z=[];Z.push("| Flag | Type | Required | Description |"),Z.push("| ---- | ---- | -------- | ----------- |");for(let X of Q){let $=MZ(X),W=X.required?"Yes":"No",H=OQ(wZ(X));Z.push(`| ${$} | ${X.type} | ${W} | ${H} |`)}return Z}function MZ(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 wZ(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 kQ(Q){return Q.map((Z)=>`- ${Z}`)}function UZ(Q){if(typeof Q==="string")return GQ(Q);return kQ(i(Q))}function bQ(Q,Z){let X=[],$=C(Q);if(X.push("---"),X.push(""),Q.path.length>1){let H=Q.path.slice(0,-1),B=EQ(Z,H);if(B){let z=C(B),J=$Q($,z),K=WQ(B);X.push(`Parent: [\`${K}\`](${J})`),X.push("")}}let W=$Q($,"SKILL.md");return X.push(`[Skill Overview](${W})`),X.push(""),X}function EQ(Q,Z){if(OZ(Q.path,Z))return Q;for(let X of Q.children){let $=EQ(X,Z);if($)return $}return}function OZ(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 VZ}from"fs/promises";import{join as RZ}from"path";var HQ="crust.json";async function m(Q){try{let Z=await VZ(RZ(Q,HQ),"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 bZ="auto",vQ=/^[a-z0-9]+(-[a-z0-9]+)*$/;function SQ(Q){return Q.length>=1&&Q.length<=64&&vQ.test(Q)}function S(Q){return Q.startsWith("use-")?Q:`use-${Q}`}async function A(Q){let{command:Z,meta:X,agents:$,scope:W="global",clean:H=!0,force:B=!1,installMode:z=bZ}=Q,J=S(X.name);if(!SQ(J))throw Error(`Invalid skill name "${J}": must be 1\u201364 lowercase `+`alphanumeric characters and hyphens, no leading/trailing/consecutive hyphens. Pattern: ${vQ.source}`);let K=$[0];if(!K)return{agents:[]};let x={...X,name:J},F=MQ(Z),M=VQ(F,x),h=NZ(x),N=[...M,...h].sort((G,V)=>G.path<V.path?-1:G.path>V.path?1:0),t=N.map((G)=>G.path),R=new Map;for(let G of $){let V=v(G,W,x.name),T=R.get(V);if(T)T.push(G);else R.set(V,[G])}let l=new Map;for(let G of R.keys())l.set(G,await m(G));let y=s(W,x.name),p=await m(y);if(p===null){if(await fQ(y)&&!B)throw new b({agent:K,outputDir:v(K,W,x.name)})}let g=p!==x.version;if(g){if(H)await BQ(y);await hQ(y,N)}let L=[];for(let[G,V]of R){let T=V[0];if(!T)continue;let E=l.get(G)??null,q=await AQ(G,y),w=E!==null||q.exists&&q.isSymlink&&q.pointsToCanonical;if(q.exists&&!w&&!B)throw new b({agent:T,outputDir:G});let U=await PZ({outputDir:G,canonicalOutputDir:y,allFiles:N,clean:H,installMode:z,inspection:q,installedVersion:E,currentVersion:x.version}),O=EZ({installedVersion:E,currentVersion:x.version,canonicalChanged:g,pathChanged:U});for(let n of V)L.push({agent:n,outputDir:G,files:O==="up-to-date"?[]:t,status:O,previousVersion:O==="updated"?E??void 0:void 0})}return{agents:L}}async function qQ(Q){let{name:Z,agents:X,scope:$="global"}=Q,W=S(Z),H=s($,W),B=[],z=new Map;for(let K of X){let x=v(K,$,W),F=z.get(x);if(F)F.push(K);else z.set(x,[K])}for(let[K,x]of z)if(await fQ(K)){await YQ(K,{recursive:!0,force:!0});for(let M of x)B.push({agent:M,outputDir:K,status:"removed"})}else for(let M of x)B.push({agent:M,outputDir:K,status:"not-found"});if(!await CZ(W,$))await YQ(H,{recursive:!0,force:!0});return{agents:B}}async function d(Q){let{name:Z,agents:X,scope:$="global"}=Q,W=S(Z),H=[],B=new Map;for(let z of X){let J=v(z,$,W),K=B.get(J);if(K)K.push(z);else B.set(J,[z])}for(let[z,J]of B){let K=await m(z);for(let x of J)H.push({agent:x,outputDir:z,installed:K!==null,version:K??void 0})}return{agents:H}}function EZ(Q){let{installedVersion:Z,currentVersion:X,canonicalChanged:$,pathChanged:W}=Q;if(Z===null)return"installed";if(Z===X&&!$&&!W)return"up-to-date";return"updated"}async function PZ(Q){let{outputDir:Z,canonicalOutputDir:X,allFiles:$,clean:W,installMode:H,inspection:B,installedVersion:z,currentVersion:J}=Q;if(H==="copy")return jQ({outputDir:Z,allFiles:$,clean:W,inspection:B,installedVersion:z,currentVersion:J});try{return await jZ({outputDir:Z,canonicalOutputDir:X,inspection:B})}catch(K){if(H==="symlink")throw Error(`Failed to create symlink at "${Z}" (installMode: symlink).`,{cause:K});let x=await AQ(Z,X);return jQ({outputDir:Z,allFiles:$,clean:W,inspection:x,installedVersion:z,currentVersion:J})}}async function jQ(Q){let{outputDir:Z,allFiles:X,clean:$,inspection:W,installedVersion:H,currentVersion:B}=Q;if(!(!W.exists||W.isSymlink||H!==B))return!1;if(W.isSymlink||$)await BQ(Z);return await hQ(Z,X),!0}async function jZ(Q){let{outputDir:Z,canonicalOutputDir:X,inspection:$}=Q;if($.exists&&$.isSymlink&&$.pointsToCanonical)return!1;if($.exists)await BQ(Z);return await IZ(X,Z),!0}async function AQ(Q,Z){let X;try{X=await NQ(Q)}catch{return{exists:!1,isSymlink:!1,pointsToCanonical:!1}}let $=process.platform==="win32"&&X.isDirectory()&&await CQ(Q)!==null;if(!(X.isSymbolicLink()||$))return{exists:!0,isSymlink:!1,pointsToCanonical:!1};let[H,B,z]=await Promise.all([IQ(Q),IQ(Z),CQ(Q)]);return{exists:!0,isSymlink:!0,pointsToCanonical:H!==null&&B!==null&&H===B||z===Z}}async function IQ(Q){try{return await TZ(Q)}catch{return null}}async function CQ(Q){try{return await yZ(Q)}catch{return null}}async function IZ(Q,Z){await LQ(DQ(Z),{recursive:!0});let X=process.platform==="win32"?"junction":"dir";await _Z(Q,Z,X)}async function fQ(Q){try{return await NQ(Q),!0}catch{return!1}}async function CZ(Q,Z){let X=new Set;for(let $ of c)X.add(v($,Z,Q));for(let $ of X)if(await m($)!==null)return!0;return!1}function NZ(Q){let Z={name:Q.name,description:Q.description,version:Q.version};return[{path:HQ,content:`${JSON.stringify(Z,null,"\t")}
6
+ `}]}async function BQ(Q){await YQ(Q,{recursive:!0,force:!0})}async function hQ(Q,Z){let X=new Set;for(let W of Z){let H=PQ(Q,W.path),B=DQ(H);X.add(B)}let $=[...X].sort();for(let W of $)await LQ(W,{recursive:!0});for(let W of Z){let H=PQ(Q,W.path);await kZ(H,W.content,"utf-8")}}import{Crust as gQ,VALIDATION_MODE_ENV as LZ}from"@crustjs/core";import{confirm as DZ,multiselect as vZ,select as SZ,spinner as r}from"@crustjs/prompts";import{bold as a,dim as f,yellow as cQ}from"@crustjs/style";var AZ="skill",fZ="global",o="__universal__";function hZ(Q){return Q==="global"||Q==="project"}async function uQ(Q,Z){if(Q!==void 0){if(!hZ(Q))throw Error(`Invalid --scope value: ${String(Q)}. Expected "project" or "global".`);return Q}if(Z.defaultScope)return Z.defaultScope;return SZ({message:"Select scope",choices:[{label:"Project",value:"project"},{label:"Global",value:"global"}],default:fZ})}function JQ(Q){let Z=new Set(I()),X=[];if(Q.some(($)=>Z.has($)))X.push("Universal");for(let $ of Q){if(Z.has($))continue;X.push(j[$])}return X}function pQ(Q){let Z=new Set(I()),X=[],$=Q.find((W)=>Z.has(W.agent));if($)X.push({label:"Universal",outputDir:$.outputDir});for(let W of Q){if(Z.has(W.agent))continue;X.push({label:j[W.agent],outputDir:W.outputDir})}return X}function zQ(Q,Z){return{name:Q.meta.name,description:Q.meta.description??"",version:Z.version,instructions:Z.instructions,license:Z.license,allowedTools:Z.allowedTools,compatibility:Z.compatibility,disableModelInvocation:Z.disableModelInvocation}}async function pZ(Q,Z){let X=[...I(),...D()];if(X.length===0)return;let $=zQ(Q,Z),W=["project","global"];for(let H of W){let z=(await d({name:$.name,agents:X,scope:H})).agents.filter((J)=>J.installed&&J.version!==$.version);if(z.length===0)continue;try{await r({message:`Updating ${H} skills...`,task:async({updateMessage:J})=>{let K=await A({command:Q,meta:$,agents:z.map((M)=>M.agent),scope:H,installMode:Z.installMode}),x=K.agents.filter((M)=>M.status==="updated").map((M)=>M.agent),F=JQ(x);if(F.length>0)J(`Updated skill "${S($.name)}" to v${$.version} for ${F.join(", ")} (${H})`);return K}})}catch(J){if(J instanceof b)console.warn(cQ(`Skill conflict: "${J.details.outputDir}" already exists but was not created by ${$.name}. Skipping auto-update for ${H}. Delete or rename the conflicting skill to resolve.`));else throw J}}}function gZ(Q){let Z;return{name:"skills",async setup(X,$){Z=X.rootCommand;let W=Q.command??AZ;if($.addSubCommand(Z,W,cZ(Z,Q,W)),process.env[LZ]==="1")return;if(X.argv[0]===W)return;if(Q.autoUpdate!==!1)await pZ(Z,Q)}}}function cZ(Q,Z,X){let $=uZ(Q,Z);return new gQ(X).meta({description:"Manage agent skill installations"}).flags({scope:{type:"string",description:"Install scope (project or global)"}}).run(async(W)=>{let H=zQ(Q,Z),B=await uQ(W.flags.scope,Z),z=await QQ(),J=I(),K=D(),x=await d({name:H.name,agents:[...J,...K],scope:B}),F=new Set(x.agents.filter((q)=>q.installed).map((q)=>q.agent)),M=new Set(z),h=new Map(x.agents.map((q)=>[q.agent,q])),N=K.filter((q)=>{if(M.has(q))return!0;return h.get(q)?.installed===!0}),t=N.filter((q)=>F.has(q)),R=[];if(J.length>0){let q=J[0];if(!q)throw Error("Expected at least one universal agent");let U=h.get(q)?.outputDir??"path unavailable";R.push({label:"Universal",value:o,hint:U});let O=J.map((n)=>j[n]).join(", ");console.log(f(`Agents supporting universal skills: ${O}`))}for(let q of N){let U=h.get(q)?.outputDir??"path unavailable";R.push({label:j[q],value:q,hint:U})}let l=J.length>0&&J.every((q)=>F.has(q)),y=[...t.filter((q)=>!J.includes(q))];if(l)y.unshift(o);let p=R.length===0?[]:await vZ({message:"Select agents to install skills for",choices:R,default:y,required:!1}),g=new Set(p.filter((q)=>q!==o));if(p.includes(o))for(let q of J)g.add(q);let L=[...g],G=L.filter((q)=>!F.has(q)),V=L.filter((q)=>{let w=x.agents.find((U)=>U.agent===q);return w?.installed===!0&&w.version!==H.version}),T=[...F].filter((q)=>!L.includes(q)),E=[...G,...V];if(E.length>0)try{let q=await r({message:"Installing skills...",task:async()=>A({command:Q,meta:H,agents:E,scope:B,installMode:Z.installMode})});console.log(`
7
+ ${a(`Installed "${H.name}" v${H.version}`)}`);for(let w of pQ(q.agents))console.log(f(` ${w.label} \u2192 ${w.outputDir}`))}catch(q){if(q instanceof b)if(await DZ({message:`"${q.details.outputDir}" already exists but was not created by Crust. Overwrite?`,default:!1})){let U=await r({message:"Overwriting skill...",task:async()=>A({command:Q,meta:H,agents:[q.details.agent],scope:B,force:!0,installMode:Z.installMode})});console.log(`
8
+ ${a(`Installed "${H.name}" v${H.version}`)}`);for(let O of pQ(U.agents))console.log(f(` ${O.label} \u2192 ${O.outputDir}`))}else console.log(f(`
9
+ Skipped ${j[q.details.agent]}`));else throw q}if(T.length>0){let w=(await r({message:"Removing skills...",task:async()=>qQ({name:H.name,agents:T,scope:B})})).agents.filter((O)=>O.status==="removed").map((O)=>O.agent),U=JQ(w);if(U.length>0)console.log(`
10
+ ${a(`Removed from ${U.join(", ")}`)}`)}if(E.length===0&&T.length===0)console.log(f("No changes."))}).command($)._node}function uZ(Q,Z){return new gQ("update").meta({description:"Update installed skills to latest version"}).flags({scope:{type:"string",description:"Update scope (project or global)"}}).run(async(X)=>{let $=await uQ(X.flags.scope,Z),W=[...I(),...D()],H=zQ(Q,Z),z=(await d({name:H.name,agents:W,scope:$})).agents.filter((J)=>J.installed&&J.version!==H.version);if(z.length===0){console.log(f(`No updates needed (${$}).`));return}try{let K=(await r({message:`Updating ${$} skills...`,task:async()=>A({command:Q,meta:H,agents:z.map((F)=>F.agent),scope:$,installMode:Z.installMode})})).agents.filter((F)=>F.status==="updated").map((F)=>F.agent),x=JQ(K);if(x.length>0)console.log(`
11
+ ${a(`Updated "${H.name}" to v${H.version} for ${x.join(", ")} (${$})`)}`)}catch(J){if(J instanceof b)console.warn(cQ(`Skipped ${j[J.details.agent]}: "${J.details.outputDir}" already exists but was not created by ${H.name}. Delete or rename the conflicting directory to resolve.`));else throw J}})}export{qQ as uninstallSkill,d as skillStatus,gZ as skillPlugin,S as resolveSkillName,s as resolveCanonicalSkillPath,SQ as isValidSkillName,iQ as isUniversalAgent,I as getUniversalAgents,D as getAdditionalAgents,A as generateSkill,QQ as detectInstalledAgents,nQ as annotate,b as SkillConflictError};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crustjs/skills",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "Agent skill generation from Crust command definitions",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,19 +39,20 @@
39
39
  "build": "bunup",
40
40
  "dev": "bunup --watch",
41
41
  "check:types": "tsc --noEmit",
42
- "test": "bun test"
42
+ "test": "bun test",
43
+ "publish": "bun publish --no-git-checks || true"
43
44
  },
44
45
  "dependencies": {
45
- "@crustjs/prompts": "0.0.8",
46
- "@crustjs/style": "0.0.4"
46
+ "@crustjs/prompts": "0.0.9",
47
+ "@crustjs/style": "0.0.5"
47
48
  },
48
49
  "devDependencies": {
49
50
  "@crustjs/config": "0.0.0",
50
- "@crustjs/core": "0.0.12",
51
+ "@crustjs/core": "0.0.14",
51
52
  "bunup": "^0.16.29"
52
53
  },
53
54
  "peerDependencies": {
54
- "@crustjs/core": "0.0.12",
55
+ "@crustjs/core": "0.0.14",
55
56
  "typescript": "^5"
56
57
  }
57
58
  }