devsmind-mcp 3.0.0 → 4.0.1

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 (46) hide show
  1. package/README.md +11 -20
  2. package/dist/cli/diff.js +1 -1
  3. package/dist/cli/diff.js.map +1 -1
  4. package/dist/cli/index.js +20 -9
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/cli/integrations/mcp.js +22 -1
  7. package/dist/cli/integrations/mcp.js.map +1 -1
  8. package/dist/cli/integrations/memory-topics.d.ts +21 -10
  9. package/dist/cli/integrations/memory-topics.js +32 -9
  10. package/dist/cli/integrations/memory-topics.js.map +1 -1
  11. package/dist/cli/integrations/memory.d.ts +14 -9
  12. package/dist/cli/integrations/memory.js +47 -229
  13. package/dist/cli/integrations/memory.js.map +1 -1
  14. package/dist/cli/integrations/registry.d.ts +27 -16
  15. package/dist/cli/integrations/registry.js +66 -34
  16. package/dist/cli/integrations/registry.js.map +1 -1
  17. package/dist/cli/rule.js +11 -16
  18. package/dist/cli/rule.js.map +1 -1
  19. package/dist/db/activity-graph.d.ts +55 -0
  20. package/dist/db/activity-graph.js +314 -0
  21. package/dist/db/activity-graph.js.map +1 -0
  22. package/dist/db/activity.d.ts +21 -0
  23. package/dist/db/activity.js +3 -2
  24. package/dist/db/activity.js.map +1 -1
  25. package/dist/db/database.d.ts +72 -4
  26. package/dist/db/database.js +89 -8
  27. package/dist/db/database.js.map +1 -1
  28. package/dist/db/index-build.d.ts +75 -0
  29. package/dist/db/index-build.js +177 -0
  30. package/dist/db/index-build.js.map +1 -0
  31. package/dist/db/revert.js +1 -1
  32. package/dist/db/revert.js.map +1 -1
  33. package/dist/db/schema.d.ts +2 -2
  34. package/dist/db/staging.d.ts +3 -2
  35. package/dist/db/staging.js +1 -1
  36. package/dist/db/staging.js.map +1 -1
  37. package/dist/mcp/server.d.ts +1 -1
  38. package/dist/mcp/server.js +215 -208
  39. package/dist/mcp/server.js.map +1 -1
  40. package/dist/utils/config.d.ts +15 -0
  41. package/dist/utils/config.js +27 -0
  42. package/dist/utils/config.js.map +1 -1
  43. package/dist/utils/scanner.d.ts +6 -4
  44. package/dist/utils/scanner.js +6 -4
  45. package/dist/utils/scanner.js.map +1 -1
  46. package/package.json +1 -1
@@ -1,250 +1,68 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  exports.handleMemory = handleMemory;
37
- const path = __importStar(require("path"));
38
- const config_1 = require("../../utils/config");
39
4
  const registry_1 = require("./registry");
40
5
  const memory_topics_1 = require("./memory-topics");
41
6
  const prompt_1 = require("./prompt");
42
- const MEMORY_FILE_HEADER = '<!-- Seeded by `devsmind memory` — the DevsMind team code-graph MCP server -->\n\n';
43
7
  /**
44
- * `devsmind memory` — seed a tool's own persistent agent-memory/skills store
45
- * (distinct from `devsmind rule`'s static rule file) with the workflow contract
46
- * carried by the MCP `instructions` field, for the handful of tools confirmed to
47
- * actually read back a file they didn't create themselves. For every other tool
48
- * this prints honest guidance instead of writing a file that might silently do
49
- * nothing (or get overwritten by the tool's own background job).
8
+ * `devsmind memory` — prints ONE natural-language block to paste into any AI chat, framed as an
9
+ * explicit "remember this" request. DevsMind writes nothing on your behalf.
10
+ *
11
+ * Why: research across all 9 tools DevsMind integrates with turned up the same finding stated
12
+ * independently in several of those tools' own docs background/automatic memory is
13
+ * discretionary by design (Windsurf, Codex, and Qwen say so outright; e.g. "auto-memory is
14
+ * best-effort, QWEN.md is guaranteed"), while an EXPLICIT in-chat request is the one thing that
15
+ * reliably lands. A silently-written file never crosses that trigger at all. And 5 of the 9 tools
16
+ * (Cursor, VS Code/Copilot, Windsurf, Kiro, Qwen) have no file DevsMind could safely write to in
17
+ * the first place — hand-writing into an undocumented or auto-generated store risks corrupting
18
+ * it. So instead of maintaining 9 different internal file formats, this hands the user one prompt
19
+ * and lets each tool's own native memory feature do whatever it already does best with it.
50
20
  *
51
- * The contract is seeded as one file per fact where the store loads files on
52
- * demand (Claude Code), and as one combined document where it doesn't
53
- * (Antigravity Skills) — see memory-topics.ts for why.
21
+ * `--tool` only changes the framing line (which feature name to call out, e.g. "Cursor calls
22
+ * this Memories") — the prompt itself, from `renderMemoryPrompt`, is the same for everyone.
54
23
  */
55
24
  async function handleMemory(opts) {
56
- const devmindDir = (0, config_1.resolveDevmindDir)(opts.path);
57
- const workspaceRoot = devmindDir ? path.dirname(devmindDir) : process.cwd();
58
- // Piped/redirected output or an explicit --print: print what WOULD be written and stop, the
59
- // same escape hatch `devsmind rule --print` has. Without it there was no way to read the
60
- // seeded contract, diff it against what's already in a store, or produce it from a script —
61
- // the content existed but the only route to it was a series of interactive prompts.
62
- if (opts.print || !process.stdin.isTTY || !process.stdout.isTTY) {
63
- printNonInteractive(opts.tool, workspaceRoot);
64
- return;
65
- }
66
- try {
67
- const target = await (0, prompt_1.pickTarget)();
68
- const mem = target.memory;
69
- if (!mem.supported) {
70
- const divider = '─'.repeat(70);
71
- console.log(`\n${divider}`);
72
- console.log(` ${target.label} — ${mem.featureName}`);
73
- console.log(`${divider}\n`);
74
- console.log(`⚠️ Nothing written — there's no safe way to pre-seed this.\n`);
75
- console.log(mem.note);
76
- console.log('');
77
- return;
78
- }
79
- console.log(`\nℹ️ ${target.label} calls this "${mem.featureName}".`);
80
- console.log(` ${mem.note}`);
81
- const mode = await (0, prompt_1.pickMode)();
82
- const scope = await (0, prompt_1.pickMemoryScope)(target);
83
- const docs = buildDocs(target, scope);
84
- if (mode === 'manual') {
85
- printManual(target.label, scope, workspaceRoot, docs, mem.pointerFile?.file);
86
- return;
87
- }
88
- // Automatic mode.
89
- const targetDir = await resolveMemoryDir(scope, target.label, workspaceRoot);
90
- const merged = docs.map(doc => {
91
- const filePath = path.join(targetDir, doc.file);
92
- return { doc, filePath, ...(0, prompt_1.mergeRuleFile)(filePath, doc.content, 'standalone') };
93
- });
94
- console.log(`\n📝 Target: ${targetDir.replace(/\\/g, '/')}`);
95
- if (merged.length === 1) {
96
- console.log(` ${merged[0].doc.file} (${merged[0].existed ? 'overwrite our own file' : 'create new'})`);
97
- console.log(`\nContent to be written:\n`);
98
- console.log(indent(merged[0].content));
99
- }
100
- else {
101
- const fresh = merged.filter(m => !m.existed).length;
102
- console.log(` ${merged.length} files — ${fresh} new, ${merged.length - fresh} overwritten (all DevsMind's own):\n`);
103
- for (const m of merged) {
104
- console.log(` ${m.existed ? '↻' : '+'} ${m.doc.file}`);
105
- if (m.doc.summary)
106
- console.log(` ${m.doc.summary}`);
107
- }
108
- }
109
- const indexLines = mem.pointerFile && docs.length > 1 ? memory_topics_1.MEMORY_TOPICS.map(memory_topics_1.renderIndexLine).join('\n') : null;
110
- if (indexLines && mem.pointerFile) {
111
- console.log(`\n …plus an index block in ${mem.pointerFile.file} (that file is what loads every session — without it these are never found):\n`);
112
- console.log(indent(indexLines));
113
- }
114
- const ok = await (0, prompt_1.confirmPrompt)('Write this?', true);
115
- if (!ok) {
116
- console.log('\nAborted — nothing written.');
117
- return;
118
- }
119
- for (const m of merged)
120
- (0, prompt_1.writeConfigFile)(m.filePath, m.content);
121
- console.log(`\n✅ Seeded ${target.label}'s ${mem.featureName} — ` +
122
- `${merged.length === 1 ? merged[0].filePath.replace(/\\/g, '/') : `${merged.length} files in ${targetDir.replace(/\\/g, '/')}`}`);
123
- if (mem.pointerFile) {
124
- const pointerPath = path.join(targetDir, mem.pointerFile.file);
125
- const body = indexLines ?? singlePointerLine(docs[0].file);
126
- const pointerConfirm = await (0, prompt_1.confirmPrompt)(`\nAlso write the ${indexLines ? 'index block' : 'pointer line'} into ${mem.pointerFile.file}, so this gets found ` +
127
- `(it only loads "on demand" otherwise)?`, true);
128
- if (pointerConfirm) {
129
- const pointerMerged = (0, prompt_1.mergeRuleFile)(pointerPath, body, mem.pointerFile.style);
130
- if (pointerMerged.error) {
131
- console.error(`❌ ${pointerMerged.error}`);
132
- }
133
- else {
134
- (0, prompt_1.writeConfigFile)(pointerPath, pointerMerged.content);
135
- console.log(`✅ ${indexLines ? 'Index' : 'Pointer'} written to ${pointerPath.replace(/\\/g, '/')}`);
136
- }
137
- }
138
- }
139
- }
140
- catch (err) {
141
- if (err instanceof prompt_1.CancelledError) {
142
- console.log('\nCancelled.');
143
- return;
144
- }
145
- throw err;
146
- }
147
- }
148
- /** The tools that have a memory/skills store DevsMind can safely write to — the only valid `--tool` values. */
149
- function memoryCapableTargets() {
150
- return registry_1.TARGETS.filter(t => t.memory.supported && (t.memory.scopes?.length ?? 0) > 0);
25
+ const target = await resolveTarget(opts);
26
+ if (!target)
27
+ return; // already reported: unknown --tool, or the interactive picker was cancelled
28
+ console.log(`\nℹ️ ${target.label} calls this "${target.memory.featureName}".`);
29
+ if (target.memory.note)
30
+ console.log(` ${target.memory.note}`);
31
+ console.log(`\n📋 Paste this into your ${target.label} chat and ask it to remember it:\n`);
32
+ console.log(indent((0, memory_topics_1.renderMemoryPrompt)()));
33
+ console.log('');
151
34
  }
152
35
  /**
153
- * The `--print` / non-TTY path: resolve a target without prompting, then reuse the same manual
154
- * rendering the interactive flow already offers. Defaults to Claude Code's one-file-per-fact
155
- * shape rather than picking arbitrarily it is the richest of the two (a store that ranks files
156
- * individually gets every topic separately), so it is the one worth seeing when you haven't said
157
- * which tool you mean. `--tool` prints exactly what that tool would receive instead.
36
+ * `--tool` resolves directly. Otherwise, an interactive TTY offers the same picker `devsmind
37
+ * rule`/`devsmind mcp` use (purely for the framing line nothing here depends on the answer
38
+ * the way file placement used to); a non-interactive/piped run or an explicit `--print` falls
39
+ * back to Claude Code's framing and says so, so scripted use never blocks on a prompt.
158
40
  */
159
- function printNonInteractive(toolId, workspaceRoot) {
160
- const capable = memoryCapableTargets();
161
- const valid = capable.map(t => t.id).join(', ');
162
- let target;
163
- if (toolId) {
164
- target = (0, registry_1.getTarget)(toolId);
41
+ async function resolveTarget(opts) {
42
+ if (opts.tool) {
43
+ const target = (0, registry_1.getTarget)(opts.tool);
165
44
  if (!target) {
166
- console.error(`❌ Unknown tool "${toolId}". Valid values for --tool: ${valid}`);
45
+ console.error(`❌ Unknown tool "${opts.tool}". Valid values for --tool: ${registry_1.TARGETS.map(t => t.id).join(', ')}`);
167
46
  process.exit(1);
168
- return;
47
+ return undefined;
169
48
  }
170
- if (!target.memory.supported || !target.memory.scopes?.length) {
171
- console.error(`❌ ${target.label} has no memory store DevsMind can pre-seed.\n` +
172
- ` ${target.memory.note}\n` +
173
- ` Tools that do: ${valid}`);
174
- process.exit(1);
175
- return;
176
- }
177
- }
178
- else {
179
- target = capable.find(t => t.id === 'claude-code') ?? capable[0];
180
- console.log(`ℹ️ No --tool given — showing the ${target.label} shape. Others: ${valid}\n`);
181
- }
182
- const scope = target.memory.scopes[0];
183
- printManual(target.label, scope, workspaceRoot, buildDocs(target, scope), target.memory.pointerFile?.file);
184
- }
185
- /**
186
- * Turn the shared topics into the file shape this particular store reads:
187
- * one file per topic when it ranks files individually, one combined document
188
- * otherwise. The tool's own `wrap` (e.g. Skills frontmatter) applies only to the
189
- * combined shape — per-topic files carry their own frontmatter already.
190
- */
191
- function buildDocs(target, scope) {
192
- if (scope.format === 'memory-files') {
193
- return memory_topics_1.MEMORY_TOPICS.map(topic => ({
194
- file: `${topic.name}.md`,
195
- content: (0, memory_topics_1.renderTopicFile)(topic, MEMORY_FILE_HEADER),
196
- summary: topic.description,
197
- }));
198
- }
199
- const combined = (0, memory_topics_1.renderCombined)(MEMORY_FILE_HEADER);
200
- const content = scope.format === 'skill-md' && target.memory.wrap ? target.memory.wrap(combined) : combined;
201
- return [{ file: scope.file ?? 'devsmind.md', content }];
202
- }
203
- /** Fallback for a single-file store whose index still wants one line pointing at it. */
204
- function singlePointerLine(file) {
205
- return `See \`${file}\` in this folder for the DevsMind workflow contract — \`start_session\` before your ` +
206
- `first write (every write call requires that session_id; reads don't), \`search_nodes\` (query and/or a ` +
207
- `real-regex \`pattern\`) before any grep, \`edit_node\` for every file you write, ` +
208
- `\`commit_changes\` (with \`message\`, \`reasoning\`, and \`feedback\`) before the turn ends.`;
209
- }
210
- /** Resolve the directory to write into, prompting the user to navigate when the exact path isn't knowable. */
211
- async function resolveMemoryDir(scope, label, workspaceRoot) {
212
- if (scope.needsUserConfirmedDir) {
213
- const start = (0, registry_1.resolveOsPath)(scope.dir);
214
- return (0, prompt_1.pickDirectory)(start, `Navigate to the correct folder for ${label} (e.g. .../projects/<your-project-hash>/memory)`);
215
- }
216
- if (scope.scope === 'project') {
217
- const base = await (0, prompt_1.pickDirectory)(workspaceRoot, `Where is the project root for ${label}?`);
218
- return path.join(base, (0, registry_1.resolveOsPath)(scope.dir));
219
- }
220
- return (0, registry_1.resolveScopeFile)(scope.dir, 'global', workspaceRoot);
221
- }
222
- function printManual(label, scope, workspaceRoot, docs, pointerFile) {
223
- const divider = '─'.repeat(70);
224
- const dirHint = scope.needsUserConfirmedDir
225
- ? `${(0, registry_1.resolveOsPath)(scope.dir)}/<your-project-hash>/...`
226
- : scope.scope === 'project'
227
- ? path.join(workspaceRoot, (0, registry_1.resolveOsPath)(scope.dir)).replace(/\\/g, '/')
228
- : (0, registry_1.resolveOsPath)(scope.dir);
229
- const dir = String(dirHint).replace(/\\/g, '/');
230
- console.log(`\n${divider}`);
231
- console.log(` Seed DevsMind into ${label}`);
232
- console.log(`${divider}`);
233
- console.log(`\n1. Create ${docs.length === 1 ? 'this file' : `these ${docs.length} files`} under:`);
234
- console.log(` ${dir}/`);
235
- for (const doc of docs) {
236
- console.log(`\n${divider}`);
237
- console.log(` ${dir}/${doc.file}`);
238
- console.log(`${divider}\n`);
239
- console.log(indent(doc.content));
49
+ return target;
240
50
  }
241
- if (pointerFile) {
242
- console.log(`\n${divider}`);
243
- console.log(` 2. Add to ${dir}/${pointerFile} — without this they only load "on demand" and are never found:`);
244
- console.log(`${divider}\n`);
245
- console.log(indent(docs.length > 1 ? memory_topics_1.MEMORY_TOPICS.map(memory_topics_1.renderIndexLine).join('\n') : singlePointerLine(docs[0].file)));
246
- console.log('');
51
+ if (!opts.print && process.stdin.isTTY && process.stdout.isTTY) {
52
+ try {
53
+ return await (0, prompt_1.pickTarget)();
54
+ }
55
+ catch (err) {
56
+ if (err instanceof prompt_1.CancelledError) {
57
+ console.log('\nCancelled.');
58
+ return undefined;
59
+ }
60
+ throw err;
61
+ }
247
62
  }
63
+ const fallback = (0, registry_1.getTarget)('claude-code');
64
+ console.log(`ℹ️ No --tool given — showing generic phrasing (the prompt itself is identical for every tool). Others: ${registry_1.TARGETS.map(t => t.id).join(', ')}`);
65
+ return fallback;
248
66
  }
249
67
  function indent(text) {
250
68
  return text.split('\n').map(l => ' ' + l).join('\n');
@@ -1 +1 @@
1
- {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/cli/integrations/memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/cli/integrations/memory.ts"],"names":[],"mappings":";;AAqBA,oCASC;AA9BD,yCAA2D;AAC3D,mDAAqD;AACrD,qCAAsD;AAEtD;;;;;;;;;;;;;;;;GAgBG;AACI,KAAK,UAAU,YAAY,CAAC,IAAuD;IACxF,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,4EAA4E;IAEjG,OAAO,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,KAAK,gBAAgB,MAAM,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;IAChF,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI;QAAE,OAAO,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,6BAA6B,MAAM,CAAC,KAAK,oCAAoC,CAAC,CAAC;IAC3F,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAA,kCAAkB,GAAE,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,aAAa,CAAC,IAAwC;IACnE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAA,oBAAS,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,mBAAmB,IAAI,CAAC,IAAI,+BAA+B,kBAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9G,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC/D,IAAI,CAAC;YACH,OAAO,MAAM,IAAA,mBAAU,GAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,uBAAc,EAAE,CAAC;gBAClC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAC5B,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,IAAA,oBAAS,EAAC,aAAa,CAAE,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,2GAA2G,kBAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5J,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzD,CAAC"}
@@ -55,8 +55,8 @@ export interface IdeTarget {
55
55
  scopes: McpScope[];
56
56
  /** Supported transports; first is the preferred default. */
57
57
  transports: Transport[];
58
- /** The value object placed under serverMap['devsmind'] for a given transport. */
59
- entry: (t: Transport, ctx: EntryContext) => Record<string, unknown>;
58
+ /** The value object placed under serverMap['devsmind'] for a given transport and scope. */
59
+ entry: (t: Transport, ctx: EntryContext, scope: Scope) => Record<string, unknown>;
60
60
  /** Optional CLI one-liner installer (e.g. `claude mcp add ...`). */
61
61
  cliInstaller?: (t: Transport, ctx: EntryContext) => string;
62
62
  /** Extra guidance printed in manual mode. */
@@ -70,16 +70,19 @@ export interface IdeTarget {
70
70
  wrap?: (body: string) => string;
71
71
  };
72
72
  memory: {
73
- /** False when no safe write path exists manual guidance only, no file is ever touched. */
73
+ /** `devsmind memory` writes nothing for any tool (see integrations/memory.ts) this and the
74
+ * fields below are read only for their FRAMING value (the tool's own feature name + a short
75
+ * caveat), not to decide whether or how to write. `scopes`/`wrap`/`pointerFile` describe a
76
+ * write path that no longer exists; kept only as still-accurate research about each tool's
77
+ * own store, in case a genuinely safe write target ever becomes available again. */
74
78
  supported: boolean;
75
79
  /** The tool's own name for this feature — use it verbatim in prompts, not a generic "memory". */
76
80
  featureName: string;
77
81
  scopes?: MemoryScope[];
78
82
  wrap?: (body: string) => string;
79
- /** Shown (instead of writing) when supported is false, or as extra context alongside a write. */
83
+ /** The one-line caveat shown alongside the printed prompt. */
80
84
  note: string;
81
- /** Claude Code only: also offer to append a one-line pointer into MEMORY.md so an
82
- * unreferenced topic file (loaded only "on demand") is actually discoverable. */
85
+ /** Unused by `devsmind memory` (see above) retained only alongside `scopes` as research. */
83
86
  pointerFile?: {
84
87
  file: string;
85
88
  style: 'append-section';
@@ -92,18 +95,26 @@ export interface EntryContext {
92
95
  port: number;
93
96
  }
94
97
  /**
95
- * Standard stdio entry: the IDE spawns `devsmind start --stdio --path <devmindDir>`.
98
+ * Standard stdio entry: the IDE spawns `devsmind start --stdio [--path <devmindDir>]`.
96
99
  *
97
- * The explicit `--path` is what makes stdio binding deterministic. Unlike the HTTP server (you run
98
- * `devsmind start` yourself, from inside the project, so its cwd auto-detect is reliable), a stdio
99
- * server is spawned BY the IDE with a cwd we don't control some spawn from the project root, some
100
- * from the IDE's install dir or the user's home. Baking the absolute brain path in here — which the
101
- * registration flow already knows (`ctx.devmindDir`) — means the process binds to the right project
102
- * regardless of where the IDE launched it, instead of leaning on a cwd assumption that silently
103
- * fails on some tools. Path may contain spaces; it's a separate argv element, so no quoting needed.
100
+ * `--path` is included for `project` scope only. A project-scoped config file lives inside — and
101
+ * so only ever serves the one project it was written for, so baking in the absolute brain path
102
+ * (which the registration flow already knows via `ctx.devmindDir`) makes binding deterministic
103
+ * regardless of what cwd the IDE happens to spawn from.
104
+ *
105
+ * A `global` config is different: ONE file, read by every project on the machine. Baking a single
106
+ * project's path into it would silently point every other project at that same brain the exact
107
+ * bug this scope split exists to avoid. So a global entry omits `--path` entirely and leans on the
108
+ * server's own auto-detect (`bindServerToProject` walks up from its cwd looking for `.devmind`),
109
+ * which works because the IDE spawns the stdio server from whichever workspace is actually open.
110
+ * If an IDE spawns from somewhere else instead (not the common case), the server starts unbound and
111
+ * falls back to per-call `devmind_path` — degraded, but never silently wrong.
112
+ *
113
+ * Path may contain spaces; it's a separate argv element, so no quoting needed.
104
114
  */
105
- export declare function stdioEntry(ctx: EntryContext): Record<string, unknown>;
106
- /** Standard HTTP entry: connect to the already-running server. */
115
+ export declare function stdioEntry(ctx: EntryContext, scope: Scope): Record<string, unknown>;
116
+ /** Standard HTTP entry: connect to the already-running server. Scope-independent — the URL never
117
+ * names a project, since the server itself is single-project no matter which config points at it. */
107
118
  export declare function httpEntry(ctx: EntryContext): Record<string, unknown>;
108
119
  /** Resolve an {@link OsPath} to a concrete string for the current platform, expanding a leading `~`. */
109
120
  export declare function resolveOsPath(p: OsPath): string;
@@ -43,20 +43,31 @@ const os = __importStar(require("os"));
43
43
  const path = __importStar(require("path"));
44
44
  // ─── Shared entry payloads ───────────────────────────────────────────────────
45
45
  /**
46
- * Standard stdio entry: the IDE spawns `devsmind start --stdio --path <devmindDir>`.
46
+ * Standard stdio entry: the IDE spawns `devsmind start --stdio [--path <devmindDir>]`.
47
47
  *
48
- * The explicit `--path` is what makes stdio binding deterministic. Unlike the HTTP server (you run
49
- * `devsmind start` yourself, from inside the project, so its cwd auto-detect is reliable), a stdio
50
- * server is spawned BY the IDE with a cwd we don't control some spawn from the project root, some
51
- * from the IDE's install dir or the user's home. Baking the absolute brain path in here — which the
52
- * registration flow already knows (`ctx.devmindDir`) — means the process binds to the right project
53
- * regardless of where the IDE launched it, instead of leaning on a cwd assumption that silently
54
- * fails on some tools. Path may contain spaces; it's a separate argv element, so no quoting needed.
48
+ * `--path` is included for `project` scope only. A project-scoped config file lives inside — and
49
+ * so only ever serves the one project it was written for, so baking in the absolute brain path
50
+ * (which the registration flow already knows via `ctx.devmindDir`) makes binding deterministic
51
+ * regardless of what cwd the IDE happens to spawn from.
52
+ *
53
+ * A `global` config is different: ONE file, read by every project on the machine. Baking a single
54
+ * project's path into it would silently point every other project at that same brain the exact
55
+ * bug this scope split exists to avoid. So a global entry omits `--path` entirely and leans on the
56
+ * server's own auto-detect (`bindServerToProject` walks up from its cwd looking for `.devmind`),
57
+ * which works because the IDE spawns the stdio server from whichever workspace is actually open.
58
+ * If an IDE spawns from somewhere else instead (not the common case), the server starts unbound and
59
+ * falls back to per-call `devmind_path` — degraded, but never silently wrong.
60
+ *
61
+ * Path may contain spaces; it's a separate argv element, so no quoting needed.
55
62
  */
56
- function stdioEntry(ctx) {
57
- return { command: 'devsmind', args: ['start', '--stdio', '--path', ctx.devmindDir] };
63
+ function stdioEntry(ctx, scope) {
64
+ const args = ['start', '--stdio'];
65
+ if (scope === 'project')
66
+ args.push('--path', ctx.devmindDir);
67
+ return { command: 'devsmind', args };
58
68
  }
59
- /** Standard HTTP entry: connect to the already-running server. */
69
+ /** Standard HTTP entry: connect to the already-running server. Scope-independent — the URL never
70
+ * names a project, since the server itself is single-project no matter which config points at it. */
60
71
  function httpEntry(ctx) {
61
72
  return { url: `http://localhost:${ctx.port}/mcp` };
62
73
  }
@@ -85,18 +96,32 @@ function resolveScopeFile(file, scope, workspaceRoot) {
85
96
  // and some require an explicit `type`. These builders capture each tool's shape.
86
97
  const httpUrl = (ctx) => `http://localhost:${ctx.port}/mcp`;
87
98
  /** Cursor / Kiro: bare `url`, no type. */
88
- const entryUrl = (t, ctx) => t === 'stdio' ? stdioEntry(ctx) : { url: httpUrl(ctx) };
99
+ const entryUrl = (t, ctx, scope) => t === 'stdio' ? stdioEntry(ctx, scope) : { url: httpUrl(ctx) };
89
100
  /** VS Code / Claude Code: explicit `type` + url. */
90
- const entryTyped = (t, ctx) => t === 'stdio'
91
- ? { type: 'stdio', ...stdioEntry(ctx) }
101
+ const entryTyped = (t, ctx, scope) => t === 'stdio'
102
+ ? { type: 'stdio', ...stdioEntry(ctx, scope) }
92
103
  : { type: 'http', url: httpUrl(ctx) };
93
104
  /** Windsurf / Antigravity: HTTP endpoint keyed as `serverUrl`. */
94
- const entryServerUrl = (t, ctx) => t === 'stdio' ? stdioEntry(ctx) : { serverUrl: httpUrl(ctx) };
105
+ const entryServerUrl = (t, ctx, scope) => t === 'stdio' ? stdioEntry(ctx, scope) : { serverUrl: httpUrl(ctx) };
95
106
  /** Qwen Code: Streamable-HTTP endpoint keyed as `httpUrl`. */
96
- const entryHttpUrl = (t, ctx) => t === 'stdio' ? stdioEntry(ctx) : { httpUrl: httpUrl(ctx) };
107
+ const entryHttpUrl = (t, ctx, scope) => t === 'stdio' ? stdioEntry(ctx, scope) : { httpUrl: httpUrl(ctx) };
97
108
  const cursorMdcWrap = (body) => `---\ndescription: DevsMind — Team AI Brain workspace rule\nalwaysApply: true\n---\n\n${body}\n`;
98
- /** Antigravity Skills format: YAML frontmatter (name + description) + markdown body. */
99
- const antigravitySkillWrap = (body) => `---\nname: devsmind\ndescription: DevsMind team code-graph MCP server when and how to use it\n---\n\n${body}\n`;
109
+ /**
110
+ * Skill format: YAML frontmatter (name + description) + markdown body.
111
+ *
112
+ * Shared by every target that reads `.agents/skills/` — Antigravity (IDE + CLI) and Codex all
113
+ * discover the SAME `.agents/skills/devsmind/SKILL.md`. One wrap, deliberately: these writes are
114
+ * whole-file (`standalone`), so per-tool frontmatter would mean whichever command ran last
115
+ * silently rewrote the others' file. Identical bytes make that collision a no-op instead.
116
+ */
117
+ const skillMdWrap = (body) => `---\nname: devsmind\ndescription: DevsMind team code-graph MCP server — when and how to use it\n---\n\n${body}\n`;
118
+ /** The one skill location all `.agents/skills/` readers share. See {@link skillMdWrap}. */
119
+ const AGENTS_SKILL_SCOPE = {
120
+ scope: 'project',
121
+ dir: '.agents/skills/devsmind',
122
+ file: 'SKILL.md',
123
+ format: 'skill-md',
124
+ };
100
125
  // VS Code user-profile mcp.json lives in the platform user-data dir.
101
126
  const VSCODE_GLOBAL = {
102
127
  win32: '~/AppData/Roaming/Code/User/mcp.json',
@@ -128,7 +153,7 @@ exports.TARGETS = [
128
153
  memory: {
129
154
  supported: false,
130
155
  featureName: 'Memories',
131
- note: 'Cursor\'s Memories are stored in an internal, undocumented database and only save after the agent proposes one and you approve it — there is no file DevsMind can safely write to. Ask the agent to remember the DevsMind workflow in conversation (e.g. "remember to always search_nodes before grep, and stage_change + commit_changes after every change") and approve the memory Cursor proposes.',
156
+ note: 'Cursor\'s Memories are stored in an internal, undocumented database and only save after the agent proposes one and you approve it — there is no file DevsMind can safely write to. Ask the agent to remember the DevsMind workflow in conversation (e.g. "remember to always search_nodes before grep, and edit_node + commit_changes after every change") and approve the memory Cursor proposes.',
132
157
  },
133
158
  },
134
159
  {
@@ -195,7 +220,7 @@ exports.TARGETS = [
195
220
  memory: {
196
221
  supported: false,
197
222
  featureName: 'Knowledge / PR-comment learning',
198
- note: 'Kiro has no file-based memory: its manual "Knowledge" store uses JSON + embeddings (not something safe to hand-write), and its autonomous agent\'s PR-comment-driven learning is an undocumented, AWS-internal, non-file-based store. The one thing DevsMind CAN influence — steering docs — is already handled by `devsmind rule`. To also engage the autonomous agent\'s learning, leave a PR review comment once, e.g. "always call search_nodes before grep, and stage_change + commit_changes after every change."',
223
+ note: 'Kiro has no file-based memory: its manual "Knowledge" store uses JSON + embeddings (not something safe to hand-write), and its autonomous agent\'s PR-comment-driven learning is an undocumented, AWS-internal, non-file-based store. The one thing DevsMind CAN influence — steering docs — is already handled by `devsmind rule`. To also engage the autonomous agent\'s learning, leave a PR review comment once, e.g. "always call search_nodes before grep, and edit_node + commit_changes after every change."',
199
224
  },
200
225
  },
201
226
  {
@@ -218,11 +243,9 @@ exports.TARGETS = [
218
243
  memory: {
219
244
  supported: true,
220
245
  featureName: 'Skills (/learn)',
221
- scopes: [
222
- { scope: 'project', dir: '.agents/skills/devsmind', file: 'SKILL.md', format: 'skill-md' },
223
- ],
224
- wrap: antigravitySkillWrap,
225
- note: 'Antigravity discovers skills by scanning .agents/skills/ for any SKILL.md — same mechanism whether it was created via /learn or placed here directly.',
246
+ scopes: [AGENTS_SKILL_SCOPE],
247
+ wrap: skillMdWrap,
248
+ note: 'Antigravity discovers skills by scanning .agents/skills/ for any SKILL.md — same mechanism whether it was created via /learn or placed here directly. Codex reads this same file.',
226
249
  },
227
250
  },
228
251
  // ── CLI tools ───────────────────────────────────────────────────────────────
@@ -233,6 +256,11 @@ exports.TARGETS = [
233
256
  mcp: {
234
257
  scopes: [
235
258
  { scope: 'project', file: '.mcp.json', format: 'json', serverMapPath: ['mcpServers'] },
259
+ // User-scope entries live at the TOP LEVEL of ~/.claude.json under `mcpServers` — not
260
+ // nested under that file's `projects` map (that's "local" scope, which this registry
261
+ // doesn't model). Same JSON shape as project scope, so the generic merge/write path
262
+ // handles it unchanged; confirmed against Claude Code's own MCP quickstart docs.
263
+ { scope: 'global', file: '~/.claude.json', format: 'json', serverMapPath: ['mcpServers'] },
236
264
  ],
237
265
  transports: ['stdio', 'http'],
238
266
  entry: entryTyped,
@@ -250,8 +278,7 @@ exports.TARGETS = [
250
278
  scopes: [
251
279
  { scope: 'global', dir: '~/.claude/projects', format: 'memory-files', needsUserConfirmedDir: true },
252
280
  ],
253
- note: 'One file per fact, not one big file: MEMORY.md\'s first 200 lines/25KB load every session automatically, while topic files load only "on demand" — ranked by each file\'s own `description` frontmatter. Split that way, an editing task pulls in the edit_node rule without also dragging in indexing and CLI trivia. An index line per topic is appended to MEMORY.md so they get found at all.',
254
- pointerFile: { file: 'MEMORY.md', style: 'append-section' },
281
+ note: 'Auto Memory saves reliably from an EXPLICIT in-chat request ("remember this")that\'s exactly what the prompt below is. A silently-written file never triggers that path at all, which is why `devsmind memory` no longer writes one.',
255
282
  },
256
283
  },
257
284
  {
@@ -274,10 +301,8 @@ exports.TARGETS = [
274
301
  memory: {
275
302
  supported: true,
276
303
  featureName: 'Skills (/learn)',
277
- scopes: [
278
- { scope: 'project', dir: '.agents/skills/devsmind', file: 'SKILL.md', format: 'skill-md' },
279
- ],
280
- wrap: antigravitySkillWrap,
304
+ scopes: [AGENTS_SKILL_SCOPE],
305
+ wrap: skillMdWrap,
281
306
  note: 'Same Skills mechanism as the Antigravity IDE — the CLI\'s /skills command browses this same .agents/skills/ directory.',
282
307
  },
283
308
  },
@@ -302,9 +327,16 @@ exports.TARGETS = [
302
327
  style: 'append-section',
303
328
  },
304
329
  memory: {
305
- supported: false,
306
- featureName: 'Memories',
307
- note: 'Codex\'s own docs explicitly warn: "these files are treated as generated state... don\'t rely on editing them by hand." A background consolidation job periodically regenerates ~/.codex/memories/MEMORY.md and memory_summary.md, so a manual write would likely just get overwritten. Nothing is written here — let Codex build this on its own over real sessions.',
330
+ supported: true,
331
+ featureName: 'Skills',
332
+ scopes: [AGENTS_SKILL_SCOPE],
333
+ wrap: skillMdWrap,
334
+ // Codex has two stores and only one of them is ours to write. `~/.codex/memories/` is
335
+ // generated state its own docs warn against hand-editing ("don't rely on editing them by
336
+ // hand") and a background job regenerates — untouched, here and everywhere else. Skills are
337
+ // the human-authored surface, and Codex scans the same `.agents/skills/` directory
338
+ // Antigravity does, so this is one file serving both tools rather than a new integration.
339
+ note: 'Codex discovers skills by scanning .agents/skills/ for any SKILL.md — the same file Antigravity reads, so seeding once covers both. Codex\'s own ~/.codex/memories/ is generated state and is never touched. Pair this with `devsmind rule` (AGENTS.md): a skill loads only when the task matches its description, while AGENTS.md is read every turn.',
308
340
  },
309
341
  },
310
342
  {