politty 0.9.0 → 0.9.1
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 +57 -0
- package/dist/arg-registry-BeLLAW5-.js +25 -0
- package/dist/cli.js +4 -3
- package/dist/command-B4yA4LXX.js +43 -0
- package/dist/completion/index.js +1 -1
- package/dist/{completion-DHnVx9Zk.js → completion-DwTFOtQk.js} +5 -44
- package/dist/docs/index.js +2 -2
- package/dist/index.js +6 -3
- package/dist/logger-DbDkjdfO.js +134 -0
- package/dist/{runner-APRZYXUS.js → runner-B-FZMN89.js} +5 -134
- package/dist/{schema-extractor-Dqe7_kyQ.js → schema-extractor-CVHWm23M.js} +3 -24
- package/dist/skill/index.d.ts +432 -0
- package/dist/skill/index.js +1563 -0
- package/package.json +8 -1
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import { _ as AnyCommand } from "../arg-registry-DDJpsUea.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/skill/frontmatter.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Zod schema for SKILL.md frontmatter.
|
|
7
|
+
*
|
|
8
|
+
* Strictly validates the fields defined in the Agent Skills specification
|
|
9
|
+
* (https://agentskills.io/specification). Unknown fields are preserved via
|
|
10
|
+
* `.passthrough()` so spec extensions and vendor keys round-trip intact.
|
|
11
|
+
*
|
|
12
|
+
* Provenance / ownership for politty-managed installs is recorded under
|
|
13
|
+
* `metadata["politty-cli"]` as `"{packageName}:{cliName}"`.
|
|
14
|
+
*/
|
|
15
|
+
declare const skillFrontmatterSchema: z.ZodObject<{
|
|
16
|
+
name: z.ZodString;
|
|
17
|
+
description: z.ZodString;
|
|
18
|
+
license: z.ZodOptional<z.ZodString>;
|
|
19
|
+
compatibility: z.ZodOptional<z.ZodString>;
|
|
20
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
21
|
+
"allowed-tools": z.ZodOptional<z.ZodString>;
|
|
22
|
+
}, z.core.$loose>;
|
|
23
|
+
/**
|
|
24
|
+
* Result of parsing a SKILL.md file.
|
|
25
|
+
*/
|
|
26
|
+
interface ParsedSkillMd {
|
|
27
|
+
/** Parsed and validated frontmatter */
|
|
28
|
+
frontmatter: z.infer<typeof skillFrontmatterSchema>;
|
|
29
|
+
/** Markdown body (content after frontmatter) */
|
|
30
|
+
body: string;
|
|
31
|
+
/** Full raw content */
|
|
32
|
+
rawContent: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parse YAML frontmatter from a SKILL.md string.
|
|
36
|
+
*
|
|
37
|
+
* `parseError` is set when the frontmatter fence was present but the YAML
|
|
38
|
+
* inside failed to parse, so the scanner can distinguish "invalid YAML"
|
|
39
|
+
* from "missing required field" in its diagnostics. A non-object root
|
|
40
|
+
* (e.g. a top-level YAML list) also returns empty `data` without
|
|
41
|
+
* `parseError` — Zod's schema validation surfaces that case clearly
|
|
42
|
+
* enough on its own.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const result = parseFrontmatter(`---
|
|
47
|
+
* name: commit
|
|
48
|
+
* description: Git commit message generation
|
|
49
|
+
* ---
|
|
50
|
+
* # Instructions...`);
|
|
51
|
+
*
|
|
52
|
+
* result.data.name; // "commit"
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
declare function parseFrontmatter(content: string): {
|
|
56
|
+
data: Record<string, unknown>;
|
|
57
|
+
body: string;
|
|
58
|
+
parseError?: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Parse and validate a SKILL.md content string.
|
|
62
|
+
*
|
|
63
|
+
* @returns Parsed skill metadata and body, or `null` if the frontmatter is
|
|
64
|
+
* missing or fails schema validation.
|
|
65
|
+
*/
|
|
66
|
+
declare function parseSkillMd(content: string): ParsedSkillMd | null;
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/skill/types.d.ts
|
|
69
|
+
/**
|
|
70
|
+
* SKILL.md frontmatter metadata, validated against the Agent Skills
|
|
71
|
+
* specification (https://agentskills.io/specification).
|
|
72
|
+
*
|
|
73
|
+
* Provenance for politty-managed installs is recorded under
|
|
74
|
+
* `metadata["politty-cli"]` as `"{packageName}:{cliName}"`.
|
|
75
|
+
*/
|
|
76
|
+
type SkillFrontmatter = z.infer<typeof skillFrontmatterSchema>;
|
|
77
|
+
/**
|
|
78
|
+
* A skill discovered from a source directory (npm package).
|
|
79
|
+
*/
|
|
80
|
+
interface DiscoveredSkill {
|
|
81
|
+
/** Parsed frontmatter metadata */
|
|
82
|
+
frontmatter: SkillFrontmatter;
|
|
83
|
+
/** Path to the directory containing SKILL.md */
|
|
84
|
+
sourcePath: string;
|
|
85
|
+
/** Raw SKILL.md content (frontmatter + body) */
|
|
86
|
+
rawContent: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* All kinds of scan failure, as a runtime tuple so callers can exhaustively
|
|
90
|
+
* iterate (e.g. for message tables). Derived {@link ScanErrorReason} stays
|
|
91
|
+
* the single source of truth for the type-level enum.
|
|
92
|
+
*/
|
|
93
|
+
declare const SCAN_ERROR_REASONS: readonly ["parse-failed", "name-mismatch", "read-failed", "missing-source"];
|
|
94
|
+
/** Kind of problem encountered by {@link scanSourceDir}. */
|
|
95
|
+
type ScanErrorReason = (typeof SCAN_ERROR_REASONS)[number];
|
|
96
|
+
/**
|
|
97
|
+
* A non-fatal problem encountered while scanning a source directory.
|
|
98
|
+
*
|
|
99
|
+
* Scan errors (invalid frontmatter, name/parent-dir mismatch, unreadable
|
|
100
|
+
* files) are collected rather than thrown so that a single malformed skill
|
|
101
|
+
* does not hide the rest from CLI commands.
|
|
102
|
+
*/
|
|
103
|
+
interface ScanError {
|
|
104
|
+
/** Directory that produced the error. */
|
|
105
|
+
path: string;
|
|
106
|
+
/** Kind of problem encountered. */
|
|
107
|
+
reason: ScanErrorReason;
|
|
108
|
+
/** Human-readable detail, suitable for logging. */
|
|
109
|
+
message: string;
|
|
110
|
+
/**
|
|
111
|
+
* Parsed frontmatter `name`, when the scan got far enough to read it.
|
|
112
|
+
* Currently populated only for `name-mismatch` — both the directory
|
|
113
|
+
* basename and this frontmatter name correspond to plausible existing
|
|
114
|
+
* install slot names (depending on which side the user just renamed),
|
|
115
|
+
* so `sync`'s orphan-retention guard needs both to avoid reaping an
|
|
116
|
+
* installed slot belonging to a source skill that failed this scan.
|
|
117
|
+
*/
|
|
118
|
+
skillName?: string;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Result of scanning a source directory for SKILL.md files.
|
|
122
|
+
*/
|
|
123
|
+
interface ScanResult {
|
|
124
|
+
/** Valid, spec-compliant skills. */
|
|
125
|
+
skills: DiscoveredSkill[];
|
|
126
|
+
/** Directories that looked like skills but failed validation. */
|
|
127
|
+
errors: ScanError[];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* How an install materializes skill files under `.agents/skills/<name>`
|
|
131
|
+
* and each `SYMLINK_TARGETS` entry.
|
|
132
|
+
*
|
|
133
|
+
* - `"symlink"` (default): symlink the source into place. Source updates
|
|
134
|
+
* propagate live. Throws with guidance to retry with `"copy"` when
|
|
135
|
+
* `symlinkSync` fails (e.g. Windows without Developer Mode, filesystems
|
|
136
|
+
* that do not support symlinks).
|
|
137
|
+
* - `"copy"`: recursive copy. Source updates require re-running `skills
|
|
138
|
+
* sync`. Works on any filesystem, trades liveness for portability.
|
|
139
|
+
*/
|
|
140
|
+
type InstallMode = "symlink" | "copy";
|
|
141
|
+
/** Options for {@link installSkill}. */
|
|
142
|
+
interface InstallSkillOptions {
|
|
143
|
+
/** Install materialization strategy. Default: `"symlink"`. */
|
|
144
|
+
mode?: InstallMode;
|
|
145
|
+
}
|
|
146
|
+
/** Options for {@link uninstallSkill}. */
|
|
147
|
+
interface UninstallSkillOptions {
|
|
148
|
+
/**
|
|
149
|
+
* If set, `uninstallSkill` also removes a real directory at the install
|
|
150
|
+
* path when its SKILL.md's `metadata["politty-cli"]` matches this stamp
|
|
151
|
+
* (a copy-mode install this CLI owns). Without this option, only
|
|
152
|
+
* symlinks are removed — real directories are assumed to be legacy or
|
|
153
|
+
* manual installs and left untouched.
|
|
154
|
+
*/
|
|
155
|
+
expectedOwnership?: string;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Per-flag overrides for the built-in skill subcommand options.
|
|
159
|
+
*
|
|
160
|
+
* Pass through {@link SkillCommandOptions.flags} to resolve collisions with
|
|
161
|
+
* CLI-level global flags. Setting `alias` to `false` disables the short
|
|
162
|
+
* alias entirely; passing a string renames it.
|
|
163
|
+
*/
|
|
164
|
+
interface SkillFlagOverrides {
|
|
165
|
+
/**
|
|
166
|
+
* `--exclude` flag on `skills sync`. The default short alias is `-x`.
|
|
167
|
+
*/
|
|
168
|
+
exclude?: {
|
|
169
|
+
alias?: string | false;
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Options for `withSkillCommand`.
|
|
174
|
+
*/
|
|
175
|
+
interface SkillCommandOptions {
|
|
176
|
+
/**
|
|
177
|
+
* Source directory containing SKILL.md files.
|
|
178
|
+
*
|
|
179
|
+
* Each subdirectory whose name matches its `SKILL.md` frontmatter `name`
|
|
180
|
+
* is treated as a skill. Symlinks within the source tree are followed.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* // Resolves to ../skills relative to the current file.
|
|
185
|
+
* // Works from both src/ and dist/ if at the same depth.
|
|
186
|
+
* const sourceDir = resolve(dirname(fileURLToPath(import.meta.url)), "../skills");
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
sourceDir: string;
|
|
190
|
+
/**
|
|
191
|
+
* npm package name that owns this CLI's bundled skills.
|
|
192
|
+
*
|
|
193
|
+
* Each source `SKILL.md` must pre-declare
|
|
194
|
+
* `metadata["politty-cli"]: "{package}:{cliName}"`. The `skills add` and
|
|
195
|
+
* `skills sync` subcommands verify this stamp before installing — two
|
|
196
|
+
* tools managing skills in the same project cannot accidentally clobber
|
|
197
|
+
* each other. `installSkill` itself does not compare ownership;
|
|
198
|
+
* programmatic callers that bypass `withSkillCommand` are responsible
|
|
199
|
+
* for matching the stamp against their own `{package}:{cliName}` up
|
|
200
|
+
* front. (In `mode: "copy"`, `installSkill` additionally requires
|
|
201
|
+
* *some* `politty-cli` stamp on the source and throws otherwise — the
|
|
202
|
+
* caller-side ownership check naturally satisfies that precondition.)
|
|
203
|
+
*/
|
|
204
|
+
package: string;
|
|
205
|
+
/**
|
|
206
|
+
* Default install mode for the `skills add` and `skills sync` commands.
|
|
207
|
+
* Defaults to `"symlink"` — install fails with a clear error on
|
|
208
|
+
* filesystems without symlink support (e.g. Windows without Developer
|
|
209
|
+
* Mode). Set to `"copy"` to always copy. See {@link InstallMode}.
|
|
210
|
+
*/
|
|
211
|
+
mode?: InstallMode;
|
|
212
|
+
/**
|
|
213
|
+
* Project root directory used by every `skills` subcommand for resolving
|
|
214
|
+
* `.agents/skills/...` install paths.
|
|
215
|
+
*
|
|
216
|
+
* Default: walk up from `process.cwd()` and use the first ancestor that
|
|
217
|
+
* contains `.git/` or `package.json`; fall back to `process.cwd()` when
|
|
218
|
+
* neither is found. This avoids creating `<sub>/.agents/skills/...` when
|
|
219
|
+
* the CLI is invoked from a subdirectory of the project.
|
|
220
|
+
*
|
|
221
|
+
* Pass an explicit absolute (or cwd-relative) path to override — for
|
|
222
|
+
* example, the directory of a CLI-specific config file.
|
|
223
|
+
*/
|
|
224
|
+
cwd?: string;
|
|
225
|
+
/**
|
|
226
|
+
* Customize built-in subcommand flags. Use to resolve collisions with
|
|
227
|
+
* the CLI's global flags or to opt out of short aliases.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```ts
|
|
231
|
+
* // CLI already uses -x globally; rename the exclude alias.
|
|
232
|
+
* withSkillCommand(cmd, {
|
|
233
|
+
* sourceDir, package: "@my-agent/skills",
|
|
234
|
+
* flags: { exclude: { alias: "X" } },
|
|
235
|
+
* });
|
|
236
|
+
*
|
|
237
|
+
* // Disable the short alias entirely.
|
|
238
|
+
* withSkillCommand(cmd, {
|
|
239
|
+
* sourceDir, package: "@my-agent/skills",
|
|
240
|
+
* flags: { exclude: { alias: false } },
|
|
241
|
+
* });
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
flags?: SkillFlagOverrides;
|
|
245
|
+
/**
|
|
246
|
+
* Append a one-line skills usage hint to the wrapped command's
|
|
247
|
+
* `description` so `--help` advertises the skills subcommand.
|
|
248
|
+
*
|
|
249
|
+
* - `undefined` (default) — append a default hint mentioning the
|
|
250
|
+
* available subcommands.
|
|
251
|
+
* - `string` — append this exact string instead.
|
|
252
|
+
* - `false` — leave the description untouched.
|
|
253
|
+
*/
|
|
254
|
+
descriptionAppend?: string | false;
|
|
255
|
+
}
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/skill/installer.d.ts
|
|
258
|
+
/**
|
|
259
|
+
* Key used to read provenance off an installed skill. The SKILL.md's
|
|
260
|
+
* `metadata["politty-cli"]` must equal `"{packageName}:{cliName}"` for the
|
|
261
|
+
* owning CLI to manage it. This stamp is authored by the skill package,
|
|
262
|
+
* not rewritten at install time.
|
|
263
|
+
*/
|
|
264
|
+
declare const OWNERSHIP_METADATA_KEY = "politty-cli";
|
|
265
|
+
/**
|
|
266
|
+
* Install a skill to the project's agent skill directories.
|
|
267
|
+
*
|
|
268
|
+
* Canonical `.agents/skills/<name>` and each `SYMLINK_TARGETS` entry are
|
|
269
|
+
* populated according to `options.mode`:
|
|
270
|
+
*
|
|
271
|
+
* - `"symlink"` (default): symlink to the source (or to the canonical dir
|
|
272
|
+
* for the agent-specific slots). Source updates propagate live. Throws
|
|
273
|
+
* with guidance to retry with `"copy"` on filesystems without symlink
|
|
274
|
+
* support (e.g. Windows without Developer Mode).
|
|
275
|
+
* - `"copy"`: recursive copy. Works anywhere, but source updates require
|
|
276
|
+
* re-running install.
|
|
277
|
+
*
|
|
278
|
+
* **Symlink target convention.** Symlinks are written with relative
|
|
279
|
+
* targets so an install survives when the project tree is copied or
|
|
280
|
+
* mounted at a different absolute path. The two endpoints are resolved
|
|
281
|
+
* asymmetrically:
|
|
282
|
+
*
|
|
283
|
+
* - The install root (`.agents/skills/`, each `SYMLINK_TARGETS` parent)
|
|
284
|
+
* is passed through `realpathSync` so a symlinked checkout doesn't
|
|
285
|
+
* bake a stale parent path into the relative target.
|
|
286
|
+
* - The source path is resolved by {@link resolveSourcePreservingPackageHop},
|
|
287
|
+
* which walks root→leaf dereferencing every ancestor symlink (a symlinked
|
|
288
|
+
* checkout, macOS `/tmp` → `/private/tmp`, etc.) like `realpathSync` would
|
|
289
|
+
* — EXCEPT a `node_modules/<pkg>` (or `node_modules/@scope/<pkg>`)
|
|
290
|
+
* symlink, which is preserved. Following the package-manager hop would
|
|
291
|
+
* bake pnpm's volatile `node_modules/.pnpm/<pkg>@<version>_<hash>/...`
|
|
292
|
+
* into the link target and a subsequent `pnpm update` would leave every
|
|
293
|
+
* install dangling. Keeping the hop preserves the stable
|
|
294
|
+
* `node_modules/<pkg>` symlink that pnpm keeps repointing, while the
|
|
295
|
+
* project-root portion still matches the install root's realpath style
|
|
296
|
+
* so the install survives copying or remounting the project tree.
|
|
297
|
+
*
|
|
298
|
+
* The overlap guard and copy-mode payload still use the *fully*
|
|
299
|
+
* `realpathSync`-resolved source: the guard must catch a source-side
|
|
300
|
+
* symlink whose target is nested inside the install root, and the
|
|
301
|
+
* copy-mode payload reads through every symlink so a copy install doesn't
|
|
302
|
+
* leave dangling references back into `node_modules`.
|
|
303
|
+
*
|
|
304
|
+
* No absolute-path symlinks are produced by this function.
|
|
305
|
+
*
|
|
306
|
+
* **Atomicity.** This call is *not* transactional across multi-step
|
|
307
|
+
* installs. The canonical slot is cleared then written, and each
|
|
308
|
+
* `SYMLINK_TARGETS` slot is then cleared and written one at a time. A
|
|
309
|
+
* crash mid-install can leave the canonical slot updated and one or
|
|
310
|
+
* more agent-specific slots stale; re-running `installSkill` (or the
|
|
311
|
+
* `skills sync` subcommand, which iterates over multiple skills) is
|
|
312
|
+
* idempotent and converges back to the intended state. Within a single
|
|
313
|
+
* slot's copy-mode write, the staging-and-rename in {@link atomicCopyDir}
|
|
314
|
+
* guarantees the destination is either absent or fully populated — a
|
|
315
|
+
* mid-copy failure never leaves a stamp-less partial directory that the
|
|
316
|
+
* next install's `clearInstallSlot` would refuse to replace. Multi-skill
|
|
317
|
+
* orchestration in {@link createSkillSyncCommand} is fail-fast — the
|
|
318
|
+
* first failed skill aborts the loop without rolling back already-
|
|
319
|
+
* installed siblings, again because re-running converges.
|
|
320
|
+
*
|
|
321
|
+
* The ownership stamp (`metadata["politty-cli"]`) is authored by the skill
|
|
322
|
+
* package; the installer does not modify SKILL.md.
|
|
323
|
+
*/
|
|
324
|
+
declare function installSkill(skill: DiscoveredSkill, cwd?: string, options?: InstallSkillOptions): void;
|
|
325
|
+
/**
|
|
326
|
+
* Uninstall a skill from the project's agent skill directories.
|
|
327
|
+
*
|
|
328
|
+
* Each slot is unlinked only when its ownership can be proven:
|
|
329
|
+
* - Agent-specific symlink slots (`.claude/skills/<name>` etc.) — a live
|
|
330
|
+
* symlink is unlinked only when it routes to our canonical slot, so a
|
|
331
|
+
* foreign tool's symlink at the same shared path is left untouched.
|
|
332
|
+
* - The canonical slot (`.agents/skills/<name>`) — a live symlink is
|
|
333
|
+
* unlinked only when its routed-to SKILL.md carries
|
|
334
|
+
* `options.expectedOwnership`, so another politty-based CLI's live
|
|
335
|
+
* install in the same shared namespace is left untouched.
|
|
336
|
+
* - Real directories at any slot are removed only when the directory's
|
|
337
|
+
* SKILL.md carries `options.expectedOwnership`. Unstamped or foreign
|
|
338
|
+
* real directories are left alone so legacy/manual installs are not
|
|
339
|
+
* silently recursively deleted.
|
|
340
|
+
*
|
|
341
|
+
* `skills remove` / `skills sync` always pass `expectedOwnership`. Direct
|
|
342
|
+
* programmatic callers that omit it get the legacy permissive behaviour
|
|
343
|
+
* on symlinks (unconditional unlink) but the conservative behaviour on
|
|
344
|
+
* real directories (no-op). Broken (dangling) canonical symlinks are
|
|
345
|
+
* outside this function's purview — they have no SKILL.md to read, so
|
|
346
|
+
* `cleanupBrokenSlot` handles them with a routing check instead.
|
|
347
|
+
*/
|
|
348
|
+
declare function uninstallSkill(name: string, cwd?: string, options?: UninstallSkillOptions): void;
|
|
349
|
+
/**
|
|
350
|
+
* Report whether a skill is currently installed, independent of its
|
|
351
|
+
* ownership stamp. Returns `true` when `.agents/skills/<name>/SKILL.md`
|
|
352
|
+
* resolves to a readable file (through a valid symlink or directly, or
|
|
353
|
+
* via a copy-mode install); returns `false` when the path is absent or
|
|
354
|
+
* the canonical symlink is broken (source package uninstalled).
|
|
355
|
+
*
|
|
356
|
+
* Callers use this to distinguish the two cases where
|
|
357
|
+
* {@link readInstalledOwnership} returns `null` — "not installed" (safe
|
|
358
|
+
* to install fresh) vs. "installed but unstamped" (legacy or manual
|
|
359
|
+
* install that should not be silently clobbered).
|
|
360
|
+
*/
|
|
361
|
+
declare function hasInstalledSkill(name: string, cwd?: string): boolean;
|
|
362
|
+
/**
|
|
363
|
+
* Read the ownership stamp off an installed skill's SKILL.md, if any.
|
|
364
|
+
*
|
|
365
|
+
* For symlink-mode installs `.agents/skills/<name>` points at the source,
|
|
366
|
+
* so this reads the package-authored stamp. For copy-mode installs the
|
|
367
|
+
* stamp was captured at install time into the local copy.
|
|
368
|
+
*
|
|
369
|
+
* @returns `metadata["politty-cli"]` as `"{packageName}:{cliName}"`, or
|
|
370
|
+
* `null` if the skill is not installed *or* the stamp is absent/malformed.
|
|
371
|
+
* Use {@link hasInstalledSkill} to distinguish the two cases.
|
|
372
|
+
*/
|
|
373
|
+
declare function readInstalledOwnership(name: string, cwd?: string): string | null;
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region src/skill/scanner.d.ts
|
|
376
|
+
/**
|
|
377
|
+
* Scan a source directory for SKILL.md files.
|
|
378
|
+
*
|
|
379
|
+
* Each immediate subdirectory is a candidate skill; its `SKILL.md` is
|
|
380
|
+
* parsed and validated against the Agent Skills specification, and the
|
|
381
|
+
* frontmatter `name` must match the subdirectory name (spec requirement).
|
|
382
|
+
*
|
|
383
|
+
* If `sourceDir` itself contains a `SKILL.md`, it is treated as a
|
|
384
|
+
* single-skill source. The parent-directory-name match is not enforced in
|
|
385
|
+
* that case because the caller chose an arbitrary path.
|
|
386
|
+
*
|
|
387
|
+
* Symlinks within the source tree are followed (symlinked skill dirs and
|
|
388
|
+
* symlinked SKILL.md files are both accepted). npm packages already
|
|
389
|
+
* execute arbitrary JS on install, so additional symlink-based isolation
|
|
390
|
+
* here would not raise the trust boundary in any realistic threat model.
|
|
391
|
+
*
|
|
392
|
+
* @example
|
|
393
|
+
* ```
|
|
394
|
+
* sourceDir: "node_modules/@my-agent/skills/skills"
|
|
395
|
+
*
|
|
396
|
+
* node_modules/@my-agent/skills/skills/
|
|
397
|
+
* ├── commit/
|
|
398
|
+
* │ └── SKILL.md
|
|
399
|
+
* └── review-pr/
|
|
400
|
+
* └── SKILL.md
|
|
401
|
+
* ```
|
|
402
|
+
*/
|
|
403
|
+
declare function scanSourceDir(sourceDir: string): ScanResult;
|
|
404
|
+
//#endregion
|
|
405
|
+
//#region src/skill/index.d.ts
|
|
406
|
+
/**
|
|
407
|
+
* Wrap a command with a `skills` subcommand for managing SKILL.md-based skills.
|
|
408
|
+
*
|
|
409
|
+
* Adds `skills sync`, `skills add`, `skills remove`, and `skills list`.
|
|
410
|
+
* The install materialization is controlled by `options.mode`
|
|
411
|
+
* (see {@link SkillCommandOptions}):
|
|
412
|
+
*
|
|
413
|
+
* - `"symlink"` (default) — symlink the source into place. Source updates
|
|
414
|
+
* propagate live. Install errors out with guidance to retry with `"copy"`
|
|
415
|
+
* when `symlinkSync` fails (e.g. Windows without Developer Mode).
|
|
416
|
+
* - `"copy"` — recursive copy. Source updates require re-running sync.
|
|
417
|
+
*
|
|
418
|
+
* Under both modes the canonical slot is `.agents/skills/<name>` and each
|
|
419
|
+
* agent-specific directory (e.g. `.claude/skills/<name>`) is populated
|
|
420
|
+
* from that canonical slot. politty never writes to `SKILL.md`. The
|
|
421
|
+
* ownership stamp `metadata["politty-cli"] = "{package}:{cliName}"` must
|
|
422
|
+
* be authored by the skill package itself; `add` and `sync` verify it
|
|
423
|
+
* before installing and `remove` / `sync` consult it before deleting, so
|
|
424
|
+
* this CLI never clobbers skills another tool installed.
|
|
425
|
+
*
|
|
426
|
+
* @throws if `command.subCommands.skills` already exists — silently
|
|
427
|
+
* overwriting it would hide a configuration bug.
|
|
428
|
+
*/
|
|
429
|
+
declare function withSkillCommand<T extends AnyCommand>(command: T, options: SkillCommandOptions): T;
|
|
430
|
+
//#endregion
|
|
431
|
+
export { type DiscoveredSkill, type InstallMode, type InstallSkillOptions, OWNERSHIP_METADATA_KEY, type ParsedSkillMd, SCAN_ERROR_REASONS, type ScanError, type ScanErrorReason, type ScanResult, type SkillCommandOptions, type SkillFlagOverrides, type SkillFrontmatter, type UninstallSkillOptions, hasInstalledSkill, installSkill, parseFrontmatter, parseSkillMd, readInstalledOwnership, scanSourceDir, skillFrontmatterSchema, uninstallSkill, withSkillCommand };
|
|
432
|
+
//# sourceMappingURL=index.d.ts.map
|