context-mode 0.5.4 → 0.5.6
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 +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/build/server.js +19 -8
- package/build/store.d.ts +5 -1
- package/build/store.js +14 -4
- package/package.json +1 -1
- package/skills/context-mode/SKILL.md +17 -0
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"name": "context-mode",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 10 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
16
|
-
"version": "0.5.
|
|
16
|
+
"version": "0.5.6",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Mert Koseoğlu"
|
|
19
19
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 10 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mert Koseoğlu",
|
package/build/server.js
CHANGED
|
@@ -5,7 +5,7 @@ import { z } from "zod";
|
|
|
5
5
|
import { PolyglotExecutor } from "./executor.js";
|
|
6
6
|
import { ContentStore } from "./store.js";
|
|
7
7
|
import { detectRuntimes, getRuntimeSummary, getAvailableLanguages, hasBunRuntime, } from "./runtime.js";
|
|
8
|
-
const VERSION = "0.5.
|
|
8
|
+
const VERSION = "0.5.6";
|
|
9
9
|
const runtimes = detectRuntimes();
|
|
10
10
|
const available = getAvailableLanguages(runtimes);
|
|
11
11
|
const server = new McpServer({
|
|
@@ -128,7 +128,7 @@ function indexStdout(stdout, source) {
|
|
|
128
128
|
content: [
|
|
129
129
|
{
|
|
130
130
|
type: "text",
|
|
131
|
-
text: `Indexed ${indexed.totalChunks} sections (${indexed.codeChunks} with code) from: ${indexed.label}\nUse search() to query this content.`,
|
|
131
|
+
text: `Indexed ${indexed.totalChunks} sections (${indexed.codeChunks} with code) from: ${indexed.label}\nUse search() to query this content. Use source: "${indexed.label}" to scope results.`,
|
|
132
132
|
},
|
|
133
133
|
],
|
|
134
134
|
};
|
|
@@ -360,7 +360,7 @@ server.registerTool("index", {
|
|
|
360
360
|
content: [
|
|
361
361
|
{
|
|
362
362
|
type: "text",
|
|
363
|
-
text: `Indexed ${result.totalChunks} sections (${result.codeChunks} with code) from: ${result.label}\nUse search() to query this content.`,
|
|
363
|
+
text: `Indexed ${result.totalChunks} sections (${result.codeChunks} with code) from: ${result.label}\nUse search() to query this content. Use source: "${result.label}" to scope results.`,
|
|
364
364
|
},
|
|
365
365
|
],
|
|
366
366
|
};
|
|
@@ -389,9 +389,11 @@ server.registerTool("search", {
|
|
|
389
389
|
"- Get configuration details ('Tailwind responsive breakpoints')\n" +
|
|
390
390
|
"- Find migration steps ('App Router data fetching')\n\n" +
|
|
391
391
|
"SEARCH TIPS:\n" +
|
|
392
|
-
"-
|
|
392
|
+
"- Queries use OR semantics — results matching more terms rank higher via BM25\n" +
|
|
393
|
+
"- Use 2-4 specific technical terms per query for best results\n" +
|
|
394
|
+
"- Use 'source' parameter to scope search to a specific indexed source (partial match)\n" +
|
|
393
395
|
"- Check 'Searchable terms' from execute/execute_file results for available vocabulary\n" +
|
|
394
|
-
"-
|
|
396
|
+
"- For broad topics, send multiple focused searches in parallel\n\n" +
|
|
395
397
|
"Returns exact content — not summaries. Each result includes heading hierarchy and full section text.",
|
|
396
398
|
inputSchema: z.object({
|
|
397
399
|
query: z.string().describe("Natural language search query"),
|
|
@@ -400,17 +402,26 @@ server.registerTool("search", {
|
|
|
400
402
|
.optional()
|
|
401
403
|
.default(3)
|
|
402
404
|
.describe("Maximum results to return (default: 3)"),
|
|
405
|
+
source: z
|
|
406
|
+
.string()
|
|
407
|
+
.optional()
|
|
408
|
+
.describe("Filter results to a specific indexed source (partial match). " +
|
|
409
|
+
"Use the source label from index/fetch_and_index response."),
|
|
403
410
|
}),
|
|
404
|
-
}, async ({ query, limit }) => {
|
|
411
|
+
}, async ({ query, limit, source }) => {
|
|
405
412
|
try {
|
|
406
413
|
const store = getStore();
|
|
407
|
-
const results = store.search(query, limit);
|
|
414
|
+
const results = store.search(query, limit, source);
|
|
408
415
|
if (results.length === 0) {
|
|
416
|
+
const sources = store.listSources();
|
|
417
|
+
const sourceList = sources.length > 0
|
|
418
|
+
? `\nIndexed sources: ${sources.map((s) => `"${s.label}" (${s.chunkCount} sections)`).join(", ")}`
|
|
419
|
+
: "";
|
|
409
420
|
return {
|
|
410
421
|
content: [
|
|
411
422
|
{
|
|
412
423
|
type: "text",
|
|
413
|
-
text: `No results found for: "${query}"
|
|
424
|
+
text: `No results found for: "${query}"${source ? ` in source "${source}"` : ""}.${sourceList}`,
|
|
414
425
|
},
|
|
415
426
|
],
|
|
416
427
|
};
|
package/build/store.d.ts
CHANGED
|
@@ -39,7 +39,11 @@ export declare class ContentStore {
|
|
|
39
39
|
* look for headings — it chunks by line count with overlap.
|
|
40
40
|
*/
|
|
41
41
|
indexPlainText(content: string, source: string, linesPerChunk?: number): IndexResult;
|
|
42
|
-
search(query: string, limit?: number): SearchResult[];
|
|
42
|
+
search(query: string, limit?: number, source?: string): SearchResult[];
|
|
43
|
+
listSources(): Array<{
|
|
44
|
+
label: string;
|
|
45
|
+
chunkCount: number;
|
|
46
|
+
}>;
|
|
43
47
|
getDistinctiveTerms(sourceId: number, maxTerms?: number): string[];
|
|
44
48
|
getStats(): StoreStats;
|
|
45
49
|
close(): void;
|
package/build/store.js
CHANGED
|
@@ -40,7 +40,7 @@ function sanitizeQuery(query) {
|
|
|
40
40
|
!["AND", "OR", "NOT", "NEAR"].includes(w.toUpperCase()));
|
|
41
41
|
if (words.length === 0)
|
|
42
42
|
return '""';
|
|
43
|
-
return words.map((w) => `"${w}"`).join(" ");
|
|
43
|
+
return words.map((w) => `"${w}"`).join(" OR ");
|
|
44
44
|
}
|
|
45
45
|
// ─────────────────────────────────────────────────────────
|
|
46
46
|
// ContentStore
|
|
@@ -149,8 +149,9 @@ export class ContentStore {
|
|
|
149
149
|
};
|
|
150
150
|
}
|
|
151
151
|
// ── Search ──
|
|
152
|
-
search(query, limit = 3) {
|
|
152
|
+
search(query, limit = 3, source) {
|
|
153
153
|
const sanitized = sanitizeQuery(query);
|
|
154
|
+
const sourceFilter = source ? "AND sources.label LIKE ?" : "";
|
|
154
155
|
const stmt = this.#db.prepare(`
|
|
155
156
|
SELECT
|
|
156
157
|
chunks.title,
|
|
@@ -160,11 +161,14 @@ export class ContentStore {
|
|
|
160
161
|
bm25(chunks, 2.0, 1.0) AS rank
|
|
161
162
|
FROM chunks
|
|
162
163
|
JOIN sources ON sources.id = chunks.source_id
|
|
163
|
-
WHERE chunks MATCH ?
|
|
164
|
+
WHERE chunks MATCH ? ${sourceFilter}
|
|
164
165
|
ORDER BY rank
|
|
165
166
|
LIMIT ?
|
|
166
167
|
`);
|
|
167
|
-
const
|
|
168
|
+
const params = source
|
|
169
|
+
? [sanitized, `%${source}%`, limit]
|
|
170
|
+
: [sanitized, limit];
|
|
171
|
+
const rows = stmt.all(...params);
|
|
168
172
|
return rows.map((r) => ({
|
|
169
173
|
title: r.title,
|
|
170
174
|
content: r.content,
|
|
@@ -173,6 +177,12 @@ export class ContentStore {
|
|
|
173
177
|
contentType: r.content_type,
|
|
174
178
|
}));
|
|
175
179
|
}
|
|
180
|
+
// ── Sources ──
|
|
181
|
+
listSources() {
|
|
182
|
+
return this.#db
|
|
183
|
+
.prepare("SELECT label, chunk_count as chunkCount FROM sources ORDER BY id DESC")
|
|
184
|
+
.all();
|
|
185
|
+
}
|
|
176
186
|
// ── Vocabulary ──
|
|
177
187
|
getDistinctiveTerms(sourceId, maxTerms = 40) {
|
|
178
188
|
const stats = this.#db
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
|
|
6
6
|
"author": "Mert Koseoğlu",
|
|
@@ -92,6 +92,23 @@ Use context-mode for ANY of these, without being asked:
|
|
|
92
92
|
| Shell commands with pipes | `shell` | grep, awk, jq, native tools |
|
|
93
93
|
| File pattern matching | `shell` | find, wc, sort, uniq |
|
|
94
94
|
|
|
95
|
+
## Search Query Strategy
|
|
96
|
+
|
|
97
|
+
- BM25 uses **OR semantics** — results matching more terms rank higher automatically
|
|
98
|
+
- Use 2-4 specific technical terms per query: `search("transform refine pipe")`
|
|
99
|
+
- **Always use `source` parameter** when multiple docs are indexed to avoid cross-source contamination
|
|
100
|
+
- After `fetch_and_index` returns `source: "Zod API docs"`, use `search("refine", source: "Zod")`
|
|
101
|
+
- Partial match works: `source: "Node"` matches `"Node.js v22 CHANGELOG"`
|
|
102
|
+
- Send multiple `search()` calls **in parallel** for different aspects of a topic
|
|
103
|
+
- Example: instead of one broad search, send 3 focused parallel queries:
|
|
104
|
+
- `search("transform pipe", source: "Zod")` + `search("refine superRefine", source: "Zod")` + `search("coerce codec", source: "Zod")`
|
|
105
|
+
|
|
106
|
+
## External Documentation
|
|
107
|
+
|
|
108
|
+
- **Always use `fetch_and_index`** for external docs — NEVER `cat` or `execute` with local paths for packages you don't own
|
|
109
|
+
- For GitHub-hosted projects, use the raw URL: `https://raw.githubusercontent.com/org/repo/main/CHANGELOG.md`
|
|
110
|
+
- After indexing, use the `source` parameter in search to scope results to that specific document
|
|
111
|
+
|
|
95
112
|
## Critical Rules
|
|
96
113
|
|
|
97
114
|
1. **Always console.log/print your findings.** stdout is all that enters context. No output = wasted call.
|