claude-launchpad 0.9.2-dev.3 → 0.10.1-dev.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 (31) hide show
  1. package/README.md +123 -113
  2. package/dist/chunk-7YDBTED2.js +154 -0
  3. package/dist/chunk-7YDBTED2.js.map +1 -0
  4. package/dist/chunk-J5NT4JGE.js +77 -0
  5. package/dist/chunk-J5NT4JGE.js.map +1 -0
  6. package/dist/{chunk-TALTTAMW.js → chunk-JXFTVFPC.js} +43 -3
  7. package/dist/chunk-JXFTVFPC.js.map +1 -0
  8. package/dist/{chunk-4AF3NGNF.js → chunk-YEGOHLE7.js} +3 -3
  9. package/dist/{chunk-JTKRLIEV.js → chunk-ZMSHFAZQ.js} +2 -1
  10. package/dist/cli.js +47 -90
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/memory/server.js +39 -75
  13. package/dist/commands/memory/server.js.map +1 -1
  14. package/dist/{context-AGNCZJPC.js → context-SGPGEJV4.js} +4 -4
  15. package/dist/{extract-RPRYPT3Z.js → extract-T32FMLN5.js} +4 -4
  16. package/dist/{install-PSSMUGLO.js → install-OKLYDFBJ.js} +2 -2
  17. package/dist/pull-4VKUDKTB.js +66 -0
  18. package/dist/pull-4VKUDKTB.js.map +1 -0
  19. package/dist/push-WI3ZIPZU.js +89 -0
  20. package/dist/push-WI3ZIPZU.js.map +1 -0
  21. package/dist/{stats-DAUYJ4BE.js → stats-77WLARNA.js} +4 -4
  22. package/dist/{tui-A4TJFNE3.js → tui-YV7AFJFR.js} +3 -3
  23. package/package.json +1 -1
  24. package/dist/chunk-TALTTAMW.js.map +0 -1
  25. /package/dist/{chunk-4AF3NGNF.js.map → chunk-YEGOHLE7.js.map} +0 -0
  26. /package/dist/{chunk-JTKRLIEV.js.map → chunk-ZMSHFAZQ.js.map} +0 -0
  27. /package/dist/{context-AGNCZJPC.js.map → context-SGPGEJV4.js.map} +0 -0
  28. /package/dist/{extract-RPRYPT3Z.js.map → extract-T32FMLN5.js.map} +0 -0
  29. /package/dist/{install-PSSMUGLO.js.map → install-OKLYDFBJ.js.map} +0 -0
  30. /package/dist/{stats-DAUYJ4BE.js.map → stats-77WLARNA.js.map} +0 -0
  31. /package/dist/{tui-A4TJFNE3.js.map → tui-YV7AFJFR.js.map} +0 -0
package/README.md CHANGED
@@ -4,106 +4,109 @@
4
4
  [![npm downloads](https://img.shields.io/npm/dm/claude-launchpad?style=flat-square)](https://www.npmjs.com/package/claude-launchpad)
5
5
  [![GitHub stars](https://img.shields.io/github/stars/mboss37/claude-launchpad?style=flat-square)](https://github.com/mboss37/claude-launchpad)
6
6
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/mboss37/claude-launchpad/blob/master/LICENSE)
7
+ ![macOS](https://img.shields.io/badge/macOS-supported-brightgreen?style=flat-square&logo=apple)
8
+ ![Linux](https://img.shields.io/badge/Linux-supported-brightgreen?style=flat-square&logo=linux)
9
+ ![Windows](https://img.shields.io/badge/Windows-untested-yellow?style=flat-square&logo=windows)
7
10
 
8
- **Score your Claude Code setup. Fix what's broken. Prove it works.**
11
+ **Score your Claude Code config. Fix it. Prove it works.**
9
12
 
10
- CLAUDE.md is advisory — Claude follows your rules ~80% of the time. Hooks are deterministic 100% compliance. But most developers have zero hooks and too many instructions. This tool gives you a number, fixes the gaps, and lets you prove Claude actually follows your config.
13
+ Claude Code follows CLAUDE.md about 80% of the time. Hooks run at 100%. Most developers have zero hooks and too many instructions. Claude Launchpad scores your setup, fixes the gaps, and tests that Claude actually follows your rules.
14
+
15
+ This is for developers using Claude Code who want consistent results: solo devs, vibe coders, AI-first teams. If you have ever wondered why Claude ignores half your CLAUDE.md, this is the fix.
16
+
17
+ ## Install and See Your Score
11
18
 
12
19
  ```bash
13
20
  npx claude-launchpad
14
21
  ```
15
22
 
16
- That's it. Run it in any project with Claude Code. You'll see a score out of 100 and a list of exactly what's wrong. Run `--fix` to auto-repair.
23
+ ```
24
+ Instruction Budget ━━━━━━━━━━━━━━━━━━━━ 100%
25
+ CLAUDE.md Quality ━━━━━━━━━━━━━━━━━━━━ 100%
26
+ Settings ━━━━━━━━━━━━━━━━━━━━ 100%
27
+ Hooks ━━━━━━━━━━━━━━━━━━━━ 100%
28
+ Rules ━━━━━━━━━━━━━━━━━━━━ 100%
29
+ Permissions ━━━━━━━━━━━━━━━━━━━━ 100%
30
+ MCP Servers ━━━━━━━━━━━━━━━━━━━━ 100%
31
+
32
+ Overall ━━━━━━━━━━━━━━━━━━━━ 100%
17
33
 
18
- Claude Launchpad has 4 CLI commands (`init`, `doctor`, `eval`, `memory`) plus 1 in-session skill (`/lp-enhance`). Memory is optional.
34
+ No issues found. Your configuration looks solid.
35
+ ```
19
36
 
20
- ## Two Paths, One Tool
37
+ A typical unconfigured project scores ~31%. After `--fix`, it jumps to ~91%.
38
+
39
+ ## Quick Start
21
40
 
22
- ### Starting a new project?
41
+ **New project:**
23
42
 
24
43
  ```bash
25
- claude-launchpad init
44
+ npx claude-launchpad init
26
45
  ```
27
46
 
28
- Detects your stack, generates `CLAUDE.md` with your commands and conventions, creates `TASKS.md` for tracking work across sessions, sets up hooks that auto-format code and block dangerous operations, and adds a `.claudeignore` so Claude skips `node_modules` and build artifacts.
47
+ Detects your stack, generates config, hooks, and permissions. Start at ~93%.
29
48
 
30
- Then use `/lp-enhance` inside Claude Code to have Claude read your actual codebase and fill in the architecture and guardrails — not boilerplate, real project-specific content.
31
-
32
- ### Already have a project?
49
+ **Existing project:**
33
50
 
34
51
  ```bash
35
- claude-launchpad
52
+ npx claude-launchpad doctor --fix
36
53
  ```
37
54
 
38
- Scans your Claude Code config, gives you a score out of 100, and tells you exactly what's wrong. Run `doctor --fix` to auto-apply deterministic fixes, then run `/lp-enhance` inside Claude Code to rewrite CLAUDE.md with project-specific guidance, then run `eval` to prove behavior.
55
+ Scores your config, auto-repairs everything it can.
39
56
 
40
- ## Command Model
57
+ ## The Three-File System
41
58
 
42
- | Command | What it does | Runs |
59
+ | File | Purpose | Example |
43
60
  |---|---|---|
44
- | `claude-launchpad init` | Detect stack, generate config, hooks, permissions | Locally |
45
- | `claude-launchpad` | Default entrypoint (routes to doctor when config exists) | Locally |
46
- | `claude-launchpad doctor --fix` | Auto-fix issues: hooks, rules, sections, .claudeignore | Locally |
47
- | `claude-launchpad doctor --watch` | Live score that updates when you save config files | Locally |
48
- | `/lp-enhance` (skill) | Claude reads your code and completes CLAUDE.md | Inside Claude Code |
49
- | `claude-launchpad eval` | Run Claude against test scenarios, prove config works | Via Claude CLI |
50
- | `claude-launchpad memory` | Optional memory setup (or stats) + installs `/lp-migrate-memory` skill | Locally |
51
- | `claude-launchpad memory --dashboard` | TUI dashboard for memory visualization | Locally |
61
+ | `CLAUDE.md` | What Claude needs to know | Stack, commands, conventions, guardrails |
62
+ | `TASKS.md` | What we're doing now | Current sprint, session log, progress |
63
+ | `BACKLOG.md` | What we're doing later | Parked features with P0/P1/P2 priority tiers |
52
64
 
53
- ## Quick Start
65
+ Without BACKLOG.md, deferred features get lost in conversation history or bloat TASKS.md. Init generates all three. Doctor checks for them. `--fix` creates any that are missing.
54
66
 
55
- ```bash
56
- cd your-project
57
- npx claude-launchpad # see your score
58
- npx claude-launchpad doctor --fix # fix everything
59
- ```
67
+ ## Commands
60
68
 
61
- A typical unconfigured project scores ~42%. After `--fix`, it jumps to ~86%. Run `init` on a fresh project and you start at ~93%.
69
+ | Command | What it does | Runs |
70
+ |---|---|---|
71
+ | `claude-launchpad` | Score your config (routes to doctor) | Locally, free |
72
+ | `claude-launchpad init` | Detect stack, generate config + hooks + permissions | Locally, free |
73
+ | `claude-launchpad doctor --fix` | Auto-fix issues found by doctor | Locally, free |
74
+ | `claude-launchpad eval` | Run Claude against test scenarios, score results | Via Claude CLI |
75
+ | `claude-launchpad memory` | Optional persistent memory system | Locally |
76
+ | `/lp-enhance` (skill) | Claude reads your code and completes CLAUDE.md | Inside Claude Code |
62
77
 
63
- ## The Doctor
78
+ ## Doctor
64
79
 
65
- The core of the tool. Runs 7 core analyzers against your `.claude/` directory and `CLAUDE.md` (plus an optional Memory analyzer when agentic memory is detected):
80
+ Runs 7 analyzers against your `.claude/` directory and CLAUDE.md. No API calls, no network, no cost.
81
+
82
+ **Analyzers:**
66
83
 
67
84
  | Analyzer | What it catches |
68
85
  |---|---|
69
- | **Instruction Budget** | Too many instructions in CLAUDE.md Claude starts ignoring rules past ~150 |
70
- | **CLAUDE.md Quality** | Missing sections (including Memory & Learnings), vague instructions ("write good code"), hardcoded secrets |
86
+ | **Instruction Budget** | Too many instructions. Claude starts ignoring rules past ~200. |
87
+ | **CLAUDE.md Quality** | Missing sections, vague instructions, hardcoded secrets |
71
88
  | **Settings** | No hooks configured, dangerous tool access without safety nets |
72
- | **Hooks** | Missing auto-format on save, no .env file protection, no security gates, no PostCompact hook |
89
+ | **Hooks** | Missing auto-format, no .env protection, no PostCompact hook |
73
90
  | **Rules** | Dead rule files, stale references, empty configs |
74
- | **Permissions** | Credential file exposure (~/.ssh, ~/.aws, ~/.npmrc), blanket Bash approval, bypass mode unprotected, sandbox disabled, .env gap between hooks and .claudeignore, no force-push protection |
91
+ | **Permissions** | Credential exposure (~/.ssh, ~/.aws), blanket Bash approval, sandbox disabled |
75
92
  | **MCP Servers** | Invalid transport configs, missing commands/URLs |
76
93
 
77
- Output looks like this:
94
+ An optional Memory analyzer runs when agentic memory is detected.
78
95
 
79
- ```
80
- Instruction Budget ━━━━━━━━━━━━━━━━━━━━ 100%
81
- CLAUDE.md Quality ━━━━━━━━━━━━━━━━━━━━ 100%
82
- Settings ━━━━━━━━━━━━━━━━━━━━ 100%
83
- Hooks ━━━━━━━━━━━━━━━━━━━━ 100%
84
- Rules ━━━━━━━━━━━━━━━━━━━━ 100%
85
- Permissions ━━━━━━━━━━━━━━━━━━━━ 100%
86
- MCP Servers ━━━━━━━━━━────────── 50%
87
-
88
- Overall ━━━━━━━━━━━━━━━━━━━─ 93%
89
-
90
- ✓ No issues found. Your configuration looks solid.
91
- ```
92
-
93
- **All doctor flags:**
96
+ **Flags:**
94
97
 
95
98
  | Flag | What it does |
96
99
  |---|---|
97
- | `--fix` | Auto-fixes issues: adds hooks, CLAUDE.md sections, rules, .claudeignore |
98
- | `--fix --dry-run` | Preview what --fix would change without applying |
99
- | `--watch` | Re-runs every second, updates when you save a config file |
100
- | `--json` | Pure JSON output, no colors, no banner — for scripts and CI |
101
- | `--min-score <n>` | Exit code 1 if score is below threshold use in CI to block bad configs |
100
+ | `--fix` | Auto-fix: adds hooks, CLAUDE.md sections, BACKLOG.md, rules, .claudeignore |
101
+ | `--fix --dry-run` | Preview fixes without applying them |
102
+ | `--watch` | Re-runs every second as you edit config files |
103
+ | `--json` | Pure JSON output for scripts and CI |
104
+ | `--min-score <n>` | Exit code 1 if score is below threshold (for CI) |
102
105
  | `-p, --path <dir>` | Run on a different directory |
103
106
 
104
107
  ## Init
105
108
 
106
- Detects your project and generates Claude Code config that fits. No templates, no menus — it reads your manifest files and figures it out.
109
+ Reads your manifest files (package.json, go.mod, pyproject.toml, etc.) and generates config that fits. No templates, no menus.
107
110
 
108
111
  ```
109
112
  → Detecting project...
@@ -112,74 +115,47 @@ Detects your project and generates Claude Code config that fits. No templates, n
112
115
 
113
116
  ✓ Generated CLAUDE.md
114
117
  ✓ Generated TASKS.md
118
+ ✓ Generated BACKLOG.md
115
119
  ✓ Generated .claude/settings.json (schema, permissions, hooks)
116
120
  ✓ Generated .claude/.gitignore
117
121
  ✓ Generated .claudeignore
118
122
  ✓ Generated .claude/rules/conventions.md
119
123
  ```
120
124
 
121
- **Works with:** TypeScript, JavaScript, Python, Go, Ruby, Rust, Dart, PHP, Java, Kotlin, Swift, Elixir, C# — and detects frameworks (Next.js, FastAPI, Django, Rails, Laravel, Express, SvelteKit, Angular, NestJS, and 15+ more).
122
-
123
125
  **What init writes:**
124
- - Always writes: `CLAUDE.md`, `TASKS.md`, `.claude/settings.json`
126
+ - Always: `CLAUDE.md`, `TASKS.md`, `BACKLOG.md`, `.claude/settings.json`
125
127
  - Creates when missing: `.claude/.gitignore`, `.claudeignore`, `.claude/rules/conventions.md`
126
- - Offers `/lp-enhance` install (project/global/skip) only when no project/global/legacy install already exists
128
+ - Offers `/lp-enhance` install (project/global/skip) if not already present
129
+
130
+ **Supported stacks:** TypeScript, JavaScript, Python, Go, Ruby, Rust, Dart, PHP, Java, Kotlin, Swift, Elixir, C#. Detects frameworks: Next.js, FastAPI, Django, Rails, Laravel, Express, SvelteKit, Angular, NestJS, and 15+ more.
127
131
 
128
132
  ## Enhance
129
133
 
130
- Init detects your stack but can't understand your architecture. The `/lp-enhance` skill runs inside your Claude Code session to read your actual code and fill in the details.
134
+ Init detects your stack but cannot read your architecture. The `/lp-enhance` skill runs inside Claude Code to fill in the details.
131
135
 
132
136
  ```
133
137
  /lp-enhance
134
138
  ```
135
139
 
136
- Installed as a skill during `init` (you pick global or project scope). Claude reads your codebase and updates CLAUDE.md with real content - actual architecture, actual conventions, actual guardrails, and memory management instructions. Not boilerplate. It also suggests project-specific hooks (including PostCompact for session continuity) and MCP servers based on what it finds.
140
+ Claude reads your codebase and updates CLAUDE.md with real content: actual architecture, actual conventions, actual guardrails. Not boilerplate. It also suggests project-specific hooks and MCP servers.
137
141
 
138
- Stays under the 120-instruction budget. Overflows detailed content to `.claude/rules/` files. If the skill is missing, `doctor --fix` will create it.
139
-
140
- ## Memory
141
-
142
- Optional persistent memory system that replaces Claude Code's built-in flat-file memory with intelligent, decay-based retrieval.
143
-
144
- ```bash
145
- claude-launchpad memory
146
- ```
147
-
148
- Requires native deps first: `npm install better-sqlite3 sqlite-vec` (the CLI will prompt you if missing). Interactive setup - asks before changing anything. Installs a SQLite database, hooks for automatic context injection, and 7 MCP tools.
149
-
150
- **What it does:**
151
- - **Smart session injection** - each session starts with the most relevant memories, ranked by 6 signals (context, value, importance, recency, type, noise) and packed into a 2000-token budget across three tiers (full content / summary / title-only)
152
- - **Stop hook** extracts facts from the conversation transcript when you're done
153
- - **Decay model** - memories fade naturally based on type (episodic: 60 days, semantic: 1 year, procedural: 2 years)
154
- - **Self-tuning retrieval** - memories Claude actively searches for rise in rank; memories injected but never used gradually stop appearing
155
- - **Project-scoped** - memories are partitioned per project, no cross-contamination
156
- - **TUI dashboard** (`--dashboard`) for visualization with vim navigation, filtering, and search
157
-
158
- No cloud. No sync. Everything stays in `~/.agentic-memory/memory.db`.
159
-
160
- **Memory flags:**
161
-
162
- | Flag | What it does |
163
- |---|---|
164
- | `--dashboard` | Opens the interactive TUI dashboard |
142
+ Stays under the 200-instruction budget. Overflows detailed content to `.claude/rules/` files. If the skill is missing, `doctor --fix` will create it.
165
143
 
166
- Default behavior of `claude-launchpad memory`:
167
- - If memory is not installed, it runs interactive install
168
- - If memory is installed, it shows memory stats
144
+ **When to re-run:** after major refactors, new dependencies, or architecture changes.
169
145
 
170
146
  ## Eval
171
147
 
172
- The part nobody else has built. Runs Claude against real test scenarios and scores the results.
148
+ Runs Claude against real test scenarios and scores the results. Nobody else has built this.
173
149
 
174
150
  ```bash
175
- # Interactive mode pick suite, runs, and model
151
+ # Interactive mode (pick suite, runs, model)
176
152
  claude-launchpad eval
177
153
 
178
154
  # Or pass flags directly
179
155
  claude-launchpad eval --suite security --runs 1 --model haiku
180
156
  ```
181
157
 
182
- Each scenario creates an isolated sandbox with your full Claude Code config (settings.json, rules, hooks, .claudeignore) copied in, runs Claude with a task, and checks if your configuration made Claude follow the rules:
158
+ Each scenario creates an isolated sandbox with your full Claude Code config copied in. It runs Claude with a task and checks if your configuration made Claude follow the rules.
183
159
 
184
160
  ```
185
161
  ✓ security/sql-injection 10/10 PASS
@@ -192,7 +168,7 @@ Each scenario creates an isolated sandbox with your full Claude Code config (set
192
168
  Config Eval Score ━━━━━━━━━━━━━━━━━━━─ 95%
193
169
  ```
194
170
 
195
- Results are saved to `.claude/eval/` as structured markdown you can feed these reports back to Claude to fix the failures.
171
+ Results save to `.claude/eval/` as structured markdown. Feed them back to Claude to fix failures.
196
172
 
197
173
  **Suites:**
198
174
 
@@ -202,19 +178,48 @@ Results are saved to `.claude/eval/` as structured markdown — you can feed the
202
178
  | `conventions` | 5 | Error handling, immutability, file size, naming, no hardcoded values |
203
179
  | `workflow` | 4 | Git conventions, session continuity, memory persistence, deferred tracking |
204
180
 
205
- **All eval flags:**
181
+ **Flags:**
206
182
 
207
183
  | Flag | What it does |
208
184
  |---|---|
209
185
  | `--suite <name>` | Run one suite: `security`, `conventions`, or `workflow` |
210
- | `-p, --path <dir>` | Project root to evaluate (defaults to current directory) |
186
+ | `-p, --path <dir>` | Project root to evaluate (defaults to cwd) |
211
187
  | `--scenarios <path>` | Use a custom scenarios directory |
212
188
  | `--model <model>` | Model to use: `haiku`, `sonnet`, `opus` |
213
189
  | `--runs <n>` | Runs per scenario (default 3, median score used) |
214
- | `--debug` | Keep sandbox directories so you can inspect what Claude wrote |
190
+ | `--debug` | Keep sandbox directories for inspection |
215
191
  | `--json` | JSON output |
216
192
  | `--timeout <ms>` | Timeout per run (default 120000) |
217
193
 
194
+ ## Memory
195
+
196
+ Optional persistent memory that replaces Claude Code's built-in flat-file memory with intelligent, decay-based retrieval.
197
+
198
+ ```bash
199
+ claude-launchpad memory
200
+ ```
201
+
202
+ If memory is not installed, it runs interactive setup. If installed, it shows stats. Requires native deps first: `npm install better-sqlite3 sqlite-vec`.
203
+
204
+ **What it does:**
205
+ - **Smart session injection** starts each session with the most relevant memories, ranked by 6 signals and packed into a 2000-token budget across three tiers
206
+ - **Stop hook** extracts facts from the conversation when you finish
207
+ - **Decay model** fades memories naturally (episodic: 60 days, semantic: 1 year, procedural: 2 years)
208
+ - **Self-tuning retrieval** promotes memories Claude searches for, demotes ones injected but never used
209
+ - **Project-scoped** with no cross-contamination between projects
210
+ - **TUI dashboard** (`--dashboard`) with vim navigation, filtering, and search
211
+ - **Cross-device sync** via private GitHub Gist — push/pull memories between machines
212
+
213
+ Data stays in `~/.agentic-memory/memory.db`. Sync is opt-in and uses your existing `gh` CLI auth.
214
+
215
+ | Flag / Subcommand | What it does |
216
+ |---|---|
217
+ | `--dashboard` | Opens the interactive TUI dashboard |
218
+ | `push` | Push memories to a private GitHub Gist |
219
+ | `pull` | Pull memories from a private GitHub Gist |
220
+ | `push --project <name>` | Push only one project's memories |
221
+ | `pull --project <name>` | Pull only one project's memories |
222
+
218
223
  ## Use in CI
219
224
 
220
225
  Block PRs that degrade your Claude Code config quality:
@@ -241,33 +246,38 @@ Score below threshold = exit code 1 = PR blocked.
241
246
 
242
247
  **Doctor** reads your files and runs static analysis. No API calls. No network. No cost.
243
248
 
244
- **Init** scans manifest files (package.json, go.mod, pyproject.toml, etc.), detects your stack, and generates 8 files: CLAUDE.md (with sprint reviews and backlog management), TASKS.md (with deferred issues section), BACKLOG.md (priority-tiered feature parking), settings.json (with credential deny rules, sandbox enabled, bypass mode disabled, hooks including sprint review and PostCompact), .claude/.gitignore, .claudeignore, /lp-enhance skill, and language-specific rules. Formatter hooks use hardcoded safe commands only.
245
-
246
- **Enhance** is a `/lp-enhance` skill installed during `init`. It runs inside your active Claude Code session - no separate process, no overhead. Claude already has your codebase context, so it produces better results than an external command.
249
+ **Init** scans manifest files (package.json, go.mod, pyproject.toml, etc.) and detects your stack. Generates 8 files:
250
+ - CLAUDE.md (sprint reviews, backlog management)
251
+ - TASKS.md (session log, sprint tracking)
252
+ - BACKLOG.md (priority-tiered feature parking)
253
+ - settings.json (credential deny rules, sandbox, hooks)
254
+ - .claude/.gitignore, .claudeignore, /lp-enhance skill, conventions.md
247
255
 
248
- **Eval** creates a temp directory, copies your full `.claude/` config (settings.json, rules, hooks, permissions) and `.claudeignore` into it, writes seed files from the scenario YAML, initializes a git repo, runs Claude via the Agent SDK (or falls back to CLI), then checks the output with grep/file assertions. Your code is never copied — only your Claude Code configuration. Sandbox is cleaned up after (or preserved with `--debug`).
256
+ Formatter hooks use hardcoded safe commands only.
249
257
 
250
- ## Why This Exists
258
+ **Enhance** is a `/lp-enhance` skill installed during `init`. It runs inside your active Claude Code session, not a separate process. Claude already has your codebase context, so it produces better results than an external command.
251
259
 
252
- Nobody measures their Claude Code config quality. You write CLAUDE.md, hope Claude follows it, and never verify. This tool gives you a number. Fix the issues, re-run, watch it go up.
260
+ **Eval** creates a temp directory, copies your full `.claude/` config (settings.json, rules, hooks, permissions) and `.claudeignore` into it, writes seed files from the scenario YAML, initializes a git repo, runs Claude via the Agent SDK (or falls back to CLI), then checks the output with grep/file assertions. Your code is never copied, only your Claude Code configuration. Sandbox is cleaned up after (or preserved with `--debug`).
253
261
 
254
262
  ## Glossary
255
263
 
256
- New to Claude Code? Here's what the terms mean:
264
+ New to Claude Code? Here's what the terms mean.
257
265
 
258
266
  | Term | What it is |
259
267
  |---|---|
260
268
  | **CLAUDE.md** | A markdown file in your project root that tells Claude how to work on your code. Think of it as instructions for your AI pair programmer. [Official docs](https://docs.anthropic.com/en/docs/claude-code/memory#claudemd) |
261
- | **Hooks** | Shell commands that run automatically when Claude does something. For example: auto-format a file after Claude edits it, or block Claude from reading your `.env` file. They live in `.claude/settings.json`. |
262
- | **Instruction budget** | CLAUDE.md has a soft limit of ~150 actionable lines. Past that, Claude starts ignoring rules at the bottom. Doctor counts your lines and warns you. |
269
+ | **TASKS.md** | Sprint tracker and session log. Claude reads this at session start to pick up where you left off. |
270
+ | **BACKLOG.md** | Where deferred features live. Priority tiers (P0/P1/P2) keep future ideas organized without cluttering TASKS.md. |
271
+ | **Hooks** | Shell commands that run automatically when Claude does something. Example: auto-format after edits, block reading `.env`. They live in `.claude/settings.json`. |
272
+ | **Instruction budget** | CLAUDE.md has a soft limit of ~200 actionable lines. Past that, Claude starts ignoring rules at the bottom. Doctor counts your lines and warns you. |
263
273
  | **Rules** | Extra markdown files in `.claude/rules/` that Claude reads alongside CLAUDE.md. Use them to offload detailed conventions so CLAUDE.md stays under budget. |
264
- | **Compaction** | When a Claude Code conversation gets too long, it compresses older messages to free up space. This can lose context a PostCompact hook re-injects critical files (like TASKS.md) after compaction. |
274
+ | **Compaction** | When a conversation gets too long, Claude compresses older messages. This can lose context. A PostCompact hook re-injects critical files (like TASKS.md) after compaction. |
265
275
  | **MCP Servers** | External tools Claude can connect to (databases, APIs, docs). Configured in `.claude/settings.json`. Most projects don't need them. |
266
- | **.claudeignore** | Like `.gitignore` but for Claude. Tells Claude which files to skip (node_modules, dist, lockfiles) so it doesn't waste time reading noise. |
276
+ | **.claudeignore** | Like `.gitignore` but for Claude. Tells Claude which files to skip so it doesn't waste time reading noise. |
267
277
 
268
278
  ## Privacy
269
279
 
270
- No telemetry. No analytics. No data sent anywhere. Doctor, init, and fix are fully offline. Memory stores data locally at `~/.agentic-memory/` - no cloud sync. Enhance and eval run through your local Claude CLI - no data passes through this tool. [Full privacy policy](https://mboss37.github.io/claude-launchpad/privacy.html).
280
+ No telemetry. No analytics. No data sent anywhere. Doctor, init, and fix are fully offline. Memory stores data locally at `~/.agentic-memory/`. The optional sync feature (`memory push/pull`) uses a private GitHub Gist under your own account — data goes to GitHub, not to us. Enhance and eval run through your local Claude CLI, no data passes through this tool. [Full privacy policy](https://mboss37.github.io/claude-launchpad/privacy.html).
271
281
 
272
282
  ## License
273
283
 
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DEFAULT_CONFIG,
4
+ resolveDataDir
5
+ } from "./chunk-ZMSHFAZQ.js";
6
+
7
+ // src/commands/memory/utils/gist-transport.ts
8
+ import { execSync } from "child_process";
9
+ import { readFileSync, writeFileSync, unlinkSync, mkdirSync } from "fs";
10
+ import { join, dirname } from "path";
11
+ import { tmpdir } from "os";
12
+ var EXEC_OPTS = { encoding: "utf-8", timeout: 3e4 };
13
+ var GIST_FILENAME = "agentic-memory-sync.json";
14
+ var SYNC_CONFIG_FILE = "sync-config.json";
15
+ function syncConfigPath() {
16
+ return join(resolveDataDir(DEFAULT_CONFIG.dataDir), SYNC_CONFIG_FILE);
17
+ }
18
+ function assertGhAvailable() {
19
+ try {
20
+ execSync("gh --version", { ...EXEC_OPTS, stdio: "pipe" });
21
+ } catch {
22
+ throw new Error(
23
+ "Memory sync requires the GitHub CLI.\nInstall: https://cli.github.com/\nThen run: gh auth login"
24
+ );
25
+ }
26
+ try {
27
+ execSync("gh auth status", { ...EXEC_OPTS, stdio: "pipe" });
28
+ } catch {
29
+ throw new Error(
30
+ "gh is installed but not authenticated.\nRun: gh auth login"
31
+ );
32
+ }
33
+ }
34
+ function loadSyncConfig() {
35
+ try {
36
+ const raw = readFileSync(syncConfigPath(), "utf-8");
37
+ const parsed = JSON.parse(raw);
38
+ if (typeof parsed.gistId === "string" && parsed.gistId.length > 0) {
39
+ return { gistId: parsed.gistId };
40
+ }
41
+ return null;
42
+ } catch {
43
+ return null;
44
+ }
45
+ }
46
+ function saveSyncConfig(config) {
47
+ const filePath = syncConfigPath();
48
+ mkdirSync(dirname(filePath), { recursive: true });
49
+ writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
50
+ }
51
+ function createGist(payload) {
52
+ const tmpFile = join(tmpdir(), GIST_FILENAME);
53
+ try {
54
+ writeFileSync(tmpFile, payload, "utf-8");
55
+ const result = execSync(
56
+ `gh gist create "${tmpFile}" --desc "agentic-memory sync" --public=false`,
57
+ { ...EXEC_OPTS, stdio: ["pipe", "pipe", "pipe"] }
58
+ ).trim();
59
+ const gistId = result.split("/").pop() ?? "";
60
+ if (!gistId) throw new Error(`Failed to parse gist ID from: ${result}`);
61
+ saveSyncConfig({ gistId });
62
+ return gistId;
63
+ } finally {
64
+ try {
65
+ unlinkSync(tmpFile);
66
+ } catch {
67
+ }
68
+ }
69
+ }
70
+ function readGist(gistId) {
71
+ try {
72
+ return execSync(
73
+ `gh gist view "${gistId}" --filename "${GIST_FILENAME}" --raw`,
74
+ { ...EXEC_OPTS, stdio: ["pipe", "pipe", "pipe"] }
75
+ );
76
+ } catch {
77
+ return null;
78
+ }
79
+ }
80
+ function updateGist(gistId, payload) {
81
+ const tmpFile = join(tmpdir(), GIST_FILENAME);
82
+ try {
83
+ writeFileSync(tmpFile, payload, "utf-8");
84
+ execSync(
85
+ `gh gist edit "${gistId}" --filename "${GIST_FILENAME}" "${tmpFile}"`,
86
+ { ...EXEC_OPTS, stdio: ["pipe", "pipe", "pipe"] }
87
+ );
88
+ } finally {
89
+ try {
90
+ unlinkSync(tmpFile);
91
+ } catch {
92
+ }
93
+ }
94
+ }
95
+
96
+ // src/commands/memory/utils/sync-merge.ts
97
+ function memoryToSyncRow(m) {
98
+ return {
99
+ id: m.id,
100
+ type: m.type,
101
+ title: m.title,
102
+ content: m.content,
103
+ context: m.context,
104
+ source: m.source,
105
+ project: m.project,
106
+ tags: [...m.tags],
107
+ importance: m.importance,
108
+ access_count: m.accessCount,
109
+ injection_count: m.injectionCount,
110
+ created_at: m.createdAt,
111
+ updated_at: m.updatedAt,
112
+ last_accessed: m.lastAccessed
113
+ };
114
+ }
115
+ function mergeFromRemote(memoryRepo, relationRepo, payload, project) {
116
+ let inserted = 0;
117
+ let updated = 0;
118
+ let relationsAdded = 0;
119
+ const memories = project ? payload.memories.filter((m) => m.project === project) : payload.memories;
120
+ for (const remote of memories) {
121
+ const local = memoryRepo.getById(remote.id);
122
+ if (!local) {
123
+ memoryRepo.upsertFromSync(remote);
124
+ inserted++;
125
+ } else if (remote.updated_at > local.updatedAt) {
126
+ memoryRepo.upsertFromSync(remote);
127
+ updated++;
128
+ }
129
+ }
130
+ const localIds = new Set(memoryRepo.getAll().map((m) => m.id));
131
+ const relations = payload.relations.filter(
132
+ (r) => localIds.has(r.source_id) && localIds.has(r.target_id)
133
+ );
134
+ for (const rel of relations) {
135
+ const added = relationRepo.create(
136
+ rel.source_id,
137
+ rel.target_id,
138
+ rel.relation_type
139
+ );
140
+ if (added) relationsAdded++;
141
+ }
142
+ return { inserted, updated, relationsAdded };
143
+ }
144
+
145
+ export {
146
+ assertGhAvailable,
147
+ loadSyncConfig,
148
+ createGist,
149
+ readGist,
150
+ updateGist,
151
+ memoryToSyncRow,
152
+ mergeFromRemote
153
+ };
154
+ //# sourceMappingURL=chunk-7YDBTED2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/memory/utils/gist-transport.ts","../src/commands/memory/utils/sync-merge.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { readFileSync, writeFileSync, unlinkSync, mkdirSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { tmpdir } from 'node:os';\nimport { randomUUID } from 'node:crypto';\nimport { resolveDataDir, DEFAULT_CONFIG } from '../config.js';\nimport type { SyncConfig } from '../types.js';\n\nconst EXEC_OPTS = { encoding: 'utf-8' as const, timeout: 30_000 };\nconst GIST_FILENAME = 'agentic-memory-sync.json';\nconst SYNC_CONFIG_FILE = 'sync-config.json';\n\nfunction syncConfigPath(): string {\n return join(resolveDataDir(DEFAULT_CONFIG.dataDir), SYNC_CONFIG_FILE);\n}\n\nexport function assertGhAvailable(): void {\n try {\n execSync('gh --version', { ...EXEC_OPTS, stdio: 'pipe' });\n } catch {\n throw new Error(\n 'Memory sync requires the GitHub CLI.\\n' +\n 'Install: https://cli.github.com/\\n' +\n 'Then run: gh auth login'\n );\n }\n try {\n execSync('gh auth status', { ...EXEC_OPTS, stdio: 'pipe' });\n } catch {\n throw new Error(\n 'gh is installed but not authenticated.\\n' +\n 'Run: gh auth login'\n );\n }\n}\n\nexport function loadSyncConfig(): SyncConfig | null {\n try {\n const raw = readFileSync(syncConfigPath(), 'utf-8');\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n if (typeof parsed.gistId === 'string' && parsed.gistId.length > 0) {\n return { gistId: parsed.gistId };\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function saveSyncConfig(config: SyncConfig): void {\n const filePath = syncConfigPath();\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport function createGist(payload: string): string {\n const tmpFile = join(tmpdir(), GIST_FILENAME);\n try {\n writeFileSync(tmpFile, payload, 'utf-8');\n const result = execSync(\n `gh gist create \"${tmpFile}\" --desc \"agentic-memory sync\" --public=false`,\n { ...EXEC_OPTS, stdio: ['pipe', 'pipe', 'pipe'] },\n ).trim();\n const gistId = result.split('/').pop() ?? '';\n if (!gistId) throw new Error(`Failed to parse gist ID from: ${result}`);\n saveSyncConfig({ gistId });\n return gistId;\n } finally {\n try { unlinkSync(tmpFile); } catch { /* ignore */ }\n }\n}\n\nexport function readGist(gistId: string): string | null {\n try {\n return execSync(\n `gh gist view \"${gistId}\" --filename \"${GIST_FILENAME}\" --raw`,\n { ...EXEC_OPTS, stdio: ['pipe', 'pipe', 'pipe'] },\n );\n } catch {\n return null;\n }\n}\n\nexport function updateGist(gistId: string, payload: string): void {\n const tmpFile = join(tmpdir(), GIST_FILENAME);\n try {\n writeFileSync(tmpFile, payload, 'utf-8');\n execSync(\n `gh gist edit \"${gistId}\" --filename \"${GIST_FILENAME}\" \"${tmpFile}\"`,\n { ...EXEC_OPTS, stdio: ['pipe', 'pipe', 'pipe'] },\n );\n } finally {\n try { unlinkSync(tmpFile); } catch { /* ignore */ }\n }\n}\n","import type { Memory, SyncPayload, SyncMemoryRow, MergeResult, RelationType } from '../types.js';\nimport type { MemoryRepo } from '../storage/memory-repo.js';\nimport type { RelationRepo } from '../storage/relation-repo.js';\n\nfunction memoryToSyncRow(m: Memory): SyncMemoryRow {\n return {\n id: m.id,\n type: m.type,\n title: m.title,\n content: m.content,\n context: m.context,\n source: m.source,\n project: m.project,\n tags: [...m.tags],\n importance: m.importance,\n access_count: m.accessCount,\n injection_count: m.injectionCount,\n created_at: m.createdAt,\n updated_at: m.updatedAt,\n last_accessed: m.lastAccessed,\n };\n}\n\nexport { memoryToSyncRow };\n\nexport function mergeFromRemote(\n memoryRepo: MemoryRepo,\n relationRepo: RelationRepo,\n payload: SyncPayload,\n project?: string,\n): MergeResult {\n let inserted = 0;\n let updated = 0;\n let relationsAdded = 0;\n\n const memories = project\n ? payload.memories.filter((m) => m.project === project)\n : payload.memories;\n\n for (const remote of memories) {\n const local = memoryRepo.getById(remote.id);\n if (!local) {\n memoryRepo.upsertFromSync(remote);\n inserted++;\n } else if (remote.updated_at > local.updatedAt) {\n memoryRepo.upsertFromSync(remote);\n updated++;\n }\n }\n\n const localIds = new Set(memoryRepo.getAll().map((m) => m.id));\n const relations = payload.relations.filter(\n (r) => localIds.has(r.source_id) && localIds.has(r.target_id),\n );\n\n for (const rel of relations) {\n const added = relationRepo.create(\n rel.source_id,\n rel.target_id,\n rel.relation_type as RelationType,\n );\n if (added) relationsAdded++;\n }\n\n return { inserted, updated, relationsAdded };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/memory/types.ts
4
+ import { z } from "zod";
5
+ var MEMORY_TYPES = ["working", "episodic", "semantic", "procedural", "pattern"];
6
+ var MEMORY_SOURCES = ["manual", "session_end", "consolidation", "hook", "import"];
7
+ var RELATION_TYPES = [
8
+ "relates_to",
9
+ "depends_on",
10
+ "contradicts",
11
+ "extends",
12
+ "implements",
13
+ "derived_from"
14
+ ];
15
+ var StoreInputSchema = z.object({
16
+ type: z.enum(MEMORY_TYPES),
17
+ content: z.string().min(1).max(1e4),
18
+ title: z.string().max(200).optional(),
19
+ tags: z.array(z.string()).max(20).default([]),
20
+ importance: z.number().min(0).max(1).default(0.5),
21
+ context: z.string().optional(),
22
+ source: z.enum(MEMORY_SOURCES).default("manual"),
23
+ project: z.string().max(200).optional()
24
+ });
25
+ var SearchInputSchema = z.object({
26
+ query: z.string().min(1).max(500),
27
+ id: z.string().optional(),
28
+ type: z.enum(MEMORY_TYPES).optional(),
29
+ tags: z.array(z.string()).max(10).optional(),
30
+ limit: z.number().int().min(1).max(50).default(10),
31
+ min_importance: z.number().min(0).max(1).default(0),
32
+ project: z.string().max(200).optional()
33
+ });
34
+ var ForgetInputSchema = z.object({
35
+ id: z.string(),
36
+ hard_delete: z.boolean().default(false)
37
+ });
38
+ var RelateInputSchema = z.object({
39
+ source_id: z.string(),
40
+ target_id: z.string(),
41
+ relation_type: z.enum(RELATION_TYPES)
42
+ });
43
+ var SyncPayloadSchema = z.object({
44
+ version: z.number(),
45
+ machine_id: z.string(),
46
+ pushed_at: z.string(),
47
+ memories: z.array(z.object({
48
+ id: z.string(),
49
+ type: z.enum(MEMORY_TYPES),
50
+ title: z.string().nullable(),
51
+ content: z.string(),
52
+ context: z.string().nullable(),
53
+ source: z.enum(MEMORY_SOURCES).nullable(),
54
+ project: z.string().nullable(),
55
+ tags: z.array(z.string()),
56
+ importance: z.number(),
57
+ access_count: z.number(),
58
+ injection_count: z.number(),
59
+ created_at: z.string(),
60
+ updated_at: z.string(),
61
+ last_accessed: z.string().nullable()
62
+ })),
63
+ relations: z.array(z.object({
64
+ source_id: z.string(),
65
+ target_id: z.string(),
66
+ relation_type: z.enum(RELATION_TYPES),
67
+ created_at: z.string()
68
+ }))
69
+ });
70
+
71
+ export {
72
+ MEMORY_TYPES,
73
+ MEMORY_SOURCES,
74
+ RELATION_TYPES,
75
+ SyncPayloadSchema
76
+ };
77
+ //# sourceMappingURL=chunk-J5NT4JGE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/memory/types.ts"],"sourcesContent":["import { z } from 'zod';\n\n// ── Memory Types ──────────────────────────────────────────────\n\nexport const MEMORY_TYPES = ['working', 'episodic', 'semantic', 'procedural', 'pattern'] as const;\nexport type MemoryType = typeof MEMORY_TYPES[number];\n\nexport const MEMORY_SOURCES = ['manual', 'session_end', 'consolidation', 'hook', 'import'] as const;\nexport type MemorySource = typeof MEMORY_SOURCES[number];\n\nexport const RELATION_TYPES = [\n 'relates_to', 'depends_on', 'contradicts', 'extends', 'implements', 'derived_from',\n] as const;\nexport type RelationType = typeof RELATION_TYPES[number];\n\n// ── Core Entities ─────────────────────────────────────────────\n\nexport interface Memory {\n readonly id: string;\n readonly type: MemoryType;\n readonly title: string | null;\n readonly content: string;\n readonly context: string | null;\n readonly source: MemorySource | null;\n readonly project: string | null;\n readonly tags: readonly string[];\n readonly importance: number;\n readonly createdAt: string;\n readonly updatedAt: string;\n readonly accessCount: number;\n readonly lastAccessed: string | null;\n readonly injectionCount: number;\n}\n\nexport interface Relation {\n readonly sourceId: string;\n readonly targetId: string;\n readonly relationType: RelationType;\n readonly createdAt: string;\n}\n\n// ── Search Types ──────────────────────────────────────────────\n\nexport interface SearchResult {\n readonly memory: Memory;\n readonly score: number;\n readonly explanation: string;\n}\n\nexport interface FtsMatch {\n readonly rowid: number;\n readonly memoryId: string;\n readonly rank: number;\n}\n\nexport interface ScoredCandidate {\n readonly memoryId: string;\n readonly textScore: number;\n readonly importanceScore: number;\n readonly recencyScore: number;\n readonly accessScore: number;\n readonly contextScore: number;\n readonly composite: number;\n}\n\n// ── Decay Parameters ──────────────────────────────────────────\n\nexport interface DecayParams {\n readonly tauByType: Record<MemoryType, number>;\n readonly accessModifiers: readonly { readonly maxCount: number; readonly multiplier: number }[];\n readonly relationModifier: { readonly connectedThreshold: number; readonly connectedMultiplier: number; readonly isolatedMultiplier: number };\n readonly importanceFloor: number;\n readonly pruneThreshold: number;\n readonly pruneMinAgeDays: number;\n}\n\n// ── Input Schemas (for MCP tools) ─────────────────────────────\n\nexport const StoreInputSchema = z.object({\n type: z.enum(MEMORY_TYPES),\n content: z.string().min(1).max(10000),\n title: z.string().max(200).optional(),\n tags: z.array(z.string()).max(20).default([]),\n importance: z.number().min(0).max(1).default(0.5),\n context: z.string().optional(),\n source: z.enum(MEMORY_SOURCES).default('manual'),\n project: z.string().max(200).optional(),\n});\nexport type StoreInput = z.infer<typeof StoreInputSchema>;\n\nexport const SearchInputSchema = z.object({\n query: z.string().min(1).max(500),\n id: z.string().optional(),\n type: z.enum(MEMORY_TYPES).optional(),\n tags: z.array(z.string()).max(10).optional(),\n limit: z.number().int().min(1).max(50).default(10),\n min_importance: z.number().min(0).max(1).default(0),\n project: z.string().max(200).optional(),\n});\nexport type SearchInput = z.infer<typeof SearchInputSchema>;\n\nexport const ForgetInputSchema = z.object({\n id: z.string(),\n hard_delete: z.boolean().default(false),\n});\nexport type ForgetInput = z.infer<typeof ForgetInputSchema>;\n\nexport const RelateInputSchema = z.object({\n source_id: z.string(),\n target_id: z.string(),\n relation_type: z.enum(RELATION_TYPES),\n});\nexport type RelateInput = z.infer<typeof RelateInputSchema>;\n\n// ── Sync Types ───────────────────────────────────────────────\n\nexport interface SyncPayload {\n readonly version: number;\n readonly machine_id: string;\n readonly pushed_at: string;\n readonly memories: readonly SyncMemoryRow[];\n readonly relations: readonly SyncRelationRow[];\n}\n\nexport interface SyncMemoryRow {\n readonly id: string;\n readonly type: MemoryType;\n readonly title: string | null;\n readonly content: string;\n readonly context: string | null;\n readonly source: MemorySource | null;\n readonly project: string | null;\n readonly tags: readonly string[];\n readonly importance: number;\n readonly access_count: number;\n readonly injection_count: number;\n readonly created_at: string;\n readonly updated_at: string;\n readonly last_accessed: string | null;\n}\n\nexport interface SyncRelationRow {\n readonly source_id: string;\n readonly target_id: string;\n readonly relation_type: RelationType;\n readonly created_at: string;\n}\n\nexport const SyncPayloadSchema = z.object({\n version: z.number(),\n machine_id: z.string(),\n pushed_at: z.string(),\n memories: z.array(z.object({\n id: z.string(),\n type: z.enum(MEMORY_TYPES),\n title: z.string().nullable(),\n content: z.string(),\n context: z.string().nullable(),\n source: z.enum(MEMORY_SOURCES).nullable(),\n project: z.string().nullable(),\n tags: z.array(z.string()),\n importance: z.number(),\n access_count: z.number(),\n injection_count: z.number(),\n created_at: z.string(),\n updated_at: z.string(),\n last_accessed: z.string().nullable(),\n })),\n relations: z.array(z.object({\n source_id: z.string(),\n target_id: z.string(),\n relation_type: z.enum(RELATION_TYPES),\n created_at: z.string(),\n })),\n});\n\nexport interface SyncConfig {\n readonly gistId: string;\n}\n\nexport interface MergeResult {\n readonly inserted: number;\n readonly updated: number;\n readonly relationsAdded: number;\n}\n\n// ── Stats ─────────────────────────────────────────────────────\n\nexport interface MemoryStats {\n readonly totalMemories: number;\n readonly byType: Record<MemoryType, number>;\n readonly totalRelations: number;\n readonly dbSizeBytes: number;\n readonly oldestMemory: string | null;\n readonly newestMemory: string | null;\n readonly topInjected: readonly { readonly id: string; readonly title: string | null; readonly injectionCount: number }[];\n}\n"],"mappings":"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","names":[]}