@membank/cli 0.6.0 → 0.7.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.
- package/dist/index.mjs +69 -27
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { cancel, confirm, intro, isCancel, multiselect, note, outro } from "@clack/prompts";
|
|
3
|
-
import { DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MemoryRepository, ProjectRepository, QueryEngine, SessionContextBuilder, resolveProject } from "@membank/core";
|
|
3
|
+
import { DatabaseManager, EmbeddingService, MEMORY_TYPE_VALUES, MIGRATIONS, MemoryRepository, ProjectRepository, QueryEngine, SessionContextBuilder, resolveProject, runScopeToProjectsMigration } from "@membank/core";
|
|
4
4
|
import { startServer } from "@membank/mcp";
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import { Command } from "commander";
|
|
@@ -22,12 +22,13 @@ async function addCommand(content, options, formatter, db, embeddingService) {
|
|
|
22
22
|
try {
|
|
23
23
|
const repo = new MemoryRepository(resolvedDb, embeddingService ?? new EmbeddingService(), new ProjectRepository(resolvedDb));
|
|
24
24
|
const tags = options.tags !== void 0 ? options.tags.split(",").map((t) => t.trim()) : [];
|
|
25
|
+
const projectScope = options.global ? void 0 : await resolveProject();
|
|
25
26
|
const spinner = formatter.isJson ? null : ora("Saving memory…").start();
|
|
26
27
|
const memory = await repo.save({
|
|
27
28
|
content,
|
|
28
29
|
type: options.type,
|
|
29
30
|
tags,
|
|
30
|
-
|
|
31
|
+
projectScope
|
|
31
32
|
});
|
|
32
33
|
spinner?.succeed("Memory saved");
|
|
33
34
|
formatter.outputMemory(memory);
|
|
@@ -165,10 +166,7 @@ function outputAdditionalContext(text, harness, eventName) {
|
|
|
165
166
|
process.stdout.write(`${text}\n`);
|
|
166
167
|
}
|
|
167
168
|
async function handleSessionStart(opts) {
|
|
168
|
-
const projectScope = (
|
|
169
|
-
hash: opts.scope,
|
|
170
|
-
name: opts.scope
|
|
171
|
-
} : await resolveProject()).hash;
|
|
169
|
+
const projectScope = (await resolveProject()).hash;
|
|
172
170
|
const db = DatabaseManager.open();
|
|
173
171
|
let text;
|
|
174
172
|
try {
|
|
@@ -199,18 +197,53 @@ async function listCommand(options, formatter) {
|
|
|
199
197
|
}
|
|
200
198
|
}
|
|
201
199
|
//#endregion
|
|
200
|
+
//#region src/commands/migrate.ts
|
|
201
|
+
async function migrateCommand(mode, name, formatter) {
|
|
202
|
+
if (mode === "list") {
|
|
203
|
+
if (formatter.isJson) process.stdout.write(`${JSON.stringify(MIGRATIONS.map((m) => ({
|
|
204
|
+
name: m.name,
|
|
205
|
+
description: m.description
|
|
206
|
+
})))}\n`);
|
|
207
|
+
else for (const m of MIGRATIONS) process.stdout.write(`${m.name}\n ${m.description}\n`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (name === void 0) {
|
|
211
|
+
formatter.error("Migration name is required for run mode.");
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
if (!MIGRATIONS.some((m) => m.name === name)) {
|
|
215
|
+
formatter.error(`Unknown migration: "${name}". Available: ${MIGRATIONS.map((m) => m.name).join(", ")}`);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
const db = DatabaseManager.open();
|
|
219
|
+
try {
|
|
220
|
+
if (name === "scope-to-projects") {
|
|
221
|
+
const result = await runScopeToProjectsMigration(new ProjectRepository(db));
|
|
222
|
+
if (result === null) {
|
|
223
|
+
formatter.error("No project found for current directory.");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (formatter.isJson) process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
227
|
+
else {
|
|
228
|
+
const { oldName, newName, memoryCount } = result;
|
|
229
|
+
process.stdout.write(`Found project: ${oldName} (${memoryCount} ${memoryCount === 1 ? "memory" : "memories"})\n`);
|
|
230
|
+
process.stdout.write(`Resolved name: ${newName}\n`);
|
|
231
|
+
process.stdout.write(`Renamed → ${newName}\n`);
|
|
232
|
+
process.stdout.write("Done.\n");
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} finally {
|
|
236
|
+
db.close();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//#endregion
|
|
202
240
|
//#region src/commands/pin.ts
|
|
203
|
-
function pinCommand(id,
|
|
241
|
+
function pinCommand(id, db) {
|
|
204
242
|
const ownDb = db === void 0;
|
|
205
243
|
const resolvedDb = db ?? DatabaseManager.open();
|
|
206
244
|
try {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
process.exit(2);
|
|
210
|
-
} else {
|
|
211
|
-
resolvedDb.db.prepare("UPDATE memories SET pinned = 1 WHERE id = ?").run(id);
|
|
212
|
-
process.stdout.write(`${chalk.green("✓")} Pinned: ${chalk.dim(id)}\n`);
|
|
213
|
-
}
|
|
245
|
+
new MemoryRepository(resolvedDb, new EmbeddingService(), new ProjectRepository(resolvedDb)).setPin(id, true);
|
|
246
|
+
process.stdout.write(`${chalk.green("✓")} Pinned: ${chalk.dim(id)}\n`);
|
|
214
247
|
} finally {
|
|
215
248
|
if (ownDb) resolvedDb.close();
|
|
216
249
|
}
|
|
@@ -248,17 +281,12 @@ async function statsCommand(formatter) {
|
|
|
248
281
|
}
|
|
249
282
|
//#endregion
|
|
250
283
|
//#region src/commands/unpin.ts
|
|
251
|
-
function unpinCommand(id,
|
|
284
|
+
function unpinCommand(id, db) {
|
|
252
285
|
const ownDb = db === void 0;
|
|
253
286
|
const resolvedDb = db ?? DatabaseManager.open();
|
|
254
287
|
try {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
process.exit(2);
|
|
258
|
-
} else {
|
|
259
|
-
resolvedDb.db.prepare("UPDATE memories SET pinned = 0 WHERE id = ?").run(id);
|
|
260
|
-
process.stdout.write(`${chalk.green("✓")} Unpinned: ${chalk.dim(id)}\n`);
|
|
261
|
-
}
|
|
288
|
+
new MemoryRepository(resolvedDb, new EmbeddingService(), new ProjectRepository(resolvedDb)).setPin(id, false);
|
|
289
|
+
process.stdout.write(`${chalk.green("✓")} Unpinned: ${chalk.dim(id)}\n`);
|
|
262
290
|
} finally {
|
|
263
291
|
if (ownDb) resolvedDb.close();
|
|
264
292
|
}
|
|
@@ -299,7 +327,7 @@ var Formatter = class Formatter {
|
|
|
299
327
|
process.stdout.write(` ${colorType(memory.type)} ${chalk.dim(memory.id)}\n`);
|
|
300
328
|
process.stdout.write(` ${memory.content}\n`);
|
|
301
329
|
const scope = memory.projects.length > 0 ? memory.projects.map((p) => p.name).join(", ") : "global";
|
|
302
|
-
process.stdout.write(` ${chalk.dim("Tags:")} ${tags} ${chalk.dim("
|
|
330
|
+
process.stdout.write(` ${chalk.dim("Tags:")} ${tags} ${chalk.dim("Project:")} ${scope}\n`);
|
|
303
331
|
process.stdout.write(`\n ${chalk.dim(`Hint: pin with membank pin ${memory.id}`)}\n\n`);
|
|
304
332
|
}
|
|
305
333
|
outputMemories(memories) {
|
|
@@ -1257,7 +1285,7 @@ program.command("delete <id>").description("delete a memory by ID").action(async
|
|
|
1257
1285
|
db.close();
|
|
1258
1286
|
}
|
|
1259
1287
|
});
|
|
1260
|
-
program.command("add <content>").description("save a new memory").requiredOption("--type <type>", "memory type (correction|preference|decision|learning|fact)").option("--tags <tags>", "comma-separated tags").option("--
|
|
1288
|
+
program.command("add <content>").description("save a new memory").requiredOption("--type <type>", "memory type (correction|preference|decision|learning|fact)").option("--tags <tags>", "comma-separated tags").option("--global", "save as a global memory, not tied to any project").action(async (content, cmdOptions) => {
|
|
1261
1289
|
const globalOpts = program.opts();
|
|
1262
1290
|
const formatter = Formatter.create(globalOpts.json === true);
|
|
1263
1291
|
try {
|
|
@@ -1271,7 +1299,7 @@ program.command("pin <id>").description("pin a memory by ID").action((id) => {
|
|
|
1271
1299
|
const globalOpts = program.opts();
|
|
1272
1300
|
const formatter = Formatter.create(globalOpts.json === true);
|
|
1273
1301
|
try {
|
|
1274
|
-
pinCommand(id
|
|
1302
|
+
pinCommand(id);
|
|
1275
1303
|
} catch (err) {
|
|
1276
1304
|
formatter.error(err instanceof Error ? err.message : String(err));
|
|
1277
1305
|
process.exit(2);
|
|
@@ -1281,7 +1309,7 @@ program.command("unpin <id>").description("unpin a memory by ID").action((id) =>
|
|
|
1281
1309
|
const globalOpts = program.opts();
|
|
1282
1310
|
const formatter = Formatter.create(globalOpts.json === true);
|
|
1283
1311
|
try {
|
|
1284
|
-
unpinCommand(id
|
|
1312
|
+
unpinCommand(id);
|
|
1285
1313
|
} catch (err) {
|
|
1286
1314
|
formatter.error(err instanceof Error ? err.message : String(err));
|
|
1287
1315
|
process.exit(2);
|
|
@@ -1314,7 +1342,7 @@ program.command("import <file>").description("import memories from a JSON export
|
|
|
1314
1342
|
db.close();
|
|
1315
1343
|
}
|
|
1316
1344
|
});
|
|
1317
|
-
program.command("inject").description("output session context for harness injection (used by setup hooks)").option("--harness <name>", "format output for a specific harness (claude-code|copilot-cli|codex|opencode)").option("--
|
|
1345
|
+
program.command("inject").description("output session context for harness injection (used by setup hooks)").option("--harness <name>", "format output for a specific harness (claude-code|copilot-cli|codex|opencode)").option("--event <event>", "hook event type (only session-start is supported; other values no-op for legacy hook compatibility)", "session-start").action(async (cmdOptions) => {
|
|
1318
1346
|
try {
|
|
1319
1347
|
await injectCommand(cmdOptions);
|
|
1320
1348
|
} catch (err) {
|
|
@@ -1390,6 +1418,20 @@ program.command("setup").description("detect installed harnesses and write MCP c
|
|
|
1390
1418
|
process.exit(2);
|
|
1391
1419
|
}
|
|
1392
1420
|
});
|
|
1421
|
+
program.command("migrate <mode> [name]").description("list or run a named data migration (modes: list, run)").action(async (mode, name) => {
|
|
1422
|
+
if (mode !== "list" && mode !== "run") {
|
|
1423
|
+
process.stderr.write(`Error: mode must be "list" or "run"\n`);
|
|
1424
|
+
process.exit(1);
|
|
1425
|
+
}
|
|
1426
|
+
const globalOpts = program.opts();
|
|
1427
|
+
const formatter = Formatter.create(globalOpts.json === true);
|
|
1428
|
+
try {
|
|
1429
|
+
await migrateCommand(mode, name, formatter);
|
|
1430
|
+
} catch (err) {
|
|
1431
|
+
formatter.error(err instanceof Error ? err.message : String(err));
|
|
1432
|
+
process.exit(2);
|
|
1433
|
+
}
|
|
1434
|
+
});
|
|
1393
1435
|
program.command("dashboard").description("open the memory management dashboard in the browser").option("--port <port>", "port to listen on (default: 3847, fallback to random)").action(async (cmdOptions) => {
|
|
1394
1436
|
try {
|
|
1395
1437
|
await dashboardCommand(cmdOptions);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@membank/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"cli-table3": "^0.6.5",
|
|
21
21
|
"commander": "^14.0.3",
|
|
22
22
|
"ora": "^9.4.0",
|
|
23
|
-
"@membank/core": "0.6.
|
|
24
|
-
"@membank/
|
|
25
|
-
"@membank/
|
|
23
|
+
"@membank/core": "0.6.1",
|
|
24
|
+
"@membank/mcp": "0.8.0",
|
|
25
|
+
"@membank/dashboard": "0.4.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^25.6.0",
|