@heytherevibin/skillforge 0.7.0 → 0.10.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/CHANGELOG.md +29 -0
- package/CONTRIBUTING.md +30 -19
- package/README.md +248 -198
- package/RELEASING.md +19 -7
- package/SECURITY.md +61 -13
- package/STRATEGY.md +40 -14
- package/bin/cli.js +112 -5
- package/ci/bundle-gate.json +4 -0
- package/lib/host-setup.js +312 -0
- package/lib/templates/claude-code-skillforge-global.md +19 -0
- package/lib/templates/cursor-skillforge-global.md +16 -0
- package/package.json +3 -2
- package/python/app/eval_cli.py +133 -0
- package/python/app/feedback_meta.py +96 -0
- package/python/app/health_cli.py +160 -0
- package/python/app/main.py +502 -26
- package/python/app/materialize.py +72 -4
- package/python/app/mcp_contract.py +13 -1
- package/python/app/mcp_server.py +344 -25
- package/python/app/route_cli.py +32 -13
- package/python/app/route_eval_harness.py +98 -0
- package/python/app/route_policies.py +243 -0
- package/python/app/route_quality.py +99 -0
- package/python/app/routing_signals.py +155 -0
- package/python/app/weights_cli.py +152 -0
- package/python/fixtures/route_eval/smoke.json +18 -0
- package/python/requirements.txt +1 -0
- package/python/tests/test_feedback_weights.py +77 -0
- package/python/tests/test_materialize.py +51 -0
- package/python/tests/test_mcp_contract.py +117 -0
- package/python/tests/test_route_eval_harness.py +45 -0
- package/python/tests/test_route_policies.py +115 -0
- package/python/tests/test_route_quality.py +120 -0
- package/python/tests/test_routing_overlay.py +55 -0
- package/python/tests/test_routing_signals.py +112 -0
package/RELEASING.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
| Workflow | File | When it runs |
|
|
6
6
|
|----------|------|----------------|
|
|
7
7
|
| **CI** | [.github/workflows/ci.yml](.github/workflows/ci.yml) | Every **push** and **pull request** to `main`; also **`workflow_dispatch`** (run manually from the Actions tab) |
|
|
8
|
-
| **Skillforge release** | [.github/workflows/release.yml](.github/workflows/release.yml) | When a **`v*`** tag is **pushed** to the repository (e.g. `v0.
|
|
8
|
+
| **Skillforge release** | [.github/workflows/release.yml](.github/workflows/release.yml) | When a **`v*`** tag is **pushed** to the repository (e.g. `v0.10.0`) |
|
|
9
9
|
|
|
10
10
|
In the GitHub UI, open **Actions** and look for **CI** and **Skillforge release** (not the older “publish to npm” name).
|
|
11
11
|
|
|
@@ -28,14 +28,14 @@ You need the **`NPM_TOKEN`** repository secret.
|
|
|
28
28
|
|
|
29
29
|
Create one at [npm → Access Tokens](https://www.npmjs.com/settings/~/tokens) (**Generate New Token** → **Granular Access Token**). Optionally explore [**trusted publishing** (OIDC)](https://docs.npmjs.com/trusted-publishers/) later to avoid long-lived tokens.
|
|
30
30
|
|
|
31
|
-
1. On `main`, set **`version`** in `package.json` to the version you are releasing (must be **unused** on npm — e.g. `0.
|
|
32
|
-
2. Match **MCP** `serverInfo.version` in `python/app/mcp_server.py` and add a **`CHANGELOG.md`** section for that version.
|
|
31
|
+
1. On `main`, set **`version`** in `package.json` to the version you are releasing (must be **unused** on npm — e.g. `0.10.0`).
|
|
32
|
+
2. Match **MCP** `serverInfo.version` in `python/app/mcp_server.py` (must equal `package.json`) and add a **`CHANGELOG.md`** section for that version.
|
|
33
33
|
3. Commit and **`git push origin main`**. Wait for **CI** to pass.
|
|
34
34
|
4. Create a tag whose name is **`v` + that exact version**:
|
|
35
|
-
`git tag v0.
|
|
35
|
+
`git tag v0.10.0 && git push origin v0.10.0`
|
|
36
36
|
5. Open **Actions → Skillforge release**. The job will **fail the version check** if the tag does not match `package.json`.
|
|
37
37
|
6. Confirm on npm: `npm view @heytherevibin/skillforge version`
|
|
38
|
-
Confirm the **GitHub Release** exists with title **`Skillforge <tag>`** (e.g. **`Skillforge v0.
|
|
38
|
+
Confirm the **GitHub Release** exists with title **`Skillforge <tag>`** (e.g. **`Skillforge v0.10.0`**) and the `.tgz` asset.
|
|
39
39
|
|
|
40
40
|
Scoped packages require a **public** publish; the workflow already runs `npm publish --access public`.
|
|
41
41
|
|
|
@@ -67,6 +67,10 @@ Typical causes: the tag was created before **Skillforge release** existed on `ma
|
|
|
67
67
|
1. Bump `version` in `package.json`, commit, push `main`.
|
|
68
68
|
2. Push a **new** tag: `v` + new version.
|
|
69
69
|
|
|
70
|
+
## Bundled skills gate
|
|
71
|
+
|
|
72
|
+
The **minimum** number of **`skills/**/**/SKILL.md`** files required in CI is **`ci/bundle-gate.json`** → **`minSkillMdFiles`**. Change that value when your distribution policy for the vendored catalog changes (do not edit the number inline in **`ci.yml`**).
|
|
73
|
+
|
|
70
74
|
## Local sanity checks (before push)
|
|
71
75
|
|
|
72
76
|
```bash
|
|
@@ -74,10 +78,18 @@ node --check bin/cli.js && node --check lib/packs.js
|
|
|
74
78
|
npm test
|
|
75
79
|
```
|
|
76
80
|
|
|
77
|
-
Python (syntax only):
|
|
81
|
+
Python (syntax only)—the **authoritative** module list is in **`.github/workflows/ci.yml`** (step “Check Python syntax”). Example:
|
|
78
82
|
|
|
79
83
|
```bash
|
|
80
|
-
for f in
|
|
84
|
+
for f in \
|
|
85
|
+
python/app/main.py python/app/mcp_server.py python/app/events_cli.py python/app/materialize.py \
|
|
86
|
+
python/app/db_paths.py python/app/route_cli.py python/app/mcp_contract.py python/app/chunking.py \
|
|
87
|
+
python/app/project_index.py python/app/index_cli.py python/app/context_fusion.py python/app/redaction.py \
|
|
88
|
+
python/app/route_policies.py python/app/routing_signals.py python/app/route_quality.py \
|
|
89
|
+
python/app/route_eval_harness.py python/app/eval_cli.py python/app/health_cli.py \
|
|
90
|
+
python/app/feedback_meta.py python/app/weights_cli.py; do
|
|
91
|
+
python3 -m py_compile "$f"
|
|
92
|
+
done
|
|
81
93
|
```
|
|
82
94
|
|
|
83
95
|
## Troubleshooting: `EOTP` / one-time password in CI
|
package/SECURITY.md
CHANGED
|
@@ -2,30 +2,78 @@
|
|
|
2
2
|
|
|
3
3
|
## Supported versions
|
|
4
4
|
|
|
5
|
-
Security fixes are applied to the **latest
|
|
5
|
+
Security fixes are applied to the **latest published release** on the default branch (**`main`**). Older release lines may not receive backports; upgrade to the current release when advisories apply.
|
|
6
6
|
|
|
7
7
|
## Reporting a vulnerability
|
|
8
8
|
|
|
9
|
-
Please **do not** open a public GitHub issue for undisclosed security vulnerabilities.
|
|
9
|
+
Please **do not** open a **public** GitHub issue for undisclosed security vulnerabilities.
|
|
10
10
|
|
|
11
11
|
**Preferred:** use [GitHub Security Advisories](https://github.com/heytherevibin/skillforge/security/advisories/new) for this repository (if you have access).
|
|
12
12
|
|
|
13
|
-
**Alternative:**
|
|
13
|
+
**Alternative:** **Security → Report a vulnerability** on the repository, or contact maintainers through channels published on their GitHub profiles.
|
|
14
14
|
|
|
15
15
|
Include:
|
|
16
16
|
|
|
17
|
-
- Description of the issue and impact
|
|
18
|
-
- Steps to reproduce (if known)
|
|
19
|
-
- Affected version or commit (if known)
|
|
17
|
+
- Description of the issue and assessed impact
|
|
18
|
+
- Steps to reproduce (if known)
|
|
19
|
+
- Affected **version**, **tag**, or **commit** (if known)
|
|
20
20
|
|
|
21
|
-
We aim to acknowledge valid reports within a few business days.
|
|
21
|
+
We aim to **acknowledge** valid reports within a few **business days**. Resolution timelines depend on severity and validation effort.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
---
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
- Keep **2FA** enabled on the npm account that owns the `@heytherevibin` scope.
|
|
27
|
-
- Prefer pinning action versions or reviewing Dependabot PRs before merge.
|
|
25
|
+
## Threat model (summary)
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
| Component | Exposure |
|
|
28
|
+
|-----------|-----------|
|
|
29
|
+
| **MCP stdio server** | Runs locally; accepts JSON-RPC from the parent **MCP host** process. Treat the host as part of your trust boundary. |
|
|
30
|
+
| **CLI** | Spawns Python modules with environment inherited from the shell; avoid untrusted **`PATH`** or wrapper scripts. |
|
|
31
|
+
| **SQLite databases** | Contain prompts (redacted where configured), events, embeddings metadata, and learning weights. Protect filesystem permissions and backups. |
|
|
32
|
+
| **Optional Anthropic API** | Outbound HTTPS when **`ANTHROPIC_API_KEY`** is set; prompts and router context may leave the machine per Anthropic’s policies. |
|
|
30
33
|
|
|
31
|
-
Skillforge
|
|
34
|
+
Skillforge does **not** implement network listening for the published OSS package (no HTTP API in current releases).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Data handling & privacy
|
|
39
|
+
|
|
40
|
+
- **Redaction** (`SKILLFORGE_REDACT_*`) is **pattern-based** and **best-effort**—not a substitute for data-classification or DLP controls.
|
|
41
|
+
- **Project routing notes** (`project_notes` / aliases in policies) are **prefixed** to the internal routing query only when **`project_root`** is set—reducing accidental global application from org-wide env JSON.
|
|
42
|
+
- Operators should assume **route events** and **`_meta`** may contain **sensitive path fragments** unless redaction is enabled and effective for their workload.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Secrets & configuration
|
|
47
|
+
|
|
48
|
+
- **Never commit** `ANTHROPIC_API_KEY`, npm **`NPM_TOKEN`**, or workspace tokens.
|
|
49
|
+
- Prefer **OS secret stores**, **CI secrets**, or MCP host **env injection**.
|
|
50
|
+
- Review **`policies.json`** and **`SKILLFORGE_ROUTE_POLICIES`** for **prompt injection** risk: notes influence embeddings for the declared project only, but can still steer retrieval.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Supply chain & distribution
|
|
55
|
+
|
|
56
|
+
### npm
|
|
57
|
+
|
|
58
|
+
- Use **granular access tokens** with the minimum scope required; enable **Bypass 2FA** only on dedicated automation tokens when CI publishing requires it (see [RELEASING.md](RELEASING.md)).
|
|
59
|
+
- Keep **2FA** enabled on maintainer accounts that own the **`@heytherevibin`** scope.
|
|
60
|
+
- Review **Dependabot** / dependency updates before merge for typosquatting and breaking changes.
|
|
61
|
+
|
|
62
|
+
### CI
|
|
63
|
+
|
|
64
|
+
- Workflows run with **`contents: read`** on the default **CI** job; verify **`release.yml`** permissions when extending publish steps.
|
|
65
|
+
- Prefer **pinned** major versions of third-party Actions or follow your org’s pinning policy.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Runtime hardening (recommended)
|
|
70
|
+
|
|
71
|
+
- Run Skillforge on **managed workstations** or **locked-down CI agents** appropriate to your data classification.
|
|
72
|
+
- Separate **production** and **development** orchestrator databases if weights or events must not mix.
|
|
73
|
+
- Periodically run **`skillforge health`** and **`skillforge route-eval`** after upgrades to validate embeddings and bundled catalog integrity in your environment.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Coordinated disclosure
|
|
78
|
+
|
|
79
|
+
If you are preparing **public** research or a conference talk that names Skillforge, please contact maintainers **before** the embargo date so fixes or guidance can ship alongside disclosures when appropriate.
|
package/STRATEGY.md
CHANGED
|
@@ -1,24 +1,50 @@
|
|
|
1
|
-
# Skillforge strategy
|
|
1
|
+
# Skillforge — product strategy
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Mission
|
|
4
4
|
|
|
5
|
-
Skillforge is
|
|
5
|
+
Skillforge is a **local, MCP-first orchestration layer** that selects a **small, relevant** subset of **`SKILL.md`** (and optional indexed project) context for each user task—so agent hosts can stay **grounded** without loading entire catalogs.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Principles
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
| Principle | Implication |
|
|
10
|
+
|-----------|-------------|
|
|
11
|
+
| **Local-first** | Default data plane is **SQLite** and **stdio MCP** on the operator’s machine. |
|
|
12
|
+
| **Explicit trust** | Optional **LLM** stages run only when keys and modes allow; **host** mode delegates final skill choice to the MCP client. |
|
|
13
|
+
| **Observable** | Versioned **`_meta`**, route **events**, and operator CLIs (**`events`**, **`health`**, **`route-eval`**) support enterprise debugging and CI gates. |
|
|
14
|
+
| **Portable learning** | Weights and feedback are **exportable**—suitable for backup, migration, and controlled restore. |
|
|
15
|
+
| **Governable** | **Regex policies** and **project overlays** (exclude, boost, notes) let platform teams steer routing without forking the catalog. |
|
|
11
16
|
|
|
12
|
-
##
|
|
17
|
+
## Primary surfaces
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
| Surface | Role |
|
|
20
|
+
|---------|------|
|
|
21
|
+
| **MCP (`skillforge mcp`)** | Integration for Claude, Cursor, Claude Code, and other JSON-RPC MCP hosts. |
|
|
22
|
+
| **CLI** | Parity routing, indexing, observability, preflight, eval harness, weights I/O. |
|
|
15
23
|
|
|
16
|
-
##
|
|
24
|
+
## Integration matrix
|
|
17
25
|
|
|
18
|
-
|
|
19
|
-
|
|
26
|
+
| Host capability | Skillforge pattern |
|
|
27
|
+
|-----------------|---------------------|
|
|
28
|
+
| **Project workspace** | Pass **`project_root`** so state and optional RAG live under **`.skillforge/`**. |
|
|
29
|
+
| **Strict context budgets** | Tune **`SKILLFORGE_CONTEXT_*`**, **`SKILLFORGE_ROUTE_MAX_CHARS`**, and project RAG caps. |
|
|
30
|
+
| **No LLM keys on router** | Use **`SKILLFORGE_ROUTER_MODE=embedding`** (or omit **`ANTHROPIC_API_KEY`** in auto mode). |
|
|
31
|
+
| **Human-in-the-loop picks** | **`SKILLFORGE_ROUTER_MODE=host`**: shortlist first, then **`picked_names`**. |
|
|
32
|
+
| **Org policy** | Central **`SKILLFORGE_ROUTE_POLICIES`** / file + per-repo **`policies.json`** with overlay keys. |
|
|
20
33
|
|
|
21
|
-
##
|
|
34
|
+
## Near-term themes
|
|
22
35
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
36
|
+
- Continue tightening **parity** between MCP tools and CLI (**routing**, **meta**, **policies**).
|
|
37
|
+
- Expand **fixture library** for **`route-eval`** as catalog and hybrid modes evolve.
|
|
38
|
+
- Optional: richer **enterprise** packaging (e.g. signed SBOM, pinned base images) as downstream consumers require—tracked outside this doc when scope is agreed.
|
|
39
|
+
|
|
40
|
+
## Non-goals
|
|
41
|
+
|
|
42
|
+
- Replacing the host model or owning end-user billing for conversations.
|
|
43
|
+
- Implicit network egress except **optional** model APIs (Anthropic) and **pack** git clones invoked explicitly by operators.
|
|
44
|
+
- A hosted multi-tenant SaaS as part of the core OSS package.
|
|
45
|
+
|
|
46
|
+
## References
|
|
47
|
+
|
|
48
|
+
- **Operator documentation:** [README.md](README.md)
|
|
49
|
+
- **Security posture:** [SECURITY.md](SECURITY.md)
|
|
50
|
+
- **Shipping checklist:** [RELEASING.md](RELEASING.md)
|
package/bin/cli.js
CHANGED
|
@@ -8,7 +8,12 @@
|
|
|
8
8
|
* skillforge events [--watch] [--limit=N] Print SQLite routing events
|
|
9
9
|
* skillforge route [words…] [--prompt=…] Same routing as MCP route_skills (terminal)
|
|
10
10
|
* skillforge index --project-root=… Chunk/embed repo files for project RAG
|
|
11
|
-
* skillforge
|
|
11
|
+
* skillforge health [--quick] [--json] Preflight: paths, catalog, optional router load
|
|
12
|
+
* skillforge route-eval --fixture=… Embedding-only regression cases (CI-friendly)
|
|
13
|
+
* skillforge weights export|import Snapshot learned weights (JSON)
|
|
14
|
+
* skillforge install One-time Python venv + deps (+ Cursor /skillforge when detected)
|
|
15
|
+
* skillforge hosts init [--force] Install global /skillforge for Cursor + Claude Code (no Python setup)
|
|
16
|
+
* skillforge cursor init [--force] Same as hosts init (alias)
|
|
12
17
|
* skillforge skills … / pack … / reset
|
|
13
18
|
*/
|
|
14
19
|
|
|
@@ -19,7 +24,9 @@ const os = require('os');
|
|
|
19
24
|
const packs = require('../lib/packs');
|
|
20
25
|
|
|
21
26
|
const PKG_ROOT = path.resolve(__dirname, '..');
|
|
22
|
-
const
|
|
27
|
+
const PKG = require(path.join(PKG_ROOT, 'package.json'));
|
|
28
|
+
const NPM_PKG_NAME = PKG.name;
|
|
29
|
+
const PKG_VERSION = PKG.version || '0.0.0';
|
|
23
30
|
const CONFIG_DIR = path.join(os.homedir(), '.skillforge');
|
|
24
31
|
const VENV_DIR = path.join(CONFIG_DIR, 'venv');
|
|
25
32
|
const DATA_DIR = path.join(CONFIG_DIR, 'data');
|
|
@@ -143,7 +150,23 @@ function runSetup() {
|
|
|
143
150
|
}
|
|
144
151
|
ok('Python dependencies installed');
|
|
145
152
|
|
|
146
|
-
// 4.
|
|
153
|
+
// 4. Cursor / MCP host hooks (no Python required)
|
|
154
|
+
try {
|
|
155
|
+
const hostSetup = require('../lib/host-setup');
|
|
156
|
+
hostSetup.reportHostsAndInstallAgentCommands({
|
|
157
|
+
force: process.argv.includes('--force-cursor'),
|
|
158
|
+
pkgRoot: PKG_ROOT,
|
|
159
|
+
pkgVersion: PKG_VERSION,
|
|
160
|
+
log,
|
|
161
|
+
ok,
|
|
162
|
+
err,
|
|
163
|
+
dim: s => log(c.dim(s)),
|
|
164
|
+
});
|
|
165
|
+
} catch (e) {
|
|
166
|
+
err(`Host integration failed: ${/** @type {Error} */ (e).message}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 5. Mark setup complete
|
|
147
170
|
fs.writeFileSync(SETUP_MARKER, new Date().toISOString());
|
|
148
171
|
ok('Setup complete\n');
|
|
149
172
|
}
|
|
@@ -237,6 +260,41 @@ function runIndexCmd() {
|
|
|
237
260
|
proc.on('exit', (code) => process.exit(code ?? 0));
|
|
238
261
|
}
|
|
239
262
|
|
|
263
|
+
function runHealthCmd() {
|
|
264
|
+
setupIfNeeded();
|
|
265
|
+
const sub = args.slice(1);
|
|
266
|
+
const proc = spawn(venvPython(), ['-m', 'app.health_cli', ...sub], {
|
|
267
|
+
stdio: 'inherit',
|
|
268
|
+
env: buildEnv(),
|
|
269
|
+
});
|
|
270
|
+
proc.on('exit', (code) => process.exit(code ?? 0));
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function runRouteEvalCmd() {
|
|
274
|
+
setupIfNeeded();
|
|
275
|
+
const sub = args.slice(1);
|
|
276
|
+
const proc = spawn(venvPython(), ['-m', 'app.eval_cli', ...sub], {
|
|
277
|
+
stdio: 'inherit',
|
|
278
|
+
env: buildEnv(),
|
|
279
|
+
});
|
|
280
|
+
proc.on('exit', (code) => process.exit(code ?? 0));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function runWeightsCmd() {
|
|
284
|
+
setupIfNeeded();
|
|
285
|
+
const sub = args.slice(1);
|
|
286
|
+
if (sub.length === 0 || sub[0] === '--help' || sub[0] === '-h') {
|
|
287
|
+
log(c.dim('Usage: skillforge weights export [-o file] [--user-id=] [--project-root=]'));
|
|
288
|
+
log(c.dim(' skillforge weights import <file.json> [--user-id=] [--replace-user] [--project-root=]'));
|
|
289
|
+
process.exit(sub.length === 0 ? 1 : 0);
|
|
290
|
+
}
|
|
291
|
+
const proc = spawn(venvPython(), ['-m', 'app.weights_cli', ...sub], {
|
|
292
|
+
stdio: 'inherit',
|
|
293
|
+
env: buildEnv(),
|
|
294
|
+
});
|
|
295
|
+
proc.on('exit', (code) => process.exit(code ?? 0));
|
|
296
|
+
}
|
|
297
|
+
|
|
240
298
|
// ---- skill management ----
|
|
241
299
|
function skillsAdd(srcPath) {
|
|
242
300
|
if (!srcPath) {
|
|
@@ -306,6 +364,19 @@ function reset() {
|
|
|
306
364
|
}
|
|
307
365
|
}
|
|
308
366
|
|
|
367
|
+
function runHostsInit() {
|
|
368
|
+
const hostSetup = require('../lib/host-setup');
|
|
369
|
+
hostSetup.reportHostsAndInstallAgentCommands({
|
|
370
|
+
force: args.includes('--force') || args.includes('--force-cursor'),
|
|
371
|
+
pkgRoot: PKG_ROOT,
|
|
372
|
+
pkgVersion: PKG_VERSION,
|
|
373
|
+
log,
|
|
374
|
+
ok,
|
|
375
|
+
err,
|
|
376
|
+
dim: s => log(c.dim(s)),
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
309
380
|
function showHelp() {
|
|
310
381
|
log(`
|
|
311
382
|
${c.bold('skillforge')} — skill orchestrator co-tool for Claude (MCP-first)
|
|
@@ -317,6 +388,8 @@ ${c.bold('Run modes:')}
|
|
|
317
388
|
skillforge events [--watch] [--limit=N] [--verbose] [--user=…] Live routing log + usage (see --help)
|
|
318
389
|
skillforge route [words…] [--project-root=…] [--include-project-rag] Route a prompt (see skillforge route --help)
|
|
319
390
|
skillforge index --project-root=… [--reset] [--stats-only] Index repo text for include_project_rag
|
|
391
|
+
skillforge health [--quick] [--json] [--project-root=…] Paths + SKILL.md counts; omit --quick to load the embedder
|
|
392
|
+
skillforge route-eval --fixture=path/to/cases.json [--router-mode=embedding] Run routing eval cases
|
|
320
393
|
|
|
321
394
|
${c.bold('Skills:')}
|
|
322
395
|
skillforge skills list List bundled and user skills
|
|
@@ -331,10 +404,15 @@ ${c.bold('Skill packs (install from git):')}
|
|
|
331
404
|
|
|
332
405
|
${c.bold('Maintenance:')}
|
|
333
406
|
skillforge reset Wipe learned state and event log
|
|
334
|
-
skillforge
|
|
407
|
+
skillforge weights export Dump learned weights JSON (see skillforge weights export --help)
|
|
408
|
+
skillforge weights import Restore weights snapshot (see skillforge weights import --help)
|
|
409
|
+
skillforge install Re-run setup (auto-runs on first launch; installs editor /skillforge when detected)
|
|
410
|
+
skillforge install --force-cursor Replace managed host command files even if present
|
|
411
|
+
skillforge hosts init [--force] Write ~/.cursor/commands + ~/.claude/commands /skillforge (no Python)
|
|
412
|
+
skillforge cursor init [--force] Alias for hosts init
|
|
335
413
|
skillforge --help This message
|
|
336
414
|
|
|
337
|
-
${c.bold('First run:')} ${c.cyan('skillforge install')} (auto on first command).
|
|
415
|
+
${c.bold('First run:')} ${c.cyan('skillforge install')} (auto on first command) or ${c.cyan('npx -y')} ${NPM_PKG_NAME} ${c.cyan('install')}. Detects ${c.cyan('Cursor')} and ${c.cyan('Claude Code')} and installs managed **/skillforge** under ${c.cyan('~/.cursor/commands')} and ${c.cyan('~/.claude/commands')} (skip: ${c.dim('SKILLFORGE_SKIP_CURSOR_SETUP')}, ${c.dim('SKILLFORGE_SKIP_CLAUDE_CODE_SETUP')}; force paths: ${c.dim('SKILLFORGE_CURSOR_GLOBAL_COMMAND')} / ${c.dim('SKILLFORGE_CLAUDE_CODE_GLOBAL_COMMAND')}). ${c.cyan('skillforge mcp')} needs no API key for embedding-only routing.
|
|
338
416
|
${c.bold('Config dir:')} ${CONFIG_DIR}
|
|
339
417
|
|
|
340
418
|
${c.bold('MCP integration:')}
|
|
@@ -366,6 +444,15 @@ async function main() {
|
|
|
366
444
|
case 'index':
|
|
367
445
|
runIndexCmd();
|
|
368
446
|
break;
|
|
447
|
+
case 'health':
|
|
448
|
+
runHealthCmd();
|
|
449
|
+
break;
|
|
450
|
+
case 'route-eval':
|
|
451
|
+
runRouteEvalCmd();
|
|
452
|
+
break;
|
|
453
|
+
case 'weights':
|
|
454
|
+
runWeightsCmd();
|
|
455
|
+
break;
|
|
369
456
|
case 'mcp':
|
|
370
457
|
if (args[1] === 'config') {
|
|
371
458
|
printMcpConfig();
|
|
@@ -376,6 +463,26 @@ async function main() {
|
|
|
376
463
|
case 'install':
|
|
377
464
|
runSetup();
|
|
378
465
|
break;
|
|
466
|
+
case 'hosts': {
|
|
467
|
+
const sub = args[1];
|
|
468
|
+
if (sub === 'init') {
|
|
469
|
+
runHostsInit();
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
err('Unknown hosts subcommand.');
|
|
473
|
+
log(c.dim(' Try: skillforge hosts init [--force]'));
|
|
474
|
+
process.exit(1);
|
|
475
|
+
}
|
|
476
|
+
case 'cursor': {
|
|
477
|
+
const sub = args[1];
|
|
478
|
+
if (sub === 'init') {
|
|
479
|
+
runHostsInit();
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
err('Unknown cursor subcommand.');
|
|
483
|
+
log(c.dim(' Try: skillforge cursor init [--force] (alias: hosts init)'));
|
|
484
|
+
process.exit(1);
|
|
485
|
+
}
|
|
379
486
|
case 'reset':
|
|
380
487
|
reset();
|
|
381
488
|
break;
|