@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/README.md
CHANGED
|
@@ -6,61 +6,78 @@
|
|
|
6
6
|
<a href="https://github.com/heytherevibin/skillforge/actions/workflows/ci.yml"><img src="https://github.com/heytherevibin/skillforge/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
|
|
7
7
|
</p>
|
|
8
8
|
|
|
9
|
-
**Skillforge** is a **
|
|
9
|
+
**Skillforge** is a **local-first orchestration layer** for agent workflows: it maintains a catalog of **`SKILL.md`** documents, **routes** a small subset per task using **embedding-first retrieval**, optional **hybrid** sparse signals and **LLM** stages, optional **project-scoped** policies and notes, and returns **structured context** for downstream models. The **primary integration** is **stdio MCP**; the **CLI** provides parity, operations, and automation hooks.
|
|
10
10
|
|
|
11
|
-
**
|
|
12
|
-
|
|
13
|
-
**Observability:** run **`skillforge events --watch`** in a terminal (top skills, active sessions, and live **route** / **feedback** lines from SQLite).
|
|
11
|
+
**Published version:** see **`package.json`** and the npm badge above (they should match after each release). **Change history:** [CHANGELOG.md](CHANGELOG.md). **Product direction:** [STRATEGY.md](STRATEGY.md). **Vulnerability reporting:** [SECURITY.md](SECURITY.md). **Release process:** [RELEASING.md](RELEASING.md).
|
|
14
12
|
|
|
15
13
|
---
|
|
16
14
|
|
|
17
15
|
## Table of contents
|
|
18
16
|
|
|
19
|
-
- [
|
|
17
|
+
- [What Skillforge provides](#what-skillforge-provides)
|
|
18
|
+
- [Architecture at a glance](#architecture-at-a-glance)
|
|
20
19
|
- [Requirements](#requirements)
|
|
21
20
|
- [Quick start](#quick-start)
|
|
22
21
|
- [Installation](#installation)
|
|
23
|
-
- [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- [MCP response contract](#mcp-response-contract)
|
|
27
|
-
- [Skills and packs](#skills-and-packs)
|
|
22
|
+
- [Operational interfaces](#operational-interfaces)
|
|
23
|
+
- [Model Context Protocol (MCP)](#model-context-protocol-mcp)
|
|
24
|
+
- [MCP response contract](#mcp-response-contract)
|
|
28
25
|
- [Routing pipeline](#routing-pipeline)
|
|
26
|
+
- [Route policies and project overlay](#route-policies-and-project-overlay)
|
|
27
|
+
- [Project RAG](#project-rag)
|
|
28
|
+
- [Learning, weights, and portability](#learning-weights-and-portability)
|
|
29
|
+
- [Skills and packs](#skills-and-packs)
|
|
29
30
|
- [Configuration](#configuration)
|
|
30
|
-
- [Local data and
|
|
31
|
-
- [Security
|
|
31
|
+
- [Local data and paths](#local-data-and-paths)
|
|
32
|
+
- [Security](#security)
|
|
32
33
|
- [Contributing and governance](#contributing-and-governance)
|
|
33
|
-
- [Releases and maintainers](#releases-and-maintainers)
|
|
34
34
|
- [License](#license)
|
|
35
35
|
|
|
36
36
|
---
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## What Skillforge provides
|
|
39
|
+
|
|
40
|
+
| Area | Capability |
|
|
41
|
+
|------|------------|
|
|
42
|
+
| **Context control** | Returns only **relevant** skill (and optional project) chunks instead of an entire catalog. |
|
|
43
|
+
| **Routing** | Dense embeddings on skill **cards** (title, description, optional triggers); optional **keyword / BM25** fusion; optional **LLM** rerank and final pick—or **embedding-only** or **host-delegated** selection. |
|
|
44
|
+
| **Conversation-aware retrieval** | Recent turns can influence the **shortlist query** when enabled via environment (see [Configuration](#configuration)). |
|
|
45
|
+
| **Governance** | Regex **policies** to append skills after routing; **project overlay** for excludes, score boosts, and **project notes** (notes require a declared **project root**). |
|
|
46
|
+
| **Adaptation** | Per-user **SQLite** statistics and explicit feedback adjust routing over time (portable via **export/import**). |
|
|
47
|
+
| **Project grounding** | Optional **index** of repository text into the same SQLite DB used for sessions (**project RAG**). |
|
|
48
|
+
| **Observability** | Versioned **`_meta`** on MCP responses; route **events** in SQLite; **`skillforge events`** for operators. |
|
|
49
|
+
| **Reliability hooks** | **`skillforge health`** (preflight) and **`skillforge route-eval`** (fixture-driven smoke checks; used in CI). |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Architecture at a glance
|
|
39
54
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
```
|
|
56
|
+
Host (Claude / Cursor / Claude Code / …)
|
|
57
|
+
│ MCP JSON-RPC (stdio)
|
|
58
|
+
▼
|
|
59
|
+
┌───────────────────────────────────────────────────────────┐
|
|
60
|
+
│ skillforge mcp → Python: embed → shortlist → optional │
|
|
61
|
+
│ LLM stages → policies/overlay → context assembly │
|
|
62
|
+
└───────────────────────────────────────────────────────────┘
|
|
63
|
+
│
|
|
64
|
+
├── SQLite (global ~/.skillforge or <project>/.skillforge)
|
|
65
|
+
└── Optional: Anthropic API (Haiku) in-process when enabled
|
|
66
|
+
```
|
|
50
67
|
|
|
51
|
-
|
|
68
|
+
**Trust boundary:** Skillforge runs **on the operator’s machine** (or your CI runner). Prompts and retrieved text should be handled per your org’s data policy. See [Security](#security).
|
|
52
69
|
|
|
53
70
|
---
|
|
54
71
|
|
|
55
72
|
## Requirements
|
|
56
73
|
|
|
57
|
-
| Dependency |
|
|
58
|
-
|
|
59
|
-
| **Node.js** |
|
|
60
|
-
| **Python** |
|
|
61
|
-
| **Anthropic API** |
|
|
74
|
+
| Dependency | Notes |
|
|
75
|
+
|------------|--------|
|
|
76
|
+
| **Node.js** | **≥ 18** (CLI bootstrap). CI validates on **Node 22** (see `.github/workflows/ci.yml`). |
|
|
77
|
+
| **Python** | **≥ 3.10**; the CLI creates **`~/.skillforge/venv`** and installs `python/requirements.txt`. |
|
|
78
|
+
| **Anthropic API** | **Optional.** Without **`ANTHROPIC_API_KEY`**, routing stays **embedding-first** unless you delegate picks to the host. |
|
|
62
79
|
|
|
63
|
-
**First run
|
|
80
|
+
**First run** installs the virtualenv and Python dependencies and may download the default sentence-transformer model once; subsequent starts are typically fast.
|
|
64
81
|
|
|
65
82
|
---
|
|
66
83
|
|
|
@@ -70,15 +87,25 @@ Bundled content includes **200+** curated skills (coding, security, research, fr
|
|
|
70
87
|
npx --yes @heytherevibin/skillforge --help
|
|
71
88
|
```
|
|
72
89
|
|
|
73
|
-
|
|
90
|
+
Configure **MCP** in your host (see [Model Context Protocol](#model-context-protocol-mcp)). **Embedding-only** operation does not require an Anthropic key.
|
|
91
|
+
|
|
92
|
+
**Operator visibility:**
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
skillforge events --watch
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Preflight (after install):**
|
|
74
99
|
|
|
75
|
-
|
|
100
|
+
```bash
|
|
101
|
+
skillforge health --quick
|
|
102
|
+
```
|
|
76
103
|
|
|
77
104
|
---
|
|
78
105
|
|
|
79
106
|
## Installation
|
|
80
107
|
|
|
81
|
-
**
|
|
108
|
+
**Evaluate without global install**
|
|
82
109
|
|
|
83
110
|
```bash
|
|
84
111
|
npx --yes @heytherevibin/skillforge --help
|
|
@@ -91,238 +118,261 @@ npm install -g @heytherevibin/skillforge
|
|
|
91
118
|
skillforge --help
|
|
92
119
|
```
|
|
93
120
|
|
|
94
|
-
|
|
95
|
-
Source
|
|
121
|
+
- **npm:** [@heytherevibin/skillforge](https://www.npmjs.com/package/@heytherevibin/skillforge)
|
|
122
|
+
- **Source / issues:** [github.com/heytherevibin/skillforge](https://github.com/heytherevibin/skillforge)
|
|
96
123
|
|
|
97
124
|
---
|
|
98
125
|
|
|
99
|
-
##
|
|
126
|
+
## Operational interfaces
|
|
100
127
|
|
|
101
|
-
|
|
128
|
+
Skillforge is organized around a small **CLI** surface (implemented in **Node** spawning **Python** modules). Use **`skillforge <command> --help`** for flags.
|
|
102
129
|
|
|
103
|
-
|
|
|
104
|
-
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
|
|
|
108
|
-
|
|
|
109
|
-
| `
|
|
130
|
+
| Group | Commands | Purpose |
|
|
131
|
+
|-------|----------|--------|
|
|
132
|
+
| **Core** | `mcp`, `route`, `events`, `index` | Primary routing, logs, project indexing. |
|
|
133
|
+
| **Reliability** | `health`, `route-eval` | Preflight checks; embedding-mode fixture evaluation (CI uses both). |
|
|
134
|
+
| **Learning portability** | `weights export`, `weights import` | Snapshot / restore **`skill_weights`** rows (JSON). |
|
|
135
|
+
| **Catalog** | `skills`, `pack` | User skills and git-backed **packs**. |
|
|
136
|
+
| **Setup** | `install`, `hosts init`, `reset` | Bootstrap venv, global `/skillforge` commands, wipe local DB state. |
|
|
110
137
|
|
|
111
|
-
|
|
138
|
+
**MCP config snippet (stdout):**
|
|
112
139
|
|
|
113
|
-
|
|
140
|
+
```bash
|
|
141
|
+
skillforge mcp config
|
|
142
|
+
# Optional: --local (checkout), --with-anthropic (env placeholder)
|
|
143
|
+
```
|
|
114
144
|
|
|
115
|
-
|
|
116
|
-
|--------------------------|---------------------|-------------|
|
|
117
|
-
| *(unset)* — auto | omitted | Embedding-only (keyless) |
|
|
118
|
-
| *(unset)* — auto | set | Full router (Haiku) |
|
|
119
|
-
| `embedding` | either | Embedding-only |
|
|
120
|
-
| `full` | set recommended | Full router (Haiku); falls back on API errors |
|
|
145
|
+
**Important:** MCP requires a **clean stdout** stream (JSON-RPC). Logs belong on **stderr**. If tools do not appear in the host, update the package and fully restart the host after setup.
|
|
121
146
|
|
|
122
|
-
|
|
147
|
+
---
|
|
123
148
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
149
|
+
## Model Context Protocol (MCP)
|
|
150
|
+
|
|
151
|
+
### Router modes (`SKILLFORGE_ROUTER_MODE`)
|
|
152
|
+
|
|
153
|
+
| Mode / default | Anthropic key | Behavior |
|
|
154
|
+
|----------------|---------------|----------|
|
|
155
|
+
| *(unset)* **auto** | optional | Embedding-first when key absent; full LLM routing when key present. |
|
|
156
|
+
| `embedding` | ignored for routing | No in-process LLM pick; top candidates drive selection. |
|
|
157
|
+
| `full` | recommended | LLM final pick; falls back per implementation on errors. |
|
|
158
|
+
| `host` | optional for pick | **Two-step:** first `route_skills` returns shortlist; second call passes **`picked_names`**. |
|
|
159
|
+
|
|
160
|
+
### MCP tools (summary)
|
|
161
|
+
|
|
162
|
+
| Tool | Role |
|
|
163
|
+
|------|------|
|
|
164
|
+
| `route_skills` | Main routing: **prompt**, optional **conversation**, **`project_root`**, **`include_project_rag`**, **`session_id`**, **`user_id`**, **`picked_names`** (host or override). |
|
|
165
|
+
| `search_skills` | Embedding shortlist for a **query** (read-only). |
|
|
166
|
+
| `explain_route` | Diagnostics: shortlist + picks + policy audit **without** writing sessions. |
|
|
167
|
+
| `get_skill`, `list_skills` | Catalog access. |
|
|
168
|
+
| `skill_feedback`, `skill_referenced`, `disable_skill` | Learning loop and toggles. |
|
|
169
|
+
| `materialize_project`, `skillforge_bootstrap` | Project file materialization (bootstrap **errors** in `host` mode by design—use two-step routing + materialize). |
|
|
170
|
+
|
|
171
|
+
Full argument lists: tool definitions in **`python/app/mcp_server.py`** (source of truth).
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## MCP response contract
|
|
176
|
+
|
|
177
|
+
Successful **`route_skills`** responses include **`_meta`** built in **`python/app/mcp_contract.py`**. The **`schema_version`** string tracks additive JSON shape changes (hosts may rely on it for parsing).
|
|
178
|
+
|
|
179
|
+
**Authoritative version:** constant **`MCP_RESPONSE_SCHEMA_VERSION`** in **`app/mcp_contract.py`** (do not rely on this README if the two drift).
|
|
180
|
+
|
|
181
|
+
**Notable `_meta` fields (non-exhaustive):**
|
|
182
|
+
|
|
183
|
+
| Field | Description |
|
|
184
|
+
|-------|-------------|
|
|
185
|
+
| `schema_version` | Contract version string. |
|
|
186
|
+
| `sources`, `budget` | Chunk citations and size accounting. |
|
|
187
|
+
| `fusion` | Present when MMR-style fusion ran. |
|
|
188
|
+
| `context_redaction` | Redaction hit counts when enabled. |
|
|
189
|
+
| `route_quality` | Shortlist / router / policy / session telemetry for calibration. |
|
|
190
|
+
| `feedback_effect` | Per-pick **learned weight** snapshot (uses / thumbs / reference rate). |
|
|
191
|
+
| `routing_overlay` | Audit of **exclude** / **boost** / **project notes** application when configured. |
|
|
192
|
+
| `host_pick_shortlist`, `host_pick_candidates` | Host-pick phase payloads. |
|
|
193
|
+
|
|
194
|
+
Structured errors (e.g. empty prompt) return **`isError`: true** with **`_meta.error`** and **`schema_version`**.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Routing pipeline
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
User prompt (+ optional conversation-aware routing query)
|
|
202
|
+
→ Encode routing query (skill cards + optional hybrid sparse signal)
|
|
203
|
+
→ Fuse scores + per-user weights + optional project overlay boosts
|
|
204
|
+
→ Shortlist (top-K)
|
|
205
|
+
→ Optional LLM rerank / final pick (or embedding / host selection)
|
|
206
|
+
→ Assemble context (skill chunks ± project chunks, optional fusion)
|
|
207
|
+
→ Return markdown + _meta; optional SQLite events
|
|
133
208
|
```
|
|
134
209
|
|
|
135
|
-
|
|
210
|
+
Re-routing when the active skill set changes significantly is controlled by **`SKILLFORGE_REROUTE_THRESHOLD`** (see [Configuration](#configuration)).
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Route policies and project overlay
|
|
215
|
+
|
|
216
|
+
### Regex policies (post-pick merge)
|
|
217
|
+
|
|
218
|
+
Rules match the user **`prompt`** with **`re.search`** (**`re.DOTALL`**). Matched **`include`** skills append after the router, capped by **`SKILLFORGE_MAX_ACTIVE`**. Audit lands on route **events** under **`policy`**.
|
|
219
|
+
|
|
220
|
+
**Load order:** **`SKILLFORGE_ROUTE_POLICIES`** (inline JSON) → **`SKILLFORGE_ROUTE_POLICIES_FILE`** → **`<project_root>/.skillforge/policies.json`** → **`<project_root>/skillforge-policies.json`**.
|
|
221
|
+
|
|
222
|
+
### Project routing overlay (same JSON document)
|
|
223
|
+
|
|
224
|
+
Optional keys alongside **`rules`**:
|
|
225
|
+
|
|
226
|
+
| Key | Aliases | Purpose |
|
|
227
|
+
|-----|---------|--------|
|
|
228
|
+
| `exclude_skills` | `host_exclude`, `denylist` | Remove skills from the embedding shortlist. |
|
|
229
|
+
| `routing_boosts` | `skill_boosts` | Additive score delta after learned weight (clamped; see **route_policies** module). |
|
|
230
|
+
| `project_notes` | `routing_notes`, `rag_notes` | Free text **prepended** to the internal routing query when **`project_root`** is set (not applied without a project root—mitigates accidental global injection from shared policy files). |
|
|
231
|
+
|
|
232
|
+
**Example fragment** (illustrative—adjust skill ids to your catalog):
|
|
136
233
|
|
|
137
234
|
```json
|
|
138
235
|
{
|
|
139
|
-
"
|
|
140
|
-
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"env": {
|
|
144
|
-
"ANTHROPIC_API_KEY": "sk-ant-..."
|
|
145
|
-
}
|
|
236
|
+
"rules": [
|
|
237
|
+
{
|
|
238
|
+
"if_text_matches": "(?i)(auth|oauth|jwt)",
|
|
239
|
+
"include": ["security-review"]
|
|
146
240
|
}
|
|
147
|
-
|
|
241
|
+
],
|
|
242
|
+
"project_notes": "Service stack and conventions for this repo (short, factual).",
|
|
243
|
+
"routing_boosts": { "python-testing": 0.15 },
|
|
244
|
+
"exclude_skills": ["legacy-skill-id"]
|
|
148
245
|
}
|
|
149
246
|
```
|
|
150
247
|
|
|
151
|
-
|
|
248
|
+
---
|
|
152
249
|
|
|
153
|
-
|
|
250
|
+
## Project RAG
|
|
154
251
|
|
|
155
|
-
|
|
156
|
-
|------|---------|
|
|
157
|
-
| `route_skills` | Returns routed **`SKILL.md`** context (chunks or full body). Pass **`project_root`** for per-repo SQLite under **`.skillforge/orchestrator.db`**. Optional **`include_project_rag`** (after **`skillforge index --project-root=…`**), **`session_id`**, **`user_id`** / **`SKILLFORGE_MCP_USER_ID`**, or env **`SKILLFORGE_PROJECT_ROOT`**. |
|
|
158
|
-
| `list_skills` | Catalog overview; optional **`user_id`** scopes usage stats. |
|
|
159
|
-
| `skill_feedback` | Feedback for the learning loop; optional **`user_id`**, **`session_id`** (stored with events). |
|
|
160
|
-
| `skill_referenced` | Mark a routed skill as **used** in the reply (increments **`referenced`** + weight; optional **`user_id`**). |
|
|
161
|
-
| `disable_skill` | Toggle skills; optional **`user_id`**. |
|
|
162
|
-
| `materialize_project` | Writes **`.cursor/rules/skillforge.mdc`**, **`docs/SKILLFORGE-PRD.md`**, updates **`CLAUDE.md`** (Skillforge block). Args: **`project_root`**, **`skill_names`** from **`route_skills`**. |
|
|
163
|
-
| `skillforge_bootstrap` | **`route_skills`** + **`materialize_project`** in one call (needs **`project_root`**). |
|
|
252
|
+
1. **Index** repository text into **`<project>/.skillforge/orchestrator.db`**:
|
|
164
253
|
|
|
165
|
-
|
|
254
|
+
```bash
|
|
255
|
+
skillforge index --project-root=/path/to/repo
|
|
256
|
+
```
|
|
166
257
|
|
|
167
|
-
|
|
258
|
+
2. Call **`route_skills`** with **`project_root`** and **`include_project_rag`** (or CLI **`--include-project-rag`**) when embeddings and schema match (see **`project_index.py`** for model/dimension guards).
|
|
168
259
|
|
|
169
|
-
|
|
170
|
-
- **`sources`**: citations; each item has **`kind`** (`skill` or **`file`**), **`ref`**, **`line_start`** / **`line_end`**, **`score`**, optional **`mmr_rank`** after fusion.
|
|
171
|
-
- **`fusion`**: present when MMR fusion ran (**`enabled`: true**): **`lambda`**, **`budget_chars`**, **`pool_skill`**, **`pool_project`**, **`mmr_trace`**, …
|
|
172
|
-
- **`context_redaction`**: optional; when scrubbing is enabled, reports **`enabled`**, **`secret_hits`**, **`path_hits`** for exported context.
|
|
173
|
-
- **`budget`**: **`chars_skill_bodies`**, **`chars_project_chunks`**, **`chars_context_items_total`**, **`chars_response_total`**, **`est_tokens_approx`** (rough `chars/4`).
|
|
174
|
-
- **`candidates_preview`**: up to 15 shortlist entries **`{ name, score }`** for debugging.
|
|
175
|
-
- **`picked`**, **`reasoning`**, **`session_id`**, **`user_id`**, **`rerouted`**, **`change_pct`**, **`route_ms`**, **`orchestrator_db`**.
|
|
260
|
+
Chunk caps and ignore rules are **environment-driven** (see configuration table).
|
|
176
261
|
|
|
177
|
-
|
|
262
|
+
---
|
|
178
263
|
|
|
179
|
-
|
|
264
|
+
## Learning, weights, and portability
|
|
180
265
|
|
|
181
|
-
|
|
266
|
+
- **Signals:** route **`uses`**, **`skill_referenced`**, **`skill_feedback`** (thumbs), and **`disable_skill`** feed **SQLite** **`skill_weights`**.
|
|
267
|
+
- **Transparency:** **`_meta.feedback_effect`** summarizes per-pick weight context after the route’s **`uses`** increment.
|
|
268
|
+
- **Portability:**
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
skillforge weights export -o weights.json
|
|
272
|
+
skillforge weights import weights.json
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Use **`--project-root`** / **`--user-id`** / **`--replace-user`** as documented in **`skillforge weights --help`** (implemented in **`python/app/weights_cli.py`**).
|
|
182
276
|
|
|
183
277
|
---
|
|
184
278
|
|
|
185
279
|
## Skills and packs
|
|
186
280
|
|
|
187
|
-
**Bundled
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
skillforge skills list
|
|
191
|
-
```
|
|
281
|
+
**Bundled catalog** ships inside the npm package. **CI** enforces a **minimum** bundled **`SKILL.md`** count so releases cannot silently ship an empty tree—the threshold lives in **`ci/bundle-gate.json`** (`minSkillMdFiles`); **`.github/workflows/ci.yml`** reads that file at build time.
|
|
192
282
|
|
|
193
|
-
**Custom
|
|
283
|
+
**Custom skills:** directory with **`SKILL.md`** and YAML frontmatter (`name`, `description`; optional **`triggers`** / **`anti_triggers`**).
|
|
194
284
|
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
name: my-skill
|
|
198
|
-
description: Clear trigger conditions—used by the router.
|
|
199
|
-
---
|
|
200
|
-
# My Skill
|
|
285
|
+
```bash
|
|
286
|
+
skillforge skills add ./path/to/skill
|
|
201
287
|
```
|
|
202
288
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
**Skill packs** are git repositories with a root **`skillforge.json`** manifest listing skill folder names. Install:
|
|
289
|
+
**Packs:** repositories with **`skillforge.json`**:
|
|
206
290
|
|
|
207
291
|
```bash
|
|
208
292
|
skillforge pack install <org/repo>
|
|
209
|
-
skillforge pack install https://example.com/repo.git
|
|
210
293
|
skillforge pack list
|
|
211
|
-
skillforge pack update <name>
|
|
212
|
-
skillforge pack remove <name>
|
|
213
294
|
```
|
|
214
295
|
|
|
215
296
|
---
|
|
216
297
|
|
|
217
|
-
## Routing pipeline
|
|
218
|
-
|
|
219
|
-
```
|
|
220
|
-
User prompt
|
|
221
|
-
→ Local embeddings (sentence-transformers)
|
|
222
|
-
→ Cosine similarity + per-user weights
|
|
223
|
-
→ Top-K candidates
|
|
224
|
-
→ Router model (Haiku) selects final active skills — *or* embedding-only mode takes top-N from candidates
|
|
225
|
-
→ Skill bodies injected; response model answers (e.g. Opus)
|
|
226
|
-
→ Usage signals update weights (optional)
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
Re-route: when overlap between successive active sets falls below a configurable threshold, the pipeline selects a new set for the next turn. Events are stored in SQLite; stream them with **`skillforge events --watch`**.
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
298
|
## Configuration
|
|
234
299
|
|
|
235
|
-
Environment variables
|
|
236
|
-
|
|
237
|
-
| Variable |
|
|
238
|
-
|
|
239
|
-
| `ANTHROPIC_API_KEY` |
|
|
240
|
-
| `SKILLFORGE_ROUTER_MODE` |
|
|
241
|
-
| `SKILLFORGE_EMBED_MODEL
|
|
242
|
-
| `
|
|
243
|
-
| `
|
|
244
|
-
| `
|
|
245
|
-
| `
|
|
246
|
-
| `
|
|
247
|
-
| `
|
|
248
|
-
| `
|
|
249
|
-
| `
|
|
250
|
-
| `
|
|
251
|
-
| `
|
|
252
|
-
| `
|
|
253
|
-
| `
|
|
254
|
-
| `
|
|
255
|
-
|
|
|
256
|
-
|
|
|
257
|
-
| `SKILLFORGE_PROJECT_RAG_MAX_CHUNKS` | `20000` | Max **project_chunks** rows loaded for one retrieval. |
|
|
258
|
-
| `SKILLFORGE_INDEX_MAX_FILE_BYTES` | `524288` | Skip indexing files larger than this (bytes). |
|
|
259
|
-
| `SKILLFORGE_INDEX_IGNORE_DIRS` | `""` | Extra comma-separated directory **basename** ignores (e.g. `out,tmp`). |
|
|
260
|
-
| `SKILLFORGE_REDACT_CONTEXT` | `1` | When **`1`** (default), scrub common secret shapes and (with home path scrub) exported context before MCP/CLI output and route events. |
|
|
261
|
-
| `SKILLFORGE_REDACT_HOME_IN_PATHS` | `1` | Replace resolved home-directory prefixes in chunk paths / DB path hints with **`[HOME]`**. |
|
|
262
|
-
| `SKILLFORGE_MCP_USER_ID` | `""` | Default logical **user id** for MCP tool calls when arguments omit `user_id` (weights, sessions, events). |
|
|
263
|
-
| `SKILLFORGE_PROJECT_ROOT` | `""` | Default workspace root when MCP **`project_root`** is omitted: events/weights/sessions live in **`<root>/.skillforge/orchestrator.db`**. Prefer passing **`project_root`** on each tool call from the host. |
|
|
264
|
-
| `SKILLFORGE_SKILL_HOT_RELOAD` | `1` | When **`0`** / **`false`**, disable **SKILL.md** hot-reload; restart the MCP process to refresh the catalog. |
|
|
265
|
-
| `SKILLFORGE_WATCH_SKILLS_INTERVAL` | `30` | Seconds between background catalog checks when hot reload is on. **`0`**: no background polling and no MCP **`tools.listChanged`**; **`tools/list`** and **`tools/call`** still reload when files change. |
|
|
266
|
-
| `SKILLFORGE_MCP_LIST_CHANGED` | `1` | When **`0`** / **`false`**, never emit **`notifications/tools/list_changed`** (and **`listChanged`** is not advertised), even if a background interval is set. |
|
|
300
|
+
Environment variables tune routing, context budgets, redaction, MCP defaults, and file watchers. **Authoritative defaults and parsing** live in **`python/app/main.py`** and related modules—treat the table below as **operator reference**, not a legal spec.
|
|
301
|
+
|
|
302
|
+
| Variable | Role |
|
|
303
|
+
|----------|------|
|
|
304
|
+
| `ANTHROPIC_API_KEY` | Enables in-process **Haiku** routing / rerank when configured. |
|
|
305
|
+
| `SKILLFORGE_ROUTER_MODE` | `full` · `embedding` · `host` · auto. |
|
|
306
|
+
| `SKILLFORGE_EMBED_MODEL`, `SKILLFORGE_ROUTER_MODEL` | Model identifiers for embeddings / routing LLM. |
|
|
307
|
+
| `SKILLFORGE_TOP_K`, `SKILLFORGE_MAX_ACTIVE` | Shortlist size and max simultaneous skills. |
|
|
308
|
+
| `SKILLFORGE_REROUTE_THRESHOLD` | Re-route sensitivity (Jaccard distance). |
|
|
309
|
+
| `SKILLFORGE_ROUTER_CONV_MAX_TURNS`, `SKILLFORGE_ROUTER_CONV_MSG_CHARS` | Conversation-aware routing query. |
|
|
310
|
+
| `SKILLFORGE_ROUTER_HYBRID`, `SKILLFORGE_ROUTER_HYBRID_ALPHA` | Hybrid sparse/dense fusion. |
|
|
311
|
+
| `SKILLFORGE_HAIKU_RERANK`, `SKILLFORGE_HAIKU_RERANK_MAX`, `SKILLFORGE_HAIKU_RERANK_MODEL` | Optional rerank stage. |
|
|
312
|
+
| `SKILLFORGE_CONTEXT_MODE`, `SKILLFORGE_ROUTE_MAX_CHARS`, chunk envs | Skill body chunking vs full-body legacy. |
|
|
313
|
+
| `SKILLFORGE_CONTEXT_FUSION`, `SKILLFORGE_CONTEXT_BUDGET_CHARS`, `SKILLFORGE_CONTEXT_MMR_LAMBDA`, pool sizes | Skill + project **MMR** fusion. |
|
|
314
|
+
| `SKILLFORGE_PROJECT_RAG_MAX_CHARS`, `SKILLFORGE_PROJECT_RAG_MAX_CHUNKS` | Project chunk retrieval caps. |
|
|
315
|
+
| `SKILLFORGE_PROJECT_NOTES_MAX_CHARS` | Cap for **`project_notes`** prepended to routing query. |
|
|
316
|
+
| `SKILLFORGE_REDACT_CONTEXT`, `SKILLFORGE_REDACT_HOME_IN_PATHS` | Output redaction behavior. |
|
|
317
|
+
| `SKILLFORGE_MCP_USER_ID`, `SKILLFORGE_PROJECT_ROOT` | MCP defaults for user scoping and DB resolution. |
|
|
318
|
+
| `SKILLFORGE_ROUTE_POLICIES`, `SKILLFORGE_ROUTE_POLICIES_FILE` | Inline or file-backed policy JSON. |
|
|
319
|
+
| `SKILLFORGE_HOST_PICK_MAX`, `SKILLFORGE_HOST_PICK_LINE_CHARS` | Host-mode shortlist sizing / formatting. |
|
|
320
|
+
| Hot reload | `SKILLFORGE_SKILL_HOT_RELOAD`, `SKILLFORGE_WATCH_SKILLS_INTERVAL`, `SKILLFORGE_MCP_LIST_CHANGED`. |
|
|
321
|
+
| Install hooks | `SKILLFORGE_SKIP_*`, `SKILLFORGE_*_GLOBAL_COMMAND`, etc. |
|
|
267
322
|
|
|
268
323
|
---
|
|
269
324
|
|
|
270
|
-
## Local data and
|
|
325
|
+
## Local data and paths
|
|
271
326
|
|
|
272
|
-
|
|
327
|
+
**Per-project** (when **`project_root`** / **`SKILLFORGE_PROJECT_ROOT`** is used):
|
|
273
328
|
|
|
274
329
|
```
|
|
275
330
|
<workspace>/.skillforge/
|
|
276
|
-
├── orchestrator.db
|
|
277
|
-
|
|
331
|
+
├── orchestrator.db # SQLite: sessions, weights, events, project_chunks (after index)
|
|
332
|
+
├── policies.json # Optional policies + overlay (or repo-root skillforge-policies.json)
|
|
333
|
+
└── last_route.json # Last CLI route snapshot (when applicable)
|
|
278
334
|
```
|
|
279
335
|
|
|
280
|
-
Global default
|
|
336
|
+
**Global default:**
|
|
281
337
|
|
|
282
338
|
```
|
|
283
339
|
~/.skillforge/
|
|
284
|
-
├── venv/
|
|
285
|
-
├── data/orchestrator.db
|
|
286
|
-
├── skills/
|
|
287
|
-
|
|
288
|
-
├── packs.json # Pack registry
|
|
340
|
+
├── venv/
|
|
341
|
+
├── data/orchestrator.db
|
|
342
|
+
├── skills/ # User skills
|
|
343
|
+
└── packs/ # Pack working copies
|
|
289
344
|
```
|
|
290
345
|
|
|
291
|
-
| Command |
|
|
292
|
-
|
|
293
|
-
| `skillforge events` |
|
|
294
|
-
| `skillforge index` |
|
|
295
|
-
| `skillforge reset` | Clears learning
|
|
296
|
-
| `skillforge
|
|
297
|
-
| `
|
|
346
|
+
| Command | Role |
|
|
347
|
+
|---------|------|
|
|
348
|
+
| `skillforge events` | Usage + recent **`route`** / **`feedback`** rows (`--watch`, `--project-root`, `--user`, `--verbose`). |
|
|
349
|
+
| `skillforge index` | (Re)build **`project_chunks`**. |
|
|
350
|
+
| `skillforge reset` | Clears learning + events in the target DB. |
|
|
351
|
+
| `skillforge health` | Validates paths, catalog discovery, optional deep router load. |
|
|
352
|
+
| `skillforge route-eval` | Runs JSON fixtures (CI). |
|
|
298
353
|
|
|
299
354
|
---
|
|
300
355
|
|
|
301
|
-
## Security
|
|
356
|
+
## Security
|
|
302
357
|
|
|
303
|
-
- **Redaction is best-effort
|
|
304
|
-
-
|
|
305
|
-
-
|
|
358
|
+
- **Redaction is best-effort.** Do not treat scrubbed output as a certified wipe of secrets.
|
|
359
|
+
- **Secrets:** keep **`ANTHROPIC_API_KEY`** and workspace tokens out of VCS; inject via host or OS secret stores.
|
|
360
|
+
- **Project notes** intentionally **do not apply** without **`project_root`** to reduce cross-talk from global policy config.
|
|
361
|
+
- **Disclosure:** follow **[SECURITY.md](SECURITY.md)** (private channels for undisclosed issues).
|
|
306
362
|
|
|
307
363
|
---
|
|
308
364
|
|
|
309
365
|
## Contributing and governance
|
|
310
366
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
- **Continuous integration:** `.github/workflows/ci.yml` (push and pull request to **`main`**).
|
|
320
|
-
- **Release & npm publish:** **Skillforge release** runs when you push tag **`vX.Y.Z`** and **`package.json`** **`version`** is exactly **`X.Y.Z`** (e.g. **`v0.2.1`** ↔ **`0.2.1`**). That same number is what **`npm publish`** ships. GitHub releases are titled **`Skillforge <tag>`**.
|
|
321
|
-
- **Procedure and npm tokens:** **[RELEASING.md](RELEASING.md)** (granular npm access tokens, **Bypass 2FA** for CI publish where applicable).
|
|
322
|
-
- **License:** MIT — see **[LICENSE](LICENSE)**.
|
|
323
|
-
|
|
324
|
-
---
|
|
367
|
+
| Document | Purpose |
|
|
368
|
+
|----------|---------|
|
|
369
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | Workflow and local checks. |
|
|
370
|
+
| [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) | Community standards. |
|
|
371
|
+
| [SECURITY.md](SECURITY.md) | Reporting vulnerabilities. |
|
|
372
|
+
| [RELEASING.md](RELEASING.md) | Tags, **`NPM_TOKEN`**, npm **2FA** / granular tokens, CI vs release workflows. |
|
|
373
|
+
| [CHANGELOG.md](CHANGELOG.md) | Version-by-version changes. |
|
|
374
|
+
| [STRATEGY.md](STRATEGY.md) | Product direction and non-goals. |
|
|
325
375
|
|
|
326
|
-
|
|
376
|
+
**Continuous integration:** `.github/workflows/ci.yml` (**push** / **PR** to **`main`**).
|
|
327
377
|
|
|
328
|
-
|
|
378
|
+
**License:** [LICENSE](LICENSE) (MIT).
|