@slorenzot/memento-cli 0.2.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/CLI.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export declare class CLI {
2
+ private program;
3
+ private memory;
4
+ private activeSessionId;
5
+ private projectId;
6
+ constructor();
7
+ private setupCommands;
8
+ private getOrCreateSessionId;
9
+ run(argv?: string[]): Promise<void>;
10
+ close(): void;
11
+ }
12
+ //# sourceMappingURL=CLI.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../src/CLI.ts"],"names":[],"mappings":"AAKA,qBAAa,GAAG;IACd,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,SAAS,CAAS;;IAY1B,OAAO,CAAC,aAAa;YAsJP,oBAAoB;IAa5B,GAAG,CAAC,IAAI,GAAE,MAAM,EAAiB;IAIvC,KAAK;CAGN"}
package/dist/CLI.js ADDED
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CLI = void 0;
4
+ const commander_1 = require("commander");
5
+ const memento_core_1 = require("@slorenzot/memento-core");
6
+ // @ts-ignore
7
+ class CLI {
8
+ program;
9
+ memory;
10
+ activeSessionId = null;
11
+ projectId;
12
+ constructor() {
13
+ const config = (0, memento_core_1.loadConfig)();
14
+ const dbPath = (0, memento_core_1.resolveDbPath)(config);
15
+ this.projectId = (0, memento_core_1.getProjectId)(config);
16
+ this.program = new commander_1.Command();
17
+ this.memory = new memento_core_1.MemoryEngine(dbPath);
18
+ this.setupCommands();
19
+ }
20
+ setupCommands() {
21
+ this.program
22
+ .name('memento')
23
+ .description('Persistent memory system for AI coding agents')
24
+ .version('0.1.0');
25
+ this.program
26
+ .command('setup [agent]')
27
+ .description('Setup configuration for an AI agent')
28
+ .action((agent) => {
29
+ console.log(`Setup for agent: ${agent || 'default'}`);
30
+ console.log('Configuration saved to ~/.memento/config.json');
31
+ });
32
+ this.program
33
+ .command('serve [port]')
34
+ .description('Start API server')
35
+ .option('-d, --db <path>', 'Database path', './data/memento.db')
36
+ .action((port, options) => {
37
+ console.log(`Starting API server on port ${port || 3000}`);
38
+ console.log(`Database: ${options.db}`);
39
+ console.log('Note: API server not implemented in CLI mode');
40
+ });
41
+ this.program
42
+ .command('mcp')
43
+ .description('Start MCP server')
44
+ .option('-d, --db <path>', 'Database path', './data/memento.db')
45
+ .action((options) => {
46
+ console.log(`Starting MCP server`);
47
+ console.log(`Database: ${options.db}`);
48
+ console.log('Note: MCP server not implemented in CLI mode');
49
+ });
50
+ this.program
51
+ .command('search <query>')
52
+ .description('Search observations')
53
+ .option('-t, --type <type>', 'Filter by type')
54
+ .option('-p, --project <project>', 'Filter by project')
55
+ .option('--limit <number>', 'Limit results')
56
+ .action(async (query, options) => {
57
+ const result = await this.memory.search({
58
+ query,
59
+ type: options.type,
60
+ projectId: options.project,
61
+ limit: options.limit ? parseInt(options.limit) : undefined,
62
+ });
63
+ console.log(`Found ${result.total} observations:`);
64
+ result.observations.forEach((obs) => {
65
+ console.log(` [${obs.type}] ${obs.title}`);
66
+ console.log(` ${obs.content.substring(0, 100)}...`);
67
+ });
68
+ });
69
+ this.program
70
+ .command('save <title> <content>')
71
+ .description('Save an observation')
72
+ .option('-t, --type <type>', 'Observation type', 'note')
73
+ .option('-k, --topic <topic>', 'Topic key')
74
+ .option('-p, --project <project>', 'Project ID', this.projectId)
75
+ .action(async (title, content, options) => {
76
+ const sessionId = await this.getOrCreateSessionId(options.project);
77
+ const observation = await this.memory.createObservation({
78
+ sessionId,
79
+ title,
80
+ content,
81
+ type: options.type,
82
+ topicKey: options.topic || null,
83
+ projectId: options.project,
84
+ metadata: {},
85
+ });
86
+ console.log(`Saved observation: ${observation.uuid}`);
87
+ });
88
+ this.program
89
+ .command('get <id>')
90
+ .description('Get observation by ID')
91
+ .action(async (id) => {
92
+ const observation = await this.memory.getObservation(parseInt(id));
93
+ if (!observation) {
94
+ console.error('Observation not found');
95
+ return;
96
+ }
97
+ console.log(`[${observation.type}] ${observation.title}`);
98
+ console.log(observation.content);
99
+ console.log(`Topic: ${observation.topicKey || 'none'}`);
100
+ console.log(`Created: ${observation.createdAt.toISOString()}`);
101
+ });
102
+ this.program
103
+ .command('update <id>')
104
+ .description('Update observation')
105
+ .option('-t, --title <title>', 'New title')
106
+ .option('-c, --content <content>', 'New content')
107
+ .option('-k, --topic <topic>', 'New topic key')
108
+ .action(async (id, options) => {
109
+ const updates = {};
110
+ if (options.title)
111
+ updates.title = options.title;
112
+ if (options.content)
113
+ updates.content = options.content;
114
+ if (options.topic)
115
+ updates.topicKey = options.topic;
116
+ const observation = await this.memory.updateObservation(parseInt(id), updates);
117
+ console.log(`Updated observation: ${observation.uuid}`);
118
+ });
119
+ this.program
120
+ .command('delete <id>')
121
+ .description('Delete observation')
122
+ .action(async (id) => {
123
+ await this.memory.deleteObservation(parseInt(id));
124
+ console.log(`Deleted observation ${id}`);
125
+ });
126
+ this.program
127
+ .command('timeline [project]')
128
+ .description('Show timeline of observations')
129
+ .option('-l, --limit <number>', 'Limit results', '20')
130
+ .action(async (project, options) => {
131
+ const result = await this.memory.search({
132
+ projectId: project,
133
+ limit: parseInt(options.limit),
134
+ });
135
+ console.log(`Timeline (${result.total} observations):`);
136
+ result.observations.forEach((obs) => {
137
+ const date = obs.createdAt.toLocaleDateString();
138
+ console.log(` ${date} [${obs.type}] ${obs.title}`);
139
+ });
140
+ });
141
+ this.program
142
+ .command('stats')
143
+ .description('Show statistics')
144
+ .action(async () => {
145
+ const result = await this.memory.search({});
146
+ const byType = result.observations.reduce((acc, obs) => {
147
+ acc[obs.type] = (acc[obs.type] || 0) + 1;
148
+ return acc;
149
+ }, {});
150
+ console.log('Statistics:');
151
+ console.log(` Total observations: ${result.total}`);
152
+ console.log(' By type:');
153
+ Object.entries(byType).forEach(([type, count]) => {
154
+ console.log(` ${type}: ${count}`);
155
+ });
156
+ });
157
+ }
158
+ async getOrCreateSessionId(projectId) {
159
+ if (this.activeSessionId) {
160
+ return this.activeSessionId;
161
+ }
162
+ const session = await this.memory.createSession({
163
+ projectId,
164
+ endedAt: null,
165
+ metadata: {},
166
+ });
167
+ this.activeSessionId = session.id;
168
+ return session.id;
169
+ }
170
+ async run(argv = process.argv) {
171
+ await this.program.parseAsync(argv);
172
+ }
173
+ close() {
174
+ this.memory.close();
175
+ }
176
+ }
177
+ exports.CLI = CLI;
178
+ //# sourceMappingURL=CLI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CLI.js","sourceRoot":"","sources":["../src/CLI.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -3,7 +3,12 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const commander_1 = require("commander");
5
5
  const memento_core_1 = require("@slorenzot/memento-core");
6
- const dbPath = process.env.MEMENTO_DB_PATH || "./data/memento.db";
6
+ const fs_1 = require("fs");
7
+ const path_1 = require("path");
8
+ const os_1 = require("os");
9
+ const config = (0, memento_core_1.loadConfig)();
10
+ const dbPath = (0, memento_core_1.resolveDbPath)(config);
11
+ const projectId = (0, memento_core_1.getProjectId)(config);
7
12
  const memory = new memento_core_1.MemoryEngine(dbPath);
8
13
  let activeSessionId = null;
9
14
  async function getOrCreateSessionId(projectId) {
@@ -14,42 +19,75 @@ async function getOrCreateSessionId(projectId) {
14
19
  return session.id;
15
20
  }
16
21
  const program = new commander_1.Command();
17
- program.name("memento").description("Persistent memory system for AI coding agents").version("0.2.0");
18
- program.command("search <query>").description("Search observations")
19
- .option("-t, --type <type>", "Filter by type")
20
- .option("-p, --project <project>", "Filter by project")
21
- .option("--limit <number>", "Limit results")
22
+ program
23
+ .name('memento')
24
+ .description('Persistent memory system for AI coding agents')
25
+ .version('1.0.0');
26
+ // ─── Search ─────────────────────────────────────────────────
27
+ program
28
+ .command('search <query>')
29
+ .description('Search observations')
30
+ .option('-t, --type <type>', 'Filter by type')
31
+ .option('-p, --project <project>', 'Filter by project')
32
+ .option('--limit <number>', 'Limit results')
33
+ .option('--include-deleted', 'Include soft-deleted observations')
22
34
  .action(async (query, options) => {
23
- const result = await memory.search({ query, type: options.type, projectId: options.project, limit: options.limit ? parseInt(options.limit) : undefined });
35
+ const result = await memory.search({
36
+ query,
37
+ type: options.type,
38
+ projectId: options.project,
39
+ limit: options.limit ? parseInt(options.limit) : undefined,
40
+ includeDeleted: options.includeDeleted,
41
+ });
24
42
  console.log(`Found ${result.total} observations:`);
25
- result.observations.forEach((obs) => { console.log(` [${obs.type}] ${obs.title}\n ${obs.content.substring(0, 100)}...`); });
43
+ result.observations.forEach((obs) => {
44
+ const deleted = obs.deletedAt ? ' [DELETED]' : '';
45
+ console.log(` [${obs.type}] ${obs.title}${deleted}\n ${obs.content.substring(0, 100)}...`);
46
+ });
26
47
  memory.close();
27
48
  });
28
- program.command("save <title> <content>").description("Save an observation")
29
- .option("-t, --type <type>", "Observation type", "note")
30
- .option("-k, --topic <topic>", "Topic key")
31
- .option("-p, --project <project>", "Project ID", "default")
49
+ // ─── Save ───────────────────────────────────────────────────
50
+ program
51
+ .command('save <title> <content>')
52
+ .description('Save an observation')
53
+ .option('-t, --type <type>', 'Observation type', 'note')
54
+ .option('-k, --topic <topic>', 'Topic key')
55
+ .option('-p, --project <project>', 'Project ID', projectId)
32
56
  .action(async (title, content, options) => {
33
57
  const sessionId = await getOrCreateSessionId(options.project);
34
- const observation = await memory.createObservation({ sessionId, title, content, type: options.type, topicKey: options.topic || null, projectId: options.project, metadata: {} });
58
+ const observation = await memory.createObservation({
59
+ sessionId,
60
+ title,
61
+ content,
62
+ type: options.type,
63
+ topicKey: options.topic || null,
64
+ projectId: options.project,
65
+ metadata: {},
66
+ });
35
67
  console.log(`Saved observation: ${observation.uuid}`);
36
68
  memory.close();
37
69
  });
38
- program.command("get <id>").description("Get observation by ID")
70
+ // ─── Get ────────────────────────────────────────────────────
71
+ program
72
+ .command('get <id>')
73
+ .description('Get observation by ID')
39
74
  .action(async (id) => {
40
75
  const observation = await memory.getObservation(parseInt(id));
41
76
  if (!observation) {
42
- console.error("Observation not found");
77
+ console.error('Observation not found');
43
78
  memory.close();
44
79
  return;
45
80
  }
46
- console.log(`[${observation.type}] ${observation.title}\n${observation.content}\nTopic: ${observation.topicKey || "none"}\nCreated: ${observation.createdAt.toISOString()}`);
81
+ console.log(`[${observation.type}] ${observation.title}\n${observation.content}\nTopic: ${observation.topicKey || 'none'}\nCreated: ${observation.createdAt.toISOString()}`);
47
82
  memory.close();
48
83
  });
49
- program.command("update <id>").description("Update observation")
50
- .option("-t, --title <title>", "New title")
51
- .option("-c, --content <content>", "New content")
52
- .option("-k, --topic <topic>", "New topic key")
84
+ // ─── Update ─────────────────────────────────────────────────
85
+ program
86
+ .command('update <id>')
87
+ .description('Update observation')
88
+ .option('-t, --title <title>', 'New title')
89
+ .option('-c, --content <content>', 'New content')
90
+ .option('-k, --topic <topic>', 'New topic key')
53
91
  .action(async (id, options) => {
54
92
  const updates = {};
55
93
  if (options.title)
@@ -62,28 +100,214 @@ program.command("update <id>").description("Update observation")
62
100
  console.log(`Updated observation: ${observation.uuid}`);
63
101
  memory.close();
64
102
  });
65
- program.command("delete <id>").description("Delete observation")
103
+ // ─── Delete (soft) ──────────────────────────────────────────
104
+ program
105
+ .command('delete <id>')
106
+ .description('Soft-delete observation (can be restored)')
107
+ .option('-r, --reason <reason>', 'Reason for deletion')
108
+ .action(async (id, options) => {
109
+ await memory.deleteObservation(parseInt(id), options.reason);
110
+ console.log(`Soft-deleted observation ${id} (use 'restore' to undo, 'purge' to permanently delete)`);
111
+ memory.close();
112
+ });
113
+ // ─── Restore ────────────────────────────────────────────────
114
+ program
115
+ .command('restore <id>')
116
+ .description('Restore a soft-deleted observation')
66
117
  .action(async (id) => {
67
- await memory.deleteObservation(parseInt(id));
68
- console.log(`Deleted observation ${id}`);
118
+ const obs = await memory.restoreObservation(parseInt(id));
119
+ console.log(`Restored observation: ${obs.uuid} — "${obs.title}"`);
69
120
  memory.close();
70
121
  });
71
- program.command("timeline [project]").description("Show timeline")
72
- .option("-l, --limit <number>", "Limit results", "20")
122
+ // ─── Purge ──────────────────────────────────────────────────
123
+ program
124
+ .command('purge')
125
+ .description('Permanently delete soft-deleted observations (IRREVERSIBLE)')
126
+ .option('-p, --project <project>', 'Purge only for this project')
127
+ .option('--yes', 'Skip confirmation')
128
+ .action(async (options) => {
129
+ if (!options.yes) {
130
+ console.error('⚠️ This will PERMANENTLY delete all soft-deleted observations.');
131
+ console.error(' Use --yes to confirm.');
132
+ memory.close();
133
+ return;
134
+ }
135
+ const result = await memory.purgeObservations({ projectId: options.project });
136
+ console.log(`Purged ${result.purgedCount} observations permanently.`);
137
+ if (result.purgedIds.length > 0) {
138
+ console.log(`IDs: ${result.purgedIds.join(', ')}`);
139
+ }
140
+ memory.close();
141
+ });
142
+ // ─── List Deleted ───────────────────────────────────────────
143
+ program
144
+ .command('list-deleted')
145
+ .description('List soft-deleted observations')
146
+ .option('-p, --project <project>', 'Filter by project')
147
+ .option('-l, --limit <number>', 'Limit results', '20')
148
+ .action(async (options) => {
149
+ const result = await memory.listDeleted({
150
+ projectId: options.project,
151
+ limit: parseInt(options.limit),
152
+ });
153
+ console.log(`Soft-deleted observations (${result.total} total):`);
154
+ result.observations.forEach((obs) => {
155
+ console.log(` [#${obs.id}] ${obs.title} — deleted: ${obs.deletedAt?.toISOString()}`);
156
+ });
157
+ memory.close();
158
+ });
159
+ // ─── Merge ──────────────────────────────────────────────────
160
+ program
161
+ .command('merge')
162
+ .description('Merge related observations')
163
+ .requiredOption('-p, --project <project>', 'Project ID')
164
+ .option('-s, --strategy <strategy>', 'Strategy: by_topic, by_similarity, by_ids', 'by_topic')
165
+ .option('-k, --topic <topic>', 'Merge only this topic key')
166
+ .option('--dry-run', 'Preview candidates without executing')
167
+ .action(async (options) => {
168
+ const results = await memory.mergeObservations({
169
+ projectId: options.project,
170
+ topicKey: options.topic,
171
+ strategy: options.strategy,
172
+ dryRun: options.dryRun,
173
+ });
174
+ if (options.dryRun) {
175
+ console.log(`Merge candidates (dry run — no changes made):`);
176
+ }
177
+ else {
178
+ console.log(`Merge results:`);
179
+ }
180
+ for (const r of results) {
181
+ console.log(` Merged ${r.originalCount} obs → #${r.mergedObservation.id} "${r.mergedObservation.title}" (deleted: ${r.deletedIds.join(', ')})`);
182
+ }
183
+ if (results.length === 0) {
184
+ console.log(' No candidates found for merging.');
185
+ }
186
+ memory.close();
187
+ });
188
+ // ─── Export ─────────────────────────────────────────────────
189
+ program
190
+ .command('export')
191
+ .description('Export observations to JSON, XML, or TXT')
192
+ .option('-f, --format <format>', 'Format: json, xml, txt', 'json')
193
+ .option('-p, --project <project>', 'Filter by project')
194
+ .option('-t, --type <type>', 'Filter by type')
195
+ .option('-k, --topic <topic>', 'Filter by topic key')
196
+ .option('--from <date>', 'Export from this date (ISO format)')
197
+ .option('--to <date>', 'Export until this date (ISO format)')
198
+ .option('--include-deleted', 'Include soft-deleted observations')
199
+ .option('-o, --output <file>', 'Output file path (default: stdout)')
200
+ .action(async (options) => {
201
+ const result = await memory.exportObservations({
202
+ format: options.format,
203
+ projectId: options.project,
204
+ type: options.type,
205
+ topicKey: options.topic,
206
+ dateFrom: options.from ? new Date(options.from) : undefined,
207
+ dateTo: options.to ? new Date(options.to) : undefined,
208
+ includeDeleted: options.includeDeleted,
209
+ });
210
+ if (options.output) {
211
+ const { writeFileSync } = await import('fs');
212
+ writeFileSync(options.output, result.content, 'utf-8');
213
+ console.error(`Exported ${result.recordCount} observations to ${options.output} (${result.format})`);
214
+ }
215
+ else {
216
+ console.log(result.content);
217
+ }
218
+ memory.close();
219
+ });
220
+ // ─── Timeline ───────────────────────────────────────────────
221
+ program
222
+ .command('timeline [project]')
223
+ .description('Show timeline')
224
+ .option('-l, --limit <number>', 'Limit results', '20')
73
225
  .action(async (project, options) => {
74
226
  const result = await memory.search({ projectId: project, limit: parseInt(options.limit) });
75
227
  console.log(`Timeline (${result.total} observations):`);
76
- result.observations.forEach((obs) => { console.log(` ${obs.createdAt.toLocaleDateString()} [${obs.type}] ${obs.title}`); });
228
+ result.observations.forEach((obs) => {
229
+ console.log(` ${obs.createdAt.toLocaleDateString()} [${obs.type}] ${obs.title}`);
230
+ });
77
231
  memory.close();
78
232
  });
79
- program.command("stats").description("Show statistics")
233
+ // ─── Stats ──────────────────────────────────────────────────
234
+ program
235
+ .command('stats')
236
+ .description('Show statistics')
80
237
  .action(async () => {
81
238
  const result = await memory.search({});
239
+ const deleted = await memory.listDeleted({});
82
240
  const byType = {};
83
- result.observations.forEach((obs) => { byType[obs.type] = (byType[obs.type] || 0) + 1; });
84
- console.log(`Statistics:\n Total observations: ${result.total}\n By type:`);
85
- Object.entries(byType).forEach(([type, count]) => { console.log(` ${type}: ${count}`); });
241
+ result.observations.forEach((obs) => {
242
+ byType[obs.type] = (byType[obs.type] || 0) + 1;
243
+ });
244
+ console.log(`Statistics:`);
245
+ console.log(` Total observations: ${result.total}`);
246
+ console.log(` Soft-deleted: ${deleted.total}`);
247
+ console.log(` By type:`);
248
+ Object.entries(byType).forEach(([type, count]) => {
249
+ console.log(` ${type}: ${count}`);
250
+ });
86
251
  memory.close();
87
252
  });
253
+ // ─── Install Skill ──────────────────────────────────────────
254
+ program
255
+ .command('install-skill')
256
+ .description('Install Memento AI skill for coding agents')
257
+ .option('--target <target>', 'Target: opencode, claude, or a custom path', 'opencode')
258
+ .action(async (options) => {
259
+ const target = options.target;
260
+ // Resolve SKILL.md source — try multiple locations
261
+ const possiblePaths = [
262
+ // When installed as npm package
263
+ (0, path_1.join)((0, path_1.dirname)(require.resolve('@slorenzot/memento-mcp-server/package.json')), 'skills', 'memento', 'SKILL.md'),
264
+ ].filter(() => {
265
+ try {
266
+ require.resolve('@slorenzot/memento-mcp-server/package.json');
267
+ return true;
268
+ }
269
+ catch {
270
+ return false;
271
+ }
272
+ });
273
+ // Fallback: relative to this CLI package (monorepo dev)
274
+ possiblePaths.push((0, path_1.join)(__dirname, '..', '..', 'mcp-server', 'skills', 'memento', 'SKILL.md'), (0, path_1.join)(__dirname, '..', '..', '..', 'packages', 'mcp-server', 'skills', 'memento', 'SKILL.md'));
275
+ let sourcePath = null;
276
+ for (const p of possiblePaths) {
277
+ if ((0, fs_1.existsSync)(p)) {
278
+ sourcePath = p;
279
+ break;
280
+ }
281
+ }
282
+ if (!sourcePath) {
283
+ console.error('Error: Could not find SKILL.md file.');
284
+ console.error('Searched in:', possiblePaths);
285
+ console.error('Make sure @slorenzot/memento-mcp-server is installed.');
286
+ process.exit(1);
287
+ }
288
+ // Determine destination
289
+ let destDir;
290
+ switch (target) {
291
+ case 'opencode':
292
+ destDir = (0, path_1.join)((0, os_1.homedir)(), '.config', 'opencode', 'skills', 'memento');
293
+ break;
294
+ case 'claude':
295
+ destDir = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'skills', 'memento');
296
+ break;
297
+ default:
298
+ // Custom path
299
+ destDir = (0, path_1.join)(target, 'memento');
300
+ break;
301
+ }
302
+ const destPath = (0, path_1.join)(destDir, 'SKILL.md');
303
+ // Create directory and copy
304
+ (0, fs_1.mkdirSync)(destDir, { recursive: true });
305
+ (0, fs_1.copyFileSync)(sourcePath, destPath);
306
+ console.log(`✓ Memento skill installed successfully!`);
307
+ console.log(` Source: ${sourcePath}`);
308
+ console.log(` Target: ${destPath}`);
309
+ console.log(` Agent: ${target}`);
310
+ console.log(`\n The AI agent will now know how to use all memento_mem_* tools.`);
311
+ });
88
312
  program.parseAsync(process.argv);
89
313
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@slorenzot/memento-cli",
3
- "version": "0.2.1",
4
- "description": "CLI interface for Memento memory system",
3
+ "version": "1.0.0",
4
+ "description": "CLI interface for Memento memory system with merge, export, soft-delete, and skill installation",
5
5
  "keywords": [
6
6
  "memento",
7
7
  "memory",
8
- "cli"
8
+ "cli",
9
+ "merge",
10
+ "export"
9
11
  ],
10
12
  "license": "CC-BY-NC-ND-4.0",
11
13
  "author": "Soulberto Lorenzo",
@@ -21,7 +23,7 @@
21
23
  "prepare": "npm run build"
22
24
  },
23
25
  "dependencies": {
24
- "@slorenzot/memento-core": "^0.2.0",
26
+ "@slorenzot/memento-core": "^1.0.0",
25
27
  "commander": "^12.0.0"
26
28
  },
27
29
  "devDependencies": {
@@ -0,0 +1,60 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
2
+ import { CLI } from './CLI';
3
+
4
+ describe('CLI', () => {
5
+ let cli: CLI;
6
+ let testDbPath: string;
7
+
8
+ beforeEach(() => {
9
+ testDbPath = `/tmp/test-cli-${Date.now()}.db`;
10
+ cli = new CLI(testDbPath);
11
+ });
12
+
13
+ afterEach(() => {
14
+ cli.close();
15
+ });
16
+
17
+ it('should initialize without errors', () => {
18
+ expect(cli).toBeDefined();
19
+ });
20
+
21
+ describe('Commands', () => {
22
+ it('should have all required commands', () => {
23
+ const commands = cli['program'].commands;
24
+
25
+ const commandNames = commands.map((c) => c.name());
26
+ expect(commandNames).toContain('setup');
27
+ expect(commandNames).toContain('serve');
28
+ expect(commandNames).toContain('mcp');
29
+ expect(commandNames).toContain('search');
30
+ expect(commandNames).toContain('save');
31
+ expect(commandNames).toContain('get');
32
+ expect(commandNames).toContain('update');
33
+ expect(commandNames).toContain('delete');
34
+ expect(commandNames).toContain('timeline');
35
+ expect(commandNames).toContain('stats');
36
+ });
37
+
38
+ it('should have proper descriptions', () => {
39
+ const commands = cli['program'].commands;
40
+
41
+ const setupCommand = commands.find((c) => c.name() === 'setup');
42
+ expect(setupCommand).toBeDefined();
43
+ expect(setupCommand?.description()).toContain('Setup');
44
+
45
+ const searchCommand = commands.find((c) => c.name() === 'search');
46
+ expect(searchCommand).toBeDefined();
47
+ expect(searchCommand?.description()).toContain('Search');
48
+ });
49
+ });
50
+
51
+ describe('Session Management', () => {
52
+ it('should create and track active session', async () => {
53
+ const sessionId = await cli['getOrCreateSessionId']('test-project');
54
+ expect(sessionId).toBeDefined();
55
+
56
+ const sameSessionId = await cli['getOrCreateSessionId']('test-project');
57
+ expect(sameSessionId).toBe(sessionId);
58
+ });
59
+ });
60
+ });
package/src/CLI.ts ADDED
@@ -0,0 +1,192 @@
1
+ import { Command } from 'commander';
2
+ import { MemoryEngine, loadConfig, resolveDbPath, getProjectId } from '@slorenzot/memento-core';
3
+ import type { Observation } from '@slorenzot/memento-core';
4
+
5
+ // @ts-ignore
6
+ export class CLI {
7
+ private program: Command;
8
+ private memory: MemoryEngine;
9
+ private activeSessionId: number | null = null;
10
+ private projectId: string;
11
+
12
+ constructor() {
13
+ const config = loadConfig();
14
+ const dbPath = resolveDbPath(config);
15
+ this.projectId = getProjectId(config);
16
+
17
+ this.program = new Command();
18
+ this.memory = new MemoryEngine(dbPath);
19
+ this.setupCommands();
20
+ }
21
+
22
+ private setupCommands() {
23
+ this.program
24
+ .name('memento')
25
+ .description('Persistent memory system for AI coding agents')
26
+ .version('0.1.0');
27
+
28
+ this.program
29
+ .command('setup [agent]')
30
+ .description('Setup configuration for an AI agent')
31
+ .action((agent) => {
32
+ console.log(`Setup for agent: ${agent || 'default'}`);
33
+ console.log('Configuration saved to ~/.memento/config.json');
34
+ });
35
+
36
+ this.program
37
+ .command('serve [port]')
38
+ .description('Start API server')
39
+ .option('-d, --db <path>', 'Database path', './data/memento.db')
40
+ .action((port, options) => {
41
+ console.log(`Starting API server on port ${port || 3000}`);
42
+ console.log(`Database: ${options.db}`);
43
+ console.log('Note: API server not implemented in CLI mode');
44
+ });
45
+
46
+ this.program
47
+ .command('mcp')
48
+ .description('Start MCP server')
49
+ .option('-d, --db <path>', 'Database path', './data/memento.db')
50
+ .action((options) => {
51
+ console.log(`Starting MCP server`);
52
+ console.log(`Database: ${options.db}`);
53
+ console.log('Note: MCP server not implemented in CLI mode');
54
+ });
55
+
56
+ this.program
57
+ .command('search <query>')
58
+ .description('Search observations')
59
+ .option('-t, --type <type>', 'Filter by type')
60
+ .option('-p, --project <project>', 'Filter by project')
61
+ .option('--limit <number>', 'Limit results')
62
+ .action(async (query, options) => {
63
+ const result = await this.memory.search({
64
+ query,
65
+ type: options.type as Observation['type'] | undefined,
66
+ projectId: options.project as string | undefined,
67
+ limit: options.limit ? parseInt(options.limit as string) : undefined,
68
+ });
69
+ console.log(`Found ${result.total} observations:`);
70
+ result.observations.forEach((obs) => {
71
+ console.log(` [${obs.type}] ${obs.title}`);
72
+ console.log(` ${obs.content.substring(0, 100)}...`);
73
+ });
74
+ });
75
+
76
+ this.program
77
+ .command('save <title> <content>')
78
+ .description('Save an observation')
79
+ .option('-t, --type <type>', 'Observation type', 'note')
80
+ .option('-k, --topic <topic>', 'Topic key')
81
+ .option('-p, --project <project>', 'Project ID', this.projectId)
82
+ .action(async (title, content, options) => {
83
+ const sessionId = await this.getOrCreateSessionId(options.project as string);
84
+ const observation = await this.memory.createObservation({
85
+ sessionId,
86
+ title,
87
+ content,
88
+ type: options.type as Observation['type'],
89
+ topicKey: options.topic || null,
90
+ projectId: options.project as string,
91
+ metadata: {},
92
+ });
93
+ console.log(`Saved observation: ${observation.uuid}`);
94
+ });
95
+
96
+ this.program
97
+ .command('get <id>')
98
+ .description('Get observation by ID')
99
+ .action(async (id) => {
100
+ const observation = await this.memory.getObservation(parseInt(id));
101
+ if (!observation) {
102
+ console.error('Observation not found');
103
+ return;
104
+ }
105
+ console.log(`[${observation.type}] ${observation.title}`);
106
+ console.log(observation.content);
107
+ console.log(`Topic: ${observation.topicKey || 'none'}`);
108
+ console.log(`Created: ${observation.createdAt.toISOString()}`);
109
+ });
110
+
111
+ this.program
112
+ .command('update <id>')
113
+ .description('Update observation')
114
+ .option('-t, --title <title>', 'New title')
115
+ .option('-c, --content <content>', 'New content')
116
+ .option('-k, --topic <topic>', 'New topic key')
117
+ .action(async (id, options) => {
118
+ const updates: Partial<Observation> = {};
119
+ if (options.title) updates.title = options.title;
120
+ if (options.content) updates.content = options.content;
121
+ if (options.topic) updates.topicKey = options.topic;
122
+
123
+ const observation = await this.memory.updateObservation(parseInt(id), updates);
124
+ console.log(`Updated observation: ${observation.uuid}`);
125
+ });
126
+
127
+ this.program
128
+ .command('delete <id>')
129
+ .description('Delete observation')
130
+ .action(async (id) => {
131
+ await this.memory.deleteObservation(parseInt(id));
132
+ console.log(`Deleted observation ${id}`);
133
+ });
134
+
135
+ this.program
136
+ .command('timeline [project]')
137
+ .description('Show timeline of observations')
138
+ .option('-l, --limit <number>', 'Limit results', '20')
139
+ .action(async (project, options) => {
140
+ const result = await this.memory.search({
141
+ projectId: project,
142
+ limit: parseInt(options.limit as string),
143
+ });
144
+ console.log(`Timeline (${result.total} observations):`);
145
+ result.observations.forEach((obs) => {
146
+ const date = obs.createdAt.toLocaleDateString();
147
+ console.log(` ${date} [${obs.type}] ${obs.title}`);
148
+ });
149
+ });
150
+
151
+ this.program
152
+ .command('stats')
153
+ .description('Show statistics')
154
+ .action(async () => {
155
+ const result = await this.memory.search({});
156
+ const byType = result.observations.reduce(
157
+ (acc, obs) => {
158
+ acc[obs.type] = (acc[obs.type] || 0) + 1;
159
+ return acc;
160
+ },
161
+ {} as Record<string, number>
162
+ );
163
+ console.log('Statistics:');
164
+ console.log(` Total observations: ${result.total}`);
165
+ console.log(' By type:');
166
+ Object.entries(byType).forEach(([type, count]) => {
167
+ console.log(` ${type}: ${count}`);
168
+ });
169
+ });
170
+ }
171
+
172
+ private async getOrCreateSessionId(projectId: string): Promise<number> {
173
+ if (this.activeSessionId) {
174
+ return this.activeSessionId;
175
+ }
176
+ const session = await this.memory.createSession({
177
+ projectId,
178
+ endedAt: null,
179
+ metadata: {},
180
+ });
181
+ this.activeSessionId = session.id;
182
+ return session.id;
183
+ }
184
+
185
+ async run(argv: string[] = process.argv) {
186
+ await this.program.parseAsync(argv);
187
+ }
188
+
189
+ close() {
190
+ this.memory.close();
191
+ }
192
+ }
package/src/index.ts CHANGED
@@ -1,10 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { Command } from "commander";
4
- import { MemoryEngine } from "@slorenzot/memento-core";
5
- import type { Observation } from "@slorenzot/memento-core";
3
+ import { Command } from 'commander';
4
+ import { MemoryEngine, loadConfig, resolveDbPath, getProjectId } from '@slorenzot/memento-core';
5
+ import type { Observation, ExportFormat } from '@slorenzot/memento-core';
6
+ import { existsSync, mkdirSync, copyFileSync } from 'fs';
7
+ import { join, dirname } from 'path';
8
+ import { homedir } from 'os';
6
9
 
7
- const dbPath = process.env.MEMENTO_DB_PATH || "./data/memento.db";
10
+ const config = loadConfig();
11
+ const dbPath = resolveDbPath(config);
12
+ const projectId = getProjectId(config);
8
13
  const memory = new MemoryEngine(dbPath);
9
14
  let activeSessionId: number | null = null;
10
15
 
@@ -16,42 +21,87 @@ async function getOrCreateSessionId(projectId: string): Promise<number> {
16
21
  }
17
22
 
18
23
  const program = new Command();
19
- program.name("memento").description("Persistent memory system for AI coding agents").version("0.2.0");
24
+ program
25
+ .name('memento')
26
+ .description('Persistent memory system for AI coding agents')
27
+ .version('1.0.0');
20
28
 
21
- program.command("search <query>").description("Search observations")
22
- .option("-t, --type <type>", "Filter by type")
23
- .option("-p, --project <project>", "Filter by project")
24
- .option("--limit <number>", "Limit results")
29
+ // ─── Search ─────────────────────────────────────────────────
30
+
31
+ program
32
+ .command('search <query>')
33
+ .description('Search observations')
34
+ .option('-t, --type <type>', 'Filter by type')
35
+ .option('-p, --project <project>', 'Filter by project')
36
+ .option('--limit <number>', 'Limit results')
37
+ .option('--include-deleted', 'Include soft-deleted observations')
25
38
  .action(async (query: string, options: any) => {
26
- const result = await memory.search({ query, type: options.type, projectId: options.project, limit: options.limit ? parseInt(options.limit) : undefined });
39
+ const result = await memory.search({
40
+ query,
41
+ type: options.type,
42
+ projectId: options.project,
43
+ limit: options.limit ? parseInt(options.limit) : undefined,
44
+ includeDeleted: options.includeDeleted,
45
+ });
27
46
  console.log(`Found ${result.total} observations:`);
28
- result.observations.forEach((obs: Observation) => { console.log(` [${obs.type}] ${obs.title}\n ${obs.content.substring(0, 100)}...`); });
47
+ result.observations.forEach((obs: Observation) => {
48
+ const deleted = obs.deletedAt ? ' [DELETED]' : '';
49
+ console.log(
50
+ ` [${obs.type}] ${obs.title}${deleted}\n ${obs.content.substring(0, 100)}...`
51
+ );
52
+ });
29
53
  memory.close();
30
54
  });
31
55
 
32
- program.command("save <title> <content>").description("Save an observation")
33
- .option("-t, --type <type>", "Observation type", "note")
34
- .option("-k, --topic <topic>", "Topic key")
35
- .option("-p, --project <project>", "Project ID", "default")
56
+ // ─── Save ───────────────────────────────────────────────────
57
+
58
+ program
59
+ .command('save <title> <content>')
60
+ .description('Save an observation')
61
+ .option('-t, --type <type>', 'Observation type', 'note')
62
+ .option('-k, --topic <topic>', 'Topic key')
63
+ .option('-p, --project <project>', 'Project ID', projectId)
36
64
  .action(async (title: string, content: string, options: any) => {
37
65
  const sessionId = await getOrCreateSessionId(options.project);
38
- const observation = await memory.createObservation({ sessionId, title, content, type: options.type, topicKey: options.topic || null, projectId: options.project, metadata: {} });
66
+ const observation = await memory.createObservation({
67
+ sessionId,
68
+ title,
69
+ content,
70
+ type: options.type,
71
+ topicKey: options.topic || null,
72
+ projectId: options.project,
73
+ metadata: {},
74
+ });
39
75
  console.log(`Saved observation: ${observation.uuid}`);
40
76
  memory.close();
41
77
  });
42
78
 
43
- program.command("get <id>").description("Get observation by ID")
79
+ // ─── Get ────────────────────────────────────────────────────
80
+
81
+ program
82
+ .command('get <id>')
83
+ .description('Get observation by ID')
44
84
  .action(async (id: string) => {
45
85
  const observation = await memory.getObservation(parseInt(id));
46
- if (!observation) { console.error("Observation not found"); memory.close(); return; }
47
- console.log(`[${observation.type}] ${observation.title}\n${observation.content}\nTopic: ${observation.topicKey || "none"}\nCreated: ${observation.createdAt.toISOString()}`);
86
+ if (!observation) {
87
+ console.error('Observation not found');
88
+ memory.close();
89
+ return;
90
+ }
91
+ console.log(
92
+ `[${observation.type}] ${observation.title}\n${observation.content}\nTopic: ${observation.topicKey || 'none'}\nCreated: ${observation.createdAt.toISOString()}`
93
+ );
48
94
  memory.close();
49
95
  });
50
96
 
51
- program.command("update <id>").description("Update observation")
52
- .option("-t, --title <title>", "New title")
53
- .option("-c, --content <content>", "New content")
54
- .option("-k, --topic <topic>", "New topic key")
97
+ // ─── Update ─────────────────────────────────────────────────
98
+
99
+ program
100
+ .command('update <id>')
101
+ .description('Update observation')
102
+ .option('-t, --title <title>', 'New title')
103
+ .option('-c, --content <content>', 'New content')
104
+ .option('-k, --topic <topic>', 'New topic key')
55
105
  .action(async (id: string, options: any) => {
56
106
  const updates: any = {};
57
107
  if (options.title) updates.title = options.title;
@@ -62,30 +112,258 @@ program.command("update <id>").description("Update observation")
62
112
  memory.close();
63
113
  });
64
114
 
65
- program.command("delete <id>").description("Delete observation")
115
+ // ─── Delete (soft) ──────────────────────────────────────────
116
+
117
+ program
118
+ .command('delete <id>')
119
+ .description('Soft-delete observation (can be restored)')
120
+ .option('-r, --reason <reason>', 'Reason for deletion')
121
+ .action(async (id: string, options: any) => {
122
+ await memory.deleteObservation(parseInt(id), options.reason);
123
+ console.log(
124
+ `Soft-deleted observation ${id} (use 'restore' to undo, 'purge' to permanently delete)`
125
+ );
126
+ memory.close();
127
+ });
128
+
129
+ // ─── Restore ────────────────────────────────────────────────
130
+
131
+ program
132
+ .command('restore <id>')
133
+ .description('Restore a soft-deleted observation')
66
134
  .action(async (id: string) => {
67
- await memory.deleteObservation(parseInt(id));
68
- console.log(`Deleted observation ${id}`);
135
+ const obs = await memory.restoreObservation(parseInt(id));
136
+ console.log(`Restored observation: ${obs.uuid} — "${obs.title}"`);
137
+ memory.close();
138
+ });
139
+
140
+ // ─── Purge ──────────────────────────────────────────────────
141
+
142
+ program
143
+ .command('purge')
144
+ .description('Permanently delete soft-deleted observations (IRREVERSIBLE)')
145
+ .option('-p, --project <project>', 'Purge only for this project')
146
+ .option('--yes', 'Skip confirmation')
147
+ .action(async (options: any) => {
148
+ if (!options.yes) {
149
+ console.error('⚠️ This will PERMANENTLY delete all soft-deleted observations.');
150
+ console.error(' Use --yes to confirm.');
151
+ memory.close();
152
+ return;
153
+ }
154
+
155
+ const result = await memory.purgeObservations({ projectId: options.project });
156
+ console.log(`Purged ${result.purgedCount} observations permanently.`);
157
+ if (result.purgedIds.length > 0) {
158
+ console.log(`IDs: ${result.purgedIds.join(', ')}`);
159
+ }
160
+ memory.close();
161
+ });
162
+
163
+ // ─── List Deleted ───────────────────────────────────────────
164
+
165
+ program
166
+ .command('list-deleted')
167
+ .description('List soft-deleted observations')
168
+ .option('-p, --project <project>', 'Filter by project')
169
+ .option('-l, --limit <number>', 'Limit results', '20')
170
+ .action(async (options: any) => {
171
+ const result = await memory.listDeleted({
172
+ projectId: options.project,
173
+ limit: parseInt(options.limit),
174
+ });
175
+ console.log(`Soft-deleted observations (${result.total} total):`);
176
+ result.observations.forEach((obs: Observation) => {
177
+ console.log(` [#${obs.id}] ${obs.title} — deleted: ${obs.deletedAt?.toISOString()}`);
178
+ });
69
179
  memory.close();
70
180
  });
71
181
 
72
- program.command("timeline [project]").description("Show timeline")
73
- .option("-l, --limit <number>", "Limit results", "20")
182
+ // ─── Merge ──────────────────────────────────────────────────
183
+
184
+ program
185
+ .command('merge')
186
+ .description('Merge related observations')
187
+ .requiredOption('-p, --project <project>', 'Project ID')
188
+ .option('-s, --strategy <strategy>', 'Strategy: by_topic, by_similarity, by_ids', 'by_topic')
189
+ .option('-k, --topic <topic>', 'Merge only this topic key')
190
+ .option('--dry-run', 'Preview candidates without executing')
191
+ .action(async (options: any) => {
192
+ const results = await memory.mergeObservations({
193
+ projectId: options.project,
194
+ topicKey: options.topic,
195
+ strategy: options.strategy,
196
+ dryRun: options.dryRun,
197
+ });
198
+
199
+ if (options.dryRun) {
200
+ console.log(`Merge candidates (dry run — no changes made):`);
201
+ } else {
202
+ console.log(`Merge results:`);
203
+ }
204
+
205
+ for (const r of results) {
206
+ console.log(
207
+ ` Merged ${r.originalCount} obs → #${r.mergedObservation.id} "${r.mergedObservation.title}" (deleted: ${r.deletedIds.join(', ')})`
208
+ );
209
+ }
210
+
211
+ if (results.length === 0) {
212
+ console.log(' No candidates found for merging.');
213
+ }
214
+
215
+ memory.close();
216
+ });
217
+
218
+ // ─── Export ─────────────────────────────────────────────────
219
+
220
+ program
221
+ .command('export')
222
+ .description('Export observations to JSON, XML, or TXT')
223
+ .option('-f, --format <format>', 'Format: json, xml, txt', 'json')
224
+ .option('-p, --project <project>', 'Filter by project')
225
+ .option('-t, --type <type>', 'Filter by type')
226
+ .option('-k, --topic <topic>', 'Filter by topic key')
227
+ .option('--from <date>', 'Export from this date (ISO format)')
228
+ .option('--to <date>', 'Export until this date (ISO format)')
229
+ .option('--include-deleted', 'Include soft-deleted observations')
230
+ .option('-o, --output <file>', 'Output file path (default: stdout)')
231
+ .action(async (options: any) => {
232
+ const result = await memory.exportObservations({
233
+ format: options.format as ExportFormat,
234
+ projectId: options.project,
235
+ type: options.type,
236
+ topicKey: options.topic,
237
+ dateFrom: options.from ? new Date(options.from) : undefined,
238
+ dateTo: options.to ? new Date(options.to) : undefined,
239
+ includeDeleted: options.includeDeleted,
240
+ });
241
+
242
+ if (options.output) {
243
+ const { writeFileSync } = await import('fs');
244
+ writeFileSync(options.output, result.content, 'utf-8');
245
+ console.error(
246
+ `Exported ${result.recordCount} observations to ${options.output} (${result.format})`
247
+ );
248
+ } else {
249
+ console.log(result.content);
250
+ }
251
+
252
+ memory.close();
253
+ });
254
+
255
+ // ─── Timeline ───────────────────────────────────────────────
256
+
257
+ program
258
+ .command('timeline [project]')
259
+ .description('Show timeline')
260
+ .option('-l, --limit <number>', 'Limit results', '20')
74
261
  .action(async (project: string, options: any) => {
75
262
  const result = await memory.search({ projectId: project, limit: parseInt(options.limit) });
76
263
  console.log(`Timeline (${result.total} observations):`);
77
- result.observations.forEach((obs: Observation) => { console.log(` ${obs.createdAt.toLocaleDateString()} [${obs.type}] ${obs.title}`); });
264
+ result.observations.forEach((obs: Observation) => {
265
+ console.log(` ${obs.createdAt.toLocaleDateString()} [${obs.type}] ${obs.title}`);
266
+ });
78
267
  memory.close();
79
268
  });
80
269
 
81
- program.command("stats").description("Show statistics")
270
+ // ─── Stats ──────────────────────────────────────────────────
271
+
272
+ program
273
+ .command('stats')
274
+ .description('Show statistics')
82
275
  .action(async () => {
83
276
  const result = await memory.search({});
277
+ const deleted = await memory.listDeleted({});
84
278
  const byType: Record<string, number> = {};
85
- result.observations.forEach((obs: Observation) => { byType[obs.type] = (byType[obs.type] || 0) + 1; });
86
- console.log(`Statistics:\n Total observations: ${result.total}\n By type:`);
87
- Object.entries(byType).forEach(([type, count]) => { console.log(` ${type}: ${count}`); });
279
+ result.observations.forEach((obs: Observation) => {
280
+ byType[obs.type] = (byType[obs.type] || 0) + 1;
281
+ });
282
+ console.log(`Statistics:`);
283
+ console.log(` Total observations: ${result.total}`);
284
+ console.log(` Soft-deleted: ${deleted.total}`);
285
+ console.log(` By type:`);
286
+ Object.entries(byType).forEach(([type, count]) => {
287
+ console.log(` ${type}: ${count}`);
288
+ });
88
289
  memory.close();
89
290
  });
90
291
 
292
+ // ─── Install Skill ──────────────────────────────────────────
293
+
294
+ program
295
+ .command('install-skill')
296
+ .description('Install Memento AI skill for coding agents')
297
+ .option('--target <target>', 'Target: opencode, claude, or a custom path', 'opencode')
298
+ .action(async (options: any) => {
299
+ const target = options.target;
300
+
301
+ // Resolve SKILL.md source — try multiple locations
302
+ const possiblePaths = [
303
+ // When installed as npm package
304
+ join(
305
+ dirname(require.resolve('@slorenzot/memento-mcp-server/package.json')),
306
+ 'skills',
307
+ 'memento',
308
+ 'SKILL.md'
309
+ ),
310
+ ].filter(() => {
311
+ try {
312
+ require.resolve('@slorenzot/memento-mcp-server/package.json');
313
+ return true;
314
+ } catch {
315
+ return false;
316
+ }
317
+ });
318
+
319
+ // Fallback: relative to this CLI package (monorepo dev)
320
+ possiblePaths.push(
321
+ join(__dirname, '..', '..', 'mcp-server', 'skills', 'memento', 'SKILL.md'),
322
+ join(__dirname, '..', '..', '..', 'packages', 'mcp-server', 'skills', 'memento', 'SKILL.md')
323
+ );
324
+
325
+ let sourcePath: string | null = null;
326
+ for (const p of possiblePaths) {
327
+ if (existsSync(p)) {
328
+ sourcePath = p;
329
+ break;
330
+ }
331
+ }
332
+
333
+ if (!sourcePath) {
334
+ console.error('Error: Could not find SKILL.md file.');
335
+ console.error('Searched in:', possiblePaths);
336
+ console.error('Make sure @slorenzot/memento-mcp-server is installed.');
337
+ process.exit(1);
338
+ }
339
+
340
+ // Determine destination
341
+ let destDir: string;
342
+
343
+ switch (target) {
344
+ case 'opencode':
345
+ destDir = join(homedir(), '.config', 'opencode', 'skills', 'memento');
346
+ break;
347
+ case 'claude':
348
+ destDir = join(homedir(), '.claude', 'skills', 'memento');
349
+ break;
350
+ default:
351
+ // Custom path
352
+ destDir = join(target, 'memento');
353
+ break;
354
+ }
355
+
356
+ const destPath = join(destDir, 'SKILL.md');
357
+
358
+ // Create directory and copy
359
+ mkdirSync(destDir, { recursive: true });
360
+ copyFileSync(sourcePath, destPath);
361
+
362
+ console.log(`✓ Memento skill installed successfully!`);
363
+ console.log(` Source: ${sourcePath}`);
364
+ console.log(` Target: ${destPath}`);
365
+ console.log(` Agent: ${target}`);
366
+ console.log(`\n The AI agent will now know how to use all memento_mem_* tools.`);
367
+ });
368
+
91
369
  program.parseAsync(process.argv);
package/data/memento.db DELETED
Binary file
Binary file
Binary file
Binary file