hmem-mcp 2.0.3 → 2.2.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.
@@ -0,0 +1,113 @@
1
+ ---
2
+ name: hmem-self-curate
3
+ description: Curate your own memory. Systematically review entries — mark obsolete, irrelevant, or favorite. Run periodically to keep memory clean.
4
+ ---
5
+
6
+ # Self-Curation: Review Your Own Memory
7
+
8
+ You are curating **your own** memory — not another agent's. You know best which entries are still relevant. Use your regular tools: `read_memory`, `update_memory`, `write_memory`.
9
+
10
+ ---
11
+
12
+ ## Step 1 — Load overview
13
+
14
+ ```
15
+ read_memory(titles_only=true)
16
+ ```
17
+
18
+ This gives you every entry as a compact line: `ID date [flags] title`. Scan the full list before acting.
19
+
20
+ ---
21
+
22
+ ## Step 2 — Identify candidates
23
+
24
+ Work through the list prefix by prefix. For each entry, decide:
25
+
26
+ | Decision | Action |
27
+ |----------|--------|
28
+ | Still valid and useful | Skip (no action needed) |
29
+ | Important reference I need every session | `update_memory(id="X", content="...", favorite=true)` |
30
+ | Outdated — a better entry exists | Mark obsolete (see Step 3) |
31
+ | Just noise — not wrong, but irrelevant | `update_memory(id="X", content="...", irrelevant=true)` |
32
+ | L1 wording is vague or misleading | `update_memory(id="X", content="Better wording")` |
33
+ | Sub-node has valuable reference info | `update_memory(id="X.N", content="...", favorite=true)` |
34
+
35
+ **Drill into entries** before judging: `read_memory(id="L0042")` to see L2 children. An entry with a weak L1 may have valuable detail underneath.
36
+
37
+ ---
38
+
39
+ ## Step 3 — Marking obsolete
40
+
41
+ Obsolete requires a correction reference. Two patterns:
42
+
43
+ **Pattern A: Replacement exists already**
44
+ Find the existing entry that supersedes it, then mark:
45
+ ```
46
+ update_memory(id="E0023", content="Wrong approach — see [✓E0076]", obsolete=true)
47
+ ```
48
+
49
+ **Pattern B: No replacement exists yet**
50
+ Write the correction first, then mark:
51
+ ```
52
+ write_memory(prefix="L", content="Correct approach is XYZ\n\tDetails...") # -> L0090
53
+ update_memory(id="L0042", content="Superseded — see [✓L0090]", obsolete=true)
54
+ ```
55
+
56
+ **Pattern C: Just stale, no correction needed**
57
+ If the entry is simply outdated with no replacement (e.g., a task that's done, a project note about a past state), mark it irrelevant instead:
58
+ ```
59
+ update_memory(id="T0005", content="...", irrelevant=true)
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Step 4 — Consolidate duplicates
65
+
66
+ Look for entries that cover the same topic (common with P entries). Merge them:
67
+
68
+ 1. Pick the **keeper** (the more complete one)
69
+ 2. Copy unique info from the duplicate into the keeper:
70
+ ```
71
+ append_memory(id="P0029", content="Session from duplicate entry\n\tDetail carried over")
72
+ ```
73
+ 3. Mark the duplicate irrelevant:
74
+ ```
75
+ update_memory(id="P0031", content="Merged into P0029", irrelevant=true)
76
+ ```
77
+
78
+ You cannot delete entries yourself (only the curator can). Marking irrelevant hides them from bulk reads, which is the same practical effect.
79
+
80
+ ---
81
+
82
+ ## Step 5 — Favorite audit
83
+
84
+ Check your current favorites: look for `[♥]` markers in the title listing.
85
+
86
+ - **Too many favorites?** If more than ~10% of entries are favorites, they lose their purpose. Demote the less important ones: `update_memory(id="X", content="...", favorite=false)`
87
+ - **Missing favorites?** Reference entries you always need (API endpoints, key architecture decisions, frequently-used patterns) should be favorited.
88
+ - **Sub-node favorites:** If a specific L2/L3 detail is the real reference (not the whole entry), favorite the sub-node: `update_memory(id="L0042.2", content="...", favorite=true)`
89
+
90
+ ---
91
+
92
+ ## Guidelines
93
+
94
+ - **Work in batches.** Don't try to curate 100+ entries in one session. Focus on one or two prefixes per run.
95
+ - **Read before marking.** Always `read_memory(id=X)` to see L2 children before marking obsolete/irrelevant. The L1 might be weak but the detail valuable.
96
+ - **Preserve learning value.** Error entries (E) and lessons (L) that describe *why* something failed are valuable even if the bug is fixed. Only mark obsolete if the root cause analysis is wrong.
97
+ - **When in doubt, skip.** You can always curate again later. False irrelevant/obsolete is harder to undo than leaving an entry alone.
98
+ - **Update stale L1 text.** If an entry's summary doesn't match its content anymore, rewrite it. A clear L1 is the most impactful improvement you can make.
99
+
100
+ ---
101
+
102
+ ## Quick reference
103
+
104
+ | Tool | When |
105
+ |------|------|
106
+ | `read_memory(titles_only=true)` | Get full overview |
107
+ | `read_memory(titles_only=true, prefix="L")` | Focus on one category |
108
+ | `read_memory(id="L0042")` | Drill into entry before judging |
109
+ | `update_memory(id, content, favorite=true)` | Mark as always-show reference |
110
+ | `update_memory(id, content, irrelevant=true)` | Hide from bulk reads (noise) |
111
+ | `update_memory(id, content, obsolete=true)` | Mark as wrong (needs [✓ID]) |
112
+ | `append_memory(id, content)` | Merge info from duplicate |
113
+ | `read_memory(show_obsolete=true)` | Review already-obsolete entries |
@@ -138,10 +138,11 @@ Place `hmem.config.json` in your `HMEM_PROJECT_DIR` to customize behavior. All k
138
138
  "maxLnChars": 50000,
139
139
  "maxDepth": 5,
140
140
  "defaultReadLimit": 100,
141
- "recentDepthTiers": [
142
- { "count": 10, "depth": 2 },
143
- { "count": 3, "depth": 3 }
144
- ]
141
+ "bulkReadV2": {
142
+ "topAccessCount": 3,
143
+ "topNewestCount": 5,
144
+ "topObsoleteCount": 3
145
+ }
145
146
  }
146
147
  ```
147
148
 
@@ -149,18 +150,7 @@ Place `hmem.config.json` in your `HMEM_PROJECT_DIR` to customize behavior. All k
149
150
  - `"maxL1Chars"` + `"maxLnChars"`: set endpoints only, intermediate levels interpolated linearly
150
151
  - `"maxCharsPerLevel"`: explicit array `[L1, L2, L3, L4, L5]`
151
152
 
152
- **Recency gradient** (`recentDepthTiers`): controls how deeply children are inlined for recent entries in a default `read_memory()` call.
153
-
154
- Each tier is `{ "count": N, "depth": D }` — the N most recent entries get children inlined up to depth D. The highest applicable depth wins.
155
-
156
- Default behavior:
157
- | Entry position | What you see |
158
- |---|---|
159
- | 0–2 (most recent) | L1 + L2 + L3 |
160
- | 3–9 | L1 + L2 |
161
- | 10+ | L1 only |
162
-
163
- Set to `[]` to disable (L1-only for all entries).
153
+ **Bulk-read tuning** (`bulkReadV2`): controls which entries get expanded (all L2 children shown) in a default `read_memory()` call. Per prefix category: top N newest + top M most-accessed are expanded. Favorites are always expanded.
164
154
 
165
155
  ---
166
156
 
@@ -19,10 +19,14 @@ If the tool `write_memory` is not available:
19
19
  ```
20
20
  write_memory(
21
21
  prefix: "E",
22
- content: "L1 sentence — concise, understandable without context\n\tL2 detail (1 tab)\n\t\tL3 detail (2 tabs)\n\t\t\tL4 raw data (3 tabs — rarely needed)"
22
+ content: "Short Title (~50 chars)\nL1 sentence — concise, understandable without context\n\tL2 detail (1 tab)\n\t\tL3 detail (2 tabs)\n\t\t\tL4 raw data (3 tabs — rarely needed)"
23
23
  )
24
24
  ```
25
25
 
26
+ **Title convention:** The first non-indented line is the **title** (~50 chars, configurable via `maxTitleChars` in `hmem.config.json`) — a short label for navigation, like a chapter title. The second non-indented line is the L1 summary (full sentence). If only one non-indented line is provided, the title is auto-extracted from the first `maxTitleChars` characters.
27
+
28
+ **Child node titles** are always auto-extracted from the first `maxTitleChars` characters of their content (or text before ` — ` if shorter). No explicit title needed for children.
29
+
26
30
  **Indentation:** 1 tab = 1 level. Alternatively: 2 or 4 spaces per level (auto-detected).
27
31
  **Warning:** A tab at the start of any line always means "go one level deeper" — it is structural, not content. If you need to store code or text that contains leading tabs, use spaces instead.
28
32
  **IDs and timestamps** are assigned automatically — never write them yourself.
@@ -109,12 +113,27 @@ write_memory(
109
113
 
110
114
  ---
111
115
 
112
- ## L1 Quality Rule
116
+ ## Title + L1 Quality Rules
117
+
118
+ **Title:** Short navigation label, ~50 chars (configurable via `maxTitleChars`). Think "chapter title in a book".
119
+ - Good: `"hmem.py Performance: Bulk-Queries statt N+1"`, `"Ghost Wakeup Bug in msg-router.ts"`
120
+ - Bad: `"Fixed a bug"`, `"Important lesson"` (too vague)
113
121
 
114
- - **One complete, informative sentence** — ~15–20 tokens
122
+ **L1:** One complete, informative sentence — ~15–20 tokens.
115
123
  - Must be understandable without any context
116
124
  - Not "Fixed a bug" — instead "SQLite connection failed due to wrong path in .mcp.json"
117
125
 
126
+ **With explicit title (recommended):**
127
+ ```
128
+ write_memory(prefix="L", content="hmem.py Performance\nAlle Nodes in 2 Bulk-Queries laden, nicht pro Entry einzeln\n\tload_nodes() pro Entry = N+1 SQLite-Connections")
129
+ ```
130
+
131
+ **Without explicit title (auto-extracted):**
132
+ ```
133
+ write_memory(prefix="E", content="SQLite connection failed due to wrong path in .mcp.json\n\tFix: use absolute path in env var")
134
+ ```
135
+ Title auto-extracted: `"SQLite connection failed due to wrong path in .mc"`
136
+
118
137
  ---
119
138
 
120
139
  ## Company Knowledge (requires AL+ role)
@@ -194,9 +213,9 @@ Use when: you have new context to add without replacing what's there.
194
213
 
195
214
  ---
196
215
 
197
- ## Access Count (Automatic)
216
+ ## Access Count (Automatic + Time-Weighted)
198
217
 
199
- Access counts are managed automatically — every `read_memory` and `append_memory` call bumps the accessed entries. Entries with high access counts get [★] markers and expanded treatment in bulk reads. To explicitly mark an entry as important, use `favorite: true` on `write_memory` or `update_memory`.
218
+ Access counts are managed automatically — every `read_memory` and `append_memory` call bumps the accessed entries. The ranking uses **time-weighted scoring** (`access_count / log2(age_in_days + 2)`) so newer entries with fewer accesses can outrank stale old ones. Entries with the highest weighted scores get `[★]` markers and expanded treatment in bulk reads. To explicitly mark an entry as important, use `favorite: true` on `write_memory` or `update_memory`.
200
219
 
201
220
  ---
202
221
 
@@ -1,128 +0,0 @@
1
- ---
2
- name: save
3
- description: >
4
- End-of-session save routine. Use when the user types /hmem-save or /save or asks to
5
- "save", "save session", or "save progress".
6
- Saves session learnings to memory via write_memory, commits git changes,
7
- then compacts the conversation context.
8
- ---
9
-
10
- # Save Session
11
-
12
- Execute these steps in order. Report results after all complete.
13
-
14
- ## Step 0 — First-time setup check
15
-
16
- Before saving, verify that hmem is ready.
17
-
18
- **Check 1: Is write_memory available?**
19
-
20
- Try calling `write_memory` (or check if the tool exists in your tool list).
21
-
22
- If `write_memory` is NOT available:
23
- - Tell the user: "The hmem MCP server is not connected. Run `npx hmem-mcp init` in your terminal to set it up, then restart your AI tool."
24
- - **STOP. Do not continue.**
25
-
26
- **Check 2: Does a memory file exist?**
27
-
28
- Call `read_memory()`. If it returns entries → memory exists, skip to Step 1.
29
-
30
- If `read_memory()` returns an **empty memory** (no entries at all) for the first time, this is likely a fresh setup. Ask the user:
31
-
32
- > "No memory found yet. Where should hmem store your memories?
33
- > 1) Global — works in any directory (`~/.hmem/`)
34
- > 2) Project-local — only in this directory (current folder)
35
- >
36
- > Recommendation: Global for personal assistants. Project-local for team projects."
37
-
38
- After the user chooses, walk them through the config setup:
39
-
40
- > "Let me set up your `hmem.config.json`. I'll explain each setting — press Enter to accept the recommendation or type a new value."
41
-
42
- Go through these parameters one by one:
43
-
44
- | Parameter | Recommendation | Question to ask |
45
- |-----------|---------------|-----------------|
46
- | `maxL1Chars` | 120 | "How long should memory summaries be? (60–200 characters — shorter loads faster at startup)" |
47
- | `maxDepth` | 5 | "How many detail levels do you want? (2–5 — 5 gives the most flexibility)" |
48
- | `recentDepthTiers` | [{count:10,depth:2},{count:3,depth:3}] | "Auto-expand recent entries? This shows extra detail for your newest memories without extra tool calls. Recommended: yes" |
49
- | `prefixes` | default | "Do you want custom memory categories beyond the defaults (P/L/E/D/M/S/T/N/H/R)? If yes, name them (e.g. R=Research, B=Bookmark). Otherwise press Enter." |
50
-
51
- Write the resulting `hmem.config.json` to the chosen directory.
52
- Tell the user: "Config saved to `<path>/hmem.config.json`. You can adjust settings anytime with `/hmem-config`."
53
-
54
- ## Step 1 — Write Memory
55
-
56
- **IMPORTANT:** You MUST use the `write_memory` MCP tool. NEVER write directly to `.hmem` files via sqlite3 or shell commands — this bypasses WAL journaling, integrity checks, and tree logic, causing corruption or data loss.
57
-
58
- Your L1 memory summaries are already in your context (injected at session start).
59
- **Check them first** — do not re-write anything that already exists.
60
-
61
- Only write what is **new since the last `/save` or session start**:
62
-
63
- | Prefix | When to use |
64
- |--------|-------------|
65
- | `P` | (P)roject progress — work done this session |
66
- | `L` | (L)essons learned applicable beyond this session |
67
- | `E` | (E)rror patterns — root cause + fix |
68
- | `D` | (D)ecisions — architectural or design decisions |
69
-
70
- Quality over quantity. Skip trivial things and anything already captured.
71
-
72
- ### P entries: append to existing, don't duplicate
73
-
74
- Before creating a new P entry, check if an existing P entry covers the **same project or topic**.
75
-
76
- - Scan your L1 summaries (already in context) for a matching P entry.
77
- - If one exists: use `append_memory` to add this session as a new L2 node.
78
- - Keep the new L2 text concise (what was done this session, ~15–20 tokens).
79
- - Add L3 nodes for details.
80
- - If none exists: use `write_memory` to create a new P entry.
81
-
82
- **Goal: one P entry per project, growing over time — not one P entry per session.**
83
-
84
- ```
85
- # Existing entry found → append this session
86
- append_memory(id="P0038", content="Session 02-24: update_memory + append_memory tools (v1.5.0)
87
- update_memory: update text of single node without touching children
88
- append_memory: add child nodes to existing entry, relative indentation
89
- access_count auto-promotion: top-5 most accessed entries get L2 in bulk reads")
90
-
91
- # No existing entry → create new
92
- write_memory(prefix="P", content="New project: authentication service
93
- Implemented JWT flow with refresh token rotation
94
- Session 02-24: initial setup + basic login endpoint")
95
- ```
96
-
97
- ### L / E / D entries: always create new
98
-
99
- For lessons, errors, and decisions — always create a new entry. These are indexed insights, not project logs.
100
-
101
- ```
102
- write_memory(prefix="L", content="Always restart MCP server after recompiling TypeScript
103
- Running process holds the old dist — tool calls return stale results otherwise")
104
-
105
- write_memory(prefix="E", content="write_memory returned HMEM_PROJECT_DIR not set
106
- Cause: relative path in .mcp.json env — must be absolute
107
- Fix: replace with full absolute path, restart AI tool")
108
- ```
109
-
110
- ## Step 2 — Commit & Push
111
-
112
- **IMPORTANT:** Step 1 (write_memory) MUST complete before this step. The `.hmem` file is modified by write_memory — if you push before writing, the memory changes won't be included in the commit.
113
-
114
- If in a git repository:
115
-
116
- ```bash
117
- git add -A
118
- git commit -m "concise imperative summary of this session's changes"
119
- git push
120
- ```
121
-
122
- Skip if there are no changes or no git repo.
123
-
124
- ## Step 3 — Compact (Claude only)
125
-
126
- If you are running on **Claude** (Claude Code, claude.ai): run `/compact` to compress the conversation context. The next interaction starts fresh with your updated memories already loaded.
127
-
128
- If you are running on **Gemini CLI, OpenCode, or another tool**: skip this step — `/compact` is a Claude-specific command.