@lyupro/skillforge-mcp 1.2.0 → 1.4.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.
Files changed (81) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +47 -0
  4. package/README.md +27 -12
  5. package/dist/cli/dispatcher.d.ts.map +1 -1
  6. package/dist/cli/dispatcher.js +13 -10
  7. package/dist/cli/dispatcher.js.map +1 -1
  8. package/dist/cli/folders-format.d.ts +10 -0
  9. package/dist/cli/folders-format.d.ts.map +1 -0
  10. package/dist/cli/folders-format.js +41 -0
  11. package/dist/cli/folders-format.js.map +1 -0
  12. package/dist/cli/folders-handlers.d.ts +16 -0
  13. package/dist/cli/folders-handlers.d.ts.map +1 -0
  14. package/dist/cli/folders-handlers.js +195 -0
  15. package/dist/cli/folders-handlers.js.map +1 -0
  16. package/dist/cli/folders-shared.d.ts +29 -0
  17. package/dist/cli/folders-shared.d.ts.map +1 -0
  18. package/dist/cli/folders-shared.js +82 -0
  19. package/dist/cli/folders-shared.js.map +1 -0
  20. package/dist/cli/folders.d.ts +7 -2
  21. package/dist/cli/folders.d.ts.map +1 -1
  22. package/dist/cli/folders.js +28 -177
  23. package/dist/cli/folders.js.map +1 -1
  24. package/dist/cli/skills-format.d.ts +15 -0
  25. package/dist/cli/skills-format.d.ts.map +1 -0
  26. package/dist/cli/skills-format.js +84 -0
  27. package/dist/cli/skills-format.js.map +1 -0
  28. package/dist/cli/skills-handlers.d.ts +15 -0
  29. package/dist/cli/skills-handlers.d.ts.map +1 -0
  30. package/dist/cli/skills-handlers.js +112 -0
  31. package/dist/cli/skills-handlers.js.map +1 -0
  32. package/dist/cli/skills-shared.d.ts +32 -0
  33. package/dist/cli/skills-shared.d.ts.map +1 -0
  34. package/dist/cli/skills-shared.js +90 -0
  35. package/dist/cli/skills-shared.js.map +1 -0
  36. package/dist/cli/skills.d.ts +46 -0
  37. package/dist/cli/skills.d.ts.map +1 -0
  38. package/dist/cli/skills.js +107 -0
  39. package/dist/cli/skills.js.map +1 -0
  40. package/dist/cli/tools.d.ts.map +1 -1
  41. package/dist/cli/tools.js +6 -0
  42. package/dist/cli/tools.js.map +1 -1
  43. package/dist/config/config-schema.d.ts +248 -136
  44. package/dist/config/config-schema.d.ts.map +1 -1
  45. package/dist/config/config-schema.js +34 -14
  46. package/dist/config/config-schema.js.map +1 -1
  47. package/dist/detect/skill-source-conflict.d.ts +24 -7
  48. package/dist/detect/skill-source-conflict.d.ts.map +1 -1
  49. package/dist/detect/skill-source-conflict.js +62 -10
  50. package/dist/detect/skill-source-conflict.js.map +1 -1
  51. package/dist/reconcile.d.ts +5 -0
  52. package/dist/reconcile.d.ts.map +1 -0
  53. package/dist/reconcile.js +20 -0
  54. package/dist/reconcile.js.map +1 -0
  55. package/dist/runtime.d.ts +14 -0
  56. package/dist/runtime.d.ts.map +1 -0
  57. package/dist/runtime.js +29 -0
  58. package/dist/runtime.js.map +1 -0
  59. package/dist/server-deps.d.ts +3 -1
  60. package/dist/server-deps.d.ts.map +1 -1
  61. package/dist/server.d.ts.map +1 -1
  62. package/dist/server.js +26 -9
  63. package/dist/server.js.map +1 -1
  64. package/dist/tools/configure.d.ts +2 -0
  65. package/dist/tools/configure.d.ts.map +1 -1
  66. package/dist/tools/configure.js +22 -26
  67. package/dist/tools/configure.js.map +1 -1
  68. package/dist/tools/list.d.ts +2 -0
  69. package/dist/tools/list.d.ts.map +1 -1
  70. package/dist/tools/list.js +12 -0
  71. package/dist/tools/list.js.map +1 -1
  72. package/dist/watcher/config-watcher.d.ts +25 -0
  73. package/dist/watcher/config-watcher.d.ts.map +1 -0
  74. package/dist/watcher/config-watcher.js +92 -0
  75. package/dist/watcher/config-watcher.js.map +1 -0
  76. package/dist/watcher/index.d.ts +2 -0
  77. package/dist/watcher/index.d.ts.map +1 -1
  78. package/dist/watcher/index.js +1 -0
  79. package/dist/watcher/index.js.map +1 -1
  80. package/manifest.json +3 -3
  81. package/package.json +1 -1
@@ -14,7 +14,7 @@
14
14
  "package": "@lyupro/skillforge-mcp"
15
15
  },
16
16
  "description": "Universal Skills MCP server — load Markdown skills from arbitrary folders, lazy-by-design, cross-tool.",
17
- "version": "1.2.0",
17
+ "version": "1.4.0",
18
18
  "author": {
19
19
  "name": "Lyu Pro",
20
20
  "email": "lyupro.dev@gmail.com"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "skillforge",
4
- "version": "1.2.0",
4
+ "version": "1.4.0",
5
5
  "description": "Universal Skills MCP server — load Markdown skills from arbitrary folders, lazy-by-design, cross-tool.",
6
6
  "author": {
7
7
  "name": "Lyu Pro",
package/CHANGELOG.md CHANGED
@@ -2,6 +2,51 @@
2
2
 
3
3
  All notable changes to **SkillForge MCP** are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
+ ## [1.4.0] — 2026-05-17
6
+
7
+ Config live-reload, a new `skills` CLI subcommand, more accurate conflict detection, and forward-compatible config schemas.
8
+
9
+ ### Added
10
+
11
+ - **`ConfigWatcher`** (`src/watcher/config-watcher.ts`) — watches the config directory and reconciles the folder list and skill registry whenever `config.json` changes on disk. Previously a long-lived MCP server held a startup snapshot and never saw edits made by the `skillforge folders` CLI (which writes from a separate process) until the server was restarted. `skills__configure` `list_folders` and `get_blacklist` now report current disk state instead of the in-memory snapshot.
12
+ - **`skillforge skills` CLI subcommand** (`src/cli/skills.ts`) — terminal-side skill inspection without an LLM session. Three commands:
13
+ - `skills list` — prints a table of all registered skills. Filters: `--search <text>`, `--source <name>`, `--folder <path|alias>`, `--folder-tag <name>`. Display options: `--json`, `--folder-fmt alias|path` (the `FOLDER` column shows the alias by default when one is set).
14
+ - `skills get <name>` — prints the full SKILL.md body and frontmatter for a single skill.
15
+ - `skills reload` — forces a full registry rescan and prints folder/skill counts.
16
+
17
+ ### Changed
18
+
19
+ - **Conflict-hint accuracy** (`src/detect/skill-source-conflict.ts`) — the skill-source conflict detector (warns when a registered folder overlaps with a host plugin's native store, which would double-load skills) previously ran on path logic alone and warned even for plugins the user had already disabled. It now reads the host's plugin enable state: a disabled plugin produces no warning; an unknown/unreadable enable state produces a softened conditional hint.
20
+ - **Config schema forward-compatibility** (`src/config/config-schema.ts`) — all Zod config schemas previously used the default `strip` mode, silently dropping unknown keys on load/save. Any config written by a newer version of SkillForge would lose unrecognised fields when read by an older version. All schemas now use `passthrough`, so unknown keys survive a full load/save round-trip.
21
+
22
+ ### Verified
23
+
24
+ - 609 / 609 tests passing + 1 win32-skip (610 total).
25
+ - `pnpm lint` (`tsc --noEmit`) clean.
26
+ - `pnpm build` clean.
27
+ - `pnpm check:size` — all 68 source files ≤ 400 lines.
28
+
29
+ ## [1.3.0] — 2026-05-16
30
+
31
+ Folder ergonomics — address folders by a short alias, toggle them on and off, and filter skills by folder tag.
32
+
33
+ ### Added
34
+
35
+ - Folder alias. A folder entry now carries an optional kebab-case `alias` — a single short handle for a folder. `skillforge folders add <path> --alias <name>` registers it; `skillforge folders remove <name>` and the new `skillforge folders alias <path|alias> <name>` accept the alias in place of the full absolute path. The full path keeps working everywhere. Aliases are validated kebab-case and unique across registered folders — a collision fails with exit ≠ 0 and leaves the config untouched. The `skills__configure` `add_folder` action accepts an `alias` field too, and `folders list` shows an `ALIAS` column.
36
+ - `skillforge folders enable <path|alias>` / `skillforge folders disable <path|alias>` — a two-way toggle for the `enabled` flag. `folders add --disabled` previously had no inverse; re-activating a folder meant hand-editing `config.json`. A disabled folder stays in the config but is skipped on scan.
37
+ - Folder-tag filtering. Folder `tags` were written to the config but never read. `skills__list` now accepts a `folderTag` argument that keeps only skills under folders carrying that tag, and `skillforge folders list --tag <name>` filters the listing the same way. `docs/CONFIGURATION.md` gains a "tags vs alias" section: `alias` is one unique handle per folder for addressing, `tags` are many shared labels for grouping.
38
+
39
+ ### Changed
40
+
41
+ - `src/cli/folders.ts` split into four flat sibling modules (`folders.ts`, `folders-handlers.ts`, `folders-format.ts`, `folders-shared.ts`) to stay under the 400-line file gate. The `dispatcher.ts` import path is unchanged.
42
+
43
+ ### Verified
44
+
45
+ - 561 / 561 tests passing + 1 win32-skip.
46
+ - `pnpm lint` (`tsc --noEmit`) clean.
47
+ - `pnpm build` clean.
48
+ - `pnpm check:size` — all source files ≤ 400 lines.
49
+
5
50
  ## [1.2.0] — 2026-05-16
6
51
 
7
52
  Terminal-side tooling — inspect MCP tools and manage skill folders without an LLM session, plus repo-local install scope and Claude Code plugin packaging.
@@ -157,6 +202,8 @@ All 10 verified through real parse pipeline + `StrategyFactory.create()` correct
157
202
  - **`pnpm build`** clean.
158
203
  - **`pnpm smoke`** end-to-end via subprocess `dist/server.js` — LoggingDecorator trace visible.
159
204
 
205
+ [1.4.0]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.4.0
206
+ [1.3.0]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.3.0
160
207
  [1.2.0]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.2.0
161
208
  [1.1.1]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.1.1
162
209
  [1.1.0]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.1.0
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org)
7
7
  [![MCP](https://img.shields.io/badge/MCP-stdio-purple)](https://modelcontextprotocol.io)
8
8
 
9
- **v1.2.0** — 5 MCP tools, one-command install across Claude Code / Codex CLI / Cursor, terminal `tools` + `folders` subcommands, global/project install scopes, Claude Code plugin packaging, 535 tests, 10 sample skills, modular architecture (all source files ≤ 400 lines).
9
+ **v1.4.0** — 5 MCP tools, one-command install across Claude Code / Codex CLI / Cursor, terminal `tools` + `folders` + `skills` subcommands, config live-reload, forward-compatible config schemas, global/project install scopes, Claude Code plugin packaging, 609 tests, 10 sample skills, modular architecture (all source files ≤ 400 lines).
10
10
 
11
11
  ---
12
12
 
@@ -105,7 +105,8 @@ The `skillforge` / `skillforge-mcp` binary is a dispatcher — the first positio
105
105
  | `install` | Wire SkillForge into Claude Code / Codex CLI / Cursor. Flags: `--claude` / `--codex` / `--cursor` / `--all`, `--dry-run`, `--uninstall`, `--force`, `--entry npx\|local`, `--binary-path <path>`, `--scope global\|project`. |
106
106
  | `uninstall` | Reverse a previous install. Accepts the same `--scope global\|project` flag. |
107
107
  | `tools` | Print the 5 MCP tools the server exposes (name, description, parameters, example). Pass `--json` for machine-readable output. |
108
- | `folders` | Manage skill folders from the terminal — `list` / `add` / `remove` / `reset`. |
108
+ | `folders` | Manage skill folders from the terminal — `list` / `add` / `remove` / `alias` / `enable` / `disable` / `reset`. |
109
+ | `skills` | Inspect the skill registry from the terminal — `list` (with `--search`, `--source`, `--folder`, `--folder-tag`, `--json`, `--folder-fmt`), `get <name>`, `reload`. |
109
110
  | `--version`, `-v` | Print the package version. |
110
111
  | `--help`, `-h` | Print combined usage. |
111
112
 
@@ -123,22 +124,30 @@ Prints every MCP tool the server exposes (`skills__list`, `skills__get`, `skills
123
124
  Folder management is also available from the shell, not just via the `skills__configure` MCP tool inside an LLM session:
124
125
 
125
126
  ```bash
126
- skillforge folders list [--json] # print registered folders
127
- skillforge folders add <path> [flags] # register a folder
128
- skillforge folders remove <path> # remove a folder entry
129
- skillforge folders reset --yes # reset folders to the default (empty) list
127
+ skillforge folders list [--json] [--tag <name>] # print registered folders
128
+ skillforge folders add <path> [flags] # register a folder
129
+ skillforge folders remove <path|alias> # remove a folder entry
130
+ skillforge folders alias <path|alias> <name> # set or change a folder alias
131
+ skillforge folders enable <path|alias> # re-activate a disabled folder
132
+ skillforge folders disable <path|alias> # deactivate a folder (kept in config)
133
+ skillforge folders reset --yes # reset folders to the default (empty) list
130
134
  ```
131
135
 
132
136
  `add` flags:
133
137
 
134
138
  - `--priority <n>` — folder priority (default `100`; higher wins on name collisions).
135
- - `--tags <a,b,c>` — comma-separated tags.
139
+ - `--alias <name>` — a short kebab-case handle, unique across folders. Lets `remove` / `enable` / `disable` target the folder without typing the full path.
140
+ - `--tags <a,b,c>` — comma-separated tags. Filter on them via `folders list --tag <name>` or the `skills__list` `folderTag` argument.
136
141
  - `--disabled` — register the folder disabled.
137
142
 
138
143
  ```bash
139
- skillforge folders add ~/.lyupro/skills --priority 50 --tags work,review
144
+ skillforge folders add ~/.lyupro/skills --priority 50 --alias core --tags work,review
145
+ skillforge folders disable core # address it by alias, not by path
146
+ skillforge folders list --tag work # only folders tagged "work"
140
147
  ```
141
148
 
149
+ `alias` is one unique handle per folder (addressing); `tags` are many shared labels (grouping and filtering) — see [docs/CONFIGURATION.md](./docs/CONFIGURATION.md) for the full contrast.
150
+
142
151
  `reset` requires `--yes` to apply — without it, the command prints what would change and makes no edits. All `folders` actions read and write the same persisted config (`~/.lyupro/.skillforge/config.json`) as the `skills__configure` MCP tool.
143
152
 
144
153
  If you register a folder that already lives inside another tool's native skill store (a Claude Code plugin cache or a Gemini CLI extension), `folders add` prints a hint to disable the duplicate source so the same skills don't load twice. SkillForge only prints the hint — it never edits another tool's config.
@@ -147,7 +156,7 @@ If you register a folder that already lives inside another tool's native skill s
147
156
 
148
157
  | Tool | Purpose |
149
158
  |------|---------|
150
- | `skills__list` | Enumerate available skills (metadata only). Filters: `folder`, `search`, `source`. |
159
+ | `skills__list` | Enumerate available skills (metadata only). Filters: `folder`, `search`, `source`, `folderTag`. |
151
160
  | `skills__get` | Fetch full SKILL.md body + metadata for one skill. |
152
161
  | `skills__invoke` | Execute a skill via its assigned strategy, wrapped in the decorator chain (Logging → Timeout → Cache). Composite skills (`metadata.skills: [a, b]`) walk nested skills sequentially with DFS cycle detection. |
153
162
  | `skills__configure` | Manage configured folders + manual blacklist. Actions: `add_folder`, `remove_folder`, `list_folders`, `set_blacklist`, `get_blacklist`, `reset`. Persists to the config file and reconciles in-process state without restart. |
@@ -233,15 +242,21 @@ For production use with untrusted skill authors, run SkillForge inside Docker or
233
242
 
234
243
  ## Updating
235
244
 
245
+ Pick the block that matches how you installed.
246
+
236
247
  ```bash
237
- # Plugin install
248
+ # Installed as a Claude Code plugin
238
249
  /plugin update skillforge
239
250
 
240
- # npm install
251
+ # Installed via the install CLI (global npm package)
252
+ npm install -g @lyupro/skillforge-mcp@latest
253
+ # host wiring already points at the global bin — restart the host session
254
+
255
+ # Installed as a bare MCP server (npx)
241
256
  claude mcp remove skillforge
242
257
  claude mcp add skillforge -- npx -y @lyupro/skillforge-mcp@latest
243
258
 
244
- # Local-build install
259
+ # Local-build install (git clone)
245
260
  cd skillforge-mcp
246
261
  git pull
247
262
  pnpm install
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/cli/dispatcher.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAwCH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAa1D;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAsBD;;;;;;GAMG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GACnD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkCxB"}
1
+ {"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/cli/dispatcher.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA+CH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAa1D;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAeD;;;;;;GAMG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GACnD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqCxB"}
@@ -26,6 +26,7 @@
26
26
  import { main as installMain } from './install.js';
27
27
  import { main as toolsMain } from './tools.js';
28
28
  import { main as foldersMain } from './folders.js';
29
+ import { main as skillsMain } from './skills.js';
29
30
  const USAGE = `skillforge-mcp — universal Skills MCP server + install CLI.
30
31
 
31
32
  Usage:
@@ -49,6 +50,12 @@ Commands:
49
50
  folders Manage skill folders from the terminal (list/add/remove/reset).
50
51
  Run "skillforge-mcp folders" for sub-action usage.
51
52
  Example: skillforge-mcp folders add ~/.lyupro/skills
53
+ skills View and reload skills from the terminal (list/get/reload).
54
+ The CLI reads disk, not a live server session.
55
+ Run "skillforge-mcp skills" for sub-action usage.
56
+ Example: skillforge-mcp skills list
57
+ Example: skillforge-mcp skills get code-review
58
+ Example: skillforge-mcp skills reload
52
59
 
53
60
  Options:
54
61
  --help, -h Show this message.
@@ -75,20 +82,13 @@ export async function readPackageVersion() {
75
82
  }
76
83
  async function defaultStartServe() {
77
84
  const { buildDeps, buildServer } = await import('../server.js');
85
+ const { startRuntime, registerShutdown } = await import('../runtime.js');
78
86
  const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
79
87
  const deps = await buildDeps();
80
88
  const server = buildServer(deps);
81
89
  await server.connect(new StdioServerTransport());
82
- await deps.folderWatcher.start();
83
- const shutdown = async () => {
84
- await deps.folderWatcher.stop();
85
- };
86
- process.once('SIGTERM', () => {
87
- void shutdown();
88
- });
89
- process.once('SIGINT', () => {
90
- void shutdown();
91
- });
90
+ await startRuntime(deps);
91
+ registerShutdown(deps);
92
92
  }
93
93
  /**
94
94
  * Dispatcher entry. Returns:
@@ -120,6 +120,9 @@ export async function main(rawArgv, overrides = {}) {
120
120
  if (first === 'folders') {
121
121
  return foldersMain(rawArgv.slice(1));
122
122
  }
123
+ if (first === 'skills') {
124
+ return skillsMain(rawArgv.slice(1));
125
+ }
123
126
  if (first === 'serve' || first === undefined) {
124
127
  const start = overrides.startServe ?? defaultStartServe;
125
128
  await start();
@@ -1 +1 @@
1
- {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/cli/dispatcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/cli/dispatcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Table rendering for the `folders list` subcommand.
3
+ *
4
+ * Split out of `folders.ts` so the entry module stays under the 400-line
5
+ * file-size gate. Pure formatting — no I/O.
6
+ */
7
+ import type { FolderEntry } from '../config/config-schema.js';
8
+ /** Render the registered folders as a fixed-width text table. */
9
+ export declare function formatFoldersTable(folders: FolderEntry[]): string;
10
+ //# sourceMappingURL=folders-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders-format.d.ts","sourceRoot":"","sources":["../../src/cli/folders-format.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAkCjE"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Table rendering for the `folders list` subcommand.
3
+ *
4
+ * Split out of `folders.ts` so the entry module stays under the 400-line
5
+ * file-size gate. Pure formatting — no I/O.
6
+ */
7
+ /** Render the registered folders as a fixed-width text table. */
8
+ export function formatFoldersTable(folders) {
9
+ if (folders.length === 0) {
10
+ return 'No folders registered.\n';
11
+ }
12
+ const rows = folders.map((f) => ({
13
+ priority: String(f.priority),
14
+ enabled: f.enabled ? 'yes' : 'no',
15
+ alias: f.alias !== undefined && f.alias.length > 0 ? f.alias : '-',
16
+ tags: f.tags.length > 0 ? f.tags.join(',') : '-',
17
+ path: f.path,
18
+ }));
19
+ const headers = {
20
+ priority: 'PRIORITY',
21
+ enabled: 'ENABLED',
22
+ alias: 'ALIAS',
23
+ tags: 'TAGS',
24
+ path: 'PATH',
25
+ };
26
+ const width = {
27
+ priority: Math.max(headers.priority.length, ...rows.map((r) => r.priority.length)),
28
+ enabled: Math.max(headers.enabled.length, ...rows.map((r) => r.enabled.length)),
29
+ alias: Math.max(headers.alias.length, ...rows.map((r) => r.alias.length)),
30
+ tags: Math.max(headers.tags.length, ...rows.map((r) => r.tags.length)),
31
+ };
32
+ const pad = (text, len) => text.padEnd(len);
33
+ const lines = [
34
+ `${pad(headers.priority, width.priority)} ${pad(headers.enabled, width.enabled)} ${pad(headers.alias, width.alias)} ${pad(headers.tags, width.tags)} ${headers.path}`,
35
+ ];
36
+ for (const r of rows) {
37
+ lines.push(`${pad(r.priority, width.priority)} ${pad(r.enabled, width.enabled)} ${pad(r.alias, width.alias)} ${pad(r.tags, width.tags)} ${r.path}`);
38
+ }
39
+ return `${lines.join('\n')}\n`;
40
+ }
41
+ //# sourceMappingURL=folders-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders-format.js","sourceRoot":"","sources":["../../src/cli/folders-format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Action handlers for the `folders` subcommand.
3
+ *
4
+ * Each handler takes a `ConfigStore`, the post-action args, and stdout/stderr
5
+ * sinks; it returns a process exit code. Split out of `folders.ts` so the
6
+ * entry module stays under the 400-line file-size gate.
7
+ */
8
+ import type { ConfigStore } from '../config/config-store.js';
9
+ export declare function handleList(store: ConfigStore, rest: string[], stdout: (t: string) => void, stderr: (t: string) => void): Promise<number>;
10
+ export declare function handleAdd(store: ConfigStore, rest: string[], stdout: (t: string) => void, stderr: (t: string) => void, isDirectory: (p: string) => Promise<boolean>): Promise<number>;
11
+ export declare function handleRemove(store: ConfigStore, rest: string[], stdout: (t: string) => void, stderr: (t: string) => void): Promise<number>;
12
+ export declare function handleAlias(store: ConfigStore, rest: string[], stdout: (t: string) => void, stderr: (t: string) => void): Promise<number>;
13
+ export declare function handleEnable(store: ConfigStore, rest: string[], stdout: (t: string) => void, stderr: (t: string) => void): Promise<number>;
14
+ export declare function handleDisable(store: ConfigStore, rest: string[], stdout: (t: string) => void, stderr: (t: string) => void): Promise<number>;
15
+ export declare function handleReset(store: ConfigStore, rest: string[], stdout: (t: string) => void, stderr: (t: string) => void): Promise<number>;
16
+ //# sourceMappingURL=folders-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders-handlers.d.ts","sourceRoot":"","sources":["../../src/cli/folders-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAU7D,wBAAsB,UAAU,CAC9B,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAED,wBAAsB,SAAS,CAC7B,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC3B,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAqDjB;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,EAC3B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAC1B,OAAO,CAAC,MAAM,CAAC,CAqBjB"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Action handlers for the `folders` subcommand.
3
+ *
4
+ * Each handler takes a `ConfigStore`, the post-action args, and stdout/stderr
5
+ * sinks; it returns a process exit code. Split out of `folders.ts` so the
6
+ * entry module stays under the 400-line file-size gate.
7
+ */
8
+ import { resolve } from 'node:path';
9
+ import { defaultConfig } from '../config/config-schema.js';
10
+ import { detectSkillSourceConflict, formatConflictHint, } from '../detect/skill-source-conflict.js';
11
+ import { formatFoldersTable } from './folders-format.js';
12
+ import { findFolderEntry, isValidAlias, parseAddFlags } from './folders-shared.js';
13
+ export async function handleList(store, rest, stdout, stderr) {
14
+ let asJson = false;
15
+ let tagFilter;
16
+ for (let i = 0; i < rest.length; i += 1) {
17
+ const arg = rest[i];
18
+ if (arg === '--json') {
19
+ asJson = true;
20
+ }
21
+ else if (arg === '--tag') {
22
+ const value = rest[i + 1];
23
+ if (value === undefined) {
24
+ stderr(`skillforge folders list: --tag requires a value\n`);
25
+ return 2;
26
+ }
27
+ tagFilter = value;
28
+ i += 1;
29
+ }
30
+ else {
31
+ stderr(`skillforge folders list: unknown flag: ${arg}\n`);
32
+ return 2;
33
+ }
34
+ }
35
+ const config = await store.load();
36
+ const folders = tagFilter !== undefined
37
+ ? config.folders.filter((f) => f.tags.includes(tagFilter))
38
+ : config.folders;
39
+ if (asJson) {
40
+ stdout(`${JSON.stringify({ folders }, null, 2)}\n`);
41
+ }
42
+ else {
43
+ stdout(formatFoldersTable(folders));
44
+ }
45
+ return 0;
46
+ }
47
+ export async function handleAdd(store, rest, stdout, stderr, isDirectory) {
48
+ const rawPath = rest[0];
49
+ if (rawPath === undefined || rawPath.startsWith('--')) {
50
+ stderr(`skillforge folders add: missing <path>\n`);
51
+ return 2;
52
+ }
53
+ const flags = parseAddFlags(rest.slice(1));
54
+ if (flags === null) {
55
+ stderr(`skillforge folders add: invalid or malformed flag\n`);
56
+ return 2;
57
+ }
58
+ if (flags.alias !== undefined && !isValidAlias(flags.alias)) {
59
+ stderr(`skillforge folders add: invalid --alias "${flags.alias}" — use kebab-case (e.g. my-folder)\n`);
60
+ return 2;
61
+ }
62
+ const absPath = resolve(rawPath);
63
+ if (!(await isDirectory(absPath))) {
64
+ stderr(`skillforge folders add: path does not exist or is not a directory: ${absPath}\n`);
65
+ return 1;
66
+ }
67
+ const config = await store.load();
68
+ const alreadyPresent = config.folders.some((f) => resolve(f.path) === absPath);
69
+ if (alreadyPresent) {
70
+ stdout(`Folder already registered: ${absPath}\n`);
71
+ return 0;
72
+ }
73
+ if (flags.alias !== undefined) {
74
+ const aliasTaken = config.folders.some((f) => f.alias === flags.alias);
75
+ if (aliasTaken) {
76
+ stderr(`skillforge folders add: alias already in use: ${flags.alias}\n`);
77
+ return 2;
78
+ }
79
+ }
80
+ const entry = {
81
+ path: absPath,
82
+ priority: flags.priority ?? 100,
83
+ enabled: !flags.disabled,
84
+ tags: flags.tags ?? [],
85
+ ...(flags.alias !== undefined ? { alias: flags.alias } : {}),
86
+ };
87
+ config.folders.push(entry);
88
+ await store.save(config);
89
+ stdout(`Registered folder: ${absPath}\n`);
90
+ // Informational only: a conflict does not block the add or change the exit code.
91
+ const conflict = await detectSkillSourceConflict(absPath);
92
+ if (conflict !== null) {
93
+ stdout(`${formatConflictHint(conflict)}\n`);
94
+ }
95
+ return 0;
96
+ }
97
+ export async function handleRemove(store, rest, stdout, stderr) {
98
+ const token = rest[0];
99
+ if (token === undefined || token.startsWith('--')) {
100
+ stderr(`skillforge folders remove: missing <path>\n`);
101
+ return 2;
102
+ }
103
+ const config = await store.load();
104
+ const entry = findFolderEntry(config.folders, token);
105
+ if (entry === null) {
106
+ stderr(`skillforge folders remove: no registered folder matches: ${token}\n`);
107
+ return 1;
108
+ }
109
+ config.folders = config.folders.filter((f) => f !== entry);
110
+ await store.save(config);
111
+ stdout(`Removed folder: ${entry.path}\n`);
112
+ return 0;
113
+ }
114
+ export async function handleAlias(store, rest, stdout, stderr) {
115
+ const token = rest[0];
116
+ const name = rest[1];
117
+ if (token === undefined || token.startsWith('--') || name === undefined) {
118
+ stderr(`skillforge folders alias: usage: folders alias <path> <name>\n`);
119
+ return 2;
120
+ }
121
+ if (!isValidAlias(name)) {
122
+ stderr(`skillforge folders alias: invalid alias "${name}" — use kebab-case (e.g. my-folder)\n`);
123
+ return 2;
124
+ }
125
+ const config = await store.load();
126
+ const entry = findFolderEntry(config.folders, token);
127
+ if (entry === null) {
128
+ stderr(`skillforge folders alias: no registered folder matches: ${token}\n`);
129
+ return 1;
130
+ }
131
+ const aliasTaken = config.folders.some((f) => f !== entry && f.alias === name);
132
+ if (aliasTaken) {
133
+ stderr(`skillforge folders alias: alias already in use: ${name}\n`);
134
+ return 2;
135
+ }
136
+ entry.alias = name;
137
+ await store.save(config);
138
+ stdout(`Set alias "${name}" for folder: ${entry.path}\n`);
139
+ return 0;
140
+ }
141
+ export async function handleEnable(store, rest, stdout, stderr) {
142
+ const token = rest[0];
143
+ if (token === undefined || token.startsWith('--')) {
144
+ stderr(`skillforge folders enable: missing <path|alias>\n`);
145
+ return 2;
146
+ }
147
+ const config = await store.load();
148
+ const entry = findFolderEntry(config.folders, token);
149
+ if (entry === null) {
150
+ stderr(`skillforge folders enable: no registered folder matches: ${token}\n`);
151
+ return 1;
152
+ }
153
+ entry.enabled = true;
154
+ await store.save(config);
155
+ stdout(`Enabled folder: ${entry.path}\n`);
156
+ return 0;
157
+ }
158
+ export async function handleDisable(store, rest, stdout, stderr) {
159
+ const token = rest[0];
160
+ if (token === undefined || token.startsWith('--')) {
161
+ stderr(`skillforge folders disable: missing <path|alias>\n`);
162
+ return 2;
163
+ }
164
+ const config = await store.load();
165
+ const entry = findFolderEntry(config.folders, token);
166
+ if (entry === null) {
167
+ stderr(`skillforge folders disable: no registered folder matches: ${token}\n`);
168
+ return 1;
169
+ }
170
+ entry.enabled = false;
171
+ await store.save(config);
172
+ stdout(`Disabled folder: ${entry.path}\n`);
173
+ return 0;
174
+ }
175
+ export async function handleReset(store, rest, stdout, stderr) {
176
+ const confirmed = rest.includes('--yes');
177
+ for (const arg of rest) {
178
+ if (arg !== '--yes') {
179
+ stderr(`skillforge folders reset: unknown flag: ${arg}\n`);
180
+ return 2;
181
+ }
182
+ }
183
+ if (!confirmed) {
184
+ const config = await store.load();
185
+ stdout(`Would reset ${config.folders.length} folder(s) to the default (empty) list.\n` +
186
+ `Re-run with --yes to apply. No changes were made.\n`);
187
+ return 0;
188
+ }
189
+ const config = await store.load();
190
+ config.folders = defaultConfig().folders;
191
+ await store.save(config);
192
+ stdout(`Reset folders to the default (empty) list.\n`);
193
+ return 0;
194
+ }
195
+ //# sourceMappingURL=folders-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders-handlers.js","sourceRoot":"","sources":["../../src/cli/folders-handlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Shared helpers for the `folders` subcommand modules.
3
+ *
4
+ * Holds pure parsing/lookup logic split out of `folders.ts` so the entry
5
+ * module stays small and the handler modules can reuse it.
6
+ */
7
+ import type { FolderEntry } from '../config/config-schema.js';
8
+ /** Kebab-case shape required for a folder alias (lowercase words joined by `-`). */
9
+ export declare const ALIAS_PATTERN: RegExp;
10
+ /** Whether `name` is a valid kebab-case alias token. */
11
+ export declare function isValidAlias(name: string): boolean;
12
+ /** Check whether a path exists and is a directory. Overridable for tests. */
13
+ export declare function defaultIsDirectory(p: string): Promise<boolean>;
14
+ /**
15
+ * Locate a registered folder by `token`, matching an alias first and falling
16
+ * back to a resolved-path comparison. Shared so `remove`/`alias` address the
17
+ * same entry the same way.
18
+ */
19
+ export declare function findFolderEntry(folders: FolderEntry[], token: string): FolderEntry | null;
20
+ /** Parsed result of the flags accepted by `add`. */
21
+ export interface ParsedAddFlags {
22
+ priority?: number;
23
+ tags?: string[];
24
+ disabled: boolean;
25
+ alias?: string;
26
+ }
27
+ /** Parse the flags accepted by `add`. Returns null on a malformed flag. */
28
+ export declare function parseAddFlags(args: string[]): ParsedAddFlags | null;
29
+ //# sourceMappingURL=folders-shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders-shared.d.ts","sourceRoot":"","sources":["../../src/cli/folders-shared.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,oFAAoF;AACpF,eAAO,MAAM,aAAa,QAA6B,CAAC;AAExD,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,6EAA6E;AAC7E,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOpE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAMzF;AAED,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,GAAG,IAAI,CAmCnE"}