claude-recall 0.29.1 → 0.30.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/README.md +5 -4
- package/dist/cli/commands/kiro-commands.js +3 -1
- package/dist/hooks/shared.js +64 -19
- package/docs/kiro-llm-capture.md +8 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ You get: active rules injected into context automatically at agent start (no too
|
|
|
103
103
|
claude-recall kiro setup --merge-into <agent-name>
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
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 four hooks —
|
|
106
|
+
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 four hooks — 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.
|
|
107
107
|
|
|
108
108
|
> **⚠️ After `kiro setup` or `--merge-into`: start ONE fresh conversation per project (no `--resume`).** Kiro snapshots the agent config into each conversation **at creation** — `--resume` restores that snapshot and ignores agent-config changes made since. So conversations created *before* you wired claude-recall will **never** run its hooks, no matter how often you resume them or restart Kiro. Start one fresh conversation after wiring; every conversation created from then on carries the hooks, **including when resumed** (`--resume` works normally afterwards — this is a one-time rollover per project).
|
|
109
109
|
|
|
@@ -123,7 +123,7 @@ tail -5 ~/.claude-recall/hook-logs/hook-dispatcher.log
|
|
|
123
123
|
|
|
124
124
|
The log should show a `scope [...] → project=your-project` line; `claude-recall kiro doctor` gives a fuller health report.
|
|
125
125
|
|
|
126
|
-
> **Capture uses Kiro's own LLM — no API key needed.** To decide what's worth remembering, the capture hook classifies each prompt with Kiro's model via a headless `kiro-cli chat --no-interactive` call (through a bundled bare `claude-recall-classifier` agent). So natural statements like "my favourite color is green" are captured without any `ANTHROPIC_API_KEY` and without the `store_memory` MCP tool — which matters under enterprise governance that blocks the MCP server. It runs in a detached background worker, so your turn is never blocked; it spends ~0.06 Kiro credits per prompt.
|
|
126
|
+
> **Capture uses Kiro's own LLM — no API key needed.** To decide what's worth remembering, the capture hook classifies each prompt with Kiro's model via a headless `kiro-cli chat --no-interactive` call (through a bundled bare `claude-recall-classifier` agent). So natural statements like "my favourite color is green" are captured without any `ANTHROPIC_API_KEY` and without the `store_memory` MCP tool — which matters under enterprise governance that blocks the MCP server. It runs in a detached background worker, so your turn is never blocked; it spends ~0.06 Kiro credits per prompt. **Under Kiro the included LLM is used first even if you happen to have `ANTHROPIC_API_KEY` set** — so a key exported for other tools won't quietly spend your Anthropic credits. Order: Kiro's LLM → `ANTHROPIC_API_KEY` (if present) → regex; set `CLAUDE_RECALL_PREFER_API_KEY=1` to force your key first (e.g. for a stronger model you pay for). Tune the Kiro model with `CLAUDE_RECALL_KIRO_MODEL` (default `claude-haiku-4.5`). Details in [docs/kiro-llm-capture.md](docs/kiro-llm-capture.md).
|
|
127
127
|
|
|
128
128
|
**Option B — MCP tools only (no hooks, works in Kiro's default agent).**
|
|
129
129
|
|
|
@@ -175,7 +175,7 @@ Per-runtime notes:
|
|
|
175
175
|
|
|
176
176
|
- **Claude Code** — nothing else needed; registrations point at the `claude-recall` command, not a pinned path. If the release notes mention new or changed hooks (a `hooksVersion` bump), also re-run `claude-recall setup --install` in each active project — safe any time; a no-op when hooks are already current.
|
|
177
177
|
- **Pi** — run `pi update npm:claude-recall` and restart Pi.
|
|
178
|
-
- **Kiro CLI** —
|
|
178
|
+
- **Kiro CLI** — the agent config points at the `claude-recall` command, so the binary upgrade alone applies to hook *behaviour*. But when the release notes change the agent *template* (new hooks, the classifier agent, revised wiring — e.g. the **0.29.x** Kiro-LLM capture), re-run setup once so the agent picks it up: `claude-recall kiro setup --force` for the standalone `recall` agent, or `claude-recall kiro setup --merge-into <agent>` for an agent you merged into. That also writes the `claude-recall-classifier` agent and strips any superseded hooks. Then start one fresh conversation per project (the snapshot rollover above). `claude-recall kiro doctor` confirms the result.
|
|
179
179
|
|
|
180
180
|
> **Claude Code registered before v0.27.x?** Older versions auto-registered the MCP server with an `npx`-based command, which re-resolves the package on every server start and can be shadowed by stale project-local installs. Switch to the direct binary form (run in each affected project):
|
|
181
181
|
>
|
|
@@ -562,8 +562,9 @@ Runtime behavior can be tuned via environment variables. Defaults are chosen so
|
|
|
562
562
|
| Variable | Default | Effect |
|
|
563
563
|
| ---------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- |
|
|
564
564
|
| `CLAUDE_RECALL_DB_PATH` | `~/.claude-recall/` | Database directory. |
|
|
565
|
-
| `ANTHROPIC_API_KEY` | _(unset)_ |
|
|
565
|
+
| `ANTHROPIC_API_KEY` | _(unset)_ | LLM classification via Haiku. Not required — Claude Code provides it to its hooks, and under Kiro the included LLM is used instead (and is preferred even if this is set). Regex is the final fallback. |
|
|
566
566
|
| `CLAUDE_RECALL_KIRO_MODEL` | `claude-haiku-4.5` | Model for Kiro-LLM capture classification. Raise to `claude-sonnet-4.6` for steadier judgement at more credits. See [docs/kiro-llm-capture.md](docs/kiro-llm-capture.md). |
|
|
567
|
+
| `CLAUDE_RECALL_PREFER_API_KEY` | _(unset)_ | Under Kiro, force `ANTHROPIC_API_KEY`-based classification ahead of Kiro's included LLM (uses your Anthropic credits — e.g. for a stronger model). No effect under Claude Code. |
|
|
567
568
|
| `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. |
|
|
568
569
|
| `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`. |
|
|
569
570
|
| `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>`. |
|
|
@@ -480,7 +480,9 @@ class KiroCommands {
|
|
|
480
480
|
line('⚠', 'kiro-cli not on PATH — capture cannot reach Kiro\'s LLM and falls back to regex.');
|
|
481
481
|
}
|
|
482
482
|
if (process.env.ANTHROPIC_API_KEY) {
|
|
483
|
-
line('•',
|
|
483
|
+
line('•', process.env.CLAUDE_RECALL_PREFER_API_KEY
|
|
484
|
+
? 'ANTHROPIC_API_KEY set + CLAUDE_RECALL_PREFER_API_KEY — capture uses your key (your Anthropic credits) before the Kiro LLM.'
|
|
485
|
+
: 'ANTHROPIC_API_KEY is set but under Kiro the included LLM is used first, so it won\'t spend your Anthropic credits. Set CLAUDE_RECALL_PREFER_API_KEY to force the key.');
|
|
484
486
|
}
|
|
485
487
|
// --- Hook activity ---
|
|
486
488
|
console.log('\nRecent hook activity');
|
package/dist/hooks/shared.js
CHANGED
|
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.isConversationalNotRule = isConversationalNotRule;
|
|
36
37
|
exports.readStdin = readStdin;
|
|
37
38
|
exports.classifyContentRegex = classifyContentRegex;
|
|
38
39
|
exports.classifyContent = classifyContent;
|
|
@@ -90,6 +91,17 @@ const PREFERENCE_PATTERNS = [
|
|
|
90
91
|
// corrections ("no worries, that looks good").
|
|
91
92
|
const INTERROGATIVE_START = /^(do|does|did|can|could|would|should|shall|is|are|was|were|will|have|has|what|why|how|when|where|who|which)\b/i;
|
|
92
93
|
const PLEASANTRY_NO = /^no\s+(worries|problem|problems|prob|thanks|thank|rush|need|biggie|sweat|pressure)\b/i;
|
|
94
|
+
/**
|
|
95
|
+
* True when a prompt reads as conversation rather than a storable rule: it ends
|
|
96
|
+
* with a question mark, opens with an interrogative, or is a "no worries"-style
|
|
97
|
+
* pleasantry. Applied to EVERY classifier path (regex, Haiku, Kiro) — the LLMs
|
|
98
|
+
* otherwise trust their own judgement and have stored questions like "what
|
|
99
|
+
* memories do you have?" as preferences.
|
|
100
|
+
*/
|
|
101
|
+
function isConversationalNotRule(text) {
|
|
102
|
+
const trimmed = text.trim();
|
|
103
|
+
return trimmed.endsWith('?') || INTERROGATIVE_START.test(trimmed) || PLEASANTRY_NO.test(trimmed);
|
|
104
|
+
}
|
|
93
105
|
// Failure, devops, and project-knowledge patterns removed — single-keyword
|
|
94
106
|
// matches ("error", "git", "build") are too broad for regex. These types
|
|
95
107
|
// require context that only the LLM classifier can assess. When the LLM is
|
|
@@ -108,9 +120,8 @@ function readStdin() {
|
|
|
108
120
|
* Returns the highest-confidence match, prioritizing corrections > preferences.
|
|
109
121
|
*/
|
|
110
122
|
function classifyContentRegex(text) {
|
|
111
|
-
const trimmed = text.trim();
|
|
112
123
|
// Interrogatives and pleasantries are conversation, not rules
|
|
113
|
-
if (
|
|
124
|
+
if (isConversationalNotRule(text)) {
|
|
114
125
|
return null;
|
|
115
126
|
}
|
|
116
127
|
// Priority order: correction > preference > failure > devops > project-knowledge
|
|
@@ -132,26 +143,60 @@ function classifyContentRegex(text) {
|
|
|
132
143
|
return null;
|
|
133
144
|
}
|
|
134
145
|
/**
|
|
135
|
-
* Classify text content — LLM-first, regex fallback.
|
|
146
|
+
* Classify text content — LLM-first, regex fallback. No API key is ever
|
|
147
|
+
* required: each runtime brings its own LLM.
|
|
148
|
+
*
|
|
136
149
|
* Precedence:
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
150
|
+
* - Under Claude Code: Claude Haiku via ANTHROPIC_API_KEY (Claude Code
|
|
151
|
+
* provides this to its hooks) → regex.
|
|
152
|
+
* - Under Kiro (CLAUDE_RECALL_KIRO_CLASSIFIER set by the kiro-capture-worker):
|
|
153
|
+
* Kiro's own headless LLM (`kiro-cli chat --no-interactive`) → ANTHROPIC_
|
|
154
|
+
* API_KEY if present → regex. Kiro's included LLM is preferred so a stray
|
|
155
|
+
* key doesn't spend the user's Anthropic credits; CLAUDE_RECALL_PREFER_API_
|
|
156
|
+
* KEY flips the order. The Kiro call is ~3s, so it runs only from the
|
|
157
|
+
* detached worker, never inline. See docs/kiro-llm-capture.md.
|
|
143
158
|
*/
|
|
144
159
|
async function classifyContent(text) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
160
|
+
// Guard the LLM paths the same way the regex path is guarded: a question or
|
|
161
|
+
// pleasantry is conversation, never a rule. Haiku/Kiro don't apply this on
|
|
162
|
+
// their own and have stored prompts like "what memories do you have?".
|
|
163
|
+
if (isConversationalNotRule(text))
|
|
164
|
+
return null;
|
|
165
|
+
const result = await classifyContentInner(text);
|
|
166
|
+
// Reject if the classifier echoed a question instead of distilling a rule:
|
|
167
|
+
// a stored directive is declarative, so a '?' in the extract signals a
|
|
168
|
+
// conversational false positive (e.g. an LLM regurgitating the prompt).
|
|
169
|
+
if (result && result.extract.includes('?'))
|
|
170
|
+
return null;
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
async function classifyContentInner(text) {
|
|
174
|
+
const underKiro = !!process.env.CLAUDE_RECALL_KIRO_CLASSIFIER;
|
|
175
|
+
const preferApiKey = !!process.env.CLAUDE_RECALL_PREFER_API_KEY;
|
|
176
|
+
const tryApiKey = () => (0, llm_classifier_1.classifyWithLLM)(text);
|
|
177
|
+
// Dynamic import keeps kiro-classifier (and child_process) out of the module
|
|
178
|
+
// graph for every non-Kiro hook invocation.
|
|
179
|
+
const tryKiro = async () => (await Promise.resolve().then(() => __importStar(require('./kiro-classifier')))).classifyWithKiro(text);
|
|
180
|
+
// Order the two LLM backends. Under Kiro, prefer Kiro's INCLUDED LLM over a
|
|
181
|
+
// stray ANTHROPIC_API_KEY: a key exported for other tools should not silently
|
|
182
|
+
// spend the user's Anthropic credits when Kiro already ships an LLM. Set
|
|
183
|
+
// CLAUDE_RECALL_PREFER_API_KEY to force the key first (e.g. to use a stronger
|
|
184
|
+
// model you pay for). Under Claude Code the Kiro backend isn't available, so
|
|
185
|
+
// the key path is the only LLM classifier.
|
|
186
|
+
const backends = [];
|
|
187
|
+
if (underKiro && !preferApiKey) {
|
|
188
|
+
backends.push(tryKiro, tryApiKey);
|
|
189
|
+
}
|
|
190
|
+
else if (underKiro) {
|
|
191
|
+
backends.push(tryApiKey, tryKiro);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
backends.push(tryApiKey);
|
|
195
|
+
}
|
|
196
|
+
for (const backend of backends) {
|
|
197
|
+
const result = await backend();
|
|
198
|
+
if (result)
|
|
199
|
+
return result;
|
|
155
200
|
}
|
|
156
201
|
return classifyContentRegex(text);
|
|
157
202
|
}
|
package/docs/kiro-llm-capture.md
CHANGED
|
@@ -93,9 +93,13 @@ Kiro userPromptSubmit
|
|
|
93
93
|
└─ regex fallback (only if both above yield nothing)
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
Capture precedence under Kiro
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
Capture precedence under Kiro: **Kiro's included LLM → `ANTHROPIC_API_KEY` if
|
|
97
|
+
present → regex as a last resort.** The Kiro LLM comes first *even when a key is
|
|
98
|
+
set*, so a key exported for other tools never silently spends the user's
|
|
99
|
+
Anthropic credits — Kiro already ships an LLM. `CLAUDE_RECALL_PREFER_API_KEY=1`
|
|
100
|
+
flips the order back to key-first for anyone who deliberately wants to pay for a
|
|
101
|
+
stronger model. (Under Claude Code there is no Kiro backend, so the key path is
|
|
102
|
+
the only LLM classifier — Claude Code provides the key to its hooks.)
|
|
99
103
|
|
|
100
104
|
### Output parsing
|
|
101
105
|
|
|
@@ -112,6 +116,7 @@ returns `null`, degrading to regex — a hook must never throw.
|
|
|
112
116
|
| `CLAUDE_RECALL_KIRO_CLASSIFIER` | *(set by the worker)* | Enables the Kiro-LLM path in `classifyContent`. Set automatically by `kiro-capture-worker`; never needed by hand. |
|
|
113
117
|
| `CLAUDE_RECALL_KIRO_MODEL` | `claude-haiku-4.5` | Model for the classify call. Raise to `claude-sonnet-4.6` for steadier judgement at ~3× the credits. |
|
|
114
118
|
| `CLAUDE_RECALL_KIRO_LLM_TIMEOUT_MS` | `30000` | Hard cap on the headless call before the worker gives up and falls back to regex. |
|
|
119
|
+
| `CLAUDE_RECALL_PREFER_API_KEY` | *(unset)* | Force `ANTHROPIC_API_KEY`-based classification ahead of Kiro's included LLM (opt-in; uses your Anthropic credits). |
|
|
115
120
|
|
|
116
121
|
## Caveats
|
|
117
122
|
|
package/package.json
CHANGED