@crustjs/skills 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +2 -676
- package/dist/index.d.ts +172 -893
- package/dist/index.js +1435 -16
- package/package.json +29 -15
package/dist/index.d.ts
CHANGED
|
@@ -1,899 +1,178 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
* alphanumeric characters and hyphens, no leading/trailing/consecutive
|
|
29
|
-
* hyphens.
|
|
30
|
-
*/
|
|
31
|
-
name: string;
|
|
32
|
-
/** Human-readable description of what the CLI does */
|
|
33
|
-
description: string;
|
|
34
|
-
/** Version string for the generated skill bundle */
|
|
35
|
-
version: string;
|
|
36
|
-
/**
|
|
37
|
-
* License name or reference to a bundled license file.
|
|
38
|
-
*
|
|
39
|
-
* Emitted in SKILL.md YAML frontmatter as `license:`.
|
|
40
|
-
*/
|
|
41
|
-
license?: string;
|
|
42
|
-
/**
|
|
43
|
-
* Environment requirements or compatibility notes (max 500 chars per spec).
|
|
44
|
-
*
|
|
45
|
-
* Indicates intended product, required system packages, network access, etc.
|
|
46
|
-
* Emitted in SKILL.md YAML frontmatter as `compatibility:`.
|
|
47
|
-
*
|
|
48
|
-
* @example "Requires deploy-cli installed on PATH"
|
|
49
|
-
*/
|
|
50
|
-
compatibility?: string;
|
|
51
|
-
/**
|
|
52
|
-
* When `true`, prevents agents from automatically loading this skill.
|
|
53
|
-
* Users must invoke it manually with `/skill-name`.
|
|
54
|
-
*
|
|
55
|
-
* Emitted in SKILL.md YAML frontmatter as `disable-model-invocation: true`.
|
|
56
|
-
* @default false
|
|
57
|
-
*/
|
|
58
|
-
disableModelInvocation?: boolean;
|
|
59
|
-
/**
|
|
60
|
-
* Space-delimited list of pre-approved tools the skill may use.
|
|
61
|
-
*
|
|
62
|
-
* For CLI skills, setting this to `Bash(<cli-name> *)` allows agents to
|
|
63
|
-
* execute the CLI without per-use permission prompts.
|
|
64
|
-
*
|
|
65
|
-
* Emitted in SKILL.md YAML frontmatter as `allowed-tools:`.
|
|
66
|
-
*
|
|
67
|
-
* @example "Bash(my-cli *) Read Grep"
|
|
68
|
-
*/
|
|
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[];
|
|
82
|
-
}
|
|
83
|
-
/** Supported agent targets for skill installation. */
|
|
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";
|
|
85
|
-
/** Agent install class used by interactive skill management UX. */
|
|
1
|
+
import { CommandDefinition, CommandSnapshot, ExtensionFactory } from "@crustjs/core";
|
|
2
|
+
//#region src/build.d.ts
|
|
3
|
+
/** Options for rendering a skill source. */
|
|
4
|
+
interface WriteSkillsOptions {
|
|
5
|
+
/** Application whose command tree is rendered into a generated skill. Omit to write only `extras`. */
|
|
6
|
+
readonly app?: {
|
|
7
|
+
snapshot(): Promise<CommandSnapshot>;
|
|
8
|
+
};
|
|
9
|
+
/** `skills` directory that receives one subdirectory per skill. */
|
|
10
|
+
readonly outDir: string;
|
|
11
|
+
/** Version recorded in the generated skill's SKILL.md metadata. Omitted when absent. */
|
|
12
|
+
readonly version?: string;
|
|
13
|
+
/** Generated skill name. Defaults to the root command name. */
|
|
14
|
+
readonly name?: string;
|
|
15
|
+
/** Generated skill description. Defaults to the root command description. */
|
|
16
|
+
readonly description?: string;
|
|
17
|
+
/** Hand-authored skill directories included alongside the generated skill. */
|
|
18
|
+
readonly extras?: readonly (string | URL)[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Renders generated and authored skills into a package-ready skill source.
|
|
22
|
+
*/
|
|
23
|
+
export declare function writeSkills({ app, ...options }: WriteSkillsOptions): Promise<readonly string[]>;
|
|
24
|
+
/** Renders skills from a Command Snapshot prepared in this or another process. */
|
|
25
|
+
export declare function writeSkillsFromSnapshot(snapshot: CommandSnapshot, options: Omit<WriteSkillsOptions, "app">): Promise<readonly string[]>;
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/agents.d.ts
|
|
86
28
|
type AgentClass = "universal" | "additional";
|
|
87
|
-
/** Installation scope — global (home directory) or project (cwd, except home dir which normalizes to global). */
|
|
88
29
|
type Scope = "global" | "project";
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
* await generateSkill({
|
|
118
|
-
* command: rootCommand,
|
|
119
|
-
* meta: {
|
|
120
|
-
* name: "my-cli", // output: my-cli/
|
|
121
|
-
* description: "CLI tool for managing widgets",
|
|
122
|
-
* version: "1.0.0",
|
|
123
|
-
* },
|
|
124
|
-
* agents: ["claude-code", "opencode"],
|
|
125
|
-
* });
|
|
126
|
-
* ```
|
|
127
|
-
*/
|
|
128
|
-
interface GenerateOptions {
|
|
129
|
-
/** Root command to generate the skill from */
|
|
130
|
-
command: CommandNode;
|
|
131
|
-
/** Skill metadata for the generated bundle */
|
|
132
|
-
meta: SkillMeta;
|
|
133
|
-
/**
|
|
134
|
-
* Agent targets to install skills for.
|
|
135
|
-
*
|
|
136
|
-
* When omitted (or explicitly `undefined`), defaults to
|
|
137
|
-
* `[...getUniversalAgents(), ...await detectInstalledAgents()]` — the union
|
|
138
|
-
* of always-included universal agents and additional agents whose CLI is
|
|
139
|
-
* detected on `PATH`. Pass an explicit array to override; `agents: []`
|
|
140
|
-
* is treated as a no-op (no install performed).
|
|
141
|
-
*
|
|
142
|
-
* **Note:** Omitting this field performs filesystem I/O via
|
|
143
|
-
* `detectInstalledAgents()` to probe `PATH` for installed agent CLIs.
|
|
144
|
-
*/
|
|
145
|
-
agents?: AgentTarget[];
|
|
146
|
-
/**
|
|
147
|
-
* Installation strategy for agent output paths.
|
|
148
|
-
*
|
|
149
|
-
* - `"auto"` (default): create a symlink to the canonical `.crust/skills`
|
|
150
|
-
* bundle, falling back to a hard copy when symlinks are unavailable.
|
|
151
|
-
* - `"symlink"`: require symlinks; fail if a symlink cannot be created.
|
|
152
|
-
* - `"copy"`: write full copies directly into each agent path.
|
|
153
|
-
*
|
|
154
|
-
* Canonical bundles are always generated once under `.crust/skills` (project)
|
|
155
|
-
* or `~/.crust/skills` (global). When `process.cwd()` is the home directory,
|
|
156
|
-
* project scope is normalized to the global location.
|
|
157
|
-
* @default "auto"
|
|
158
|
-
*/
|
|
159
|
-
installMode?: SkillInstallMode;
|
|
160
|
-
/**
|
|
161
|
-
* Installation scope — global (home directory) or project (cwd).
|
|
162
|
-
* When `process.cwd()` is the home directory, `"project"` is treated as `"global"`.
|
|
163
|
-
* @default "global"
|
|
164
|
-
*/
|
|
165
|
-
scope?: Scope;
|
|
166
|
-
/**
|
|
167
|
-
* When `true`, removes the existing skill directory before writing.
|
|
168
|
-
* Prevents stale files from previous generations.
|
|
169
|
-
* @default true
|
|
170
|
-
*/
|
|
171
|
-
clean?: boolean;
|
|
172
|
-
/**
|
|
173
|
-
* When `true`, rewrite the generated skill even when the recorded version is
|
|
174
|
-
* unchanged, and overwrite an existing conflicting directory (for example,
|
|
175
|
-
* no `crust.json`, malformed `crust.json`, or a different skill kind)
|
|
176
|
-
* instead of throwing {@link SkillConflictError}.
|
|
177
|
-
* @default false
|
|
178
|
-
*/
|
|
179
|
-
force?: boolean;
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Top-level options for installing a hand-authored skill bundle.
|
|
183
|
-
*
|
|
184
|
-
* Unlike {@link GenerateOptions}, the bundle entrypoint does not render
|
|
185
|
-
* `SKILL.md` from a command tree — it copies a directory the caller has
|
|
186
|
-
* already authored. The bundle's `SKILL.md` frontmatter is the source of
|
|
187
|
-
* truth for `name` and `description`; Crust reads them but does not rewrite
|
|
188
|
-
* the file. A fresh `crust.json` is written alongside the bundle for
|
|
189
|
-
* ownership and version tracking.
|
|
190
|
-
*
|
|
191
|
-
* Bundle files are copied as raw bytes. `SKILL.md` is also parsed as UTF-8
|
|
192
|
-
* to read its required frontmatter.
|
|
193
|
-
*
|
|
194
|
-
* Bundle content changes do not propagate without a `version` bump:
|
|
195
|
-
* identical-version reinstalls report `up-to-date` and leave the canonical
|
|
196
|
-
* store untouched. Pass a fresh `version` whenever the bundle contents
|
|
197
|
-
* change (e.g. wire it to the consuming package's `package.json` `version`).
|
|
198
|
-
*
|
|
199
|
-
* @example
|
|
200
|
-
* ```ts
|
|
201
|
-
* import { installSkillBundle } from "@crustjs/skills";
|
|
202
|
-
* import pkg from "./package.json" with { type: "json" };
|
|
203
|
-
*
|
|
204
|
-
* // SKILL.md frontmatter supplies name + description; the caller passes
|
|
205
|
-
* // the version explicitly (typically wired to package.json).
|
|
206
|
-
* await installSkillBundle({
|
|
207
|
-
* sourceDir: "skills/funnel-builder",
|
|
208
|
-
* agents: ["claude-code"],
|
|
209
|
-
* version: pkg.version,
|
|
210
|
-
* });
|
|
211
|
-
* ```
|
|
212
|
-
*/
|
|
213
|
-
interface InstallSkillBundleOptions {
|
|
214
|
-
/**
|
|
215
|
-
* Source directory containing the bundle to install.
|
|
216
|
-
*
|
|
217
|
-
* Resolution rules (mirror `@crustjs/create`'s `scaffold({ template })`):
|
|
218
|
-
* - `URL` — must use `file:` protocol; resolved via `fileURLToPath()`.
|
|
219
|
-
* - Absolute string path — used as-is via `path.resolve()`.
|
|
220
|
-
* - Relative string path — resolved from the nearest `package.json`
|
|
221
|
-
* directory walking up from `process.argv[1]`. Throws if `process.argv[1]`
|
|
222
|
-
* is unset or no `package.json` is found.
|
|
223
|
-
*
|
|
224
|
-
* The directory must contain a `SKILL.md` whose YAML frontmatter declares
|
|
225
|
-
* top-level `name:` and `description:` fields.
|
|
226
|
-
*/
|
|
227
|
-
sourceDir: string | URL;
|
|
228
|
-
/**
|
|
229
|
-
* Agent targets to install the bundle for.
|
|
230
|
-
*
|
|
231
|
-
* Required — unlike {@link GenerateOptions.agents}, the bundle entrypoint
|
|
232
|
-
* does not auto-detect agents. Pass `[]` for a validated no-op: no install
|
|
233
|
-
* is performed, but `sourceDir`, `SKILL.md`, bundle paths, frontmatter, and
|
|
234
|
-
* skill name are still validated.
|
|
235
|
-
*/
|
|
236
|
-
agents: AgentTarget[];
|
|
237
|
-
/**
|
|
238
|
-
* Version string recorded for this install and compared on subsequent
|
|
239
|
-
* installs to decide between `installed` / `updated` / `up-to-date`.
|
|
240
|
-
*
|
|
241
|
-
* Required. Typically wired to the consuming package's `package.json`
|
|
242
|
-
* `version` (e.g. via `import pkg from "./package.json" with { type:
|
|
243
|
-
* "json" }`). Identical-version reinstalls report `up-to-date` and skip
|
|
244
|
-
* the canonical-store rewrite (unless `force: true` is passed), so bump
|
|
245
|
-
* this whenever bundle contents change.
|
|
246
|
-
*/
|
|
247
|
-
version: string;
|
|
248
|
-
/**
|
|
249
|
-
* Installation strategy for agent output paths.
|
|
250
|
-
* @default "auto"
|
|
251
|
-
*/
|
|
252
|
-
installMode?: SkillInstallMode;
|
|
253
|
-
/**
|
|
254
|
-
* Installation scope — global (home directory) or project (cwd).
|
|
255
|
-
* @default "global"
|
|
256
|
-
*/
|
|
257
|
-
scope?: Scope;
|
|
258
|
-
/**
|
|
259
|
-
* When `true`, removes the existing skill directory before writing.
|
|
260
|
-
* @default true
|
|
261
|
-
*/
|
|
262
|
-
clean?: boolean;
|
|
263
|
-
/**
|
|
264
|
-
* When `true`, rewrite the bundle even when the recorded version is
|
|
265
|
-
* unchanged, and overwrite an existing conflicting directory (for example,
|
|
266
|
-
* no `crust.json`, malformed `crust.json`, or a different skill kind)
|
|
267
|
-
* instead of throwing {@link SkillConflictError}.
|
|
268
|
-
* @default false
|
|
269
|
-
*/
|
|
270
|
-
force?: boolean;
|
|
271
|
-
/**
|
|
272
|
-
* When set, the bundle's `SKILL.md` frontmatter `name:` must equal this
|
|
273
|
-
* string. A mismatch throws before any filesystem write.
|
|
274
|
-
*
|
|
275
|
-
* Used by `skillPlugin`'s `customSkills` reconciliation to keep the
|
|
276
|
-
* config-level `name` (used for status / uninstall lookups) in lockstep
|
|
277
|
-
* with the frontmatter `name` (the canonical install path), preventing
|
|
278
|
-
* orphan installs.
|
|
279
|
-
*/
|
|
280
|
-
expectedName?: string;
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Result returned by `installSkillBundle` after writing files to disk.
|
|
284
|
-
*
|
|
285
|
-
* Type alias of {@link GenerateResult} — the per-agent shape is identical.
|
|
286
|
-
*/
|
|
287
|
-
type InstallSkillBundleResult = GenerateResult;
|
|
288
|
-
/** Status of an individual agent installation. */
|
|
289
|
-
type InstallStatus = "installed" | "updated" | "up-to-date";
|
|
290
|
-
/** Status of an individual agent uninstallation. */
|
|
30
|
+
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" | "warp" | "windsurf" | "zed" | "zencoder";
|
|
31
|
+
/** Returns agents that use the canonical `.agents/skills` layout. */
|
|
32
|
+
export declare function getUniversalAgents(): AgentTarget[];
|
|
33
|
+
/** Returns agents that do not use the canonical layout at both scopes. */
|
|
34
|
+
export declare function getAdditionalAgents(): AgentTarget[];
|
|
35
|
+
/** Returns true if the agent uses the canonical layout at both scopes. */
|
|
36
|
+
export declare function isUniversalAgent(agent: AgentTarget): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Detects installed non-universal agents by checking PATH for their CLI binaries.
|
|
39
|
+
*
|
|
40
|
+
* Universal agents are intentionally not detected here so callers can always
|
|
41
|
+
* present them as a single optional "Universal" install target.
|
|
42
|
+
*/
|
|
43
|
+
export declare function detectInstalledAgents(): Promise<AgentTarget[]>;
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/types.d.ts
|
|
46
|
+
/** Options for linking one packaged skill source into agent directories. */
|
|
47
|
+
interface InstallSkillOptions {
|
|
48
|
+
/** Package directory `skills/<name>` containing the skill's SKILL.md. */
|
|
49
|
+
sourceDir: string | URL;
|
|
50
|
+
/** Agent targets. Omit to use universal plus PATH-detected agents. */
|
|
51
|
+
agents?: AgentTarget[];
|
|
52
|
+
/** Agent-directory scope. @default "global" */
|
|
53
|
+
scope?: Scope;
|
|
54
|
+
/** Allow replacing a directory that is not owned by this skill. @default false */
|
|
55
|
+
force?: boolean;
|
|
56
|
+
}
|
|
57
|
+
type InstallStatus = "installed" | "repaired" | "up-to-date";
|
|
291
58
|
type UninstallStatus = "removed" | "not-found";
|
|
292
|
-
/** Per-agent result from a generateSkill call. */
|
|
293
59
|
interface AgentResult {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
interface
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Installation scope to check.
|
|
364
|
-
* When `process.cwd()` is the home directory, `"project"` is treated as `"global"`.
|
|
365
|
-
* @default "global"
|
|
366
|
-
*/
|
|
367
|
-
scope?: Scope;
|
|
368
|
-
}
|
|
369
|
-
/** Result returned by `skillStatus`. */
|
|
370
|
-
interface StatusResult {
|
|
371
|
-
/** Per-agent status results */
|
|
372
|
-
agents: Array<{
|
|
373
|
-
agent: AgentTarget;
|
|
374
|
-
outputDir: string;
|
|
375
|
-
installed: boolean;
|
|
376
|
-
version?: string;
|
|
377
|
-
}>;
|
|
378
|
-
}
|
|
379
|
-
/**
|
|
380
|
-
* Configuration for a single hand-authored skill bundle managed by
|
|
381
|
-
* {@link skillPlugin} alongside the auto-generated command-reference skill.
|
|
382
|
-
*
|
|
383
|
-
* Each entry is reconciled through the same plugin lifecycle as the main
|
|
384
|
-
* skill — auto-update on version change, surfaced in the interactive `skill`
|
|
385
|
-
* subcommand multiselect, supports uninstall via the same toggle UX, and
|
|
386
|
-
* respects `autoUpdate: false` and `--all` non-interactive mode. Bundles
|
|
387
|
-
* inherit `version`, `defaultScope`, and `installMode` from the plugin
|
|
388
|
-
* unless overridden per-entry.
|
|
389
|
-
*
|
|
390
|
-
* The bundle's `SKILL.md` frontmatter remains the source of truth for the
|
|
391
|
-
* display `name` and `description` (validated by {@link installSkillBundle}
|
|
392
|
-
* at install time). The duplicated `name` field on this config is what the
|
|
393
|
-
* plugin uses for cheap collision-detection, status lookups, and uninstall
|
|
394
|
-
* paths without having to read the bundle's frontmatter at plugin setup.
|
|
395
|
-
*
|
|
396
|
-
* @example
|
|
397
|
-
* ```ts
|
|
398
|
-
* import { skillPlugin } from "@crustjs/skills";
|
|
399
|
-
* import pkg from "./package.json" with { type: "json" };
|
|
400
|
-
*
|
|
401
|
-
* skillPlugin({
|
|
402
|
-
* version: pkg.version,
|
|
403
|
-
* customSkills: [
|
|
404
|
-
* // Inherits `version: pkg.version` from the plugin.
|
|
405
|
-
* { name: "funnel-builder", sourceDir: "skills/funnel-builder" },
|
|
406
|
-
* // Explicit override for an independently-versioned bundle.
|
|
407
|
-
* {
|
|
408
|
-
* name: "vendored-toolkit",
|
|
409
|
-
* sourceDir: "skills/vendored-toolkit",
|
|
410
|
-
* version: "0.3.0",
|
|
411
|
-
* },
|
|
412
|
-
* ],
|
|
413
|
-
* });
|
|
414
|
-
* ```
|
|
415
|
-
*/
|
|
416
|
-
interface CustomSkillConfig extends Pick<InstallSkillBundleOptions, "sourceDir" | "scope" | "installMode"> {
|
|
417
|
-
/**
|
|
418
|
-
* Skill name used by the plugin for collision detection, status lookups,
|
|
419
|
-
* and uninstall paths.
|
|
420
|
-
*
|
|
421
|
-
* Must satisfy `isValidSkillName` (1–64 lowercase alphanumeric characters
|
|
422
|
-
* and hyphens, no leading/trailing/consecutive hyphens), must be unique
|
|
423
|
-
* within the `customSkills` array, and must not collide with the main
|
|
424
|
-
* skill's name (derived from the root command's `meta`).
|
|
425
|
-
*
|
|
426
|
-
* The bundle's `SKILL.md` frontmatter `name:` must match this value —
|
|
427
|
-
* mismatches are rejected at install time so plugin status / uninstall
|
|
428
|
-
* paths can never drift from the canonical install location.
|
|
429
|
-
*/
|
|
430
|
-
name: string;
|
|
431
|
-
/**
|
|
432
|
-
* Version override. When omitted, the bundle inherits the plugin's
|
|
433
|
-
* top-level {@link SkillPluginOptions.version}. Drives auto-update
|
|
434
|
-
* detection: a bundle is reinstalled when its recorded `crust.json`
|
|
435
|
-
* version differs from the effective (entry-or-plugin) version.
|
|
436
|
-
*
|
|
437
|
-
* Inheriting from the plugin matches the typical case where the bundle
|
|
438
|
-
* ships in the same package as the consuming CLI — one `pkg.version`
|
|
439
|
-
* drives the main skill and every bundle. Pass an explicit value when a
|
|
440
|
-
* bundle's release cadence is independent of the consuming CLI (for
|
|
441
|
-
* example, vendored from another package).
|
|
442
|
-
*
|
|
443
|
-
* The bundle's `SKILL.md` frontmatter `version:` / `metadata.version`,
|
|
444
|
-
* if any, is intentionally not read — this option (or its plugin-level
|
|
445
|
-
* fallback) is the sole source of truth.
|
|
446
|
-
*/
|
|
447
|
-
version?: InstallSkillBundleOptions["version"];
|
|
448
|
-
/**
|
|
449
|
-
* Installation scope override. When omitted, the bundle inherits
|
|
450
|
-
* {@link SkillPluginOptions.defaultScope} resolution: explicit `--scope`
|
|
451
|
-
* flag wins, else `defaultScope`, else the interactive scope prompt
|
|
452
|
-
* (or `"global"` in non-interactive mode).
|
|
453
|
-
*/
|
|
454
|
-
scope?: InstallSkillBundleOptions["scope"];
|
|
455
|
-
/**
|
|
456
|
-
* Installation strategy override. When omitted, inherits
|
|
457
|
-
* {@link SkillPluginOptions.installMode} (default `"auto"`).
|
|
458
|
-
*/
|
|
459
|
-
installMode?: InstallSkillBundleOptions["installMode"];
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* Options for the skill plugin.
|
|
463
|
-
*
|
|
464
|
-
* The plugin reads `name` and `description` from the root command's `meta`
|
|
465
|
-
* at setup time, so only `version` is required here.
|
|
466
|
-
*
|
|
467
|
-
* Installed agents are detected automatically.
|
|
468
|
-
*
|
|
469
|
-
* Only detected agents are managed.
|
|
470
|
-
*
|
|
471
|
-
* **Auto-update** (default): silently updates already-installed skills when a
|
|
472
|
-
* new version is detected. Disable with `autoUpdate: false`.
|
|
473
|
-
*
|
|
474
|
-
* For first-time installation, use the interactive `skill` subcommand or
|
|
475
|
-
* build custom auto-install logic with the exported primitives
|
|
476
|
-
* (`detectInstalledAgents`, `skillStatus`, `generateSkill`).
|
|
477
|
-
*
|
|
478
|
-
* **Interactive command** (default): registers a `skill` subcommand (or the
|
|
479
|
-
* custom `command` name) that
|
|
480
|
-
* presents a single multiselect prompt for toggling agent installations.
|
|
481
|
-
*
|
|
482
|
-
* Scope resolution for interactive commands:
|
|
483
|
-
* - If `defaultScope` is set, that scope is used and no scope prompt is shown.
|
|
484
|
-
* - If `defaultScope` is not set and the terminal is interactive, users are
|
|
485
|
-
* prompted to choose `project` or `global`.
|
|
486
|
-
* - If `defaultScope` is not set and the terminal is non-interactive, scope
|
|
487
|
-
* falls back to `"global"`.
|
|
488
|
-
* - When `process.cwd()` is the home directory, `"project"` is normalized to
|
|
489
|
-
* `"global"` for path resolution and update/status messaging.
|
|
490
|
-
*/
|
|
491
|
-
interface SkillPluginOptions {
|
|
492
|
-
/** Skill version string — compared against the installed crust.json */
|
|
493
|
-
version: string;
|
|
494
|
-
/**
|
|
495
|
-
* Default installation scope for interactive commands.
|
|
496
|
-
*
|
|
497
|
-
* When omitted, interactive commands prompt for scope in TTY mode.
|
|
498
|
-
* Non-interactive mode falls back to "global".
|
|
499
|
-
* When `process.cwd()` is the home directory, `"project"` behaves as `"global"`.
|
|
500
|
-
*/
|
|
501
|
-
defaultScope?: Scope;
|
|
502
|
-
/**
|
|
503
|
-
* Installation strategy used when the plugin calls `generateSkill()`.
|
|
504
|
-
* @default "auto"
|
|
505
|
-
*/
|
|
506
|
-
installMode?: SkillInstallMode;
|
|
507
|
-
/**
|
|
508
|
-
* Automatically update skills when the installed version is outdated.
|
|
509
|
-
* @default true
|
|
510
|
-
*/
|
|
511
|
-
autoUpdate?: boolean;
|
|
512
|
-
/**
|
|
513
|
-
* Additional top-level instructions rendered into the generated `SKILL.md`.
|
|
514
|
-
*
|
|
515
|
-
* **Note:** When a `string` value contains markdown headings (e.g. `## Foo`),
|
|
516
|
-
* they are rendered at the same level as `## General Guidance`, not nested
|
|
517
|
-
* under it. Use a `string[]` of plain instructions to avoid unintended
|
|
518
|
-
* heading hierarchy.
|
|
519
|
-
*/
|
|
520
|
-
instructions?: string | string[];
|
|
521
|
-
/** License name or reference emitted in SKILL.md frontmatter. */
|
|
522
|
-
license?: string;
|
|
523
|
-
/**
|
|
524
|
-
* Space-delimited list of pre-approved tools the skill may use.
|
|
525
|
-
*
|
|
526
|
-
* @example "Bash(my-cli *) Read Grep"
|
|
527
|
-
*/
|
|
528
|
-
allowedTools?: string;
|
|
529
|
-
/** Environment requirements or compatibility notes (max 500 chars). */
|
|
530
|
-
compatibility?: string;
|
|
531
|
-
/**
|
|
532
|
-
* When `true`, prevents agents from automatically loading this skill.
|
|
533
|
-
* @default false
|
|
534
|
-
*/
|
|
535
|
-
disableModelInvocation?: boolean;
|
|
536
|
-
/**
|
|
537
|
-
* Hand-authored skill bundles to manage alongside the auto-generated
|
|
538
|
-
* command-reference skill.
|
|
539
|
-
*
|
|
540
|
-
* Each entry is reconciled through the same plugin lifecycle as the main
|
|
541
|
-
* skill — auto-update on version change, surfaced in the interactive
|
|
542
|
-
* `skill` subcommand multiselect (one prompt per bundle, in array order,
|
|
543
|
-
* after the main-skill prompt), supports uninstall via the same toggle
|
|
544
|
-
* UX, and respects `autoUpdate: false` and `--all` non-interactive mode.
|
|
545
|
-
*
|
|
546
|
-
* Bundles share the canonical `.crust/skills` store with the main skill
|
|
547
|
-
* via {@link installSkillBundle} and inherit `defaultScope` /
|
|
548
|
-
* `installMode` resolution unless overridden per-entry.
|
|
549
|
-
*
|
|
550
|
-
* Each entry's effective `version` drives auto-update detection (compared
|
|
551
|
-
* against the recorded `crust.json` version). When the entry omits
|
|
552
|
-
* `version`, the plugin's top-level {@link SkillPluginOptions.version} is
|
|
553
|
-
* used — the typical case when the bundle ships in the same package as
|
|
554
|
-
* the consuming CLI.
|
|
555
|
-
*
|
|
556
|
-
* Setup-time validation enforces:
|
|
557
|
-
* - Each `name` satisfies `isValidSkillName`.
|
|
558
|
-
* - No `name` collides with the main skill's name.
|
|
559
|
-
* - All `name` values are unique within the array.
|
|
560
|
-
* - When set, `version` is a non-empty string.
|
|
561
|
-
* - Each `sourceDir` is a `string` or `URL`.
|
|
562
|
-
*
|
|
563
|
-
* `sourceDir` resolution-time errors (non-`file:` URL, missing source
|
|
564
|
-
* directory, missing `SKILL.md`, etc.) defer to the underlying
|
|
565
|
-
* `installSkillBundle` invocation and surface there with descriptive
|
|
566
|
-
* messages.
|
|
567
|
-
*
|
|
568
|
-
* When omitted or empty, plugin behavior is byte-identical to running
|
|
569
|
-
* without the option — only the auto-generated main skill is managed.
|
|
570
|
-
*
|
|
571
|
-
* @default []
|
|
572
|
-
*/
|
|
573
|
-
customSkills?: CustomSkillConfig[];
|
|
574
|
-
/**
|
|
575
|
-
* Register an interactive skill management subcommand on the root command.
|
|
576
|
-
*
|
|
577
|
-
* The command presents a single multiselect prompt listing all detected
|
|
578
|
-
* agents with their current installation status pre-filled. The user
|
|
579
|
-
* toggles agents on/off and the system reconciles the desired state:
|
|
580
|
-
* newly selected agents are installed, deselected agents are uninstalled,
|
|
581
|
-
* and already-correct agents are skipped.
|
|
582
|
-
*
|
|
583
|
-
* @default "skill"
|
|
584
|
-
*/
|
|
585
|
-
command?: string;
|
|
586
|
-
}
|
|
587
|
-
/** Returns agents that use the canonical `.agents/skills` layout. */
|
|
588
|
-
declare function getUniversalAgents(): AgentTarget[];
|
|
589
|
-
/** Returns agents that use agent-specific skill roots. */
|
|
590
|
-
declare function getAdditionalAgents(): AgentTarget[];
|
|
591
|
-
/** Returns true if the agent uses the canonical `.agents/skills` layout. */
|
|
592
|
-
declare function isUniversalAgent(agent: AgentTarget): boolean;
|
|
593
|
-
interface DetectInstalledAgentsOptions {
|
|
594
|
-
/** Kept for backwards compatibility with previous API. */
|
|
595
|
-
scope?: Scope;
|
|
596
|
-
/** Kept for backwards compatibility with previous API. */
|
|
597
|
-
home?: string;
|
|
598
|
-
/** Working directory for PATH lookups. */
|
|
599
|
-
cwd?: string;
|
|
600
|
-
/** Test-only hook to override command detection. */
|
|
601
|
-
commandChecker?: (command: string, cwd: string) => Promise<boolean>;
|
|
60
|
+
agent: AgentTarget;
|
|
61
|
+
outputDir: string;
|
|
62
|
+
/** Effective scope after remapping project scope at the home directory. */
|
|
63
|
+
scope: Scope;
|
|
64
|
+
status: InstallStatus;
|
|
65
|
+
}
|
|
66
|
+
interface InstallSkillResult {
|
|
67
|
+
agents: AgentResult[];
|
|
68
|
+
}
|
|
69
|
+
interface UninstallSkillOptions {
|
|
70
|
+
name: string;
|
|
71
|
+
agents?: AgentTarget[];
|
|
72
|
+
scope?: Scope;
|
|
73
|
+
}
|
|
74
|
+
interface UninstallSkillResult {
|
|
75
|
+
agents: Array<{
|
|
76
|
+
agent: AgentTarget;
|
|
77
|
+
outputDir: string;
|
|
78
|
+
scope: Scope;
|
|
79
|
+
status: UninstallStatus;
|
|
80
|
+
}>;
|
|
81
|
+
}
|
|
82
|
+
interface SkillStatusOptions {
|
|
83
|
+
name: string;
|
|
84
|
+
/** Expected source used to identify stale-target links. */
|
|
85
|
+
sourceDir: string | URL;
|
|
86
|
+
agents?: AgentTarget[];
|
|
87
|
+
scope?: Scope;
|
|
88
|
+
}
|
|
89
|
+
type SkillLinkStatus = "linked" | "dangling" | "conflict" | "absent";
|
|
90
|
+
interface SkillStatusResult {
|
|
91
|
+
agents: Array<{
|
|
92
|
+
agent: AgentTarget;
|
|
93
|
+
outputDir: string;
|
|
94
|
+
scope: Scope;
|
|
95
|
+
status: SkillLinkStatus;
|
|
96
|
+
}>;
|
|
97
|
+
}
|
|
98
|
+
/** Options for the skills extension. */
|
|
99
|
+
interface SkillOptions {
|
|
100
|
+
/** Packaged skills directory read at runtime for discovery and installation. */
|
|
101
|
+
distDir: string | URL;
|
|
102
|
+
/** Hand-authored skill directories (URL, absolute, or package-root-relative path) built alongside the generated skill. */
|
|
103
|
+
extras?: readonly (string | URL)[];
|
|
104
|
+
/** Generated command skill name. Defaults to the root command name. */
|
|
105
|
+
name?: string;
|
|
106
|
+
/** Generated command skill description. Defaults to the root command description. */
|
|
107
|
+
description?: string;
|
|
108
|
+
/** Whether to build the generated command skill. Set `false` to ship only `extras`. @default true */
|
|
109
|
+
generated?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Agent-directory scope used when no `--scope` flag is passed.
|
|
112
|
+
* When set, skips the scope prompt and limits automatic link repairs to this scope.
|
|
113
|
+
* When omitted, interactive management prompts for scope.
|
|
114
|
+
* @default "global" for `--all` and the scope prompt.
|
|
115
|
+
*/
|
|
116
|
+
defaultScope?: Scope;
|
|
117
|
+
/** Repair stale or dangling owned links before commands run. @default true */
|
|
118
|
+
autoUpdate?: boolean;
|
|
119
|
+
/** Name of the interactive management command. @default "skill" */
|
|
120
|
+
command?: string;
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/errors.d.ts
|
|
124
|
+
export declare class SkillSourceConflictError extends Error {
|
|
125
|
+
override readonly name = "SkillSourceConflictError";
|
|
126
|
+
readonly skillName: string;
|
|
127
|
+
constructor(skillName: string);
|
|
602
128
|
}
|
|
603
|
-
/**
|
|
604
|
-
* Detects installed additional agents by checking PATH for their CLI binaries.
|
|
605
|
-
*
|
|
606
|
-
* Universal agents are intentionally not detected here so callers can always
|
|
607
|
-
* present them as a single optional "Universal" install target.
|
|
608
|
-
*/
|
|
609
|
-
declare function detectInstalledAgents(options?: string | DetectInstalledAgentsOptions): Promise<AgentTarget[]>;
|
|
610
|
-
/**
|
|
611
|
-
* Resolves the canonical skill bundle path used by Crust.
|
|
612
|
-
*/
|
|
613
|
-
declare function resolveCanonicalSkillPath(scope: Scope, name: string): string;
|
|
614
|
-
import { CommandNode as CommandNode2 } from "@crustjs/core";
|
|
615
|
-
import { Crust } from "@crustjs/core";
|
|
616
|
-
/**
|
|
617
|
-
* Agent-oriented instructions attached to a command for skills rendering.
|
|
618
|
-
*/
|
|
619
|
-
interface SkillCommandAnnotations {
|
|
620
|
-
/** Additional prompt guidance rendered into the command's markdown file */
|
|
621
|
-
instructions?: string[];
|
|
622
|
-
}
|
|
623
|
-
type SkillCommandTarget = CommandNode2 | Crust<any, any, any>;
|
|
624
|
-
/**
|
|
625
|
-
* Attaches agent-facing instructions to a command definition without changing
|
|
626
|
-
* the public `@crustjs/core` API surface.
|
|
627
|
-
*
|
|
628
|
-
* The instructions are stored on the internal command node using an enumerable
|
|
629
|
-
* symbol so they survive Crust's immutable clone/spread builder operations.
|
|
630
|
-
*
|
|
631
|
-
* Duplicate instructions are silently deduplicated — calling `annotate()` again
|
|
632
|
-
* with the same text is a safe no-op.
|
|
633
|
-
*/
|
|
634
|
-
declare function annotate<T extends SkillCommandTarget>(target: T, annotations: string | string[] | SkillCommandAnnotations): T;
|
|
635
|
-
/**
|
|
636
|
-
* Installs a hand-authored skill bundle through the same canonical-store and
|
|
637
|
-
* agent-fan-out pipeline used by {@link generateSkill}.
|
|
638
|
-
*
|
|
639
|
-
* Unlike `generateSkill`, this entrypoint does not render any markdown — it
|
|
640
|
-
* copies the directory at `sourceDir` as authored (subject to a
|
|
641
|
-
* path-traversal guard against symlink escapes and a cycle guard) and
|
|
642
|
-
* writes a fresh `crust.json` recording `kind: "bundle"`. Bundle authors
|
|
643
|
-
* are responsible for keeping `sourceDir` clean — `crust.json` at the
|
|
644
|
-
* bundle root is reserved and will throw if present in the source.
|
|
645
|
-
*
|
|
646
|
-
* The bundle's `SKILL.md` frontmatter is the source of truth for `name` and
|
|
647
|
-
* `description`; both are required and read by Crust without rewriting the
|
|
648
|
-
* file. The caller supplies `version` explicitly — typically wired to the
|
|
649
|
-
* consuming package's `package.json` `version`.
|
|
650
|
-
*
|
|
651
|
-
* Bundles and generated skills cannot share a name unless the existing
|
|
652
|
-
* install is removed first. `force: true` overwrites a conflicting install
|
|
653
|
-
* (no `crust.json`, malformed `crust.json`, or kind mismatch) and also
|
|
654
|
-
* rewrites a same-version bundle.
|
|
655
|
-
*
|
|
656
|
-
* @param options - Bundle install options (see {@link InstallSkillBundleOptions})
|
|
657
|
-
* @returns Per-agent install results
|
|
658
|
-
* @throws {SkillConflictError} If the canonical store exists with no
|
|
659
|
-
* `crust.json`, a malformed `crust.json`, or a different kind (and `force`
|
|
660
|
-
* is not set).
|
|
661
|
-
* @throws {Error} If `SKILL.md` is missing, its frontmatter lacks `name:` or
|
|
662
|
-
* `description:`, the declared `name` is not a valid skill name, the
|
|
663
|
-
* declared `name` does not match `expectedName` when set, the source
|
|
664
|
-
* directory escapes itself via symlink, or `sourceDir` cannot be resolved.
|
|
665
|
-
*
|
|
666
|
-
* @example
|
|
667
|
-
* ```ts
|
|
668
|
-
* import { installSkillBundle } from "@crustjs/skills";
|
|
669
|
-
* import pkg from "./package.json" with { type: "json" };
|
|
670
|
-
*
|
|
671
|
-
* await installSkillBundle({
|
|
672
|
-
* sourceDir: "skills/funnel-builder",
|
|
673
|
-
* agents: ["claude-code"],
|
|
674
|
-
* version: pkg.version,
|
|
675
|
-
* });
|
|
676
|
-
* ```
|
|
677
|
-
*/
|
|
678
|
-
declare function installSkillBundle(options: InstallSkillBundleOptions): Promise<InstallSkillBundleResult>;
|
|
679
|
-
/**
|
|
680
|
-
* Why an installed manifest could not be interpreted.
|
|
681
|
-
*
|
|
682
|
-
* - `parse-error`: `crust.json` is present but is not valid JSON.
|
|
683
|
-
* - `not-an-object`: top-level JSON value is not an object.
|
|
684
|
-
* - `missing-version`: `version` field is absent or not a string.
|
|
685
|
-
* - `unknown-kind`: `kind` is present but is neither `"bundle"` nor `"generated"` —
|
|
686
|
-
* typically a hand-edit typo or a forward-compatible value emitted by a
|
|
687
|
-
* newer Crust release.
|
|
688
|
-
*/
|
|
689
|
-
type InstalledManifestMalformedReason = "parse-error" | "not-an-object" | "missing-version" | "unknown-kind";
|
|
690
|
-
/**
|
|
691
|
-
* Describes a kind mismatch between an existing installed bundle and an
|
|
692
|
-
* incoming install attempt.
|
|
693
|
-
*
|
|
694
|
-
* Set on {@link SkillConflictDetails.kindMismatch} when {@link generateSkill}
|
|
695
|
-
* or {@link installSkillBundle} discovers an existing `crust.json` whose
|
|
696
|
-
* `kind` differs from the kind being installed (e.g. a generated skill
|
|
697
|
-
* already lives at the target path and a bundle install was attempted).
|
|
698
|
-
*/
|
|
699
|
-
interface SkillKindMismatch {
|
|
700
|
-
/** Kind recorded in the existing `crust.json` */
|
|
701
|
-
existing: SkillKind;
|
|
702
|
-
/** Kind requested by the current install attempt */
|
|
703
|
-
attempted: SkillKind;
|
|
704
|
-
}
|
|
705
|
-
/**
|
|
706
|
-
* Describes a malformed `crust.json` discovered at the conflicting skill
|
|
707
|
-
* directory.
|
|
708
|
-
*
|
|
709
|
-
* Set on {@link SkillConflictDetails.manifestMalformed} when the directory
|
|
710
|
-
* contains a `crust.json` that exists but cannot be interpreted — e.g. it is
|
|
711
|
-
* not valid JSON, lacks a `version`, or has an unrecognized `kind` value
|
|
712
|
-
* (a hand-edit typo like `"bundel"`, or a forward-compatible value emitted by
|
|
713
|
-
* a newer Crust release). Distinct from a missing `crust.json`, which keeps
|
|
714
|
-
* the original "not created by Crust" semantics.
|
|
715
|
-
*/
|
|
716
|
-
interface SkillManifestMalformed {
|
|
717
|
-
/** Why the manifest could not be interpreted. */
|
|
718
|
-
reason: InstalledManifestMalformedReason;
|
|
719
|
-
/** Raw `kind` value when `reason === "unknown-kind"`. */
|
|
720
|
-
rawKind?: string;
|
|
721
|
-
}
|
|
722
|
-
/** Details about the conflict between an existing skill and an incoming one. */
|
|
723
129
|
interface SkillConflictDetails {
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
*
|
|
748
|
-
*
|
|
749
|
-
*
|
|
750
|
-
*
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
*
|
|
760
|
-
*
|
|
761
|
-
*
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
* );
|
|
774
|
-
* }
|
|
775
|
-
* }
|
|
776
|
-
* }
|
|
777
|
-
* ```
|
|
778
|
-
*/
|
|
779
|
-
declare class SkillConflictError extends Error {
|
|
780
|
-
readonly name = "SkillConflictError";
|
|
781
|
-
readonly details: SkillConflictDetails;
|
|
782
|
-
constructor(details: SkillConflictDetails);
|
|
783
|
-
}
|
|
784
|
-
/**
|
|
785
|
-
* Validates a resolved skill name against the Agent Skills specification.
|
|
786
|
-
*
|
|
787
|
-
* @param name - The resolved skill name to validate
|
|
788
|
-
* @returns `true` if valid, `false` otherwise
|
|
789
|
-
*/
|
|
790
|
-
declare function isValidSkillName(name: string): boolean;
|
|
791
|
-
/**
|
|
792
|
-
* Resolves the canonical current skill name.
|
|
793
|
-
*
|
|
794
|
-
* All generated output (directory names, crust.json metadata, SKILL.md content)
|
|
795
|
-
* uses the resolved name directly. Consumers pass the raw CLI name
|
|
796
|
-
* (e.g. `"my-cli"`), and this function returns that same canonical name.
|
|
797
|
-
*
|
|
798
|
-
* @param name - The raw CLI tool name
|
|
799
|
-
* @returns The canonical skill name
|
|
800
|
-
*
|
|
801
|
-
* @example
|
|
802
|
-
* ```ts
|
|
803
|
-
* resolveSkillName("my-cli"); // "my-cli"
|
|
804
|
-
* ```
|
|
805
|
-
*/
|
|
806
|
-
declare function resolveSkillName(name: string): string;
|
|
807
|
-
/**
|
|
808
|
-
* Generates and installs agent skill bundles from a Crust command tree.
|
|
809
|
-
*
|
|
810
|
-
* The generator renders the bundle once into a canonical Crust store
|
|
811
|
-
* (`.crust/skills` project scope, `~/.crust/skills` global scope), then
|
|
812
|
-
* installs into agent-specific output paths using the configured install mode
|
|
813
|
-
* (`auto`, `symlink`, `copy`).
|
|
814
|
-
*
|
|
815
|
-
* @param options - Generation options including command, metadata, agents, and scope
|
|
816
|
-
* @returns Per-agent installation results
|
|
817
|
-
* @throws {SkillConflictError} If the output directory conflicts (no `crust.json`, malformed `crust.json`, or kind mismatch) and `force` is not set
|
|
818
|
-
*
|
|
819
|
-
* @example
|
|
820
|
-
* ```ts
|
|
821
|
-
* import { generateSkill } from "@crustjs/skills";
|
|
822
|
-
* import { rootCommand } from "./commands.ts";
|
|
823
|
-
*
|
|
824
|
-
* const result = await generateSkill({
|
|
825
|
-
* command: rootCommand,
|
|
826
|
-
* meta: {
|
|
827
|
-
* name: "my-cli",
|
|
828
|
-
* description: "CLI tool for managing widgets",
|
|
829
|
-
* version: "1.0.0",
|
|
830
|
-
* },
|
|
831
|
-
* agents: ["claude-code", "opencode"],
|
|
832
|
-
* });
|
|
833
|
-
*
|
|
834
|
-
* for (const r of result.agents) {
|
|
835
|
-
* console.log(`${r.agent}: ${r.status} → ${r.outputDir}`);
|
|
836
|
-
* }
|
|
837
|
-
* ```
|
|
838
|
-
*/
|
|
839
|
-
declare function generateSkill(options: GenerateOptions): Promise<GenerateResult>;
|
|
840
|
-
/**
|
|
841
|
-
* Removes installed skills from agent directories.
|
|
842
|
-
*
|
|
843
|
-
* @param options - Uninstall options specifying name, agents, and scope
|
|
844
|
-
* @returns Per-agent uninstall results
|
|
845
|
-
*/
|
|
846
|
-
declare function uninstallSkill(options: UninstallOptions): Promise<UninstallResult>;
|
|
847
|
-
/**
|
|
848
|
-
* Checks the installation status of skills across agent directories.
|
|
849
|
-
*
|
|
850
|
-
* @param options - Status options specifying name, agents, and scope
|
|
851
|
-
* @returns Per-agent status results
|
|
852
|
-
*/
|
|
853
|
-
declare function skillStatus(options: StatusOptions): Promise<StatusResult>;
|
|
854
|
-
import { CrustPlugin } from "@crustjs/core";
|
|
855
|
-
/**
|
|
856
|
-
* Plugin that manages agent skills for a Crust CLI application.
|
|
857
|
-
*
|
|
858
|
-
* `name` and `description` are read from the root command's `meta` at setup
|
|
859
|
-
* time — only `version` needs to be supplied in the options.
|
|
860
|
-
*
|
|
861
|
-
* Installed agents are detected automatically.
|
|
862
|
-
*
|
|
863
|
-
* Only detected agents are managed by automatic update and the interactive
|
|
864
|
-
* command.
|
|
865
|
-
*
|
|
866
|
-
* **Auto-update** (default): silently updates already-installed skills when a
|
|
867
|
-
* new version is detected. Disable with `autoUpdate: false`.
|
|
868
|
-
*
|
|
869
|
-
* **Interactive command** (default): registers a `skill` subcommand that
|
|
870
|
-
* presents a single multiselect prompt for toggling agent installations.
|
|
871
|
-
* Detected agents are shown with their current installation status pre-filled.
|
|
872
|
-
* The system reconciles the desired state: newly selected agents are installed,
|
|
873
|
-
* deselected agents are uninstalled, and already-correct agents are skipped.
|
|
874
|
-
* `command` configures the injected command name.
|
|
875
|
-
*
|
|
876
|
-
* For first-time installation, use the interactive command or build custom
|
|
877
|
-
* auto-install logic with the exported primitives (`detectInstalledAgents`,
|
|
878
|
-
* `skillStatus`, `generateSkill`).
|
|
879
|
-
*
|
|
880
|
-
* @param options - Plugin configuration with version and defaults
|
|
881
|
-
* @returns A `CrustPlugin` to register in a command's `plugins` array
|
|
882
|
-
*
|
|
883
|
-
* @example
|
|
884
|
-
* ```ts
|
|
885
|
-
* import { Crust } from "@crustjs/core";
|
|
886
|
-
* import { skillPlugin } from "@crustjs/skills";
|
|
887
|
-
*
|
|
888
|
-
* const app = new Crust("my-cli").meta({ description: "My CLI" })
|
|
889
|
-
* .use(skillPlugin({
|
|
890
|
-
* version: "1.0.0",
|
|
891
|
-
* command: "skill", // registers "my-cli skill" subcommand
|
|
892
|
-
* }))
|
|
893
|
-
* .run(() => { /* ... *�/ });
|
|
894
|
-
*
|
|
895
|
-
* await app.execute();
|
|
896
|
-
* ```
|
|
897
|
-
*/
|
|
898
|
-
declare function skillPlugin(options: SkillPluginOptions): CrustPlugin;
|
|
899
|
-
export { uninstallSkill, skillStatus, skillPlugin, resolveSkillName, resolveCanonicalSkillPath, isValidSkillName, isUniversalAgent, installSkillBundle, getUniversalAgents, getAdditionalAgents, generateSkill, detectInstalledAgents, annotate, UninstallStatus, UninstallResult, UninstallOptions, StatusResult, StatusOptions, SkillPluginOptions, SkillMeta, SkillManifestMalformed, SkillKindMismatch, SkillKind, SkillInstallMode, SkillConflictError, SkillConflictDetails, SkillCommandAnnotations, Scope, InstallStatus, InstallSkillBundleResult, InstallSkillBundleOptions, GenerateResult, GenerateOptions, CustomSkillConfig, AgentTarget, AgentResult, AgentClass };
|
|
130
|
+
agent: AgentTarget;
|
|
131
|
+
outputDir: string;
|
|
132
|
+
}
|
|
133
|
+
/** Refuses to overwrite an agent entry that is not owned by the requested skill. */
|
|
134
|
+
export declare class SkillConflictError extends Error {
|
|
135
|
+
override readonly name = "SkillConflictError";
|
|
136
|
+
readonly details: SkillConflictDetails;
|
|
137
|
+
constructor(details: SkillConflictDetails);
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/extension.d.ts
|
|
141
|
+
export declare const skill: ExtensionFactory<[options: SkillOptions], {}, [], [], readonly CommandDefinition<any, any, any, any>[]>;
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/generate.d.ts
|
|
144
|
+
/** Links one packaged skill source into the requested agent directories. */
|
|
145
|
+
export declare function installSkill(options: InstallSkillOptions): Promise<InstallSkillResult>;
|
|
146
|
+
/** Unlinks only agent-directory entries carrying the requested skill's ownership signature. */
|
|
147
|
+
export declare function uninstallSkill(options: UninstallSkillOptions): Promise<UninstallSkillResult>;
|
|
148
|
+
/** Reports the ownership and health of each requested agent-directory entry. */
|
|
149
|
+
export declare function getSkillStatus(options: SkillStatusOptions): Promise<SkillStatusResult>;
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/skill-name.d.ts
|
|
152
|
+
/**
|
|
153
|
+
* Validates a resolved skill name against the Agent Skills specification.
|
|
154
|
+
*
|
|
155
|
+
* @param name - The resolved skill name to validate
|
|
156
|
+
* @returns `true` if valid, `false` otherwise
|
|
157
|
+
*/
|
|
158
|
+
export declare function isValidSkillName(name: string): boolean;
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/source.d.ts
|
|
161
|
+
export declare class SkillSourceUnavailableError extends Error {
|
|
162
|
+
override readonly name = "SkillSourceUnavailableError";
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Resolves a logical packaged skill-source root. When the package path is
|
|
166
|
+
* unavailable, falls back to the executable directory: absolute and URL
|
|
167
|
+
* sources by their basename, relative sources by the same relative path.
|
|
168
|
+
*/
|
|
169
|
+
export declare function resolveSkillSource(source: string | URL): string;
|
|
170
|
+
interface PackagedSkill {
|
|
171
|
+
readonly sourceDir: string;
|
|
172
|
+
readonly name: string;
|
|
173
|
+
readonly description: string;
|
|
174
|
+
}
|
|
175
|
+
/** Reads every self-describing skill directory in a packaged skill source. */
|
|
176
|
+
export declare function loadPackagedSkills(source: string | URL): readonly PackagedSkill[];
|
|
177
|
+
//#endregion
|
|
178
|
+
export type { AgentClass, AgentResult, AgentTarget, InstallSkillOptions, InstallSkillResult, InstallStatus, PackagedSkill, Scope, SkillLinkStatus, SkillOptions, SkillStatusOptions, SkillStatusResult, UninstallSkillOptions, UninstallSkillResult, UninstallStatus, WriteSkillsOptions };
|