myagentmemory 0.4.7 → 0.4.10
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/README.md +32 -7
- package/dist/agent-memory +0 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +151 -12
- package/dist/core.d.ts +77 -2
- package/dist/core.js +502 -4
- package/package.json +1 -1
- package/scripts/install-skills.ps1 +5 -2
- package/scripts/install-skills.sh +54 -11
- package/skills/agent/SKILL.md +39 -14
- package/skills/claude-code/SKILL.md +39 -14
- package/skills/codex/SKILL.md +39 -14
- package/skills/cursor/SKILL.md +39 -14
- package/src/cli.ts +167 -14
- package/src/core.ts +605 -6
package/src/cli.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Subcommands:
|
|
6
6
|
* version — Print binary version
|
|
7
|
-
* install-skills — Install SKILL.md files into local agent directories
|
|
7
|
+
* install-skills — Install (or --uninstall) SKILL.md files into local agent directories
|
|
8
8
|
* context — Build & print context injection string to stdout
|
|
9
9
|
* write — Write to memory files
|
|
10
10
|
* read — Read memory files
|
|
@@ -20,15 +20,13 @@
|
|
|
20
20
|
|
|
21
21
|
import * as fs from "node:fs";
|
|
22
22
|
|
|
23
|
-
declare const __VERSION__: string;
|
|
24
|
-
const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "dev";
|
|
25
|
-
|
|
26
23
|
import {
|
|
27
24
|
_setBaseDir,
|
|
28
25
|
buildMemoryContext,
|
|
29
26
|
checkCollection,
|
|
30
27
|
dailyPath,
|
|
31
28
|
detectQmd,
|
|
29
|
+
distilMemories,
|
|
32
30
|
ensureDirs,
|
|
33
31
|
ensureQmdAvailableForSync,
|
|
34
32
|
ensureQmdAvailableForUpdate,
|
|
@@ -41,6 +39,7 @@ import {
|
|
|
41
39
|
getQmdResultPath,
|
|
42
40
|
getQmdResultText,
|
|
43
41
|
getScratchpadFile,
|
|
42
|
+
getTopicsDir,
|
|
44
43
|
installSkills,
|
|
45
44
|
nowTimestamp,
|
|
46
45
|
parseScratchpad,
|
|
@@ -53,9 +52,15 @@ import {
|
|
|
53
52
|
searchRelevantMemories,
|
|
54
53
|
serializeScratchpad,
|
|
55
54
|
setupQmdCollection,
|
|
55
|
+
slugifyTopic,
|
|
56
56
|
todayStr,
|
|
57
|
+
topicPath,
|
|
58
|
+
uninstallSkills,
|
|
57
59
|
} from "./core.js";
|
|
58
60
|
|
|
61
|
+
declare const __VERSION__: string;
|
|
62
|
+
const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "dev";
|
|
63
|
+
|
|
59
64
|
// ---------------------------------------------------------------------------
|
|
60
65
|
// Arg parsing (no external deps)
|
|
61
66
|
// ---------------------------------------------------------------------------
|
|
@@ -151,12 +156,14 @@ async function cmdContext(flags: Record<string, string | boolean>) {
|
|
|
151
156
|
|
|
152
157
|
async function cmdWrite(flags: Record<string, string | boolean>) {
|
|
153
158
|
const json = hasFlag(flags, "json");
|
|
154
|
-
const target = getFlag(flags, "target");
|
|
159
|
+
const target = getFlag(flags, "target") ?? "daily";
|
|
155
160
|
const content = getFlag(flags, "content");
|
|
156
161
|
const mode = getFlag(flags, "mode") ?? "append";
|
|
162
|
+
const topic = getFlag(flags, "topic");
|
|
163
|
+
const date = getFlag(flags, "date");
|
|
157
164
|
|
|
158
|
-
if (!
|
|
159
|
-
exitError("--target must be 'long_term' or 'daily
|
|
165
|
+
if (!["long_term", "daily", "topic"].includes(target)) {
|
|
166
|
+
exitError("--target must be 'long_term', 'daily', or 'topic' (default: daily)", json);
|
|
160
167
|
}
|
|
161
168
|
if (!content) {
|
|
162
169
|
exitError("--content is required", json);
|
|
@@ -183,6 +190,33 @@ async function cmdWrite(flags: Record<string, string | boolean>) {
|
|
|
183
190
|
return;
|
|
184
191
|
}
|
|
185
192
|
|
|
193
|
+
if (target === "topic") {
|
|
194
|
+
if (!topic) {
|
|
195
|
+
exitError("--topic is required when --target is 'topic'", json);
|
|
196
|
+
}
|
|
197
|
+
const slug = slugifyTopic(topic);
|
|
198
|
+
if (!slug) {
|
|
199
|
+
exitError("--topic must include at least one letter or number", json);
|
|
200
|
+
}
|
|
201
|
+
const filePath = topicPath(slug);
|
|
202
|
+
const existing = readFileSafe(filePath) ?? "";
|
|
203
|
+
const linkDate = date?.trim() || todayStr();
|
|
204
|
+
const header = `# Topic: ${topic}\n\n<!-- created: ${ts} [${sid}] -->\n`;
|
|
205
|
+
const separator = existing.trim() ? "\n\n" : "";
|
|
206
|
+
const base = existing.trim() ? existing : header.trimEnd();
|
|
207
|
+
const stamped = `<!-- ${ts} [${sid}] -->\n${content.trim()}\nDaily: [[${linkDate}]]`;
|
|
208
|
+
fs.writeFileSync(filePath, `${base}${separator}${stamped}`, "utf-8");
|
|
209
|
+
await ensureQmdAvailableForUpdate();
|
|
210
|
+
scheduleQmdUpdate();
|
|
211
|
+
output(
|
|
212
|
+
json
|
|
213
|
+
? { ok: true, path: filePath, target, mode: "append", timestamp: ts, topic, slug, date: linkDate }
|
|
214
|
+
: `Appended to topic: ${filePath}`,
|
|
215
|
+
json,
|
|
216
|
+
);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
186
220
|
// long_term
|
|
187
221
|
const memFile = getMemoryFile();
|
|
188
222
|
const existing = readFileSafe(memFile) ?? "";
|
|
@@ -209,9 +243,10 @@ async function cmdRead(flags: Record<string, string | boolean>) {
|
|
|
209
243
|
const json = hasFlag(flags, "json");
|
|
210
244
|
const target = getFlag(flags, "target");
|
|
211
245
|
const date = getFlag(flags, "date");
|
|
246
|
+
const topic = getFlag(flags, "topic");
|
|
212
247
|
|
|
213
|
-
if (!target || !["long_term", "scratchpad", "daily", "list"].includes(target)) {
|
|
214
|
-
exitError("--target must be 'long_term', 'scratchpad', 'daily', or '
|
|
248
|
+
if (!target || !["long_term", "scratchpad", "daily", "list", "topic", "topics"].includes(target)) {
|
|
249
|
+
exitError("--target must be 'long_term', 'scratchpad', 'daily', 'list', 'topic', or 'topics'", json);
|
|
215
250
|
}
|
|
216
251
|
|
|
217
252
|
ensureDirs();
|
|
@@ -248,6 +283,41 @@ async function cmdRead(flags: Record<string, string | boolean>) {
|
|
|
248
283
|
return;
|
|
249
284
|
}
|
|
250
285
|
|
|
286
|
+
if (target === "topics") {
|
|
287
|
+
try {
|
|
288
|
+
const files = fs
|
|
289
|
+
.readdirSync(getTopicsDir())
|
|
290
|
+
.filter((f) => f.endsWith(".md"))
|
|
291
|
+
.sort()
|
|
292
|
+
.reverse();
|
|
293
|
+
if (json) {
|
|
294
|
+
output({ files }, true);
|
|
295
|
+
} else if (files.length === 0) {
|
|
296
|
+
console.log("No topics found.");
|
|
297
|
+
} else {
|
|
298
|
+
console.log(`Topics:\n${files.map((f) => `- ${f}`).join("\n")}`);
|
|
299
|
+
}
|
|
300
|
+
} catch {
|
|
301
|
+
output(json ? { files: [] } : "No topics directory.", json);
|
|
302
|
+
}
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (target === "topic") {
|
|
307
|
+
if (!topic) {
|
|
308
|
+
exitError("--topic is required when --target is 'topic'", json);
|
|
309
|
+
}
|
|
310
|
+
const slug = slugifyTopic(topic);
|
|
311
|
+
const filePath = topicPath(slug);
|
|
312
|
+
const content = readFileSafe(filePath);
|
|
313
|
+
if (!content) {
|
|
314
|
+
output(json ? { content: null, topic } : `No topic file found for ${topic}.`, json);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
output(json ? { content, topic, slug, path: filePath } : content, json);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
251
321
|
if (target === "scratchpad") {
|
|
252
322
|
const content = readFileSafe(getScratchpadFile());
|
|
253
323
|
if (!content?.trim()) {
|
|
@@ -402,6 +472,32 @@ async function cmdSearch(flags: Record<string, string | boolean>) {
|
|
|
402
472
|
|
|
403
473
|
function cmdInstallSkills(flags: Record<string, string | boolean>) {
|
|
404
474
|
const json = hasFlag(flags, "json");
|
|
475
|
+
const uninstall = hasFlag(flags, "uninstall");
|
|
476
|
+
|
|
477
|
+
if (uninstall) {
|
|
478
|
+
const report = uninstallSkills();
|
|
479
|
+
|
|
480
|
+
if (!report.ok) {
|
|
481
|
+
exitError(report.error ?? "Failed to uninstall skills.", json);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (json) {
|
|
485
|
+
output(report, true);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
for (const item of report.removed) {
|
|
490
|
+
console.log(`Uninstalled ${item.label}: ${item.path}`);
|
|
491
|
+
}
|
|
492
|
+
for (const item of report.skipped) {
|
|
493
|
+
console.log(`Skipping ${item.label} (${item.reason})`);
|
|
494
|
+
}
|
|
495
|
+
if (report.removed.length === 0) {
|
|
496
|
+
console.log("No skills were installed.");
|
|
497
|
+
}
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
|
|
405
501
|
const report = installSkills();
|
|
406
502
|
|
|
407
503
|
if (!report.ok) {
|
|
@@ -413,7 +509,15 @@ function cmdInstallSkills(flags: Record<string, string | boolean>) {
|
|
|
413
509
|
return;
|
|
414
510
|
}
|
|
415
511
|
|
|
416
|
-
if (report.
|
|
512
|
+
if (report.checked.length > 0) {
|
|
513
|
+
for (const item of report.checked) {
|
|
514
|
+
if (item.status === "detected") {
|
|
515
|
+
console.log(`Detecting ${item.label}... found`);
|
|
516
|
+
} else {
|
|
517
|
+
console.log(`Detecting ${item.label}... not found (${item.reason ?? "unknown"})`);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
} else if (report.detected.length === 0) {
|
|
417
521
|
console.log("No supported agent installations detected.");
|
|
418
522
|
} else {
|
|
419
523
|
const detectedLabels = report.detected.map((item) => item.label).join(", ");
|
|
@@ -512,7 +616,7 @@ async function cmdInit(flags: Record<string, string | boolean>) {
|
|
|
512
616
|
);
|
|
513
617
|
} else {
|
|
514
618
|
console.log(`Memory directory: ${dir}`);
|
|
515
|
-
console.log(` MEMORY.md, SCRATCHPAD.md, daily/ created.`);
|
|
619
|
+
console.log(` MEMORY.md, SCRATCHPAD.md, daily/, topics/ created.`);
|
|
516
620
|
if (qmdFound) {
|
|
517
621
|
if (collectionCreated) {
|
|
518
622
|
console.log(` qmd collection '${getCollectionName()}' created.`);
|
|
@@ -540,6 +644,7 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
540
644
|
const memFile = getMemoryFile();
|
|
541
645
|
const spFile = getScratchpadFile();
|
|
542
646
|
const dailyDir = getDailyDir();
|
|
647
|
+
const topicsDir = getTopicsDir();
|
|
543
648
|
|
|
544
649
|
const memContent = readFileSafe(memFile);
|
|
545
650
|
const spContent = readFileSafe(spFile);
|
|
@@ -550,6 +655,12 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
550
655
|
} catch {
|
|
551
656
|
// directory may not exist
|
|
552
657
|
}
|
|
658
|
+
let topicCount = 0;
|
|
659
|
+
try {
|
|
660
|
+
topicCount = fs.readdirSync(topicsDir).filter((f) => f.endsWith(".md")).length;
|
|
661
|
+
} catch {
|
|
662
|
+
// directory may not exist
|
|
663
|
+
}
|
|
553
664
|
|
|
554
665
|
const qmdFound = await detectQmd();
|
|
555
666
|
let hasCollection = false;
|
|
@@ -579,6 +690,7 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
579
690
|
openItems: spContent ? parseScratchpad(spContent).filter((i) => !i.done).length : 0,
|
|
580
691
|
},
|
|
581
692
|
dailyLogs: dailyCount,
|
|
693
|
+
topics: topicCount,
|
|
582
694
|
qmd: {
|
|
583
695
|
available: qmdFound,
|
|
584
696
|
collection: hasCollection ? getCollectionName() : null,
|
|
@@ -605,6 +717,7 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
605
717
|
console.log("SCRATCHPAD.md: not created yet");
|
|
606
718
|
}
|
|
607
719
|
console.log(`Daily logs: ${dailyCount} file(s)`);
|
|
720
|
+
console.log(`Topics: ${topicCount} file(s)`);
|
|
608
721
|
console.log("");
|
|
609
722
|
if (qmdFound) {
|
|
610
723
|
console.log(`qmd: available`);
|
|
@@ -627,6 +740,33 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
627
740
|
}
|
|
628
741
|
}
|
|
629
742
|
|
|
743
|
+
async function cmdDistil(flags: Record<string, string | boolean>) {
|
|
744
|
+
const json = hasFlag(flags, "json");
|
|
745
|
+
const dryRun = hasFlag(flags, "dry-run");
|
|
746
|
+
|
|
747
|
+
const result = await distilMemories({ dryRun });
|
|
748
|
+
|
|
749
|
+
if (json) {
|
|
750
|
+
output(result, true);
|
|
751
|
+
} else {
|
|
752
|
+
if (result.totalEntries === 0) {
|
|
753
|
+
console.log(result.output.trim());
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
if (dryRun) {
|
|
757
|
+
console.log("--- Dry run (MEMORY.md not modified) ---\n");
|
|
758
|
+
}
|
|
759
|
+
console.log(result.output.trim());
|
|
760
|
+
console.log("");
|
|
761
|
+
console.log(
|
|
762
|
+
`Distilled ${result.totalEntries} entries from ${result.totalDailyFiles} daily file(s) and ${result.totalTopicFiles} topic file(s), ${result.totalTags} tag(s).`,
|
|
763
|
+
);
|
|
764
|
+
if (!dryRun) {
|
|
765
|
+
console.log("MEMORY.md updated.");
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
630
770
|
// ---------------------------------------------------------------------------
|
|
631
771
|
// Usage
|
|
632
772
|
// ---------------------------------------------------------------------------
|
|
@@ -639,12 +779,14 @@ Usage:
|
|
|
639
779
|
|
|
640
780
|
Commands:
|
|
641
781
|
version Show binary version
|
|
642
|
-
install-skills Install bundled skills
|
|
782
|
+
install-skills Install (or --uninstall) bundled skills
|
|
783
|
+
uninstall-skills Uninstall bundled skills
|
|
643
784
|
context Build & print context injection string
|
|
644
|
-
write Write to memory files
|
|
785
|
+
write Write to memory files (default: daily)
|
|
645
786
|
read Read memory files
|
|
646
787
|
scratchpad Manage checklist items
|
|
647
788
|
search Search across memory files (requires qmd)
|
|
789
|
+
distil Generate compact MEMORY.md index from daily logs + topics
|
|
648
790
|
sync Re-index and embed all files (requires qmd)
|
|
649
791
|
init Initialize memory directory and qmd collection
|
|
650
792
|
status Show configuration and status
|
|
@@ -655,15 +797,19 @@ Global flags:
|
|
|
655
797
|
|
|
656
798
|
Examples:
|
|
657
799
|
agent-memory init
|
|
800
|
+
agent-memory write --content "Fixed auth bug in login flow"
|
|
658
801
|
agent-memory write --target long_term --content "User prefers dark mode"
|
|
659
|
-
agent-memory write --target
|
|
802
|
+
agent-memory write --target topic --topic "auth" --content "Rolled JWT refresh to edge"
|
|
660
803
|
agent-memory read --target long_term
|
|
661
804
|
agent-memory read --target daily --date 2026-02-15
|
|
662
805
|
agent-memory read --target list
|
|
806
|
+
agent-memory read --target topic --topic "auth"
|
|
807
|
+
agent-memory read --target topics
|
|
663
808
|
agent-memory scratchpad add --text "Review PR #42"
|
|
664
809
|
agent-memory scratchpad list
|
|
665
810
|
agent-memory scratchpad done --text "PR #42"
|
|
666
811
|
agent-memory search --query "database choice" --mode keyword
|
|
812
|
+
agent-memory distil --dry-run
|
|
667
813
|
agent-memory context --no-search
|
|
668
814
|
agent-memory sync
|
|
669
815
|
agent-memory status --json`);
|
|
@@ -712,6 +858,13 @@ async function main() {
|
|
|
712
858
|
case "install-skills":
|
|
713
859
|
cmdInstallSkills(flags);
|
|
714
860
|
break;
|
|
861
|
+
case "uninstall-skills":
|
|
862
|
+
cmdInstallSkills({ ...flags, uninstall: true });
|
|
863
|
+
break;
|
|
864
|
+
case "distil":
|
|
865
|
+
case "distill":
|
|
866
|
+
await cmdDistil(flags);
|
|
867
|
+
break;
|
|
715
868
|
case "sync":
|
|
716
869
|
await cmdSync(flags);
|
|
717
870
|
break;
|