dude-claude-plugin 2026.2.2 → 2026.2.5
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-plugin/plugin.json +3 -3
- package/bin/dude-claude.js +13 -3
- package/hooks.json +4 -4
- package/package.json +1 -1
- package/src/db.js +10 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dude-claude-plugin",
|
|
3
|
-
"version": "2026.2.
|
|
3
|
+
"version": "2026.2.3",
|
|
4
4
|
"description": "Ultra-minimal RAG and cross-project memory for Claude CLI",
|
|
5
5
|
"author": { "name": "Fingerskier" },
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"hooks": "./hooks.json",
|
|
9
9
|
"mcpServers": {
|
|
10
10
|
"dude": {
|
|
11
|
-
"command": "
|
|
12
|
-
"args": ["
|
|
11
|
+
"command": "npx",
|
|
12
|
+
"args": ["-y", "dude-claude-plugin", "mcp"]
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
}
|
package/bin/dude-claude.js
CHANGED
|
@@ -13,11 +13,21 @@ switch (command) {
|
|
|
13
13
|
await startWebServer();
|
|
14
14
|
break;
|
|
15
15
|
}
|
|
16
|
+
case 'auto-retrieve': {
|
|
17
|
+
await import('../hooks/auto-retrieve.js');
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
case 'auto-persist': {
|
|
21
|
+
await import('../hooks/auto-persist.js');
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
16
24
|
default:
|
|
17
|
-
console.error(`Usage: dude-claude [mcp|serve]
|
|
25
|
+
console.error(`Usage: dude-claude [mcp|serve|auto-retrieve|auto-persist]
|
|
18
26
|
|
|
19
27
|
Commands:
|
|
20
|
-
mcp
|
|
21
|
-
serve
|
|
28
|
+
mcp Start the MCP stdio server (default)
|
|
29
|
+
serve Start the web UI server on http://127.0.0.1:${process.env.DUDE_PORT || 3456}
|
|
30
|
+
auto-retrieve Run the auto-retrieve hook (reads prompt from stdin)
|
|
31
|
+
auto-persist Run the auto-persist hook (reads classification from stdin)`);
|
|
22
32
|
process.exit(1);
|
|
23
33
|
}
|
package/hooks.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"hooks": [
|
|
6
6
|
{
|
|
7
7
|
"type": "command",
|
|
8
|
-
"command": "
|
|
9
|
-
"timeout":
|
|
8
|
+
"command": "npx -y dude-claude-plugin auto-retrieve",
|
|
9
|
+
"timeout": 60
|
|
10
10
|
}
|
|
11
11
|
]
|
|
12
12
|
}
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"hooks": [
|
|
17
17
|
{
|
|
18
18
|
"type": "command",
|
|
19
|
-
"command": "
|
|
20
|
-
"timeout":
|
|
19
|
+
"command": "npx -y dude-claude-plugin auto-persist",
|
|
20
|
+
"timeout": 60
|
|
21
21
|
}
|
|
22
22
|
]
|
|
23
23
|
}
|
package/package.json
CHANGED
package/src/db.js
CHANGED
|
@@ -6,6 +6,11 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
6
6
|
import Database from 'better-sqlite3';
|
|
7
7
|
import * as sqliteVec from 'sqlite-vec';
|
|
8
8
|
|
|
9
|
+
/** Convert a Float32Array embedding to a Node.js Buffer for sqlite-vec binding. */
|
|
10
|
+
function embeddingBuffer(emb) {
|
|
11
|
+
return Buffer.from(emb.buffer, emb.byteOffset, emb.byteLength);
|
|
12
|
+
}
|
|
13
|
+
|
|
9
14
|
const DATA_DIR = join(homedir(), '.dude-claude');
|
|
10
15
|
const DB_PATH = join(DATA_DIR, 'dude.db');
|
|
11
16
|
|
|
@@ -174,7 +179,7 @@ export function searchRecords(embedding, { kind, projectId, limit = 5 } = {}) {
|
|
|
174
179
|
JOIN project p ON r.project_id = p.id
|
|
175
180
|
WHERE re.embedding MATCH ? AND k = ?
|
|
176
181
|
`;
|
|
177
|
-
const params = [new Float32Array(embedding)
|
|
182
|
+
const params = [embeddingBuffer(new Float32Array(embedding)), limit * 3]; // over-fetch for filtering
|
|
178
183
|
|
|
179
184
|
if (kind && kind !== 'all') {
|
|
180
185
|
sql += ' AND r.kind = ?';
|
|
@@ -217,7 +222,7 @@ export function upsertRecord({ id, projectId, kind, title, body = '', status = '
|
|
|
217
222
|
|
|
218
223
|
// vec0 doesn't support UPDATE — delete then insert
|
|
219
224
|
d.prepare('DELETE FROM record_embedding WHERE record_id = ?').run(id);
|
|
220
|
-
d.prepare('INSERT INTO record_embedding (record_id, embedding) VALUES (?, ?)').run(id, embedding
|
|
225
|
+
d.prepare('INSERT INTO record_embedding (record_id, embedding) VALUES (?, ?)').run(BigInt(id), embeddingBuffer(embedding));
|
|
221
226
|
|
|
222
227
|
return getRecord(id);
|
|
223
228
|
}
|
|
@@ -231,7 +236,7 @@ export function upsertRecord({ id, projectId, kind, title, body = '', status = '
|
|
|
231
236
|
AND r.project_id = ? AND r.kind = ?
|
|
232
237
|
ORDER BY re.distance
|
|
233
238
|
LIMIT 1
|
|
234
|
-
`).all(embedding
|
|
239
|
+
`).all(embeddingBuffer(embedding), proj, kind);
|
|
235
240
|
|
|
236
241
|
if (candidates.length > 0 && candidates[0].distance <= 0.15) {
|
|
237
242
|
// Close match found — update existing record
|
|
@@ -242,7 +247,7 @@ export function upsertRecord({ id, projectId, kind, title, body = '', status = '
|
|
|
242
247
|
`).run(title, body, status, now, existingId);
|
|
243
248
|
|
|
244
249
|
d.prepare('DELETE FROM record_embedding WHERE record_id = ?').run(existingId);
|
|
245
|
-
d.prepare('INSERT INTO record_embedding (record_id, embedding) VALUES (?, ?)').run(existingId, embedding
|
|
250
|
+
d.prepare('INSERT INTO record_embedding (record_id, embedding) VALUES (?, ?)').run(BigInt(existingId), embeddingBuffer(embedding));
|
|
246
251
|
|
|
247
252
|
return getRecord(existingId);
|
|
248
253
|
}
|
|
@@ -254,7 +259,7 @@ export function upsertRecord({ id, projectId, kind, title, body = '', status = '
|
|
|
254
259
|
`).run(proj, kind, title, body, status, now, now);
|
|
255
260
|
|
|
256
261
|
const newId = result.lastInsertRowid;
|
|
257
|
-
d.prepare('INSERT INTO record_embedding (record_id, embedding) VALUES (?, ?)').run(newId, embedding
|
|
262
|
+
d.prepare('INSERT INTO record_embedding (record_id, embedding) VALUES (?, ?)').run(BigInt(newId), embeddingBuffer(embedding));
|
|
258
263
|
|
|
259
264
|
return getRecord(Number(newId));
|
|
260
265
|
}
|