@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.
Files changed (58) hide show
  1. package/README.md +8 -5
  2. package/bin/cmk-auto-extract.mjs +13 -0
  3. package/bin/cmk-capture-prompt.mjs +0 -0
  4. package/bin/cmk-capture-turn.mjs +0 -0
  5. package/bin/cmk-compress-session.mjs +31 -17
  6. package/bin/cmk-inject-context.mjs +12 -2
  7. package/bin/cmk-observe-edit.mjs +0 -0
  8. package/bin/cmk-weekly-curate.mjs +14 -2
  9. package/package.json +3 -2
  10. package/src/audit-log.mjs +6 -0
  11. package/src/auto-drain.mjs +59 -0
  12. package/src/auto-extract.mjs +117 -6
  13. package/src/auto-persona.mjs +544 -0
  14. package/src/bullet-lookup.mjs +59 -0
  15. package/src/capture-turn.mjs +54 -0
  16. package/src/compress-session.mjs +6 -8
  17. package/src/compressor.mjs +37 -22
  18. package/src/conflict-queue.mjs +8 -1
  19. package/src/daily-distill.mjs +19 -11
  20. package/src/doctor.mjs +79 -26
  21. package/src/forget.mjs +14 -0
  22. package/src/graduate-session.mjs +65 -0
  23. package/src/graduation.mjs +179 -0
  24. package/src/index-rebuild.mjs +26 -4
  25. package/src/inject-context.mjs +352 -65
  26. package/src/install.mjs +52 -7
  27. package/src/lessons-promote.mjs +137 -0
  28. package/src/mcp-server.mjs +17 -0
  29. package/src/memory-write.mjs +20 -7
  30. package/src/native-memory.mjs +98 -0
  31. package/src/persona-portability.mjs +253 -0
  32. package/src/provenance.mjs +23 -5
  33. package/src/read-hook-stdin.mjs +47 -0
  34. package/src/register-crons.mjs +17 -8
  35. package/src/sanitize.mjs +39 -0
  36. package/src/scratchpad.mjs +247 -19
  37. package/src/session-end-tasks.mjs +127 -0
  38. package/src/settings-hooks.mjs +33 -3
  39. package/src/spawn-bin.mjs +83 -0
  40. package/src/subcommands.mjs +472 -26
  41. package/src/weekly-curate.mjs +53 -6
  42. package/src/write-fact.mjs +60 -3
  43. package/template/.claude/skills/memory-write/SKILL.md +47 -88
  44. package/template/.gitignore.fragment +6 -0
  45. package/template/CLAUDE.md.template +17 -7
  46. package/template/local/machine-paths.md.template +1 -12
  47. package/template/local/overrides.md.template +1 -11
  48. package/template/project/MEMORY.md.template +5 -26
  49. package/template/project/SOUL.md.template +1 -10
  50. package/template/user/fragments/INDEX.md.template +1 -1
  51. package/template/.claude/hooks/pre-tool-memory.js +0 -78
  52. package/template/.claude/hooks/transcript-capture.js +0 -69
  53. package/template/.claude/settings.json +0 -27
  54. package/template/support/scripts/auto-extract-memory.sh +0 -102
  55. package/template/support/scripts/refresh-distill-timestamp.py +0 -35
  56. package/template/support/scripts/register-crons.py +0 -242
  57. package/template/support/scripts/run-daily-distill.sh +0 -67
  58. 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
+ }