promptgraph-mcp 2.9.8 → 2.9.10

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/README.md CHANGED
@@ -1,205 +1,235 @@
1
- # PromptGraph
2
-
3
- **Semantic skill router and marketplace for Claude Code.**
4
-
5
- Instead of loading every `.md` skill into your context, Claude calls `pg_search` and loads only the one skill it needs.
6
-
7
- [![npm](https://img.shields.io/npm/v/promptgraph-mcp?color=7C3AED&label=npm)](https://www.npmjs.com/package/promptgraph-mcp)
8
- [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
-
10
- ---
11
-
12
- ## How it works
13
-
14
- ```
15
- pg_search("refactor without breaking tests")
16
- → embed query (BGE-Small-EN, 384-dim)
17
- ANN index (HNSW by default, flat fallback) — topK×4 candidates
18
- → BM25 (FTS5) — topK×4 candidates
19
- → hybrid merge (embedWeight × cosine + bm25Weight × BM25)
20
- term-overlap reranker (TF frequency + header-position boost)
21
- → return topK skill paths + snippets
22
- Claude reads only the files it needs
23
- ```
24
-
25
- **Index:** SQLite + Float32 BLOB embeddings + HNSW approximate nearest neighbor (configurable: `PG_VECTOR_STORE=flat` for brute-force cosine). No external vector DB, no API key, no cloud.
26
-
27
- **Reranker:** lightweight term-overlap scorer (binary overlap + TF frequency + header-position boost). Not a cross-encoder — disable via `PG_RERANKER=0`.
28
-
29
- **File watcher:** `chokidar` detects `.md` changes and reindexes automatically (MCP server mode only).
30
-
31
- ---
32
-
33
- ## Benchmarks (measured on real hardware)
34
-
35
- | Operation | Result |
36
- |---|---|
37
- | 88 new skills indexed (first time, cold ONNX) | **49.5 s** |
38
- | 88 skills reindexed (unchanged, hash match) | **< 1 s** |
39
- | `pg reindex --fast` (3000 files, keyword only) | **~30 s** |
40
- | `pg reindex` full embed (3000 files) | **~30 min** |
41
- | Semantic search query (HNSW) | **< 50 ms** |
42
- | Semantic search query (flat, brute-force) | **< 200 ms** |
43
- | Model size (BGE-Small-EN-v1.5, one-time download) | **23 MB** |
44
- | Embedding dimensions | **384** |
45
- | Max chunks per skill | **8** (configurable: `PG_MAX_CHUNKS`) |
46
- | Embedding batch size | **256** |
47
-
48
- > ONNX model initialization (~2–3 min) happens once on first use and is cached in `~/.claude/.promptgraph/model-cache/`.
49
-
50
- ---
51
-
52
- ## Environment Variables
53
-
54
- | Variable | Default | Description |
55
- |---|---|---|
56
- | `PG_VECTOR_STORE` | `hnsw` | Vector index: `hnsw` (ANN, faster at scale) or `flat` (brute-force cosine) |
57
- | `PG_RERANKER` | `1` | Enable term-overlap reranker after hybrid search (set `0` to disable) |
58
- | `PG_MAX_CHUNKS` | `8` | Max semantic chunks per skill (higher = more detail per long file, more embedding cost) |
59
-
60
- ---
61
-
62
- ## Quick Start
63
-
64
- ```bash
65
- npm install -g promptgraph-mcp@latest
66
- pg init
67
- ```
68
-
69
- `pg init` downloads the model (~23 MB, once), indexes your local skills, and prints the config snippet.
70
-
71
- ### Claude Code (`~/.claude/settings.json`)
72
-
73
- ```json
74
- {
75
- "mcpServers": {
76
- "promptgraph": {
77
- "command": "npx",
78
- "args": ["promptgraph-mcp"]
79
- }
80
- }
81
- }
82
- ```
83
-
84
- ### Claude Desktop / Cursor / Windsurf / Cline
85
-
86
- Same config — any MCP-compatible client works.
87
-
88
- ### OpenCode (`~/.config/opencode/opencode.json`)
89
-
90
- ```json
91
- {
92
- "mcp": {
93
- "promptgraph": {
94
- "type": "local",
95
- "command": ["npx", "promptgraph-mcp"],
96
- "enabled": true
97
- }
98
- }
99
- }
100
- ```
101
-
102
- > `pg setup` auto-detects installed clients and writes config automatically.
103
-
104
- ---
105
-
106
- ## CLI
107
-
108
- ```bash
109
- pg init # first-time setup
110
- pg status # show indexed sources, repos, installed bundles
111
- pg reindex # full reindex (semantic search, slow)
112
- pg reindex --fast # keyword-only reindex (~30s, no embeddings)
113
- pg search "deploy" # search from terminal
114
- pg import owner/repo # clone and index any GitHub repo of .md skills
115
- pg marketplace # browse skills by category
116
- pg marketplace bundles # browse curated bundles
117
- pg bundle install <id> # install a bundle
118
- pg validate my-skill.md # validate before publishing
119
- pg doctor # clean orphaned DB rows
120
- pg update # update to latest version
121
- ```
122
-
123
- ---
124
-
125
- ## Marketplace
126
-
127
- ```bash
128
- pg marketplace # 🛠 Engineering 💻 Coding 🤖 AI Tools 🔒 Security 🎨 Creative
129
- pg marketplace Engineering # filter by category
130
- pg marketplace bundles # install whole repos as skill bundles
131
- ```
132
-
133
- **Bundles** install an entire GitHub repo as a skill source — auto-detects `skills/`, `commands/`, `prompts/` subdirectory.
134
-
135
- Example:
136
- ```bash
137
- pg bundle install elementalsouls-claude-bughunter # 88 security skills from GitHub
138
- pg bundle install engineering-essentials # 4 curated workflow skills
139
- ```
140
-
141
- **Publish your skill** (auto-validated, no manual review):
142
-
143
- Open an issue on [promptgraph-registry](https://github.com/NeiP4n/promptgraph-registry) with label `skill-submission`. The bot fetches, validates, commits, and closes the issue automatically.
144
-
145
- Anti-spam checks: min 200 chars, 2+ headers, code/bullets required, prompt injection detection, duplicate URL/description check, 3 submissions per user per 24h.
146
-
147
- ---
148
-
149
- ## MCP Tools
150
-
151
- Claude uses these automatically when the MCP server is running:
152
-
153
- | Tool | What it does |
154
- |---|---|
155
- | `pg_search` | Semantic search by task description |
156
- | `pg_list` | List all indexed skills |
157
- | `pg_context` | Full skill details + callers/callees |
158
- | `pg_callers` | Which skills reference this one |
159
- | `pg_callees` | Which skills this one calls |
160
- | `pg_impact` | What breaks if this skill changes |
161
- | `pg_marketplace_browse` | Browse community registry |
162
- | `pg_marketplace_install` | Install a skill by code or name |
163
- | `pg_bundle_browse` | Browse skill bundles |
164
- | `pg_bundle_install` | Install a bundle |
165
- | `pg_top_rated` | Highest-rated skills |
166
- | `pg_rate` | Rate a skill after use |
167
-
168
- ---
169
-
170
- ## Search modes
171
-
172
- Search runs a multi-stage pipeline:
173
-
174
- 1. **ANN retrieval** — HNSW approximate nearest neighbor (default) or flat brute-force cosine (`PG_VECTOR_STORE=flat`)
175
- 2. **BM25 keyword** SQLite FTS5
176
- 3. **Hybrid fusion** — weighted sum (embedding × embedWeight + BM25 × bm25Weight, adaptive per query)
177
- 4. **Reranker** term-overlap rescoring with TF frequency and header-position boost (disable via `PG_RERANKER=0`)
178
- 5. **Rating boost** success/fail history adjusts final ranking
179
-
180
- Falls back to FTS5 only if no embeddings exist.
181
-
182
- ---
183
-
184
- ## Skill filtering
185
-
186
- When importing a GitHub repo, PromptGraph:
187
- 1. Looks for a dedicated subdir (`skills/`, `commands/`, `prompts/`, `agents/`, `templates/`, etc.) — indexes only that dir if found with 2+ `.md` files
188
- 2. Falls back to repo root with content quality filter: min 150 chars, 2+ headers, must have code blocks or bullet points, skips readme/changelog/license/docs
189
-
190
- ---
191
-
192
- ## Requirements
193
-
194
- - Node.js 18+
195
- - Any MCP-compatible client (Claude Code, Claude Desktop, Cline, OpenCode, Cursor, Windsurf…)
196
-
197
- ---
198
-
199
- ## Related
200
-
201
- - 📋 [promptgraph-registry](https://github.com/NeiP4n/promptgraph-registry) — community skill registry and auto-publish bot
202
-
203
- ---
204
-
205
- *Built with [Claude Code](https://claude.com/claude-code).*
1
+ # PromptGraph
2
+
3
+ **Semantic skill router and marketplace for Claude Code and OpenCode.**
4
+
5
+ Instead of loading every `.md` skill into context, Claude calls `pg_search` and loads only the skill it needs — saving 20k+ tokens per session.
6
+
7
+ [![npm](https://img.shields.io/npm/v/promptgraph-mcp?color=7C3AED&label=npm)](https://www.npmjs.com/package/promptgraph-mcp)
8
+ [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
+
10
+ ---
11
+
12
+ ## Installation
13
+
14
+ **Requirements:** Node.js 18+ — [nodejs.org](https://nodejs.org)
15
+
16
+ ```bash
17
+ npm install -g promptgraph-mcp@latest
18
+ ```
19
+
20
+ Check version:
21
+ ```bash
22
+ pg --version
23
+ ```
24
+
25
+ Update to latest:
26
+ ```bash
27
+ pg update
28
+ # or
29
+ npm install -g promptgraph-mcp@latest
30
+ ```
31
+
32
+ Uninstall:
33
+ ```bash
34
+ npm uninstall -g promptgraph-mcp
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Quick Start
40
+
41
+ ```bash
42
+ npm install -g promptgraph-mcp@latest
43
+ pg init
44
+ ```
45
+
46
+ `pg init` auto-detects your installed editor, downloads the embedding model (~23 MB, once), indexes your skills, and writes the config automatically.
47
+
48
+ ---
49
+
50
+ ## Setup
51
+
52
+ ### Claude Code
53
+
54
+ **Option 1 auto (recommended):**
55
+ ```bash
56
+ pg init
57
+ # or
58
+ pg setup claude-code
59
+ ```
60
+
61
+ **Option 2 — manual.** Add to `~/.claude/settings.json`:
62
+ ```json
63
+ {
64
+ "mcpServers": {
65
+ "promptgraph": {
66
+ "command": "npx",
67
+ "args": ["promptgraph-mcp"]
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ **Option 3 — official plugin:**
74
+ ```
75
+ /plugin install promptgraph@claude-community
76
+ ```
77
+
78
+ ### OpenCode
79
+
80
+ **Option 1 — auto (recommended):**
81
+ ```bash
82
+ pg init
83
+ # or
84
+ pg setup opencode
85
+ ```
86
+
87
+ **Option 2 — manual.** Add to `~/.config/opencode/opencode.json`:
88
+ ```json
89
+ {
90
+ "plugin": ["promptgraph-mcp/plugin"]
91
+ }
92
+ ```
93
+
94
+ ### Other clients
95
+
96
+ | Client | Command |
97
+ |---|---|
98
+ | Claude Desktop | `pg setup claude-desktop` |
99
+ | Cursor | `pg setup cursor` |
100
+ | Windsurf | `pg setup windsurf` |
101
+ | Cline | `pg setup cline` |
102
+ | OpenAI Codex CLI | `pg setup codex` |
103
+
104
+ ---
105
+
106
+ ## Install skill bundles
107
+
108
+ ```bash
109
+ pg install engineering-best-practices
110
+ pg install pg-000001
111
+ pg install "LLM Prompts"
112
+ ```
113
+
114
+ Or browse interactively:
115
+ ```bash
116
+ pg marketplace
117
+ ```
118
+
119
+ ---
120
+
121
+ ## CLI
122
+
123
+ ```bash
124
+ pg init # first-time setup (auto-detects editor)
125
+ pg setup <platform> # register MCP in a specific editor
126
+ pg install <name> # install a bundle by name, code, or id
127
+ pg marketplace # browse + search + install (interactive TUI)
128
+ pg status # show indexed sources, repos, installed bundles
129
+ pg reindex # full reindex (semantic + keyword)
130
+ pg reindex --fast # keyword-only reindex (~30 s)
131
+ pg search "deploy" # search from terminal
132
+ pg import owner/repo # import any GitHub repo of .md skills
133
+ pg bundle update # update all installed bundles
134
+ pg validate my-skill.md # validate before publishing
135
+ pg doctor # clean orphaned DB rows
136
+ pg update # update to latest version
137
+ ```
138
+
139
+ ---
140
+
141
+ ## How it works
142
+
143
+ ```
144
+ pg_search("refactor without breaking tests")
145
+ embed query (BGE-Small-EN, 384-dim)
146
+ → HNSW ANN index — topK×4 candidates
147
+ → BM25 FTS5 — topK×4 candidates
148
+ → hybrid merge (cosine + BM25, adaptive weights)
149
+ term-overlap reranker (TF + header-position boost)
150
+ → return topK skill paths + snippets
151
+ Claude reads only the files it needs
152
+ ```
153
+
154
+ **Index:** SQLite + Float32 BLOB embeddings + HNSW. No external vector DB, no API key, no cloud.
155
+
156
+ ---
157
+
158
+ ## Marketplace
159
+
160
+ ```bash
161
+ pg marketplace # 🛠 Engineering 💻 Coding 🤖 AI 🔒 Security 🎨 Creative
162
+ pg marketplace bundles # curated GitHub repos as skill bundles
163
+ ```
164
+
165
+ **Bundles** clone a GitHub repo and index only the skill files — auto-detects `skills/`, `commands/`, `prompts/` subdirectory.
166
+
167
+ **Publish your skill** — open an issue on [promptgraph-registry](https://github.com/NeiP4n/promptgraph-registry) with label `skill-submission`. The bot validates, commits, and closes automatically.
168
+
169
+ ---
170
+
171
+ ## MCP Tools
172
+
173
+ Claude uses these automatically when the server is running:
174
+
175
+ | Tool | Description |
176
+ |---|---|
177
+ | `pg_search` | Semantic search by task description |
178
+ | `pg_list` | List all indexed skills |
179
+ | `pg_context` | Full skill details + callers/callees |
180
+ | `pg_callers` | Which skills reference this one |
181
+ | `pg_callees` | Which skills this one calls |
182
+ | `pg_impact` | What breaks if this skill changes |
183
+ | `pg_marketplace_browse` | Browse community registry |
184
+ | `pg_marketplace_install` | Install a skill by code or name |
185
+ | `pg_bundle_browse` | Browse skill bundles |
186
+ | `pg_bundle_install` | Install a bundle |
187
+ | `pg_top_rated` | Highest-rated skills |
188
+ | `pg_rate` | Rate a skill after use |
189
+
190
+ ---
191
+
192
+ ## Environment Variables
193
+
194
+ | Variable | Default | Description |
195
+ |---|---|---|
196
+ | `PG_VECTOR_STORE` | `hnsw` | `hnsw` (ANN) or `flat` (brute-force cosine) |
197
+ | `PG_RERANKER` | `1` | Term-overlap reranker — set `0` to disable |
198
+ | `PG_MAX_CHUNKS` | `8` | Max semantic chunks per skill file |
199
+
200
+ ---
201
+
202
+ ## Skill filtering
203
+
204
+ When importing a GitHub repo, PromptGraph:
205
+ 1. Looks for a dedicated subdir (`skills/`, `commands/`, `prompts/`, `agents/`, etc.) — indexes only that if found
206
+ 2. Falls back to repo root with a content quality filter: min 150 chars, 2+ headers, code blocks or bullets required, skips readme/changelog/license
207
+
208
+ ---
209
+
210
+ ## Benchmarks
211
+
212
+ | Operation | Result |
213
+ |---|---|
214
+ | 88 new skills (cold ONNX) | **49.5 s** |
215
+ | 88 skills (unchanged, hash match) | **< 1 s** |
216
+ | `pg reindex --fast` (3000 files) | **~30 s** |
217
+ | Semantic search (HNSW) | **< 50 ms** |
218
+ | Model size (BGE-Small-EN-v1.5, one-time) | **23 MB** |
219
+
220
+ ---
221
+
222
+ ## Requirements
223
+
224
+ - Node.js 18+
225
+ - Claude Code, OpenCode, Cursor, Windsurf, Cline, or any MCP-compatible client
226
+
227
+ ---
228
+
229
+ ## Related
230
+
231
+ - 📋 [promptgraph-registry](https://github.com/NeiP4n/promptgraph-registry) — community skill registry
232
+
233
+ ---
234
+
235
+ *Built with [Claude Code](https://claude.com/claude-code).*
package/index.js CHANGED
@@ -18,7 +18,7 @@ const args = process.argv.slice(2);
18
18
  const rawBin = process.argv[1]?.split(/[\\/]/).pop()?.replace(/\.js$/, '');
19
19
  const bin = (rawBin && rawBin !== 'index') ? rawBin : 'pg';
20
20
 
21
- const KNOWN_COMMANDS = new Set(['init', 'reindex', 'update', 'import', 'install', 'setup', 'validate', 'marketplace', 'doctor', 'search', 'help', '--help', '-h', 'bundle', 'status', 'train']);
21
+ const KNOWN_COMMANDS = new Set(['init', 'reindex', 'update', 'import', 'install', 'setup', 'validate', 'marketplace', 'doctor', 'search', 'help', '--help', '-h', '--version', '-v', 'version', 'bundle', 'status', 'train']);
22
22
 
23
23
  function showHelp() {
24
24
  console.log(
@@ -57,6 +57,14 @@ if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h') {
57
57
  process.exit(0);
58
58
  }
59
59
 
60
+ // Version flag
61
+ if (args[0] === '--version' || args[0] === '-v' || args[0] === 'version') {
62
+ const { createRequire } = await import('module');
63
+ const _pkg = createRequire(import.meta.url)('./package.json');
64
+ console.log(_pkg.version);
65
+ process.exit(0);
66
+ }
67
+
60
68
  // No args: if launched from an interactive terminal, show help.
61
69
  // If stdin is a pipe (i.e. an MCP client like Claude), fall through and
62
70
  // start the server — NEVER print to stdout here, it corrupts JSON-RPC.
package/marketplace.js CHANGED
@@ -359,9 +359,21 @@ async function _findBundle(bundleId) {
359
359
  const text = await fetchText(REGISTRY_URL);
360
360
  const registry = JSON.parse(text);
361
361
  const q = String(bundleId).trim().toLowerCase();
362
+ const valid = (registry.bundles || []).filter(b => validateRegistryEntry(b).ok);
362
363
  const validSkills = (registry.skills || []).filter(s => validateRegistryEntry(s).ok);
363
- const bundle = (registry.bundles || []).filter(b => validateRegistryEntry(b).ok).find(b =>
364
- (b.code || codeFor(b.id)).toLowerCase() === q || b.id?.toLowerCase() === q || b.name?.toLowerCase() === q
364
+ // 1. Exact match (code, id, name)
365
+ let bundle = valid.find(b =>
366
+ (b.code || codeFor(b.id)).toLowerCase() === q ||
367
+ b.id?.toLowerCase() === q ||
368
+ b.name?.toLowerCase() === q
369
+ );
370
+ // 2. Partial name/id match (starts with)
371
+ if (!bundle) bundle = valid.find(b =>
372
+ b.name?.toLowerCase().startsWith(q) || b.id?.toLowerCase().startsWith(q)
373
+ );
374
+ // 3. Contains match
375
+ if (!bundle) bundle = valid.find(b =>
376
+ b.name?.toLowerCase().includes(q) || b.id?.toLowerCase().includes(q)
365
377
  );
366
378
  if (!bundle) return { error: `No bundle matching "${bundleId}"` };
367
379
  return { bundle, validSkills };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptgraph-mcp",
3
- "version": "2.9.8",
3
+ "version": "2.9.10",
4
4
  "files": [
5
5
  "*.js",
6
6
  "commands/",
package/platform.js CHANGED
@@ -88,12 +88,15 @@ export function detectPlatforms() {
88
88
 
89
89
  function isBinaryInstalled(bin) {
90
90
  try {
91
- const r = spawnSync(bin, ['--version'], { encoding: 'utf8', timeout: 3000, stdio: 'pipe' });
92
- return r.status === 0;
91
+ const cmd = process.platform === 'win32' ? 'where' : 'which';
92
+ const r = spawnSync(cmd, [bin], { encoding: 'utf8', timeout: 3000, stdio: 'pipe' });
93
+ return r.status === 0 && r.stdout.trim().length > 0;
93
94
  } catch { return false; }
94
95
  }
95
96
 
96
- function isOpenCodeInstalled() { return isBinaryInstalled('opencode'); }
97
+ function isOpenCodeInstalled() {
98
+ return isBinaryInstalled('opencode') || isBinaryInstalled('OpenCode');
99
+ }
97
100
  function isClaudeCodeInstalled() { return isBinaryInstalled('claude'); }
98
101
 
99
102
  function getOpenCodeConfig() {