memax-cli 0.1.0-alpha.4 → 0.1.0-alpha.40
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/assets/skills/memax-memory/SKILL.md +154 -0
- package/dist/commands/agent-sessions.d.ts +62 -0
- package/dist/commands/agent-sessions.d.ts.map +1 -0
- package/dist/commands/agent-sessions.js +1338 -0
- package/dist/commands/agent-sessions.js.map +1 -0
- package/dist/commands/agent-sessions.test.d.ts +2 -0
- package/dist/commands/agent-sessions.test.d.ts.map +1 -0
- package/dist/commands/agent-sessions.test.js +255 -0
- package/dist/commands/agent-sessions.test.js.map +1 -0
- package/dist/commands/agents.d.ts +3 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +36 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +38 -7
- package/dist/commands/auth.js.map +1 -1
- package/dist/commands/capture.d.ts +19 -0
- package/dist/commands/capture.d.ts.map +1 -0
- package/dist/commands/capture.js +69 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +13 -0
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/delete.d.ts +3 -1
- package/dist/commands/delete.d.ts.map +1 -1
- package/dist/commands/delete.js +30 -5
- package/dist/commands/delete.js.map +1 -1
- package/dist/commands/dreams.d.ts +22 -0
- package/dist/commands/dreams.d.ts.map +1 -0
- package/dist/commands/dreams.js +205 -0
- package/dist/commands/dreams.js.map +1 -0
- package/dist/commands/dreams.test.d.ts +2 -0
- package/dist/commands/dreams.test.d.ts.map +1 -0
- package/dist/commands/dreams.test.js +39 -0
- package/dist/commands/dreams.test.js.map +1 -0
- package/dist/commands/hook.d.ts +2 -0
- package/dist/commands/hook.d.ts.map +1 -1
- package/dist/commands/hook.js +6 -0
- package/dist/commands/hook.js.map +1 -1
- package/dist/commands/hub.d.ts +31 -0
- package/dist/commands/hub.d.ts.map +1 -0
- package/dist/commands/hub.js +295 -0
- package/dist/commands/hub.js.map +1 -0
- package/dist/commands/hub.test.d.ts +2 -0
- package/dist/commands/hub.test.d.ts.map +1 -0
- package/dist/commands/hub.test.js +62 -0
- package/dist/commands/hub.test.js.map +1 -0
- package/dist/commands/list.d.ts +8 -1
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +110 -9
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/list.test.d.ts +2 -0
- package/dist/commands/list.test.d.ts.map +1 -0
- package/dist/commands/list.test.js +14 -0
- package/dist/commands/list.test.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +50 -19
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +285 -42
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/push.d.ts +6 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +73 -11
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/recall.d.ts +9 -0
- package/dist/commands/recall.d.ts.map +1 -1
- package/dist/commands/recall.js +206 -39
- package/dist/commands/recall.js.map +1 -1
- package/dist/commands/recall.test.d.ts +2 -0
- package/dist/commands/recall.test.d.ts.map +1 -0
- package/dist/commands/recall.test.js +31 -0
- package/dist/commands/recall.test.js.map +1 -0
- package/dist/commands/setup-hooks.d.ts +12 -0
- package/dist/commands/setup-hooks.d.ts.map +1 -0
- package/dist/commands/setup-hooks.js +193 -0
- package/dist/commands/setup-hooks.js.map +1 -0
- package/dist/commands/setup-instructions.d.ts +21 -0
- package/dist/commands/setup-instructions.d.ts.map +1 -0
- package/dist/commands/setup-instructions.js +172 -0
- package/dist/commands/setup-instructions.js.map +1 -0
- package/dist/commands/setup-mcp.d.ts +14 -0
- package/dist/commands/setup-mcp.d.ts.map +1 -0
- package/dist/commands/setup-mcp.js +288 -0
- package/dist/commands/setup-mcp.js.map +1 -0
- package/dist/commands/setup-types.d.ts +20 -0
- package/dist/commands/setup-types.d.ts.map +1 -0
- package/dist/commands/setup-types.js +60 -0
- package/dist/commands/setup-types.js.map +1 -0
- package/dist/commands/setup.d.ts +8 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +163 -307
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/show.d.ts +2 -0
- package/dist/commands/show.d.ts.map +1 -1
- package/dist/commands/show.js +25 -13
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/sync.d.ts +47 -2
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +1299 -119
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/sync.test.d.ts +2 -0
- package/dist/commands/sync.test.d.ts.map +1 -0
- package/dist/commands/sync.test.js +130 -0
- package/dist/commands/sync.test.js.map +1 -0
- package/dist/commands/topic.d.ts +32 -0
- package/dist/commands/topic.d.ts.map +1 -0
- package/dist/commands/topic.js +223 -0
- package/dist/commands/topic.js.map +1 -0
- package/dist/commands/topic.test.d.ts +2 -0
- package/dist/commands/topic.test.d.ts.map +1 -0
- package/dist/commands/topic.test.js +114 -0
- package/dist/commands/topic.test.js.map +1 -0
- package/dist/index.js +33 -125
- package/dist/index.js.map +1 -1
- package/dist/lib/client.d.ts +9 -0
- package/dist/lib/client.d.ts.map +1 -0
- package/dist/lib/client.js +77 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/config.d.ts +45 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +74 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/hubs.d.ts +7 -0
- package/dist/lib/hubs.d.ts.map +1 -0
- package/dist/lib/hubs.js +33 -0
- package/dist/lib/hubs.js.map +1 -0
- package/dist/lib/hubs.test.d.ts +2 -0
- package/dist/lib/hubs.test.d.ts.map +1 -0
- package/dist/lib/hubs.test.js +57 -0
- package/dist/lib/hubs.test.js.map +1 -0
- package/dist/lib/project-context.d.ts +56 -0
- package/dist/lib/project-context.d.ts.map +1 -0
- package/dist/lib/project-context.js +231 -0
- package/dist/lib/project-context.js.map +1 -0
- package/dist/lib/project-context.test.d.ts +2 -0
- package/dist/lib/project-context.test.d.ts.map +1 -0
- package/dist/lib/project-context.test.js +75 -0
- package/dist/lib/project-context.test.js.map +1 -0
- package/dist/lib/prompt.d.ts +7 -0
- package/dist/lib/prompt.d.ts.map +1 -0
- package/dist/lib/prompt.js +41 -0
- package/dist/lib/prompt.js.map +1 -0
- package/dist/lib/trash.d.ts +6 -0
- package/dist/lib/trash.d.ts.map +1 -0
- package/dist/lib/trash.js +28 -0
- package/dist/lib/trash.js.map +1 -0
- package/package.json +17 -13
- package/.vscode/mcp.json +0 -8
- package/dist/lib/api.d.ts +0 -4
- package/dist/lib/api.d.ts.map +0 -1
- package/dist/lib/api.js +0 -95
- package/dist/lib/api.js.map +0 -1
- package/src/commands/auth.ts +0 -92
- package/src/commands/config.ts +0 -27
- package/src/commands/delete.ts +0 -20
- package/src/commands/hook.ts +0 -243
- package/src/commands/list.ts +0 -38
- package/src/commands/login.ts +0 -162
- package/src/commands/mcp.ts +0 -357
- package/src/commands/push.ts +0 -82
- package/src/commands/recall.ts +0 -163
- package/src/commands/setup.ts +0 -682
- package/src/commands/show.ts +0 -35
- package/src/commands/sync.ts +0 -403
- package/src/index.ts +0 -192
- package/src/lib/api.ts +0 -110
- package/src/lib/config.ts +0 -61
- package/src/lib/credentials.ts +0 -42
- package/tsconfig.json +0 -9
package/dist/commands/setup.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import {
|
|
3
|
-
import { join
|
|
4
|
-
import { homedir
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
5
|
import { execSync } from "node:child_process";
|
|
6
|
+
import { createInterface } from "node:readline";
|
|
7
|
+
import { commandExists, resolveMemaxBin, } from "./setup-types.js";
|
|
8
|
+
import { ensureApiKey, setupMcpRemote, setupMcp, printMcpConfigs, removeMcpJson, removeMcpToml, } from "./setup-mcp.js";
|
|
9
|
+
import { setupHooks, removeHooks } from "./setup-hooks.js";
|
|
10
|
+
import { injectInstructions, removeInstructions, installSkills, removeSkills, } from "./setup-instructions.js";
|
|
11
|
+
// --- Agent definitions ---
|
|
6
12
|
function getAgents() {
|
|
7
13
|
const home = homedir();
|
|
8
|
-
const
|
|
14
|
+
const cwd = process.cwd();
|
|
9
15
|
return [
|
|
10
16
|
{
|
|
11
17
|
name: "Claude Code",
|
|
@@ -14,6 +20,7 @@ function getAgents() {
|
|
|
14
20
|
format: "json-mcpServers",
|
|
15
21
|
mcpKey: "mcpServers",
|
|
16
22
|
hasHooks: true,
|
|
23
|
+
globalInstructionFile: join(home, ".claude", "CLAUDE.md"),
|
|
17
24
|
detect: () => existsSync(join(home, ".claude")) || commandExists("claude"),
|
|
18
25
|
},
|
|
19
26
|
{
|
|
@@ -23,6 +30,7 @@ function getAgents() {
|
|
|
23
30
|
format: "json-mcpServers",
|
|
24
31
|
mcpKey: "mcpServers",
|
|
25
32
|
hasHooks: false,
|
|
33
|
+
globalInstructionFile: null, // project-level .cursorrules only
|
|
26
34
|
detect: () => existsSync(join(home, ".cursor")) || commandExists("cursor"),
|
|
27
35
|
},
|
|
28
36
|
{
|
|
@@ -32,6 +40,7 @@ function getAgents() {
|
|
|
32
40
|
format: "json-mcpServers",
|
|
33
41
|
mcpKey: "mcpServers",
|
|
34
42
|
hasHooks: false,
|
|
43
|
+
globalInstructionFile: null, // project-level .windsurfrules only
|
|
35
44
|
detect: () => existsSync(join(home, ".codeium", "windsurf")) ||
|
|
36
45
|
commandExists("windsurf"),
|
|
37
46
|
},
|
|
@@ -42,6 +51,7 @@ function getAgents() {
|
|
|
42
51
|
format: "json-mcpServers",
|
|
43
52
|
mcpKey: "mcpServers",
|
|
44
53
|
hasHooks: true,
|
|
54
|
+
globalInstructionFile: join(home, ".gemini", "GEMINI.md"),
|
|
45
55
|
detect: () => existsSync(join(home, ".gemini")) || commandExists("gemini"),
|
|
46
56
|
},
|
|
47
57
|
{
|
|
@@ -51,15 +61,17 @@ function getAgents() {
|
|
|
51
61
|
format: "json-mcpServers",
|
|
52
62
|
mcpKey: "mcpServers",
|
|
53
63
|
hasHooks: false,
|
|
64
|
+
globalInstructionFile: null, // uses .github/copilot-instructions.md (project-level)
|
|
54
65
|
detect: () => existsSync(join(home, ".copilot")) || commandExists("gh copilot"),
|
|
55
66
|
},
|
|
56
67
|
{
|
|
57
68
|
name: "Copilot (VS Code)",
|
|
58
69
|
id: "vscode",
|
|
59
|
-
configPath: join(".vscode", "mcp.json"),
|
|
70
|
+
configPath: join(".vscode", "mcp.json"),
|
|
60
71
|
format: "json-servers",
|
|
61
72
|
mcpKey: "servers",
|
|
62
73
|
hasHooks: false,
|
|
74
|
+
globalInstructionFile: null,
|
|
63
75
|
detect: () => existsSync(".vscode") || commandExists("code"),
|
|
64
76
|
},
|
|
65
77
|
{
|
|
@@ -69,22 +81,54 @@ function getAgents() {
|
|
|
69
81
|
format: "toml",
|
|
70
82
|
mcpKey: "mcp_servers",
|
|
71
83
|
hasHooks: false,
|
|
84
|
+
globalInstructionFile: join(home, ".codex", "AGENTS.md"),
|
|
72
85
|
detect: () => existsSync(join(home, ".codex")) || commandExists("codex"),
|
|
73
86
|
},
|
|
87
|
+
{
|
|
88
|
+
name: "OpenClaw",
|
|
89
|
+
id: "openclaw",
|
|
90
|
+
configPath: join(home, ".openclaw", "openclaw.json"),
|
|
91
|
+
format: "json-mcpServers",
|
|
92
|
+
mcpKey: "mcp.servers",
|
|
93
|
+
hasHooks: false,
|
|
94
|
+
globalInstructionFile: null, // OpenClaw has its own memory system
|
|
95
|
+
detect: () => existsSync(join(home, ".openclaw")) || commandExists("openclaw"),
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "OpenCode",
|
|
99
|
+
id: "opencode",
|
|
100
|
+
configPath: join(cwd, ".opencode", "opencode.jsonc"),
|
|
101
|
+
format: "json-mcpServers",
|
|
102
|
+
mcpKey: "mcp",
|
|
103
|
+
hasHooks: false,
|
|
104
|
+
globalInstructionFile: null, // project-level only
|
|
105
|
+
detect: () => existsSync(join(cwd, ".opencode")) || commandExists("opencode"),
|
|
106
|
+
},
|
|
74
107
|
];
|
|
75
108
|
}
|
|
76
109
|
export async function setupCommand(options) {
|
|
77
110
|
const enableMcp = options.all || options.mcp;
|
|
78
111
|
const enableHooks = options.all || options.hooks;
|
|
79
|
-
|
|
112
|
+
const enableInstructions = options.all || options.instructions;
|
|
113
|
+
if (!enableMcp && !enableHooks && !enableInstructions && !options.print) {
|
|
80
114
|
printUsage();
|
|
81
115
|
return;
|
|
82
116
|
}
|
|
83
|
-
//
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
117
|
+
// --print: just output config JSON for manual copy/paste
|
|
118
|
+
if (options.print) {
|
|
119
|
+
await printMcpConfigs(options.local ?? false);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Remote mode (default): per-agent API keys (agent_name on each key)
|
|
123
|
+
const useRemote = !options.local;
|
|
124
|
+
// Local mode: need memax binary
|
|
125
|
+
let memaxBin = null;
|
|
126
|
+
if (!useRemote || enableHooks) {
|
|
127
|
+
memaxBin = resolveMemaxBin();
|
|
128
|
+
if (!memaxBin && !useRemote) {
|
|
129
|
+
console.error(chalk.red("\n Could not find memax binary.\n Install globally: npm install -g memax-cli@alpha\n"));
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
88
132
|
}
|
|
89
133
|
// Filter agents
|
|
90
134
|
const allAgents = getAgents();
|
|
@@ -111,21 +155,37 @@ export async function setupCommand(options) {
|
|
|
111
155
|
return;
|
|
112
156
|
}
|
|
113
157
|
console.log(chalk.bold("\n Memax Setup\n"));
|
|
158
|
+
if (useRemote) {
|
|
159
|
+
console.log(chalk.gray(" Mode: remote server (recommended)\n"));
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
console.log(chalk.gray(" Mode: local CLI\n"));
|
|
163
|
+
}
|
|
114
164
|
const results = [];
|
|
115
165
|
for (const agent of agents) {
|
|
116
166
|
const changes = [];
|
|
117
|
-
// MCP setup
|
|
167
|
+
// MCP setup — per-agent key with agent_name for attribution
|
|
118
168
|
if (enableMcp) {
|
|
119
169
|
try {
|
|
120
|
-
|
|
121
|
-
|
|
170
|
+
if (useRemote) {
|
|
171
|
+
const agentKey = await ensureApiKey(options.hub, agent.id);
|
|
172
|
+
if (!agentKey) {
|
|
173
|
+
console.error(chalk.red(` ✗ ${agent.name}: Could not create API key. Run: memax login`));
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
setupMcpRemote(agent, agentKey);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
setupMcp(agent, memaxBin);
|
|
180
|
+
}
|
|
181
|
+
changes.push(useRemote ? "MCP server (remote)" : "MCP server (local)");
|
|
122
182
|
}
|
|
123
183
|
catch (err) {
|
|
124
184
|
console.log(chalk.red(` ✗ ${agent.name}: MCP setup failed — ${err.message}`));
|
|
125
185
|
}
|
|
126
186
|
}
|
|
127
|
-
// Hook setup (only for agents that support it)
|
|
128
|
-
if (enableHooks && agent.hasHooks) {
|
|
187
|
+
// Hook setup (only for agents that support it — needs local binary)
|
|
188
|
+
if (enableHooks && agent.hasHooks && memaxBin) {
|
|
129
189
|
try {
|
|
130
190
|
setupHooks(agent, memaxBin);
|
|
131
191
|
changes.push("Context injection hook");
|
|
@@ -134,6 +194,26 @@ export async function setupCommand(options) {
|
|
|
134
194
|
console.log(chalk.red(` ✗ ${agent.name}: Hook setup failed — ${err.message}`));
|
|
135
195
|
}
|
|
136
196
|
}
|
|
197
|
+
// Inject memax instructions into agent's global instruction file
|
|
198
|
+
if (enableInstructions && agent.globalInstructionFile) {
|
|
199
|
+
try {
|
|
200
|
+
injectInstructions(agent.globalInstructionFile);
|
|
201
|
+
changes.push("Instructions injected");
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
console.log(chalk.red(` ✗ ${agent.name}: Instruction injection failed — ${err.message}`));
|
|
205
|
+
}
|
|
206
|
+
// Install memax skills for agents that support skill directories
|
|
207
|
+
try {
|
|
208
|
+
const skillCount = await installSkills(agent);
|
|
209
|
+
if (skillCount > 0) {
|
|
210
|
+
changes.push(`${skillCount} skill${skillCount > 1 ? "s" : ""} installed`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
console.log(chalk.red(` ✗ ${agent.name}: Skill install failed — ${err.message}`));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
137
217
|
if (changes.length > 0) {
|
|
138
218
|
results.push({ agent: agent.name, changes });
|
|
139
219
|
}
|
|
@@ -153,8 +233,8 @@ export async function setupCommand(options) {
|
|
|
153
233
|
console.log(chalk.gray("\n MCP tools available to all configured agents:"));
|
|
154
234
|
console.log(chalk.gray(" • memax_recall — semantic search your knowledge"));
|
|
155
235
|
console.log(chalk.gray(" • memax_push — save knowledge from sessions"));
|
|
156
|
-
console.log(chalk.gray(" • memax_get — read full
|
|
157
|
-
console.log(chalk.gray(" • memax_search — browse
|
|
236
|
+
console.log(chalk.gray(" • memax_get — read full memory by ID"));
|
|
237
|
+
console.log(chalk.gray(" • memax_search — browse memories by category"));
|
|
158
238
|
if (enableHooks) {
|
|
159
239
|
const hookAgents = results.filter((r) => r.changes.includes("Context injection hook"));
|
|
160
240
|
if (hookAgents.length > 0) {
|
|
@@ -162,8 +242,32 @@ export async function setupCommand(options) {
|
|
|
162
242
|
console.log(chalk.gray(" Every prompt gets relevant context injected automatically."));
|
|
163
243
|
}
|
|
164
244
|
}
|
|
165
|
-
console.log(chalk.gray("\n Restart your agents for changes to take effect
|
|
245
|
+
console.log(chalk.gray("\n Restart your agents for changes to take effect."));
|
|
246
|
+
// Offer to restore configs from cloud if this looks like a new device
|
|
247
|
+
if (enableInstructions || options.all) {
|
|
248
|
+
try {
|
|
249
|
+
const { syncAgentMemoryCommand } = await import("./sync.js");
|
|
250
|
+
const rl = createInterface({
|
|
251
|
+
input: process.stdin,
|
|
252
|
+
output: process.stdout,
|
|
253
|
+
});
|
|
254
|
+
const restore = await new Promise((resolve) => {
|
|
255
|
+
rl.question(chalk.gray("\n Restore agent configs from Memax cloud? [Y/n] "), (answer) => {
|
|
256
|
+
rl.close();
|
|
257
|
+
resolve(answer.trim().toLowerCase() !== "n");
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
if (restore) {
|
|
261
|
+
await syncAgentMemoryCommand({ skipConflicts: true });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// Sync not available (not logged in, etc.) — skip silently
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
console.log();
|
|
166
269
|
}
|
|
270
|
+
// --- Teardown command ---
|
|
167
271
|
export async function teardownCommand(options) {
|
|
168
272
|
const allAgents = getAgents();
|
|
169
273
|
const onlySet = options.only
|
|
@@ -191,6 +295,11 @@ export async function teardownCommand(options) {
|
|
|
191
295
|
if (removeHooks(agent))
|
|
192
296
|
removed = true;
|
|
193
297
|
}
|
|
298
|
+
if (agent.globalInstructionFile &&
|
|
299
|
+
removeInstructions(agent.globalInstructionFile)) {
|
|
300
|
+
console.log(chalk.gray(` Removed instructions from ${agent.name}`));
|
|
301
|
+
removed = true;
|
|
302
|
+
}
|
|
194
303
|
continue;
|
|
195
304
|
}
|
|
196
305
|
if (!existsSync(agent.configPath))
|
|
@@ -205,6 +314,15 @@ export async function teardownCommand(options) {
|
|
|
205
314
|
}
|
|
206
315
|
if (agent.hasHooks && removeHooks(agent))
|
|
207
316
|
removed = true;
|
|
317
|
+
if (agent.globalInstructionFile &&
|
|
318
|
+
removeInstructions(agent.globalInstructionFile)) {
|
|
319
|
+
console.log(chalk.gray(` Removed instructions from ${agent.name}`));
|
|
320
|
+
removed = true;
|
|
321
|
+
}
|
|
322
|
+
if (removeSkills(agent)) {
|
|
323
|
+
console.log(chalk.gray(` Removed skills from ${agent.name}`));
|
|
324
|
+
removed = true;
|
|
325
|
+
}
|
|
208
326
|
}
|
|
209
327
|
catch {
|
|
210
328
|
// Skip agents we can't clean up
|
|
@@ -216,270 +334,7 @@ export async function teardownCommand(options) {
|
|
|
216
334
|
}
|
|
217
335
|
console.log(chalk.green("\n Memax integrations removed.\n Restart your agents for changes to take effect.\n"));
|
|
218
336
|
}
|
|
219
|
-
// ---
|
|
220
|
-
function setupMcp(agent, bin) {
|
|
221
|
-
// Claude Code has its own CLI for MCP management
|
|
222
|
-
if (agent.id === "claude-code") {
|
|
223
|
-
setupMcpClaudeCode(bin);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
mkdirSync(dirname(agent.configPath), { recursive: true });
|
|
227
|
-
if (agent.format === "toml") {
|
|
228
|
-
setupMcpToml(agent, bin);
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
// JSON-based agents
|
|
232
|
-
let config = {};
|
|
233
|
-
if (existsSync(agent.configPath)) {
|
|
234
|
-
try {
|
|
235
|
-
config = JSON.parse(readFileSync(agent.configPath, "utf-8"));
|
|
236
|
-
}
|
|
237
|
-
catch {
|
|
238
|
-
// Start fresh
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
const servers = (config[agent.mcpKey] ?? {});
|
|
242
|
-
servers.memax = {
|
|
243
|
-
command: bin.command,
|
|
244
|
-
args: [...bin.args, "mcp", "serve"],
|
|
245
|
-
};
|
|
246
|
-
config[agent.mcpKey] = servers;
|
|
247
|
-
writeFileSync(agent.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
248
|
-
}
|
|
249
|
-
function setupMcpClaudeCode(bin) {
|
|
250
|
-
// Claude Code uses its own CLI for MCP — settings.json mcpServers is ignored
|
|
251
|
-
if (!commandExists("claude")) {
|
|
252
|
-
throw new Error("claude CLI not found in PATH");
|
|
253
|
-
}
|
|
254
|
-
// Remove existing first (idempotent)
|
|
255
|
-
try {
|
|
256
|
-
execSync("claude mcp remove memax", { stdio: "pipe" });
|
|
257
|
-
}
|
|
258
|
-
catch {
|
|
259
|
-
// Not installed yet — fine
|
|
260
|
-
}
|
|
261
|
-
// claude mcp add <name> -- <command> [args...]
|
|
262
|
-
const allArgs = [...bin.args, "mcp", "serve"];
|
|
263
|
-
const cmd = `claude mcp add memax -- ${bin.command} ${allArgs.join(" ")}`;
|
|
264
|
-
try {
|
|
265
|
-
execSync(cmd, { stdio: "pipe" });
|
|
266
|
-
}
|
|
267
|
-
catch (err) {
|
|
268
|
-
throw new Error(`claude mcp add failed: ${err.message}`);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
function setupMcpToml(agent, bin) {
|
|
272
|
-
// Codex uses TOML — append or update the memax section
|
|
273
|
-
let content = "";
|
|
274
|
-
if (existsSync(agent.configPath)) {
|
|
275
|
-
content = readFileSync(agent.configPath, "utf-8");
|
|
276
|
-
}
|
|
277
|
-
// Remove existing memax section if present
|
|
278
|
-
content = content.replace(/\[mcp_servers\.memax\][\s\S]*?(?=\n\[|$)/, "");
|
|
279
|
-
const args = [...bin.args, "mcp", "serve"].map((a) => `"${a}"`).join(", ");
|
|
280
|
-
content = content.trim();
|
|
281
|
-
if (content)
|
|
282
|
-
content += "\n\n";
|
|
283
|
-
content += `[mcp_servers.memax]\ncommand = "${bin.command}"\nargs = [${args}]\n`;
|
|
284
|
-
writeFileSync(agent.configPath, content);
|
|
285
|
-
}
|
|
286
|
-
// --- Hook setup ---
|
|
287
|
-
function setupHooks(agent, bin) {
|
|
288
|
-
if (agent.id === "claude-code") {
|
|
289
|
-
setupClaudeCodeHooks(agent, bin);
|
|
290
|
-
}
|
|
291
|
-
else if (agent.id === "gemini") {
|
|
292
|
-
setupGeminiHooks(agent, bin);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
function setupClaudeCodeHooks(agent, bin) {
|
|
296
|
-
const hookScript = writeHookScript(bin);
|
|
297
|
-
let config = {};
|
|
298
|
-
if (existsSync(agent.configPath)) {
|
|
299
|
-
try {
|
|
300
|
-
config = JSON.parse(readFileSync(agent.configPath, "utf-8"));
|
|
301
|
-
}
|
|
302
|
-
catch {
|
|
303
|
-
// Start fresh
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
const hooks = (config.hooks ?? {});
|
|
307
|
-
// Remove existing memax hooks
|
|
308
|
-
if (hooks["UserPromptSubmit"]) {
|
|
309
|
-
hooks["UserPromptSubmit"] = hooks["UserPromptSubmit"].filter((h) => !h.hooks?.some((hh) => hh.command?.includes("memax")));
|
|
310
|
-
}
|
|
311
|
-
hooks["UserPromptSubmit"] = [
|
|
312
|
-
...(hooks["UserPromptSubmit"] ?? []),
|
|
313
|
-
{
|
|
314
|
-
matcher: "",
|
|
315
|
-
hooks: [{ type: "command", command: hookScript, timeout: 30 }],
|
|
316
|
-
},
|
|
317
|
-
];
|
|
318
|
-
config.hooks = hooks;
|
|
319
|
-
writeFileSync(agent.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
320
|
-
}
|
|
321
|
-
function setupGeminiHooks(agent, bin) {
|
|
322
|
-
const hookScript = writeHookScript(bin);
|
|
323
|
-
let config = {};
|
|
324
|
-
if (existsSync(agent.configPath)) {
|
|
325
|
-
try {
|
|
326
|
-
config = JSON.parse(readFileSync(agent.configPath, "utf-8"));
|
|
327
|
-
}
|
|
328
|
-
catch {
|
|
329
|
-
// Start fresh
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
const hooks = (config.hooks ?? {});
|
|
333
|
-
// Remove existing memax hooks from both old ("Startup") and correct event
|
|
334
|
-
for (const event of ["Startup", "BeforeAgent"]) {
|
|
335
|
-
if (hooks[event]) {
|
|
336
|
-
hooks[event] = hooks[event].filter((h) => !h.hooks?.some((hh) => hh.command?.includes("memax")));
|
|
337
|
-
if (hooks[event].length === 0)
|
|
338
|
-
delete hooks[event];
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
// BeforeAgent fires after user submits a prompt — equivalent to Claude Code's PrePromptSubmit
|
|
342
|
-
hooks["BeforeAgent"] = [
|
|
343
|
-
...(hooks["BeforeAgent"] ?? []),
|
|
344
|
-
{
|
|
345
|
-
matcher: "",
|
|
346
|
-
hooks: [{ type: "command", command: hookScript, timeout: 30 }],
|
|
347
|
-
},
|
|
348
|
-
];
|
|
349
|
-
config.hooks = hooks;
|
|
350
|
-
writeFileSync(agent.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
351
|
-
}
|
|
352
|
-
// --- Teardown helpers ---
|
|
353
|
-
function removeMcpJson(agent) {
|
|
354
|
-
if (!existsSync(agent.configPath))
|
|
355
|
-
return false;
|
|
356
|
-
try {
|
|
357
|
-
const config = JSON.parse(readFileSync(agent.configPath, "utf-8"));
|
|
358
|
-
const servers = config[agent.mcpKey];
|
|
359
|
-
if (!servers?.memax)
|
|
360
|
-
return false;
|
|
361
|
-
delete servers.memax;
|
|
362
|
-
if (Object.keys(servers).length === 0)
|
|
363
|
-
delete config[agent.mcpKey];
|
|
364
|
-
writeFileSync(agent.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
365
|
-
console.log(chalk.gray(` Removed MCP from ${agent.name}`));
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
catch {
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
function removeMcpToml(agent) {
|
|
373
|
-
if (!existsSync(agent.configPath))
|
|
374
|
-
return false;
|
|
375
|
-
let content = readFileSync(agent.configPath, "utf-8");
|
|
376
|
-
const before = content;
|
|
377
|
-
content = content.replace(/\[mcp_servers\.memax\][\s\S]*?(?=\n\[|$)/, "");
|
|
378
|
-
if (content === before)
|
|
379
|
-
return false;
|
|
380
|
-
writeFileSync(agent.configPath, content.trim() + "\n");
|
|
381
|
-
console.log(chalk.gray(` Removed MCP from ${agent.name}`));
|
|
382
|
-
return true;
|
|
383
|
-
}
|
|
384
|
-
function removeHooks(agent) {
|
|
385
|
-
if (!existsSync(agent.configPath))
|
|
386
|
-
return false;
|
|
387
|
-
try {
|
|
388
|
-
const config = JSON.parse(readFileSync(agent.configPath, "utf-8"));
|
|
389
|
-
const hooks = config.hooks;
|
|
390
|
-
if (!hooks)
|
|
391
|
-
return false;
|
|
392
|
-
let removed = false;
|
|
393
|
-
for (const event of Object.keys(hooks)) {
|
|
394
|
-
const before = hooks[event].length;
|
|
395
|
-
hooks[event] = hooks[event].filter((h) => !h.command?.includes("memax") &&
|
|
396
|
-
!h.hooks?.some((hh) => hh.command?.includes("memax")));
|
|
397
|
-
if (hooks[event].length < before)
|
|
398
|
-
removed = true;
|
|
399
|
-
if (hooks[event].length === 0)
|
|
400
|
-
delete hooks[event];
|
|
401
|
-
}
|
|
402
|
-
if (Object.keys(hooks).length === 0)
|
|
403
|
-
delete config.hooks;
|
|
404
|
-
if (removed) {
|
|
405
|
-
writeFileSync(agent.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
406
|
-
console.log(chalk.gray(` Removed hooks from ${agent.name}`));
|
|
407
|
-
}
|
|
408
|
-
return removed;
|
|
409
|
-
}
|
|
410
|
-
catch {
|
|
411
|
-
return false;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
function resolveMemaxBin() {
|
|
415
|
-
// 1. Global install — use absolute path so agents find it without shell PATH
|
|
416
|
-
if (commandExists("memax")) {
|
|
417
|
-
try {
|
|
418
|
-
const which = platform() === "win32" ? "where memax" : "which memax";
|
|
419
|
-
const absPath = execSync(which, { encoding: "utf-8", stdio: "pipe" })
|
|
420
|
-
.trim()
|
|
421
|
-
.split("\n")[0];
|
|
422
|
-
if (absPath) {
|
|
423
|
-
return { command: absPath, args: [], shell: absPath };
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
catch {
|
|
427
|
-
// fall through
|
|
428
|
-
}
|
|
429
|
-
return { command: "memax", args: [], shell: "memax" };
|
|
430
|
-
}
|
|
431
|
-
// 2. Local repo build (faster than npx, always up-to-date during dev)
|
|
432
|
-
const localBuild = join(process.cwd(), "packages", "cli", "dist", "index.js");
|
|
433
|
-
if (existsSync(localBuild)) {
|
|
434
|
-
return {
|
|
435
|
-
command: "node",
|
|
436
|
-
args: [localBuild],
|
|
437
|
-
shell: `node ${localBuild}`,
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
// 3. npx as last resort (slow startup — agents may timeout on first run)
|
|
441
|
-
try {
|
|
442
|
-
execSync("npx --yes memax-cli --version", {
|
|
443
|
-
encoding: "utf-8",
|
|
444
|
-
timeout: 15000,
|
|
445
|
-
stdio: "pipe",
|
|
446
|
-
});
|
|
447
|
-
return {
|
|
448
|
-
command: "npx",
|
|
449
|
-
args: ["-y", "memax-cli"],
|
|
450
|
-
shell: "npx -y memax-cli",
|
|
451
|
-
};
|
|
452
|
-
}
|
|
453
|
-
catch {
|
|
454
|
-
// npx failed
|
|
455
|
-
}
|
|
456
|
-
return null;
|
|
457
|
-
}
|
|
458
|
-
function commandExists(cmd) {
|
|
459
|
-
try {
|
|
460
|
-
const which = platform() === "win32" ? "where" : "which";
|
|
461
|
-
execSync(`${which} ${cmd}`, { stdio: "pipe" });
|
|
462
|
-
return true;
|
|
463
|
-
}
|
|
464
|
-
catch {
|
|
465
|
-
return false;
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
function writeHookScript(bin) {
|
|
469
|
-
const hooksDir = join(homedir(), ".memax", "hooks");
|
|
470
|
-
mkdirSync(hooksDir, { recursive: true });
|
|
471
|
-
const isWindows = platform() === "win32";
|
|
472
|
-
const scriptName = isWindows ? "context-inject.cmd" : "context-inject.sh";
|
|
473
|
-
const scriptPath = join(hooksDir, scriptName);
|
|
474
|
-
if (isWindows) {
|
|
475
|
-
writeFileSync(scriptPath, WIN_HOOK.replace(/\$MEMAX/g, bin.shell));
|
|
476
|
-
}
|
|
477
|
-
else {
|
|
478
|
-
writeFileSync(scriptPath, UNIX_HOOK.replace(/\$MEMAX/g, bin.shell));
|
|
479
|
-
chmodSync(scriptPath, 0o755);
|
|
480
|
-
}
|
|
481
|
-
return scriptPath;
|
|
482
|
-
}
|
|
337
|
+
// --- Usage ---
|
|
483
338
|
function printUsage() {
|
|
484
339
|
const agents = getAgents();
|
|
485
340
|
const detected = agents.filter((a) => a.detect());
|
|
@@ -493,10 +348,12 @@ function printUsage() {
|
|
|
493
348
|
console.log();
|
|
494
349
|
}
|
|
495
350
|
console.log(chalk.gray(" Usage:\n"));
|
|
496
|
-
console.log(chalk.gray(" memax setup --mcp
|
|
497
|
-
console.log(chalk.gray(" memax setup --
|
|
351
|
+
console.log(chalk.gray(" memax setup --mcp Remote MCP server for all detected agents"));
|
|
352
|
+
console.log(chalk.gray(" memax setup --instructions Inject memax usage instructions into agent configs"));
|
|
353
|
+
console.log(chalk.gray(" memax setup --all MCP + hooks + instructions"));
|
|
354
|
+
console.log(chalk.gray(" memax setup --mcp --local Use local CLI instead of remote server"));
|
|
355
|
+
console.log(chalk.gray(" memax setup --print Print MCP config to copy/paste"));
|
|
498
356
|
console.log(chalk.gray(" memax setup --mcp --only claude-code,cursor"));
|
|
499
|
-
console.log(chalk.gray(" memax setup --all --skip codex"));
|
|
500
357
|
console.log(chalk.gray(" memax teardown Remove all integrations\n"));
|
|
501
358
|
console.log(chalk.gray(" Supported agents:"));
|
|
502
359
|
for (const a of agents) {
|
|
@@ -507,25 +364,24 @@ function printUsage() {
|
|
|
507
364
|
}
|
|
508
365
|
console.log();
|
|
509
366
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
`;
|
|
367
|
+
export function registerSetupCommands(program) {
|
|
368
|
+
program
|
|
369
|
+
.command("setup")
|
|
370
|
+
.description("Set up AI agent integrations (auto-detects installed agents)")
|
|
371
|
+
.option("--mcp", "Enable MCP server (agent tools)")
|
|
372
|
+
.option("--hooks", "Enable context injection hooks")
|
|
373
|
+
.option("--instructions", "Inject memax instructions into agent config files")
|
|
374
|
+
.option("--all", "Enable MCP + hooks + instructions")
|
|
375
|
+
.option("--local", "Use local stdio MCP instead of remote server")
|
|
376
|
+
.option("--print", "Print MCP config JSON to copy/paste (no changes made)")
|
|
377
|
+
.option("--only <agents>", "Only configure these agents (comma-separated)")
|
|
378
|
+
.option("--skip <agents>", "Skip these agents (comma-separated)")
|
|
379
|
+
.option("--hub <id>", "Scope MCP key to a specific hub")
|
|
380
|
+
.action(setupCommand);
|
|
381
|
+
program
|
|
382
|
+
.command("teardown")
|
|
383
|
+
.description("Remove Memax integrations from agents")
|
|
384
|
+
.option("--only <agents>", "Only remove from these agents (comma-separated)")
|
|
385
|
+
.action(teardownCommand);
|
|
386
|
+
}
|
|
531
387
|
//# sourceMappingURL=setup.js.map
|