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.
- package/README.md +123 -113
- package/dist/chunk-7YDBTED2.js +154 -0
- package/dist/chunk-7YDBTED2.js.map +1 -0
- package/dist/chunk-J5NT4JGE.js +77 -0
- package/dist/chunk-J5NT4JGE.js.map +1 -0
- package/dist/{chunk-TALTTAMW.js → chunk-JXFTVFPC.js} +43 -3
- package/dist/chunk-JXFTVFPC.js.map +1 -0
- package/dist/{chunk-4AF3NGNF.js → chunk-YEGOHLE7.js} +3 -3
- package/dist/{chunk-JTKRLIEV.js → chunk-ZMSHFAZQ.js} +2 -1
- package/dist/cli.js +47 -90
- package/dist/cli.js.map +1 -1
- package/dist/commands/memory/server.js +39 -75
- package/dist/commands/memory/server.js.map +1 -1
- package/dist/{context-AGNCZJPC.js → context-SGPGEJV4.js} +4 -4
- package/dist/{extract-RPRYPT3Z.js → extract-T32FMLN5.js} +4 -4
- package/dist/{install-PSSMUGLO.js → install-OKLYDFBJ.js} +2 -2
- package/dist/pull-4VKUDKTB.js +66 -0
- package/dist/pull-4VKUDKTB.js.map +1 -0
- package/dist/push-WI3ZIPZU.js +89 -0
- package/dist/push-WI3ZIPZU.js.map +1 -0
- package/dist/{stats-DAUYJ4BE.js → stats-77WLARNA.js} +4 -4
- package/dist/{tui-A4TJFNE3.js → tui-YV7AFJFR.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-TALTTAMW.js.map +0 -1
- /package/dist/{chunk-4AF3NGNF.js.map → chunk-YEGOHLE7.js.map} +0 -0
- /package/dist/{chunk-JTKRLIEV.js.map → chunk-ZMSHFAZQ.js.map} +0 -0
- /package/dist/{context-AGNCZJPC.js.map → context-SGPGEJV4.js.map} +0 -0
- /package/dist/{extract-RPRYPT3Z.js.map → extract-T32FMLN5.js.map} +0 -0
- /package/dist/{install-PSSMUGLO.js.map → install-OKLYDFBJ.js.map} +0 -0
- /package/dist/{stats-DAUYJ4BE.js.map → stats-77WLARNA.js.map} +0 -0
- /package/dist/{tui-A4TJFNE3.js.map → tui-YV7AFJFR.js.map} +0 -0
package/README.md
CHANGED
|
@@ -4,106 +4,109 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/claude-launchpad)
|
|
5
5
|
[](https://github.com/mboss37/claude-launchpad)
|
|
6
6
|
[](https://github.com/mboss37/claude-launchpad/blob/master/LICENSE)
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
7
10
|
|
|
8
|
-
**Score your Claude Code
|
|
11
|
+
**Score your Claude Code config. Fix it. Prove it works.**
|
|
9
12
|
|
|
10
|
-
|
|
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
|
-
|
|
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
|
-
|
|
34
|
+
✓ No issues found. Your configuration looks solid.
|
|
35
|
+
```
|
|
19
36
|
|
|
20
|
-
|
|
37
|
+
A typical unconfigured project scores ~31%. After `--fix`, it jumps to ~91%.
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
21
40
|
|
|
22
|
-
|
|
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
|
|
47
|
+
Detects your stack, generates config, hooks, and permissions. Start at ~93%.
|
|
29
48
|
|
|
30
|
-
|
|
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
|
-
|
|
55
|
+
Scores your config, auto-repairs everything it can.
|
|
39
56
|
|
|
40
|
-
##
|
|
57
|
+
## The Three-File System
|
|
41
58
|
|
|
42
|
-
|
|
|
59
|
+
| File | Purpose | Example |
|
|
43
60
|
|---|---|---|
|
|
44
|
-
| `
|
|
45
|
-
| `
|
|
46
|
-
| `
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
78
|
+
## Doctor
|
|
64
79
|
|
|
65
|
-
|
|
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
|
|
70
|
-
| **CLAUDE.md Quality** | Missing sections
|
|
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
|
|
89
|
+
| **Hooks** | Missing auto-format, no .env protection, no PostCompact hook |
|
|
73
90
|
| **Rules** | Dead rule files, stale references, empty configs |
|
|
74
|
-
| **Permissions** | Credential
|
|
91
|
+
| **Permissions** | Credential exposure (~/.ssh, ~/.aws), blanket Bash approval, sandbox disabled |
|
|
75
92
|
| **MCP Servers** | Invalid transport configs, missing commands/URLs |
|
|
76
93
|
|
|
77
|
-
|
|
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-
|
|
98
|
-
| `--fix --dry-run` | Preview
|
|
99
|
-
| `--watch` | Re-runs every second
|
|
100
|
-
| `--json` | Pure JSON output
|
|
101
|
-
| `--min-score <n>` | Exit code 1 if score is below threshold
|
|
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
|
-
|
|
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
|
|
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)
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
148
|
+
Runs Claude against real test scenarios and scores the results. Nobody else has built this.
|
|
173
149
|
|
|
174
150
|
```bash
|
|
175
|
-
# Interactive mode
|
|
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
|
|
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
|
|
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
|
-
**
|
|
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
|
|
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
|
|
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.)
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
256
|
+
Formatter hooks use hardcoded safe commands only.
|
|
249
257
|
|
|
250
|
-
|
|
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
|
-
|
|
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
|
-
| **
|
|
262
|
-
| **
|
|
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
|
|
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
|
|
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
|
|
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":[]}
|