claude-memory-explorer 0.1.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.
Files changed (80) hide show
  1. package/.claude-plugin/plugin.json +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +177 -0
  4. package/dist/cli/commands/dedupe.d.ts +1 -0
  5. package/dist/cli/commands/dedupe.js +187 -0
  6. package/dist/cli/commands/dedupe.js.map +1 -0
  7. package/dist/cli/commands/doctor.d.ts +1 -0
  8. package/dist/cli/commands/doctor.js +177 -0
  9. package/dist/cli/commands/doctor.js.map +1 -0
  10. package/dist/cli/commands/lint.d.ts +1 -0
  11. package/dist/cli/commands/lint.js +139 -0
  12. package/dist/cli/commands/lint.js.map +1 -0
  13. package/dist/cli/commands/list.d.ts +1 -0
  14. package/dist/cli/commands/list.js +97 -0
  15. package/dist/cli/commands/list.js.map +1 -0
  16. package/dist/cli/commands/mcp.d.ts +1 -0
  17. package/dist/cli/commands/mcp.js +105 -0
  18. package/dist/cli/commands/mcp.js.map +1 -0
  19. package/dist/cli/commands/merge.d.ts +1 -0
  20. package/dist/cli/commands/merge.js +111 -0
  21. package/dist/cli/commands/merge.js.map +1 -0
  22. package/dist/cli/commands/promote.d.ts +1 -0
  23. package/dist/cli/commands/promote.js +157 -0
  24. package/dist/cli/commands/promote.js.map +1 -0
  25. package/dist/cli/commands/tui.d.ts +1 -0
  26. package/dist/cli/commands/tui.js +60 -0
  27. package/dist/cli/commands/tui.js.map +1 -0
  28. package/dist/cli/commands/undo.d.ts +1 -0
  29. package/dist/cli/commands/undo.js +157 -0
  30. package/dist/cli/commands/undo.js.map +1 -0
  31. package/dist/cli/index.d.ts +2 -0
  32. package/dist/cli/index.js +85 -0
  33. package/dist/cli/index.js.map +1 -0
  34. package/dist/cli/tui/App.d.ts +8 -0
  35. package/dist/cli/tui/App.js +333 -0
  36. package/dist/cli/tui/App.js.map +1 -0
  37. package/dist/core/apply.d.ts +27 -0
  38. package/dist/core/apply.js +191 -0
  39. package/dist/core/apply.js.map +1 -0
  40. package/dist/core/claudeMd.d.ts +27 -0
  41. package/dist/core/claudeMd.js +103 -0
  42. package/dist/core/claudeMd.js.map +1 -0
  43. package/dist/core/dedupe.d.ts +78 -0
  44. package/dist/core/dedupe.js +212 -0
  45. package/dist/core/dedupe.js.map +1 -0
  46. package/dist/core/doctor.d.ts +35 -0
  47. package/dist/core/doctor.js +106 -0
  48. package/dist/core/doctor.js.map +1 -0
  49. package/dist/core/journal.d.ts +31 -0
  50. package/dist/core/journal.js +64 -0
  51. package/dist/core/journal.js.map +1 -0
  52. package/dist/core/lint.d.ts +26 -0
  53. package/dist/core/lint.js +254 -0
  54. package/dist/core/lint.js.map +1 -0
  55. package/dist/core/memoryIndex.d.ts +42 -0
  56. package/dist/core/memoryIndex.js +81 -0
  57. package/dist/core/memoryIndex.js.map +1 -0
  58. package/dist/core/merge.d.ts +19 -0
  59. package/dist/core/merge.js +58 -0
  60. package/dist/core/merge.js.map +1 -0
  61. package/dist/core/parse.d.ts +2 -0
  62. package/dist/core/parse.js +84 -0
  63. package/dist/core/parse.js.map +1 -0
  64. package/dist/core/plan.d.ts +34 -0
  65. package/dist/core/plan.js +85 -0
  66. package/dist/core/plan.js.map +1 -0
  67. package/dist/core/promote.d.ts +29 -0
  68. package/dist/core/promote.js +103 -0
  69. package/dist/core/promote.js.map +1 -0
  70. package/dist/core/scan.d.ts +16 -0
  71. package/dist/core/scan.js +81 -0
  72. package/dist/core/scan.js.map +1 -0
  73. package/dist/core/types.d.ts +36 -0
  74. package/dist/core/types.js +4 -0
  75. package/dist/core/types.js.map +1 -0
  76. package/dist/mcp/server.d.ts +13 -0
  77. package/dist/mcp/server.js +211 -0
  78. package/dist/mcp/server.js.map +1 -0
  79. package/package.json +71 -0
  80. package/skills/curate-memory/SKILL.md +60 -0
@@ -0,0 +1,60 @@
1
+ // `memex tui` — interactive three-pane browser.
2
+ function parseArgs(argv) {
3
+ const out = { help: false };
4
+ for (let i = 0; i < argv.length; i++) {
5
+ const a = argv[i];
6
+ switch (a) {
7
+ case "--root":
8
+ out.root = argv[++i];
9
+ break;
10
+ case "--help":
11
+ case "-h":
12
+ out.help = true;
13
+ break;
14
+ default:
15
+ throw new Error(`unknown flag: ${a}`);
16
+ }
17
+ }
18
+ return out;
19
+ }
20
+ const HELP = `memex tui — interactive three-pane browser
21
+
22
+ Usage:
23
+ memex tui [--root PATH]
24
+
25
+ Keybindings (shown also via ? in-app):
26
+ ↑/↓ Navigate within a pane
27
+ Tab / ←/→ Switch pane
28
+ / Search across all memories
29
+ d Dedupe view (cross-project duplicate clusters)
30
+ l Lint view (structural issues)
31
+ ? Help
32
+ Esc Back to browse
33
+ q Quit
34
+
35
+ Read-only by design. Mutating actions (merge, promote, undo) stay on
36
+ the CLI, where they have dry-run + journal + undo by default.
37
+ `;
38
+ export async function runTui(argv) {
39
+ let args;
40
+ try {
41
+ args = parseArgs(argv);
42
+ }
43
+ catch (err) {
44
+ process.stderr.write(`memex tui: ${err instanceof Error ? err.message : String(err)}\n\n${HELP}`);
45
+ return 2;
46
+ }
47
+ if (args.help) {
48
+ process.stdout.write(HELP);
49
+ return 0;
50
+ }
51
+ // Lazy-import ink so the rest of memex doesn't pay the React startup cost
52
+ // when running CLI subcommands.
53
+ const { render } = await import("ink");
54
+ const { App } = await import("../tui/App.js");
55
+ const { createElement } = await import("react");
56
+ const instance = render(createElement(App, { projectsRoot: args.root }));
57
+ await instance.waitUntilExit();
58
+ return 0;
59
+ }
60
+ //# sourceMappingURL=tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui.js","sourceRoot":"","sources":["../../../src/cli/commands/tui.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAOhD,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,GAAG,GAAY,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,QAAQ,CAAC,EAAE,CAAC;YACV,KAAK,QAAQ;gBACX,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBACrB,MAAM;YACR,KAAK,QAAQ,CAAC;YACd,KAAK,IAAI;gBACP,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR;gBACE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;CAiBZ,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAClG,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC;IACX,CAAC;IAED,0EAA0E;IAC1E,gCAAgC;IAChC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;IAC9C,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACzE,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;IAC/B,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function runUndo(argv: string[]): number;
@@ -0,0 +1,157 @@
1
+ // `memex undo` — revert the most-recent applied plan, or list the journal.
2
+ //
3
+ // Exit codes:
4
+ // 0 success (or nothing to undo, with informative message)
5
+ // 1 undo failed mid-flight
6
+ // 2 bad usage
7
+ import { homedir } from "node:os";
8
+ import { relative } from "node:path";
9
+ import { listJournal, latestJournalEntry } from "../../core/journal.js";
10
+ import { undoPlan } from "../../core/apply.js";
11
+ function parseArgs(argv) {
12
+ const out = { list: false, json: false, dryRun: false, help: false };
13
+ for (let i = 0; i < argv.length; i++) {
14
+ const a = argv[i];
15
+ switch (a) {
16
+ case "--list":
17
+ out.list = true;
18
+ break;
19
+ case "--json":
20
+ out.json = true;
21
+ break;
22
+ case "--id":
23
+ out.id = argv[++i];
24
+ break;
25
+ case "--journal-dir":
26
+ out.journalDir = argv[++i];
27
+ break;
28
+ case "--dry-run":
29
+ out.dryRun = true;
30
+ break;
31
+ case "--help":
32
+ case "-h":
33
+ out.help = true;
34
+ break;
35
+ default:
36
+ throw new Error(`unknown flag: ${a}`);
37
+ }
38
+ }
39
+ return out;
40
+ }
41
+ const HELP = `memex undo — revert the most recent applied plan
42
+
43
+ Usage:
44
+ memex undo Revert the most recent applied plan
45
+ memex undo --id <plan-id> Revert a specific plan (warn if not most recent)
46
+ memex undo --dry-run Print what would be undone, change nothing
47
+ memex undo --list Show the journal (newest first)
48
+ memex undo --list --json Journal as JSON
49
+
50
+ Flags:
51
+ --id <plan-id> Revert a specific plan instead of the latest
52
+ --dry-run Print what would change, write nothing
53
+ --list Show the journal (newest first)
54
+ --json (with --list) emit journal as JSON
55
+ --journal-dir PATH Override journal location (default: ~/.claude/.memex/log/)
56
+
57
+ Exit codes:
58
+ 0 success, or nothing to undo (informative message)
59
+ 1 undo failed mid-flight (run --list to see state)
60
+ 2 bad usage
61
+
62
+ Journal location: ~/.claude/.memex/log/
63
+ `;
64
+ function shortPath(p) {
65
+ const home = homedir();
66
+ if (p.startsWith(home))
67
+ return "~" + p.slice(home.length);
68
+ try {
69
+ const r = relative(process.cwd(), p);
70
+ return r.length < p.length ? r : p;
71
+ }
72
+ catch {
73
+ return p;
74
+ }
75
+ }
76
+ function summarizeEntry(e) {
77
+ const opCount = e.plan.ops.length;
78
+ const ok = e.ops.filter((a) => a.result === "success").length;
79
+ const fail = e.ops.filter((a) => a.result === "failure").length;
80
+ const undoMark = e.undoOf ? ` (undo of ${e.undoOf})` : "";
81
+ return `${e.plan.id} ${e.status.padEnd(8)} ${e.plan.label.padEnd(28)} ${opCount} ops (${ok}✓ ${fail}✗)${undoMark}`;
82
+ }
83
+ export function runUndo(argv) {
84
+ let args;
85
+ try {
86
+ args = parseArgs(argv);
87
+ }
88
+ catch (err) {
89
+ process.stderr.write(`memex undo: ${err instanceof Error ? err.message : String(err)}\n\n${HELP}`);
90
+ return 2;
91
+ }
92
+ if (args.help) {
93
+ process.stdout.write(HELP);
94
+ return 0;
95
+ }
96
+ const journalOpts = args.journalDir ? { journalDir: args.journalDir } : {};
97
+ // --list mode
98
+ if (args.list) {
99
+ const entries = listJournal(journalOpts);
100
+ if (args.json) {
101
+ process.stdout.write(`${JSON.stringify(entries, null, 2)}\n`);
102
+ return 0;
103
+ }
104
+ if (entries.length === 0) {
105
+ process.stdout.write("(journal is empty)\n");
106
+ return 0;
107
+ }
108
+ process.stdout.write("Journal (newest first):\n");
109
+ for (const e of entries)
110
+ process.stdout.write(` ${summarizeEntry(e)}\n`);
111
+ return 0;
112
+ }
113
+ // Find target entry
114
+ const target = args.id ? null : latestJournalEntry(journalOpts);
115
+ if (!args.id && !target) {
116
+ process.stdout.write("Nothing to undo — journal is empty.\n");
117
+ return 0;
118
+ }
119
+ // Dry-run shows what would happen without writing.
120
+ if (args.dryRun) {
121
+ const t = args.id
122
+ ? listJournal(journalOpts).find((e) => e.plan.id === args.id)
123
+ : target;
124
+ if (!t) {
125
+ process.stderr.write(`memex undo: no journal entry with id "${args.id}"\n`);
126
+ return 2;
127
+ }
128
+ process.stdout.write(`Would undo: ${t.plan.label} (${t.plan.id})\n`);
129
+ const successOps = t.ops.filter((a) => a.result === "success");
130
+ process.stdout.write(` ${successOps.length} successful op(s) would be reversed:\n`);
131
+ for (const a of successOps.slice().reverse()) {
132
+ const inv = a.inverse;
133
+ const pathInfo = "path" in inv ? ` ${shortPath(inv.path)}` : "";
134
+ process.stdout.write(` ${inv.kind}${pathInfo}\n`);
135
+ }
136
+ return 0;
137
+ }
138
+ const { undone, newEntry } = undoPlan(args.id ?? "latest", {
139
+ ...journalOpts,
140
+ onProgress: (m) => process.stdout.write(`${m}\n`),
141
+ });
142
+ if (!undone) {
143
+ process.stderr.write(`memex undo: no journal entry with id "${args.id}"\n`);
144
+ return 2;
145
+ }
146
+ if (!newEntry) {
147
+ process.stdout.write(`Plan ${undone.plan.id} had no successful ops — nothing to reverse.\n`);
148
+ return 0;
149
+ }
150
+ if (newEntry.status === "complete") {
151
+ process.stdout.write(`✓ Undone: ${undone.plan.label} (was ${undone.plan.id}; recorded ${newEntry.plan.id})\n`);
152
+ return 0;
153
+ }
154
+ process.stderr.write(`✗ Undo failed mid-flight. Journal at ~/.claude/.memex/log/ — run \`memex undo --list\` for state.\n`);
155
+ return 1;
156
+ }
157
+ //# sourceMappingURL=undo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undo.js","sourceRoot":"","sources":["../../../src/cli/commands/undo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ // Entrypoint for the `memex` CLI. Dispatches subcommands to keep the bin small.
3
+ import { readFileSync } from "node:fs";
4
+ import { fileURLToPath } from "node:url";
5
+ import { dirname, join } from "node:path";
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "..", "package.json"), "utf8"));
8
+ const HELP = `memex ${pkg.version} — Claude Code memory curator
9
+
10
+ Usage:
11
+ memex <command> [options]
12
+
13
+ Commands:
14
+ list List memories across all projects
15
+ lint Report structural problems with memory files
16
+ doctor Health snapshot of your memory tree (run weekly)
17
+ dedupe Find duplicate memories across projects
18
+ merge Collapse a duplicate cluster down to its representative
19
+ promote Promote a memory to ~/.claude/CLAUDE.md as a managed block
20
+ undo Revert the most recent applied plan (memex's mutation log)
21
+ tui Interactive three-pane browser
22
+ mcp Run as an MCP server over stdio (for Claude Code plugins)
23
+ --version Print version
24
+ --help Show this help
25
+ `;
26
+ async function main(argv) {
27
+ const [cmd, ...rest] = argv;
28
+ if (!cmd || cmd === "--help" || cmd === "-h" || cmd === "help") {
29
+ process.stdout.write(HELP);
30
+ return 0;
31
+ }
32
+ if (cmd === "--version" || cmd === "-v") {
33
+ process.stdout.write(`${pkg.version}\n`);
34
+ return 0;
35
+ }
36
+ if (cmd === "list") {
37
+ const { runList } = await import("./commands/list.js");
38
+ return runList(rest);
39
+ }
40
+ if (cmd === "lint") {
41
+ const { runLint } = await import("./commands/lint.js");
42
+ return runLint(rest);
43
+ }
44
+ if (cmd === "doctor") {
45
+ const { runDoctorCli } = await import("./commands/doctor.js");
46
+ return runDoctorCli(rest);
47
+ }
48
+ if (cmd === "dedupe") {
49
+ const { runDedupe } = await import("./commands/dedupe.js");
50
+ return runDedupe(rest);
51
+ }
52
+ if (cmd === "undo") {
53
+ const { runUndo } = await import("./commands/undo.js");
54
+ return runUndo(rest);
55
+ }
56
+ if (cmd === "merge") {
57
+ const { runMerge } = await import("./commands/merge.js");
58
+ return runMerge(rest);
59
+ }
60
+ if (cmd === "promote") {
61
+ const { runPromote } = await import("./commands/promote.js");
62
+ return runPromote(rest);
63
+ }
64
+ if (cmd === "tui") {
65
+ const { runTui } = await import("./commands/tui.js");
66
+ return runTui(rest);
67
+ }
68
+ if (cmd === "mcp") {
69
+ const { runMcp } = await import("./commands/mcp.js");
70
+ return runMcp(rest);
71
+ }
72
+ process.stderr.write(`memex: unknown command "${cmd}"\n\n${HELP}`);
73
+ return 2;
74
+ }
75
+ // Setting process.exitCode (instead of calling process.exit) lets Node drain
76
+ // stdout/stderr buffers before the process terminates. Calling process.exit()
77
+ // with a piped stdout truncates output mid-write — broke `memex list --json |
78
+ // jq` on large outputs (~275 KB stress fixture).
79
+ main(process.argv.slice(2)).then((code) => {
80
+ process.exitCode = code;
81
+ }, (err) => {
82
+ process.stderr.write(`memex: ${err instanceof Error ? err.message : String(err)}\n`);
83
+ process.exitCode = 1;
84
+ });
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ProjectMemoryDir } from "../../core/types.js";
2
+ interface AppProps {
3
+ projectsRoot?: string;
4
+ /** Initial data injection — used by tests to avoid disk reads. */
5
+ initialProjects?: ProjectMemoryDir[];
6
+ }
7
+ export declare function App({ projectsRoot, initialProjects }: AppProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};