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,19 @@
1
+ {
2
+ "name": "claude-memory-explorer",
3
+ "version": "0.1.0",
4
+ "description": "Browse, dedupe, lint, and promote your Claude Code auto-memory across every project. Closes the gap anthropics/claude-code#58840 describes.",
5
+ "homepage": "https://github.com/hseinmoussa/claude-memory-explorer",
6
+ "license": "MIT",
7
+ "author": {
8
+ "name": "Hussein Moussa",
9
+ "url": "https://github.com/hseinmoussa"
10
+ },
11
+ "skills": ["./skills/curate-memory"],
12
+ "mcpServers": {
13
+ "memex": {
14
+ "type": "stdio",
15
+ "command": "npx",
16
+ "args": ["-y", "claude-memory-explorer", "mcp"]
17
+ }
18
+ }
19
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hussein Moussa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # memex — claude-memory-explorer
2
+
3
+ [![CI](https://github.com/hseinmoussa/claude-memory-explorer/actions/workflows/ci.yml/badge.svg)](https://github.com/hseinmoussa/claude-memory-explorer/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/claude-memory-explorer.svg)](https://www.npmjs.com/package/claude-memory-explorer)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+
7
+ > Browse, dedupe, lint, and promote your Claude Code auto-memory across every project.
8
+ > Every mutation is journaled and reversible by `memex undo`.
9
+ > Closes the gap [anthropics/claude-code#58840](https://github.com/anthropics/claude-code/issues/58840) describes.
10
+
11
+ Claude Code stores per-project memory at `~/.claude/projects/<slug>/memory/`.
12
+ Every project is a silo. After a few months of real use:
13
+
14
+ - The same `user_*` / `feedback_*` rule ends up in 12 different projects
15
+ - Stale project facts keep loading into every session
16
+ - `user`/`feedback` memories that should live in `~/.claude/CLAUDE.md` don't
17
+ - `MEMORY.md` files quietly cross the documented 200-line / 25KB cutoff and the tail is dropped at load time
18
+ - Malformed YAML in a single memory file (which Claude itself sometimes writes) makes that memory invisible — and there's no warning
19
+
20
+ `memex` is a CLI, TUI, and MCP server that finds and fixes all of that. Install once as a Claude Code plugin and Claude can curate its own memory inside a normal session.
21
+
22
+ ## What's inside
23
+
24
+ ```
25
+ memex list List memories across all projects
26
+ memex doctor One-shot health report (run weekly)
27
+ memex lint Structural problems (CI-friendly)
28
+ memex dedupe Find duplicate memories across projects
29
+ memex merge Collapse a duplicate cluster down to its representative
30
+ memex promote Move a memory (or whole cluster) into ~/.claude/CLAUDE.md
31
+ memex undo Reverse the most recent mutation (any of the above)
32
+ memex tui Interactive three-pane browser
33
+ memex mcp Run as an MCP server for Claude Code plugins
34
+ ```
35
+
36
+ Every mutation goes through a journaled `Plan → applyPlan` layer at
37
+ `~/.claude/.memex/log/`. **Everything is undoable.** `memex undo` reverses
38
+ the most recent plan; a second undo is redo.
39
+
40
+ ## Install
41
+
42
+ ### As a Claude Code plugin (recommended)
43
+
44
+ ```bash
45
+ /plugin install claude-memory-explorer@community
46
+ ```
47
+
48
+ If the community catalog hasn't synced this plugin yet (sync is ~once
49
+ a day), install directly from this repo instead:
50
+
51
+ ```bash
52
+ /plugin marketplace add hseinmoussa/claude-memory-explorer
53
+ /plugin install claude-memory-explorer
54
+ ```
55
+
56
+ Once installed, ask Claude:
57
+
58
+ > "Clean up my memory."
59
+
60
+ …and the bundled `curate-memory` skill takes over. Claude calls `doctor`,
61
+ shows you the findings, generates Plans for the suggested fixes, asks for
62
+ your OK, then applies them via `apply_plan` (all journaled, all undoable).
63
+
64
+ ### As a standalone CLI
65
+
66
+ ```bash
67
+ npm install -g claude-memory-explorer
68
+
69
+ memex doctor # health snapshot
70
+ memex lint # structural issues
71
+ memex dedupe # cross-project duplicates
72
+ memex tui # interactive browser
73
+ ```
74
+
75
+ Or one-shot via `npx`:
76
+
77
+ ```bash
78
+ npx claude-memory-explorer doctor
79
+ ```
80
+
81
+ ## The killer demo
82
+
83
+ Three projects, same user-preference memory written into each:
84
+
85
+ ```
86
+ ~/.claude/projects/-Users-foo-Desktop-vida/memory/user_terse.md
87
+ ~/.claude/projects/-Users-foo-Desktop-app/memory/user_terse.md
88
+ ~/.claude/projects/-Users-foo-Desktop-bot/memory/user_terse.md
89
+ ```
90
+
91
+ `memex dedupe` finds the cluster and flags it as a promote-to-global candidate:
92
+
93
+ ```
94
+ c1 type=user count=3 distinctProjects=3 [promote-to-global candidate]
95
+ ★ -Users-foo-Desktop-bot/user_terse.md
96
+ -Users-foo-Desktop-vida/user_terse.md
97
+ -Users-foo-Desktop-app/user_terse.md
98
+ ```
99
+
100
+ `memex promote --cluster c1 --apply` then:
101
+
102
+ 1. Writes the body into `~/.claude/CLAUDE.md` under a managed marker block:
103
+ ```
104
+ <!-- memex:start:user_terse -->
105
+ ## Be terse
106
+ The user prefers terse, direct answers.
107
+ <!-- memex:end:user_terse -->
108
+ ```
109
+ 2. Deletes the 3 source files
110
+ 3. Cleans the affected `MEMORY.md` indexes (removes pointer lines, leaves unrelated entries intact)
111
+
112
+ Result: one block in `~/.claude/CLAUDE.md` (which Claude loads in every session of every project) replaces three siloed copies.
113
+
114
+ Run `memex undo` and everything is restored byte-for-byte.
115
+
116
+ ## How memex thinks
117
+
118
+ | Concept | Description |
119
+ |---|---|
120
+ | **Memory** | A markdown file at `~/.claude/projects/<slug>/memory/<topic>.md` with YAML frontmatter (`type: user\|feedback\|project\|reference`) |
121
+ | **Index** | `MEMORY.md` in each memory dir. Documented as a list of pointer-style links to topic files; in practice Claude writes inline content too. memex tolerates both. |
122
+ | **Worktree collapse** | `<slug>--claude-worktrees-*` slugs collapse to the base slug when counting distinct projects, so worktrees of one repo don't inflate the duplicate count |
123
+ | **Promotion candidate** | A cluster where `distinctProjects ≥ 3` AND `type ∈ {user, feedback}`. Project- and reference-typed memories stay project-scoped. |
124
+ | **Managed block** | `<!-- memex:start:<slug> -->` / `<!-- memex:end:<slug> -->` markers in `~/.claude/CLAUDE.md`. memex never touches content outside its own markers. |
125
+ | **Plan** | A JSON-serializable list of `write` / `delete` / `ensure-dir` ops. Every mutation builds a plan, then `applyPlan` is the single writer. |
126
+ | **Journal** | `~/.claude/.memex/log/<id>.json`. One entry per applied plan, with inverse ops captured at apply time. `memex undo` walks the journal. |
127
+
128
+ ## MCP server tools
129
+
130
+ When installed as a plugin, the MCP server exposes 11 tools:
131
+
132
+ | Tool | Type | Description |
133
+ |---|---|---|
134
+ | `list_memories` | read | All memories, filterable by type/project |
135
+ | `find_duplicates` | read | Cross-project clusters |
136
+ | `lint` | read | Structural issues |
137
+ | `doctor` | read | Aggregate health report |
138
+ | `journal_list` | read | All journal entries |
139
+ | `journal_latest` | read | Most recent journal entry |
140
+ | `plan_merge` | plan | Build (don't execute) a merge plan |
141
+ | `plan_promote_memory` | plan | Build a single-memory promote plan |
142
+ | `plan_promote_cluster` | plan | Build a whole-cluster promote plan |
143
+ | `apply_plan` | write | Execute a Plan (journaled, undoable) |
144
+ | `undo` | write | Reverse most recent (or specific) plan |
145
+
146
+ Plan tools never execute. Claude must explicitly call `apply_plan` — that's the confirmation surface.
147
+
148
+ ## Compared to existing tools
149
+
150
+ | Tool | Scope | What it does | What it doesn't |
151
+ |---|---|---|---|
152
+ | **memex** | Cross-project | Browse / lint / dedupe / promote / merge / journal-backed undo | (this is the gap) |
153
+ | `consolidate-memory` (Anthropic, built-in) | One project | LLM-driven dedup inside a memory dir | Cross-project view, structural lint, undo |
154
+ | `dream-skill` (community) | One project | Hook-triggered intra-project consolidation | Cross-project promotion |
155
+ | `mem0` / `supermemory` / vector-DB MCP servers | Separate store | Bolt a different memory store onto Claude | Don't touch the native `~/.claude/projects/*/memory/` format |
156
+
157
+ `memex` is the **curator** for the native auto-memory format, not a replacement store.
158
+
159
+ ## Status
160
+
161
+ Pre-1.0. The CLI commands and MCP server are stable and tested
162
+ (191 unit + integration tests across 19 files, real end-to-end
163
+ round-trips for every mutation: scan, lint, dedupe, merge, promote,
164
+ undo, MCP, TUI). Tested on Node 20 and 22 on macOS and Ubuntu
165
+ (see CI badge above). Windows untested.
166
+
167
+ ## Roadmap
168
+
169
+ - [x] v0.1: scan + parse, lint, doctor, dedupe (exact-match), merge, promote, undo, TUI, MCP
170
+ - [ ] v0.2: near-duplicate detection (TF-IDF char-3gram cosine, ~80 lines, zero new deps)
171
+ - [ ] v0.3: scheduled hook (auto-`doctor` weekly), conflict detection
172
+ - [ ] v0.4: semantic dedup (transformers.js + local MiniLM embedding)
173
+ - [ ] v1.0: when MCP TypeScript SDK v2 stabilizes
174
+
175
+ ## License
176
+
177
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1 @@
1
+ export declare function runDedupe(argv: string[]): number;
@@ -0,0 +1,187 @@
1
+ // `memex dedupe` — find duplicate memories across all projects.
2
+ //
3
+ // Read-only. Mutating merge/promote ships in Phase 6.
4
+ //
5
+ // Exit codes:
6
+ // 0 no duplicate clusters found
7
+ // 1 one or more clusters found (so CI users can gate on "no dupes")
8
+ // 2 bad usage
9
+ import { homedir } from "node:os";
10
+ import { relative } from "node:path";
11
+ import { findDuplicates } from "../../core/dedupe.js";
12
+ function parseArgs(argv) {
13
+ const out = {
14
+ format: "human",
15
+ noIntra: false,
16
+ promoteOnly: false,
17
+ verbose: false,
18
+ help: false,
19
+ };
20
+ for (let i = 0; i < argv.length; i++) {
21
+ const a = argv[i];
22
+ switch (a) {
23
+ case "--project":
24
+ out.project = argv[++i];
25
+ break;
26
+ case "--root":
27
+ out.root = argv[++i];
28
+ break;
29
+ case "--json":
30
+ out.format = "json";
31
+ break;
32
+ case "--format": {
33
+ const f = argv[++i];
34
+ if (f !== "human" && f !== "fdupes" && f !== "json") {
35
+ throw new Error(`--format must be human|fdupes|json (got: ${f})`);
36
+ }
37
+ out.format = f;
38
+ break;
39
+ }
40
+ case "--no-intra":
41
+ out.noIntra = true;
42
+ break;
43
+ case "--promote-only":
44
+ out.promoteOnly = true;
45
+ break;
46
+ case "--verbose":
47
+ case "-v":
48
+ out.verbose = true;
49
+ break;
50
+ case "--help":
51
+ case "-h":
52
+ out.help = true;
53
+ break;
54
+ default:
55
+ throw new Error(`unknown flag: ${a}`);
56
+ }
57
+ }
58
+ return out;
59
+ }
60
+ const HELP = `memex dedupe — find duplicate memories across projects
61
+
62
+ Usage:
63
+ memex dedupe [--project SUBSTR] [--format human|fdupes|json] [--json]
64
+ [--no-intra] [--promote-only] [--verbose] [--root PATH]
65
+
66
+ Flags:
67
+ --project SUBSTR Restrict to projects whose slug contains SUBSTR
68
+ --format FORMAT human (default), fdupes (pipe-friendly), json
69
+ --json Shorthand for --format json
70
+ --no-intra Hide clusters whose members are all in one project
71
+ --promote-only Show only clusters flagged as promotion candidates
72
+ (distinctProjects >= 3 AND type in {user, feedback})
73
+ --verbose, -v Surface scan-level warnings on stderr
74
+ --root PATH Override projects root (default: ~/.claude/projects)
75
+
76
+ Exit codes:
77
+ 0 no duplicate clusters found
78
+ 1 one or more clusters found
79
+ 2 bad usage
80
+
81
+ Notes:
82
+ v0.1 finds EXACT body-content matches after normalization (NFC,
83
+ smart-quote fold, lowercase, strip trivial markdown wrappers,
84
+ collapse whitespace). Near-duplicates with paraphrased wording are
85
+ not yet detected — that's planned for v0.2.
86
+ `;
87
+ function shortPath(p) {
88
+ const home = homedir();
89
+ if (p.startsWith(home))
90
+ return "~" + p.slice(home.length);
91
+ try {
92
+ const rel = relative(process.cwd(), p);
93
+ return rel.length < p.length ? rel : p;
94
+ }
95
+ catch {
96
+ return p;
97
+ }
98
+ }
99
+ function filterClusters(clusters, args) {
100
+ let out = clusters;
101
+ if (args.noIntra)
102
+ out = out.filter((c) => !c.intraProject);
103
+ if (args.promoteOnly)
104
+ out = out.filter((c) => c.promotionCandidate);
105
+ return out;
106
+ }
107
+ function renderHuman(result, clusters) {
108
+ const lines = [];
109
+ if (clusters.length === 0) {
110
+ lines.push(`✓ No duplicate clusters across ${result.summary.projectsScanned} projects ` +
111
+ `(${result.summary.memoriesScanned} memories scanned).`);
112
+ return lines.join("\n") + "\n";
113
+ }
114
+ for (const c of clusters) {
115
+ const flags = [
116
+ c.intraProject ? "intra-project" : null,
117
+ c.promotionCandidate ? "promote-to-global candidate" : null,
118
+ ].filter(Boolean);
119
+ const tag = flags.length ? ` [${flags.join(", ")}]` : "";
120
+ lines.push(`${c.id} type=${c.type} count=${c.count} distinctProjects=${c.distinctProjects}${tag}`);
121
+ lines.push(` fingerprint: ${c.fingerprint.slice(0, 12)}…`);
122
+ for (const m of c.members) {
123
+ const star = m.id === c.representative.id ? "★" : " ";
124
+ lines.push(` ${star} ${m.id}`);
125
+ lines.push(` name: ${m.name ?? "(none)"}`);
126
+ lines.push(` ${shortPath(m.filePath)} (${m.bodyBytes}B, ${m.mtime})`);
127
+ }
128
+ lines.push("");
129
+ }
130
+ lines.push(`${clusters.length} cluster(s) shown / ${result.summary.clusterCount} total · ` +
131
+ `${result.summary.duplicateFileCount} duplicate files · ` +
132
+ `${result.summary.wastedBytes}B wasted · ` +
133
+ `${result.summary.promotionCandidates} promote-to-global candidates`);
134
+ if (result.summary.skippedEmptyBodies > 0) {
135
+ lines.push(`(${result.summary.skippedEmptyBodies} empty-body memorie(s) excluded from clustering)`);
136
+ }
137
+ return lines.join("\n") + "\n";
138
+ }
139
+ function renderFdupes(clusters) {
140
+ // Classic fdupes shape: blank line between clusters, no per-cluster header.
141
+ // We do prepend a `#` comment with the cluster id so the output is still
142
+ // human-grepable, then list filePath one per line, representative first.
143
+ const lines = [];
144
+ for (const c of clusters) {
145
+ lines.push(`# ${c.id} type=${c.type} count=${c.count} distinctProjects=${c.distinctProjects}`);
146
+ const rep = c.members.find((m) => m.id === c.representative.id);
147
+ lines.push(rep.filePath);
148
+ for (const m of c.members) {
149
+ if (m.id !== rep.id)
150
+ lines.push(m.filePath);
151
+ }
152
+ lines.push("");
153
+ }
154
+ return lines.join("\n");
155
+ }
156
+ export function runDedupe(argv) {
157
+ let args;
158
+ try {
159
+ args = parseArgs(argv);
160
+ }
161
+ catch (err) {
162
+ process.stderr.write(`memex dedupe: ${err instanceof Error ? err.message : String(err)}\n\n${HELP}`);
163
+ return 2;
164
+ }
165
+ if (args.help) {
166
+ process.stdout.write(HELP);
167
+ return 0;
168
+ }
169
+ const result = findDuplicates({
170
+ projectsRoot: args.root,
171
+ projectFilter: args.project,
172
+ onWarning: args.verbose ? (m) => process.stderr.write(`${m}\n`) : undefined,
173
+ });
174
+ const visible = filterClusters(result.clusters, args);
175
+ if (args.format === "json") {
176
+ process.stdout.write(`${JSON.stringify({ ...result, clusters: visible }, null, 2)}\n`);
177
+ }
178
+ else if (args.format === "fdupes") {
179
+ process.stdout.write(renderFdupes(visible));
180
+ }
181
+ else {
182
+ process.stdout.write(renderHuman(result, visible));
183
+ }
184
+ // Exit code reflects the unfiltered total — filters are presentation only.
185
+ return result.summary.clusterCount > 0 ? 1 : 0;
186
+ }
187
+ //# sourceMappingURL=dedupe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedupe.js","sourceRoot":"","sources":["../../../src/cli/commands/dedupe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function runDoctorCli(argv: string[]): number;
@@ -0,0 +1,177 @@
1
+ // `memex doctor` — human-friendly health report.
2
+ //
3
+ // Exit codes:
4
+ // 0 no errors found
5
+ // 1 one or more error-level issues
6
+ // 2 bad usage
7
+ import { homedir } from "node:os";
8
+ import { relative } from "node:path";
9
+ import { runDoctor } from "../../core/doctor.js";
10
+ function parseArgs(argv) {
11
+ const out = { json: false, verbose: false, help: false };
12
+ for (let i = 0; i < argv.length; i++) {
13
+ const a = argv[i];
14
+ switch (a) {
15
+ case "--project":
16
+ out.project = argv[++i];
17
+ break;
18
+ case "--root":
19
+ out.root = argv[++i];
20
+ break;
21
+ case "--json":
22
+ out.json = true;
23
+ break;
24
+ case "--verbose":
25
+ case "-v":
26
+ out.verbose = true;
27
+ break;
28
+ case "--help":
29
+ case "-h":
30
+ out.help = true;
31
+ break;
32
+ default:
33
+ throw new Error(`unknown flag: ${a}`);
34
+ }
35
+ }
36
+ return out;
37
+ }
38
+ const HELP = `memex doctor — health snapshot of your memory tree
39
+
40
+ Usage:
41
+ memex doctor [--project SUBSTR] [--json] [--verbose] [--root PATH]
42
+
43
+ Flags:
44
+ --project SUBSTR Filter projects whose slug contains SUBSTR
45
+ --json Output JSON instead of formatted report
46
+ --verbose, -v Surface scan-level warnings on stderr
47
+ --root PATH Override projects root (default: ~/.claude/projects)
48
+
49
+ Exit codes:
50
+ 0 no errors
51
+ 1 one or more error issues found
52
+ 2 bad usage
53
+ `;
54
+ const SEV_LABEL = {
55
+ error: "ERROR",
56
+ warn: "WARN ",
57
+ info: "INFO ",
58
+ };
59
+ function shortPath(p) {
60
+ if (!p)
61
+ return "";
62
+ const home = homedir();
63
+ if (p.startsWith(home))
64
+ return "~" + p.slice(home.length);
65
+ try {
66
+ const rel = relative(process.cwd(), p);
67
+ return rel.length < p.length ? rel : p;
68
+ }
69
+ catch {
70
+ return p;
71
+ }
72
+ }
73
+ function formatProjectLine(p) {
74
+ const status = p.worstSeverity === "error"
75
+ ? "✗"
76
+ : p.worstSeverity === "warn"
77
+ ? "!"
78
+ : p.worstSeverity === "info"
79
+ ? "i"
80
+ : "✓";
81
+ const indexInfo = (() => {
82
+ if (!p.hasIndex && p.memoryCount === 0)
83
+ return "no memory";
84
+ if (!p.hasIndex)
85
+ return `${p.memoryCount} files, no index`;
86
+ const sizeStr = p.indexLineCount !== null
87
+ ? `${p.indexLineCount}L/${p.indexByteSize ?? "?"}B`
88
+ : `${p.indexByteSize ?? "?"}B`;
89
+ const tag = p.indexOverCap ? " OVER CAP" : p.indexApproachingCap ? " near cap" : "";
90
+ return `index ${sizeStr}${tag}, ${p.memoryCount} files`;
91
+ })();
92
+ return ` ${status} ${p.slug} (${indexInfo})`;
93
+ }
94
+ function formatReport(report) {
95
+ const { totals, projects, nextActions } = report;
96
+ const lines = [];
97
+ lines.push(`memex doctor — ${report.generatedAt}`);
98
+ lines.push("");
99
+ lines.push(`Scanned ${report.projectsScanned} project(s), parsed ${report.filesScanned} memory file(s).`);
100
+ lines.push("");
101
+ // Issues summary
102
+ lines.push("Issues:");
103
+ lines.push(` ${totals.issuesBySeverity.error} error · ${totals.issuesBySeverity.warn} warn · ${totals.issuesBySeverity.info} info`);
104
+ lines.push("");
105
+ // Memory counts by type
106
+ lines.push("Memories by type:");
107
+ lines.push(` ${totals.memoriesByType.user} user · ${totals.memoriesByType.feedback} feedback · ${totals.memoriesByType.project} project · ${totals.memoriesByType.reference} reference · ${totals.memoriesByType.untyped} untyped`);
108
+ lines.push("");
109
+ // Per-project breakdown
110
+ lines.push("Projects:");
111
+ if (projects.length === 0) {
112
+ lines.push(" (none)");
113
+ }
114
+ else {
115
+ for (const p of projects) {
116
+ lines.push(formatProjectLine(p));
117
+ for (const issue of p.issues) {
118
+ lines.push(` [${SEV_LABEL[issue.severity]}] ${issue.code}`);
119
+ }
120
+ }
121
+ }
122
+ lines.push("");
123
+ // Next actions
124
+ if (nextActions.length > 0) {
125
+ lines.push("Next actions:");
126
+ nextActions.forEach((issue, idx) => {
127
+ lines.push(` ${idx + 1}. [${SEV_LABEL[issue.severity]}] ${issue.code} in ${issue.projectSlug}`);
128
+ lines.push(` ${issue.message}`);
129
+ if (issue.filePath)
130
+ lines.push(` at: ${shortPath(issue.filePath)}`);
131
+ if (issue.hint)
132
+ lines.push(` hint: ${issue.hint}`);
133
+ });
134
+ lines.push("");
135
+ }
136
+ // Footer verdict
137
+ if (totals.issuesBySeverity.error > 0) {
138
+ lines.push(`✗ Action needed: ${totals.issuesBySeverity.error} error issue(s) — memory currently broken.`);
139
+ }
140
+ else if (totals.issuesBySeverity.warn > 0) {
141
+ lines.push(`! ${totals.issuesBySeverity.warn} warn(s) to look at when you have time.`);
142
+ }
143
+ else if (totals.issuesBySeverity.info > 0) {
144
+ lines.push(`✓ No errors or warnings. ${totals.issuesBySeverity.info} info note(s).`);
145
+ }
146
+ else {
147
+ lines.push("✓ All clear.");
148
+ }
149
+ return lines.join("\n") + "\n";
150
+ }
151
+ export function runDoctorCli(argv) {
152
+ let args;
153
+ try {
154
+ args = parseArgs(argv);
155
+ }
156
+ catch (err) {
157
+ process.stderr.write(`memex doctor: ${err instanceof Error ? err.message : String(err)}\n\n${HELP}`);
158
+ return 2;
159
+ }
160
+ if (args.help) {
161
+ process.stdout.write(HELP);
162
+ return 0;
163
+ }
164
+ const report = runDoctor({
165
+ projectsRoot: args.root,
166
+ projectFilter: args.project,
167
+ onWarning: args.verbose ? (m) => process.stderr.write(`${m}\n`) : undefined,
168
+ });
169
+ if (args.json) {
170
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
171
+ }
172
+ else {
173
+ process.stdout.write(formatReport(report));
174
+ }
175
+ return report.totals.issuesBySeverity.error > 0 ? 1 : 0;
176
+ }
177
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function runLint(argv: string[]): number;