@lyupro/skillforge-mcp 1.3.0 → 1.4.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 (60) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +33 -0
  4. package/README.md +2 -1
  5. package/dist/cli/dispatcher.d.ts +11 -0
  6. package/dist/cli/dispatcher.d.ts.map +1 -1
  7. package/dist/cli/dispatcher.js +39 -14
  8. package/dist/cli/dispatcher.js.map +1 -1
  9. package/dist/cli/folders-handlers.js +1 -1
  10. package/dist/cli/folders-handlers.js.map +1 -1
  11. package/dist/cli/skills-format.d.ts +15 -0
  12. package/dist/cli/skills-format.d.ts.map +1 -0
  13. package/dist/cli/skills-format.js +84 -0
  14. package/dist/cli/skills-format.js.map +1 -0
  15. package/dist/cli/skills-handlers.d.ts +15 -0
  16. package/dist/cli/skills-handlers.d.ts.map +1 -0
  17. package/dist/cli/skills-handlers.js +112 -0
  18. package/dist/cli/skills-handlers.js.map +1 -0
  19. package/dist/cli/skills-shared.d.ts +32 -0
  20. package/dist/cli/skills-shared.d.ts.map +1 -0
  21. package/dist/cli/skills-shared.js +90 -0
  22. package/dist/cli/skills-shared.js.map +1 -0
  23. package/dist/cli/skills.d.ts +46 -0
  24. package/dist/cli/skills.d.ts.map +1 -0
  25. package/dist/cli/skills.js +107 -0
  26. package/dist/cli/skills.js.map +1 -0
  27. package/dist/config/config-schema.d.ts +246 -142
  28. package/dist/config/config-schema.d.ts.map +1 -1
  29. package/dist/config/config-schema.js +28 -14
  30. package/dist/config/config-schema.js.map +1 -1
  31. package/dist/detect/skill-source-conflict.d.ts +24 -7
  32. package/dist/detect/skill-source-conflict.d.ts.map +1 -1
  33. package/dist/detect/skill-source-conflict.js +62 -10
  34. package/dist/detect/skill-source-conflict.js.map +1 -1
  35. package/dist/reconcile.d.ts +5 -0
  36. package/dist/reconcile.d.ts.map +1 -0
  37. package/dist/reconcile.js +20 -0
  38. package/dist/reconcile.js.map +1 -0
  39. package/dist/runtime.d.ts +14 -0
  40. package/dist/runtime.d.ts.map +1 -0
  41. package/dist/runtime.js +29 -0
  42. package/dist/runtime.js.map +1 -0
  43. package/dist/server-deps.d.ts +3 -1
  44. package/dist/server-deps.d.ts.map +1 -1
  45. package/dist/server.d.ts.map +1 -1
  46. package/dist/server.js +23 -8
  47. package/dist/server.js.map +1 -1
  48. package/dist/tools/configure.d.ts.map +1 -1
  49. package/dist/tools/configure.js +8 -25
  50. package/dist/tools/configure.js.map +1 -1
  51. package/dist/watcher/config-watcher.d.ts +25 -0
  52. package/dist/watcher/config-watcher.d.ts.map +1 -0
  53. package/dist/watcher/config-watcher.js +92 -0
  54. package/dist/watcher/config-watcher.js.map +1 -0
  55. package/dist/watcher/index.d.ts +2 -0
  56. package/dist/watcher/index.d.ts.map +1 -1
  57. package/dist/watcher/index.js +1 -0
  58. package/dist/watcher/index.js.map +1 -1
  59. package/manifest.json +1 -1
  60. package/package.json +1 -1
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Shared helpers for the `skills` subcommand modules.
3
+ *
4
+ * Holds pure parsing/lookup logic split out of `skills.ts` so the entry
5
+ * module stays small and the handler modules can reuse it.
6
+ */
7
+ import { resolve } from 'node:path';
8
+ import { findFolderEntry } from './folders-shared.js';
9
+ /**
10
+ * Parse the flags accepted by `skills list`.
11
+ * Returns null on a malformed or unknown flag.
12
+ */
13
+ export function parseListFlags(args) {
14
+ let search;
15
+ let source;
16
+ let folder;
17
+ let folderTag;
18
+ let folderFmt = 'alias';
19
+ let asJson = false;
20
+ for (let i = 0; i < args.length; i += 1) {
21
+ const arg = args[i];
22
+ if (arg === '--json') {
23
+ asJson = true;
24
+ }
25
+ else if (arg === '--search') {
26
+ const value = args[i + 1];
27
+ if (value === undefined || value.startsWith('--'))
28
+ return null;
29
+ search = value;
30
+ i += 1;
31
+ }
32
+ else if (arg === '--source') {
33
+ const value = args[i + 1];
34
+ if (value === undefined || value.startsWith('--'))
35
+ return null;
36
+ source = value;
37
+ i += 1;
38
+ }
39
+ else if (arg === '--folder') {
40
+ const value = args[i + 1];
41
+ if (value === undefined || value.startsWith('--'))
42
+ return null;
43
+ folder = value;
44
+ i += 1;
45
+ }
46
+ else if (arg === '--folder-tag') {
47
+ const value = args[i + 1];
48
+ if (value === undefined || value.startsWith('--'))
49
+ return null;
50
+ folderTag = value;
51
+ i += 1;
52
+ }
53
+ else if (arg === '--folder-fmt') {
54
+ const value = args[i + 1];
55
+ if (value !== 'alias' && value !== 'path')
56
+ return null;
57
+ folderFmt = value;
58
+ i += 1;
59
+ }
60
+ else {
61
+ return null;
62
+ }
63
+ }
64
+ return { search, source, folder, folderTag, folderFmt, asJson };
65
+ }
66
+ /**
67
+ * Resolve a `--folder` token (alias or path) to the resolved folder path.
68
+ * Returns null if the token does not match any registered folder.
69
+ */
70
+ export function resolveFolderArg(token, folders) {
71
+ const entry = findFolderEntry(folders, token);
72
+ if (entry === null)
73
+ return null;
74
+ return entry.path;
75
+ }
76
+ /**
77
+ * Build a map of folder path → display label.
78
+ * When an alias is set, the alias is used; otherwise the path itself.
79
+ */
80
+ export function buildFolderAliasMap(folders, fmt) {
81
+ const map = new Map();
82
+ for (const f of folders) {
83
+ const label = fmt === 'alias' && f.alias !== undefined && f.alias.length > 0
84
+ ? f.alias
85
+ : f.path;
86
+ map.set(resolve(f.path), label);
87
+ }
88
+ return map;
89
+ }
90
+ //# sourceMappingURL=skills-shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills-shared.js","sourceRoot":"","sources":["../../src/cli/skills-shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * SkillForge `skills` subcommand.
4
+ *
5
+ * Terminal-side skill inspection and registry reload. Without this, skills
6
+ * could only be viewed from inside an LLM session via the `skills__list` or
7
+ * `skills__get` MCP tools. This subcommand exposes the same tool handlers to
8
+ * the shell — no separate registry logic.
9
+ *
10
+ * Note: the CLI reads config.json and skill files directly from disk. It
11
+ * reflects disk truth, NOT the state of any running MCP server session.
12
+ *
13
+ * Usage:
14
+ * skillforge skills list [flags] List skills from the registry
15
+ * skillforge skills get <name> [flags] Print full content of one skill
16
+ * skillforge skills reload Force a registry rebuild from disk
17
+ *
18
+ * list flags:
19
+ * --search <s> Case-insensitive substring filter over name + description.
20
+ * --source <format> Filter by skill format: claude | codex | persona | custom.
21
+ * --folder <path|alias> Restrict to one configured folder (alias or path).
22
+ * --folder-tag <tag> Restrict to folders with this tag in config.
23
+ * --folder-fmt <fmt> FOLDER column format: alias (default) or path.
24
+ * --json Emit raw JSON instead of a table.
25
+ *
26
+ * get flags:
27
+ * --json Emit raw JSON instead of human-readable output.
28
+ *
29
+ * This module keeps only the entry point + action dispatch; the handlers,
30
+ * table formatting, and shared parsing helpers live in sibling modules.
31
+ */
32
+ import type { ServerDeps } from '../server-deps.js';
33
+ export interface SkillsDeps {
34
+ stdout?: (text: string) => void;
35
+ stderr?: (text: string) => void;
36
+ /** Override the ServerDeps factory — tests inject a fake deps object here. */
37
+ buildDeps?: () => Promise<ServerDeps>;
38
+ }
39
+ /**
40
+ * `skills` subcommand entry. Returns an exit code:
41
+ * - 0 on success
42
+ * - 1 on a runtime failure (e.g. skill not found)
43
+ * - 2 on a missing/unknown sub-action or malformed flag
44
+ */
45
+ export declare function main(rawArgv: string[], deps?: SkillsDeps): Promise<number>;
46
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/cli/skills.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAOpD,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;CACvC;AA8BD;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA0CpF"}
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * SkillForge `skills` subcommand.
4
+ *
5
+ * Terminal-side skill inspection and registry reload. Without this, skills
6
+ * could only be viewed from inside an LLM session via the `skills__list` or
7
+ * `skills__get` MCP tools. This subcommand exposes the same tool handlers to
8
+ * the shell — no separate registry logic.
9
+ *
10
+ * Note: the CLI reads config.json and skill files directly from disk. It
11
+ * reflects disk truth, NOT the state of any running MCP server session.
12
+ *
13
+ * Usage:
14
+ * skillforge skills list [flags] List skills from the registry
15
+ * skillforge skills get <name> [flags] Print full content of one skill
16
+ * skillforge skills reload Force a registry rebuild from disk
17
+ *
18
+ * list flags:
19
+ * --search <s> Case-insensitive substring filter over name + description.
20
+ * --source <format> Filter by skill format: claude | codex | persona | custom.
21
+ * --folder <path|alias> Restrict to one configured folder (alias or path).
22
+ * --folder-tag <tag> Restrict to folders with this tag in config.
23
+ * --folder-fmt <fmt> FOLDER column format: alias (default) or path.
24
+ * --json Emit raw JSON instead of a table.
25
+ *
26
+ * get flags:
27
+ * --json Emit raw JSON instead of human-readable output.
28
+ *
29
+ * This module keeps only the entry point + action dispatch; the handlers,
30
+ * table formatting, and shared parsing helpers live in sibling modules.
31
+ */
32
+ import { handleSkillsList, handleSkillsGet, handleSkillsReload, } from './skills-handlers.js';
33
+ const USAGE = `skillforge skills — view and reload skills from the terminal.
34
+
35
+ Note: the CLI reads disk, not a live server session. Results reflect the
36
+ current state of config.json and skill files on disk.
37
+
38
+ Usage:
39
+ skillforge skills <action> [args]
40
+
41
+ Actions:
42
+ list [flags] Print a table of skills from the registry.
43
+ Flags: --search <s>, --source <format>,
44
+ --folder <path|alias>, --folder-tag <tag>,
45
+ --folder-fmt alias|path (default alias), --json
46
+ get <name> [flags] Print the full content of one skill.
47
+ Flags: --json
48
+ reload Force a registry rebuild + config reconcile from disk.
49
+ Prints: N folders, M skills, and any per-file errors.
50
+
51
+ Examples:
52
+ skillforge skills list
53
+ skillforge skills list --search review --json
54
+ skillforge skills list --folder work --folder-fmt path
55
+ skillforge skills list --source claude
56
+ skillforge skills get code-review
57
+ skillforge skills get code-review --json
58
+ skillforge skills reload
59
+ `;
60
+ /**
61
+ * `skills` subcommand entry. Returns an exit code:
62
+ * - 0 on success
63
+ * - 1 on a runtime failure (e.g. skill not found)
64
+ * - 2 on a missing/unknown sub-action or malformed flag
65
+ */
66
+ export async function main(rawArgv, deps = {}) {
67
+ const stdout = deps.stdout ?? ((text) => process.stdout.write(text));
68
+ const stderr = deps.stderr ?? ((text) => process.stderr.write(text));
69
+ const action = rawArgv[0];
70
+ const rest = rawArgv.slice(1);
71
+ if (action === undefined || (action !== 'list' && action !== 'get' && action !== 'reload')) {
72
+ if (action !== undefined) {
73
+ stderr(`skillforge skills: unknown action: ${action}\n\n`);
74
+ }
75
+ stderr(USAGE);
76
+ return 2;
77
+ }
78
+ let serverDeps;
79
+ try {
80
+ const factory = deps.buildDeps ?? (async () => {
81
+ const { buildDeps } = await import('../server.js');
82
+ return buildDeps();
83
+ });
84
+ serverDeps = await factory();
85
+ }
86
+ catch (err) {
87
+ const msg = err instanceof Error ? err.message : String(err);
88
+ stderr(`skillforge skills: failed to initialise registry: ${msg}\n`);
89
+ return 1;
90
+ }
91
+ try {
92
+ switch (action) {
93
+ case 'list':
94
+ return await handleSkillsList(serverDeps, rest, stdout, stderr);
95
+ case 'get':
96
+ return await handleSkillsGet(serverDeps, rest, stdout, stderr);
97
+ case 'reload':
98
+ return await handleSkillsReload(serverDeps, rest, stdout, stderr);
99
+ }
100
+ }
101
+ catch (err) {
102
+ const msg = err instanceof Error ? err.message : String(err);
103
+ stderr(`skillforge skills: ${msg}\n`);
104
+ return 1;
105
+ }
106
+ }
107
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/cli/skills.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAS9B,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Bb,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAAiB,EAAE,OAAmB,EAAE;IACjE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAE7E,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE9B,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC3F,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,CAAC,sCAAsC,MAAM,MAAM,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,CAAC;QACd,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,UAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,IAAI,EAAE;YAC5C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;YACnD,OAAO,SAAS,EAAE,CAAC;QACrB,CAAC,CAAC,CAAC;QACH,UAAU,GAAG,MAAM,OAAO,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,CAAC,qDAAqD,GAAG,IAAI,CAAC,CAAC;QACrE,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,CAAC;QACH,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,MAAM;gBACT,OAAO,MAAM,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAClE,KAAK,KAAK;gBACR,OAAO,MAAM,eAAe,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACjE,KAAK,QAAQ;gBACX,OAAO,MAAM,kBAAkB,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;QACtC,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}