@lh8ppl/claude-memory-kit 0.1.1 → 0.2.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 +8 -5
- package/bin/cmk-auto-extract.mjs +13 -0
- package/bin/cmk-capture-prompt.mjs +0 -0
- package/bin/cmk-capture-turn.mjs +0 -0
- package/bin/cmk-compress-session.mjs +31 -17
- package/bin/cmk-inject-context.mjs +12 -2
- package/bin/cmk-observe-edit.mjs +0 -0
- package/bin/cmk-weekly-curate.mjs +14 -2
- package/package.json +3 -2
- package/src/audit-log.mjs +6 -0
- package/src/auto-drain.mjs +59 -0
- package/src/auto-extract.mjs +117 -6
- package/src/auto-persona.mjs +544 -0
- package/src/bullet-lookup.mjs +59 -0
- package/src/capture-turn.mjs +54 -0
- package/src/compress-session.mjs +6 -8
- package/src/compressor.mjs +37 -22
- package/src/conflict-queue.mjs +8 -1
- package/src/daily-distill.mjs +19 -11
- package/src/doctor.mjs +79 -26
- package/src/forget.mjs +14 -0
- package/src/graduate-session.mjs +65 -0
- package/src/graduation.mjs +179 -0
- package/src/index-rebuild.mjs +26 -4
- package/src/inject-context.mjs +352 -65
- package/src/install.mjs +52 -7
- package/src/lessons-promote.mjs +137 -0
- package/src/mcp-server.mjs +17 -0
- package/src/memory-write.mjs +20 -7
- package/src/native-memory.mjs +98 -0
- package/src/persona-portability.mjs +253 -0
- package/src/provenance.mjs +23 -5
- package/src/read-hook-stdin.mjs +47 -0
- package/src/register-crons.mjs +17 -8
- package/src/sanitize.mjs +39 -0
- package/src/scratchpad.mjs +247 -19
- package/src/session-end-tasks.mjs +127 -0
- package/src/settings-hooks.mjs +33 -3
- package/src/spawn-bin.mjs +83 -0
- package/src/subcommands.mjs +472 -26
- package/src/weekly-curate.mjs +53 -6
- package/src/write-fact.mjs +60 -3
- package/template/.claude/skills/memory-write/SKILL.md +47 -88
- package/template/.gitignore.fragment +6 -0
- package/template/CLAUDE.md.template +17 -7
- package/template/local/machine-paths.md.template +1 -12
- package/template/local/overrides.md.template +1 -11
- package/template/project/MEMORY.md.template +5 -26
- package/template/project/SOUL.md.template +1 -10
- package/template/user/fragments/INDEX.md.template +1 -1
- package/template/.claude/hooks/pre-tool-memory.js +0 -78
- package/template/.claude/hooks/transcript-capture.js +0 -69
- package/template/.claude/settings.json +0 -27
- package/template/support/scripts/auto-extract-memory.sh +0 -102
- package/template/support/scripts/refresh-distill-timestamp.py +0 -35
- package/template/support/scripts/register-crons.py +0 -242
- package/template/support/scripts/run-daily-distill.sh +0 -67
- package/template/support/scripts/run-weekly-curate.sh +0 -58
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// spawn-bin.mjs — cross-platform subprocess spawning that AVOIDS the
|
|
2
|
+
// `shell:true` + args-array combination (self-test finding #4).
|
|
3
|
+
//
|
|
4
|
+
// Why this exists
|
|
5
|
+
// ---------------
|
|
6
|
+
// Spawning an npm-global bin (claude, memsearch, cmk-*) needs `shell:true` on
|
|
7
|
+
// Windows so the `.cmd` shim resolves through cmd.exe — Node won't auto-resolve
|
|
8
|
+
// `.cmd`/`.bat` without a shell (CVE-2024-27980 hardening). But `shell:true`
|
|
9
|
+
// WITH an args array is doubly bad:
|
|
10
|
+
// 1. Node emits DEP0190 ("passing args to a child process with shell:true …
|
|
11
|
+
// arguments are not escaped, only concatenated").
|
|
12
|
+
// 2. The args ARE concatenated unescaped, so a path containing a space
|
|
13
|
+
// (e.g. `--mcp-config C:\Users\First Last\…\empty-mcp.json` under tmpdir)
|
|
14
|
+
// is re-tokenized by cmd.exe and breaks parsing — silently failing
|
|
15
|
+
// auto-extract/compression for any Windows user whose profile has a space.
|
|
16
|
+
//
|
|
17
|
+
// The fix: never pass an args array together with shell:true.
|
|
18
|
+
// - POSIX: spawn(bin, args, {shell:false}) — Node resolves PATH directly and
|
|
19
|
+
// passes argv safely. No shell, no concatenation.
|
|
20
|
+
// - Windows: shell:true with a SINGLE pre-quoted command string (no args
|
|
21
|
+
// array) — clears DEP0190 and lets us quote each arg so spaces survive.
|
|
22
|
+
//
|
|
23
|
+
// The kit's spawn args are controlled (flags + filesystem paths, never
|
|
24
|
+
// user-supplied shell text), so cmd.exe double-quoting is sufficient: inside
|
|
25
|
+
// double-quotes cmd.exe treats &|<>^ as literal; `%` is the only residual
|
|
26
|
+
// special char and kit paths/flags never contain it.
|
|
27
|
+
|
|
28
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Quote one argument for a cmd.exe command line. Quotes args that contain a
|
|
32
|
+
* space or a double-quote, AND empty-string args (an unquoted empty arg would
|
|
33
|
+
* vanish and shift the next token into its value slot — the compressor passes
|
|
34
|
+
* `--allowed-tools ''`). Embedded double-quotes are doubled.
|
|
35
|
+
*/
|
|
36
|
+
function quoteWinArg(s) {
|
|
37
|
+
const str = String(s);
|
|
38
|
+
if (str === '' || /[\s"]/.test(str)) {
|
|
39
|
+
// Double embedded double-quotes, AND double any trailing backslash run so
|
|
40
|
+
// a quoted value ending in `\` (e.g. a directory path with a space) does
|
|
41
|
+
// NOT escape the closing quote — the classic Windows CommandLineToArgv /
|
|
42
|
+
// cmd.exe footgun (`"C:\dir\"` parses as `C:\dir"`).
|
|
43
|
+
const escaped = str.replace(/"/g, '""').replace(/(\\+)$/, '$1$1');
|
|
44
|
+
return `"${escaped}"`;
|
|
45
|
+
}
|
|
46
|
+
return str;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Build the single cmd.exe command string for a Windows `shell:true` spawn.
|
|
51
|
+
* Exported for direct unit testing of the quoting (platform-independent).
|
|
52
|
+
*/
|
|
53
|
+
export function winCommandLine(bin, args = []) {
|
|
54
|
+
return [bin, ...args].map(quoteWinArg).join(' ');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Spawn a bin cross-platform without ever pairing `shell:true` with an args
|
|
59
|
+
* array. `deps` allows tests to inject a recording spawn + force a platform:
|
|
60
|
+
* deps.spawnImpl — defaults to node:child_process spawn (compressor injects
|
|
61
|
+
* its own for the kill-chain / testability).
|
|
62
|
+
* deps.platform — defaults to process.platform.
|
|
63
|
+
* Returns whatever the spawn impl returns (a ChildProcess in production).
|
|
64
|
+
*/
|
|
65
|
+
export function spawnBin(bin, args = [], opts = {}, deps = {}) {
|
|
66
|
+
const { spawnImpl = spawn, platform = process.platform } = deps;
|
|
67
|
+
// spawn-discipline: ignore pass-through helper — timeout/kill is the
|
|
68
|
+
// caller's contract (compressor terminateSubprocess + setTimeout; doctor
|
|
69
|
+
// timeout:3500), not this wrapper's.
|
|
70
|
+
if (platform === 'win32') {
|
|
71
|
+
return spawnImpl(winCommandLine(bin, args), { ...opts, shell: true });
|
|
72
|
+
}
|
|
73
|
+
return spawnImpl(bin, args, { ...opts, shell: false });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Synchronous twin of spawnBin (for one-shot checks like `cmk doctor`'s memsearch probe). */
|
|
77
|
+
export function spawnBinSync(bin, args = [], opts = {}, deps = {}) {
|
|
78
|
+
const { spawnImpl = spawnSync, platform = process.platform } = deps;
|
|
79
|
+
if (platform === 'win32') {
|
|
80
|
+
return spawnImpl(winCommandLine(bin, args), { ...opts, shell: true });
|
|
81
|
+
}
|
|
82
|
+
return spawnImpl(bin, args, { ...opts, shell: false });
|
|
83
|
+
}
|