memento-mcp 0.3.12 → 0.3.13
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/package.json +1 -1
- package/src/cli.js +54 -124
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -120,9 +120,7 @@ before compaction. Trust the hooks. Focus on writing good memories.`;
|
|
|
120
120
|
|
|
121
121
|
const HEADLESS_CMDS = {
|
|
122
122
|
"claude-code": (prompt) => ["claude", "-p", "--dangerously-skip-permissions", prompt],
|
|
123
|
-
"codex": (prompt) => ["codex", "exec", prompt],
|
|
124
123
|
"gemini": (prompt) => ["gemini", prompt],
|
|
125
|
-
"opencode": (prompt) => ["opencode", "run", prompt],
|
|
126
124
|
};
|
|
127
125
|
|
|
128
126
|
function buildIntegrationPrompt(blob) {
|
|
@@ -162,13 +160,16 @@ function runAgentHeadless(agentKey, prompt) {
|
|
|
162
160
|
// ---------------------------------------------------------------------------
|
|
163
161
|
|
|
164
162
|
function parseFlags(argv) {
|
|
165
|
-
const flags = { nonInteractive: false, apiKey: null };
|
|
163
|
+
const flags = { nonInteractive: false, apiKey: null, agent: null };
|
|
166
164
|
for (let i = 0; i < argv.length; i++) {
|
|
167
165
|
if (argv[i] === "-y" || argv[i] === "--yes") {
|
|
168
166
|
flags.nonInteractive = true;
|
|
169
167
|
} else if (argv[i] === "--api-key" && argv[i + 1]) {
|
|
170
168
|
flags.apiKey = argv[i + 1];
|
|
171
169
|
i++;
|
|
170
|
+
} else if (argv[i] === "--agent" && argv[i + 1]) {
|
|
171
|
+
flags.agent = argv[i + 1];
|
|
172
|
+
i++;
|
|
172
173
|
}
|
|
173
174
|
}
|
|
174
175
|
// Also check environment variable
|
|
@@ -244,29 +245,6 @@ function writeMcpJson(cwd) {
|
|
|
244
245
|
return ".mcp.json";
|
|
245
246
|
}
|
|
246
247
|
|
|
247
|
-
function writeCodexToml(cwd) {
|
|
248
|
-
const dir = path.join(cwd, ".codex");
|
|
249
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
250
|
-
const filePath = path.join(dir, "config.toml");
|
|
251
|
-
|
|
252
|
-
let content = "";
|
|
253
|
-
try {
|
|
254
|
-
content = fs.readFileSync(filePath, "utf8");
|
|
255
|
-
} catch {
|
|
256
|
-
/* file doesn't exist */
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Skip if memento section already exists
|
|
260
|
-
if (/\[mcp_servers\.memento\]/.test(content)) {
|
|
261
|
-
return ".codex/config.toml (already configured)";
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const section = `\n[mcp_servers.memento]\ncommand = "npx"\nargs = ["-y", "memento-mcp"]\n`;
|
|
265
|
-
const separator = content && !content.endsWith("\n") ? "\n" : "";
|
|
266
|
-
fs.writeFileSync(filePath, content + separator + section);
|
|
267
|
-
return ".codex/config.toml";
|
|
268
|
-
}
|
|
269
|
-
|
|
270
248
|
function writeGeminiJson(cwd) {
|
|
271
249
|
const dir = path.join(cwd, ".gemini");
|
|
272
250
|
fs.mkdirSync(dir, { recursive: true });
|
|
@@ -277,22 +255,6 @@ function writeGeminiJson(cwd) {
|
|
|
277
255
|
return ".gemini/settings.json";
|
|
278
256
|
}
|
|
279
257
|
|
|
280
|
-
function writeOpencodeJson(cwd) {
|
|
281
|
-
const filePath = path.join(cwd, "opencode.json");
|
|
282
|
-
const existing = readJsonFile(filePath) || {};
|
|
283
|
-
deepMerge(existing, {
|
|
284
|
-
mcp: {
|
|
285
|
-
memento: {
|
|
286
|
-
type: "local",
|
|
287
|
-
command: ["npx", "-y", "memento-mcp"],
|
|
288
|
-
enabled: true,
|
|
289
|
-
},
|
|
290
|
-
},
|
|
291
|
-
});
|
|
292
|
-
writeJsonFile(filePath, existing);
|
|
293
|
-
return "opencode.json";
|
|
294
|
-
}
|
|
295
|
-
|
|
296
258
|
const AGENTS = {
|
|
297
259
|
"claude-code": {
|
|
298
260
|
name: "Claude Code",
|
|
@@ -301,38 +263,31 @@ const AGENTS = {
|
|
|
301
263
|
hasHooks: true,
|
|
302
264
|
nextSteps: "Restart Claude Code to activate.",
|
|
303
265
|
},
|
|
304
|
-
codex: {
|
|
305
|
-
name: "OpenAI Codex",
|
|
306
|
-
detect: (cwd) => fs.existsSync(path.join(cwd, ".codex")),
|
|
307
|
-
configWriter: writeCodexToml,
|
|
308
|
-
hasHooks: false,
|
|
309
|
-
nextSteps: "Run `codex` in this directory — memento tools load automatically.",
|
|
310
|
-
},
|
|
311
266
|
gemini: {
|
|
312
267
|
name: "Gemini CLI",
|
|
313
268
|
detect: (cwd) => fs.existsSync(path.join(cwd, ".gemini")),
|
|
314
269
|
configWriter: writeGeminiJson,
|
|
315
|
-
hasHooks:
|
|
270
|
+
hasHooks: true,
|
|
316
271
|
nextSteps: "Run `gemini` in this directory — memento tools load automatically.",
|
|
317
272
|
},
|
|
318
|
-
|
|
319
|
-
name: "
|
|
320
|
-
detect: (
|
|
321
|
-
configWriter:
|
|
273
|
+
manual: {
|
|
274
|
+
name: "I'll set up my agent myself",
|
|
275
|
+
detect: () => false,
|
|
276
|
+
configWriter: () => "(skipped — manual setup)",
|
|
322
277
|
hasHooks: false,
|
|
323
|
-
nextSteps: "
|
|
278
|
+
nextSteps: "Point your agent's MCP config at: npx -y memento-mcp",
|
|
324
279
|
},
|
|
325
280
|
};
|
|
326
281
|
|
|
327
282
|
// Exported for testing
|
|
328
|
-
export { AGENTS, writeMcpJson,
|
|
283
|
+
export { AGENTS, writeMcpJson, writeGeminiJson };
|
|
329
284
|
|
|
330
285
|
// ---------------------------------------------------------------------------
|
|
331
286
|
// CLI
|
|
332
287
|
// ---------------------------------------------------------------------------
|
|
333
288
|
|
|
334
289
|
async function runInit(flags = {}) {
|
|
335
|
-
const { nonInteractive = false, apiKey: flagApiKey = null } = flags;
|
|
290
|
+
const { nonInteractive = false, apiKey: flagApiKey = null, agent: flagAgent = null } = flags;
|
|
336
291
|
const cwd = process.cwd();
|
|
337
292
|
const projectName = path.basename(cwd);
|
|
338
293
|
|
|
@@ -420,16 +375,25 @@ async function runInit(flags = {}) {
|
|
|
420
375
|
|
|
421
376
|
let selectedAgents;
|
|
422
377
|
if (nonInteractive) {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
378
|
+
if (flagAgent) {
|
|
379
|
+
// Validate --agent value
|
|
380
|
+
if (!AGENTS[flagAgent]) {
|
|
381
|
+
const valid = Object.keys(AGENTS).join(", ");
|
|
382
|
+
console.error(` Error: unknown agent "${flagAgent}". Valid agents: ${valid}`);
|
|
383
|
+
process.exit(1);
|
|
384
|
+
}
|
|
385
|
+
selectedAgents = [flagAgent];
|
|
386
|
+
console.log(` Agent: ${AGENTS[flagAgent].name} (--agent flag)`);
|
|
387
|
+
} else {
|
|
388
|
+
// Auto-detect: use first detected agent, or default to claude-code
|
|
389
|
+
selectedAgents = detected.length > 0 ? [detected[0]] : ["claude-code"];
|
|
390
|
+
console.log(` Agent: ${AGENTS[selectedAgents[0]].name} (auto-detected)`);
|
|
391
|
+
}
|
|
426
392
|
} else {
|
|
427
393
|
console.log("\nDetected agents:");
|
|
428
394
|
const markers = {
|
|
429
395
|
"claude-code": ".claude/",
|
|
430
|
-
codex: ".codex/",
|
|
431
396
|
gemini: ".gemini/",
|
|
432
|
-
opencode: "opencode.json",
|
|
433
397
|
};
|
|
434
398
|
for (const key of agentKeys) {
|
|
435
399
|
const agent = AGENTS[key];
|
|
@@ -464,8 +428,6 @@ async function runInit(flags = {}) {
|
|
|
464
428
|
}
|
|
465
429
|
|
|
466
430
|
const hasClaude = selectedAgents.includes("claude-code");
|
|
467
|
-
|
|
468
|
-
// 5. Hooks — if any hook-supporting agent is selected (Claude Code, Gemini CLI)
|
|
469
431
|
const hasGemini = selectedAgents.includes("gemini");
|
|
470
432
|
const hasHookAgent = hasClaude || hasGemini;
|
|
471
433
|
|
|
@@ -531,7 +493,6 @@ async function runInit(flags = {}) {
|
|
|
531
493
|
created.push(".memento.json");
|
|
532
494
|
|
|
533
495
|
// 7. Copy hook scripts — gated on any hook-supporting agent
|
|
534
|
-
const hasCodex = selectedAgents.includes("codex");
|
|
535
496
|
const anyHookEnabled =
|
|
536
497
|
enableUserPrompt || enableStop || enablePreCompact || enableSessionStart;
|
|
537
498
|
|
|
@@ -549,9 +510,6 @@ async function runInit(flags = {}) {
|
|
|
549
510
|
enableSessionStart && "memento-sessionstart-identity.sh",
|
|
550
511
|
].filter(Boolean);
|
|
551
512
|
|
|
552
|
-
// Also copy Codex notify script if Codex is selected
|
|
553
|
-
if (hasCodex) scriptFiles.push("memento-codex-notify.sh");
|
|
554
|
-
|
|
555
513
|
for (const name of scriptFiles) {
|
|
556
514
|
const src = path.join(pkgScriptsDir, name);
|
|
557
515
|
if (!fs.existsSync(src)) continue; // skip if script doesn't exist yet
|
|
@@ -604,31 +562,7 @@ async function runInit(flags = {}) {
|
|
|
604
562
|
}
|
|
605
563
|
}
|
|
606
564
|
|
|
607
|
-
// 8c.
|
|
608
|
-
if (hasCodex) {
|
|
609
|
-
const pkgScriptsDir = path.resolve(__dirname, "..", "scripts");
|
|
610
|
-
const localScriptsDir = path.join(cwd, ".memento", "scripts");
|
|
611
|
-
// Ensure the notify script is copied (may not have been copied above if no hook agent)
|
|
612
|
-
const notifySrc = path.join(pkgScriptsDir, "memento-codex-notify.sh");
|
|
613
|
-
const notifyDest = path.join(localScriptsDir, "memento-codex-notify.sh");
|
|
614
|
-
if (fs.existsSync(notifySrc) && !fs.existsSync(notifyDest)) {
|
|
615
|
-
fs.mkdirSync(localScriptsDir, { recursive: true });
|
|
616
|
-
fs.copyFileSync(notifySrc, notifyDest);
|
|
617
|
-
fs.chmodSync(notifyDest, 0o755);
|
|
618
|
-
}
|
|
619
|
-
const notifyScript = notifyDest;
|
|
620
|
-
const codexTomlPath = path.join(cwd, ".codex", "config.toml");
|
|
621
|
-
let tomlContent = "";
|
|
622
|
-
try { tomlContent = fs.readFileSync(codexTomlPath, "utf-8"); } catch { /* doesn't exist yet */ }
|
|
623
|
-
if (!tomlContent.includes("notify")) {
|
|
624
|
-
const notifyLine = `\nnotify = ["bash", "${notifyScript}"]\n`;
|
|
625
|
-
const separator = tomlContent && !tomlContent.endsWith("\n") ? "\n" : "";
|
|
626
|
-
fs.writeFileSync(codexTomlPath, tomlContent + separator + notifyLine);
|
|
627
|
-
created.push(".codex/config.toml (notify)");
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// 9. Per-agent config files
|
|
565
|
+
// 8c. Per-agent config files
|
|
632
566
|
for (const agentKey of selectedAgents) {
|
|
633
567
|
const agent = AGENTS[agentKey];
|
|
634
568
|
const result = agent.configWriter(cwd);
|
|
@@ -641,16 +575,15 @@ async function runInit(flags = {}) {
|
|
|
641
575
|
if (appendToGitignore(cwd, ".memento/scripts/")) gitignoreUpdated = true;
|
|
642
576
|
if (gitignoreUpdated) created.push(".gitignore (updated)");
|
|
643
577
|
|
|
644
|
-
//
|
|
578
|
+
// 10. Summary
|
|
645
579
|
const labels = {
|
|
646
580
|
".memento.json": "workspace config + credentials",
|
|
647
581
|
".memento/scripts/": "hook scripts (recall + distillation)",
|
|
648
582
|
".claude/settings.local.json": "hooks registered with Claude Code",
|
|
649
583
|
".mcp.json": "MCP server registered (Claude Code)",
|
|
650
|
-
".codex/config.toml": "MCP server registered (Codex)",
|
|
651
|
-
".codex/config.toml (already configured)": "MCP server (Codex, skipped)",
|
|
652
584
|
".gemini/settings.json": "MCP server registered (Gemini CLI)",
|
|
653
|
-
"
|
|
585
|
+
".gemini/settings.json (hooks)": "hooks registered with Gemini CLI",
|
|
586
|
+
"(skipped — manual setup)": "MCP config skipped (manual setup)",
|
|
654
587
|
".gitignore (updated)": "credentials excluded from git",
|
|
655
588
|
};
|
|
656
589
|
const colWidth = Math.max(...created.map((f) => f.length)) + 2;
|
|
@@ -669,6 +602,14 @@ async function runInit(flags = {}) {
|
|
|
669
602
|
}
|
|
670
603
|
console.log(" Your agent will wake up remembering.\n");
|
|
671
604
|
|
|
605
|
+
// Show non-interactive equivalent
|
|
606
|
+
if (!nonInteractive) {
|
|
607
|
+
const parts = ["npx memento-mcp init -y"];
|
|
608
|
+
if (apiKey) parts.push(`--api-key ${apiKey}`);
|
|
609
|
+
parts.push(`--agent ${selectedAgents[0]}`);
|
|
610
|
+
console.log(` Non-interactive equivalent:\n ${parts.join(" ")}\n`);
|
|
611
|
+
}
|
|
612
|
+
|
|
672
613
|
// 12. Auto-integrate agent instructions
|
|
673
614
|
const primaryAgent = selectedAgents[0];
|
|
674
615
|
const prompt = buildIntegrationPrompt(INSTRUCTIONS_BLOB);
|
|
@@ -797,23 +738,6 @@ async function runUpdate() {
|
|
|
797
738
|
}
|
|
798
739
|
}
|
|
799
740
|
|
|
800
|
-
// Codex CLI — ensure notify is configured
|
|
801
|
-
const hasCodex = agents.includes("codex")
|
|
802
|
-
|| fs.existsSync(path.join(cwd, ".codex"));
|
|
803
|
-
if (hasCodex) {
|
|
804
|
-
const notifyScript = path.join(localScriptsDir, "memento-codex-notify.sh");
|
|
805
|
-
const codexTomlPath = path.join(cwd, ".codex", "config.toml");
|
|
806
|
-
let tomlContent = "";
|
|
807
|
-
try { tomlContent = fs.readFileSync(codexTomlPath, "utf-8"); } catch { /* doesn't exist yet */ }
|
|
808
|
-
if (!tomlContent.includes("notify") && fs.existsSync(notifyScript)) {
|
|
809
|
-
const notifyLine = `\nnotify = ["bash", "${notifyScript}"]\n`;
|
|
810
|
-
const separator = tomlContent && !tomlContent.endsWith("\n") ? "\n" : "";
|
|
811
|
-
fs.mkdirSync(path.dirname(codexTomlPath), { recursive: true });
|
|
812
|
-
fs.writeFileSync(codexTomlPath, tomlContent + separator + notifyLine);
|
|
813
|
-
registeredHooks.push("Codex CLI → .codex/config.toml (notify)");
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
|
|
817
741
|
console.log(`\n ✓ Memento hooks updated to v${pkgVersion}\n`);
|
|
818
742
|
console.log(" Updated scripts:");
|
|
819
743
|
for (const name of updated) {
|
|
@@ -882,16 +806,22 @@ if (isMain) {
|
|
|
882
806
|
Memento Protocol CLI
|
|
883
807
|
|
|
884
808
|
Usage:
|
|
885
|
-
npx memento-mcp init
|
|
886
|
-
npx memento-mcp init -y
|
|
887
|
-
npx memento-mcp init
|
|
888
|
-
npx memento-mcp
|
|
889
|
-
npx memento-mcp
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
809
|
+
npx memento-mcp init Set up Memento in the current project
|
|
810
|
+
npx memento-mcp init -y Non-interactive setup (uses defaults)
|
|
811
|
+
npx memento-mcp init -y --agent gemini Non-interactive with specific agent
|
|
812
|
+
npx memento-mcp init --api-key KEY Provide API key (skips signup)
|
|
813
|
+
npx memento-mcp update Update hook scripts to latest version
|
|
814
|
+
npx memento-mcp Start the MCP server (used by .mcp.json)
|
|
815
|
+
|
|
816
|
+
Flags:
|
|
817
|
+
-y, --yes Non-interactive mode (uses defaults, for CI/scripting)
|
|
818
|
+
--api-key KEY Provide API key (skips signup prompt)
|
|
819
|
+
--agent AGENT Select agent: claude-code, gemini, or manual
|
|
820
|
+
|
|
821
|
+
The -y flag enables fully non-interactive setup. Combine with --agent
|
|
822
|
+
to select a specific agent (defaults to auto-detect, then claude-code).
|
|
823
|
+
|
|
824
|
+
Supports Claude Code, Gemini CLI, and manual setup for any agent.
|
|
895
825
|
`);
|
|
896
826
|
process.exit(1);
|
|
897
827
|
}
|