memory-crystal 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 (104) hide show
  1. package/.env.example +20 -0
  2. package/CHANGELOG.md +6 -0
  3. package/LETTERS.md +22 -0
  4. package/LICENSE +21 -0
  5. package/README-ENTERPRISE.md +162 -0
  6. package/README-old.md +275 -0
  7. package/README.md +91 -0
  8. package/RELAY.md +88 -0
  9. package/TECHNICAL.md +379 -0
  10. package/ai/dev-updates/2026-02-25--cc-air--phase2-architecture-pivot.md +70 -0
  11. package/ai/dev-updates/2026-02-25--cc-air--phase2-worker-build.md +72 -0
  12. package/ai/dev-updates/2026-02-26--10-25-16--cc-mini--phase2-implementation.md +49 -0
  13. package/ai/dev-updates/2026-02-27--20-30-00--cc-mini--readme-overhaul-and-public-deploy.md +69 -0
  14. package/ai/notes/2026-02-26--cc-air--notes.md +412 -0
  15. package/ai/notes/2026-02-27--cc-mini--grok-feedback.md +44 -0
  16. package/ai/notes/2026-02-27--cc-mini--lesa-feedback.md +45 -0
  17. package/ai/notes/RESEARCH.md +1185 -0
  18. package/ai/notes/salience-research/README.md +29 -0
  19. package/ai/notes/salience-research/eurosla-salience-review.md +64 -0
  20. package/ai/notes/salience-research/full-research-summary.md +269 -0
  21. package/ai/notes/salience-research/salience-levels-diagram.png +0 -0
  22. package/ai/plan/2026-02-27--cc-mini--qr-pairing-spec.md +203 -0
  23. package/ai/plan/_archive/PLAN.md +194 -0
  24. package/ai/plan/_archive/PRD.md +1014 -0
  25. package/ai/plan/cc-plans-duplicates-from-dot-claude/2026-02-26--cc-mini--phase2-implementation-plan.md +245 -0
  26. package/ai/plan/dev-conventions-note.md +70 -0
  27. package/ai/plan/ldm-os-install-and-boot-architecture.md +285 -0
  28. package/ai/plan/memory-crystal-phase2-plan.md +192 -0
  29. package/ai/plan/memory-system-lay-of-the-land.md +214 -0
  30. package/ai/plan/phase2-ephemeral-relay.md +238 -0
  31. package/ai/plan/readme-first.md +68 -0
  32. package/ai/plan/roadmap.md +159 -0
  33. package/ai/todos/PUNCHLIST.md +44 -0
  34. package/ai/todos/README.md +31 -0
  35. package/ai/todos/inboxes/cc-air/2026-02-26--cc-air--post-relay-todos.md +85 -0
  36. package/ai/todos/inboxes/cc-mini/2026-02-26--cc-mini--phase2-status.md +100 -0
  37. package/ai/todos/inboxes/cc-mini/_archive/TODO.md +25 -0
  38. package/ai/todos/inboxes/parker/2026-02-25--cc-air--setup-checklist.md +139 -0
  39. package/ai/todos/inboxes/parker/2026-02-26--cc-mini--phase2-your-moves.md +72 -0
  40. package/dist/cc-hook.d.ts +1 -0
  41. package/dist/cc-hook.js +349 -0
  42. package/dist/chunk-3VFIJYS4.js +818 -0
  43. package/dist/chunk-52QE3YI3.js +1169 -0
  44. package/dist/chunk-AA3OPP4Z.js +432 -0
  45. package/dist/chunk-D3I3ZSE2.js +411 -0
  46. package/dist/chunk-EKSACBTJ.js +1070 -0
  47. package/dist/chunk-F3Y7EL7K.js +83 -0
  48. package/dist/chunk-JWZXYVET.js +1068 -0
  49. package/dist/chunk-KYVWO6ZM.js +1069 -0
  50. package/dist/chunk-L3VHARQH.js +413 -0
  51. package/dist/chunk-LOVAHSQV.js +411 -0
  52. package/dist/chunk-LQOYCAGG.js +446 -0
  53. package/dist/chunk-MK42FMEG.js +147 -0
  54. package/dist/chunk-NIJCVN3O.js +147 -0
  55. package/dist/chunk-O2UITJGH.js +465 -0
  56. package/dist/chunk-PEK6JH65.js +432 -0
  57. package/dist/chunk-PJ6FFKEX.js +77 -0
  58. package/dist/chunk-PLUBBZYR.js +800 -0
  59. package/dist/chunk-SGL6ISBJ.js +1061 -0
  60. package/dist/chunk-UNHVZB5G.js +411 -0
  61. package/dist/chunk-VAFTWSTE.js +1061 -0
  62. package/dist/chunk-XZ3S56RQ.js +1061 -0
  63. package/dist/chunk-Y72C7F6O.js +148 -0
  64. package/dist/cli.d.ts +1 -0
  65. package/dist/cli.js +325 -0
  66. package/dist/core.d.ts +188 -0
  67. package/dist/core.js +12 -0
  68. package/dist/crypto.d.ts +16 -0
  69. package/dist/crypto.js +18 -0
  70. package/dist/dev-update-SZ2Z4WCQ.js +6 -0
  71. package/dist/ldm.d.ts +17 -0
  72. package/dist/ldm.js +12 -0
  73. package/dist/mcp-server.d.ts +1 -0
  74. package/dist/mcp-server.js +250 -0
  75. package/dist/migrate.d.ts +1 -0
  76. package/dist/migrate.js +89 -0
  77. package/dist/mirror-sync.d.ts +1 -0
  78. package/dist/mirror-sync.js +130 -0
  79. package/dist/openclaw.d.ts +5 -0
  80. package/dist/openclaw.js +349 -0
  81. package/dist/poller.d.ts +1 -0
  82. package/dist/poller.js +272 -0
  83. package/dist/summarize.d.ts +19 -0
  84. package/dist/summarize.js +10 -0
  85. package/dist/worker.js +137 -0
  86. package/openclaw.plugin.json +11 -0
  87. package/package.json +40 -0
  88. package/scripts/migrate-lance-to-sqlite.mjs +217 -0
  89. package/skills/memory/SKILL.md +61 -0
  90. package/src/cc-hook.ts +447 -0
  91. package/src/cli.ts +356 -0
  92. package/src/core.ts +1472 -0
  93. package/src/crypto.ts +113 -0
  94. package/src/dev-update.ts +178 -0
  95. package/src/ldm.ts +117 -0
  96. package/src/mcp-server.ts +274 -0
  97. package/src/migrate.ts +104 -0
  98. package/src/mirror-sync.ts +175 -0
  99. package/src/openclaw.ts +250 -0
  100. package/src/poller.ts +345 -0
  101. package/src/summarize.ts +210 -0
  102. package/src/worker.ts +208 -0
  103. package/tsconfig.json +18 -0
  104. package/wrangler.toml +20 -0
@@ -0,0 +1,245 @@
1
+ # Memory Crystal Phase 2 — Implementation Plan
2
+
3
+ ## Context
4
+
5
+ Memory Crystal currently only produces vector DB embeddings (crystal.db at ~/.openclaw/memory-crystal/). It needs to become the universal archive manager for ~/.ldm/: producing JSONL transcript copies, MD session summaries, and hosting the shared crystal.db at the LDM root. cc-air designed the architecture and built the ephemeral relay code on `cc-air/phase2-relay`. This plan implements Priorities 1-3 from the roadmap on a new `mini/phase2-relay` branch.
6
+
7
+ ## Branch
8
+
9
+ `mini/phase2-relay` forked from `main` (which now has cc-air's planning docs merged).
10
+
11
+ ## Execution Order
12
+
13
+ The sequencing matters. Dependencies flow downward:
14
+
15
+ 1. **LDM Scaffolding** (P2) ... file writes depend on directories existing
16
+ 2. **crystal.db move** (P1c) ... everything must resolve the new DB path
17
+ 3. **JSONL archive** (P1a) ... simple file copy, depends on scaffold
18
+ 4. **MD session summaries** (P1b) ... depends on JSONL and scaffold
19
+ 5. **Dev-update migration** ... parallel-safe, small scope
20
+ 6. **Relay merge** (P3) ... touches cc-hook, core, mcp-server that P1/P2 already modified
21
+
22
+ ---
23
+
24
+ ## Step 1: LDM Scaffolding (Priority 2)
25
+
26
+ **New file: `src/ldm.ts` (~120 lines)**
27
+
28
+ Central module for all LDM directory knowledge. Every other file imports paths from here.
29
+
30
+ - `getAgentId()` ... resolves from `CRYSTAL_AGENT_ID` env var, default `cc-mini`
31
+ - `ldmPaths(agentId?)` ... returns object with all paths: `root`, `config`, `crystalDb`, `crystalLance`, `agentRoot`, `transcripts`, `sessions`, `daily`, `journals`
32
+ - `scaffoldLdm(agentId?)` ... creates full directory tree, writes/updates `~/.ldm/config.json` with agents array
33
+ - `ensureLdm(agentId?)` ... idempotent check, calls scaffoldLdm if needed
34
+
35
+ **Modify: `src/cli.ts`** ... add `crystal init [--agent <id>]` subcommand calling `scaffoldLdm()`
36
+
37
+ **Target structure:**
38
+ ```
39
+ ~/.ldm/
40
+ config.json (version, agents array)
41
+ memory/
42
+ crystal.db (shared, all agents)
43
+ lance/ (LanceDB dual-write, pending removal)
44
+ agents/{agent_id}/
45
+ memory/
46
+ transcripts/ sessions/ daily/ journals/
47
+ ```
48
+
49
+ **Verify:** `crystal init --agent cc-mini` creates all dirs, config.json has cc-mini in agents array.
50
+
51
+ ---
52
+
53
+ ## Step 2: crystal.db Move (Priority 1c)
54
+
55
+ **Strategy: symlink-first, hard move later.** The 1.5GB DB with 152K+ chunks must not be corrupted.
56
+
57
+ **Modify: `src/core.ts` resolveConfig()**
58
+
59
+ Change dataDir default resolution:
60
+ 1. Explicit override (always wins)
61
+ 2. `CRYSTAL_DATA_DIR` env var (for testing)
62
+ 3. If `~/.ldm/memory/crystal.db` exists, use `~/.ldm/memory/`
63
+ 4. Fall back to legacy `~/.openclaw/memory-crystal/`
64
+
65
+ This auto-detection means old deployments keep working until migration runs.
66
+
67
+ **Add to `src/cli.ts`: `crystal migrate-db` subcommand**
68
+
69
+ 1. Calls `ensureLdm()`
70
+ 2. Checks source exists at `~/.openclaw/memory-crystal/crystal.db`
71
+ 3. Checks destination doesn't exist (or is symlink)
72
+ 4. Copies crystal.db to `~/.ldm/memory/crystal.db` (copy first, never move)
73
+ 5. Verifies copy by opening with better-sqlite3, checking chunk count
74
+ 6. Creates symlinks: old path -> new path (for lance/ too)
75
+ 7. Reports success
76
+
77
+ **Safety:** Gateway and CC must be stopped during migration. Script checks for locks via `lsof`.
78
+
79
+ **Verify:** `crystal migrate-db` succeeds, `crystal status` shows same chunk count, `crystal search "test"` returns results.
80
+
81
+ ---
82
+
83
+ ## Step 3: JSONL Archive (Priority 1a)
84
+
85
+ **Modify: `src/cc-hook.ts`**
86
+
87
+ Add `archiveTranscript(transcriptPath, agentId)` function:
88
+ - Calls `ensureLdm(agentId)`
89
+ - Copies full JSONL file to `~/.ldm/agents/{agent_id}/memory/transcripts/`
90
+ - Only copies if source is newer than destination (mtime check)
91
+ - Called early in `main()`, after kill-switch checks, before watermark logic
92
+
93
+ Also update `appendDailyLog()` to use `ldmPaths()` instead of the hardcoded `LDM_DAILY` constant.
94
+
95
+ **Verify:** Run CC session with capture enabled, check JSONL copy appears in transcripts/, file size matches source.
96
+
97
+ ---
98
+
99
+ ## Step 4: MD Session Summaries (Priority 1b)
100
+
101
+ **New file: `src/summarize.ts` (~200 lines)**
102
+
103
+ Two modes, configurable via `CRYSTAL_SUMMARY_MODE` env var:
104
+
105
+ **LLM mode (default):** Calls gpt-4o-mini (or configured provider) with condensed transcript. Returns title, slug, summary, key topics. Format:
106
+ ```markdown
107
+ # Session Title
108
+ **Session:** {id} **Date:** {date} **Messages:** {count}
109
+ ## Summary
110
+ 2-4 sentences
111
+ ## Key Topics
112
+ - topic1
113
+ - topic2
114
+ ```
115
+
116
+ **Simple mode:** First user message becomes title. Concatenates first 10 messages as preview. No API call.
117
+
118
+ **Integration in `src/cc-hook.ts`:**
119
+ - After successful ingest, call summary generator
120
+ - Write to `~/.ldm/agents/{agent_id}/memory/sessions/YYYY-MM-DD--HH-MM-SS--{agent}--{slug}.md`
121
+ - Wrapped in try/catch (non-fatal ... ingestion is more important than summary)
122
+
123
+ **Config env vars:** `CRYSTAL_SUMMARY_MODE` (llm|simple), `CRYSTAL_SUMMARY_PROVIDER` (openai|google), `CRYSTAL_SUMMARY_MODEL` (gpt-4o-mini)
124
+
125
+ **Verify:** Run capture with both modes, check MD files appear in sessions/ with correct naming format.
126
+
127
+ ---
128
+
129
+ ## Step 5: Dev-Update Migration
130
+
131
+ **Modify: `src/dev-update.ts`**
132
+
133
+ - Change output from centralized `wip-dev-updates` repo to each repo's own `ai/` folder
134
+ - Update filename format to `YYYY-MM-DD--HH-MM-SS--{agent}--dev-update-{repo}.md`
135
+ - Remove git add/commit/push to wip-dev-updates (each repo manages its own ai/)
136
+ - Keep throttle logic (once per hour)
137
+
138
+ **Verify:** Run dev update, files appear in `<repo>/ai/` with correct naming.
139
+
140
+ ---
141
+
142
+ ## Step 6: Merge Relay Code (Priority 3)
143
+
144
+ **Strategy:** `git merge origin/cc-air/phase2-relay` into `mini/phase2-relay`, resolve conflicts.
145
+
146
+ **Conflict zones:**
147
+ - `src/cc-hook.ts` ... heaviest conflicts (P1 added archive+summary, relay added mode switching). Resolution: keep both. Relay mode still archives JSONL and generates summary locally before encrypting.
148
+ - `src/core.ts` ... relay adds RemoteCrystal + createCrystal at end. P1c changed resolveConfig. Different locations, should merge clean.
149
+ - `src/mcp-server.ts` ... relay changed Crystal import. Minor conflicts.
150
+ - `package.json` ... build script merge (manual).
151
+
152
+ **New files from relay (no conflicts):**
153
+ - `src/crypto.ts` ... take as-is, fix HOME default
154
+ - `src/worker.ts` ... take as-is
155
+ - `src/poller.ts` ... needs expansion (see below)
156
+ - `src/mirror-sync.ts` ... update paths to use ldmPaths()
157
+ - `wrangler.toml` ... take as-is
158
+
159
+ **Poller expansion (key change):**
160
+
161
+ After decrypting relay blobs and ingesting into crystal, the poller must also reconstruct the remote agent's full file tree on the Mini:
162
+
163
+ 1. Write JSONL to `~/.ldm/agents/{drop.agent_id}/memory/transcripts/relay-{blob.id}.jsonl`
164
+ 2. Generate MD summary to `~/.ldm/agents/{drop.agent_id}/memory/sessions/`
165
+ 3. Append daily breadcrumb to `~/.ldm/agents/{drop.agent_id}/memory/daily/`
166
+
167
+ This reuses `generateSessionSummary()` from `summarize.ts` and `appendDailyLog()` from cc-hook (refactored to be importable).
168
+
169
+ **mirror-sync.ts updates:** Change mirror DB path from `~/.openclaw/memory-crystal/crystal.db` to `~/.ldm/memory/crystal.db` via ldmPaths().
170
+
171
+ **Build scripts update:** Add `src/ldm.ts` and `src/summarize.ts` to tsup entry points in package.json.
172
+
173
+ **Verify:**
174
+ - `npm run build` passes zero errors
175
+ - `crystal status` works from `~/.ldm/memory/crystal.db`
176
+ - `crystal search "test"` returns results
177
+ - cc-hook produces all three file types (JSONL, MD, crystal)
178
+ - `node dist/poller.js --status` shows "not configured" (no relay URL yet)
179
+ - `node dist/mirror-sync.js --status` shows mirror state
180
+
181
+ ---
182
+
183
+ ## Step 7: Deploy Updated Plugin
184
+
185
+ ```bash
186
+ cd /path/to/memory-crystal
187
+ npm run build
188
+ cp -r dist skills openclaw.plugin.json package.json ~/.openclaw/extensions/memory-crystal/
189
+ cd ~/.openclaw/extensions/memory-crystal && npm install --omit=dev
190
+ openclaw gateway restart
191
+ ```
192
+
193
+ ---
194
+
195
+ ## File Inventory
196
+
197
+ **New files (3):**
198
+ | File | Lines | Purpose |
199
+ |------|-------|---------|
200
+ | `src/ldm.ts` | ~120 | LDM scaffolding, path resolution |
201
+ | `src/summarize.ts` | ~200 | MD session summary generation (LLM + simple) |
202
+
203
+ **From relay branch (4):**
204
+ | File | Lines | Changes needed |
205
+ |------|-------|----------------|
206
+ | `src/crypto.ts` | ~113 | Fix HOME default |
207
+ | `src/worker.ts` | ~208 | Take as-is |
208
+ | `src/poller.ts` | ~350 | Expand for full file tree reconstruction |
209
+ | `src/mirror-sync.ts` | ~180 | Update paths to ldmPaths() |
210
+
211
+ **Modified files (7):**
212
+ | File | What changes |
213
+ |------|-------------|
214
+ | `src/core.ts` | resolveConfig() LDM path, RemoteCrystal merge |
215
+ | `src/cc-hook.ts` | JSONL archive, summary gen, relay mode, ldm imports |
216
+ | `src/mcp-server.ts` | createCrystal() factory, remote mode guards |
217
+ | `src/cli.ts` | `crystal init` and `crystal migrate-db` subcommands |
218
+ | `src/dev-update.ts` | Write to repo ai/ folder with new naming |
219
+ | `src/openclaw.ts` | Use createCrystal() for remote mode |
220
+ | `package.json` | Updated build scripts |
221
+
222
+ ---
223
+
224
+ ## Risk Mitigation
225
+
226
+ - **crystal.db:** Copy-first, symlink-second. Original never deleted. Rollback: remove symlink.
227
+ - **WAL files:** Stop gateway before migration. SQLite recreates WAL/SHM after copy.
228
+ - **Auto-detection:** resolveConfig checks LDM first, falls back to legacy. No breakage for unmigrated setups.
229
+ - **Private mode:** All new code paths check isPrivateMode() before writing.
230
+ - **Summary failure:** Non-fatal. Ingestion succeeds even if summary generation fails.
231
+ - **Build gate:** npm run build must pass before any deployment.
232
+
233
+ ---
234
+
235
+ ## End-to-End Verification
236
+
237
+ After all steps:
238
+ 1. `crystal init --agent cc-mini` ... scaffolds ~/.ldm/
239
+ 2. `crystal migrate-db` ... moves DB, creates symlinks
240
+ 3. Run a CC session, let cc-hook fire
241
+ 4. Check: JSONL in transcripts/, MD in sessions/, chunks in crystal.db, breadcrumb in daily/
242
+ 5. `crystal search "something from the session"` ... returns the new content
243
+ 6. `crystal status` ... shows updated chunk count
244
+ 7. Gateway restart ... OpenClaw plugin initializes with new paths
245
+ 8. Lesa conversation ... crystall plugin captures to shared crystal.db
@@ -0,0 +1,70 @@
1
+ # Dev Conventions — Notes from cc-air
2
+
3
+ **Date:** 2026-02-25
4
+ **Agent:** cc-air
5
+
6
+ ## Existing Convention Sources
7
+
8
+ Two repos define how WIP.computer projects are managed:
9
+
10
+ ### 1. `wip-dev-resources` (private)
11
+ - **DEVELOPMENT-PROCESS.md** — the main best practices doc
12
+ - Covers: repo structure, architecture (4-piece pattern), release process, branch conventions, branch protection, review flow, license compliance, public/private repo pattern
13
+ - **Key rules:**
14
+ - Every change goes through a PR. No direct pushes to main. `enforce_admins=true` on all repos.
15
+ - Branch prefixes by agent/machine: `lesa/`, `mini/`, `mba/`
16
+ - Architecture: `core.ts` + `cli.ts` + `mcp-server.ts` + (optional) `openclaw.ts`
17
+ - Public repos stay clean — no todos, no dev noise
18
+ - Private dev stuff goes in `wip-dev-resources/repos/<project>/`
19
+ - Has a `repos/` subfolder for per-project todos, conversations, notes
20
+
21
+ ### 2. `wip-dev-updates` (private)
22
+ - Centralized dev update repo — one folder per project, updates accumulate
23
+ - **Naming convention:** `{who}-dev-update-{MM-DD-YYYY}--{HH-MM-SS}.md`
24
+ - **who:** `cc` (Claude Code), `lesa` (Lesa), `parker` (Parker)
25
+ - Also has a `cc-session-export/` folder with auto-generated session exports
26
+ - Has a repo index table in README.md
27
+
28
+ ### 3. Per-repo `ai/` folders (newer pattern)
29
+ - `wip-agent-pay` has `ai/dev-update/` with both date-only and timestamped files
30
+ - `memory-crystal` now has `ai/` with `dev-updates/`, `plan/`, `todos/parker/`
31
+
32
+ ## Branch Prefix Update
33
+
34
+ The existing DEVELOPMENT-PROCESS.md says `lesa/`, `mini/`, `mba/`. Parker has updated the convention:
35
+
36
+ | Agent | Machine | Branch Prefix | Notes |
37
+ |-------|---------|---------------|-------|
38
+ | cc-air | MacBook Air | `cc-air/` | Claude Code on Air |
39
+ | cc-mini | Mac Mini | `cc-mini/` or `mini/` | Claude Code on Mini |
40
+ | lesa-mini | Mac Mini | `lesa/` | Lesa on Mini via OpenClaw |
41
+
42
+ ## File Naming Convention (updated)
43
+
44
+ All files authored by an agent must include the agent name:
45
+
46
+ ```
47
+ YYYY-MM-DD--{agent}--{description}.md
48
+ ```
49
+
50
+ Examples:
51
+ - `2026-02-25--cc-air--phase2-worker-build.md`
52
+ - `2026-02-25--cc-air--setup-checklist.md`
53
+ - `2026-02-25--lesa-mini--weekly-tuning-report.md`
54
+
55
+ This differs from the older `wip-dev-updates` convention (`{who}-dev-update-{MM-DD-YYYY}--{HH-MM-SS}.md`) — the new format uses ISO dates and puts the agent name after the date with double-dash separators.
56
+
57
+ ## Decision: `ai/` folder per repo (2026-02-25)
58
+
59
+ **The `ai/` folder is the standard going forward.** Every repo gets one. It holds all the thinking between Parker and agents — plans, dev updates, todos, conversations. It's scoped to the repo it belongs to.
60
+
61
+ ```
62
+ ai/
63
+ dev-updates/ ← what was built, session logs
64
+ plan/ ← architecture plans, convention notes
65
+ todos/
66
+ parker/ ← manual tasks for Parker
67
+ ```
68
+
69
+ - `wip-dev-updates` (centralized repo) is legacy. Leave it as-is, don't add to it.
70
+ - `wip-dev-resources/DEVELOPMENT-PROCESS.md` still holds the engineering best practices (branch protection, release process, architecture pattern). Update it when branch prefixes and file naming are finalized across all agents.
@@ -0,0 +1,285 @@
1
+ # LDM OS Install and Boot Architecture
2
+
3
+ **Date:** 2026-02-27
4
+ **Status:** Migration started 2026-02-27
5
+ **Context:** Parker and CC discussing how Memory Crystal, LDM OS, and Claude Code's project system interact.
6
+
7
+ ## The Problem
8
+
9
+ Claude Code keys all context (sessions, memory, plans, MCP servers, CLAUDE.md) to the directory you open it from. Right now CC is opened from `~/.openclaw/`. Everything works because that's where CLAUDE.md, MCP configs, and all the context lives.
10
+
11
+ But `~/.openclaw/` is OpenClaw's home, not the agent's home. The agent's home should be `~/.ldm/`. And if you open CC from a different directory (a project repo, a new machine), it starts cold. No memory, no tools, no identity.
12
+
13
+ Parker's observation: "I always open Claude in the same place because of the disconnect between being able to remember context."
14
+
15
+ ## The Hub-Spoke Model
16
+
17
+ Parker's working model:
18
+
19
+ - **Hub agent** (CC on Mini, Lesa on Mini) ... full context, full tools, spawns sub-agents as needed
20
+ - **Spoke agent** (CC on Air, CC in a different project dir) ... should connect back to the hub's memory
21
+
22
+ Right now Parker runs two CC windows from `~/.openclaw/`:
23
+ - One context window for Memory Crystal work
24
+ - One context window for AI Pay work
25
+ - Switches between them using saved contexts
26
+
27
+ This works but is fragile. The context is tied to the directory, not the agent.
28
+
29
+ ## The Construct Pattern (Prior Art)
30
+
31
+ Parker previously tried solving this with a tool called "construct" (now deprecated/sunset). The idea:
32
+
33
+ 1. You `init` Claude in any directory
34
+ 2. You run `construct` over that directory
35
+ 3. Construct updates the CLAUDE.md, installs MCP servers, gives Claude all the context it needs
36
+ 4. Now Claude works properly in that directory with full LDM OS capabilities
37
+
38
+ This is the "overlay" pattern: take a vanilla Claude Code directory and overlay LDM OS onto it.
39
+
40
+ ## How Install Could Work
41
+
42
+ ### Memory Crystal Standalone
43
+ - `npm install memory-crystal` or agent-driven install via SKILL.md
44
+ - Creates `~/.ldm/memory/` if it doesn't exist
45
+ - Works immediately. No LDM OS required.
46
+ - Just memory: search, remember, forget.
47
+
48
+ ### LDM OS Full Stack
49
+ - Install Memory Crystal first (it's the entry point)
50
+ - Memory Crystal detects it's standalone, offers: "Want to install LDM OS for Bridge, Relay, and full agent capabilities?"
51
+ - Or: user says "install LDM OS" and it sees Memory Crystal is already there
52
+ - LDM OS install:
53
+ - Scaffolds `~/.ldm/` (agents, memory, extensions, config)
54
+ - Installs Bridge (local agent communication)
55
+ - Configures Relay (multi-device sync)
56
+ - Sets up boot sequence (CLAUDE.md, MCP servers, identity files)
57
+ - Overlays the current Claude Code directory with LDM OS context
58
+
59
+ ### The "Make LDM OS work here" Skill
60
+ - A skill you can run in any Claude Code session
61
+ - It checks: is Memory Crystal installed? Is `~/.ldm/` scaffolded?
62
+ - If yes: overlays CLAUDE.md, MCP config, and boot sequence into the current directory
63
+ - If no: walks you through install first
64
+ - Result: Claude Code works with full LDM OS capabilities from any directory
65
+
66
+ ## Where CC Should Live
67
+
68
+ Options for migrating from `~/.openclaw/` to `~/.ldm/`:
69
+
70
+ 1. **Symlink approach**: `~/.openclaw/` becomes a symlink to `~/.ldm/`. CC still thinks it's in `~/.openclaw/`, all project context preserved. Cleanest migration. But still tied to OpenClaw's name.
71
+
72
+ 2. **Copy project context**: Move `~/.claude/projects/-Users-lesa--openclaw/` to `-Users-lesa--ldm/`. CC picks up context at new path. CLAUDE.md, MCP configs also need to exist at `~/.ldm/`.
73
+
74
+ 3. **Fresh start at `~/.ldm/`**: Crystal memory survives (already at `~/.ldm/memory/crystal.db`). Session history stays searchable via Crystal. You just lose project-specific CC context (plans, todos). Could be fine if Crystal has everything important.
75
+
76
+ 4. **The overlay skill**: Don't move CC. Just make a skill that ensures any directory has the right CLAUDE.md and MCP config. CC opens wherever, the skill makes it work. This is the construct pattern reborn.
77
+
78
+ ## Claude Code's Native Design Patterns (Research, 2026-02-27)
79
+
80
+ Claude Code already has a hierarchy that supports what we need. We don't need to fight it.
81
+
82
+ ### Settings Hierarchy (highest priority wins)
83
+
84
+ 1. Managed settings (enterprise/MDM)
85
+ 2. Command-line arguments
86
+ 3. Local project settings (`.claude/settings.local.json`)
87
+ 4. Shared project settings (`.claude/settings.json`)
88
+ 5. User settings (`~/.claude/settings.json`)
89
+
90
+ ### CLAUDE.md Resolution
91
+
92
+ CC walks UP from the working directory to filesystem root, loading all CLAUDE.md files it finds. More specific (deeper) wins. Child directory CLAUDE.md files load on demand.
93
+
94
+ Key: **`~/.claude/CLAUDE.md` loads in every project, everywhere.** This is the user-global slot.
95
+
96
+ ### What Exists at User Level
97
+
98
+ | Resource | Location | Behavior |
99
+ |----------|----------|----------|
100
+ | `~/.claude/CLAUDE.md` | User-global instructions | Loaded in every session, every project |
101
+ | `~/.claude/rules/` | User-global rules | Apply everywhere, project rules override |
102
+ | `~/.claude/skills/` | User-global skills | Available in any project |
103
+ | `~/.claude/settings.json` | User-global settings | MCP servers, hooks, permissions |
104
+
105
+ ### What This Means for LDM OS
106
+
107
+ The "construct" pattern is already built into Claude Code. We just haven't used it:
108
+
109
+ ```
110
+ ~/.claude/CLAUDE.md <- LDM OS identity + boot sequence
111
+ ~/.claude/rules/ <- LDM OS conventions (git, naming, etc.)
112
+ ~/.claude/skills/ <- "install ldm-os" skill, deploy-public, etc.
113
+ ~/.claude/settings.json <- Crystal MCP, Bridge MCP (user-level, everywhere)
114
+ ```
115
+
116
+ Open CC from any directory. It loads your identity, your rules, your MCP servers. Automatically. No overlay, no construct, no init.
117
+
118
+ Project-level CLAUDE.md still works for project-specific stuff (build commands, test patterns, etc.). User-level is the OS. Project-level is the app.
119
+
120
+ ### MCP Server Scoping
121
+
122
+ ```bash
123
+ # User scope (follows you everywhere)
124
+ claude mcp add --scope user crystal-memory -- node /path/to/mcp-server.js
125
+
126
+ # Project scope (shared via git, .mcp.json)
127
+ claude mcp add --scope project ...
128
+
129
+ # Local scope (personal, this project only)
130
+ claude mcp add ...
131
+ ```
132
+
133
+ Resolution: local > project > user. User-level MCP servers are the baseline.
134
+
135
+ ## The Session Portability Problem (The Blocker)
136
+
137
+ **Sessions are tied to the directory you open CC from.** This is the thing that makes migration hard.
138
+
139
+ ### How It Works
140
+
141
+ - CC stores sessions at `~/.claude/projects/<directory-key>/`
142
+ - Directory key is derived from the working directory path
143
+ - Example: opening from `~/.openclaw/` stores sessions under `-Users-lesa--openclaw/`
144
+ - `--resume` and `--continue` only show sessions from the CURRENT directory by default
145
+
146
+ ### Current State
147
+
148
+ ```
149
+ ~/.claude/projects/-Users-lesa--openclaw/ 33 sessions (all our work)
150
+ ~/.claude/projects/-Users-lesa/ 6 sessions
151
+ ~/.claude/projects/-Users-lesa--openclaw-workspace/ 5 sessions
152
+ ```
153
+
154
+ ### The Workaround
155
+
156
+ In the resume picker, **press `A` to toggle between "current directory only" and "all projects."** So sessions ARE accessible from other directories... you just have to toggle. Not great, but not a wall.
157
+
158
+ ### Why Parker Is Stuck
159
+
160
+ The ideal: open CC from `~/.ldm/`, have full LDM OS capabilities, and resume any session (including the 33 from `~/.openclaw/`).
161
+
162
+ The reality:
163
+ - CLAUDE.md and MCP servers CAN move to user level (works everywhere)
164
+ - Sessions from `~/.openclaw/` stay keyed to that path
165
+ - New sessions from `~/.ldm/` go to a new project key
166
+ - Old sessions accessible via `A` toggle but not the default view
167
+
168
+ Crystal search covers the deep memory. The session transcripts are searchable via `crystal_search`. But the "resume this exact conversation" flow is directory-bound.
169
+
170
+ ### Migration Options (Updated)
171
+
172
+ **Option A: User-level migration (recommended, least risk)**
173
+ - Move CLAUDE.md content to `~/.claude/CLAUDE.md`
174
+ - Move MCP servers to user scope (`claude mcp add --scope user`)
175
+ - Keep opening CC from `~/.openclaw/` (sessions stay accessible)
176
+ - New projects just work because user-level config follows you
177
+ - Downside: still opening from `~/.openclaw/`, but it doesn't matter anymore because the config is at user level
178
+
179
+ **Option B: Directory migration**
180
+ - Move to opening from `~/.ldm/`
181
+ - Old sessions accessible via `A` toggle in resume picker
182
+ - Crystal has the deep memory for search
183
+ - New sessions accumulate under `~/.ldm/` project key
184
+ - Clean break, but old resume flow requires the toggle
185
+
186
+ **Option C: Symlink (preserves everything)**
187
+ - Symlink `~/.openclaw/` to `~/.ldm/`
188
+ - CC still resolves to `-Users-lesa--openclaw` project key
189
+ - All 33 sessions, auto-memory, plans, todos stay accessible
190
+ - User-level config still works on top
191
+ - Downside: the project key name still says "openclaw" forever
192
+
193
+ **Option D: Don't move at all**
194
+ - Put everything at user level (`~/.claude/CLAUDE.md`, user MCP servers)
195
+ - Keep `~/.openclaw/` as just another project directory
196
+ - Open CC from wherever you want
197
+ - LDM OS capabilities follow you via user-level config
198
+ - Sessions are per-project, which is actually fine... Memory Crystal is the cross-project memory
199
+
200
+ **Parker's instinct: Option D might be the answer.** The directory you open from becomes just a project workspace. LDM OS lives at user level. Crystal is the memory that follows you everywhere. Sessions are project-local, which is how Anthropic designed it.
201
+
202
+ ## Identity Architecture (Decision, 2026-02-27)
203
+
204
+ **One agent per harness per machine. That's the identity unit.**
205
+
206
+ ### The Rule
207
+
208
+ Each combination of harness + machine = one agent identity with its own SOUL.md.
209
+
210
+ | Agent ID | Harness | Machine | Identity |
211
+ |----------|---------|---------|----------|
212
+ | cc-mini | Claude Code CLI | Mac Mini | Its own SOUL.md, context, journals |
213
+ | cc-air | Claude Code CLI | MacBook Air | Its own SOUL.md, context, journals |
214
+ | oc-lesa-mini | OpenClaw | Mac Mini | Its own SOUL.md, context, journals |
215
+
216
+ ### Shared vs Local
217
+
218
+ - **Shared (via Crystal):** Memory, facts, preferences, conversation history. All agents search the same crystal.
219
+ - **Local (per agent):** SOUL.md, CONTEXT.md, journals, daily logs. Each agent has its own narrative.
220
+
221
+ cc-mini and cc-air aren't "different versions." They're the same person on different machines. Crystal is what connects them. But their local state (what happened today, what's in progress) is their own.
222
+
223
+ ### Multiple Agents on One Machine
224
+
225
+ Different agent = different OS user account. Lesa runs on one login, a second agent would run on another. One agent per user per machine. No exceptions.
226
+
227
+ ### Each Machine is a Hub
228
+
229
+ The machine itself is an entity in LDM OS. It has:
230
+ - A set of agent instances (cc-mini, oc-lesa-mini)
231
+ - A local crystal.db (synced via Relay to other machines)
232
+ - Its own `~/.ldm/` tree with agent folders
233
+
234
+ This is not dogmatic... it's a design decision that simplifies everything. Identity is deterministic: harness + machine = agent ID. No ambiguity.
235
+
236
+ ## Open Questions
237
+
238
+ - Should CLAUDE.md be generated or maintained by hand? (Currently hand-maintained, very detailed)
239
+ - How do MCP servers follow you across directories? (Currently they're in `~/.claude/settings.json` which is global, but project-level `.mcp.json` overrides)
240
+ - What's the minimum context CC needs to be "you"? (CLAUDE.md + Crystal MCP + identity files?)
241
+ - Is the answer just: Crystal IS the portable context? If Crystal has everything, the boot problem is smaller.
242
+ - How does this work on a new machine with no `~/.ldm/`? Cold start problem.
243
+
244
+ ## Dependency Chain
245
+
246
+ ```
247
+ Memory Crystal (standalone)
248
+ └── creates ~/.ldm/memory/ if needed
249
+ └── works with any AI, no other deps
250
+
251
+ LDM OS (full stack)
252
+ ├── Memory Crystal (memory, search, capture)
253
+ ├── Bridge (local agent communication, feature of Crystal)
254
+ ├── Relay (multi-device sync, feature of Crystal)
255
+ ├── Boot Sequence (warm-start, identity, CLAUDE.md)
256
+ ├── Sovereignty Covenant (trust, authority)
257
+ └── Dream Weaver Protocol (narrative consolidation)
258
+ ```
259
+
260
+ Memory Crystal is the foundation. Everything else builds on it.
261
+
262
+ ## Migration Log
263
+
264
+ ### 2026-02-27: User-level migration (Option D)
265
+
266
+ **What we did:**
267
+ 1. Copied `~/.openclaw/CLAUDE.md` to `~/.claude/CLAUDE.md` (user-level, loads everywhere)
268
+ 2. Added MCP servers at user scope in `~/.claude.json`:
269
+ - `lesa-bridge` (with `OPENCLAW_DIR` env var)
270
+ - `memory-crystal` (with `OPENCLAW_HOME` env var)
271
+ - `wip-agent-pay`
272
+ 3. Left `~/.openclaw/CLAUDE.md` and `.mcp.json` in place (no deletions)
273
+
274
+ **What this means:**
275
+ - Open CC from any directory and get full LDM OS: identity, memory, bridge, tools
276
+ - `~/.openclaw/` stays as a project directory with its 33 sessions
277
+ - New sessions from other directories get full capabilities via user-level config
278
+ - Project-level `.mcp.json` at `~/.openclaw/` still works (local > project > user, no conflict)
279
+
280
+ **What's next:**
281
+ - Test from a random directory to confirm MCP servers load
282
+ - Update `~/.claude/CLAUDE.md` going forward (stop updating `~/.openclaw/CLAUDE.md`)
283
+ - Eventually add `~/.claude/rules/` for LDM OS conventions
284
+ - Eventually add `~/.claude/skills/` for deploy-public, etc.
285
+ - Session naming convention: `cc-mini--topic-name` via `/rename`