@lyupro/skillforge-mcp 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +36 -0
- package/.claude-plugin/plugin.json +28 -0
- package/CHANGELOG.md +49 -0
- package/README.md +77 -9
- package/dist/cli/dispatcher.d.ts +40 -0
- package/dist/cli/dispatcher.d.ts.map +1 -0
- package/dist/cli/dispatcher.js +146 -0
- package/dist/cli/dispatcher.js.map +1 -0
- package/dist/cli/folders.d.ts +36 -0
- package/dist/cli/folders.d.ts.map +1 -0
- package/dist/cli/folders.js +249 -0
- package/dist/cli/folders.js.map +1 -0
- package/dist/cli/install.d.ts +2 -0
- package/dist/cli/install.d.ts.map +1 -1
- package/dist/cli/install.js +48 -10
- package/dist/cli/install.js.map +1 -1
- package/dist/cli/tools.d.ts +49 -0
- package/dist/cli/tools.d.ts.map +1 -0
- package/dist/cli/tools.js +171 -0
- package/dist/cli/tools.js.map +1 -0
- package/dist/detect/skill-source-conflict.d.ts +47 -0
- package/dist/detect/skill-source-conflict.d.ts.map +1 -0
- package/dist/detect/skill-source-conflict.js +99 -0
- package/dist/detect/skill-source-conflict.js.map +1 -0
- package/dist/installers/claude-installer.js +1 -1
- package/dist/installers/claude-installer.js.map +1 -1
- package/dist/installers/codex-installer.js +1 -1
- package/dist/installers/codex-installer.js.map +1 -1
- package/dist/installers/cursor-installer.d.ts +6 -7
- package/dist/installers/cursor-installer.d.ts.map +1 -1
- package/dist/installers/cursor-installer.js +16 -21
- package/dist/installers/cursor-installer.js.map +1 -1
- package/dist/installers/paths.d.ts +28 -6
- package/dist/installers/paths.d.ts.map +1 -1
- package/dist/installers/paths.js +72 -20
- package/dist/installers/paths.js.map +1 -1
- package/dist/installers/registry.d.ts +8 -2
- package/dist/installers/registry.d.ts.map +1 -1
- package/dist/installers/registry.js +14 -7
- package/dist/installers/registry.js.map +1 -1
- package/dist/tools/configure.d.ts +6 -0
- package/dist/tools/configure.d.ts.map +1 -1
- package/dist/tools/configure.js +3 -0
- package/dist/tools/configure.js.map +1 -1
- package/manifest.json +4 -3
- package/package.json +5 -4
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-marketplace.json",
|
|
3
|
+
"name": "skillforge",
|
|
4
|
+
"description": "SkillForge — universal Markdown skills for Claude Code and any MCP client.",
|
|
5
|
+
"owner": {
|
|
6
|
+
"name": "Lyu Pro",
|
|
7
|
+
"email": "lyupro.dev@gmail.com"
|
|
8
|
+
},
|
|
9
|
+
"plugins": [
|
|
10
|
+
{
|
|
11
|
+
"name": "skillforge",
|
|
12
|
+
"source": {
|
|
13
|
+
"source": "npm",
|
|
14
|
+
"package": "@lyupro/skillforge-mcp"
|
|
15
|
+
},
|
|
16
|
+
"description": "Universal Skills MCP server — load Markdown skills from arbitrary folders, lazy-by-design, cross-tool.",
|
|
17
|
+
"version": "1.2.0",
|
|
18
|
+
"author": {
|
|
19
|
+
"name": "Lyu Pro",
|
|
20
|
+
"email": "lyupro.dev@gmail.com"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/lyupro/skillforge-mcp",
|
|
23
|
+
"repository": "https://github.com/lyupro/skillforge-mcp",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"keywords": [
|
|
26
|
+
"skills",
|
|
27
|
+
"mcp",
|
|
28
|
+
"productivity",
|
|
29
|
+
"developer-tools",
|
|
30
|
+
"cross-tool",
|
|
31
|
+
"lazy-loading"
|
|
32
|
+
],
|
|
33
|
+
"category": "productivity"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
|
+
"name": "skillforge",
|
|
4
|
+
"version": "1.2.0",
|
|
5
|
+
"description": "Universal Skills MCP server — load Markdown skills from arbitrary folders, lazy-by-design, cross-tool.",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Lyu Pro",
|
|
8
|
+
"email": "lyupro.dev@gmail.com",
|
|
9
|
+
"url": "https://lyupro.com"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/lyupro/skillforge-mcp",
|
|
12
|
+
"repository": "https://github.com/lyupro/skillforge-mcp",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"skills",
|
|
16
|
+
"mcp",
|
|
17
|
+
"productivity",
|
|
18
|
+
"developer-tools",
|
|
19
|
+
"cross-tool",
|
|
20
|
+
"lazy-loading"
|
|
21
|
+
],
|
|
22
|
+
"mcpServers": {
|
|
23
|
+
"skillforge": {
|
|
24
|
+
"command": "node",
|
|
25
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/cli/dispatcher.js", "serve"]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,53 @@
|
|
|
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.2.0] — 2026-05-16
|
|
6
|
+
|
|
7
|
+
Terminal-side tooling — inspect MCP tools and manage skill folders without an LLM session, plus repo-local install scope and Claude Code plugin packaging.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `skillforge tools` CLI subcommand — prints the 5 MCP tools the server exposes (`skills__list`, `skills__get`, `skills__invoke`, `skills__configure`, `skills__reload`) with each tool's description, parameters, and an example invocation. Pass `--json` for machine-readable output. Lets you confirm the tool surface without starting an LLM session.
|
|
12
|
+
- `skillforge folders` CLI subcommand — manage skill folders from the terminal: `folders list [--json]`, `folders add <path> [--priority N] [--tags a,b] [--disabled]`, `folders remove <path>`, `folders reset --yes`. Previously folder management was only reachable via the `skills__configure` MCP tool inside an LLM session; both surfaces now read and write the same persisted config.
|
|
13
|
+
- `--scope global|project` flag on `skillforge install` / `skillforge uninstall`. The default `global` scope edits each host's home-directory config (unchanged behavior). `--scope project` wires SkillForge into a repo-local config rooted at the current directory — `.mcp.json` (Claude Code), `.codex/config.toml` (Codex CLI), `.cursor/mcp.json` (Cursor).
|
|
14
|
+
- Skill-source conflict detection. Registering a folder that already lives inside another tool's native skill store (a Claude Code plugin cache or a Gemini CLI extension) now surfaces a hint to disable the duplicate source — otherwise the same skills load twice and skill names collide. The `folders add` CLI prints the hint; the `skills__configure` `add_folder` action returns it as a `conflictHint` field. The conflict is informational only — it never blocks the folder from being added, and SkillForge never edits another tool's config.
|
|
15
|
+
- Claude Code plugin packaging — `.claude-plugin/plugin.json` and `.claude-plugin/marketplace.json`. SkillForge can now be installed via `claude plugin install` (rich `/plugins` UI card) in addition to `claude mcp add` and `skillforge install`.
|
|
16
|
+
|
|
17
|
+
### Verified
|
|
18
|
+
|
|
19
|
+
- 535 / 535 tests passing + 1 win32-skip.
|
|
20
|
+
- `pnpm lint` (`tsc --noEmit`) clean.
|
|
21
|
+
- `pnpm build` clean.
|
|
22
|
+
- `pnpm check:size` — all source files ≤ 400 lines.
|
|
23
|
+
|
|
24
|
+
## [1.1.1] — 2026-05-15
|
|
25
|
+
|
|
26
|
+
Single-bin dispatcher — fixes `npx @lyupro/skillforge-mcp install --all` hanging on stdin.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- `npx @lyupro/skillforge-mcp install ...` previously hung because the package shipped two bins (`skillforge-mcp` → server, `skillforge` → install CLI), and `npx` matched the package's unscoped basename to the server bin, which silently waited on stdio. Both bins now resolve to a unified dispatcher that routes by the first positional argument.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- `src/cli/dispatcher.ts` — single CLI entry point that routes between `serve`, `install`, `uninstall`, `--help`, and `--version`.
|
|
35
|
+
- `skillforge-mcp serve` subcommand — explicit invocation of the MCP stdio server (default when no command is supplied).
|
|
36
|
+
- `skillforge-mcp --version` — prints the package version.
|
|
37
|
+
- Dispatcher unit tests covering help, version, serve routing, install/uninstall delegation, and unknown-command rejection.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- `package.json#bin` — both `skillforge-mcp` and `skillforge` now point at `dist/cli/dispatcher.js`.
|
|
42
|
+
- `manifest.json#runtime.entry` — `dist/cli/dispatcher.js`. MCP host configs that auto-detect the entry pick up the dispatcher and fall through to `serve` when invoked with no args.
|
|
43
|
+
- Installer-generated host config entries now write `args: ['-y', '@lyupro/skillforge-mcp', 'serve']` explicitly. Older `['-y', '@lyupro/skillforge-mcp']` entries still work — the default subcommand resolves to `serve`.
|
|
44
|
+
|
|
45
|
+
### Verified
|
|
46
|
+
|
|
47
|
+
- All existing tests passing + dispatcher suite added.
|
|
48
|
+
- `pnpm lint` (`tsc --noEmit`) clean.
|
|
49
|
+
- `pnpm build` clean.
|
|
50
|
+
- Manual smoke test from a fresh shell: `npx --yes @lyupro/skillforge-mcp@1.1.1 install --all --dry-run` outputs planned edits and exits cleanly.
|
|
51
|
+
|
|
5
52
|
## [1.1.0] — 2026-05-14
|
|
6
53
|
|
|
7
54
|
One-command install across Claude Code, Codex CLI, and Cursor.
|
|
@@ -110,5 +157,7 @@ All 10 verified through real parse pipeline + `StrategyFactory.create()` correct
|
|
|
110
157
|
- **`pnpm build`** clean.
|
|
111
158
|
- **`pnpm smoke`** end-to-end via subprocess `dist/server.js` — LoggingDecorator trace visible.
|
|
112
159
|
|
|
160
|
+
[1.2.0]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.2.0
|
|
161
|
+
[1.1.1]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.1.1
|
|
113
162
|
[1.1.0]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.1.0
|
|
114
163
|
[1.0.0]: https://github.com/lyupro/skillforge-mcp/releases/tag/v1.0.0
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://nodejs.org)
|
|
7
7
|
[](https://modelcontextprotocol.io)
|
|
8
8
|
|
|
9
|
-
**v1.
|
|
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).
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -25,21 +25,37 @@ One skill folder. One config file. Any tool can ask for any skill on demand.
|
|
|
25
25
|
| No cross-tool format | Each tool ships its own skill layout | Universal frontmatter parser auto-detects Claude / Codex / persona / custom dialects |
|
|
26
26
|
| Skill execution = "just inline body in prompt" | No scripts, no caching, no timeouts, no composition | Strategy pattern (prompt / script / hybrid) + decorator chain (logging → timeout → cache) + composite skills with cycle detection |
|
|
27
27
|
|
|
28
|
-
## One-command install
|
|
28
|
+
## One-command install
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
31
|
npx @lyupro/skillforge-mcp install --all
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
Auto-detects Claude Code, Codex CLI, and Cursor on your machine and wires SkillForge into each. Supports `--dry-run`, `--uninstall`, and `--force`.
|
|
34
|
+
Auto-detects Claude Code, Codex CLI, and Cursor on your machine and wires SkillForge into each. Supports `--dry-run`, `--uninstall`, and `--force`.
|
|
35
|
+
|
|
36
|
+
By default the installer edits each host's global config. Pass `--scope project` to wire SkillForge into a repo-local config rooted at the current directory instead — `.mcp.json` (Claude Code), `.codex/config.toml` (Codex CLI), `.cursor/mcp.json` (Cursor):
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx @lyupro/skillforge-mcp install --all --scope project
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Full reference: [docs/INSTALL_CLI.md](./docs/INSTALL_CLI.md).
|
|
35
43
|
|
|
36
44
|
## Quick Start
|
|
37
45
|
|
|
38
|
-
### Option 1 — Claude Code
|
|
46
|
+
### Option 1 — Claude Code plugin (recommended)
|
|
47
|
+
|
|
48
|
+
SkillForge ships a Claude Code plugin manifest, so it installs through the native `/plugins` UI with a rich plugin card:
|
|
39
49
|
|
|
40
50
|
```bash
|
|
41
|
-
/plugin marketplace add lyupro/
|
|
42
|
-
/plugin install skillforge
|
|
51
|
+
/plugin marketplace add lyupro/skillforge-mcp
|
|
52
|
+
/plugin install skillforge
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or install it directly:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
claude plugin install skillforge@lyupro/skillforge-mcp
|
|
43
59
|
```
|
|
44
60
|
|
|
45
61
|
Restart your Claude Code session. The five tools (`skills__list`, `skills__get`, `skills__invoke`, `skills__configure`, `skills__reload`) appear in the tool list.
|
|
@@ -50,7 +66,11 @@ Restart your Claude Code session. The five tools (`skills__list`, `skills__get`,
|
|
|
50
66
|
claude mcp add skillforge -- npx -y @lyupro/skillforge-mcp
|
|
51
67
|
```
|
|
52
68
|
|
|
53
|
-
Works for any MCP host that can spawn a stdio command (Claude Code, Codex CLI, Cursor).
|
|
69
|
+
Works for any MCP host that can spawn a stdio command (Claude Code, Codex CLI, Cursor). Or let the install CLI wire every detected host at once:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx -y @lyupro/skillforge-mcp install --all
|
|
73
|
+
```
|
|
54
74
|
|
|
55
75
|
### Option 3 — local build
|
|
56
76
|
|
|
@@ -75,6 +95,54 @@ After the install step, run these three checks from inside any wired LLM tool se
|
|
|
75
95
|
|
|
76
96
|
If any call fails with `[skillforge] fatal:` on stderr, the most likely cause is a corrupt config file or a missing folder path — the error message points at the offending file. Delete or fix `~/.lyupro/.skillforge/config.json` and retry.
|
|
77
97
|
|
|
98
|
+
## CLI commands
|
|
99
|
+
|
|
100
|
+
The `skillforge` / `skillforge-mcp` binary is a dispatcher — the first positional argument selects a subcommand. Run `skillforge --help` for the full list.
|
|
101
|
+
|
|
102
|
+
| Command | Purpose |
|
|
103
|
+
|---------|---------|
|
|
104
|
+
| `serve` | Run the stdio MCP server. Default when no command is given. |
|
|
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
|
+
| `uninstall` | Reverse a previous install. Accepts the same `--scope global\|project` flag. |
|
|
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`. |
|
|
109
|
+
| `--version`, `-v` | Print the package version. |
|
|
110
|
+
| `--help`, `-h` | Print combined usage. |
|
|
111
|
+
|
|
112
|
+
### Inspect the MCP tools — `skillforge tools`
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
skillforge tools # human-readable reference
|
|
116
|
+
skillforge tools --json # machine-readable: { "tools": [ ... ] }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Prints every MCP tool the server exposes (`skills__list`, `skills__get`, `skills__invoke`, `skills__configure`, `skills__reload`) with its description, parameters, and an example invocation — handy for confirming the surface without starting a session.
|
|
120
|
+
|
|
121
|
+
### Manage skill folders from the terminal — `skillforge folders`
|
|
122
|
+
|
|
123
|
+
Folder management is also available from the shell, not just via the `skills__configure` MCP tool inside an LLM session:
|
|
124
|
+
|
|
125
|
+
```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
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`add` flags:
|
|
133
|
+
|
|
134
|
+
- `--priority <n>` — folder priority (default `100`; higher wins on name collisions).
|
|
135
|
+
- `--tags <a,b,c>` — comma-separated tags.
|
|
136
|
+
- `--disabled` — register the folder disabled.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
skillforge folders add ~/.lyupro/skills --priority 50 --tags work,review
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`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
|
+
|
|
144
|
+
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.
|
|
145
|
+
|
|
78
146
|
## MCP tool surface
|
|
79
147
|
|
|
80
148
|
| Tool | Purpose |
|
|
@@ -166,8 +234,8 @@ For production use with untrusted skill authors, run SkillForge inside Docker or
|
|
|
166
234
|
## Updating
|
|
167
235
|
|
|
168
236
|
```bash
|
|
169
|
-
#
|
|
170
|
-
/plugin update skillforge
|
|
237
|
+
# Plugin install
|
|
238
|
+
/plugin update skillforge
|
|
171
239
|
|
|
172
240
|
# npm install
|
|
173
241
|
claude mcp remove skillforge
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* SkillForge MCP CLI dispatcher.
|
|
4
|
+
*
|
|
5
|
+
* Single entry point for the `skillforge-mcp` and `skillforge` bins. Routes
|
|
6
|
+
* by the first positional argument so a single binary can act as both the
|
|
7
|
+
* MCP stdio server and the install CLI.
|
|
8
|
+
*
|
|
9
|
+
* skillforge-mcp install [flags] Wire SkillForge into host configs
|
|
10
|
+
* skillforge-mcp uninstall [flags] Reverse a previous install
|
|
11
|
+
* skillforge-mcp serve Run the MCP stdio server (default)
|
|
12
|
+
* skillforge-mcp [no args] Same as `serve`
|
|
13
|
+
* skillforge-mcp --help Print combined usage
|
|
14
|
+
* skillforge-mcp --version Print package version
|
|
15
|
+
*
|
|
16
|
+
* Why dispatcher exists:
|
|
17
|
+
* `npx @scope/foo <subcommand>` matches a single bin by the package's
|
|
18
|
+
* unscoped basename (`foo`). The earlier release shipped two separate
|
|
19
|
+
* bins (`skillforge-mcp` → server, `skillforge` → install CLI). The
|
|
20
|
+
* README-recommended `npx @lyupro/skillforge-mcp install --all` therefore
|
|
21
|
+
* resolved to the server bin, which silently waited on stdin while users
|
|
22
|
+
* thought the installer had hung. This dispatcher collapses both bins
|
|
23
|
+
* into one and routes by argv, so the documented quick-start works
|
|
24
|
+
* without an `--package=` override.
|
|
25
|
+
*/
|
|
26
|
+
export declare function readPackageVersion(): Promise<string>;
|
|
27
|
+
export interface ServeDeps {
|
|
28
|
+
start: () => Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Dispatcher entry. Returns:
|
|
32
|
+
* - exit code (number) for install/uninstall/help/version/unknown — caller
|
|
33
|
+
* should `process.exit(code)`.
|
|
34
|
+
* - null for serve — caller must NOT call process.exit; the server keeps
|
|
35
|
+
* the event loop alive via stdio transport + signal handlers.
|
|
36
|
+
*/
|
|
37
|
+
export declare function main(rawArgv: string[], overrides?: {
|
|
38
|
+
startServe?: () => Promise<void>;
|
|
39
|
+
}): Promise<number | null>;
|
|
40
|
+
//# sourceMappingURL=dispatcher.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* SkillForge MCP CLI dispatcher.
|
|
4
|
+
*
|
|
5
|
+
* Single entry point for the `skillforge-mcp` and `skillforge` bins. Routes
|
|
6
|
+
* by the first positional argument so a single binary can act as both the
|
|
7
|
+
* MCP stdio server and the install CLI.
|
|
8
|
+
*
|
|
9
|
+
* skillforge-mcp install [flags] Wire SkillForge into host configs
|
|
10
|
+
* skillforge-mcp uninstall [flags] Reverse a previous install
|
|
11
|
+
* skillforge-mcp serve Run the MCP stdio server (default)
|
|
12
|
+
* skillforge-mcp [no args] Same as `serve`
|
|
13
|
+
* skillforge-mcp --help Print combined usage
|
|
14
|
+
* skillforge-mcp --version Print package version
|
|
15
|
+
*
|
|
16
|
+
* Why dispatcher exists:
|
|
17
|
+
* `npx @scope/foo <subcommand>` matches a single bin by the package's
|
|
18
|
+
* unscoped basename (`foo`). The earlier release shipped two separate
|
|
19
|
+
* bins (`skillforge-mcp` → server, `skillforge` → install CLI). The
|
|
20
|
+
* README-recommended `npx @lyupro/skillforge-mcp install --all` therefore
|
|
21
|
+
* resolved to the server bin, which silently waited on stdin while users
|
|
22
|
+
* thought the installer had hung. This dispatcher collapses both bins
|
|
23
|
+
* into one and routes by argv, so the documented quick-start works
|
|
24
|
+
* without an `--package=` override.
|
|
25
|
+
*/
|
|
26
|
+
import { main as installMain } from './install.js';
|
|
27
|
+
import { main as toolsMain } from './tools.js';
|
|
28
|
+
import { main as foldersMain } from './folders.js';
|
|
29
|
+
const USAGE = `skillforge-mcp — universal Skills MCP server + install CLI.
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
skillforge-mcp <command> [flags]
|
|
33
|
+
|
|
34
|
+
Commands:
|
|
35
|
+
serve Run the stdio MCP server. Default when no command is given.
|
|
36
|
+
Example: skillforge-mcp serve
|
|
37
|
+
install Wire SkillForge into Claude Code / Codex CLI / Cursor.
|
|
38
|
+
Defaults to the host's global config; pass --scope project to
|
|
39
|
+
edit a repo-local config rooted at the current directory.
|
|
40
|
+
Run "skillforge-mcp install --help" for installer flags.
|
|
41
|
+
Example: skillforge-mcp install --all
|
|
42
|
+
Example: skillforge-mcp install --all --scope project
|
|
43
|
+
uninstall Reverse a previous install. Forwards to "install --uninstall".
|
|
44
|
+
Accepts the same --scope global|project flag.
|
|
45
|
+
Example: skillforge-mcp uninstall --all
|
|
46
|
+
tools List the 5 MCP tools the server exposes (params + examples).
|
|
47
|
+
Pass --json for machine-readable output.
|
|
48
|
+
Example: skillforge-mcp tools --json
|
|
49
|
+
folders Manage skill folders from the terminal (list/add/remove/reset).
|
|
50
|
+
Run "skillforge-mcp folders" for sub-action usage.
|
|
51
|
+
Example: skillforge-mcp folders add ~/.lyupro/skills
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
--help, -h Show this message.
|
|
55
|
+
--version, -v Print the package version.
|
|
56
|
+
Example: skillforge-mcp --version
|
|
57
|
+
|
|
58
|
+
Quick start:
|
|
59
|
+
npx -y @lyupro/skillforge-mcp install --all
|
|
60
|
+
npx -y @lyupro/skillforge-mcp install --all --dry-run
|
|
61
|
+
`;
|
|
62
|
+
export async function readPackageVersion() {
|
|
63
|
+
const { readFile } = await import('node:fs/promises');
|
|
64
|
+
const { fileURLToPath } = await import('node:url');
|
|
65
|
+
const { dirname, resolve } = await import('node:path');
|
|
66
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
67
|
+
// dist/cli/dispatcher.js → package.json is two levels up.
|
|
68
|
+
const pkgPath = resolve(here, '..', '..', 'package.json');
|
|
69
|
+
const raw = await readFile(pkgPath, 'utf8');
|
|
70
|
+
const parsed = JSON.parse(raw);
|
|
71
|
+
if (typeof parsed.version !== 'string') {
|
|
72
|
+
throw new Error('package.json missing string "version" field');
|
|
73
|
+
}
|
|
74
|
+
return parsed.version;
|
|
75
|
+
}
|
|
76
|
+
async function defaultStartServe() {
|
|
77
|
+
const { buildDeps, buildServer } = await import('../server.js');
|
|
78
|
+
const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
|
|
79
|
+
const deps = await buildDeps();
|
|
80
|
+
const server = buildServer(deps);
|
|
81
|
+
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
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Dispatcher entry. Returns:
|
|
95
|
+
* - exit code (number) for install/uninstall/help/version/unknown — caller
|
|
96
|
+
* should `process.exit(code)`.
|
|
97
|
+
* - null for serve — caller must NOT call process.exit; the server keeps
|
|
98
|
+
* the event loop alive via stdio transport + signal handlers.
|
|
99
|
+
*/
|
|
100
|
+
export async function main(rawArgv, overrides = {}) {
|
|
101
|
+
const first = rawArgv[0];
|
|
102
|
+
if (first === '--help' || first === '-h') {
|
|
103
|
+
process.stdout.write(USAGE);
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
if (first === '--version' || first === '-v') {
|
|
107
|
+
const version = await readPackageVersion();
|
|
108
|
+
process.stdout.write(`${version}\n`);
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
if (first === 'install') {
|
|
112
|
+
return installMain(rawArgv.slice(1));
|
|
113
|
+
}
|
|
114
|
+
if (first === 'uninstall') {
|
|
115
|
+
return installMain(['--uninstall', ...rawArgv.slice(1)]);
|
|
116
|
+
}
|
|
117
|
+
if (first === 'tools') {
|
|
118
|
+
return toolsMain(rawArgv.slice(1));
|
|
119
|
+
}
|
|
120
|
+
if (first === 'folders') {
|
|
121
|
+
return foldersMain(rawArgv.slice(1));
|
|
122
|
+
}
|
|
123
|
+
if (first === 'serve' || first === undefined) {
|
|
124
|
+
const start = overrides.startServe ?? defaultStartServe;
|
|
125
|
+
await start();
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
process.stderr.write(`skillforge-mcp: unknown command: ${first}\n\n${USAGE}`);
|
|
129
|
+
return 2;
|
|
130
|
+
}
|
|
131
|
+
import { fileURLToPath } from 'node:url';
|
|
132
|
+
const isDirectRun = process.argv[1] !== undefined &&
|
|
133
|
+
fileURLToPath(import.meta.url) === process.argv[1];
|
|
134
|
+
if (isDirectRun) {
|
|
135
|
+
main(process.argv.slice(2))
|
|
136
|
+
.then((code) => {
|
|
137
|
+
if (code !== null)
|
|
138
|
+
process.exit(code);
|
|
139
|
+
})
|
|
140
|
+
.catch((err) => {
|
|
141
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
142
|
+
console.error(`[skillforge-mcp] fatal: ${msg}`);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/cli/dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* SkillForge `folders` subcommand.
|
|
4
|
+
*
|
|
5
|
+
* Terminal-side skill-folder management. Without this, folders could only
|
|
6
|
+
* be registered from inside an LLM session via the `skills__configure` MCP
|
|
7
|
+
* tool. This subcommand exposes the same `ConfigStore` folder operations
|
|
8
|
+
* (load → mutate → save) to the shell — no separate config logic.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* skillforge folders list [--json] List registered folders
|
|
12
|
+
* skillforge folders add <path> [flags] Register a folder
|
|
13
|
+
* skillforge folders remove <path> Remove a folder entry
|
|
14
|
+
* skillforge folders reset --yes Reset folders to default
|
|
15
|
+
*
|
|
16
|
+
* add flags:
|
|
17
|
+
* --priority <n> Folder priority (default 100, lower wins ordering).
|
|
18
|
+
* --tags <a,b,c> Comma-separated tags.
|
|
19
|
+
* --disabled Register the folder disabled.
|
|
20
|
+
*/
|
|
21
|
+
export interface FoldersDeps {
|
|
22
|
+
stdout?: (text: string) => void;
|
|
23
|
+
stderr?: (text: string) => void;
|
|
24
|
+
/** Override the config file path — tests inject a temp path here. */
|
|
25
|
+
configPath?: string;
|
|
26
|
+
/** Check whether a path exists and is a directory. Overridable for tests. */
|
|
27
|
+
isDirectory?: (p: string) => Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* `folders` subcommand entry. Returns an exit code:
|
|
31
|
+
* - 0 on success
|
|
32
|
+
* - 1 on a runtime/validation failure (e.g. bad path)
|
|
33
|
+
* - 2 on a missing/unknown sub-action or malformed flag
|
|
34
|
+
*/
|
|
35
|
+
export declare function main(rawArgv: string[], deps?: FoldersDeps): Promise<number>;
|
|
36
|
+
//# sourceMappingURL=folders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folders.d.ts","sourceRoot":"","sources":["../../src/cli/folders.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG;AAYH,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/C;AAwND;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgCrF"}
|