purecontext-mcp 1.2.0 → 1.5.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.
Files changed (177) hide show
  1. package/AGENT_INSTRUCTIONS.md +110 -784
  2. package/AGENT_REFERENCE.md +561 -0
  3. package/CHANGELOG.md +177 -6
  4. package/FRAMEWORK-ADAPTERS.md +351 -0
  5. package/LANGUAGE-SUPPORT.md +144 -0
  6. package/README.md +92 -12
  7. package/USER-GUIDE.md +8 -0
  8. package/dist/cli/hooks.d.ts +28 -0
  9. package/dist/cli/hooks.d.ts.map +1 -0
  10. package/dist/cli/hooks.js +570 -0
  11. package/dist/cli/hooks.js.map +1 -0
  12. package/dist/cli/install-detect.d.ts +16 -0
  13. package/dist/cli/install-detect.d.ts.map +1 -0
  14. package/dist/cli/install-detect.js +70 -0
  15. package/dist/cli/install-detect.js.map +1 -0
  16. package/dist/cli/install-writers.d.ts +59 -0
  17. package/dist/cli/install-writers.d.ts.map +1 -0
  18. package/dist/cli/install-writers.js +292 -0
  19. package/dist/cli/install-writers.js.map +1 -0
  20. package/dist/cli/install.d.ts +14 -0
  21. package/dist/cli/install.d.ts.map +1 -0
  22. package/dist/cli/install.js +150 -0
  23. package/dist/cli/install.js.map +1 -0
  24. package/dist/config/config-loader.js +3 -0
  25. package/dist/config/config-loader.js.map +1 -1
  26. package/dist/config/config-schema.d.ts +11 -0
  27. package/dist/config/config-schema.d.ts.map +1 -1
  28. package/dist/config/config-schema.js +15 -0
  29. package/dist/config/config-schema.js.map +1 -1
  30. package/dist/core/db/symbol-store.d.ts +1 -0
  31. package/dist/core/db/symbol-store.d.ts.map +1 -1
  32. package/dist/core/db/symbol-store.js +120 -6
  33. package/dist/core/db/symbol-store.js.map +1 -1
  34. package/dist/core/file-discovery.d.ts +6 -0
  35. package/dist/core/file-discovery.d.ts.map +1 -1
  36. package/dist/core/file-discovery.js +20 -13
  37. package/dist/core/file-discovery.js.map +1 -1
  38. package/dist/core/file-processor.d.ts.map +1 -1
  39. package/dist/core/file-processor.js +26 -1
  40. package/dist/core/file-processor.js.map +1 -1
  41. package/dist/core/git-log-reader.d.ts.map +1 -1
  42. package/dist/core/git-log-reader.js +21 -0
  43. package/dist/core/git-log-reader.js.map +1 -1
  44. package/dist/core/index-manager.d.ts.map +1 -1
  45. package/dist/core/index-manager.js +21 -7
  46. package/dist/core/index-manager.js.map +1 -1
  47. package/dist/core/indexing-worker.d.ts.map +1 -1
  48. package/dist/core/indexing-worker.js +14 -0
  49. package/dist/core/indexing-worker.js.map +1 -1
  50. package/dist/core/parse-dispatcher.d.ts.map +1 -1
  51. package/dist/core/parse-dispatcher.js +20 -5
  52. package/dist/core/parse-dispatcher.js.map +1 -1
  53. package/dist/core/search/query-preprocessor.d.ts +69 -3
  54. package/dist/core/search/query-preprocessor.d.ts.map +1 -1
  55. package/dist/core/search/query-preprocessor.js +450 -17
  56. package/dist/core/search/query-preprocessor.js.map +1 -1
  57. package/dist/core/search/relevance-ranker.d.ts +60 -5
  58. package/dist/core/search/relevance-ranker.d.ts.map +1 -1
  59. package/dist/core/search/relevance-ranker.js +931 -33
  60. package/dist/core/search/relevance-ranker.js.map +1 -1
  61. package/dist/core/test-mapper.d.ts.map +1 -1
  62. package/dist/core/test-mapper.js +7 -1
  63. package/dist/core/test-mapper.js.map +1 -1
  64. package/dist/core/types.d.ts +28 -1
  65. package/dist/core/types.d.ts.map +1 -1
  66. package/dist/handlers/angular-html.d.ts +3 -0
  67. package/dist/handlers/angular-html.d.ts.map +1 -0
  68. package/dist/handlers/angular-html.js +215 -0
  69. package/dist/handlers/angular-html.js.map +1 -0
  70. package/dist/handlers/c.d.ts.map +1 -1
  71. package/dist/handlers/c.js +19 -0
  72. package/dist/handlers/c.js.map +1 -1
  73. package/dist/handlers/cpp-macro-registry.d.ts +21 -0
  74. package/dist/handlers/cpp-macro-registry.d.ts.map +1 -0
  75. package/dist/handlers/cpp-macro-registry.js +44 -0
  76. package/dist/handlers/cpp-macro-registry.js.map +1 -0
  77. package/dist/handlers/cpp.d.ts.map +1 -1
  78. package/dist/handlers/cpp.js +579 -10
  79. package/dist/handlers/cpp.js.map +1 -1
  80. package/dist/handlers/csharp.d.ts.map +1 -1
  81. package/dist/handlers/csharp.js +39 -2
  82. package/dist/handlers/csharp.js.map +1 -1
  83. package/dist/handlers/css.d.ts +3 -0
  84. package/dist/handlers/css.d.ts.map +1 -0
  85. package/dist/handlers/css.js +154 -0
  86. package/dist/handlers/css.js.map +1 -0
  87. package/dist/handlers/erlang.d.ts.map +1 -1
  88. package/dist/handlers/erlang.js +8 -1
  89. package/dist/handlers/erlang.js.map +1 -1
  90. package/dist/handlers/fortran.js +1 -1
  91. package/dist/handlers/fortran.js.map +1 -1
  92. package/dist/handlers/go.d.ts.map +1 -1
  93. package/dist/handlers/go.js +87 -2
  94. package/dist/handlers/go.js.map +1 -1
  95. package/dist/handlers/handler-registry.d.ts.map +1 -1
  96. package/dist/handlers/handler-registry.js +4 -0
  97. package/dist/handlers/handler-registry.js.map +1 -1
  98. package/dist/handlers/hcl.d.ts +3 -0
  99. package/dist/handlers/hcl.d.ts.map +1 -0
  100. package/dist/handlers/hcl.js +193 -0
  101. package/dist/handlers/hcl.js.map +1 -0
  102. package/dist/handlers/java.d.ts.map +1 -1
  103. package/dist/handlers/java.js +33 -16
  104. package/dist/handlers/java.js.map +1 -1
  105. package/dist/handlers/kotlin.d.ts.map +1 -1
  106. package/dist/handlers/kotlin.js +48 -3
  107. package/dist/handlers/kotlin.js.map +1 -1
  108. package/dist/handlers/less.d.ts +3 -0
  109. package/dist/handlers/less.d.ts.map +1 -0
  110. package/dist/handlers/less.js +255 -0
  111. package/dist/handlers/less.js.map +1 -0
  112. package/dist/handlers/objective-c.d.ts.map +1 -1
  113. package/dist/handlers/objective-c.js +122 -64
  114. package/dist/handlers/objective-c.js.map +1 -1
  115. package/dist/handlers/openapi.d.ts.map +1 -1
  116. package/dist/handlers/openapi.js +30 -5
  117. package/dist/handlers/openapi.js.map +1 -1
  118. package/dist/handlers/php.d.ts.map +1 -1
  119. package/dist/handlers/php.js +287 -41
  120. package/dist/handlers/php.js.map +1 -1
  121. package/dist/handlers/protobuf.d.ts.map +1 -1
  122. package/dist/handlers/protobuf.js +1 -0
  123. package/dist/handlers/protobuf.js.map +1 -1
  124. package/dist/handlers/python.d.ts.map +1 -1
  125. package/dist/handlers/python.js +1 -3
  126. package/dist/handlers/python.js.map +1 -1
  127. package/dist/handlers/ruby-dsl.d.ts +23 -0
  128. package/dist/handlers/ruby-dsl.d.ts.map +1 -0
  129. package/dist/handlers/ruby-dsl.js +251 -0
  130. package/dist/handlers/ruby-dsl.js.map +1 -0
  131. package/dist/handlers/ruby.d.ts.map +1 -1
  132. package/dist/handlers/ruby.js +29 -4
  133. package/dist/handlers/ruby.js.map +1 -1
  134. package/dist/handlers/rust.d.ts.map +1 -1
  135. package/dist/handlers/rust.js +98 -2
  136. package/dist/handlers/rust.js.map +1 -1
  137. package/dist/handlers/scss.d.ts +3 -0
  138. package/dist/handlers/scss.d.ts.map +1 -0
  139. package/dist/handlers/scss.js +290 -0
  140. package/dist/handlers/scss.js.map +1 -0
  141. package/dist/handlers/sql.d.ts.map +1 -1
  142. package/dist/handlers/sql.js +37 -18
  143. package/dist/handlers/sql.js.map +1 -1
  144. package/dist/handlers/typescript.d.ts.map +1 -1
  145. package/dist/handlers/typescript.js +65 -17
  146. package/dist/handlers/typescript.js.map +1 -1
  147. package/dist/handlers/xml.d.ts.map +1 -1
  148. package/dist/handlers/xml.js +35 -2
  149. package/dist/handlers/xml.js.map +1 -1
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.js +91 -0
  152. package/dist/index.js.map +1 -1
  153. package/dist/server/mcp-server.d.ts.map +1 -1
  154. package/dist/server/mcp-server.js +10 -0
  155. package/dist/server/mcp-server.js.map +1 -1
  156. package/dist/server/tools/detect-antipatterns.d.ts +1 -1
  157. package/dist/server/tools/get-architecture-snapshot.d.ts +1 -1
  158. package/dist/server/tools/get-entry-points.d.ts +1 -1
  159. package/dist/server/tools/get-lexical-scope-matches.d.ts +54 -0
  160. package/dist/server/tools/get-lexical-scope-matches.d.ts.map +1 -0
  161. package/dist/server/tools/get-lexical-scope-matches.js +470 -0
  162. package/dist/server/tools/get-lexical-scope-matches.js.map +1 -0
  163. package/dist/server/tools/search-symbols.d.ts +10 -0
  164. package/dist/server/tools/search-symbols.d.ts.map +1 -1
  165. package/dist/server/tools/search-symbols.js +353 -8
  166. package/dist/server/tools/search-symbols.js.map +1 -1
  167. package/dist/server/tools/trace-invocation-chain.d.ts +53 -0
  168. package/dist/server/tools/trace-invocation-chain.d.ts.map +1 -0
  169. package/dist/server/tools/trace-invocation-chain.js +280 -0
  170. package/dist/server/tools/trace-invocation-chain.js.map +1 -0
  171. package/dist/version.d.ts +1 -1
  172. package/dist/version.js +1 -1
  173. package/docs/02-installation.md +89 -17
  174. package/docs/05-cli-reference.md +89 -0
  175. package/docs/dev/benchmark-findings-eu-za-tebe.md +210 -0
  176. package/docs/dev/phase-35-coverage-audit.md +469 -0
  177. package/package.json +4 -1
@@ -0,0 +1,280 @@
1
+ /**
2
+ * trace-invocation-chain.ts
3
+ *
4
+ * MCP tool: trace_invocation_chain
5
+ *
6
+ * Trace multi-hop call chains from a start symbol forward through callees,
7
+ * returning all discovered paths as ordered symbol lists. Useful for questions
8
+ * like "what execution path leads from this API endpoint to a background worker?"
9
+ *
10
+ * Strategy: query-time text scan (same as get_call_hierarchy) — no pre-built
11
+ * call edges required. Scans symbol source text for `identifier(` patterns and
12
+ * matches them against all indexed symbols in the repo.
13
+ *
14
+ * Cycle detection: back-edges are included as leaf nodes with `cyclic: true`
15
+ * so the traversal terminates and the caller can see the cycle.
16
+ */
17
+ import { z } from 'zod';
18
+ import { openDatabase, getRepo } from '../../core/db/schema.js';
19
+ import { getSymbolsByRepo } from '../../core/db/symbol-store.js';
20
+ import { getFileContent } from '../../core/db/file-store.js';
21
+ import { buildMeta } from './_meta.js';
22
+ export const name = 'trace_invocation_chain';
23
+ export const description = 'Trace all call chains from a start symbol forward through its callees, ' +
24
+ 'returning each discovered path as an ordered list of symbols. ' +
25
+ 'Use endHint to truncate chains at a symbol matching a glob pattern ' +
26
+ '(e.g. "*Worker", "*Service"). ' +
27
+ 'Cycles are detected and annotated with cyclic=true rather than looping. ' +
28
+ 'Useful for multi-hop traces like "route handler → service → background worker". ' +
29
+ 'Use search_symbols to find the symbolId or name of the start symbol first.';
30
+ export const inputSchema = {
31
+ repoId: z.string().describe('Repository ID returned by index_folder or list_repos'),
32
+ startSymbol: z
33
+ .string()
34
+ .min(1)
35
+ .describe('Name (or symbolId) of the entry point symbol to start tracing from. ' +
36
+ 'If multiple symbols share the name, all are used as starting points.'),
37
+ endHint: z
38
+ .string()
39
+ .optional()
40
+ .describe('Glob-style pattern for terminal symbols (e.g. "*Worker", "*Job", "Background*"). ' +
41
+ 'Chains stop when a symbol matching this pattern is found, even before maxDepth. ' +
42
+ 'Supports * as wildcard. When omitted, chains end at leaves (no further callees).'),
43
+ maxDepth: z
44
+ .number()
45
+ .int()
46
+ .min(1)
47
+ .max(10)
48
+ .optional()
49
+ .describe('Maximum chain depth (default 6)'),
50
+ maxChains: z
51
+ .number()
52
+ .int()
53
+ .min(1)
54
+ .max(200)
55
+ .optional()
56
+ .describe('Maximum number of chains to return (default 50)'),
57
+ includeDynamicCalls: z
58
+ .boolean()
59
+ .optional()
60
+ .describe('When true, include symbols tagged with frameworkMeta.dynamicDispatch=true ' +
61
+ '(e.g. method_missing handlers) as potential callees. Default false.'),
62
+ };
63
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
64
+ // Keywords that match `\bword(` but are not function calls.
65
+ const CALL_SKIP = new Set([
66
+ 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'catch',
67
+ 'finally', 'try', 'new', 'return', 'throw', 'typeof', 'instanceof',
68
+ 'function', 'class', 'import', 'export', 'const', 'let', 'var',
69
+ 'async', 'await', 'yield', 'delete', 'void', 'in', 'of', 'super',
70
+ 'this', 'true', 'false', 'null', 'undefined',
71
+ ]);
72
+ /** Callable symbol kinds — only these are expanded as callee targets. */
73
+ const CALLABLE_KINDS = new Set([
74
+ 'function', 'method', 'hook', 'composable', 'route', 'middleware',
75
+ ]);
76
+ function extractCallNames(text) {
77
+ const names = new Set();
78
+ const re = /\b([A-Za-z_$][\w$]*)\s*\(/g;
79
+ let m;
80
+ while ((m = re.exec(text)) !== null) {
81
+ const n = m[1];
82
+ if (!CALL_SKIP.has(n))
83
+ names.add(n);
84
+ }
85
+ return names;
86
+ }
87
+ /** Glob-style match: only * as wildcard, anchored to full string. */
88
+ function globMatch(pattern, value) {
89
+ const escaped = pattern.replace(/[$()+.?[\\\]^{|}]/g, '\\$&').replace(/\*/g, '.*');
90
+ return new RegExp(`^${escaped}$`).test(value);
91
+ }
92
+ // ─── Handler ──────────────────────────────────────────────────────────────────
93
+ export async function handler(args) {
94
+ const t0 = Date.now();
95
+ const { repoId, startSymbol, endHint, maxDepth = 6, maxChains = 50, includeDynamicCalls = false, } = args;
96
+ const db = openDatabase(repoId);
97
+ try {
98
+ const repo = getRepo(db, repoId);
99
+ if (!repo) {
100
+ return {
101
+ content: [
102
+ {
103
+ type: 'text',
104
+ text: JSON.stringify({ error: `Repository not found: ${repoId}` }),
105
+ },
106
+ ],
107
+ isError: true,
108
+ };
109
+ }
110
+ // ── Load all symbols ─────────────────────────────────────────────────────
111
+ const allSymbols = getSymbolsByRepo(db, repoId, 1_000_000);
112
+ // Build name → SymbolRecord[] index (both full name and short name for methods)
113
+ const byName = new Map();
114
+ const byId = new Map();
115
+ for (const sym of allSymbols) {
116
+ byId.set(sym.id, sym);
117
+ const names = [sym.name];
118
+ if (sym.name.includes('.'))
119
+ names.push(sym.name.split('.').pop());
120
+ for (const n of names) {
121
+ const list = byName.get(n) ?? [];
122
+ list.push(sym);
123
+ byName.set(n, list);
124
+ }
125
+ }
126
+ // ── Resolve start symbol(s) ──────────────────────────────────────────────
127
+ // Support both name lookup and direct symbolId
128
+ let startSymbols;
129
+ if (byId.has(startSymbol)) {
130
+ startSymbols = [byId.get(startSymbol)];
131
+ }
132
+ else {
133
+ startSymbols = byName.get(startSymbol) ?? [];
134
+ }
135
+ if (startSymbols.length === 0) {
136
+ return {
137
+ content: [
138
+ {
139
+ type: 'text',
140
+ text: JSON.stringify({
141
+ chains: [],
142
+ truncated: false,
143
+ error: `Symbol not found: ${startSymbol}`,
144
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
145
+ }),
146
+ },
147
+ ],
148
+ };
149
+ }
150
+ // ── File content cache ───────────────────────────────────────────────────
151
+ const fileCache = new Map();
152
+ function getContent(filePath) {
153
+ if (!fileCache.has(filePath)) {
154
+ fileCache.set(filePath, getFileContent(db, repoId, filePath));
155
+ }
156
+ return fileCache.get(filePath) ?? null;
157
+ }
158
+ function symbolText(sym) {
159
+ const buf = getContent(sym.filePath);
160
+ if (!buf)
161
+ return '';
162
+ return buf.slice(sym.startByte, Math.min(sym.endByte, buf.length)).toString('utf8');
163
+ }
164
+ /** Direct callees of a symbol (by text scan). */
165
+ function calleesOf(sym) {
166
+ const text = symbolText(sym);
167
+ const callNames = extractCallNames(text);
168
+ const seen = new Set();
169
+ const result = [];
170
+ for (const cname of callNames) {
171
+ const candidates = byName.get(cname) ?? [];
172
+ for (const cand of candidates) {
173
+ if (cand.id === sym.id)
174
+ continue;
175
+ if (!CALLABLE_KINDS.has(cand.kind))
176
+ continue;
177
+ if (!includeDynamicCalls) {
178
+ // Skip dynamic dispatch symbols unless explicitly included
179
+ const meta = cand.frameworkMeta;
180
+ if (meta?.['dynamicDispatch'] === true)
181
+ continue;
182
+ }
183
+ if (!seen.has(cand.id)) {
184
+ seen.add(cand.id);
185
+ result.push(cand);
186
+ }
187
+ }
188
+ }
189
+ return result;
190
+ }
191
+ // ── DFS to collect chains ────────────────────────────────────────────────
192
+ const chains = [];
193
+ let overallTruncated = false;
194
+ function toChainNode(sym, cyclic = false) {
195
+ return {
196
+ symbolId: sym.id,
197
+ name: sym.name,
198
+ kind: sym.kind,
199
+ filePath: sym.filePath,
200
+ signature: sym.signature,
201
+ ...(cyclic ? { cyclic: true } : {}),
202
+ };
203
+ }
204
+ function dfs(sym, currentPath, visitedInPath, depth) {
205
+ if (chains.length >= maxChains) {
206
+ overallTruncated = true;
207
+ return;
208
+ }
209
+ // Check if this symbol matches endHint
210
+ const matchesEnd = endHint ? globMatch(endHint, sym.name) : false;
211
+ if (matchesEnd) {
212
+ // Terminal: endHint matched
213
+ const nodes = [...currentPath.map((s) => toChainNode(s)), toChainNode(sym)];
214
+ chains.push({ nodes, truncatedByDepth: false, endedAtHint: true });
215
+ return;
216
+ }
217
+ if (depth >= maxDepth) {
218
+ // Truncated by depth
219
+ const nodes = [...currentPath, sym].map((s) => toChainNode(s));
220
+ chains.push({ nodes, truncatedByDepth: true, endedAtHint: false });
221
+ return;
222
+ }
223
+ const callees = calleesOf(sym);
224
+ if (callees.length === 0) {
225
+ // Leaf node — emit chain
226
+ const nodes = [...currentPath, sym].map((s) => toChainNode(s));
227
+ chains.push({ nodes, truncatedByDepth: false, endedAtHint: false });
228
+ return;
229
+ }
230
+ // Expand callees
231
+ for (const callee of callees) {
232
+ if (chains.length >= maxChains) {
233
+ overallTruncated = true;
234
+ break;
235
+ }
236
+ if (visitedInPath.has(callee.id)) {
237
+ // Cycle detected — emit current path with cyclic leaf
238
+ const nodes = [
239
+ ...currentPath.map((s) => toChainNode(s)),
240
+ toChainNode(sym),
241
+ toChainNode(callee, true),
242
+ ];
243
+ chains.push({ nodes, truncatedByDepth: false, endedAtHint: false });
244
+ continue;
245
+ }
246
+ const nextPath = [...currentPath, sym];
247
+ const nextVisited = new Set(visitedInPath);
248
+ nextVisited.add(sym.id);
249
+ dfs(callee, nextPath, nextVisited, depth + 1);
250
+ }
251
+ }
252
+ for (const start of startSymbols) {
253
+ if (chains.length >= maxChains) {
254
+ overallTruncated = true;
255
+ break;
256
+ }
257
+ dfs(start, [], new Set([start.id]), 0);
258
+ }
259
+ const tokenEstimate = Math.ceil(chains.reduce((sum, c) => sum + c.nodes.reduce((s, n) => s + n.name.length + n.filePath.length + 40, 0), 0) / 4);
260
+ return {
261
+ content: [
262
+ {
263
+ type: 'text',
264
+ text: JSON.stringify({
265
+ chains,
266
+ totalChains: chains.length,
267
+ truncated: overallTruncated,
268
+ startSymbol,
269
+ _tokenEstimate: tokenEstimate,
270
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
271
+ }, null, 2),
272
+ },
273
+ ],
274
+ };
275
+ }
276
+ finally {
277
+ db.close();
278
+ }
279
+ }
280
+ //# sourceMappingURL=trace-invocation-chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-invocation-chain.js","sourceRoot":"","sources":["../../../src/server/tools/trace-invocation-chain.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "1.2.0";
1
+ export declare const VERSION = "1.5.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '1.2.0';
1
+ export const VERSION = '1.5.0';
2
2
  //# sourceMappingURL=version.js.map
@@ -177,43 +177,115 @@ Your API key is issued by your team's PureContext administrator. See [Team Setup
177
177
 
178
178
  Installing PureContext gives your AI agent access to the tools. Adding the agent instructions tells it *how* to use them efficiently — which tool to pick for each situation, in what order to call them, and what patterns to avoid.
179
179
 
180
- Two instruction files are provided at the repository root:
180
+ Without them, an AI agent given access to PureContext may default to reading entire files (wasting tokens) rather than using `search_symbols`, or may not know to call `list_repos` first to get the `repoId` required by every tool. The instructions encode the correct workflow: check if indexed → search by name or meaning → retrieve source only for what you'll use.
181
+
182
+ ### Recommended: `purecontext-mcp install`
183
+
184
+ PureContext ships with a multi-IDE installer that writes the workflow rules into the conventions file each tool expects. Run it once inside your project root:
185
+
186
+ ```bash
187
+ npx purecontext-mcp install all
188
+ ```
181
189
 
182
- **`AGENT_INSTRUCTIONS_SHORT.md`** A compact reference (~2 KB). Covers the mandatory first step, the complete tool selection table, the core rules, and the most common usage patterns. Use this for agents with limited system prompt space or when you want minimal overhead.
190
+ This auto-detects which AI tools are configured in the project (by looking for marker files such as `.cursor/`, `.windsurfrules`, `CLAUDE.md`, `.continue/`, etc.) and installs the rules for each.
183
191
 
184
- **`AGENT_INSTRUCTIONS.md`** The full reference (~15 KB). Adds detailed parameter notes, every usage pattern, known limitations, decision trees, and anti-patterns. Use this when you want the agent to have complete context, especially for complex multi-step workflows.
192
+ When no `--scope` flag is given, the CLI prompts you to choose where to install:
185
193
 
186
- ### Adding instructions to Claude Code
194
+ ```
195
+ Where should PureContext be installed?
196
+ 1) Local — this project only
197
+ 2) Global — all projects (user-level config)
198
+ 3) Both
199
+ ```
187
200
 
188
- Add the short version to your project's `CLAUDE.md`:
201
+ Pass `--scope` to skip the prompt:
189
202
 
190
203
  ```bash
191
- cat AGENT_INSTRUCTIONS_SHORT.md >> CLAUDE.md
204
+ npx purecontext-mcp install all --scope=local # this project only
205
+ npx purecontext-mcp install all --scope=global # user-level, all projects
206
+ npx purecontext-mcp install all --scope=both # both places at once
192
207
  ```
193
208
 
194
- Or add the full version if the project is large and complex:
209
+ For a single tool:
195
210
 
196
211
  ```bash
197
- cat AGENT_INSTRUCTIONS.md >> CLAUDE.md
212
+ npx purecontext-mcp install cursor --scope=global
213
+ npx purecontext-mcp install windsurf
214
+ npx purecontext-mcp install continue
215
+ # ...etc.
198
216
  ```
199
217
 
200
- Claude Code reads `CLAUDE.md` at the start of every session. The instructions become part of every conversation in that project automatically — no need to repeat them.
218
+ Useful flags:
201
219
 
202
- ### Adding instructions to Cursor
220
+ ```bash
221
+ npx purecontext-mcp install --list # show detection state, write nothing
222
+ npx purecontext-mcp install all --dry-run # preview which writers would run
223
+ ```
203
224
 
204
- Paste the contents of `AGENT_INSTRUCTIONS_SHORT.md` into your Cursor rules file (`.cursorrules` in the project root, or via Cursor Settings → Rules).
225
+ ### Supported tools
205
226
 
206
- ### Adding instructions to Windsurf
227
+ | Tool | Local | Global | Notes |
228
+ |------|-------|--------|-------|
229
+ | `claude` | `CLAUDE.md` in project | `~/.claude/CLAUDE.md` + hooks | Global registers seven hook events — see [Claude Code hooks](#claude-code-hooks) below. |
230
+ | `cursor` | `.cursor/rules/purecontext.mdc` | `~/.cursor/rules/purecontext.mdc` | MDC frontmatter with `alwaysApply: true`. |
231
+ | `windsurf` | `.windsurfrules` | `~/.windsurfrules` | Marked block appended or replaced in place. |
232
+ | `continue` | `.continue/config.json` | `~/.continue/config.json` | JSON-aware merge; other fields are preserved. |
233
+ | `cline` | `.clinerules` | local only | No known global config path. |
234
+ | `roo-code` | `.roo/rules-code.md` | local only | No known global config path. |
235
+ | `vscode` | `.github/copilot-instructions.md` | local only | Picked up by GitHub Copilot in VS Code. |
236
+ | `claude-desktop` | always global | always global | Merges MCP server entry; leaves other servers untouched. |
207
237
 
208
- Paste the contents into your Windsurf workspace memory or rules configuration.
238
+ ### Claude Code hooks
209
239
 
210
- ### Adding instructions to any other agent
240
+ When you run `npx purecontext-mcp install claude` (or the standalone `npx purecontext-mcp hooks --install`), PureContext registers seven hook events in `~/.claude/settings.json`. Each hook is a CLI-style command — no scripts are copied to `~/.claude/hooks/`; the hook logic lives inside the installed package and updates automatically when you upgrade.
211
241
 
212
- The files are plain Markdown. Paste the contents into whatever system prompt, memory, or rules configuration your agent supports. The short version works well for constrained contexts. The full version is better when you can afford the space.
242
+ | Hook event | Command | What it does |
243
+ |------------|---------|--------------|
244
+ | `PostToolUse` | `hook-posttooluse` | Re-indexes files modified by Edit/Write/MultiEdit |
245
+ | `PreToolUse` | `hook-pretooluse` | Soft edit guard — suggests read tools before editing unread files |
246
+ | `PreCompact` | `hook-precompact` | Injects the list of indexed repos before context is compacted |
247
+ | `WorktreeCreate` | `hook-worktree-create` | Auto-indexes a newly created agent worktree |
248
+ | `WorktreeRemove` | `hook-worktree-remove` | Fires when an agent worktree is removed (reserved for cleanup) |
249
+ | `TaskCompleted` | `hook-taskcompleted` | Post-task diagnostics: complexity hotspots, TODO count, suggested tools |
250
+ | `SubagentStart` | `hook-subagentstart` | Injects a condensed repo orientation for newly spawned subagents |
213
251
 
214
- ### What the instructions do
252
+ Running `hooks --install` more than once is safe. It replaces existing PureContext entries (including old `.mjs`-path style entries from versions prior to 1.8.0) while leaving other tools' hooks untouched.
215
253
 
216
- Without them, an AI agent given access to PureContext may default to reading entire files (wasting tokens) rather than using `search_symbols`, or may not know to call `list_repos` first to get the `repoId` required by every tool. The instructions encode the correct workflow: check if indexed → search by name or meaning → retrieve source only for what you'll use.
254
+ To see the current registration status without making changes:
255
+
256
+ ```bash
257
+ npx purecontext-mcp hooks --list
258
+ ```
259
+
260
+ ### Idempotency
261
+
262
+ Every writer is safe to re-run. The Markdown writers wrap their content in HTML comment markers:
263
+
264
+ ```html
265
+ <!-- purecontext-mcp-start -->
266
+ ... PureContext workflow rules ...
267
+ <!-- purecontext-mcp-end -->
268
+ ```
269
+
270
+ On re-run, the marked block is replaced in place. Anything outside the markers (your own rules, other tools' rules) is preserved. The JSON writers (`continue`, `claude-desktop`) parse and merge structurally rather than re-emitting the whole file.
271
+
272
+ ### Manual install (if you'd rather paste)
273
+
274
+ The two source-of-truth files are at the repository root:
275
+
276
+ - **`AGENT_INSTRUCTIONS_SHORT.md`** — Compact (~2 KB). Mandatory first step, tool selection table, core rules, common usage patterns. Use for agents with limited system prompt space.
277
+ - **`AGENT_INSTRUCTIONS.md`** — Full (~15 KB). Adds parameter notes, every usage pattern, known limitations, decision trees, anti-patterns. Use for complex multi-step workflows.
278
+
279
+ To use these manually:
280
+
281
+ ```bash
282
+ # Claude Code
283
+ cat AGENT_INSTRUCTIONS_SHORT.md >> CLAUDE.md
284
+
285
+ # Cursor — paste into .cursorrules or via Cursor Settings → Rules
286
+ # Windsurf — paste into .windsurfrules or workspace memory
287
+ # Anything else — paste into whatever rule/memory config it supports
288
+ ```
217
289
 
218
290
  ---
219
291
 
@@ -37,6 +37,95 @@ purecontext-mcp config --check
37
37
  purecontext-mcp config
38
38
  ```
39
39
 
40
+ ### `install`
41
+
42
+ Write PureContext workflow rules into the conventions file each AI tool expects.
43
+
44
+ ```bash
45
+ # Auto-detect installed tools and install rules for all of them
46
+ npx purecontext-mcp install all
47
+
48
+ # Install for a specific tool
49
+ npx purecontext-mcp install cursor
50
+ npx purecontext-mcp install windsurf
51
+ npx purecontext-mcp install continue
52
+ npx purecontext-mcp install cline
53
+ npx purecontext-mcp install roo-code
54
+ npx purecontext-mcp install vscode
55
+ npx purecontext-mcp install claude
56
+ npx purecontext-mcp install claude-desktop
57
+ ```
58
+
59
+ When no `--scope` flag is given, the CLI prompts interactively:
60
+
61
+ ```
62
+ Where should PureContext be installed?
63
+ 1) Local — this project only
64
+ 2) Global — all projects (user-level config)
65
+ 3) Both
66
+ ```
67
+
68
+ Pass `--scope` to skip the prompt:
69
+
70
+ ```bash
71
+ npx purecontext-mcp install all --scope=global # user-level for all IDEs
72
+ npx purecontext-mcp install cursor --scope=both # project + home dir
73
+ npx purecontext-mcp install all --scope=local # this project only
74
+ ```
75
+
76
+ Useful flags:
77
+
78
+ ```bash
79
+ npx purecontext-mcp install --list # show detection state, write nothing
80
+ npx purecontext-mcp install all --dry-run # preview which writers would run
81
+ npx purecontext-mcp install all --scope=global # install globally without prompt
82
+ ```
83
+
84
+ **Scope behaviour per tool:**
85
+
86
+ | Tool | Local | Global |
87
+ |------|-------|--------|
88
+ | `claude` | `CLAUDE.md` in project | `~/.claude/CLAUDE.md` + hooks |
89
+ | `cursor` | `.cursor/rules/purecontext.mdc` | `~/.cursor/rules/purecontext.mdc` |
90
+ | `windsurf` | `.windsurfrules` | `~/.windsurfrules` |
91
+ | `continue` | `.continue/config.json` | `~/.continue/config.json` |
92
+ | `cline` | `.clinerules` | local only (no global path) |
93
+ | `roo-code` | `.roo/rules-code.md` | local only (no global path) |
94
+ | `vscode` | `.github/copilot-instructions.md` | local only (no global path) |
95
+ | `claude-desktop` | always global | always global |
96
+
97
+ All writers are idempotent: re-running updates the marked block in place without touching anything outside it.
98
+
99
+ ### `hooks`
100
+
101
+ Install or inspect Claude Code hook registrations.
102
+
103
+ ```bash
104
+ # Register all PureContext hooks in ~/.claude/settings.json
105
+ npx purecontext-mcp hooks --install
106
+
107
+ # List current hook registration status
108
+ npx purecontext-mcp hooks --list
109
+ ```
110
+
111
+ Hooks are registered as CLI commands in `~/.claude/settings.json`. Re-running `--install` is safe — it replaces existing PureContext entries (including any old `.mjs`-path style entries from earlier versions) while leaving other tools' hooks untouched.
112
+
113
+ ### `hook-*` (Claude Code hook handlers)
114
+
115
+ These are the hook handlers invoked by Claude Code. They are not meant to be called directly; they are registered by `hooks --install` and executed automatically by Claude Code as events fire.
116
+
117
+ | Command | Hook event | What it does |
118
+ |---------|-----------|--------------|
119
+ | `hook-posttooluse` | `PostToolUse` | Re-indexes files modified by Edit/Write/MultiEdit |
120
+ | `hook-pretooluse` | `PreToolUse` | Soft edit guard — suggests read tools before editing |
121
+ | `hook-precompact` | `PreCompact` | Injects the list of indexed repos before context compaction |
122
+ | `hook-worktree-create` | `WorktreeCreate` | Auto-indexes a newly created agent worktree |
123
+ | `hook-worktree-remove` | `WorktreeRemove` | Fires when an agent worktree is removed (no-op, reserved) |
124
+ | `hook-taskcompleted` | `TaskCompleted` | Post-task diagnostics: complexity hotspots, TODO count, tool suggestions |
125
+ | `hook-subagentstart` | `SubagentStart` | Injects condensed repo orientation for newly spawned subagents |
126
+
127
+ All handlers read from stdin (the JSON payload Claude Code sends) and write a `systemMessage` JSON object to stdout when they have context to inject. They always exit 0 and never block tool execution.
128
+
40
129
  ### `keys`
41
130
 
42
131
  Manage API keys for hosted deployments.