claude-recall 0.29.2 → 0.30.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
CHANGED
|
@@ -123,7 +123,11 @@ 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
|
|
126
|
+
> **Capture uses Kiro's own LLM — no API key needed.** To decide what's worth remembering, the capture hook classifies each prompt via a headless `kiro-cli chat --no-interactive --model …` 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.
|
|
127
|
+
>
|
|
128
|
+
> **The classifier uses a dedicated, fixed model — not your chat model.** It always runs the model in `CLAUDE_RECALL_KIRO_MODEL` (default `claude-haiku-4.5`, chosen because classification is cheap and high-volume), **independent of your interactive Kiro chat model** (e.g. `auto`). This keeps classification cost predictable no matter what your chat is set to. Set `CLAUDE_RECALL_KIRO_MODEL` to any model from `kiro-cli chat --list-models` to change it. Every successful classification is logged to `~/.claude-recall/hook-logs/kiro-classifier.log` as `classified via kiro-cli (model=…, Kiro credits, no API key)`, so you can always see which model ran.
|
|
129
|
+
>
|
|
130
|
+
> **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). Details in [docs/kiro-llm-capture.md](docs/kiro-llm-capture.md).
|
|
127
131
|
|
|
128
132
|
**Option B — MCP tools only (no hooks, works in Kiro's default agent).**
|
|
129
133
|
|
|
@@ -562,8 +566,9 @@ Runtime behavior can be tuned via environment variables. Defaults are chosen so
|
|
|
562
566
|
| Variable | Default | Effect |
|
|
563
567
|
| ---------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------- |
|
|
564
568
|
| `CLAUDE_RECALL_DB_PATH` | `~/.claude-recall/` | Database directory. |
|
|
565
|
-
| `ANTHROPIC_API_KEY` | _(unset)_ |
|
|
566
|
-
| `CLAUDE_RECALL_KIRO_MODEL` | `claude-haiku-4.5` |
|
|
569
|
+
| `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. |
|
|
570
|
+
| `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). |
|
|
571
|
+
| `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
572
|
| `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
573
|
| `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
574
|
| `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');
|
|
@@ -154,6 +154,15 @@ function classifyWithKiro(text) {
|
|
|
154
154
|
if (!result) {
|
|
155
155
|
(0, shared_1.hookLog)('kiro-classifier', 'no parseable classification in kiro-cli output');
|
|
156
156
|
}
|
|
157
|
+
else {
|
|
158
|
+
// Log success too, not just failures — otherwise a successful Kiro
|
|
159
|
+
// classification is silent and indistinguishable from "never ran",
|
|
160
|
+
// which makes "did the Kiro LLM handle this?" impossible to answer
|
|
161
|
+
// from the log. Spell out that this ran on Kiro credits (not the
|
|
162
|
+
// ANTHROPIC_API_KEY) using a dedicated classifier model — the `model`
|
|
163
|
+
// is CLAUDE_RECALL_KIRO_MODEL, independent of the interactive chat model.
|
|
164
|
+
(0, shared_1.hookLog)('kiro-classifier', `classified via kiro-cli (model=${model}, Kiro credits, no API key): ${result.type} — ${result.extract.slice(0, 60)}`);
|
|
165
|
+
}
|
|
157
166
|
done(result);
|
|
158
167
|
});
|
|
159
168
|
});
|
package/dist/hooks/shared.js
CHANGED
|
@@ -143,14 +143,18 @@ function classifyContentRegex(text) {
|
|
|
143
143
|
return null;
|
|
144
144
|
}
|
|
145
145
|
/**
|
|
146
|
-
* 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
|
+
*
|
|
147
149
|
* Precedence:
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
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.
|
|
154
158
|
*/
|
|
155
159
|
async function classifyContent(text) {
|
|
156
160
|
// Guard the LLM paths the same way the regex path is guarded: a question or
|
|
@@ -167,16 +171,32 @@ async function classifyContent(text) {
|
|
|
167
171
|
return result;
|
|
168
172
|
}
|
|
169
173
|
async function classifyContentInner(text) {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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;
|
|
180
200
|
}
|
|
181
201
|
return classifyContentRegex(text);
|
|
182
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
|
|
|
@@ -110,8 +114,9 @@ returns `null`, degrading to regex — a hook must never throw.
|
|
|
110
114
|
| Variable | Default | Effect |
|
|
111
115
|
| --- | --- | --- |
|
|
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
|
-
| `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. |
|
|
117
|
+
| `CLAUDE_RECALL_KIRO_MODEL` | `claude-haiku-4.5` | Model for the classify call, passed explicitly as `--model`. This is a **dedicated classifier model, independent of the user's interactive Kiro chat model** (e.g. `auto`) — the headless call always uses this value. 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