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.
- package/.claude/skills/auto-corrections/SKILL.md +3 -1
- package/.claude/skills/auto-corrections/manifest.json +5 -3
- package/.claude/skills/auto-failure-lessons/SKILL.md +6 -1
- package/.claude/skills/auto-failure-lessons/manifest.json +8 -3
- package/.claude/skills/auto-preferences/SKILL.md +11 -1
- package/.claude/skills/auto-preferences/manifest.json +13 -3
- package/README.md +2 -0
- package/dist/cli/claude-recall-cli.js +11 -1
- package/dist/cli/commands/hook-commands.js +6 -1
- package/dist/hooks/memory-sync-hook.js +189 -0
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ source: claude-recall
|
|
|
8
8
|
|
|
9
9
|
# Corrections
|
|
10
10
|
|
|
11
|
-
Auto-generated from
|
|
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": "
|
|
4
|
-
"memoryCount":
|
|
5
|
-
"generatedAt": "2026-03-
|
|
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
|
|
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": "
|
|
4
|
-
"memoryCount":
|
|
5
|
-
"generatedAt": "2026-03-
|
|
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
|
|
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": "
|
|
4
|
-
"memoryCount":
|
|
5
|
-
"generatedAt": "2026-03-
|
|
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 = '
|
|
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.
|
|
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": {
|