claude-recall 0.15.36 → 0.16.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.
@@ -8,7 +8,7 @@ source: claude-recall
8
8
 
9
9
  # Corrections
10
10
 
11
- Auto-generated from 17 memories. Last updated: 2026-03-13.
11
+ Auto-generated from 19 memories. Last updated: 2026-03-16.
12
12
 
13
13
  ## Rules
14
14
 
@@ -22,6 +22,8 @@ Auto-generated from 17 memories. Last updated: 2026-03-13.
22
22
  - CORRECTION: Memory with complex metadata
23
23
  - CORRECTION: Memory with complex metadata
24
24
  - CORRECTION: Memory with complex metadata
25
+ - CORRECTION: Memory with complex metadata
26
+ - CORRECTION: Memory with complex metadata
25
27
  - CORRECTION: Replace expired access token with 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
26
28
  - CORRECTION: use spaces not tabs for indentation
27
29
  - CORRECTION: cited (loaded 5+ times): 19
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "topicId": "corrections",
3
- "sourceHash": "220924ba60fc47a579461ace78f314aff6c7fccd9f2fbb759d4773afaec9628b",
4
- "memoryCount": 17,
5
- "generatedAt": "2026-03-13T14:06:22.452Z",
3
+ "sourceHash": "a0d5ebfdc3b3ad70a29a38511679290d1e2918e5c7c3a4b856c0da65595c81ed",
4
+ "memoryCount": 19,
5
+ "generatedAt": "2026-03-16T10:21:29.906Z",
6
6
  "memoryKeys": [
7
+ "memory_1773656489899_l75d50pxo",
8
+ "memory_1773654956776_7mffm1tp2",
7
9
  "memory_1773410782442_mnfvdml5n",
8
10
  "memory_1773409168373_t4lqoqpiv",
9
11
  "memory_1773220863163_q8k0ewti8",
@@ -8,12 +8,17 @@ source: claude-recall
8
8
 
9
9
  # Failure Lessons
10
10
 
11
- Auto-generated from 18 memories. Last updated: 2026-03-13.
11
+ Auto-generated from 23 memories. Last updated: 2026-03-16.
12
12
 
13
13
  ## Rules
14
14
 
15
15
  - SQLite query syntax error: LIKE clause requires single quotes around string literal, not double quotes
16
16
  - Avoid: Command failed: npm whoami 2>&1 && npm config get registry 2>&1 → Instead: Check command syntax, file paths, and prerequisites before running
17
+ - npm install -g claude-recall@0.15.36 failed with notarget error
18
+ - claude-recall@0.15.36 does not exist on npm registry (ETARGET error)
19
+ - npm install failed: claude-recall@0.15.36 version not found in registry
20
+ - npm package claude-recall@0.15.36 does not exist - version not found in registry
21
+ - npm package claude-recall@0.15.36 not found - version does not exist in registry
17
22
  - Claude-recall MCP Server failed to start with npx claude-recall@latest mcp start
18
23
  - Claude-recall MCP Server failed to start with command: npx -y claude-recall@latest mcp start
19
24
  - Avoid: Command failed: npm run build 2>&1 | tail -3 && npm test 2>&1 → Instead: Check command syntax, file paths, and prerequisites before running
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "topicId": "failure-lessons",
3
- "sourceHash": "eb6e007a4ce3b2b87da9fc0f7affcabd89cf0ac1e90742f1408511b68e947e11",
4
- "memoryCount": 18,
5
- "generatedAt": "2026-03-13T14:06:22.419Z",
3
+ "sourceHash": "6c18a22368601e246196934bc675b7cc11619a20758e5a8067886375b499dd00",
4
+ "memoryCount": 23,
5
+ "generatedAt": "2026-03-16T09:55:56.753Z",
6
6
  "memoryKeys": [
7
7
  "hook_failure_1772637584921_0tj4rrxnt",
8
8
  "hook_failure_non-zero-exit_1773409269877_ful451241",
9
+ "hook_failure_1773410916808_5k1r6zo4u",
10
+ "hook_failure_1773410916789_xtrb8j9nw",
11
+ "hook_failure_1773410910825_rd25wy0tf",
12
+ "hook_failure_1773410885720_u05tuf2dk",
13
+ "hook_failure_1773410874391_kbnfssg62",
9
14
  "hook_failure_1773409616313_gmsfcbuzh",
10
15
  "hook_failure_1773409607268_83ie5yunz",
11
16
  "hook_failure_non-zero-exit_1773068793859_0z0ah0743",
@@ -8,10 +8,20 @@ source: claude-recall
8
8
 
9
9
  # Preferences
10
10
 
11
- Auto-generated from 71 memories. Last updated: 2026-03-13.
11
+ Auto-generated from 81 memories. Last updated: 2026-03-16.
12
12
 
13
13
  ## Rules
14
14
 
15
+ - Session test preference 1773656489963
16
+ - Test preference 1773656489911-2
17
+ - Test preference 1773656489911-1
18
+ - Test preference 1773656489911-0
19
+ - Test memory content
20
+ - Session test preference 1773654956838
21
+ - Test preference 1773654956788-2
22
+ - Test preference 1773654956788-1
23
+ - Test preference 1773654956788-0
24
+ - Test memory content
15
25
  - Session test preference 1773410782522
16
26
  - Test preference 1773410782456-2
17
27
  - Test preference 1773410782456-1
@@ -1,9 +1,19 @@
1
1
  {
2
2
  "topicId": "preferences",
3
- "sourceHash": "d9c68970596d6f78d891d1f51711a823b1a38cf1decf9c0171477649baa3560b",
4
- "memoryCount": 71,
5
- "generatedAt": "2026-03-13T14:06:22.540Z",
3
+ "sourceHash": "3dce40a1ad092880b2f8005a2c3f9982e37775ef0886a74f329ef1b167c409ce",
4
+ "memoryCount": 81,
5
+ "generatedAt": "2026-03-16T10:21:29.975Z",
6
6
  "memoryKeys": [
7
+ "memory_1773656489964_tpm4ycfc1",
8
+ "memory_1773656489936_29pvxu7ni",
9
+ "memory_1773656489924_ick7951wj",
10
+ "memory_1773656489912_w54afewzm",
11
+ "memory_1773656489839_ij3r3sg2s",
12
+ "memory_1773654956839_pluovrk77",
13
+ "memory_1773654956815_ofh9by5rb",
14
+ "memory_1773654956802_24y27xjux",
15
+ "memory_1773654956790_pnrio2ihb",
16
+ "memory_1773654956712_hnjabccni",
7
17
  "memory_1773410782523_k5hjje6pt",
8
18
  "memory_1773410782491_zbm4dcqvl",
9
19
  "memory_1773410782472_t0nrgizx2",
package/README.md CHANGED
@@ -55,6 +55,7 @@ Once installed, Claude Recall works automatically in the background:
55
55
  2. **As you work** — the `correction-detector` hook classifies every prompt you type. Natural statements like *"we use tabs here"* or *"no, put tests in `__tests__/`"* are detected and stored automatically
56
56
  3. **End of turn** — the `memory-stop` hook scans recent transcript entries for corrections, preferences, failures, and devops patterns
57
57
  4. **Before context compression** — the `precompact-preserve` hook sweeps up to 50 entries so nothing important is lost when the context window shrinks
58
+ 5. **Rules sync to auto-memory** — the `memory-sync` hook exports active rules to `~/.claude/projects/{project}/memory/recall-rules.md` so they're available even when the MCP server is down
58
59
 
59
60
  All classification uses Claude Haiku (via `ANTHROPIC_API_KEY` from your Claude Code session) with silent regex fallback. No configuration needed.
60
61
 
@@ -147,6 +148,7 @@ claude-recall project clean # Remove stale registry entries
147
148
  claude-recall hook run correction-detector # UserPromptSubmit hook
148
149
  claude-recall hook run memory-stop # Stop hook
149
150
  claude-recall hook run precompact-preserve # PreCompact hook
151
+ claude-recall hook run memory-sync # Stop + PreCompact hook (syncs rules to auto-memory)
150
152
  ```
151
153
 
152
154
  </details>
@@ -608,7 +608,7 @@ async function main() {
608
608
  // This avoids registry lookups on every hook invocation.
609
609
  const cliScript = path.join(packageDir, 'dist', 'cli', 'claude-recall-cli.js');
610
610
  const hookCmd = `node ${cliScript} hook run`;
611
- settings.hooksVersion = '6.0.0'; // v6 = local node path instead of npx for hooks
611
+ settings.hooksVersion = '7.0.0'; // v7 = add memory-sync hook for auto-memory export
612
612
  settings.hooks = {
613
613
  PreToolUse: [
614
614
  {
@@ -638,6 +638,11 @@ async function main() {
638
638
  type: "command",
639
639
  command: `${hookCmd} memory-stop`,
640
640
  timeout: 30
641
+ },
642
+ {
643
+ type: "command",
644
+ command: `${hookCmd} memory-sync`,
645
+ timeout: 10
641
646
  }
642
647
  ]
643
648
  }
@@ -649,6 +654,11 @@ async function main() {
649
654
  type: "command",
650
655
  command: `${hookCmd} precompact-preserve`,
651
656
  timeout: 60
657
+ },
658
+ {
659
+ type: "command",
660
+ command: `${hookCmd} memory-sync`,
661
+ timeout: 10
652
662
  }
653
663
  ]
654
664
  }
@@ -70,9 +70,14 @@ class HookCommands {
70
70
  await handlePrecompactPreserve(input);
71
71
  break;
72
72
  }
73
+ case 'memory-sync': {
74
+ const { handleMemorySync } = await Promise.resolve().then(() => __importStar(require('../../hooks/memory-sync-hook')));
75
+ await handleMemorySync(input);
76
+ break;
77
+ }
73
78
  default:
74
79
  console.error(`Unknown hook: ${name}`);
75
- console.error('Available: correction-detector, memory-stop, precompact-preserve');
80
+ console.error('Available: correction-detector, memory-stop, precompact-preserve, memory-sync');
76
81
  }
77
82
  }
78
83
  catch {
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ /**
3
+ * memory-sync-hook — fires on Stop and PreCompact events.
4
+ *
5
+ * Exports active rules from Claude Recall's SQLite database to a topic file
6
+ * in Claude Code's auto-memory directory, so rules are available even when
7
+ * the MCP server is down.
8
+ *
9
+ * Input: { session_id, cwd, hook_event_name }
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.deriveAutoMemoryPath = deriveAutoMemoryPath;
46
+ exports.handleMemorySync = handleMemorySync;
47
+ const fs = __importStar(require("fs"));
48
+ const path = __importStar(require("path"));
49
+ const os = __importStar(require("os"));
50
+ const shared_1 = require("./shared");
51
+ const memory_1 = require("../services/memory");
52
+ const config_1 = require("../services/config");
53
+ /** Keys that look like test data */
54
+ const TEST_KEY_PATTERNS = [/^Test /i, /^Session test /i, /^test_/i];
55
+ /** Values that may contain secrets */
56
+ const SECRET_PATTERNS = [/api_key/i, /token/i, /password/i, /secret/i, /credential/i, /private_key/i];
57
+ /**
58
+ * Derive the auto-memory directory path from a cwd.
59
+ * Matches Claude Code's convention: ~/.claude/projects/{cwd with / replaced by -}/memory/
60
+ */
61
+ function deriveAutoMemoryPath(cwd, homedir) {
62
+ const home = homedir || os.homedir();
63
+ const sanitized = cwd.replace(/\//g, '-');
64
+ return path.join(home, '.claude', 'projects', sanitized, 'memory');
65
+ }
66
+ /**
67
+ * Extract display value from a memory record, matching memory-tools.ts formatting.
68
+ */
69
+ function extractValue(m) {
70
+ const val = typeof m.value === 'object'
71
+ ? (m.value.content || m.value.value || JSON.stringify(m.value))
72
+ : m.value;
73
+ return String(val);
74
+ }
75
+ /**
76
+ * Check if a memory key matches test data patterns.
77
+ */
78
+ function isTestData(key) {
79
+ return TEST_KEY_PATTERNS.some(p => p.test(key));
80
+ }
81
+ /**
82
+ * Check if a value contains secret-like content.
83
+ */
84
+ function containsSecret(value) {
85
+ return SECRET_PATTERNS.some(p => p.test(value));
86
+ }
87
+ /**
88
+ * Format rules into markdown sections.
89
+ */
90
+ function formatRulesMarkdown(rules) {
91
+ const sections = [];
92
+ sections.push('<!-- Auto-generated by Claude Recall — overwritten each session -->');
93
+ sections.push('# Claude Recall Rules');
94
+ if (rules.preferences.length > 0) {
95
+ sections.push('\n## Preferences');
96
+ for (const m of rules.preferences) {
97
+ const val = extractValue(m);
98
+ const key = m.preference_key || m.key || '';
99
+ const isAutoKey = key.startsWith('memory_') || key.startsWith('auto_') || key.startsWith('pref_') || key.startsWith('hook_');
100
+ sections.push(isAutoKey ? `- ${val}` : `- ${key}: ${val}`);
101
+ }
102
+ }
103
+ if (rules.corrections.length > 0) {
104
+ sections.push('\n## Corrections');
105
+ for (const m of rules.corrections) {
106
+ sections.push(`- ${extractValue(m)}`);
107
+ }
108
+ }
109
+ if (rules.failures.length > 0) {
110
+ sections.push('\n## Failures');
111
+ for (const m of rules.failures) {
112
+ sections.push(`- ${extractValue(m)}`);
113
+ }
114
+ }
115
+ if (rules.devops.length > 0) {
116
+ sections.push('\n## DevOps Rules');
117
+ for (const m of rules.devops) {
118
+ sections.push(`- ${extractValue(m)}`);
119
+ }
120
+ }
121
+ sections.push(`\n---\n*Last synced: ${new Date().toISOString()}*`);
122
+ return sections.join('\n') + '\n';
123
+ }
124
+ const MEMORY_MD_POINTER = `\n## Claude Recall\n- See [recall-rules.md](recall-rules.md) for learned preferences, corrections, and failure lessons\n`;
125
+ /**
126
+ * Ensure MEMORY.md contains a pointer to recall-rules.md.
127
+ * Appends the pointer only if absent. Never overwrites existing content.
128
+ */
129
+ function ensureMemoryMdPointer(memoryDir) {
130
+ const memoryMdPath = path.join(memoryDir, 'MEMORY.md');
131
+ let existing = '';
132
+ if (fs.existsSync(memoryMdPath)) {
133
+ existing = fs.readFileSync(memoryMdPath, 'utf-8');
134
+ }
135
+ if (existing.includes('recall-rules.md')) {
136
+ return; // Pointer already present
137
+ }
138
+ fs.appendFileSync(memoryMdPath, MEMORY_MD_POINTER);
139
+ }
140
+ /**
141
+ * Filter out test data and secrets from rules.
142
+ */
143
+ function filterRules(memories) {
144
+ return memories.filter(m => {
145
+ const key = m.preference_key || m.key || '';
146
+ if (isTestData(key))
147
+ return false;
148
+ const val = extractValue(m);
149
+ if (containsSecret(val))
150
+ return false;
151
+ return true;
152
+ });
153
+ }
154
+ async function handleMemorySync(input) {
155
+ const cwd = input?.cwd ?? '';
156
+ if (!cwd) {
157
+ (0, shared_1.hookLog)('memory-sync', 'No cwd provided — skipping sync');
158
+ return;
159
+ }
160
+ try {
161
+ const projectId = config_1.ConfigService.getInstance().getProjectId();
162
+ const memoryService = memory_1.MemoryService.getInstance();
163
+ const rules = memoryService.loadActiveRules(projectId);
164
+ // Filter each category
165
+ const filtered = {
166
+ preferences: filterRules(rules.preferences),
167
+ corrections: filterRules(rules.corrections),
168
+ failures: filterRules(rules.failures),
169
+ devops: filterRules(rules.devops),
170
+ };
171
+ const totalRules = filtered.preferences.length + filtered.corrections.length +
172
+ filtered.failures.length + filtered.devops.length;
173
+ // Derive auto-memory path and ensure directory exists
174
+ const memoryDir = deriveAutoMemoryPath(cwd);
175
+ if (!fs.existsSync(memoryDir)) {
176
+ fs.mkdirSync(memoryDir, { recursive: true });
177
+ }
178
+ // Write recall-rules.md (full overwrite)
179
+ const markdown = formatRulesMarkdown(filtered);
180
+ const rulesPath = path.join(memoryDir, 'recall-rules.md');
181
+ fs.writeFileSync(rulesPath, markdown);
182
+ // Ensure MEMORY.md has pointer
183
+ ensureMemoryMdPointer(memoryDir);
184
+ (0, shared_1.hookLog)('memory-sync', `Synced ${totalRules} rules to ${rulesPath}`);
185
+ }
186
+ catch (error) {
187
+ (0, shared_1.hookLog)('memory-sync', `Error: ${error.message}`);
188
+ }
189
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-recall",
3
- "version": "0.15.36",
3
+ "version": "0.16.0",
4
4
  "description": "Persistent memory for Claude Code with native Skills integration, automatic capture, failure learning, and project scoping via MCP server",
5
5
  "main": "dist/index.js",
6
6
  "bin": {