claude-recall 0.33.0 → 0.34.1
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/README.md +6 -4
- package/dist/cli/claude-recall-cli.js +34 -2
- package/dist/cli/commands/kiro-commands.js +43 -23
- package/dist/hooks/kiro-hooks.js +138 -22
- package/docs/2025-08-07-launch-article-linkedin.md +83 -0
- package/docs/2026-07-follow-up-article-draft.md +68 -0
- package/docs/2026-07-follow-up-article-linkedin-tight.md +46 -0
- package/docs/kiro.md +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ That's the whole workflow. A background hook classified your prompt with an LLM
|
|
|
28
28
|
>
|
|
29
29
|
> **Agent:** Installing vitest with **pnpm** *(applied from memory: "Use pnpm, not npm")* …
|
|
30
30
|
|
|
31
|
-
Your rules are injected at session start and
|
|
31
|
+
Your rules are injected at session start and kept alive mid-session — just-in-time before each relevant tool call (Claude Code, Pi), or as a periodic refresh (Kiro) — at the moment of decision, not 50,000 tokens upstream. This works across agents too: correct Claude Code on Tuesday, and Kiro applies it on Friday.
|
|
32
32
|
|
|
33
33
|
**And you can audit what it knows at any time:**
|
|
34
34
|
|
|
@@ -45,7 +45,7 @@ $ claude-recall search "pnpm"
|
|
|
45
45
|
## Features
|
|
46
46
|
|
|
47
47
|
- **Automatic capture** — an LLM classifier detects preferences, corrections, and project facts in your normal prompts, running on **the agent's own LLM** (Claude subscription / Kiro credits — never a separate API key), with regex fallback when no LLM is available
|
|
48
|
-
- **Applied where it counts** — rules load at session start
|
|
48
|
+
- **Applied where it counts** — rules load at session start and are re-surfaced mid-session: just-in-time before each tool call (Claude Code, Pi) or as a periodic refresh every N prompts (Kiro)
|
|
49
49
|
- **Project-scoped** — each project gets its own memory namespace; switch directories and the agent switches context
|
|
50
50
|
- **Learns from failures** — records what broke, why, and what fixed it, so mistakes aren't repeated
|
|
51
51
|
- **Outcome-aware** — tracks whether rules actually help (tool results, test cycles, re-asks) and promotes validated lessons into active rules
|
|
@@ -162,7 +162,8 @@ Once installed, Claude Recall works in the background (CC = Claude Code):
|
|
|
162
162
|
|---|---|:-:|:-:|:-:|
|
|
163
163
|
| **Session start** | Active rules are injected into the agent's context | ✓ | ✓ | ✓ |
|
|
164
164
|
| **As you type** | Prompts are classified; durable preferences/corrections are stored | ✓ | ✓ | ✓ |
|
|
165
|
-
| **Before each tool call** | Relevant rules are re-surfaced next to the action (just-in-time injection) | ✓ | ✓ |
|
|
165
|
+
| **Before each tool call** | Relevant rules are re-surfaced next to the action (just-in-time injection) | ✓ | ✓ | |
|
|
166
|
+
| **Every 15 prompts** | Active rules are re-injected so long sessions can't silently lose them (interval configurable) | | | ✓ |
|
|
166
167
|
| **Tool outcomes** | Failures are recorded; Bash failures are paired with their eventual fix | ✓ | ✓ | ✓ |
|
|
167
168
|
| **Re-ask detection** | Frustration signals (*"still broken"*) are recorded as outcome events | ✓ | ✓ | ✓ |
|
|
168
169
|
| **Before context compression** | Important context is captured before the window shrinks | ✓ | ✓ | |
|
|
@@ -325,7 +326,7 @@ action → outcome event → episode → candidate lesson → promotion → acti
|
|
|
325
326
|
outcome resolved per injected rule
|
|
326
327
|
```
|
|
327
328
|
|
|
328
|
-
Failures become candidate lessons (deduplicated by similarity); lessons seen 2+ times (or once, if severe) are promoted to active rules; every just-in-time injection is recorded and resolved against the tool's outcome, building per-rule effectiveness data over time.
|
|
329
|
+
Failures become candidate lessons (deduplicated by similarity); lessons seen 2+ times (or once, if severe) are promoted to active rules; every just-in-time injection (Claude Code, Pi) is recorded and resolved against the tool's outcome, building per-rule effectiveness data over time.
|
|
329
330
|
|
|
330
331
|
---
|
|
331
332
|
|
|
@@ -395,6 +396,7 @@ Defaults work out of the box; tune via environment variables as needed.
|
|
|
395
396
|
| `CLAUDE_RECALL_KIRO_MODEL` | `claude-haiku-4.5` | Dedicated model for Kiro-LLM capture classification — **independent of your interactive Kiro chat model**. Raise to `claude-sonnet-4.6` for steadier judgement at more credits. See [docs/kiro-llm-capture.md](docs/kiro-llm-capture.md). |
|
|
396
397
|
| `CLAUDE_RECALL_PREFER_API_KEY` | _(unset)_ | **The only switch that enables the `ANTHROPIC_API_KEY` backend** (and prefers it first). For Pi-only machines without the `claude` binary, or a stronger model you deliberately pay for. Applies to all LLM features, under Claude Code, Kiro, and Pi. |
|
|
397
398
|
| `CLAUDE_RECALL_KIRO_LLM_TIMEOUT_MS` | `30000` | Hard cap on the headless `kiro-cli` classify call before the capture worker gives up and falls back to regex. |
|
|
399
|
+
| `CLAUDE_RECALL_REFRESH_INTERVAL` | `15` | **Kiro only.** Re-inject the active rules into context every N prompts, so marathon sessions can't silently lose them to context rollover (Kiro has no post-compaction event). `0` disables. |
|
|
398
400
|
| `CLAUDE_RECALL_LOAD_BUDGET_TOKENS` | `2000` | Token budget for the `load_rules` payload. Rules are emitted in priority order (corrections → preferences by citation → devops by citation → failures) and dropped rules surface via `search_memory`. |
|
|
399
401
|
| `CLAUDE_RECALL_AUTO_DEMOTE` | `false` | When `true`, auto-demote rules on MCP boot where `load_count >= CLAUDE_RECALL_DEMOTE_MIN_LOADS`, `cite_count = 0`, and age `> CLAUDE_RECALL_DEMOTE_MIN_AGE_DAYS`. Still reversible via `rules promote <id>`. |
|
|
400
402
|
| `CLAUDE_RECALL_DEMOTE_MIN_LOADS` | `20` | Minimum load count before a rule qualifies for auto-demotion. |
|
|
@@ -406,6 +406,12 @@ class ClaudeRecallCLI {
|
|
|
406
406
|
console.error('\nCheck your connection, then run `claude-recall upgrade` again.');
|
|
407
407
|
process.exit(1);
|
|
408
408
|
}
|
|
409
|
+
// `latest` is interpolated into an npm argument (via a shell on Windows) —
|
|
410
|
+
// accept only a plausible semver string from the registry response.
|
|
411
|
+
if (!/^\d+\.\d+\.\d+(-[\w.]+)?$/.test(latest)) {
|
|
412
|
+
console.error(`❌ Unexpected version string from the registry: "${latest}"`);
|
|
413
|
+
process.exit(1);
|
|
414
|
+
}
|
|
409
415
|
console.log(`Installed: ${current}`);
|
|
410
416
|
console.log(`Latest: ${latest}`);
|
|
411
417
|
const needsInstall = current !== latest;
|
|
@@ -413,7 +419,11 @@ class ClaudeRecallCLI {
|
|
|
413
419
|
console.log(`\n📦 Upgrading ${current} → ${latest}...\n`);
|
|
414
420
|
// Run npm install -g, streaming output so the user sees progress / errors live.
|
|
415
421
|
// shell: true on Windows — npm is npm.cmd there and a bare spawnSync ENOENTs.
|
|
416
|
-
|
|
422
|
+
// Pin the exact version `npm view` just resolved instead of `@latest`:
|
|
423
|
+
// right after a publish, the dist-tag replica npm installs from can lag
|
|
424
|
+
// the metadata endpoint `npm view` read — `@latest` then silently
|
|
425
|
+
// reinstalls the OLD version with exit 0 (observed live on 0.34.0).
|
|
426
|
+
const install = spawnSync('npm', ['install', '-g', `claude-recall@${latest}`], {
|
|
417
427
|
stdio: 'inherit',
|
|
418
428
|
shell: process.platform === 'win32',
|
|
419
429
|
});
|
|
@@ -429,7 +439,9 @@ class ClaudeRecallCLI {
|
|
|
429
439
|
if (install.status !== 0) {
|
|
430
440
|
// npm prints its own error — add the practical remediation on top
|
|
431
441
|
console.error('\n❌ Install failed.');
|
|
432
|
-
console.error(
|
|
442
|
+
console.error(`\nIf npm said it can't find claude-recall@${latest} (ETARGET): the release`);
|
|
443
|
+
console.error('is minutes old and the registry is still propagating — wait a minute and re-run.');
|
|
444
|
+
console.error('\nMost common cause otherwise: your global npm prefix is owned by root (EACCES).');
|
|
433
445
|
console.error('\nQuick fix:');
|
|
434
446
|
console.error(' sudo npm install -g claude-recall');
|
|
435
447
|
console.error('\nPermanent fix (no more sudo for any global install on this machine):');
|
|
@@ -440,6 +452,26 @@ class ClaudeRecallCLI {
|
|
|
440
452
|
console.error('\nThen re-run: claude-recall upgrade');
|
|
441
453
|
process.exit(install.status ?? 1);
|
|
442
454
|
}
|
|
455
|
+
// Trust but verify: confirm the globally installed version actually IS
|
|
456
|
+
// `latest` before claiming success. The success message used to report
|
|
457
|
+
// intent, not fact — a propagation race left 0.33.0 installed while the
|
|
458
|
+
// command printed "✓ Upgraded to 0.34.0".
|
|
459
|
+
let installedNow = '';
|
|
460
|
+
try {
|
|
461
|
+
const ls = JSON.parse(execSync('npm ls -g claude-recall --json', {
|
|
462
|
+
encoding: 'utf-8',
|
|
463
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
464
|
+
}));
|
|
465
|
+
installedNow = ls?.dependencies?.['claude-recall']?.version ?? '';
|
|
466
|
+
}
|
|
467
|
+
catch { /* verification is best-effort; fall through to the mismatch path */ }
|
|
468
|
+
if (installedNow !== latest) {
|
|
469
|
+
console.error(`\n❌ Install reported success but the global version is ${installedNow || 'unreadable'}, not ${latest}.`);
|
|
470
|
+
console.error(' This usually means the npm registry is still propagating a very recent');
|
|
471
|
+
console.error(' release. Wait a minute, then re-run: claude-recall upgrade');
|
|
472
|
+
console.error(` Or install the exact version directly: npm install -g claude-recall@${latest}`);
|
|
473
|
+
process.exit(1);
|
|
474
|
+
}
|
|
443
475
|
// Kill any running MCP servers so Claude Code respawns them with the new binary
|
|
444
476
|
console.log('\n🧹 Cleaning up running MCP servers (Claude Code respawns them on next tool call)...');
|
|
445
477
|
try {
|
|
@@ -44,7 +44,7 @@ const repair_1 = require("./repair");
|
|
|
44
44
|
* `claude-recall kiro setup` writes a Kiro custom agent config
|
|
45
45
|
* (.kiro/agents/recall.json) wiring the same shared memory database into
|
|
46
46
|
* Kiro CLI: MCP tools, rules auto-loaded into context at agentSpawn,
|
|
47
|
-
*
|
|
47
|
+
* user-prompt capture with a periodic mid-session rule refresh, and tool
|
|
48
48
|
* outcome tracking. See src/hooks/kiro-hooks.ts for the adapter details and
|
|
49
49
|
* kiro.dev/docs/cli/custom-agents for the config format.
|
|
50
50
|
*/
|
|
@@ -81,23 +81,31 @@ class KiroCommands {
|
|
|
81
81
|
fs.writeFileSync(p, JSON.stringify(KiroCommands.buildClassifierAgentConfig(), null, 2) + '\n');
|
|
82
82
|
return p;
|
|
83
83
|
}
|
|
84
|
-
/**
|
|
84
|
+
/**
|
|
85
|
+
* The lifecycle hook entries (shared by fresh config and merge).
|
|
86
|
+
*
|
|
87
|
+
* No preToolUse entry: Kiro ignores preToolUse stdout (exit codes gate the
|
|
88
|
+
* tool; only exit-2 stderr reaches the LLM — kiro.dev/docs/cli/hooks), so
|
|
89
|
+
* the kiro-rule-injector wired there by versions ≤0.33 never reached the
|
|
90
|
+
* model. Mid-session injection rides userPromptSubmit instead (the periodic
|
|
91
|
+
* rule refresh inside kiro-capture); stale kiro-rule-injector entries are
|
|
92
|
+
* stripped on merge.
|
|
93
|
+
*/
|
|
85
94
|
static buildHookEntries(hookCmd) {
|
|
86
95
|
return {
|
|
87
96
|
// stdout of agentSpawn is added to context → rules present from turn one
|
|
88
97
|
agentSpawn: [
|
|
89
98
|
{ command: `${hookCmd} kiro-agent-spawn`, timeout_ms: 10000 },
|
|
90
99
|
],
|
|
91
|
-
// Capture. kiro-capture spawns a detached worker
|
|
92
|
-
// prompt via Kiro's own headless LLM (no
|
|
93
|
-
// stores in the background — see
|
|
94
|
-
// itself returns in milliseconds,
|
|
100
|
+
// Capture + periodic rule refresh. kiro-capture spawns a detached worker
|
|
101
|
+
// that classifies the prompt via Kiro's own headless LLM (no
|
|
102
|
+
// ANTHROPIC_API_KEY needed) and stores in the background — see
|
|
103
|
+
// src/hooks/kiro-classifier.ts. The hook itself returns in milliseconds,
|
|
104
|
+
// so the short timeout is ample. Its stdout is added to context, which
|
|
105
|
+
// also carries the every-N-prompts rule re-injection for long sessions.
|
|
95
106
|
userPromptSubmit: [
|
|
96
107
|
{ command: `${hookCmd} kiro-capture`, timeout_ms: 8000 },
|
|
97
108
|
],
|
|
98
|
-
preToolUse: [
|
|
99
|
-
{ matcher: '*', command: `${hookCmd} kiro-rule-injector`, timeout_ms: 5000 },
|
|
100
|
-
],
|
|
101
109
|
postToolUse: [
|
|
102
110
|
{ matcher: '*', command: `${hookCmd} kiro-tool-outcome`, timeout_ms: 5000 },
|
|
103
111
|
],
|
|
@@ -106,7 +114,7 @@ class KiroCommands {
|
|
|
106
114
|
static buildAgentConfig(hookCmd, mcpCommand, mcpArgs) {
|
|
107
115
|
return {
|
|
108
116
|
name: 'recall',
|
|
109
|
-
description: 'Kiro agent with Claude Recall persistent memory: rules auto-loaded at start,
|
|
117
|
+
description: 'Kiro agent with Claude Recall persistent memory: rules auto-loaded at start, periodic mid-session rule refresh, automatic capture of corrections and outcomes.',
|
|
110
118
|
// Also load any servers the user configured in .kiro/settings/mcp.json
|
|
111
119
|
includeMcpJson: true,
|
|
112
120
|
mcpServers: {
|
|
@@ -162,7 +170,6 @@ class KiroCommands {
|
|
|
162
170
|
const handlerMarkers = {
|
|
163
171
|
agentSpawn: 'kiro-agent-spawn',
|
|
164
172
|
userPromptSubmit: 'kiro-capture',
|
|
165
|
-
preToolUse: 'kiro-rule-injector',
|
|
166
173
|
postToolUse: 'kiro-tool-outcome',
|
|
167
174
|
};
|
|
168
175
|
// Superseded claude-recall hooks to strip from an event before wiring the
|
|
@@ -170,28 +177,41 @@ class KiroCommands {
|
|
|
170
177
|
// across versions. Pre-0.29 wired userPromptSubmit to `correction-detector`
|
|
171
178
|
// directly; 0.29 replaced it with `kiro-capture`. Leaving the old entry
|
|
172
179
|
// makes BOTH fire, double-capturing (often as near-duplicate memories).
|
|
180
|
+
// Versions ≤0.33 wired preToolUse to `kiro-rule-injector`, whose stdout
|
|
181
|
+
// Kiro never adds to context — a per-tool-call no-op, removed entirely.
|
|
173
182
|
// Only our own commands (containing 'claude-recall' / 'hook run') are
|
|
174
183
|
// touched — a user's unrelated hook on the same event is preserved.
|
|
175
184
|
const supersededMarkers = {
|
|
176
185
|
userPromptSubmit: ['correction-detector'],
|
|
186
|
+
preToolUse: ['kiro-rule-injector'],
|
|
177
187
|
};
|
|
178
188
|
const isOurCommand = (cmd) => cmd.includes('claude-recall') || cmd.includes('hook run');
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
189
|
+
const entriesByEvent = KiroCommands.buildHookEntries(hookCmd);
|
|
190
|
+
// Visit superseded-only events too (e.g. preToolUse, which we no longer
|
|
191
|
+
// wire but must still clean up), without inventing empty hook arrays in
|
|
192
|
+
// configs that never had them.
|
|
193
|
+
const allEvents = new Set([...Object.keys(entriesByEvent), ...Object.keys(supersededMarkers)]);
|
|
194
|
+
for (const event of allEvents) {
|
|
195
|
+
const entries = entriesByEvent[event] ?? [];
|
|
183
196
|
const marker = handlerMarkers[event];
|
|
184
197
|
// Strip superseded entries first (but never the current marker).
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
if (Array.isArray(config.hooks[event])) {
|
|
199
|
+
for (const stale of supersededMarkers[event] ?? []) {
|
|
200
|
+
if (stale === marker)
|
|
201
|
+
continue;
|
|
202
|
+
const before = config.hooks[event].length;
|
|
203
|
+
config.hooks[event] = config.hooks[event].filter((h) => !(typeof h?.command === 'string' && h.command.includes(stale) && isOurCommand(h.command)));
|
|
204
|
+
const removed = before - config.hooks[event].length;
|
|
205
|
+
if (removed > 0) {
|
|
206
|
+
changes.push(`hooks.${event}: removed ${removed} superseded ${stale} entr${removed === 1 ? 'y' : 'ies'}`);
|
|
207
|
+
}
|
|
193
208
|
}
|
|
194
209
|
}
|
|
210
|
+
if (entries.length === 0)
|
|
211
|
+
continue;
|
|
212
|
+
if (!Array.isArray(config.hooks[event])) {
|
|
213
|
+
config.hooks[event] = [];
|
|
214
|
+
}
|
|
195
215
|
const alreadyWired = config.hooks[event].some((h) => typeof h?.command === 'string' && h.command.includes(marker));
|
|
196
216
|
if (alreadyWired) {
|
|
197
217
|
changes.push(`hooks.${event}: ${marker} already wired — skipped`);
|
package/dist/hooks/kiro-hooks.js
CHANGED
|
@@ -12,11 +12,15 @@
|
|
|
12
12
|
* understand. fs_write inputs use `path`, mapped to `file_path`.
|
|
13
13
|
* 2. PostToolUse carries `tool_response` (an object), not a `tool_output`
|
|
14
14
|
* string.
|
|
15
|
-
* 3. Hook stdout
|
|
16
|
-
* hookSpecificOutput JSON envelope
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
15
|
+
* 3. Hook stdout reaches the model's context ONLY on agentSpawn and
|
|
16
|
+
* userPromptSubmit (no hookSpecificOutput JSON envelope). preToolUse
|
|
17
|
+
* stdout is IGNORED — exit codes gate the tool call, and only exit-2
|
|
18
|
+
* stderr is shown to the LLM; postToolUse stdout is ignored too
|
|
19
|
+
* (kiro.dev/docs/cli/hooks, verified empirically 2026-07-13). So all
|
|
20
|
+
* context injection rides agentSpawn (rules up front at session start)
|
|
21
|
+
* and userPromptSubmit (periodic mid-session refresh, see
|
|
22
|
+
* emitRuleRefresh). Claude Code needs the search-enforcer dance for
|
|
23
|
+
* this; Kiro gets it for free.
|
|
20
24
|
*
|
|
21
25
|
* userPromptSubmit needs no adapter: Kiro sends { prompt, session_id, cwd },
|
|
22
26
|
* exactly what correction-detector expects — wire it directly.
|
|
@@ -26,6 +30,39 @@
|
|
|
26
30
|
* only assistant_response (no transcript file), so transcript-based failure
|
|
27
31
|
* detectors and session extraction don't run under Kiro.
|
|
28
32
|
*/
|
|
33
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
34
|
+
if (k2 === undefined) k2 = k;
|
|
35
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
36
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
37
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
38
|
+
}
|
|
39
|
+
Object.defineProperty(o, k2, desc);
|
|
40
|
+
}) : (function(o, m, k, k2) {
|
|
41
|
+
if (k2 === undefined) k2 = k;
|
|
42
|
+
o[k2] = m[k];
|
|
43
|
+
}));
|
|
44
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
45
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
46
|
+
}) : function(o, v) {
|
|
47
|
+
o["default"] = v;
|
|
48
|
+
});
|
|
49
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
50
|
+
var ownKeys = function(o) {
|
|
51
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
52
|
+
var ar = [];
|
|
53
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
54
|
+
return ar;
|
|
55
|
+
};
|
|
56
|
+
return ownKeys(o);
|
|
57
|
+
};
|
|
58
|
+
return function (mod) {
|
|
59
|
+
if (mod && mod.__esModule) return mod;
|
|
60
|
+
var result = {};
|
|
61
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
62
|
+
__setModuleDefault(result, mod);
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
})();
|
|
29
66
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
67
|
exports.normalizeKiroInput = normalizeKiroInput;
|
|
31
68
|
exports.handleKiroAgentSpawn = handleKiroAgentSpawn;
|
|
@@ -34,11 +71,12 @@ exports.handleKiroToolOutcome = handleKiroToolOutcome;
|
|
|
34
71
|
exports.handleKiroCapture = handleKiroCapture;
|
|
35
72
|
exports.handleKiroCaptureWorker = handleKiroCaptureWorker;
|
|
36
73
|
const child_process_1 = require("child_process");
|
|
74
|
+
const fs = __importStar(require("fs"));
|
|
75
|
+
const path = __importStar(require("path"));
|
|
37
76
|
const shared_1 = require("./shared");
|
|
38
77
|
const directives_1 = require("../shared/directives");
|
|
39
78
|
const memory_1 = require("../services/memory");
|
|
40
79
|
const config_1 = require("../services/config");
|
|
41
|
-
const rule_injector_1 = require("./rule-injector");
|
|
42
80
|
const tool_outcome_watcher_1 = require("./tool-outcome-watcher");
|
|
43
81
|
const correction_detector_1 = require("./correction-detector");
|
|
44
82
|
const memory_tools_1 = require("../mcp/tools/memory-tools");
|
|
@@ -98,7 +136,7 @@ function formatRulesForContext() {
|
|
|
98
136
|
* Standing instruction so the agent KNOWS it has persistent memory — and,
|
|
99
137
|
* critically, that capture happens via BACKGROUND HOOKS independent of the MCP
|
|
100
138
|
* tools. Under enterprise Kiro governance the claude-recall MCP server is
|
|
101
|
-
* dropped from the toolset, but the userPromptSubmit/
|
|
139
|
+
* dropped from the toolset, but the agentSpawn/userPromptSubmit/postToolUse
|
|
102
140
|
* hooks still write to and read from the local DB. Without the "even without
|
|
103
141
|
* the tools" clause the agent answers "I can't store that, I have no memory
|
|
104
142
|
* tools" — technically true of the TOOL, but false of the system, since the
|
|
@@ -155,22 +193,18 @@ async function handleKiroAgentSpawn(_input) {
|
|
|
155
193
|
}
|
|
156
194
|
}
|
|
157
195
|
/**
|
|
158
|
-
* preToolUse — just-in-time rule
|
|
159
|
-
*
|
|
160
|
-
*
|
|
196
|
+
* preToolUse — DEPRECATED no-op. This used to emit just-in-time rule
|
|
197
|
+
* injections, on the assumption that Kiro adds preToolUse stdout to context.
|
|
198
|
+
* It does not: preToolUse stdout is ignored — exit codes gate the tool call
|
|
199
|
+
* and only exit-2 stderr reaches the LLM (kiro.dev/docs/cli/hooks, verified
|
|
200
|
+
* empirically 2026-07-13) — so nothing this handler printed ever reached the
|
|
201
|
+
* model, while every emission was falsely recorded as an injection. Mid-session
|
|
202
|
+
* injection now rides userPromptSubmit (emitRuleRefresh). The handler stays
|
|
203
|
+
* registered so agent configs wired by older versions keep exiting 0;
|
|
204
|
+
* `kiro setup` no longer wires it and strips stale entries on re-run.
|
|
161
205
|
*/
|
|
162
|
-
async function handleKiroRuleInjector(
|
|
163
|
-
|
|
164
|
-
const normalized = normalizeKiroInput(input);
|
|
165
|
-
const context = await (0, rule_injector_1.computeInjection)(normalized?.tool_name ?? '', normalized?.tool_input ?? {}, '');
|
|
166
|
-
if (context) {
|
|
167
|
-
process.stdout.write(context + '\n');
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
catch (err) {
|
|
171
|
-
// Best-effort — never block the tool call
|
|
172
|
-
(0, shared_1.hookLog)(HOOK_NAME, `rule-injector error: ${(0, shared_1.safeErrorMessage)(err)}`);
|
|
173
|
-
}
|
|
206
|
+
async function handleKiroRuleInjector(_input) {
|
|
207
|
+
(0, shared_1.hookLog)(HOOK_NAME, 'kiro-rule-injector is deprecated (Kiro ignores preToolUse stdout) — no-op; re-run `claude-recall kiro setup` to unwire it');
|
|
174
208
|
}
|
|
175
209
|
/**
|
|
176
210
|
* postToolUse — outcome capture and Bash fix-pairing, delegated to the shared
|
|
@@ -184,6 +218,84 @@ async function handleKiroToolOutcome(input) {
|
|
|
184
218
|
(0, shared_1.hookLog)(HOOK_NAME, `tool-outcome error: ${(0, shared_1.safeErrorMessage)(err)}`);
|
|
185
219
|
}
|
|
186
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Mid-session rule refresh — the Kiro answer to long-session context loss.
|
|
223
|
+
* Rules enter context once at agentSpawn; when Kiro later compacts or rolls
|
|
224
|
+
* the conversation, they silently vanish and nothing re-injects them (Kiro has
|
|
225
|
+
* no post-compaction event, and preToolUse stdout is ignored — see
|
|
226
|
+
* handleKiroRuleInjector). userPromptSubmit stdout IS added to context
|
|
227
|
+
* same-turn, so every CLAUDE_RECALL_REFRESH_INTERVAL prompts (default 15,
|
|
228
|
+
* 0 disables) we re-emit the active rules from here.
|
|
229
|
+
*
|
|
230
|
+
* The prompt counter is per-session (keyed by session_id) in hook-state/;
|
|
231
|
+
* stale counter files are pruned on each session's first prompt.
|
|
232
|
+
*/
|
|
233
|
+
const DEFAULT_REFRESH_INTERVAL = 15;
|
|
234
|
+
const REFRESH_STATE_PREFIX = 'kiro-refresh-';
|
|
235
|
+
const REFRESH_STATE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
236
|
+
function refreshInterval() {
|
|
237
|
+
const raw = process.env.CLAUDE_RECALL_REFRESH_INTERVAL;
|
|
238
|
+
if (raw === undefined || raw.trim() === '')
|
|
239
|
+
return DEFAULT_REFRESH_INTERVAL;
|
|
240
|
+
const n = parseInt(raw, 10);
|
|
241
|
+
if (!Number.isFinite(n))
|
|
242
|
+
return DEFAULT_REFRESH_INTERVAL;
|
|
243
|
+
return n > 0 ? n : 0;
|
|
244
|
+
}
|
|
245
|
+
/** Increment the per-session prompt counter and return the new count. */
|
|
246
|
+
function bumpPromptCount(sessionId) {
|
|
247
|
+
const safeId = sessionId.replace(/[^a-zA-Z0-9_-]/g, '_') || 'default';
|
|
248
|
+
const file = path.join((0, shared_1.hookStateDir)(), `${REFRESH_STATE_PREFIX}${safeId}.json`);
|
|
249
|
+
let count = 0;
|
|
250
|
+
try {
|
|
251
|
+
count = JSON.parse(fs.readFileSync(file, 'utf8')).count ?? 0;
|
|
252
|
+
}
|
|
253
|
+
catch { /* first prompt of the session, or unreadable — start fresh */ }
|
|
254
|
+
count++;
|
|
255
|
+
fs.writeFileSync(file, JSON.stringify({ count, updated: Date.now() }));
|
|
256
|
+
if (count === 1)
|
|
257
|
+
pruneStaleRefreshState();
|
|
258
|
+
return count;
|
|
259
|
+
}
|
|
260
|
+
/** Best-effort removal of counter files from long-dead sessions. */
|
|
261
|
+
function pruneStaleRefreshState() {
|
|
262
|
+
try {
|
|
263
|
+
const dir = (0, shared_1.hookStateDir)();
|
|
264
|
+
const cutoff = Date.now() - REFRESH_STATE_MAX_AGE_MS;
|
|
265
|
+
for (const name of fs.readdirSync(dir)) {
|
|
266
|
+
if (!name.startsWith(REFRESH_STATE_PREFIX))
|
|
267
|
+
continue;
|
|
268
|
+
const p = path.join(dir, name);
|
|
269
|
+
try {
|
|
270
|
+
if (fs.statSync(p).mtimeMs < cutoff)
|
|
271
|
+
fs.unlinkSync(p);
|
|
272
|
+
}
|
|
273
|
+
catch { /* another process won the race — fine */ }
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch { /* pruning is housekeeping, never let it interfere */ }
|
|
277
|
+
}
|
|
278
|
+
function emitRuleRefresh(input) {
|
|
279
|
+
try {
|
|
280
|
+
const interval = refreshInterval();
|
|
281
|
+
if (interval === 0)
|
|
282
|
+
return;
|
|
283
|
+
const count = bumpPromptCount(String(input?.session_id ?? 'default'));
|
|
284
|
+
if (count % interval !== 0)
|
|
285
|
+
return;
|
|
286
|
+
const rules = formatRulesForContext();
|
|
287
|
+
if (!rules.body)
|
|
288
|
+
return;
|
|
289
|
+
process.stdout.write(`🔄 Recall: periodic rule refresh (prompt ${count} this session). ` +
|
|
290
|
+
'Earlier rule injections may have been compacted out of your context — continue applying these:\n\n' +
|
|
291
|
+
rules.body + '\n');
|
|
292
|
+
(0, shared_1.hookLog)(HOOK_NAME, `refresh: re-injected ${rules.total} rule(s) at prompt ${count} (interval ${interval})`);
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
// The refresh is an enhancement — never let it break capture
|
|
296
|
+
(0, shared_1.hookLog)(HOOK_NAME, `refresh error: ${(0, shared_1.safeErrorMessage)(err)}`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
187
299
|
/**
|
|
188
300
|
* userPromptSubmit — the synchronous gate Kiro waits on. Under Kiro there is no
|
|
189
301
|
* ANTHROPIC_API_KEY, so classification uses Kiro's own headless LLM
|
|
@@ -195,8 +307,12 @@ async function handleKiroToolOutcome(input) {
|
|
|
195
307
|
* it over stdin, and returns in milliseconds. The worker performs the slow Kiro
|
|
196
308
|
* classify call and stores the memory in the background. Same pattern as
|
|
197
309
|
* session-end-checkpoint. See docs/kiro-llm-capture.md.
|
|
310
|
+
*
|
|
311
|
+
* It also owns the mid-session rule refresh (emitRuleRefresh above): the
|
|
312
|
+
* refresh must count EVERY prompt, so it runs before the capture pre-checks.
|
|
198
313
|
*/
|
|
199
314
|
async function handleKiroCapture(input) {
|
|
315
|
+
emitRuleRefresh(input);
|
|
200
316
|
const prompt = input?.prompt ?? '';
|
|
201
317
|
// Cheap pre-checks mirror correction-detector so we don't spawn a worker (and
|
|
202
318
|
// spend Kiro credits) on input that could never be stored.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Archived: the original Claude Recall launch article, published on LinkedIn by
|
|
3
|
+
Raoul Biagioni on August 7, 2025. Preserved verbatim as a historical record of
|
|
4
|
+
the project's origin. NOTE: it predates most of what Claude Recall is today —
|
|
5
|
+
Pi and Kiro support, the outcome-aware learning loop, LLM-based capture, the
|
|
6
|
+
no-API-key/subscription architecture — so treat it as origin story, not docs.
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# Why I Spent My Weekend Teaching a Goldfish-Brained AI to Remember
|
|
10
|
+
|
|
11
|
+
**Raoul Biagioni** — ♾️ AI Development Specialist | Agentic Engineer | Enabling AI-driven Business Innovation
|
|
12
|
+
|
|
13
|
+
*Published on LinkedIn, August 7, 2025*
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Claude Code forgets what you just told it. Not just between sessions. Even 10 messages into a conversation.
|
|
18
|
+
|
|
19
|
+
But what if it didn't?
|
|
20
|
+
|
|
21
|
+
## The Problem That Sparked a Solution
|
|
22
|
+
|
|
23
|
+
Over the past six months, I watched myself explain the same codebase preferences to Claude over and over again.
|
|
24
|
+
|
|
25
|
+
PostgreSQL for data. TypeScript strict mode. Tests directory for saving tests.
|
|
26
|
+
|
|
27
|
+
Not just in new sessions. Even 20 conversation turns later, as the context window fills up, Claude starts forgetting what we discussed at the beginning.
|
|
28
|
+
|
|
29
|
+
That's when I decided: Claude Code needs a memory.
|
|
30
|
+
|
|
31
|
+
## Building Claude Recall: A Memory That Actually Works
|
|
32
|
+
|
|
33
|
+
Sure, there are memory solutions out there. xmem requires an external vector database for storing memory. Mem0 (OpenMemory) needs Chrome extensions and API keys to connect across tools.
|
|
34
|
+
|
|
35
|
+
But I wanted something different: truly local, minimal dependencies, and built directly into Claude Code using MCP. No browser extensions. No vector DB setup. No API keys. Just `npm install claude-recall` and you're done.
|
|
36
|
+
|
|
37
|
+
Here's what I built in 72 hours of coding:
|
|
38
|
+
|
|
39
|
+
### 🧠 Smart Capture
|
|
40
|
+
|
|
41
|
+
- Hooks that watch every tool Claude uses (118-line robust implementation)
|
|
42
|
+
- Patterns detected automatically from your workflow
|
|
43
|
+
- Zero configuration needed
|
|
44
|
+
|
|
45
|
+
### ⚡ Smart Retrieval
|
|
46
|
+
|
|
47
|
+
- MCP server provides memory tools directly to Claude
|
|
48
|
+
- Pattern-based intent detection from natural language
|
|
49
|
+
- Context-aware memory filtering and relevance scoring
|
|
50
|
+
|
|
51
|
+
### 🔧 The Tech Stack
|
|
52
|
+
|
|
53
|
+
Claude Recall consists of three main components: A JavaScript hook that intercepts Claude's tool usage (file reads, bash commands, etc.), a Node.js MCP server to expose memory search and retrieval tools to Claude, and a SQLite database that stores captured patterns and preferences locally.
|
|
54
|
+
|
|
55
|
+
When Claude performs an action, the hook captures it and sends it to the pattern detector. The detector uses regex-based pattern matching to identify things like file locations, tool preferences, and coding styles with confidence scores. Patterns scoring above 0.8 are stored in SQLite. During Claude sessions, the MCP server provides tools that Claude can call to search and retrieve these stored memories based on context and relevance scoring.
|
|
56
|
+
|
|
57
|
+
## Real Results From Real Conversations
|
|
58
|
+
|
|
59
|
+
**Before Claude Recall (message #25 in same chat):**
|
|
60
|
+
|
|
61
|
+
- "What database do we use?" → Claude searches everywhere
|
|
62
|
+
- "Where's the auth logic?" → Claude searches everywhere
|
|
63
|
+
- "Write a test" → Claude saves the test in the project root
|
|
64
|
+
|
|
65
|
+
**After Claude Recall (message #100, still remembers):**
|
|
66
|
+
|
|
67
|
+
- "What database do we use?" → "PostgreSQL, as always"
|
|
68
|
+
- "Where's the auth logic?" → "src/services/auth.ts:42"
|
|
69
|
+
- "Write a test" → Claude saves the test in tests/
|
|
70
|
+
|
|
71
|
+
## The Reality Check
|
|
72
|
+
|
|
73
|
+
I'm conscious that in the fast-evolving GenAI ecosystem, many projects are quickly destined to oblivion. I have no doubt that the problem I described and solved for myself will be solved better by someone else soon. But here's the thing: I had an absolute blast building Claude Recall with the help of Claude Code by Anthropic, and the amazing AI Orchestration Platform Claude-Flow by Reuven Cohen from Agentics Foundation.
|
|
74
|
+
|
|
75
|
+
Sometimes the best tools are the ones you build for yourself, not because they'll change the world, but because they solve your specific problem right now.
|
|
76
|
+
|
|
77
|
+
> 💡 **Key Takeaway:** We're living in the stone age of AI assistants. They're powerful but goldfish-brained — forgetting context even within the same conversation. That changes now.
|
|
78
|
+
|
|
79
|
+
🔗 Link: in the comments.
|
|
80
|
+
|
|
81
|
+
💬 Question for you: What's the ONE thing you wish your AI assistant would remember?
|
|
82
|
+
|
|
83
|
+
#AITools #DeveloperProductivity #OpenSource #ClaudeAI
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
DRAFT v2 — reader-first rewrite of the one-year follow-up (July 2026).
|
|
3
|
+
v1 (deleted) was structured around the author's broken-promise confession;
|
|
4
|
+
this version is structured around what the READER gets: three things they can
|
|
5
|
+
check/fix about their own agent's memory today, whether or not they install
|
|
6
|
+
anything. The tool enters late, the "when NOT to bother" section is explicit,
|
|
7
|
+
and the CTA offers a fair trade (2 commands, 1 week, reversible) for honest
|
|
8
|
+
answers to: does it work / am I over-promising / is it worth it at all.
|
|
9
|
+
Facts verified against v0.33.0 on 2026-07-10: write-time dedup (live-tested),
|
|
10
|
+
prune-on-boot, demotion (manual/opt-in — hence "can demote"), Kiro→CC shared
|
|
11
|
+
DB (live-tested), claude -p key-over-subscription precedence (live-tested).
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
# Your Coding Agent Finally Has Memory. Here's Where It Still Fails You.
|
|
15
|
+
|
|
16
|
+
**Raoul Biagioni** — *Draft v2, July 2026*
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
You've told your coding agent "use pnpm, not npm" at least five times. This year that was finally supposed to stop: Claude Code now ships auto-memory, on by default. It watches your corrections and writes itself notes.
|
|
21
|
+
|
|
22
|
+
Genuinely good. I build in this space and I'll say it plainly: for a lot of people, the built-in memory is enough.
|
|
23
|
+
|
|
24
|
+
But if you live in a coding agent daily, there are three failure modes it leaves wide open — and you'll hit all three without ever getting an error message. Whether or not you try my tool, you'll want to know they exist.
|
|
25
|
+
|
|
26
|
+
## 1. Agent memory rots — silently
|
|
27
|
+
|
|
28
|
+
Built-in memory is great for the first twenty sessions. Then the notes pile up: contradictory entries, "yesterday" written three weeks ago, fixes referencing files you've deleted. Past a point, your agent isn't remembering — it's confidently misremembering, and stale notes are worse than no notes, because you don't think to double-check something the agent states as known fact.
|
|
29
|
+
|
|
30
|
+
**Check it yourself today:** open your project's auto-memory file and read what your agent believes about your codebase. If you've been at it more than a month, I'd bet money something in there is wrong.
|
|
31
|
+
|
|
32
|
+
## 2. Your corrections don't travel
|
|
33
|
+
|
|
34
|
+
Correct Claude Code on Tuesday; Kiro makes the same mistake on Friday. Every agent keeps its own notebook, so a team (or a person) using more than one agent re-teaches every preference once per tool. The more agents you run, the more your corrections fragment.
|
|
35
|
+
|
|
36
|
+
## 3. Your exported API key may be quietly paying for things
|
|
37
|
+
|
|
38
|
+
This one surprised me, and it generalizes beyond memory tools: **if you have `ANTHROPIC_API_KEY` exported for some other tool, `claude -p` — and anything built on it — will silently bill that key instead of your Claude subscription.** Two wallets, one of them draining without you deciding anything. Audit your environment; you may be paying twice for AI you already subscribe to.
|
|
39
|
+
|
|
40
|
+
## What I built against these
|
|
41
|
+
|
|
42
|
+
A year ago I wrote here about giving my "goldfish-brained" agent a memory. That tool, Claude Recall, has since become specifically an answer to the three problems above:
|
|
43
|
+
|
|
44
|
+
- **Anti-rot:** it de-duplicates on write, prunes on every boot, and can demote rules that stop earning their keep — designed for session 200, not session 5.
|
|
45
|
+
- **One brain, every agent:** a single local SQLite file shared by Claude Code, Pi, and Kiro. Correct one agent; the others apply it.
|
|
46
|
+
- **Never your API key:** it runs on the login your agent already has (Claude subscription, Kiro credits). An exported key is untouched unless you explicitly opt in.
|
|
47
|
+
|
|
48
|
+
Local, no cloud, no telemetry, and you can read every stored memory with one command — or wipe them.
|
|
49
|
+
|
|
50
|
+
Setup is two commands: `npm install -g claude-recall`, then one setup command per project. Uninstalling is one.
|
|
51
|
+
|
|
52
|
+
## When you should NOT bother
|
|
53
|
+
|
|
54
|
+
Fair is fair: if you use a single agent, a couple of sessions a week, on one or two projects — the built-in memory is probably enough for you. Don't install another tool for a problem you don't feel.
|
|
55
|
+
|
|
56
|
+
## What I'm asking — and what you get
|
|
57
|
+
|
|
58
|
+
Here's the trade. I built this for myself, which means I genuinely don't know if it holds up in your workflow. So if the three failure modes above sound familiar, run it for a week next to the built-in memory and tell me the truth:
|
|
59
|
+
|
|
60
|
+
1. **Does it work as expected** — right things captured, surfaced at the right moment?
|
|
61
|
+
2. **Am I over-promising** — where does this article outrun your actual experience?
|
|
62
|
+
3. **Is it worth it at all** — or is the built-in memory quietly good enough?
|
|
63
|
+
|
|
64
|
+
What you get in return: a memory that survives, travels, and never touches your key — if I'm right. And if I'm wrong, you've spent two commands finding out, and your feedback directly decides what gets built next. Either answer is useful to me; only one of us is guessing right now.
|
|
65
|
+
|
|
66
|
+
Link and quick-start in the comments. Tell me which of the three failure modes you've hit.
|
|
67
|
+
|
|
68
|
+
#AITools #DeveloperProductivity #OpenSource #ClaudeAI #AIMemory
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Tight LinkedIn version (~430 words) of docs/2026-07-follow-up-article-draft.md
|
|
3
|
+
(reader-first v2). Same three failure modes, same honest opt-out, same CTA —
|
|
4
|
+
compressed for feed reading. Not yet published.
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# Your Coding Agent Finally Has Memory. Here's Where It Still Fails You.
|
|
8
|
+
|
|
9
|
+
Claude Code ships auto-memory, on by default. Your agent watches your corrections, writes itself notes, and remembers them next session.
|
|
10
|
+
|
|
11
|
+
Genuinely good. For many people it's enough.
|
|
12
|
+
|
|
13
|
+
But if you live in a coding agent daily, it leaves three failure modes wide open — and you'll hit all three without ever seeing an error.
|
|
14
|
+
|
|
15
|
+
**1. Agent memory rots — silently.**
|
|
16
|
+
Great for twenty sessions. Then the notes pile up: contradictions, "yesterday" written three weeks ago, fixes referencing deleted files — and only the first 200 lines even load at startup. Your agent stops remembering and starts confidently *mis*remembering. Anthropic knows: they shipped a periodic cleanup pass ("Auto Dream") for exactly this — a tidy-up of the same self-written notes, so a wrong note that reads plausibly stays believed. Check it yourself: open your auto-memory file and read what your agent believes about your codebase. To be clear, *no* memory system captures perfectly — mine included. The real question is what happens to the mistakes afterwards: dedup, pruning, retiring rules that stop earning their keep — or nothing.
|
|
17
|
+
|
|
18
|
+
**2. Your corrections don't travel.**
|
|
19
|
+
Correct Claude Code on Tuesday; Kiro repeats the mistake on Friday. Every agent keeps its own notebook, so every preference gets re-taught once per tool.
|
|
20
|
+
|
|
21
|
+
**3. Your exported API key may be quietly paying for things.**
|
|
22
|
+
If `ANTHROPIC_API_KEY` is exported for some other tool, headless Claude (`claude -p` — and every script or hook built on it) bills that key instead of your Claude subscription. Not a bug: Anthropic's docs say the env key *"takes precedence over subscription authentication"* — the interactive app asks you which to use; automation doesn't ask. Two wallets, one draining without you deciding anything. Audit your env.
|
|
23
|
+
|
|
24
|
+
**Claude Recall** — my open-source memory engine for coding agents — is built specifically against these three.
|
|
25
|
+
|
|
26
|
+
Some of you saw me launch it here last summer as a weekend hack: Claude-Code-only, regex-based capture, held together with enthusiasm. Today's version (v0.33) is a different animal — same local-first idea, now grown into what the weekend hack couldn't be:
|
|
27
|
+
|
|
28
|
+
▸ **Anti-rot:** de-duplicates on write, prunes on every boot, can demote rules that stop earning their keep. Built for session 200, not session 5.
|
|
29
|
+
▸ **One brain, every agent:** a single local SQLite file shared by Claude Code, Pi, and Kiro. Correct one; the others apply it.
|
|
30
|
+
▸ **Never your API key:** runs on the login your agent already has. Your key is untouched unless you explicitly opt in.
|
|
31
|
+
|
|
32
|
+
Local. No cloud. No telemetry. Two commands to install; one to remove.
|
|
33
|
+
|
|
34
|
+
**When NOT to bother:** one agent, a few sessions a week, one or two projects → the built-in memory is probably enough. Don't install a tool for a problem you don't feel.
|
|
35
|
+
|
|
36
|
+
**The ask.** I built this for myself — I genuinely don't know if it holds up in *your* workflow. If the three failure modes sound familiar: run it for a week next to the built-in memory and tell me the truth.
|
|
37
|
+
|
|
38
|
+
1. Does it work as expected?
|
|
39
|
+
2. Am I over-promising?
|
|
40
|
+
3. Is it worth it at all — or is built-in quietly enough?
|
|
41
|
+
|
|
42
|
+
Either answer is useful. Only one of us is guessing right now.
|
|
43
|
+
|
|
44
|
+
Link in the comments. Which of the three have you hit?
|
|
45
|
+
|
|
46
|
+
#AITools #DeveloperProductivity #OpenSource #ClaudeAI #AIMemory
|
package/docs/kiro.md
CHANGED
|
@@ -30,7 +30,7 @@ and inside the Kiro chat, switch to the agent:
|
|
|
30
30
|
/agent swap recall
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
You get: active rules injected into context automatically at agent start (no tool call needed),
|
|
33
|
+
You get: active rules injected into context automatically at agent start (no tool call needed), a periodic mid-session rule refresh (see below), automatic capture of corrections/preferences from your prompts, tool-outcome tracking with Bash fix-pairing, and the full MCP tool surface (read-only tools pre-approved).
|
|
34
34
|
|
|
35
35
|
### Merging into an agent you already use
|
|
36
36
|
|
|
@@ -40,7 +40,13 @@ Don't want to swap agents? Merge Claude Recall into your own:
|
|
|
40
40
|
claude-recall kiro setup --merge-into <agent-name>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
This finds the agent config (workspace `.kiro/agents/` first, then `~/.kiro/agents/`; `--global` to target the global one directly), writes a timestamped backup, and appends the claude-recall pieces — MCP server, pre-approved read-only tools, and the
|
|
43
|
+
This finds the agent config (workspace `.kiro/agents/` first, then `~/.kiro/agents/`; `--global` to target the global one directly), writes a timestamped backup, and appends the claude-recall pieces — MCP server, pre-approved read-only tools, and the three hooks (`agentSpawn`, `userPromptSubmit`, `postToolUse`) — while leaving your own config untouched. It only rewrites claude-recall's own entries: superseded ones from an older version are swapped for the current wiring (any unrelated hook you have on the same event is preserved). Idempotent: on an already-current agent, re-running changes nothing. If the agent restricts tools with an explicit list, `@claude-recall` is added to it.
|
|
44
|
+
|
|
45
|
+
### Mid-session rule refresh (long sessions)
|
|
46
|
+
|
|
47
|
+
Rules enter context once, at agent start. In a long session Kiro eventually compacts or rolls the conversation and the rules silently vanish — Kiro exposes no post-compaction event to re-inject them (Claude Code has one, and claude-recall uses it there). So under Kiro, claude-recall re-injects the active rules **every 15 prompts** via the `userPromptSubmit` hook, whose stdout Kiro adds directly to context. Tune or disable with `CLAUDE_RECALL_REFRESH_INTERVAL` (`0` = off).
|
|
48
|
+
|
|
49
|
+
> **Note for configs wired by ≤0.33:** older versions also added a `preToolUse` rule injector. Kiro ignores `preToolUse` stdout — exit codes gate the tool call, and only exit-2 stderr reaches the model ([kiro.dev/docs/cli/hooks](https://kiro.dev/docs/cli/hooks)) — so that hook never actually injected anything. It is now a harmless no-op; re-run `claude-recall kiro setup --merge-into <agent>` once and the stale entry is stripped automatically.
|
|
44
50
|
|
|
45
51
|
---
|
|
46
52
|
|
package/package.json
CHANGED