@g3nomaly/skills 0.3.0 → 1.0.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.
Files changed (87) hide show
  1. package/LICENSE +95 -0
  2. package/dist/cli/adapter.d.ts +33 -0
  3. package/dist/cli/adapter.d.ts.map +1 -0
  4. package/dist/cli/adapter.js +62 -0
  5. package/dist/cli/adapter.js.map +1 -0
  6. package/dist/cli/commands/add.d.ts +14 -0
  7. package/dist/cli/commands/add.d.ts.map +1 -0
  8. package/dist/cli/commands/add.js +22 -0
  9. package/dist/cli/commands/add.js.map +1 -0
  10. package/dist/cli/commands/init.d.ts +22 -0
  11. package/dist/cli/commands/init.d.ts.map +1 -0
  12. package/dist/cli/commands/init.js +119 -0
  13. package/dist/cli/commands/init.js.map +1 -0
  14. package/dist/cli/commands/ls.d.ts +11 -0
  15. package/dist/cli/commands/ls.d.ts.map +1 -0
  16. package/dist/cli/commands/ls.js +24 -0
  17. package/dist/cli/commands/ls.js.map +1 -0
  18. package/dist/cli/commands/remove.d.ts +12 -0
  19. package/dist/cli/commands/remove.d.ts.map +1 -0
  20. package/dist/cli/commands/remove.js +15 -0
  21. package/dist/cli/commands/remove.js.map +1 -0
  22. package/dist/cli/commands/source.d.ts +29 -0
  23. package/dist/cli/commands/source.d.ts.map +1 -0
  24. package/dist/cli/commands/source.js +31 -0
  25. package/dist/cli/commands/source.js.map +1 -0
  26. package/dist/cli/commands/update.d.ts +13 -0
  27. package/dist/cli/commands/update.d.ts.map +1 -0
  28. package/dist/cli/commands/update.js +15 -0
  29. package/dist/cli/commands/update.js.map +1 -0
  30. package/dist/cli/index.d.ts +3 -0
  31. package/dist/cli/index.d.ts.map +1 -0
  32. package/dist/cli/index.js +93 -0
  33. package/dist/cli/index.js.map +1 -0
  34. package/dist/index.d.ts +4 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +5 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/packages/index.d.ts +3 -0
  39. package/dist/packages/index.d.ts.map +1 -0
  40. package/dist/packages/index.js +3 -0
  41. package/dist/packages/index.js.map +1 -0
  42. package/dist/packages/install.d.ts +24 -0
  43. package/dist/packages/install.d.ts.map +1 -0
  44. package/dist/packages/install.js +47 -0
  45. package/dist/packages/install.js.map +1 -0
  46. package/dist/registry/index.d.ts +7 -0
  47. package/dist/registry/index.d.ts.map +1 -0
  48. package/dist/registry/index.js +7 -0
  49. package/dist/registry/index.js.map +1 -0
  50. package/dist/registry/locate.d.ts +22 -0
  51. package/dist/registry/locate.d.ts.map +1 -0
  52. package/dist/registry/locate.js +81 -0
  53. package/dist/registry/locate.js.map +1 -0
  54. package/dist/registry/manifest.d.ts +9 -0
  55. package/dist/registry/manifest.d.ts.map +1 -0
  56. package/dist/registry/manifest.js +14 -0
  57. package/dist/registry/manifest.js.map +1 -0
  58. package/dist/registry/readSkillDir.d.ts +14 -0
  59. package/dist/registry/readSkillDir.d.ts.map +1 -0
  60. package/dist/registry/readSkillDir.js +54 -0
  61. package/dist/registry/readSkillDir.js.map +1 -0
  62. package/dist/registry/readSource.d.ts +9 -0
  63. package/dist/registry/readSource.d.ts.map +1 -0
  64. package/dist/registry/readSource.js +30 -0
  65. package/dist/registry/readSource.js.map +1 -0
  66. package/dist/registry/types.d.ts +53 -0
  67. package/dist/registry/types.d.ts.map +1 -0
  68. package/dist/registry/types.js +25 -0
  69. package/dist/registry/types.js.map +1 -0
  70. package/dist/sources/builtins.d.ts +4 -0
  71. package/dist/sources/builtins.d.ts.map +1 -0
  72. package/dist/sources/builtins.js +5 -0
  73. package/dist/sources/builtins.js.map +1 -0
  74. package/dist/sources/index.d.ts +2 -0
  75. package/dist/sources/index.d.ts.map +1 -0
  76. package/dist/sources/index.js +3 -0
  77. package/dist/sources/index.js.map +1 -0
  78. package/dist/utils/frontmatter.d.ts +7 -0
  79. package/dist/utils/frontmatter.d.ts.map +1 -0
  80. package/dist/utils/frontmatter.js +20 -0
  81. package/dist/utils/frontmatter.js.map +1 -0
  82. package/dist/utils/index.d.ts +2 -0
  83. package/dist/utils/index.d.ts.map +1 -0
  84. package/dist/utils/index.js +3 -0
  85. package/dist/utils/index.js.map +1 -0
  86. package/package.json +38 -3
  87. package/README.md +0 -3
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env bun
2
+ // packages/skills/src/cli/index.ts
3
+ import { Command } from "commander";
4
+ import { readPackageMeta, warnIfOutdated } from "@g3nomaly/core/utils";
5
+ import { SkillTargetSchema } from "@g3nomaly/core/config";
6
+ import { initCommand } from "./commands/init";
7
+ import { addCommand } from "./commands/add";
8
+ import { removeCommand } from "./commands/remove";
9
+ import { updateCommand } from "./commands/update";
10
+ import { lsCommand } from "./commands/ls";
11
+ import { sourceAddCommand, sourceLsCommand, sourceRemoveCommand } from "./commands/source";
12
+ /** The `-t` value as a one-target list, or `undefined` for every configured target. */
13
+ function parseTargets(value) {
14
+ return value === undefined ? undefined : [SkillTargetSchema.parse(value)];
15
+ }
16
+ const program = new Command()
17
+ .name("g3n-skills")
18
+ .description("Install skills, with their hooks, from any registered source into a project's agent directories");
19
+ program
20
+ .command("init")
21
+ .description("Configure which harnesses skills are installed for")
22
+ .option("-f, --force", "Reconfigure without prompting")
23
+ .option("--targets <list>", "Comma-separated targets (claude,codex); skips the prompt")
24
+ .action(async (opts) => {
25
+ const targets = opts.targets?.split(",").map((t) => SkillTargetSchema.parse(t.trim()));
26
+ await initCommand({ force: opts.force, targets });
27
+ });
28
+ const source = program
29
+ .command("source")
30
+ .description("Register, list and unregister the sources skills are installed from");
31
+ source
32
+ .command("add <source>")
33
+ .description("Register a git repository (URL or owner/repo), npm package (npm:<pkg> or @scope/pkg) or local folder")
34
+ .option("--name <name>", "Name to register it under (default: derived from the source)")
35
+ .option("--ref <ref>", "Branch or tag to pin a git source to (default: its default branch)")
36
+ .option("-t, --target <target>", "Only this target (claude|codex)")
37
+ .action(async (input, opts) => {
38
+ await sourceAddCommand(input, { name: opts.name, ref: opts.ref, targets: parseTargets(opts.target) });
39
+ });
40
+ source
41
+ .command("ls")
42
+ .description("List the registered sources, built-in ones first")
43
+ .option("--json", "Output as JSON")
44
+ .option("-t, --target <target>", "Only this target (claude|codex)")
45
+ .action(async (opts) => {
46
+ await sourceLsCommand({ json: opts.json, targets: parseTargets(opts.target) });
47
+ });
48
+ source
49
+ .command("remove <name>")
50
+ .description("Unregister a source; built-in sources cannot be removed")
51
+ .option("-f, --force", "Unregister even when installed skills came from it")
52
+ .option("-t, --target <target>", "Only this target (claude|codex)")
53
+ .action(async (name, opts) => {
54
+ await sourceRemoveCommand(name, { force: opts.force, targets: parseTargets(opts.target) });
55
+ });
56
+ program
57
+ .command("add [skills...]")
58
+ .description("Install skills or whole groups with their dependencies; name one source with <skill>@<source>")
59
+ .option("-f, --force", "Overwrite locally modified files")
60
+ .option("-t, --target <target>", "Only this target (claude|codex)")
61
+ .action(async (skills, opts) => {
62
+ await addCommand(skills, { force: opts.force, targets: parseTargets(opts.target) });
63
+ });
64
+ program
65
+ .command("remove [skills...]")
66
+ .description("Remove installed skills")
67
+ .option("-f, --force", "Remove even if files have been modified")
68
+ .option("-t, --target <target>", "Only this target (claude|codex)")
69
+ .action(async (skills, opts) => {
70
+ await removeCommand(skills, { force: opts.force, targets: parseTargets(opts.target) });
71
+ });
72
+ program
73
+ .command("update [skills...]")
74
+ .description("Re-install installed skills from the source each came from")
75
+ .option("-f, --force", "Overwrite locally modified files without prompting")
76
+ .option("--dry-run", "Report what would change without writing")
77
+ .option("-t, --target <target>", "Only this target (claude|codex)")
78
+ .action(async (skills, opts) => {
79
+ await updateCommand(skills, { force: opts.force, dryRun: opts.dryRun, targets: parseTargets(opts.target) });
80
+ });
81
+ program
82
+ .command("ls")
83
+ .description("List the skills the registered sources offer")
84
+ .option("--json", "Output as JSON")
85
+ .option("--source <name>", "Only this source")
86
+ .option("--installed", "List what skills.json records instead of what the sources offer")
87
+ .action(async (opts) => {
88
+ await lsCommand({ json: opts.json, source: opts.source, installed: opts.installed });
89
+ });
90
+ const self = readPackageMeta(import.meta.url);
91
+ await warnIfOutdated(self.name, self.version, import.meta.url);
92
+ program.parseAsync();
93
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from "./registry";
2
+ export * from "./sources";
3
+ export * from "./packages";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ // packages/skills/src/index.ts
2
+ export * from "./registry";
3
+ export * from "./sources";
4
+ export * from "./packages";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { installSkillPackages, removeSkillPackages } from "./install";
2
+ export type { PackageInstall } from "./install";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/packages/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACtE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,3 @@
1
+ // packages/skills/src/packages/index.ts
2
+ export { installSkillPackages, removeSkillPackages } from "./install";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/packages/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,24 @@
1
+ /** Outcome of installing one skill's packages. */
2
+ export interface PackageInstall {
3
+ key: string;
4
+ /** Message from `bun install` when it failed, `undefined` when it succeeded */
5
+ error?: string;
6
+ }
7
+ /**
8
+ * Runs `bun install` in each installed skill folder that ships a
9
+ * `package.json`, with `--frozen-lockfile` when it ships a `bun.lock` too.
10
+ * The packages land in the skill's own `node_modules`.
11
+ *
12
+ * @param installDir - Absolute install directory, e.g. `/home/me/app/.claude/skills`
13
+ * @returns one entry per skill that has a `package.json`; skills without one are left out
14
+ */
15
+ export declare function installSkillPackages(installDir: string, keys: readonly string[]): Promise<PackageInstall[]>;
16
+ /**
17
+ * Deletes the `node_modules` of skills that are no longer installed, then the
18
+ * skill folder when nothing else is left in it.
19
+ *
20
+ * @param installDir - Absolute install directory, e.g. `/home/me/app/.claude/skills`
21
+ * @param keys - Skills whose files were removed
22
+ */
23
+ export declare function removeSkillPackages(installDir: string, keys: readonly string[]): void;
24
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/packages/install.ts"],"names":[],"mappings":"AAQA,kDAAkD;AAClD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAK,MAAM,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAgBjH;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAMrF"}
@@ -0,0 +1,47 @@
1
+ // packages/skills/src/packages/install.ts
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ const PACKAGE_FILE = "package.json";
5
+ const LOCK_FILE = "bun.lock";
6
+ const MODULES_DIR = "node_modules";
7
+ /**
8
+ * Runs `bun install` in each installed skill folder that ships a
9
+ * `package.json`, with `--frozen-lockfile` when it ships a `bun.lock` too.
10
+ * The packages land in the skill's own `node_modules`.
11
+ *
12
+ * @param installDir - Absolute install directory, e.g. `/home/me/app/.claude/skills`
13
+ * @returns one entry per skill that has a `package.json`; skills without one are left out
14
+ */
15
+ export async function installSkillPackages(installDir, keys) {
16
+ const results = [];
17
+ for (const key of keys) {
18
+ const skillDir = path.join(installDir, key);
19
+ if (!fs.existsSync(path.join(skillDir, PACKAGE_FILE)))
20
+ continue;
21
+ const frozen = fs.existsSync(path.join(skillDir, LOCK_FILE)) ? ["--frozen-lockfile"] : [];
22
+ const proc = Bun.spawn([process.execPath, "install", "--silent", ...frozen], {
23
+ cwd: skillDir,
24
+ stdout: "ignore",
25
+ stderr: "pipe",
26
+ });
27
+ const [stderr, exitCode] = await Promise.all([new Response(proc.stderr).text(), proc.exited]);
28
+ results.push(exitCode === 0 ? { key } : { key, error: stderr.trim() || `bun install exited with ${exitCode}` });
29
+ }
30
+ return results;
31
+ }
32
+ /**
33
+ * Deletes the `node_modules` of skills that are no longer installed, then the
34
+ * skill folder when nothing else is left in it.
35
+ *
36
+ * @param installDir - Absolute install directory, e.g. `/home/me/app/.claude/skills`
37
+ * @param keys - Skills whose files were removed
38
+ */
39
+ export function removeSkillPackages(installDir, keys) {
40
+ for (const key of keys) {
41
+ const skillDir = path.join(installDir, key);
42
+ fs.rmSync(path.join(skillDir, MODULES_DIR), { recursive: true, force: true });
43
+ if (fs.existsSync(skillDir) && fs.readdirSync(skillDir).length === 0)
44
+ fs.rmdirSync(skillDir);
45
+ }
46
+ }
47
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/packages/install.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,YAAY,GAAG,cAAc,CAAC;AACpC,MAAM,SAAS,GAAM,UAAU,CAAC;AAChC,MAAM,WAAW,GAAI,cAAc,CAAC;AASpC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,UAAkB,EAAE,IAAuB;IACpF,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAC5C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAAE,SAAS;QAEhE,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,EAAE;YAC3E,GAAG,EAAK,QAAQ;YAChB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9F,OAAO,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,2BAA2B,QAAQ,EAAE,EAAE,CAAC,CAAC;IAClH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB,EAAE,IAAuB;IAC7E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAC5C,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9E,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ export * from "./types";
2
+ export { readSkillDir, SKILL_FILE } from "./readSkillDir";
3
+ export { locateSkills } from "./locate";
4
+ export type { SkillPlugin, SkillScan } from "./locate";
5
+ export { readSkillSource } from "./readSource";
6
+ export { skillsManifestPath } from "./manifest";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ // packages/skills/src/registry/index.ts
2
+ export * from "./types";
3
+ export { readSkillDir, SKILL_FILE } from "./readSkillDir";
4
+ export { locateSkills } from "./locate";
5
+ export { readSkillSource } from "./readSource";
6
+ export { skillsManifestPath } from "./manifest";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** One plugin of a source with the skill folders it holds. */
2
+ export interface SkillPlugin {
3
+ name: string;
4
+ version?: string;
5
+ /** Absolute skill folders, each holding a SKILL.md */
6
+ skillDirs: string[];
7
+ }
8
+ /** The plugins found in one source, with what was skipped and why. */
9
+ export interface SkillScan {
10
+ plugins: SkillPlugin[];
11
+ warnings: string[];
12
+ }
13
+ /**
14
+ * Finds the skills a source provides. A `marketplace.json` lists plugin
15
+ * folders; a root `plugin.json` makes the source itself a plugin. Both
16
+ * `.claude-plugin` and `.cursor-plugin` layouts are read.
17
+ *
18
+ * @param sourceRoot - Absolute root of the source checkout
19
+ * @throws when the source has neither manifest; plain skill folders are rejected
20
+ */
21
+ export declare function locateSkills(sourceRoot: string): SkillScan;
22
+ //# sourceMappingURL=locate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../src/registry/locate.ts"],"names":[],"mappings":"AAmBA,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAO,MAAM,CAAC;IAClB,OAAO,CAAC,EAAG,MAAM,CAAC;IAClB,sDAAsD;IACtD,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACxB,OAAO,EAAG,WAAW,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA8BD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CA+B1D"}
@@ -0,0 +1,81 @@
1
+ // packages/skills/src/registry/locate.ts
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { z } from "zod";
5
+ import { manifestFile, readMarketplace, resolveInside } from "@g3nomaly/core/installer";
6
+ import { SKILL_FILE } from "./readSkillDir";
7
+ const PLUGIN_FILE = "plugin.json";
8
+ const DEFAULT_SKILLS_DIR = "skills";
9
+ const PluginManifestSchema = z.object({
10
+ name: z.string().min(1).optional(),
11
+ version: z.string().optional(),
12
+ /** A list of skill folders, or one folder to scan for them */
13
+ skills: z.union([z.string().min(1), z.array(z.string().min(1))]).optional(),
14
+ });
15
+ /** Folders under `dir` holding a SKILL.md; a match is not descended into further. */
16
+ function scanSkillDirs(dir) {
17
+ if (!fs.existsSync(dir))
18
+ return [];
19
+ const found = [];
20
+ const visit = (current) => {
21
+ if (fs.existsSync(path.join(current, SKILL_FILE))) {
22
+ found.push(current);
23
+ return;
24
+ }
25
+ for (const d of fs.readdirSync(current, { withFileTypes: true })) {
26
+ if (d.isDirectory() && !d.name.startsWith(".") && d.name !== "node_modules")
27
+ visit(path.join(current, d.name));
28
+ }
29
+ };
30
+ visit(dir);
31
+ return found.sort();
32
+ }
33
+ /** A plugin's skill folders: the listed ones, or a scan of its skills folder. */
34
+ function pluginSkillDirs(pluginDir, sourceRoot, manifest) {
35
+ if (Array.isArray(manifest.skills)) {
36
+ return manifest.skills.map((rel) => resolveInside(sourceRoot, pluginDir, rel));
37
+ }
38
+ if (typeof manifest.skills === "string") {
39
+ return scanSkillDirs(resolveInside(sourceRoot, pluginDir, manifest.skills));
40
+ }
41
+ return scanSkillDirs(path.join(pluginDir, DEFAULT_SKILLS_DIR));
42
+ }
43
+ /**
44
+ * Finds the skills a source provides. A `marketplace.json` lists plugin
45
+ * folders; a root `plugin.json` makes the source itself a plugin. Both
46
+ * `.claude-plugin` and `.cursor-plugin` layouts are read.
47
+ *
48
+ * @param sourceRoot - Absolute root of the source checkout
49
+ * @throws when the source has neither manifest; plain skill folders are rejected
50
+ */
51
+ export function locateSkills(sourceRoot) {
52
+ const marketplace = readMarketplace(sourceRoot);
53
+ const warnings = [...(marketplace?.warnings ?? [])];
54
+ const pluginDirs = new Map();
55
+ for (const plugin of marketplace?.plugins ?? [])
56
+ pluginDirs.set(plugin.dir, plugin.name);
57
+ const root = path.resolve(sourceRoot);
58
+ if (manifestFile(root, PLUGIN_FILE) !== null && !pluginDirs.has(root))
59
+ pluginDirs.set(root, undefined);
60
+ if (pluginDirs.size === 0) {
61
+ throw new Error("no .claude-plugin or .cursor-plugin manifest found, the source is not a plugin or marketplace");
62
+ }
63
+ const plugins = [];
64
+ const withoutSkills = [];
65
+ for (const [dir, marketplaceName] of pluginDirs) {
66
+ const manifestPath = manifestFile(dir, PLUGIN_FILE);
67
+ const manifest = manifestPath === null ? {} : PluginManifestSchema.parse(JSON.parse(fs.readFileSync(manifestPath, "utf8")));
68
+ const name = manifest.name ?? marketplaceName ?? path.basename(dir);
69
+ const skillDirs = pluginSkillDirs(dir, sourceRoot, manifest);
70
+ if (skillDirs.length === 0) {
71
+ withoutSkills.push(name);
72
+ continue;
73
+ }
74
+ plugins.push({ name, version: manifest.version, skillDirs });
75
+ }
76
+ if (withoutSkills.length > 0) {
77
+ warnings.push(`${withoutSkills.length} plugin(s) without skills skipped: ${withoutSkills.join(", ")}`);
78
+ }
79
+ return { plugins, warnings };
80
+ }
81
+ //# sourceMappingURL=locate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locate.js","sourceRoot":"","sources":["../../src/registry/locate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Path of a target's `skills.json`, which sits beside its install directory:
3
+ * `.claude/skills` → `.claude/skills.json`.
4
+ *
5
+ * @param installDir - Relative to `projectRoot`, e.g. `.claude/skills`
6
+ * @returns absolute path
7
+ */
8
+ export declare function skillsManifestPath(projectRoot: string, installDir: string): string;
9
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/registry/manifest.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAElF"}
@@ -0,0 +1,14 @@
1
+ // packages/skills/src/registry/manifest.ts
2
+ import path from "node:path";
3
+ const MANIFEST_FILE = "skills.json";
4
+ /**
5
+ * Path of a target's `skills.json`, which sits beside its install directory:
6
+ * `.claude/skills` → `.claude/skills.json`.
7
+ *
8
+ * @param installDir - Relative to `projectRoot`, e.g. `.claude/skills`
9
+ * @returns absolute path
10
+ */
11
+ export function skillsManifestPath(projectRoot, installDir) {
12
+ return path.join(projectRoot, path.dirname(installDir), MANIFEST_FILE);
13
+ }
14
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/registry/manifest.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,aAAa,GAAG,aAAa,CAAC;AAEpC;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,UAAkB;IACxE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC,CAAC;AACzE,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { ReadContext } from "@g3nomaly/core/installer";
2
+ import type { SkillMeta } from "./types";
3
+ export declare const SKILL_FILE = "SKILL.md";
4
+ /**
5
+ * Reads one skill folder into its registry entry. The key is the folder
6
+ * name and every file below it, hooks included, becomes a `files[]` entry at
7
+ * `<key>/<file>`, so the skill installs as one self-contained folder.
8
+ *
9
+ * @param skillDir - Absolute skill folder inside a source checkout
10
+ * @param context - Origin to record, the plugin as group, and the plugin's version
11
+ * @throws when the folder holds no SKILL.md or its frontmatter is invalid
12
+ */
13
+ export declare function readSkillDir(skillDir: string, context: ReadContext): Promise<[string, SkillMeta]>;
14
+ //# sourceMappingURL=readSkillDir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readSkillDir.d.ts","sourceRoot":"","sources":["../../src/registry/readSkillDir.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAK,EAA4B,SAAS,EAAE,MAAM,SAAS,CAAC;AAEnE,eAAO,MAAM,UAAU,aAAa,CAAC;AAiBrC;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAqBvG"}
@@ -0,0 +1,54 @@
1
+ // packages/skills/src/registry/readSkillDir.ts
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { z } from "zod";
5
+ import { hashFile } from "@g3nomaly/core/hash";
6
+ import { listFiles } from "@g3nomaly/core/installer";
7
+ import { readFrontmatter } from "../utils/frontmatter";
8
+ export const SKILL_FILE = "SKILL.md";
9
+ const SkillFrontmatterSchema = z.object({
10
+ name: z.string().min(1),
11
+ description: z.string().optional(),
12
+ /** `<key>` or `<key>@<source>` of skills this one needs installed beside it */
13
+ registryDependencies: z.array(z.string().min(1)).optional(),
14
+ });
15
+ /** Kind of a file by its path inside the skill: `SKILL.md`, an agent file, a hook, or a reference. */
16
+ function fileType(relativeToSkill) {
17
+ if (relativeToSkill === SKILL_FILE)
18
+ return "skill";
19
+ if (relativeToSkill.startsWith(`agents${path.sep}`))
20
+ return "agent";
21
+ if (relativeToSkill.startsWith(`hooks${path.sep}`))
22
+ return "hook";
23
+ return "reference";
24
+ }
25
+ /**
26
+ * Reads one skill folder into its registry entry. The key is the folder
27
+ * name and every file below it, hooks included, becomes a `files[]` entry at
28
+ * `<key>/<file>`, so the skill installs as one self-contained folder.
29
+ *
30
+ * @param skillDir - Absolute skill folder inside a source checkout
31
+ * @param context - Origin to record, the plugin as group, and the plugin's version
32
+ * @throws when the folder holds no SKILL.md or its frontmatter is invalid
33
+ */
34
+ export async function readSkillDir(skillDir, context) {
35
+ const skillMd = path.join(skillDir, SKILL_FILE);
36
+ if (!fs.existsSync(skillMd))
37
+ throw new Error(`${skillDir} holds no ${SKILL_FILE}`);
38
+ const key = path.basename(skillDir);
39
+ const frontmatter = SkillFrontmatterSchema.parse(await readFrontmatter(skillMd));
40
+ const files = [];
41
+ for (const rel of listFiles(skillDir)) {
42
+ files.push({ path: path.join(key, rel), type: fileType(rel), hash: await hashFile(path.join(skillDir, rel)) });
43
+ }
44
+ return [key, {
45
+ name: frontmatter.name,
46
+ description: frontmatter.description,
47
+ version: context.version,
48
+ group: context.group,
49
+ registryDependencies: frontmatter.registryDependencies,
50
+ origin: context.origin,
51
+ files,
52
+ }];
53
+ }
54
+ //# sourceMappingURL=readSkillDir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readSkillDir.js","sourceRoot":"","sources":["../../src/registry/readSkillDir.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;AAErC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,IAAI,EAAS,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,+EAA+E;IAC/E,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC,CAAC;AAEH,sGAAsG;AACtG,SAAS,QAAQ,CAAC,eAAuB;IACvC,IAAI,eAAe,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC;IACnD,IAAI,eAAe,CAAC,UAAU,CAAC,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,OAAO,OAAO,CAAC;IACpE,IAAI,eAAe,CAAC,UAAU,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,OAAO,MAAM,CAAC;IAClE,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB,EAAE,OAAoB;IACvE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,aAAa,UAAU,EAAE,CAAC,CAAC;IAEnF,MAAM,GAAG,GAAW,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,sBAAsB,CAAC,KAAK,CAAC,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IAEjF,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IACjH,CAAC;IAED,OAAO,CAAC,GAAG,EAAE;YACX,IAAI,EAAkB,WAAW,CAAC,IAAI;YACtC,WAAW,EAAW,WAAW,CAAC,WAAW;YAC7C,OAAO,EAAe,OAAO,CAAC,OAAO;YACrC,KAAK,EAAiB,OAAO,CAAC,KAAK;YACnC,oBAAoB,EAAE,WAAW,CAAC,oBAAoB;YACtD,MAAM,EAAgB,OAAO,CAAC,MAAM;YACpC,KAAK;SACN,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ReadSource } from "@g3nomaly/core/installer";
2
+ import type { SkillMeta } from "./types";
3
+ /**
4
+ * Reads every skill a checked-out source declares through its plugin
5
+ * manifests, with the plugin as group. An unreadable skill is skipped with a
6
+ * warning. Handed to `loadSourceRegistry` by every skills command.
7
+ */
8
+ export declare const readSkillSource: ReadSource<SkillMeta>;
9
+ //# sourceMappingURL=readSource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readSource.d.ts","sourceRoot":"","sources":["../../src/registry/readSource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAI3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,UAAU,CAAC,SAAS,CAmBjD,CAAC"}
@@ -0,0 +1,30 @@
1
+ // packages/skills/src/registry/readSource.ts
2
+ import path from "node:path";
3
+ import { errorMessage } from "@g3nomaly/core/utils";
4
+ import { locateSkills } from "./locate";
5
+ import { readSkillDir } from "./readSkillDir";
6
+ /**
7
+ * Reads every skill a checked-out source declares through its plugin
8
+ * manifests, with the plugin as group. An unreadable skill is skipped with a
9
+ * warning. Handed to `loadSourceRegistry` by every skills command.
10
+ */
11
+ export const readSkillSource = async (checkout) => {
12
+ const { plugins, warnings } = locateSkills(checkout.dir);
13
+ const entries = [];
14
+ for (const plugin of plugins) {
15
+ for (const skillDir of plugin.skillDirs) {
16
+ try {
17
+ entries.push(await readSkillDir(skillDir, {
18
+ origin: { source: checkout.name, dir: path.relative(checkout.dir, path.dirname(skillDir)), commit: checkout.commit, version: checkout.version },
19
+ group: plugin.name,
20
+ version: plugin.version,
21
+ }));
22
+ }
23
+ catch (error) {
24
+ warnings.push(`skipped ${path.relative(checkout.dir, skillDir)}: ${errorMessage(error)}`);
25
+ }
26
+ }
27
+ }
28
+ return { entries, warnings };
29
+ };
30
+ //# sourceMappingURL=readSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readSource.js","sourceRoot":"","sources":["../../src/registry/readSource.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAA0B,KAAK,EAAE,QAAQ,EAAE,EAAE;IACvE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzD,MAAM,OAAO,GAA0B,EAAE,CAAC;IAE1C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACxC,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,QAAQ,EAAE;oBACxC,MAAM,EAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE;oBAChJ,KAAK,EAAI,MAAM,CAAC,IAAI;oBACpB,OAAO,EAAE,MAAM,CAAC,OAAO;iBACxB,CAAC,CAAC,CAAC;YACN,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,QAAQ,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC5F,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+ export declare const SkillFileTypeSchema: z.ZodEnum<{
3
+ agent: "agent";
4
+ hook: "hook";
5
+ reference: "reference";
6
+ skill: "skill";
7
+ }>;
8
+ export type SkillFileType = z.infer<typeof SkillFileTypeSchema>;
9
+ /** One file of a skill; `path` is `<skill>/<file>`, relative to the install directory. */
10
+ export declare const SkillFileSchema: z.ZodObject<{
11
+ path: z.ZodString;
12
+ hash: z.ZodOptional<z.ZodString>;
13
+ version: z.ZodOptional<z.ZodString>;
14
+ type: z.ZodEnum<{
15
+ agent: "agent";
16
+ hook: "hook";
17
+ reference: "reference";
18
+ skill: "skill";
19
+ }>;
20
+ }, z.core.$strip>;
21
+ export type SkillFile = z.infer<typeof SkillFileSchema>;
22
+ /**
23
+ * One installable skill. Built from a source's plugin manifest plus the
24
+ * skill's `SKILL.md` frontmatter by `readSkillDir`, and written per install
25
+ * into `skills.json` by the `add` and `update` commands.
26
+ */
27
+ export declare const SkillMetaSchema: z.ZodObject<{
28
+ name: z.ZodString;
29
+ description: z.ZodOptional<z.ZodString>;
30
+ version: z.ZodOptional<z.ZodString>;
31
+ origin: z.ZodObject<{
32
+ source: z.ZodString;
33
+ dir: z.ZodString;
34
+ commit: z.ZodOptional<z.ZodString>;
35
+ version: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strip>;
37
+ group: z.ZodString;
38
+ registryDependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
+ files: z.ZodArray<z.ZodObject<{
40
+ path: z.ZodString;
41
+ hash: z.ZodOptional<z.ZodString>;
42
+ version: z.ZodOptional<z.ZodString>;
43
+ type: z.ZodEnum<{
44
+ agent: "agent";
45
+ hook: "hook";
46
+ reference: "reference";
47
+ skill: "skill";
48
+ }>;
49
+ }, z.core.$strip>>;
50
+ }, z.core.$strip>;
51
+ export type SkillMeta = z.infer<typeof SkillMetaSchema>;
52
+ export type SkillRegistry = Record<string, SkillMeta>;
53
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,mBAAmB;;;;;EAAkD,CAAC;AAEnF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,0FAA0F;AAC1F,eAAO,MAAM,eAAe;;;;;;;;;;iBAE1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;iBAS1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAO,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAC5D,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC"}
@@ -0,0 +1,25 @@
1
+ // packages/skills/src/registry/types.ts
2
+ import { z } from "zod";
3
+ import { BaseFileEntrySchema } from "@g3nomaly/core/registry";
4
+ import { OriginEntrySchema } from "@g3nomaly/core/installer";
5
+ export const SkillFileTypeSchema = z.enum(["skill", "agent", "hook", "reference"]);
6
+ /** One file of a skill; `path` is `<skill>/<file>`, relative to the install directory. */
7
+ export const SkillFileSchema = BaseFileEntrySchema.extend({
8
+ type: SkillFileTypeSchema,
9
+ });
10
+ /**
11
+ * One installable skill. Built from a source's plugin manifest plus the
12
+ * skill's `SKILL.md` frontmatter by `readSkillDir`, and written per install
13
+ * into `skills.json` by the `add` and `update` commands.
14
+ */
15
+ export const SkillMetaSchema = OriginEntrySchema.extend({
16
+ /** Plugin the skill ships in, e.g. `speech` */
17
+ group: z.string().min(1),
18
+ /**
19
+ * Skills this one needs installed beside it. As read from a source these
20
+ * are `<key>` or `<key>@<source>`; once installed, the resolved keys.
21
+ */
22
+ registryDependencies: z.array(z.string().min(1)).optional(),
23
+ files: z.array(SkillFileSchema).min(1),
24
+ });
25
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AAInF,0FAA0F;AAC1F,MAAM,CAAC,MAAM,eAAe,GAAG,mBAAmB,CAAC,MAAM,CAAC;IACxD,IAAI,EAAE,mBAAmB;CAC1B,CAAC,CAAC;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC,MAAM,CAAC;IACtD,+CAA+C;IAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB;;;OAGG;IACH,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC3D,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CACvC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { SourceRecord } from "@g3nomaly/core/sources";
2
+ /** Sources every project has without registering them; they cannot be removed. */
3
+ export declare const BUILTIN_SOURCES: SourceRecord;
4
+ //# sourceMappingURL=builtins.d.ts.map