claude-recall 0.15.35 → 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 16 memories. Last updated: 2026-03-13.
11
+ Auto-generated from 19 memories. Last updated: 2026-03-16.
12
12
 
13
13
  ## Rules
14
14
 
@@ -21,6 +21,9 @@ Auto-generated from 16 memories. Last updated: 2026-03-13.
21
21
  - CORRECTION: Memory with complex metadata
22
22
  - CORRECTION: Memory with complex metadata
23
23
  - CORRECTION: Memory with complex metadata
24
+ - CORRECTION: Memory with complex metadata
25
+ - CORRECTION: Memory with complex metadata
26
+ - CORRECTION: Memory with complex metadata
24
27
  - CORRECTION: Replace expired access token with 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
25
28
  - CORRECTION: use spaces not tabs for indentation
26
29
  - CORRECTION: cited (loaded 5+ times): 19
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "topicId": "corrections",
3
- "sourceHash": "21cd6449035ceb41ab7af48b8aed6ebb7ecccbd8170c162bee85d54f7b892566",
4
- "memoryCount": 16,
5
- "generatedAt": "2026-03-13T13:39:28.384Z",
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",
9
+ "memory_1773410782442_mnfvdml5n",
7
10
  "memory_1773409168373_t4lqoqpiv",
8
11
  "memory_1773220863163_q8k0ewti8",
9
12
  "memory_1773140547102_2wmy0cfga",
@@ -8,11 +8,19 @@ source: claude-recall
8
8
 
9
9
  # Failure Lessons
10
10
 
11
- Auto-generated from 13 memories. Last updated: 2026-03-10.
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
+ - 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
22
+ - Claude-recall MCP Server failed to start with npx claude-recall@latest mcp start
23
+ - Claude-recall MCP Server failed to start with command: npx -y claude-recall@latest mcp start
16
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
17
25
  - Avoid: Command failed: npx jest tests/unit/failure-detectors.test.ts 2>&1 → Instead: Check command syntax, file paths, and prerequisites before running
18
26
  - Missing dependency: better-sqlite3 module not installed
@@ -22,6 +30,8 @@ Auto-generated from 13 memories. Last updated: 2026-03-10.
22
30
  - npm package claude-recall@0.15.14 not found in registry - 404 error during installation
23
31
  - Avoid: Test command reported failures: npx jest tests/unit/failure-detectors.test.ts 2>&1 → Instead: Read test output carefully — exit code 0 does not mean all tests passed
24
32
  - Node.js -e flag cannot parse multiline strings with unescaped newlines in single quotes
33
+ - claude-recall reconnection failed after reinstall
34
+ - claude-recall reconnection failed after reinstall attempt
25
35
  - Output is showing '>' instead of expected response
26
36
  - Code output returns '>' instead of expected response
27
37
  - Avoid: Claude backtracked: "let me try a different approach" → Instead: Consider the problem more carefully before starting. Check for similar past failures.
@@ -1,10 +1,18 @@
1
1
  {
2
2
  "topicId": "failure-lessons",
3
- "sourceHash": "0206a4a3369d15fb6595432f69229deee0672d467387a8eb03bb556bd0314efd",
4
- "memoryCount": 13,
5
- "generatedAt": "2026-03-10T11:02:27.067Z",
3
+ "sourceHash": "6c18a22368601e246196934bc675b7cc11619a20758e5a8067886375b499dd00",
4
+ "memoryCount": 23,
5
+ "generatedAt": "2026-03-16T09:55:56.753Z",
6
6
  "memoryKeys": [
7
7
  "hook_failure_1772637584921_0tj4rrxnt",
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",
14
+ "hook_failure_1773409616313_gmsfcbuzh",
15
+ "hook_failure_1773409607268_83ie5yunz",
8
16
  "hook_failure_non-zero-exit_1773068793859_0z0ah0743",
9
17
  "hook_failure_non-zero-exit_1772640279977_g3gwlfoqi",
10
18
  "hook_failure_1772637646276_ow6m7pr34",
@@ -14,6 +22,8 @@
14
22
  "hook_failure_1771937269919_jx3wvpyxq",
15
23
  "hook_failure_silent-test-failure_1772640279996_m8f3ks8fw",
16
24
  "hook_failure_1772637495154_i21dho3dv",
25
+ "hook_failure_1773410663873_oegccxk83",
26
+ "hook_failure_1773410656672_kno1aw8wf",
17
27
  "hook_failure_1772637391602_cjj3esg33",
18
28
  "hook_failure_1772637376157_hvco6jbm4",
19
29
  "hook_failure_backtracking_1772640280006_snb0x5cgg"
@@ -8,10 +8,25 @@ source: claude-recall
8
8
 
9
9
  # Preferences
10
10
 
11
- Auto-generated from 66 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
25
+ - Session test preference 1773410782522
26
+ - Test preference 1773410782456-2
27
+ - Test preference 1773410782456-1
28
+ - Test preference 1773410782456-0
29
+ - Test memory content
15
30
  - Session test preference 1773409168447
16
31
  - Test preference 1773409168387-2
17
32
  - Test preference 1773409168387-1
@@ -1,9 +1,24 @@
1
1
  {
2
2
  "topicId": "preferences",
3
- "sourceHash": "614d7c14b75ac425b8c1ffc47e93c938b554208aadc39784730de3c3d198d7e0",
4
- "memoryCount": 66,
5
- "generatedAt": "2026-03-13T13:39:28.461Z",
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",
17
+ "memory_1773410782523_k5hjje6pt",
18
+ "memory_1773410782491_zbm4dcqvl",
19
+ "memory_1773410782472_t0nrgizx2",
20
+ "memory_1773410782457_eca2hxqcs",
21
+ "memory_1773410782389_ehwhx4mov",
7
22
  "memory_1773409168448_lp6jbcq6o",
8
23
  "memory_1773409168422_x97lwordj",
9
24
  "memory_1773409168407_gjxhfjl1u",
package/README.md CHANGED
@@ -31,11 +31,10 @@ Your preferences, project structure, workflows, corrections, and coding style ar
31
31
  ### Install & Activate
32
32
 
33
33
  ```bash
34
- cd your-project
35
- npm cache clean --force && npm install claude-recall@latest
36
- claude mcp remove claude-recall 2>/dev/null; claude mcp add claude-recall -- npx -y claude-recall@latest mcp start
37
- npx claude-recall setup --install
38
- npx claude-recall --version
34
+ npm install -g claude-recall
35
+ claude mcp remove claude-recall 2>/dev/null; claude mcp add claude-recall -s user -- claude-recall mcp start
36
+ cd your-project && claude-recall setup --install
37
+ claude-recall --version
39
38
  ```
40
39
 
41
40
  Then restart your terminal or Claude Code session.
@@ -56,6 +55,7 @@ Once installed, Claude Recall works automatically in the background:
56
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
57
56
  3. **End of turn** — the `memory-stop` hook scans recent transcript entries for corrections, preferences, failures, and devops patterns
58
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
59
59
 
60
60
  All classification uses Claude Haiku (via `ANTHROPIC_API_KEY` from your Claude Code session) with silent regex fallback. No configuration needed.
61
61
 
@@ -64,8 +64,8 @@ All classification uses Claude Haiku (via `ANTHROPIC_API_KEY` from your Claude C
64
64
  ```bash
65
65
  # Verify it's working
66
66
  cat ~/.claude-recall/hook-logs/correction-detector.log
67
- npx claude-recall stats
68
- npx claude-recall search "preference"
67
+ claude-recall stats
68
+ claude-recall search "preference"
69
69
  ```
70
70
 
71
71
  ---
@@ -88,12 +88,12 @@ Claude Recall runs as an MCP server exposing four tools, backed by a local SQLit
88
88
  ### Common Commands
89
89
 
90
90
  ```bash
91
- npx claude-recall stats # Memory statistics
92
- npx claude-recall search "query" # Search memories
93
- npx claude-recall failures # View failure memories
94
- npx claude-recall export backup.json # Export memories to JSON
95
- npx claude-recall import backup.json # Import memories from JSON
96
- npx claude-recall --version # Check version
91
+ claude-recall stats # Memory statistics
92
+ claude-recall search "query" # Search memories
93
+ claude-recall failures # View failure memories
94
+ claude-recall export backup.json # Export memories to JSON
95
+ claude-recall import backup.json # Import memories from JSON
96
+ claude-recall --version # Check version
97
97
  ```
98
98
 
99
99
  <details>
@@ -101,53 +101,54 @@ npx claude-recall --version # Check version
101
101
 
102
102
  ```bash
103
103
  # ── Upgrade ──────────────────────────────────────────────────────────
104
- npm cache clean --force && npm install claude-recall@latest
105
- npx claude-recall setup --install # Re-register hooks + skills
106
- npx claude-recall --version # Verify
104
+ npm install -g claude-recall@latest
105
+ claude-recall setup --install # Re-register hooks + skills
106
+ claude-recall --version # Verify
107
107
 
108
108
  # ── Setup & Diagnostics ─────────────────────────────────────────────
109
- npx claude-recall setup # Show activation instructions
110
- npx claude-recall setup --install # Install skills + hooks
111
- npx claude-recall status # Installation and system status
112
- npx claude-recall repair # Clean up old hooks, install skills
109
+ claude-recall setup # Show activation instructions
110
+ claude-recall setup --install # Install skills + hooks
111
+ claude-recall status # Installation and system status
112
+ claude-recall repair # Clean up old hooks, install skills
113
113
 
114
114
  # ── Memory ───────────────────────────────────────────────────────────
115
- npx claude-recall stats # Memory statistics
116
- npx claude-recall search "query" # Search memories
117
- npx claude-recall store "content" # Store memory directly
118
- npx claude-recall export backup.json # Export memories to JSON
119
- npx claude-recall import backup.json # Import memories from JSON
120
- npx claude-recall clear --force # Clear all memories
121
- npx claude-recall failures # View failure memories
122
- npx claude-recall failures --limit 20 # Limit results
123
- npx claude-recall monitor # Memory search monitoring stats
115
+ claude-recall stats # Memory statistics
116
+ claude-recall search "query" # Search memories
117
+ claude-recall store "content" # Store memory directly
118
+ claude-recall export backup.json # Export memories to JSON
119
+ claude-recall import backup.json # Import memories from JSON
120
+ claude-recall clear --force # Clear all memories
121
+ claude-recall failures # View failure memories
122
+ claude-recall failures --limit 20 # Limit results
123
+ claude-recall monitor # Memory search monitoring stats
124
124
 
125
125
  # ── Skills ───────────────────────────────────────────────────────────
126
- npx claude-recall skills generate # Generate skills from memories
127
- npx claude-recall skills generate --dry-run # Preview without writing
128
- npx claude-recall skills generate --force # Regenerate even if unchanged
129
- npx claude-recall skills list # List generated skills
130
- npx claude-recall skills clean --force # Remove all auto-generated skills
126
+ claude-recall skills generate # Generate skills from memories
127
+ claude-recall skills generate --dry-run # Preview without writing
128
+ claude-recall skills generate --force # Regenerate even if unchanged
129
+ claude-recall skills list # List generated skills
130
+ claude-recall skills clean --force # Remove all auto-generated skills
131
131
 
132
132
  # ── MCP Server ───────────────────────────────────────────────────────
133
- npx claude-recall mcp status # Current project's server status
134
- npx claude-recall mcp ps # List all running servers
135
- npx claude-recall mcp stop # Stop server
136
- npx claude-recall mcp stop --force # Force stop
137
- npx claude-recall mcp restart # Restart server
138
- npx claude-recall mcp cleanup # Remove stale PID files
139
- npx claude-recall mcp cleanup --all # Stop all servers
133
+ claude-recall mcp status # Current project's server status
134
+ claude-recall mcp ps # List all running servers
135
+ claude-recall mcp stop # Stop server
136
+ claude-recall mcp stop --force # Force stop
137
+ claude-recall mcp restart # Restart server
138
+ claude-recall mcp cleanup # Remove stale PID files
139
+ claude-recall mcp cleanup --all # Stop all servers
140
140
 
141
141
  # ── Project ──────────────────────────────────────────────────────────
142
- npx claude-recall project show # Current project info
143
- npx claude-recall project list # All registered projects
144
- npx claude-recall project register # Register current project
145
- npx claude-recall project clean # Remove stale registry entries
142
+ claude-recall project show # Current project info
143
+ claude-recall project list # All registered projects
144
+ claude-recall project register # Register current project
145
+ claude-recall project clean # Remove stale registry entries
146
146
 
147
147
  # ── Auto-Capture Hooks (run automatically, registered via setup --install) ──
148
- npx claude-recall hook run correction-detector # UserPromptSubmit hook
149
- npx claude-recall hook run memory-stop # Stop hook
150
- npx claude-recall hook run precompact-preserve # PreCompact hook
148
+ claude-recall hook run correction-detector # UserPromptSubmit hook
149
+ claude-recall hook run memory-stop # Stop hook
150
+ claude-recall hook run precompact-preserve # PreCompact hook
151
+ claude-recall hook run memory-sync # Stop + PreCompact hook (syncs rules to auto-memory)
151
152
  ```
152
153
 
153
154
  </details>
@@ -176,23 +177,11 @@ Details in [docs/security.md](docs/security.md).
176
177
  <details>
177
178
  <summary>WSL Users</summary>
178
179
 
179
- If you hit "invalid ELF header" errors from mixed Windows/WSL `node_modules`, use a global install:
180
+ If you hit "invalid ELF header" errors from mixed Windows/WSL `node_modules`, ensure you're using the global install (now the default). Verify the binary resolves to a Linux path:
180
181
 
181
182
  ```bash
182
- npm install -g claude-recall
183
- ```
184
-
185
- Update `~/.claude.json` to use the global binary:
186
-
187
- ```json
188
- {
189
- "claude-recall": {
190
- "type": "stdio",
191
- "command": "claude-recall",
192
- "args": ["mcp", "start"],
193
- "env": {}
194
- }
195
- }
183
+ which claude-recall
184
+ # Should show: /home/<user>/.nvm/.../bin/claude-recall (NOT a Windows path)
196
185
  ```
197
186
 
198
187
  Global installation does **not** affect project scoping — project ID is still detected from Claude Code's working directory.
@@ -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.35",
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": {