@wipcomputer/wip-ldm-os 0.4.0 → 0.4.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  ###### WIP Computer
2
2
 
3
- # LDM OS
3
+ # LDM OS: Learning Dreaming Machines
4
4
 
5
5
  ## All your AIs. One system.
6
6
 
@@ -47,23 +47,27 @@ That's it. Your AI reads the spec, explains what it does, and walks you through
47
47
 
48
48
  Ships with LDM OS.
49
49
 
50
+ **Bridge**
51
+ - Cross-platform agent bridge. Enables Claude Code CLI to talk to OpenClaw CLI without a human in the middle.
52
+ - [Read more about Bridge](docs/bridge/README.md)
53
+
50
54
  **Universal Installer**
51
55
  - Point any skill, application, or plugin at any AI running LDM OS, and it will convert those skills to work with all of your AIs.
52
56
  - Build applications that work with any AI, even ones that don't have LDM OS.
53
- - [Read more about Universal Installer](docs/universal-installer.md)
57
+ - [Read more about Universal Installer](docs/universal-installer/README.md)
54
58
 
55
59
  **Shared Workspace**
56
60
  - One directory for all your AIs. Memories, tools, identity files, boot config. Every AI you use reads from and writes to the same place.
57
61
  - Lives in one folder on your computer. Easy to back up, easy to move, easy to own.
58
- - [Read more about Shared Workspace](docs/shared-workspace.md)
62
+ - [Read more about Shared Workspace](docs/shared-workspace/README.md)
59
63
 
60
64
  **System Pulse**
61
65
  - Is everything working? What's installed? What needs fixing? A complete picture of your AI setup in seconds.
62
- - [Read more about System Pulse](docs/system-pulse.md)
66
+ - [Read more about System Pulse](docs/system-pulse/README.md)
63
67
 
64
68
  **Recall**
65
69
  - Every session, your AI starts with full context. Identity, memory, tools, what happened yesterday. No blank slates. No repeating yourself.
66
- - [Read more about Recall](docs/recall.md)
70
+ - [Read more about Recall](docs/recall/README.md)
67
71
 
68
72
  **LUME**
69
73
  - Language for Unified Memory and Emergence. A memory language for AI agents to document their own learning and maintain continuity across sessions. Not a programming language. A way for your AI to write memories to itself, retrieve past learnings, track unfinished thoughts, and pass context between sessions.
@@ -95,15 +99,11 @@ The OS connects your AIs. Add-ons are what they actually use. Each one is a full
95
99
  - Open-source agent runtime. Run AI agents 24/7 with identity, memory, and tool access. The existence proof for LDM OS.
96
100
  - [Read more about OpenClaw](https://github.com/openclaw/openclaw)
97
101
 
98
- **Bridge**
99
- - Cross-platform agent bridge. Enables Claude Code CLI to talk to OpenClaw CLI without a human in the middle.
100
- - [Read more about Bridge](https://github.com/wipcomputer/wip-bridge)
101
-
102
- [See all skills](docs/optional-skills.md)
102
+ [See all skills](docs/skills/README.md)
103
103
 
104
104
  ## More Info
105
105
 
106
- - [Architecture, principles, and technical details](TECHNICAL.md)
106
+ - [Architecture, principles, and technical details](docs/universal-installer/TECHNICAL.md)
107
107
 
108
108
  ## License
109
109
 
package/SKILL.md CHANGED
@@ -5,7 +5,7 @@ license: MIT
5
5
  interface: [cli, skill]
6
6
  metadata:
7
7
  display-name: "LDM OS"
8
- version: "0.4.0"
8
+ version: "0.4.2"
9
9
  homepage: "https://github.com/wipcomputer/wip-ldm-os"
10
10
  author: "Parker Todd Brooks"
11
11
  category: infrastructure
package/bin/ldm.js CHANGED
@@ -17,7 +17,7 @@
17
17
  * ldm --version Show version
18
18
  */
19
19
 
20
- import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs';
20
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, cpSync, chmodSync } from 'node:fs';
21
21
  import { join, basename, resolve, dirname } from 'node:path';
22
22
  import { execSync } from 'node:child_process';
23
23
  import { fileURLToPath } from 'node:url';
@@ -146,6 +146,28 @@ function cleanStaleHooks() {
146
146
  return cleaned;
147
147
  }
148
148
 
149
+ // ── Boot hook sync (#49) ──
150
+
151
+ function syncBootHook() {
152
+ const srcBoot = join(__dirname, '..', 'src', 'boot', 'boot-hook.mjs');
153
+ const destBoot = join(LDM_ROOT, 'shared', 'boot', 'boot-hook.mjs');
154
+
155
+ if (!existsSync(srcBoot)) return false;
156
+
157
+ try {
158
+ const srcContent = readFileSync(srcBoot, 'utf8');
159
+ let destContent = '';
160
+ try { destContent = readFileSync(destBoot, 'utf8'); } catch {}
161
+
162
+ if (srcContent !== destContent) {
163
+ mkdirSync(dirname(destBoot), { recursive: true });
164
+ writeFileSync(destBoot, srcContent);
165
+ return true;
166
+ }
167
+ } catch {}
168
+ return false;
169
+ }
170
+
149
171
  // ── Catalog helpers ──
150
172
 
151
173
  function loadCatalog() {
@@ -172,6 +194,7 @@ async function cmdInit() {
172
194
  join(LDM_ROOT, 'messages'),
173
195
  join(LDM_ROOT, 'shared', 'boot'),
174
196
  join(LDM_ROOT, 'shared', 'cron'),
197
+ join(LDM_ROOT, 'hooks'),
175
198
  ];
176
199
 
177
200
  const existing = existsSync(VERSION_PATH);
@@ -230,6 +253,27 @@ async function cmdInit() {
230
253
  console.log(` + registry.json created`);
231
254
  }
232
255
 
256
+ // Install global git pre-commit hook (blocks commits on main)
257
+ const hooksDir = join(LDM_ROOT, 'hooks');
258
+ const preCommitDest = join(hooksDir, 'pre-commit');
259
+ const preCommitSrc = join(__dirname, '..', 'templates', 'hooks', 'pre-commit');
260
+ if (!existsSync(hooksDir)) mkdirSync(hooksDir, { recursive: true });
261
+ if (existsSync(preCommitSrc)) {
262
+ cpSync(preCommitSrc, preCommitDest);
263
+ chmodSync(preCommitDest, 0o755);
264
+ // Set global hooksPath if not already set to somewhere else
265
+ try {
266
+ const currentHooksPath = execSync('git config --global core.hooksPath', { encoding: 'utf8' }).trim();
267
+ if (currentHooksPath !== hooksDir) {
268
+ console.log(` ! core.hooksPath already set to ${currentHooksPath}. Not overwriting.`);
269
+ }
270
+ } catch {
271
+ // Not set. Set it.
272
+ execSync(`git config --global core.hooksPath "${hooksDir}"`);
273
+ console.log(` + git pre-commit hook installed (blocks commits on main)`);
274
+ }
275
+ }
276
+
233
277
  console.log('');
234
278
  console.log(` LDM OS v${PKG_VERSION} initialized at ${LDM_ROOT}`);
235
279
  console.log('');
@@ -644,6 +688,11 @@ async function cmdInstallCatalog() {
644
688
  updated++;
645
689
  }
646
690
 
691
+ // Sync boot hook from npm package (#49)
692
+ if (syncBootHook()) {
693
+ ok('Boot hook updated (sessions, messages, updates now active)');
694
+ }
695
+
647
696
  console.log('');
648
697
  console.log(` Updated ${updated}/${updatable.length} extension(s).`);
649
698
 
@@ -1345,7 +1394,7 @@ async function main() {
1345
1394
  await cmdUpdateAll();
1346
1395
  break;
1347
1396
  case 'doctor':
1348
- cmdDoctor();
1397
+ await cmdDoctor();
1349
1398
  break;
1350
1399
  case 'status':
1351
1400
  cmdStatus();
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ // wip-install: thin bootstrap + delegate to ldm install.
3
+ // If ldm is on PATH, delegates immediately.
4
+ // If not, installs LDM OS from npm, then delegates.
5
+ // Replaces the standalone 700-line install.js from wip-ai-devops-toolbox.
6
+
7
+ import { run } from '../lib/bootstrap.mjs';
8
+ run(process.argv.slice(2));
@@ -28,3 +28,7 @@ LDM OS does not currently implement ACP-Comm. The file-based message bus and ses
28
28
  ## License Compatibility
29
29
 
30
30
  Both protocols are Apache 2.0, fully compatible with LDM OS's MIT + AGPLv3 dual license.
31
+
32
+ ---
33
+
34
+ [Technical Reference](./TECHNICAL.md)
@@ -0,0 +1,42 @@
1
+ # ACP Compatibility ... Technical Reference
2
+
3
+ ## Protocols
4
+
5
+ | Protocol | Full Name | Origin | License | Wire Format |
6
+ |----------|-----------|--------|---------|-------------|
7
+ | ACP-Client | Agent Client Protocol | Zed Industries | Apache 2.0 | JSON-RPC (stdio) + HTTP/WebSocket |
8
+ | ACP-Comm | Agent Communication Protocol | IBM / Linux Foundation | Apache 2.0 | REST/HTTP |
9
+ | MCP | Model Context Protocol | Anthropic | MIT | JSON-RPC (stdio) |
10
+
11
+ ## How LDM OS Uses Each
12
+
13
+ **MCP (current):** All LDM OS tools (bridge, sessions, messages, updates, crystal) are MCP servers. Claude Code, Cursor, and any MCP client can use them. This is the primary interface.
14
+
15
+ **ACP-Client (available, not configured):** OpenClaw implements ACP-Client via `@agentclientprotocol/sdk`. It enables IDE-to-agent communication (Zed, VS Code). LDM OS could expose services via ACP-Client for IDE integration. The transport-agnostic core design supports adding ACP-Client as another wrapper.
16
+
17
+ **ACP-Comm (not implemented):** Agent-to-agent REST protocol. LDM OS's file-based message bus and session registry serve the same purpose locally. Cloud relay (Phase 7) may evaluate ACP-Comm as a wire protocol for remote agent-to-agent communication.
18
+
19
+ ## Architecture
20
+
21
+ ```
22
+ LDM OS Core (pure functions, zero deps)
23
+ |
24
+ |-- MCP wrapper (current, all tools)
25
+ |-- ACP-Client wrapper (future, IDE integration)
26
+ |-- ACP-Comm wrapper (future, cloud relay)
27
+ |-- HTTP wrapper (future, web/iOS)
28
+ ```
29
+
30
+ Same core logic. Different transports. The core doesn't know or care which protocol is calling it.
31
+
32
+ ## License Compatibility
33
+
34
+ Both ACP protocols are Apache 2.0. LDM OS is MIT + AGPLv3 dual license. Apache 2.0 is compatible with both. No license conflicts.
35
+
36
+ ## Key Files
37
+
38
+ | File | What |
39
+ |------|------|
40
+ | `src/bridge/mcp-server.ts` | MCP server (current interface) |
41
+ | `lib/sessions.mjs` | Session register (could expose via ACP-Comm) |
42
+ | `lib/messages.mjs` | Message bus (could expose via ACP-Comm) |
@@ -0,0 +1,55 @@
1
+ ###### WIP Computer
2
+
3
+ # Bridge
4
+
5
+ ## Your AIs talk to each other.
6
+
7
+ Cross-platform agent communication. Bridge (MCP), Agent Client Protocol (ACP-Client, Zed Industries), and Agent Communication Protocol (ACP-Comm, IBM/Linux Foundation). Three protocols, one system. Claude Code sends a message, OpenClaw responds. OpenClaw sends a task, Claude Code executes it.
8
+
9
+ ## Three Protocols, One System
10
+
11
+ LDM OS uses three complementary protocols. Bridge is one of them.
12
+
13
+ | | Bridge | ACP-Client | ACP-Comm |
14
+ |---|---|---|---|
15
+ | **What** | Agent-to-agent messaging + shared memory | IDE-to-agent communication | Agent-to-agent REST API |
16
+ | **Protocol** | MCP (JSON-RPC over stdio) | JSON-RPC over stdio + WebSocket | REST/HTTP |
17
+ | **Built by** | WIP Computer | Zed Industries | IBM / Linux Foundation |
18
+ | **In LDM OS** | Core (v0.3.0+) | Available via OpenClaw | Planned (Cloud Relay) |
19
+ | **What it connects** | Claude Code <-> OpenClaw agents | IDEs (Zed, VS Code) <-> agents | Cloud agents <-> each other |
20
+ | **Memory access** | Yes (search + read across agents) | No | No |
21
+ | **Skill sharing** | Yes (OpenClaw skills as MCP tools) | No | No |
22
+ | **Where it runs** | Localhost only | Localhost (stdio) + remote (WebSocket) | Cloud (HTTP endpoints) |
23
+
24
+ **Bridge** is how your AIs talk to each other and share memory. **ACP-Client** is how IDEs talk to agents (OpenClaw already implements this). **ACP-Comm** is how agents would talk across the network (planned for Cloud Relay, Phase 7).
25
+
26
+ All three are Apache 2.0 compatible with our MIT + AGPL license. See [ACP docs](../acp/README.md).
27
+
28
+ ## Tools
29
+
30
+ | Tool | What |
31
+ |------|------|
32
+ | `lesa_send_message` | Send a message to the OpenClaw agent. Gets a response. |
33
+ | `lesa_check_inbox` | Check for messages the agent sent to you. |
34
+ | `lesa_conversation_search` | Semantic search over conversation history. |
35
+ | `lesa_memory_search` | Keyword search across workspace files. |
36
+ | `lesa_read_workspace` | Read a file from the agent's workspace. |
37
+ | `oc_skills_list` | List all OpenClaw skills. |
38
+ | `oc_skill_*` | Run any OpenClaw skill with scripts. |
39
+
40
+ ## Message Flow
41
+
42
+ ```
43
+ CC --lesa_send_message--> OpenClaw Gateway (localhost:18789) --> Lesa
44
+ CC <--lesa_check_inbox--- HTTP Inbox (localhost:18790) <-- Lesa
45
+ ```
46
+
47
+ Both directions are live. Everything is localhost. No cloud.
48
+
49
+ ## Part of LDM OS
50
+
51
+ Bridge ships with LDM OS v0.3.0+. The standalone repo is deprecated: [wip-bridge-deprecated](https://github.com/wipcomputer/wip-bridge-deprecated).
52
+
53
+ ---
54
+
55
+ [Technical Reference](./TECHNICAL.md)
@@ -0,0 +1,153 @@
1
+ # Bridge ... Technical Reference
2
+
3
+ ## Architecture
4
+
5
+ ```
6
+ Claude Code CLI
7
+ |
8
+ |-- MCP stdio --> wip-bridge MCP server (single process)
9
+ | |
10
+ | |-- lesa_send_message --> HTTP POST localhost:18789 (OpenClaw gateway)
11
+ | | |
12
+ | | v
13
+ | | Lesa's agent pipeline
14
+ | | |
15
+ | | v
16
+ | | Response returned
17
+ | |
18
+ | |-- lesa_check_inbox --> HTTP GET localhost:18790 (Bridge inbox)
19
+ | |
20
+ | |-- lesa_conversation_search --> SQLite (context-embeddings.sqlite)
21
+ | |
22
+ | |-- lesa_memory_search --> filesystem (workspace/*.md)
23
+ | |
24
+ | |-- oc_skill_* --> exec scripts in ~/.openclaw/extensions/*/skills/
25
+ ```
26
+
27
+ ## MCP Tools
28
+
29
+ | Tool | What | Transport |
30
+ |------|------|-----------|
31
+ | `lesa_send_message` | Send message to OpenClaw agent | HTTP POST to gateway (localhost:18789) |
32
+ | `lesa_check_inbox` | Check for pending messages from agent | In-memory queue (drained on read) |
33
+ | `lesa_conversation_search` | Semantic search over conversation history | SQLite + OpenAI embeddings |
34
+ | `lesa_memory_search` | Keyword search across workspace .md files | Filesystem scan |
35
+ | `lesa_read_workspace` | Read a specific workspace file | Filesystem |
36
+ | `oc_skill_*` | Execute OpenClaw skill scripts | child_process exec |
37
+ | `oc_skills_list` | List all available OpenClaw skills | Filesystem scan |
38
+
39
+ ## Config Resolution
40
+
41
+ Bridge resolves config in two steps:
42
+
43
+ 1. **LDM OS path** (`~/.ldm/config.json`): checks for `openclawDir`, `workspaceDir`, `dbPath`
44
+ 2. **Legacy path** (`OPENCLAW_DIR` env or `~/.openclaw`): fallback
45
+
46
+ Both return the same `BridgeConfig` shape: `openclawDir`, `workspaceDir`, `dbPath`, `inboxPort`, `embeddingModel`, `embeddingDimensions`.
47
+
48
+ ## Gateway Authentication
49
+
50
+ Bridge reads the gateway auth token from `~/.openclaw/openclaw.json` (`gateway.auth.token`). Every HTTP request to the gateway includes `Authorization: Bearer <token>`.
51
+
52
+ ## Conversation Search
53
+
54
+ Two modes:
55
+ 1. **Vector search** (if OpenAI API key available): embeds query, computes cosine similarity against all conversation chunks, applies recency weighting (exponential decay, half-life ~50 days)
56
+ 2. **Text search** (fallback): SQL LIKE query against chunk text
57
+
58
+ The API key is resolved from: environment variable > 1Password via service account token.
59
+
60
+ ## Inbox Server
61
+
62
+ Bridge starts a localhost-only HTTP server on port 18790:
63
+ - `POST /message`: push a message (from OpenClaw agent)
64
+ - `GET /status`: check pending count
65
+
66
+ Messages are held in memory. `lesa_check_inbox` drains the queue.
67
+
68
+ ## Key Files
69
+
70
+ | File | What |
71
+ |------|------|
72
+ | `src/bridge/core.ts` | Pure logic: config, messaging, search, skills |
73
+ | `src/bridge/mcp-server.ts` | MCP server: tool registration, inbox HTTP server |
74
+ | `src/bridge/cli.ts` | CLI wrapper (`lesa` command) |
75
+ | `dist/bridge/` | Compiled output (ships with npm package) |
76
+
77
+ ## Node Communication (Future)
78
+
79
+ Bridge currently works localhost only (Core). For Node -> Core communication:
80
+ - Phase 7 (Cloud Relay) handles messaging via encrypted Cloudflare R2 dead drops
81
+ - Search, workspace read, and skill execution from a Node are NOT yet covered
82
+ - Two proposed solutions: proxy pattern (Node sends requests through relay) and sync pattern (replicate crystal.db to Node)
83
+
84
+ See `ai/products/plans-prds/current/ldm-stack-spec.md` for the full platform matrix.
85
+
86
+ ## CLI Usage
87
+
88
+ ```bash
89
+ lesa send "What are you working on?" # Message the OpenClaw agent
90
+ lesa search "API key resolution" # Semantic search (recency-weighted)
91
+ lesa memory "compaction" # Keyword search across workspace files
92
+ lesa read MEMORY.md # Read a workspace file
93
+ lesa read memory/2026-02-10.md # Read a daily log
94
+ lesa status # Show bridge configuration
95
+ lesa diagnose # Check gateway, inbox, DB, skills health
96
+ ```
97
+
98
+ ## Skill Bridge
99
+
100
+ On startup, Bridge scans OpenClaw's skill directories and exposes them as MCP tools. Claude Code gets the same skills the OpenClaw agent has.
101
+
102
+ 1. Scans `extensions/*/node_modules/openclaw/skills/` (built-in) and `extensions/*/skills/` (custom)
103
+ 2. Parses each `SKILL.md` frontmatter for name, description, requirements
104
+ 3. Skills with a `scripts/` folder get registered as executable `oc_skill_{name}` tools
105
+ 4. All skills show up in `oc_skills_list`
106
+
107
+ Skills that need API keys get them from the environment. The op-secrets plugin sets these from 1Password.
108
+
109
+ ## Inbox Watcher (Auto-Relay)
110
+
111
+ Polls the inbox endpoint and auto-injects messages into a running Claude Code tmux session.
112
+
113
+ ```bash
114
+ bash scripts/watch.sh # Alert mode (notification only)
115
+ bash scripts/watch.sh --auto claude:0.0 # Auto-inject into tmux pane
116
+ ```
117
+
118
+ | Setting | Default | Description |
119
+ |---------|---------|-------------|
120
+ | `POLL_INTERVAL` | `5` | Seconds between inbox checks |
121
+ | `COOLDOWN` | `30` | Minimum seconds between alerts |
122
+ | `INBOX_URL` | `http://127.0.0.1:18790/status` | Inbox status endpoint |
123
+
124
+ ## OpenClaw Skills (Lesa -> CC)
125
+
126
+ Two skills shipped with Bridge for the reverse direction:
127
+
128
+ | Skill | What |
129
+ |-------|------|
130
+ | `claude-code` | Invoke Claude Code CLI for coding tasks (`claude -p`) |
131
+ | `send-to-claude-code` | Push messages into CC's live inbox (POST localhost:18790) |
132
+
133
+ ## Environment Variables
134
+
135
+ | Variable | Required | Default | Description |
136
+ |----------|----------|---------|-------------|
137
+ | `OPENCLAW_DIR` | Yes | `~/.openclaw` | Path to OpenClaw installation |
138
+ | `OPENAI_API_KEY` | For semantic search | Resolved from 1Password | OpenAI API key for embeddings |
139
+ | `LESA_BRIDGE_INBOX_PORT` | No | `18790` | Inbox HTTP server port |
140
+
141
+ ## Ports
142
+
143
+ | Port | Service | Bound to |
144
+ |------|---------|----------|
145
+ | 18789 | OpenClaw gateway | localhost (managed by OpenClaw) |
146
+ | 18790 | Bridge inbox | localhost (managed by Bridge) |
147
+
148
+ ## Requirements
149
+
150
+ - OpenClaw running with gateway enabled
151
+ - `gateway.auth.token` set in `openclaw.json`
152
+ - `gateway.http.endpoints.chatCompletions.enabled: true`
153
+ - OpenAI API key for semantic search (falls back to text search without it)
@@ -27,3 +27,7 @@ With Recall, your AI remembers. Not just facts, but the arc of what you're build
27
27
  ## Part of LDM OS
28
28
 
29
29
  Recall is included with LDM OS. It activates automatically after `ldm init`.
30
+
31
+ ---
32
+
33
+ [Technical Reference](./TECHNICAL.md)
@@ -0,0 +1,41 @@
1
+ # Recall ... Technical Reference
2
+
3
+ ## Boot Sequence
4
+
5
+ Recall is implemented as a SessionStart hook. When Claude Code opens a session, the boot hook loads context files in order:
6
+
7
+ ```
8
+ 1. CLAUDE.md Identity + structure (harness config)
9
+ 2. SHARED-CONTEXT.md Current state (under 50 lines)
10
+ 3. Most recent journal Narrative from last session
11
+ 4. Daily logs (today + yesterday) Recency
12
+ 5. Full history (cold start) Dream Weaver narrative
13
+ 6. CONTEXT.md Agent's own state
14
+ 7. SOUL.md Who this agent is
15
+ 8. Agent journals Check for newer entries
16
+ 9. Agent daily logs Check for newer entries
17
+ ```
18
+
19
+ ## Key Files
20
+
21
+ | File | What |
22
+ |------|------|
23
+ | `src/boot/boot-hook.mjs` | SessionStart hook (reads + injects context) |
24
+ | `src/boot/boot-config.json` | Which files to load, in what order |
25
+ | `src/boot/installer.mjs` | Deploys boot hook to `~/.ldm/shared/boot/` |
26
+
27
+ ## How It Works
28
+
29
+ The boot hook reads `boot-config.json` to determine which files to load. Each entry specifies a path pattern and priority. Files are read in priority order and concatenated into the session context.
30
+
31
+ The hook runs with a 15-second timeout. If any file is missing, it's skipped silently. The boot sequence is additive. It never modifies files, only reads them.
32
+
33
+ ## Harness Differences
34
+
35
+ **Claude Code CLI:** Full boot sequence. Identity, context, journals, daily logs all loaded via SessionStart hook.
36
+
37
+ **OpenClaw:** Has its own boot sequence (workspace files). Recall provides backup context loading if the harness boot fails or is incomplete.
38
+
39
+ ## Session Registration
40
+
41
+ On boot, Recall also registers the session in the Agent Register (`~/.ldm/sessions/`). This enables other sessions to discover this one via `ldm sessions`.
@@ -35,3 +35,7 @@ LDM OS never touches your existing data during install or update. Your memories,
35
35
  ## Part of LDM OS
36
36
 
37
37
  Shared Workspace is included with LDM OS. Run `ldm init` to create it.
38
+
39
+ ---
40
+
41
+ [Technical Reference](./TECHNICAL.md)
@@ -0,0 +1,75 @@
1
+ # Shared Workspace ... Technical Reference
2
+
3
+ ## Directory Structure
4
+
5
+ ```
6
+ ~/.ldm/
7
+ config.json Machine-level config
8
+ version.json Installed version + timestamps
9
+ extensions/
10
+ registry.json Extension metadata
11
+ memory-crystal/ Extension files
12
+ wip-release/ Extension files
13
+ ...
14
+ agents/
15
+ cc-mini/ Claude Code on Mac Mini
16
+ IDENTITY.md
17
+ SOUL.md
18
+ CONTEXT.md
19
+ REFERENCE.md
20
+ config.json
21
+ memory/
22
+ transcripts/ Raw JSONL session files
23
+ sessions/ MD per-session summaries
24
+ daily/ Daily log breadcrumbs
25
+ journals/ Dream Weaver narrative output
26
+ oc-lesa-mini/ OpenClaw/Lesa on Mac Mini
27
+ memory/
28
+ transcripts/ Raw JSONL copies (backup)
29
+ workspace/ Workspace .md snapshots
30
+ daily/ Daily log copies
31
+ memory/
32
+ crystal.db Shared vector DB (all agents)
33
+ sessions/ Active session files (Agent Register)
34
+ messages/ Inter-session messages (Message Bus)
35
+ shared/
36
+ boot/ Boot hook files
37
+ cron/ Cron job scripts
38
+ state/ Capture watermarks, role state
39
+ secrets/ Encryption keys, relay tokens
40
+ bin/ Deployed scripts
41
+ backups/ Daily backups
42
+ ```
43
+
44
+ ## Sacred Data
45
+
46
+ These paths are never overwritten during install or update:
47
+
48
+ - `memory/` (crystal.db, all vector data)
49
+ - `agents/` (identity, soul, context, journals, transcripts)
50
+ - `secrets/` (encryption keys, tokens)
51
+ - `state/` (watermarks, capture state)
52
+ - `backups/` (daily snapshots)
53
+
54
+ Only `extensions/` and `shared/` are updated by `ldm install`.
55
+
56
+ ## Agent Identity
57
+
58
+ One agent per harness per machine. The agent ID is deterministic:
59
+
60
+ | Agent ID | Harness | Machine |
61
+ |----------|---------|---------|
62
+ | `cc-mini` | Claude Code CLI | Mac Mini |
63
+ | `cc-air` | Claude Code CLI | MacBook Air |
64
+ | `oc-lesa-mini` | OpenClaw | Mac Mini |
65
+
66
+ All agents share one `crystal.db`. Memory is shared. Identity is per-agent.
67
+
68
+ ## Key Files
69
+
70
+ | File | What |
71
+ |------|------|
72
+ | `bin/ldm.js` | CLI: `ldm init` creates the workspace |
73
+ | `lib/deploy.mjs` | Extension deployment engine |
74
+ | `lib/state.mjs` | System state detection |
75
+ | `lib/safe.mjs` | Trash management (never delete, always move) |
@@ -6,6 +6,11 @@ Your AIs are only as powerful as what you give them. Here's everything available
6
6
 
7
7
  ## Core
8
8
 
9
+ **Bridge**
10
+ - Cross-platform agent communication. Bridge (MCP), Agent Client Protocol (ACP-Client), and Agent Communication Protocol (ACP-Comm). Three protocols, one system.
11
+ - *Included with LDM OS*
12
+ - [Read more about Bridge](../bridge/README.md)
13
+
9
14
  **Memory Crystal**
10
15
  - All your AI tools. One shared memory. Private, searchable, sovereign. Memory Crystal lets all your AIs remember you ... together. You use multiple AIs. They don't talk to each other. They can't search what the others know. Memory Crystal fixes this. All your AIs share one memory. Searchable and private. Anywhere in the world.
11
16
  - *Stable*
@@ -28,10 +33,6 @@ Your AIs are only as powerful as what you give them. Here's everything available
28
33
  - Open-source agent runtime. Run AI agents 24/7 with identity, memory, and tool access. The existence proof for LDM OS.
29
34
  - [Read more about OpenClaw](https://github.com/openclaw/openclaw)
30
35
 
31
- **Bridge**
32
- - Cross-platform agent bridge. Enables Claude Code CLI to talk to OpenClaw CLI without a human in the middle.
33
- - [Read more about Bridge](https://github.com/wipcomputer/wip-bridge)
34
-
35
36
  ## Identity
36
37
 
37
38
  **Mirror Test** *(not yet public)*
@@ -75,3 +76,7 @@ Your AIs are only as powerful as what you give them. Here's everything available
75
76
  **X Platform**
76
77
  - X Platform API. Read posts, search tweets, post, upload media.
77
78
  - [Read more about X Platform](https://github.com/wipcomputer/wip-xai-x)
79
+
80
+ ---
81
+
82
+ [Technical Reference](./TECHNICAL.md)
@@ -0,0 +1,67 @@
1
+ # Skills ... Technical Reference
2
+
3
+ ## Catalog
4
+
5
+ Skills are defined in `catalog.json` at the LDM OS root. Each entry has:
6
+
7
+ ```json
8
+ {
9
+ "id": "memory-crystal",
10
+ "name": "Memory Crystal",
11
+ "description": "Persistent memory for your AI.",
12
+ "npm": "@wipcomputer/memory-crystal",
13
+ "repo": "wipcomputer/memory-crystal",
14
+ "registryMatches": ["memory-crystal"],
15
+ "cliMatches": ["crystal"],
16
+ "recommended": true,
17
+ "status": "stable"
18
+ }
19
+ ```
20
+
21
+ ## Stacks
22
+
23
+ Stacks group skills for team installs. Defined in `catalog.json`:
24
+
25
+ ```json
26
+ {
27
+ "stacks": {
28
+ "core": {
29
+ "name": "WIP Core",
30
+ "components": ["memory-crystal", "wip-ai-devops-toolbox", "wip-1password", "wip-markdown-viewer"],
31
+ "mcpServers": []
32
+ },
33
+ "web": {
34
+ "name": "Web Development",
35
+ "components": [],
36
+ "mcpServers": [
37
+ { "name": "playwright", "command": "npx", "args": ["-y", "@playwright/mcp@latest"] }
38
+ ]
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ Stacks are composable via the `includes` field.
45
+
46
+ ## Interface Detection
47
+
48
+ `ldm install` auto-detects which interfaces a repo supports:
49
+
50
+ | Pattern | Interface | Install Action |
51
+ |---------|-----------|---------------|
52
+ | `package.json` with `bin` | CLI | `npm install -g` from registry |
53
+ | `main` or `exports` | Module | Reports import path |
54
+ | `mcp-server.mjs` | MCP | `claude mcp add --scope user` |
55
+ | `openclaw.plugin.json` | OpenClaw Plugin | Deploy to `~/.ldm/extensions/` + `~/.openclaw/extensions/` |
56
+ | `SKILL.md` | Skill | Deploy to `~/.openclaw/skills/` |
57
+ | `guard.mjs` or `claudeCode.hook` | CC Hook | Add to `~/.claude/settings.json` |
58
+ | `.claude-plugin/plugin.json` | CC Plugin | Register with marketplace |
59
+
60
+ ## Key Files
61
+
62
+ | File | What |
63
+ |------|------|
64
+ | `catalog.json` | Component + stack definitions |
65
+ | `lib/detect.mjs` | Interface detection engine |
66
+ | `lib/deploy.mjs` | Deployment engine |
67
+ | `bin/ldm.js` | `ldm stack` and `ldm install` commands |
@@ -24,3 +24,7 @@ System Pulse tells you the state of your entire AI setup in seconds. What's inst
24
24
  ## Part of LDM OS
25
25
 
26
26
  System Pulse is included with LDM OS. Available after `ldm init`.
27
+
28
+ ---
29
+
30
+ [Technical Reference](./TECHNICAL.md)
@@ -0,0 +1,56 @@
1
+ # System Pulse ... Technical Reference
2
+
3
+ ## Commands
4
+
5
+ ### ldm doctor
6
+
7
+ Checks system health across all components:
8
+
9
+ 1. `~/.ldm/` exists
10
+ 2. `version.json` valid and version matches CLI
11
+ 3. Full system state scan (extensions, MCP, CLIs, skills)
12
+ 4. Reconciliation (registry vs deployed vs MCP registered)
13
+ 5. Sacred directories exist (memory/, agents/, state/, sessions/, messages/)
14
+ 6. Claude Code hooks configured (checks for stale paths)
15
+ 7. MCP servers registered
16
+ 8. CLI binaries on PATH
17
+
18
+ With `--fix`:
19
+ - Removes stale registry entries (registered but not deployed)
20
+ - Removes stale hook paths from `~/.claude/settings.json` (missing files, `/tmp/` paths)
21
+
22
+ ### ldm status
23
+
24
+ Quick overview: version, install date, extension count, extension list with versions.
25
+
26
+ ### ldm updates
27
+
28
+ Shows cached update check results. Use `--check` to re-scan npm for newer versions of installed extensions.
29
+
30
+ ## State Detection
31
+
32
+ `lib/state.mjs` scans the real system:
33
+
34
+ | Source | What it finds |
35
+ |--------|--------------|
36
+ | `~/.claude.json` | MCP servers (user scope) |
37
+ | `~/.ldm/extensions/` | Deployed extensions (LDM) |
38
+ | `~/.openclaw/extensions/` | Deployed extensions (OpenClaw) |
39
+ | `~/.ldm/extensions/registry.json` | Registry metadata |
40
+ | PATH | CLI binaries (with 5s timeout per binary) |
41
+ | `~/.openclaw/skills/` | Deployed skills |
42
+
43
+ Reconciliation compares all sources and determines status:
44
+ - `healthy`: registered + deployed + source available
45
+ - `installed-unlinked`: registered + deployed, no source repo
46
+ - `registered-missing`: in registry but not deployed
47
+ - `deployed-unregistered`: deployed but not in registry
48
+ - `mcp-only`: MCP server without LDM management
49
+
50
+ ## Key Files
51
+
52
+ | File | What |
53
+ |------|------|
54
+ | `bin/ldm.js` | `cmdDoctor()`, `cmdStatus()`, `cmdUpdates()` |
55
+ | `lib/state.mjs` | `detectSystemState()`, `reconcileState()`, `formatReconciliation()` |
56
+ | `lib/updates.mjs` | npm version checking, manifest caching |
@@ -0,0 +1,206 @@
1
+ # The Universal Interface Specification
2
+
3
+ Every tool is a sensor, an actuator, or both. Every tool should be accessible through multiple interfaces. We call this the Universal Interface.
4
+
5
+ This is the spec.
6
+
7
+ ## The Six Interfaces
8
+
9
+ ### 1. CLI
10
+
11
+ A shell command. The most universal interface. If it has a terminal, it works.
12
+
13
+ **Convention:** `package.json` with a `bin` field.
14
+
15
+ **Detection:** `pkg.bin` exists.
16
+
17
+ **Install:** `npm install -g .` or `npm link`.
18
+
19
+ ```json
20
+ {
21
+ "bin": {
22
+ "wip-grok": "./cli.mjs"
23
+ }
24
+ }
25
+ ```
26
+
27
+ ### 2. Module
28
+
29
+ An importable ES module. The programmatic interface. Other tools compose with it.
30
+
31
+ **Convention:** `package.json` with `main` or `exports` field. File is `core.mjs` by convention.
32
+
33
+ **Detection:** `pkg.main` or `pkg.exports` exists.
34
+
35
+ **Install:** `npm install <package>` or import directly from path.
36
+
37
+ ```json
38
+ {
39
+ "type": "module",
40
+ "main": "core.mjs",
41
+ "exports": {
42
+ ".": "./core.mjs",
43
+ "./cli": "./cli.mjs"
44
+ }
45
+ }
46
+ ```
47
+
48
+ ### 3. MCP Server
49
+
50
+ A JSON-RPC server implementing the Model Context Protocol. Any MCP-compatible agent can use it.
51
+
52
+ **Convention:** `mcp-server.mjs` (or `.js`, `.ts`) at the repo root. Uses `@modelcontextprotocol/sdk`.
53
+
54
+ **Detection:** One of `mcp-server.mjs`, `mcp-server.js`, `mcp-server.ts`, `dist/mcp-server.js` exists.
55
+
56
+ **Install:** Add to `.mcp.json`:
57
+
58
+ ```json
59
+ {
60
+ "tool-name": {
61
+ "command": "node",
62
+ "args": ["/path/to/mcp-server.mjs"]
63
+ }
64
+ }
65
+ ```
66
+
67
+ ### 4. OpenClaw Plugin
68
+
69
+ A plugin for OpenClaw agents. Lifecycle hooks, tool registration, settings.
70
+
71
+ **Convention:** `openclaw.plugin.json` at the repo root.
72
+
73
+ **Detection:** `openclaw.plugin.json` exists.
74
+
75
+ **Install:** Copy to `~/.openclaw/extensions/<name>/`, run `npm install --omit=dev`.
76
+
77
+ ### 5. Skill (SKILL.md)
78
+
79
+ A markdown file that teaches agents when and how to use the tool. The instruction interface.
80
+
81
+ **Convention:** `SKILL.md` at the repo root. YAML frontmatter with name, version, description, metadata.
82
+
83
+ **Detection:** `SKILL.md` exists.
84
+
85
+ **Install:** Referenced by path. Agents read it when they need the tool.
86
+
87
+ ```yaml
88
+ ---
89
+ name: wip-grok
90
+ version: 1.0.0
91
+ description: xAI Grok API. Search the web, search X, generate images.
92
+ metadata:
93
+ category: search,media
94
+ capabilities:
95
+ - web-search
96
+ - image-generation
97
+ ---
98
+ ```
99
+
100
+ ### 6. Claude Code Hook
101
+
102
+ A hook that runs during Claude Code's tool lifecycle (PreToolUse, Stop, etc.).
103
+
104
+ **Convention:** `guard.mjs` at repo root, or `claudeCode.hook` in `package.json`.
105
+
106
+ **Detection:** `guard.mjs` exists, or `pkg.claudeCode.hook` is defined.
107
+
108
+ **Install:** Added to `~/.claude/settings.json` under `hooks`.
109
+
110
+ ```json
111
+ {
112
+ "hooks": {
113
+ "PreToolUse": [{
114
+ "matcher": "Edit|Write",
115
+ "hooks": [{
116
+ "type": "command",
117
+ "command": "node /path/to/guard.mjs",
118
+ "timeout": 5
119
+ }]
120
+ }]
121
+ }
122
+ }
123
+ ```
124
+
125
+ ## Architecture
126
+
127
+ Every repo that follows this spec has the same basic structure:
128
+
129
+ ```
130
+ your-tool/
131
+ core.mjs pure logic, zero or minimal deps
132
+ cli.mjs thin CLI wrapper around core
133
+ mcp-server.mjs MCP server wrapping core functions as tools
134
+ SKILL.md agent instructions with YAML frontmatter
135
+ package.json name, bin, main, exports, type: module
136
+ README.md human documentation
137
+ ai/ development process (plans, todos, notes)
138
+ ```
139
+
140
+ Not every tool needs all six interfaces. Build the ones that make sense.
141
+
142
+ The minimum viable agent-native tool has two interfaces: **Module** (importable) and **Skill** (agent instructions). Add CLI for humans. Add MCP for agents that speak MCP. Add OpenClaw/CC Hook for specific platforms.
143
+
144
+ ## The `ai/` Folder
145
+
146
+ Every repo should have an `ai/` folder. This is where agents and humans collaborate on the project ... plans, todos, dev updates, research notes, conversations.
147
+
148
+ ```
149
+ ai/
150
+ plan/ architecture plans, roadmaps
151
+ dev-updates/ what was built, session logs
152
+ todos/
153
+ PUNCHLIST.md blockers to ship
154
+ inboxes/ per-agent action items
155
+ notes/ research, references, raw conversation logs
156
+ ```
157
+
158
+ The `ai/` folder is the development process. It is not part of the published product.
159
+
160
+ **Public/private split:** If a repo is public, the `ai/` folder should not ship. The recommended pattern is to maintain a private working repo (with `ai/`) and a public repo (everything except `ai/`). The public repo has everything an LLM or human needs to understand and use the tool. The `ai/` folder is operational context for the team building it.
161
+
162
+ ## The Reference Installer
163
+
164
+ `ldm install` is the primary installer (part of LDM OS). `wip-install` is the standalone fallback. Both scan a repo, detect which interfaces exist, and install them all. One command.
165
+
166
+ ```bash
167
+ ldm install /path/to/repo # local (via LDM OS)
168
+ ldm install org/repo # from GitHub
169
+ ldm install org/repo --dry-run # detect only
170
+ wip-install /path/to/repo # standalone fallback (bootstraps LDM OS if needed)
171
+ wip-install --json /path/to/repo # JSON output
172
+ ```
173
+
174
+ For toolbox repos (with a `tools/` directory containing sub-tools), the installer enters toolbox mode and installs each sub-tool.
175
+
176
+ ## Examples
177
+
178
+ ### AI DevOps Toolbox (this repo)
179
+
180
+ | # | Tool | Interfaces |
181
+ |---|------|------------|
182
+ | | **Repo Management** | |
183
+ | 1 | [Repo Visibility Guard](tools/wip-repo-permissions-hook/) | CLI + Module + MCP + OpenClaw + Skill + CC Hook |
184
+ | 2 | [Repo Manifest Reconciler](tools/wip-repos/) | CLI + Module + MCP + Skill |
185
+ | 3 | [Repo Init](tools/wip-repo-init/) | CLI + Skill |
186
+ | 4 | [README Formatter](tools/wip-readme-format/) | CLI + Skill |
187
+ | 5 | [Branch Guard](tools/wip-branch-guard/) | CLI + Module + CC Hook |
188
+ | | **License, Compliance, and Protection** | |
189
+ | 6 | [Identity File Protection](tools/wip-file-guard/) | CLI + Module + OpenClaw + Skill + CC Hook |
190
+ | 7 | [License Guard](tools/wip-license-guard/) | CLI + Skill |
191
+ | 8 | [License Rug-Pull Detection](tools/wip-license-hook/) | CLI + Module + MCP + Skill |
192
+ | | **Release & Deploy** | |
193
+ | 9 | [Release Pipeline](tools/wip-release/) | CLI + Module + MCP + Skill |
194
+ | 10 | [Private-to-Public Sync](tools/deploy-public/) | CLI + Skill |
195
+ | 11 | [Post-Merge Branch Naming](tools/post-merge-rename/) | CLI + Skill |
196
+ | 12 | [Universal Installer](tools/wip-universal-installer/) | CLI + Module + Skill |
197
+
198
+ ### Other WIP Computer Tools
199
+
200
+ | Repo | Interfaces |
201
+ |------|------------|
202
+ | [Memory Crystal](https://github.com/wipcomputer/memory-crystal) | CLI + Module + MCP + OpenClaw + Skill |
203
+ | [LDM OS](https://github.com/wipcomputer/wip-ldm-os) | CLI + Module + Skill + CC Hook |
204
+ | [wip-grok](https://github.com/wipcomputer/wip-grok) | CLI + Module + MCP + Skill |
205
+ | [wip-x](https://github.com/wipcomputer/wip-x) | CLI + Module + MCP + Skill |
206
+ | [Markdown Viewer](https://github.com/wipcomputer/wip-markdown-viewer) | CLI + Module |
@@ -0,0 +1,92 @@
1
+ /**
2
+ * lib/bootstrap.mjs
3
+ * Thin bootstrap for wip-install.
4
+ * If ldm is on PATH, delegates to ldm install.
5
+ * If not, installs LDM OS from npm, then delegates.
6
+ * This replaces the 700-line standalone install.js from the toolbox.
7
+ * Zero external dependencies.
8
+ */
9
+
10
+ import { execSync } from 'node:child_process';
11
+
12
+ /**
13
+ * Check if ldm CLI is available on PATH.
14
+ * @returns {boolean}
15
+ */
16
+ export function isLdmAvailable() {
17
+ try {
18
+ execSync('ldm --version', { stdio: 'pipe', timeout: 5000 });
19
+ return true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Install LDM OS from npm registry.
27
+ * @returns {boolean} true if install succeeded
28
+ */
29
+ export function bootstrapLdmOs() {
30
+ try {
31
+ execSync('npm install -g @wipcomputer/wip-ldm-os', { stdio: 'pipe', timeout: 120000 });
32
+ execSync('ldm init --yes --none', { stdio: 'pipe', timeout: 30000 });
33
+ return isLdmAvailable();
34
+ } catch {
35
+ return false;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Delegate to ldm install with the given arguments.
41
+ * @param {string} target - what to install (org/repo, path, or empty for update-all)
42
+ * @param {string[]} flags - CLI flags (--dry-run, --json, etc.)
43
+ */
44
+ export function delegateToLdm(target, flags = []) {
45
+ const cmd = target
46
+ ? `ldm install ${target} ${flags.join(' ')}`
47
+ : `ldm install ${flags.join(' ')}`;
48
+ execSync(cmd.trim(), { stdio: 'inherit' });
49
+ }
50
+
51
+ /**
52
+ * Full bootstrap + delegate flow.
53
+ * Called by wip-install as the entry point.
54
+ * @param {string[]} argv - process.argv.slice(2)
55
+ */
56
+ export function run(argv) {
57
+ const target = argv.find(a => !a.startsWith('--'));
58
+ const flags = argv.filter(a => a.startsWith('--'));
59
+ const jsonOutput = flags.includes('--json');
60
+
61
+ if (isLdmAvailable()) {
62
+ if (!jsonOutput) {
63
+ console.log('');
64
+ console.log(' LDM OS detected. Delegating to ldm install...');
65
+ console.log('');
66
+ }
67
+ delegateToLdm(target, flags);
68
+ return;
69
+ }
70
+
71
+ // LDM not on PATH, try bootstrap
72
+ if (!jsonOutput) {
73
+ console.log('');
74
+ console.log(' LDM OS not found. Installing...');
75
+ console.log('');
76
+ }
77
+
78
+ if (bootstrapLdmOs()) {
79
+ if (!jsonOutput) {
80
+ console.log(' LDM OS installed. Delegating to ldm install...');
81
+ console.log('');
82
+ }
83
+ delegateToLdm(target, flags);
84
+ } else {
85
+ if (!jsonOutput) {
86
+ console.log(' LDM OS could not be installed automatically.');
87
+ console.log(' Install manually: npm install -g @wipcomputer/wip-ldm-os');
88
+ console.log('');
89
+ }
90
+ process.exit(1);
91
+ }
92
+ }
package/lib/state.mjs CHANGED
@@ -89,11 +89,11 @@ function detectCLIBinaries() {
89
89
  const binaries = {};
90
90
  for (const bin of knownBins) {
91
91
  try {
92
- const path = execSync(`which ${bin} 2>/dev/null`, { encoding: 'utf8' }).trim();
92
+ const path = execSync(`which ${bin} 2>/dev/null`, { encoding: 'utf8', timeout: 5000 }).trim();
93
93
  if (path) {
94
94
  binaries[bin] = { path };
95
95
  try {
96
- const ver = execSync(`${bin} --version 2>/dev/null`, { encoding: 'utf8' }).trim().split('\n')[0];
96
+ const ver = execSync(`${bin} --version 2>/dev/null`, { encoding: 'utf8', timeout: 5000 }).trim().split('\n')[0];
97
97
  binaries[bin].version = ver;
98
98
  } catch {}
99
99
  }
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@wipcomputer/wip-ldm-os",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "description": "LDM OS: identity, memory, and sovereignty infrastructure for AI agents",
6
6
  "main": "src/boot/boot-hook.mjs",
7
7
  "bin": {
8
8
  "ldm": "bin/ldm.js",
9
9
  "wip-ldm-os": "bin/ldm.js",
10
+ "wip-install": "bin/wip-install.js",
10
11
  "ldm-scaffold": "bin/scaffold.sh",
11
12
  "ldm-boot-install": "src/boot/install-cli.js",
12
13
  "lesa": "dist/bridge/cli.js"
package/src/bridge/cli.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // lesa-bridge/cli.ts: CLI interface.
2
+ // wip-bridge/cli.ts: CLI interface.
3
3
  // lesa send "message", lesa inbox, lesa search "query", lesa read <file>
4
4
 
5
5
  import { existsSync, statSync } from "node:fs";
@@ -17,7 +17,7 @@ import {
17
17
  const config = resolveConfig();
18
18
 
19
19
  function usage(): void {
20
- console.log(`lesa-bridge: Claude Code CLI ↔ OpenClaw TUI agent bridge
20
+ console.log(`wip-bridge: Claude Code CLI ↔ OpenClaw TUI agent bridge
21
21
 
22
22
  Usage:
23
23
  lesa send <message> Send a message to the OpenClaw agent
@@ -130,7 +130,7 @@ async function main(): Promise<void> {
130
130
  }
131
131
 
132
132
  case "status": {
133
- console.log(`lesa-bridge status`);
133
+ console.log(`wip-bridge status`);
134
134
  console.log(` OpenClaw dir: ${config.openclawDir}`);
135
135
  console.log(` Workspace: ${config.workspaceDir}`);
136
136
  console.log(` Database: ${config.dbPath}`);
@@ -140,7 +140,7 @@ async function main(): Promise<void> {
140
140
  }
141
141
 
142
142
  case "diagnose": {
143
- console.log("lesa-bridge diagnose\n");
143
+ console.log("wip-bridge diagnose\n");
144
144
  let issues = 0;
145
145
 
146
146
  // 1. OpenClaw dir
@@ -1,4 +1,4 @@
1
- // lesa-bridge/core.ts: Pure logic. Zero framework deps.
1
+ // wip-bridge/core.ts: Pure logic. Zero framework deps.
2
2
  // Handles messaging, memory search, and workspace access for OpenClaw agents.
3
3
 
4
4
  import { execSync, exec } from "node:child_process";
@@ -1,4 +1,4 @@
1
- // lesa-bridge/mcp-server.ts: MCP server wrapping core.
1
+ // wip-bridge/mcp-server.ts: MCP server wrapping core.
2
2
  // Thin layer: registers tools, starts inbox HTTP server, connects transport.
3
3
 
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -73,12 +73,12 @@ function startInboxServer(cfg: BridgeConfig): void {
73
73
  timestamp: new Date().toISOString(),
74
74
  };
75
75
  const queued = pushInbox(msg);
76
- console.error(`lesa-bridge inbox: message from ${msg.from}`);
76
+ console.error(`wip-bridge inbox: message from ${msg.from}`);
77
77
 
78
78
  try {
79
79
  server.sendLoggingMessage({
80
80
  level: "info",
81
- logger: "lesa-bridge",
81
+ logger: "wip-bridge",
82
82
  data: `[OpenClaw → Claude Code] ${msg.from}: ${msg.message}`,
83
83
  });
84
84
  } catch {}
@@ -103,18 +103,18 @@ function startInboxServer(cfg: BridgeConfig): void {
103
103
  });
104
104
 
105
105
  httpServer.listen(cfg.inboxPort, "127.0.0.1", () => {
106
- console.error(`lesa-bridge inbox listening on 127.0.0.1:${cfg.inboxPort}`);
106
+ console.error(`wip-bridge inbox listening on 127.0.0.1:${cfg.inboxPort}`);
107
107
  });
108
108
 
109
109
  httpServer.on("error", (err: Error) => {
110
- console.error(`lesa-bridge inbox server error: ${err.message}`);
110
+ console.error(`wip-bridge inbox server error: ${err.message}`);
111
111
  });
112
112
  }
113
113
 
114
114
  // ── MCP Server ───────────────────────────────────────────────────────
115
115
 
116
116
  const server = new McpServer({
117
- name: "lesa-bridge",
117
+ name: "wip-bridge",
118
118
  version: "0.3.0",
119
119
  });
120
120
 
@@ -344,7 +344,7 @@ function registerSkillTools(skills: SkillInfo[]): void {
344
344
  }
345
345
  );
346
346
 
347
- console.error(`lesa-bridge: registered ${executableSkills.length} skill tools + oc_skills_list (${skills.length} total skills)`);
347
+ console.error(`wip-bridge: registered ${executableSkills.length} skill tools + oc_skills_list (${skills.length} total skills)`);
348
348
  }
349
349
 
350
350
  // ── Start ────────────────────────────────────────────────────────────
@@ -357,12 +357,12 @@ async function main() {
357
357
  const skills = discoverSkills(config.openclawDir);
358
358
  registerSkillTools(skills);
359
359
  } catch (err: any) {
360
- console.error(`lesa-bridge: skill discovery failed: ${err.message}`);
360
+ console.error(`wip-bridge: skill discovery failed: ${err.message}`);
361
361
  }
362
362
 
363
363
  const transport = new StdioServerTransport();
364
364
  await server.connect(transport);
365
- console.error(`lesa-bridge MCP server running (openclaw: ${config.openclawDir})`);
365
+ console.error(`wip-bridge MCP server running (openclaw: ${config.openclawDir})`);
366
366
  }
367
367
 
368
368
  main().catch((error) => {
@@ -0,0 +1,19 @@
1
+ #!/bin/bash
2
+ # LDM OS: Global pre-commit hook
3
+ # Blocks commits on main/master. Use a branch or worktree.
4
+ # Installed by: ldm init
5
+ # Location: ~/.ldm/hooks/pre-commit
6
+ # Activated by: git config --global core.hooksPath ~/.ldm/hooks
7
+
8
+ branch=$(git branch --show-current 2>/dev/null)
9
+
10
+ if [ "$branch" = "main" ] || [ "$branch" = "master" ]; then
11
+ echo ""
12
+ echo " BLOCKED: Cannot commit on $branch."
13
+ echo " Create a branch first: git checkout -b cc-mini/your-feature"
14
+ echo " Or use a worktree: git worktree add /tmp/wt-name -b branch-name"
15
+ echo ""
16
+ echo " To bypass (emergencies only): git commit --no-verify"
17
+ echo ""
18
+ exit 1
19
+ fi