myagentmemory 0.4.8 → 0.4.11
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 +140 -11
- package/dist/core.d.ts +72 -2
- package/dist/core.js +494 -4
- package/package.json +1 -1
- package/scripts/install-skills.sh +46 -9
- 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 +158 -13
- package/src/core.ts +596 -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) {
|
|
@@ -520,7 +616,7 @@ async function cmdInit(flags: Record<string, string | boolean>) {
|
|
|
520
616
|
);
|
|
521
617
|
} else {
|
|
522
618
|
console.log(`Memory directory: ${dir}`);
|
|
523
|
-
console.log(` MEMORY.md, SCRATCHPAD.md, daily/ created.`);
|
|
619
|
+
console.log(` MEMORY.md, SCRATCHPAD.md, daily/, topics/ created.`);
|
|
524
620
|
if (qmdFound) {
|
|
525
621
|
if (collectionCreated) {
|
|
526
622
|
console.log(` qmd collection '${getCollectionName()}' created.`);
|
|
@@ -548,6 +644,7 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
548
644
|
const memFile = getMemoryFile();
|
|
549
645
|
const spFile = getScratchpadFile();
|
|
550
646
|
const dailyDir = getDailyDir();
|
|
647
|
+
const topicsDir = getTopicsDir();
|
|
551
648
|
|
|
552
649
|
const memContent = readFileSafe(memFile);
|
|
553
650
|
const spContent = readFileSafe(spFile);
|
|
@@ -558,6 +655,12 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
558
655
|
} catch {
|
|
559
656
|
// directory may not exist
|
|
560
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
|
+
}
|
|
561
664
|
|
|
562
665
|
const qmdFound = await detectQmd();
|
|
563
666
|
let hasCollection = false;
|
|
@@ -587,6 +690,7 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
587
690
|
openItems: spContent ? parseScratchpad(spContent).filter((i) => !i.done).length : 0,
|
|
588
691
|
},
|
|
589
692
|
dailyLogs: dailyCount,
|
|
693
|
+
topics: topicCount,
|
|
590
694
|
qmd: {
|
|
591
695
|
available: qmdFound,
|
|
592
696
|
collection: hasCollection ? getCollectionName() : null,
|
|
@@ -613,6 +717,7 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
613
717
|
console.log("SCRATCHPAD.md: not created yet");
|
|
614
718
|
}
|
|
615
719
|
console.log(`Daily logs: ${dailyCount} file(s)`);
|
|
720
|
+
console.log(`Topics: ${topicCount} file(s)`);
|
|
616
721
|
console.log("");
|
|
617
722
|
if (qmdFound) {
|
|
618
723
|
console.log(`qmd: available`);
|
|
@@ -635,6 +740,33 @@ async function cmdStatus(flags: Record<string, string | boolean>) {
|
|
|
635
740
|
}
|
|
636
741
|
}
|
|
637
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
|
+
|
|
638
770
|
// ---------------------------------------------------------------------------
|
|
639
771
|
// Usage
|
|
640
772
|
// ---------------------------------------------------------------------------
|
|
@@ -647,12 +779,14 @@ Usage:
|
|
|
647
779
|
|
|
648
780
|
Commands:
|
|
649
781
|
version Show binary version
|
|
650
|
-
install-skills Install bundled skills
|
|
782
|
+
install-skills Install (or --uninstall) bundled skills
|
|
783
|
+
uninstall-skills Uninstall bundled skills
|
|
651
784
|
context Build & print context injection string
|
|
652
|
-
write Write to memory files
|
|
785
|
+
write Write to memory files (default: daily)
|
|
653
786
|
read Read memory files
|
|
654
787
|
scratchpad Manage checklist items
|
|
655
788
|
search Search across memory files (requires qmd)
|
|
789
|
+
distil Generate compact MEMORY.md index from daily logs + topics
|
|
656
790
|
sync Re-index and embed all files (requires qmd)
|
|
657
791
|
init Initialize memory directory and qmd collection
|
|
658
792
|
status Show configuration and status
|
|
@@ -663,15 +797,19 @@ Global flags:
|
|
|
663
797
|
|
|
664
798
|
Examples:
|
|
665
799
|
agent-memory init
|
|
800
|
+
agent-memory write --content "Fixed auth bug in login flow"
|
|
666
801
|
agent-memory write --target long_term --content "User prefers dark mode"
|
|
667
|
-
agent-memory write --target
|
|
802
|
+
agent-memory write --target topic --topic "auth" --content "Rolled JWT refresh to edge"
|
|
668
803
|
agent-memory read --target long_term
|
|
669
804
|
agent-memory read --target daily --date 2026-02-15
|
|
670
805
|
agent-memory read --target list
|
|
806
|
+
agent-memory read --target topic --topic "auth"
|
|
807
|
+
agent-memory read --target topics
|
|
671
808
|
agent-memory scratchpad add --text "Review PR #42"
|
|
672
809
|
agent-memory scratchpad list
|
|
673
810
|
agent-memory scratchpad done --text "PR #42"
|
|
674
811
|
agent-memory search --query "database choice" --mode keyword
|
|
812
|
+
agent-memory distil --dry-run
|
|
675
813
|
agent-memory context --no-search
|
|
676
814
|
agent-memory sync
|
|
677
815
|
agent-memory status --json`);
|
|
@@ -720,6 +858,13 @@ async function main() {
|
|
|
720
858
|
case "install-skills":
|
|
721
859
|
cmdInstallSkills(flags);
|
|
722
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;
|
|
723
868
|
case "sync":
|
|
724
869
|
await cmdSync(flags);
|
|
725
870
|
break;
|