claude-memory-hub 0.10.0 → 0.11.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/CHANGELOG.md +76 -0
- package/README.md +97 -10
- package/dist/cli.js +151 -9
- package/dist/hooks/post-compact.js +166 -19
- package/dist/hooks/post-tool-use.js +173 -26
- package/dist/hooks/pre-compact.js +166 -19
- package/dist/hooks/session-end.js +197 -46
- package/dist/hooks/user-prompt-submit.js +166 -19
- package/dist/index.js +136 -29
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,82 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## [0.11.0] - 2026-04-03
|
|
9
|
+
|
|
10
|
+
Privacy-first memory, smarter search, and slash commands. Three features the community asked for most.
|
|
11
|
+
|
|
12
|
+
### New Feature: Privacy Protection (3-layer)
|
|
13
|
+
|
|
14
|
+
- **`<private>` tag stripping** — wrap sensitive content in `<private>API_KEY=sk-xxx</private>` and it's replaced with `[REDACTED]` before reaching the database. Works across all capture points: entity extraction, observations, user prompts, transcript parsing
|
|
15
|
+
- **Auto secret detection** — built-in regex patterns catch API keys (`sk-`, `ghp_`, `gho_`, `AKIA`), Bearer tokens, passwords, private key blocks, and hex/base64 secrets. Keeps first 12 chars for identification, redacts the rest
|
|
16
|
+
- **Path-based filtering** — files matching `.env`, `.env.*`, `*.pem`, `*.key`, `*.p12`, `credentials.*`, `**/secrets/**`, `**/private/**` are completely excluded from entity tracking. No file_read/file_modified entities created for these paths
|
|
17
|
+
- **Custom configuration** — create `~/.claude-memory-hub/privacy.json` to add your own ignored paths and regex patterns. Custom rules are added to defaults, not replacing them
|
|
18
|
+
- **New file: `src/capture/privacy-filter.ts`** — self-contained privacy engine with `sanitize()` and `isIgnoredPath()` APIs. Called at every capture point. <1ms overhead (regex-only, no I/O)
|
|
19
|
+
|
|
20
|
+
#### Files changed
|
|
21
|
+
|
|
22
|
+
| File | Change |
|
|
23
|
+
|------|--------|
|
|
24
|
+
| `src/capture/privacy-filter.ts` | **New** — 3-layer privacy engine (230 LOC) |
|
|
25
|
+
| `src/capture/entity-extractor.ts` | `isIgnoredPath()` on file entities + `sanitize()` on all values/context |
|
|
26
|
+
| `src/capture/observation-extractor.ts` | `sanitize()` input before heuristic matching |
|
|
27
|
+
| `src/capture/hook-handler.ts` | `sanitize()` user prompts before saving to messages table |
|
|
28
|
+
| `src/capture/transcript-parser.ts` | `sanitize()` all messages before returning |
|
|
29
|
+
|
|
30
|
+
### New Feature: Enhanced Semantic Search
|
|
31
|
+
|
|
32
|
+
- **Code-aware tokenizer** — TF-IDF tokenizer now splits camelCase (`getUserName` → `get`, `user`, `name`), snake_case (`user_auth_service` → `user`, `auth`, `service` + full compound), and file paths (`/src/hooks/auth.ts` → `src`, `hooks`, `auth`, `ts`). Dramatically improves search for code-heavy memory content
|
|
33
|
+
- **Expanded stop words (100+)** — added code keywords (`const`, `let`, `var`, `function`, `return`, `class`, `import`, `export`, `async`, `await`, etc.) and CLI noise words (`file`, `line`, `error`, `warning`, `info`, `debug`, `log`). Reduces false matches on high-frequency, low-signal terms
|
|
34
|
+
- **Recency decay** — search results from recent sessions are boosted: <7 days = 1.5x, <30 days = 1.2x, 30-90 days = 1.0x, >90 days = 0.8x. Yesterday's work ranks higher than last quarter's
|
|
35
|
+
- **RRF multi-source fusion** — results found by 2+ search engines (FTS5, TF-IDF, semantic) get a boost: 2 engines = 1.2x, 3 engines = 1.4x. Cross-validated results are more likely relevant
|
|
36
|
+
- **Score combination** — deduplication now properly combines scores across engines instead of just keeping max. RRF + recency + multi-source = significantly better ranking
|
|
37
|
+
|
|
38
|
+
#### Files changed
|
|
39
|
+
|
|
40
|
+
| File | Change |
|
|
41
|
+
|------|--------|
|
|
42
|
+
| `src/search/vector-search.ts` | Code-aware tokenizer, 100+ stop words, `tokenize()` now exported |
|
|
43
|
+
| `src/search/search-workflow.ts` | RRF fusion, recency decay, multi-source boost in `searchIndex()` |
|
|
44
|
+
|
|
45
|
+
### New Feature: Slash Commands
|
|
46
|
+
|
|
47
|
+
- **`/mem-search <query>`** — 3-layer progressive memory search. Guides Claude through the index → timeline → fetch workflow automatically
|
|
48
|
+
- **`/mem-status [project]`** — runs health check + token budget analysis + current session activity in one command
|
|
49
|
+
- **`/mem-save <note>`** — saves an important decision or finding to persistent memory via `memory_store`
|
|
50
|
+
- **Auto-install** — commands are copied to `~/.claude/commands/` during `bunx claude-memory-hub install` and removed on `uninstall`
|
|
51
|
+
- **Improved MCP tool descriptions** — all 10 tool descriptions rewritten with AUTO-USE hints, workflow guidance, and clearer parameter docs. `memory_recall` and `memory_entities` now suggest proactive usage
|
|
52
|
+
|
|
53
|
+
#### Files changed
|
|
54
|
+
|
|
55
|
+
| File | Change |
|
|
56
|
+
|------|--------|
|
|
57
|
+
| `commands/mem-search.md` | **New** — `/mem-search` slash command |
|
|
58
|
+
| `commands/mem-status.md` | **New** — `/mem-status` slash command |
|
|
59
|
+
| `commands/mem-save.md` | **New** — `/mem-save` slash command |
|
|
60
|
+
| `src/cli/main.ts` | `installCommands()` + `uninstallCommands()` + install output updated |
|
|
61
|
+
| `src/mcp/tool-definitions.ts` | All 10 tool descriptions rewritten with AUTO-USE and workflow hints |
|
|
62
|
+
|
|
63
|
+
### Before vs After
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Before (0.10.x):
|
|
67
|
+
Privacy: None — API keys, tokens, passwords stored in plain text
|
|
68
|
+
Search: "getUserName" only matches exact term; 3-month-old results rank same as today's
|
|
69
|
+
Commands: None — must know MCP tool names and call manually
|
|
70
|
+
|
|
71
|
+
After (0.11.0):
|
|
72
|
+
Privacy: <private> tags + auto-detect sk-/ghp_/Bearer/AKIA + .env/.pem excluded
|
|
73
|
+
Search: "getUserName" matches "get", "user", "name"; today's work ranks 1.5x higher
|
|
74
|
+
Commands: /mem-search, /mem-status, /mem-save — Claude knows the workflow
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Documentation
|
|
78
|
+
|
|
79
|
+
- **README.md** — added Privacy Protection section, Slash Commands section, updated comparison table (4 new rows), updated Data & Privacy section, updated Version History
|
|
80
|
+
- **CLAUDE.md** — added `privacy-filter.ts` to project structure, updated search descriptions, added 4 new key patterns
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
8
84
|
## [0.10.0] - 2026-04-03
|
|
9
85
|
|
|
10
86
|
Full conversation capture — memory-hub now remembers what you said AND what Claude said.
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<a href="https://github.com/TranHoaiHung/claude-memory-hub/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/claude-memory-hub.svg" alt="license" /></a>
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
|
-
Zero API key. Zero Python. Zero config. One install command.
|
|
16
|
+
Zero API key. Zero Python. Zero config. One install command. Privacy-first.
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -28,7 +28,9 @@ What makes it different? **The Compact Interceptor** — something no other memo
|
|
|
28
28
|
But it doesn't stop there:
|
|
29
29
|
- **Full conversation capture** — every user prompt + assistant response saved via transcript parsing
|
|
30
30
|
- **Cross-session memory** — past work auto-injected when you start a new session
|
|
31
|
-
- **3-engine hybrid search** — FTS5 + TF-IDF + semantic embeddings
|
|
31
|
+
- **3-engine hybrid search** — FTS5 + TF-IDF + semantic embeddings with recency-aware ranking
|
|
32
|
+
- **Privacy-first** — `<private>` tags, auto secret detection, path-based filtering
|
|
33
|
+
- **Slash commands** — `/mem-search`, `/mem-status`, `/mem-save` built-in
|
|
32
34
|
- **Proactive retrieval** — detects topic shifts mid-session, injects relevant context automatically
|
|
33
35
|
- **100+ unit tests**, batch queue (75ms→3ms), JSONL export/import, browser UI
|
|
34
36
|
- **Multi-agent ready** — subagents share memory for free via MCP
|
|
@@ -64,6 +66,10 @@ Search: Keyword-only, no semantic ranking
|
|
|
64
66
|
| Cross-session memory | -- | Yes | **Yes** |
|
|
65
67
|
| Full conversation capture (user+assistant) | -- | -- | **Yes** |
|
|
66
68
|
| Conversation search (FTS5) | -- | -- | **Yes** |
|
|
69
|
+
| Privacy filtering (`<private>` tags + secret detection) | -- | Partial | **Yes** |
|
|
70
|
+
| Slash commands (`/mem-search`, `/mem-status`, `/mem-save`) | -- | Yes | **Yes** |
|
|
71
|
+
| Code-aware search (camelCase, snake_case, paths) | -- | -- | **Yes** |
|
|
72
|
+
| Recency-aware ranking (recent sessions boosted) | -- | -- | **Yes** |
|
|
67
73
|
| Influence what compact preserves | -- | -- | **Yes** |
|
|
68
74
|
| Save compact output to L3 | -- | -- | **Yes** |
|
|
69
75
|
| Hybrid search (FTS5 + TF-IDF + semantic) | -- | Partial | **Yes** |
|
|
@@ -158,7 +164,7 @@ memory-hub search: query → Layer 1 (index) → ~50 tokens/result
|
|
|
158
164
|
Token savings: ~80-90% vs. full context
|
|
159
165
|
```
|
|
160
166
|
|
|
161
|
-
Hybrid ranking: FTS5 BM25 (keyword) + TF-IDF (term frequency) + semantic cosine similarity (384-dim embeddings). "debugging tips" matches "error fixing" even without shared keywords.
|
|
167
|
+
Hybrid ranking: FTS5 BM25 (keyword) + TF-IDF (term frequency) + semantic cosine similarity (384-dim embeddings). Code-aware tokenizer splits camelCase, snake_case, and file paths into meaningful tokens. Recency decay boosts recent sessions (7d=1.5x, 30d=1.2x, >90d=0.8x). Multi-source boost rewards results found by 2+ engines. "debugging tips" matches "error fixing" even without shared keywords.
|
|
162
168
|
|
|
163
169
|
### Layer 5 — Resource Intelligence
|
|
164
170
|
|
|
@@ -266,6 +272,80 @@ User prompt contains "remember that we use TypeScript strict"
|
|
|
266
272
|
|
|
267
273
|
---
|
|
268
274
|
|
|
275
|
+
## Privacy Protection
|
|
276
|
+
|
|
277
|
+
3-layer privacy system — sensitive data never reaches the database.
|
|
278
|
+
|
|
279
|
+
### Layer 1: `<private>` Tags
|
|
280
|
+
|
|
281
|
+
Wrap sensitive content in `<private>` tags — stripped before storage:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
<private>API_KEY=sk-abc123def456</private>
|
|
285
|
+
→ stored as: [REDACTED]
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Layer 2: Auto Secret Detection
|
|
289
|
+
|
|
290
|
+
Built-in patterns catch common secrets automatically:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
sk-proj-abc123... → sk-proj-abc1[REDACTED]
|
|
294
|
+
Bearer eyJhbGci... → Bearer eyJhb[REDACTED]
|
|
295
|
+
password: "hunter2" → password: "h[REDACTED]
|
|
296
|
+
AKIAIOSFODNN7... → AKIAIOSFODNN[REDACTED]
|
|
297
|
+
-----BEGIN PRIVATE KEY---- → [REDACTED]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Detected: API keys (`sk-`, `ghp_`, `gho_`, `AKIA`), Bearer tokens, passwords, private keys, hex/base64 secrets.
|
|
301
|
+
|
|
302
|
+
### Layer 3: Path Filtering
|
|
303
|
+
|
|
304
|
+
Sensitive files are completely excluded from entity tracking:
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
.env, .env.*, *.pem, *.key, *.p12
|
|
308
|
+
credentials.*, **/secrets/**, **/private/**
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Custom Configuration
|
|
312
|
+
|
|
313
|
+
Create `~/.claude-memory-hub/privacy.json` to extend:
|
|
314
|
+
|
|
315
|
+
```json
|
|
316
|
+
{
|
|
317
|
+
"tag_stripping": true,
|
|
318
|
+
"auto_detect_secrets": true,
|
|
319
|
+
"ignored_paths": ["my-secrets.yaml", "**/vault/**"],
|
|
320
|
+
"custom_patterns": ["INTERNAL_TOKEN_[A-Z0-9]{20,}"]
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Custom paths and patterns are **added** to defaults, not replacing them.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Slash Commands
|
|
329
|
+
|
|
330
|
+
Installed automatically with `bunx claude-memory-hub install`. Available as `/mem-*` in Claude Code.
|
|
331
|
+
|
|
332
|
+
| Command | What it does |
|
|
333
|
+
|---------|-------------|
|
|
334
|
+
| `/mem-search <query>` | 3-layer progressive search — finds past sessions by topic, file, or keyword |
|
|
335
|
+
| `/mem-status [project]` | Health check + token budget analysis + current session activity |
|
|
336
|
+
| `/mem-save <note>` | Save an important decision or finding to persistent memory |
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
# Examples
|
|
340
|
+
/mem-search auth login bug
|
|
341
|
+
/mem-status claude-memory-hub
|
|
342
|
+
/mem-save Decided to use JWT refresh tokens with 15min expiry
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Commands are copied to `~/.claude/commands/` during install and removed on uninstall.
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
269
349
|
## Install
|
|
270
350
|
|
|
271
351
|
### From npm (recommended)
|
|
@@ -274,7 +354,7 @@ User prompt contains "remember that we use TypeScript strict"
|
|
|
274
354
|
bunx claude-memory-hub install
|
|
275
355
|
```
|
|
276
356
|
|
|
277
|
-
One command. Registers MCP server + 5 hooks globally. Works on CLI, VS Code, JetBrains.
|
|
357
|
+
One command. Registers MCP server + 5 hooks + 3 slash commands globally. Works on CLI, VS Code, JetBrains.
|
|
278
358
|
|
|
279
359
|
**Coming from claude-mem?** The installer auto-detects `~/.claude-mem/claude-mem.db` and migrates your data automatically.
|
|
280
360
|
|
|
@@ -318,11 +398,11 @@ Claude can call these tools directly during conversation:
|
|
|
318
398
|
|
|
319
399
|
| Tool | What it does | When to use |
|
|
320
400
|
|------|-------------|-------------|
|
|
321
|
-
| `memory_recall` | FTS5 search past sessions (
|
|
322
|
-
| `memory_entities` | Find all sessions that touched a file | Before editing
|
|
323
|
-
| `memory_session_notes` | Current session activity (L1 cache) | Mid-session
|
|
324
|
-
| `memory_store` |
|
|
325
|
-
| `memory_context_budget` |
|
|
401
|
+
| `memory_recall` | FTS5 + semantic search past sessions (AUTO-USE) | Starting any task — proactively checks for prior work |
|
|
402
|
+
| `memory_entities` | Find all sessions that touched a file (AUTO-USE) | Before editing any file — understand its history |
|
|
403
|
+
| `memory_session_notes` | Current session activity (L1 cache) | Mid-session review of files, decisions, errors |
|
|
404
|
+
| `memory_store` | Save a note/decision to persistent memory | Architectural decisions, key findings, workarounds |
|
|
405
|
+
| `memory_context_budget` | Token overhead analysis + recommendations | When sessions feel slow or context seems bloated |
|
|
326
406
|
|
|
327
407
|
### 3-Layer Search
|
|
328
408
|
|
|
@@ -439,6 +519,7 @@ Migration is idempotent — safe to run multiple times with zero duplicates.
|
|
|
439
519
|
| **v0.9.5** | Stable install path — hooks no longer break after reboot or bunx cache cleanup |
|
|
440
520
|
| **v0.9.6** | Agent/Skill result capture, higher summary limits, IDE tag stripping, PostCompact cap, broader observation patterns (20+) |
|
|
441
521
|
| **v0.10.0** | **Full conversation capture** — all user prompts + assistant responses via transcript parsing, `messages` table with FTS5, `memory_conversation` MCP tool, conversation-enriched summaries |
|
|
522
|
+
| **v0.11.0** | **Privacy + Search + Commands** — 3-layer privacy filtering (`<private>` tags, auto secret detection, path filtering), code-aware tokenizer (camelCase/snake_case/path splitting), recency-aware ranking (7d/30d/90d decay), RRF multi-source fusion, slash commands (`/mem-search`, `/mem-status`, `/mem-save`), improved MCP tool descriptions with AUTO-USE hints |
|
|
442
523
|
|
|
443
524
|
See [CHANGELOG.md](CHANGELOG.md) for full details.
|
|
444
525
|
|
|
@@ -468,11 +549,12 @@ bun:sqlite Built-in, zero install
|
|
|
468
549
|
|
|
469
550
|
## Data & Privacy
|
|
470
551
|
|
|
471
|
-
All data stored locally at `~/.claude-memory-hub/`.
|
|
552
|
+
All data stored locally at `~/.claude-memory-hub/`. **Privacy-first by design.**
|
|
472
553
|
|
|
473
554
|
```
|
|
474
555
|
~/.claude-memory-hub/
|
|
475
556
|
├── memory.db # SQLite database (all memory data)
|
|
557
|
+
├── privacy.json # Privacy config (optional — custom patterns/paths)
|
|
476
558
|
├── batch/
|
|
477
559
|
│ └── queue.jsonl # PostToolUse batch queue (auto-flushed)
|
|
478
560
|
├── proactive/
|
|
@@ -481,6 +563,11 @@ All data stored locally at `~/.claude-memory-hub/`.
|
|
|
481
563
|
└── memory-hub.log # Structured JSON logs (auto-rotated at 5MB)
|
|
482
564
|
```
|
|
483
565
|
|
|
566
|
+
**3-layer privacy protection** (see [Privacy Protection](#privacy-protection)):
|
|
567
|
+
- `<private>` tags stripped before storage
|
|
568
|
+
- API keys, tokens, passwords auto-detected and redacted
|
|
569
|
+
- Sensitive file paths (`.env`, `*.pem`, `*.key`) excluded from tracking
|
|
570
|
+
|
|
484
571
|
No cloud. No telemetry. No network calls. Your memory stays on your machine.
|
|
485
572
|
|
|
486
573
|
---
|
package/dist/cli.js
CHANGED
|
@@ -852,12 +852,42 @@ var init_semantic_search = __esm(() => {
|
|
|
852
852
|
var exports_vector_search = {};
|
|
853
853
|
__export(exports_vector_search, {
|
|
854
854
|
vectorSearch: () => vectorSearch,
|
|
855
|
+
tokenize: () => tokenize,
|
|
855
856
|
reindexAll: () => reindexAll,
|
|
856
857
|
rebuildIDF: () => rebuildIDF,
|
|
857
858
|
indexDocument: () => indexDocument
|
|
858
859
|
});
|
|
859
860
|
function tokenize(text) {
|
|
860
|
-
|
|
861
|
+
const tokens = [];
|
|
862
|
+
const camelSplit = text.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
|
|
863
|
+
const words = camelSplit.toLowerCase().replace(/[^a-z0-9_./\-]/g, " ").split(/\s+/).filter(Boolean);
|
|
864
|
+
for (const word of words) {
|
|
865
|
+
if (word.includes("/") && word.length > 3) {
|
|
866
|
+
const parts = word.split("/").filter((p) => p.length > 1);
|
|
867
|
+
for (const part of parts) {
|
|
868
|
+
const subparts = part.split(".").filter((s) => s.length > 1);
|
|
869
|
+
for (const sp of subparts) {
|
|
870
|
+
if (!STOP_WORDS.has(sp))
|
|
871
|
+
tokens.push(sp);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
continue;
|
|
875
|
+
}
|
|
876
|
+
if (word.includes("_") && word.length > 3) {
|
|
877
|
+
const parts = word.split("_").filter((p) => p.length > 1);
|
|
878
|
+
for (const part of parts) {
|
|
879
|
+
if (!STOP_WORDS.has(part))
|
|
880
|
+
tokens.push(part);
|
|
881
|
+
}
|
|
882
|
+
if (!STOP_WORDS.has(word))
|
|
883
|
+
tokens.push(word);
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
if (word.length > 1 && !STOP_WORDS.has(word)) {
|
|
887
|
+
tokens.push(word);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return tokens;
|
|
861
891
|
}
|
|
862
892
|
function computeTF(tokens) {
|
|
863
893
|
const freq = new Map;
|
|
@@ -1056,7 +1086,63 @@ var init_vector_search = __esm(() => {
|
|
|
1056
1086
|
"her",
|
|
1057
1087
|
"they",
|
|
1058
1088
|
"them",
|
|
1059
|
-
"their"
|
|
1089
|
+
"their",
|
|
1090
|
+
"const",
|
|
1091
|
+
"let",
|
|
1092
|
+
"var",
|
|
1093
|
+
"function",
|
|
1094
|
+
"return",
|
|
1095
|
+
"class",
|
|
1096
|
+
"new",
|
|
1097
|
+
"true",
|
|
1098
|
+
"false",
|
|
1099
|
+
"null",
|
|
1100
|
+
"undefined",
|
|
1101
|
+
"void",
|
|
1102
|
+
"type",
|
|
1103
|
+
"interface",
|
|
1104
|
+
"export",
|
|
1105
|
+
"import",
|
|
1106
|
+
"from",
|
|
1107
|
+
"default",
|
|
1108
|
+
"async",
|
|
1109
|
+
"await",
|
|
1110
|
+
"try",
|
|
1111
|
+
"catch",
|
|
1112
|
+
"throw",
|
|
1113
|
+
"if",
|
|
1114
|
+
"else",
|
|
1115
|
+
"for",
|
|
1116
|
+
"while",
|
|
1117
|
+
"switch",
|
|
1118
|
+
"case",
|
|
1119
|
+
"break",
|
|
1120
|
+
"continue",
|
|
1121
|
+
"public",
|
|
1122
|
+
"private",
|
|
1123
|
+
"protected",
|
|
1124
|
+
"static",
|
|
1125
|
+
"readonly",
|
|
1126
|
+
"extends",
|
|
1127
|
+
"implements",
|
|
1128
|
+
"super",
|
|
1129
|
+
"this",
|
|
1130
|
+
"typeof",
|
|
1131
|
+
"instanceof",
|
|
1132
|
+
"file",
|
|
1133
|
+
"line",
|
|
1134
|
+
"error",
|
|
1135
|
+
"warning",
|
|
1136
|
+
"info",
|
|
1137
|
+
"debug",
|
|
1138
|
+
"log",
|
|
1139
|
+
"true",
|
|
1140
|
+
"false",
|
|
1141
|
+
"yes",
|
|
1142
|
+
"no",
|
|
1143
|
+
"ok",
|
|
1144
|
+
"done",
|
|
1145
|
+
"success"
|
|
1060
1146
|
]);
|
|
1061
1147
|
});
|
|
1062
1148
|
|
|
@@ -1127,10 +1213,32 @@ async function searchIndex(query, opts = {}, db) {
|
|
|
1127
1213
|
for (const r of filtered) {
|
|
1128
1214
|
const key = `${r.type}:${r.id}`;
|
|
1129
1215
|
const existing = deduped.get(key);
|
|
1130
|
-
if (!existing
|
|
1131
|
-
deduped.set(key, r);
|
|
1216
|
+
if (!existing) {
|
|
1217
|
+
deduped.set(key, { ...r, sourceCount: 1 });
|
|
1218
|
+
} else {
|
|
1219
|
+
existing.score = Math.max(existing.score, r.score);
|
|
1220
|
+
existing.sourceCount++;
|
|
1221
|
+
}
|
|
1132
1222
|
}
|
|
1133
|
-
const
|
|
1223
|
+
const now = Date.now();
|
|
1224
|
+
const merged = [...deduped.values()].map((r) => {
|
|
1225
|
+
let score = r.score;
|
|
1226
|
+
const ageMs = now - r.created_at;
|
|
1227
|
+
const ageDays = ageMs / (1000 * 60 * 60 * 24);
|
|
1228
|
+
if (ageDays < 7)
|
|
1229
|
+
score *= 1.5;
|
|
1230
|
+
else if (ageDays < 30)
|
|
1231
|
+
score *= 1.2;
|
|
1232
|
+
else if (ageDays < 90)
|
|
1233
|
+
score *= 1;
|
|
1234
|
+
else
|
|
1235
|
+
score *= 0.8;
|
|
1236
|
+
if (r.sourceCount >= 3)
|
|
1237
|
+
score *= 1.4;
|
|
1238
|
+
else if (r.sourceCount >= 2)
|
|
1239
|
+
score *= 1.2;
|
|
1240
|
+
return { ...r, score };
|
|
1241
|
+
});
|
|
1134
1242
|
merged.sort((a, b) => b.score - a.score);
|
|
1135
1243
|
return merged.slice(0, limit);
|
|
1136
1244
|
}
|
|
@@ -2009,6 +2117,7 @@ function buildSummaryText(s) {
|
|
|
2009
2117
|
import { spawnSync } from "child_process";
|
|
2010
2118
|
var CLAUDE_DIR = join5(homedir5(), ".claude");
|
|
2011
2119
|
var SETTINGS_PATH = join5(CLAUDE_DIR, "settings.json");
|
|
2120
|
+
var COMMANDS_DIR = join5(CLAUDE_DIR, "commands");
|
|
2012
2121
|
var PKG_DIR = resolve(dirname(import.meta.dir));
|
|
2013
2122
|
var STABLE_DIR = join5(homedir5(), ".claude-memory-hub");
|
|
2014
2123
|
function shellPath(p) {
|
|
@@ -2079,6 +2188,32 @@ function saveSettings(settings) {
|
|
|
2079
2188
|
writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + `
|
|
2080
2189
|
`);
|
|
2081
2190
|
}
|
|
2191
|
+
function installCommands() {
|
|
2192
|
+
const srcCommands = join5(PKG_DIR, "commands");
|
|
2193
|
+
if (!existsSync5(srcCommands))
|
|
2194
|
+
return 0;
|
|
2195
|
+
mkdirSync3(COMMANDS_DIR, { recursive: true });
|
|
2196
|
+
let count = 0;
|
|
2197
|
+
for (const file of readdirSync(srcCommands)) {
|
|
2198
|
+
if (!file.endsWith(".md"))
|
|
2199
|
+
continue;
|
|
2200
|
+
const src = join5(srcCommands, file);
|
|
2201
|
+
const dest = join5(COMMANDS_DIR, file);
|
|
2202
|
+
writeFileSync(dest, readFileSync(src));
|
|
2203
|
+
count++;
|
|
2204
|
+
}
|
|
2205
|
+
return count;
|
|
2206
|
+
}
|
|
2207
|
+
function uninstallCommands() {
|
|
2208
|
+
const memCommands = ["mem-search.md", "mem-status.md", "mem-save.md"];
|
|
2209
|
+
for (const file of memCommands) {
|
|
2210
|
+
const p = join5(COMMANDS_DIR, file);
|
|
2211
|
+
try {
|
|
2212
|
+
if (existsSync5(p))
|
|
2213
|
+
__require("fs").unlinkSync(p);
|
|
2214
|
+
} catch {}
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2082
2217
|
function install() {
|
|
2083
2218
|
console.log(`claude-memory-hub \u2014 install
|
|
2084
2219
|
`);
|
|
@@ -2142,13 +2277,18 @@ function install() {
|
|
|
2142
2277
|
3. Data directory exists: ${dataDir}`);
|
|
2143
2278
|
}
|
|
2144
2279
|
console.log(`
|
|
2280
|
+
4. Installing slash commands...`);
|
|
2281
|
+
const cmdCount = installCommands();
|
|
2282
|
+
console.log(` ${cmdCount} command(s) installed to ~/.claude/commands/`);
|
|
2283
|
+
console.log(`
|
|
2145
2284
|
========================================`);
|
|
2146
2285
|
console.log("Installation complete!");
|
|
2147
2286
|
console.log("");
|
|
2148
|
-
console.log(" MCP:
|
|
2149
|
-
console.log(" Hooks:
|
|
2150
|
-
console.log("
|
|
2151
|
-
console.log("
|
|
2287
|
+
console.log(" MCP: claude-memory-hub");
|
|
2288
|
+
console.log(" Hooks: PostToolUse, UserPromptSubmit, PreCompact, PostCompact, Stop");
|
|
2289
|
+
console.log(" Commands: /mem-search, /mem-status, /mem-save");
|
|
2290
|
+
console.log(" Data: ~/.claude-memory-hub/memory.db");
|
|
2291
|
+
console.log(" Key: not needed");
|
|
2152
2292
|
console.log("");
|
|
2153
2293
|
console.log(" Restart Claude Code to activate.");
|
|
2154
2294
|
console.log("========================================");
|
|
@@ -2171,6 +2311,8 @@ function install() {
|
|
|
2171
2311
|
function uninstall() {
|
|
2172
2312
|
console.log(`claude-memory-hub \u2014 uninstall
|
|
2173
2313
|
`);
|
|
2314
|
+
uninstallCommands();
|
|
2315
|
+
console.log("Removed slash commands from ~/.claude/commands/");
|
|
2174
2316
|
spawnSync("claude", ["mcp", "remove", "claude-memory-hub", "-s", "user"], {
|
|
2175
2317
|
stdio: "inherit"
|
|
2176
2318
|
});
|