baby-daemon 1.0.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/.env.example ADDED
@@ -0,0 +1,3 @@
1
+ # Gemini API Key from Google AI Studio
2
+ # Get a free key from https://aistudio.google.com/
3
+ GEMINI_API_KEY=your_free_gemini_api_key_here
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 sankolte
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,224 @@
1
+ # ๐Ÿง  Baby Daemon
2
+
3
+ > A background daemon that gives AI coding agents persistent memory across sessions.
4
+
5
+ ---
6
+
7
+ ## The Problem
8
+
9
+ Every AI coding session is stateless by default. Switch agents, restart a session, or continue the next day โ€” your AI forgets everything. Decisions, bugs, architecture choices. You re-explain it all. Every. Single. Time.
10
+
11
+ **Baby Daemon fixes that.**
12
+
13
+ ---
14
+
15
+ ## How It Works
16
+
17
+ ```
18
+ 1. Run `memory-watch ./logs` โ†’ daemon starts watching your agent's chat logs
19
+ 2. File changes detected โ†’ Gemini 2.5 Flash extracts structured memories
20
+ 3. Memories stored โ†’ LanceDB (vector) + memory.jsonl (flat)
21
+ 4. New session, new agent โ†’ `memory search "why did auth break?"` โ†’ instant context
22
+ ```
23
+
24
+ ---
25
+
26
+ ## CLI Commands
27
+
28
+ ```bash
29
+ # Start the daemon (watches a folder for AI chat logs)
30
+ memory-watch ./logs
31
+
32
+ # Start with human approval for high-confidence decisions
33
+ memory-watch ./logs --require-approval
34
+
35
+ # Semantic search across all stored memories
36
+ memory search "authentication bug"
37
+
38
+ # Filtered search
39
+ memory search "caching strategy" --type decision --since "3 days ago"
40
+
41
+ # Dump raw logs (bypasses vector DB โ€” emergency fallback)
42
+ memory dump --since "yesterday"
43
+
44
+ # Archive old memories to keep search fast
45
+ memory archive --age 14
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Tech Stack
51
+
52
+ | Layer | Technology |
53
+ |---|---|
54
+ | Runtime | Node.js (ES Modules) |
55
+ | File Watcher | `chokidar` (event-driven, OS-native) |
56
+ | LLM Summarizer | Google Gemini 2.5 Flash |
57
+ | Embeddings | `gemini-embedding-2` |
58
+ | Vector DB | LanceDB (local, embedded โ€” no server) |
59
+ | Keyword Fallback | `minisearch` (pure JS) |
60
+ | Date Parsing | `chrono-node` ("yesterday", "2 days ago") |
61
+ | Integrity | SHA-256 hashing (`node:crypto`) |
62
+
63
+ ---
64
+
65
+ ## Memory Schema
66
+
67
+ Every memory is a structured, typed object โ€” never a plain string:
68
+
69
+ ```json
70
+ {
71
+ "id": "mem-1716300000-a1b2c3d4",
72
+ "timestamp": "2026-05-21T10:30:00Z",
73
+ "type": "proposed_idea",
74
+ "content": "Consider switching to Redis for caching layer",
75
+ "original_text": "maybe we should use Redis...",
76
+ "confidence": 0.4,
77
+ "status": "active",
78
+ "related_files": ["cache.ts"],
79
+ "tags": ["redis", "caching"],
80
+ "source": { "chat_file": "chat_042.md" },
81
+ "hash": "e4a91b7a9f..."
82
+ }
83
+ ```
84
+
85
+ **Types:** `decision` ยท `proposed_idea` ยท `rejected_idea` ยท `open_question` ยท `bug` ยท `resolved_bug` ยท `architecture_note` ยท `file_change`
86
+
87
+ ---
88
+
89
+ ## Key Design Decisions
90
+
91
+ ### Duplicate Prevention (Idempotency)
92
+ OS file watchers fire multiple times per save. Every file event is fingerprinted:
93
+ ```
94
+ key = SHA-256(absolute_path + "|" + last_modified_ms)
95
+ ```
96
+ Key is stored in `processed_keys.json`. Only recorded **after** successful processing โ€” so failures auto-retry.
97
+
98
+ ### Memory Drift Prevention
99
+ LLMs compress uncertainty. *"Maybe use Redis"* becomes *"Project migrated to Redis."*
100
+
101
+ Fixes:
102
+ - Strict type schema โ€” `decision` requires explicit commitment from both sides
103
+ - Every memory stores the **exact source quote** (`original_text`)
104
+ - `--require-approval` flag for human-in-the-loop on high-risk memories
105
+ - `status: outdated` for contradicted memories + archival system
106
+
107
+ ### 3-Layer Hybrid Search
108
+ 1. **LanceDB vector search** โ€” cosine similarity, 0.70 threshold
109
+ 2. **Metadata filtering** โ€” type, date (natural language via chrono-node), file
110
+ 3. **MiniSearch keyword fallback** โ€” if vector search returns nothing
111
+ 4. **Raw dump fallback** โ€” if everything else fails, `memory dump` bypasses the AI layer entirely
112
+
113
+ ### Never Summarize a Summary
114
+ Memories are always generated from **original raw logs**, never from previous summaries. Prevents information entropy across multi-agent handoffs.
115
+
116
+ ---
117
+
118
+ ## Build Phases
119
+
120
+ - [x] **Phase 1** โ€” File watcher shell + idempotency
121
+ - [x] **Phase 2** โ€” Gemini summarization pipeline + structured schema
122
+ - [x] **Phase 3** โ€” LanceDB vector store + semantic search
123
+ - [x] **Phase 4** โ€” Integrity (SHA-256 hashes, fallback dump, approval mode, archival)
124
+ - [x] **Phase 5** โ€” MCP Server (wrap as plug-and-play tool for any MCP-compatible agent)
125
+
126
+ ---
127
+
128
+ ## Setup
129
+
130
+ ```bash
131
+ git clone https://github.com/sankolte/Baby-Daemon.git
132
+ cd Baby-Daemon
133
+ npm install
134
+ cp .env.example .env
135
+ # Add your GEMINI_API_KEY to .env
136
+ ```
137
+
138
+ ```bash
139
+ # Watch your logs folder
140
+ node bin/memory-watch.js ./logs
141
+
142
+ # Or if installed globally via npm link:
143
+ memory-watch ./logs
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Project Structure
149
+
150
+ ```
151
+ โ”œโ”€โ”€ mcp-server.js โ† MCP server entry point (Phase 5)
152
+ โ”œโ”€โ”€ bin/
153
+ โ”‚ โ”œโ”€โ”€ memory-watch.js โ† Start the daemon
154
+ โ”‚ โ””โ”€โ”€ memory.js โ† Search, dump, archive
155
+ โ”œโ”€โ”€ src/
156
+ โ”‚ โ”œโ”€โ”€ watcher.js โ† chokidar + pipeline orchestration
157
+ โ”‚ โ”œโ”€โ”€ summarizer.js โ† Gemini call + JSON schema enforcement
158
+ โ”‚ โ”œโ”€โ”€ vectorStore.js โ† LanceDB, embeddings cache, MiniSearch fallback
159
+ โ”‚ โ”œโ”€โ”€ memoryStore.js โ† JSONL read/write
160
+ โ”‚ โ”œโ”€โ”€ idempotency.js โ† SHA-256 key generation + persistence
161
+ โ”‚ โ””โ”€โ”€ config.js โ† Gemini SDK init
162
+ โ”œโ”€โ”€ memory.jsonl โ† Flat structured memory store (gitignored)
163
+ โ”œโ”€โ”€ .lancedb/ โ† Local vector DB (gitignored)
164
+ โ”œโ”€โ”€ claude_desktop_config.example.json โ† Example MCP config
165
+ โ””โ”€โ”€ .env.example โ† Environment variable template
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Phase 5 โ€” MCP Server
171
+
172
+ Baby Daemon is now available as an **MCP (Model Context Protocol) server**. Any MCP-compatible AI host can use it natively โ€” no CLI required.
173
+
174
+ ### Available MCP Tools
175
+
176
+ | Tool | Description |
177
+ |------|-------------|
178
+ | `memory_search` | Semantic + keyword search with filters (type, date, file, limit) |
179
+ | `memory_store` | Push raw text through the summarization pipeline and store |
180
+ | `memory_dump` | Dump all stored memories with optional filters |
181
+ | `memory_archive` | Move old memories to archive table |
182
+ | `memory_read` | Full project knowledge briefing grouped by category |
183
+
184
+ **Resource:** `memory://status` โ€” system health, counts, LanceDB status
185
+ **Prompt:** `continue_from_memory` โ€” context-rich prompt to resume work from previous sessions
186
+
187
+ ### Setup for Claude Desktop
188
+
189
+ Add to `%APPDATA%/Claude/claude_desktop_config.json`:
190
+
191
+ ```json
192
+ {
193
+ "mcpServers": {
194
+ "baby-daemon": {
195
+ "command": "node",
196
+ "args": ["C:\\path\\to\\proj101\\mcp-server.js"]
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ Restart Claude Desktop โ€” Baby Daemon tools appear automatically.
203
+
204
+ ### Setup for Cursor / Cline / Other MCP Hosts
205
+
206
+ Most MCP hosts use a similar JSON config. Point it to:
207
+ ```
208
+ command: node
209
+ args: ["<absolute-path-to>/mcp-server.js"]
210
+ ```
211
+
212
+ ### Testing with MCP Inspector
213
+
214
+ ```bash
215
+ npx @modelcontextprotocol/inspector node mcp-server.js
216
+ ```
217
+
218
+ Opens a web UI where you can interactively test all tools, read resources, and invoke prompts.
219
+
220
+ ---
221
+
222
+ ## License
223
+
224
+ MIT
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * bin/baby-daemon.js
5
+ * โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
6
+ * The main entry command for Baby Daemon.
7
+ *
8
+ * When a user installs globally (npm install -g baby-daemon),
9
+ * they can run: baby-daemon
10
+ *
11
+ * This shows:
12
+ * - Quick status (is API key set? are there memories?)
13
+ * - Available commands
14
+ * - MCP setup instructions
15
+ * - First-time setup help
16
+ */
17
+
18
+ import fs from 'fs';
19
+ import path from 'path';
20
+ import { fileURLToPath } from 'url';
21
+ import dotenv from 'dotenv';
22
+
23
+ // Load .env from current working directory (where the user runs the command)
24
+ dotenv.config({ path: path.join(process.cwd(), '.env') });
25
+
26
+ // Also try loading from the package directory (for global installs)
27
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
28
+ const PACKAGE_ROOT = path.join(__dirname, '..');
29
+ dotenv.config({ path: path.join(PACKAGE_ROOT, '.env') });
30
+
31
+ // CLI Styling
32
+ const R = '\x1b[0m'; // Reset
33
+ const B = '\x1b[1m'; // Bold
34
+ const D = '\x1b[2m'; // Dim
35
+ const C = '\x1b[36m'; // Cyan
36
+ const G = '\x1b[32m'; // Green
37
+ const Y = '\x1b[33m'; // Yellow
38
+ const M = '\x1b[35m'; // Magenta
39
+ const RED = '\x1b[31m'; // Red
40
+
41
+ const args = process.argv.slice(2);
42
+ const command = args[0]?.toLowerCase();
43
+
44
+ if (command === 'setup') {
45
+ handleSetup();
46
+ } else if (command === 'mcp-config') {
47
+ handleMcpConfig();
48
+ } else {
49
+ handleDefault();
50
+ }
51
+
52
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
53
+ // DEFAULT: Show status + available commands
54
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
55
+
56
+ function handleDefault() {
57
+ const hasApiKey = !!process.env.GEMINI_API_KEY;
58
+ const memoryFile = path.join(process.cwd(), 'memory.jsonl');
59
+ const hasMemories = fs.existsSync(memoryFile);
60
+ let memoryCount = 0;
61
+ if (hasMemories) {
62
+ try {
63
+ const content = fs.readFileSync(memoryFile, 'utf-8');
64
+ memoryCount = content.split('\n').filter(l => l.trim()).length;
65
+ } catch { /* ignore */ }
66
+ }
67
+
68
+ console.log(`
69
+ ${B}${C}๐Ÿง  Baby Daemon${R} ${D}v0.1.0${R}
70
+ ${D}AI memory system for coding agents${R}
71
+
72
+ ${B}STATUS:${R}
73
+ API Key : ${hasApiKey ? `${G}โœ“ Set${R}` : `${RED}โœ— Not set${R} ${D}(run: baby-daemon setup)${R}`}
74
+ Memories : ${hasMemories ? `${G}${memoryCount} stored${R}` : `${Y}None yet${R}`}
75
+ Directory : ${D}${process.cwd()}${R}
76
+
77
+ ${B}COMMANDS:${R}
78
+ ${C}memory-watch ${D}<folder>${R} Watch a folder for AI chat logs
79
+ ${C}memory search ${D}<query>${R} Search stored memories (semantic + keyword)
80
+ ${C}memory read${R} View all active memories by category
81
+ ${C}memory dump${R} Dump raw memory data
82
+ ${C}memory archive${R} Archive old memories
83
+
84
+ ${B}SETUP:${R}
85
+ ${C}baby-daemon setup${R} First-time setup guide
86
+ ${C}baby-daemon mcp-config${R} Show MCP server config for Claude/Cursor
87
+
88
+ ${B}MCP SERVER:${R}
89
+ ${D}For AI hosts (Claude Desktop, Cursor, Cline):${R}
90
+ ${C}baby-daemon mcp-config${R} ${D}โ† shows the JSON config to copy${R}
91
+ `);
92
+ }
93
+
94
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
95
+ // SETUP: First-time setup guide
96
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
97
+
98
+ function handleSetup() {
99
+ const hasApiKey = !!process.env.GEMINI_API_KEY;
100
+ const envExists = fs.existsSync(path.join(process.cwd(), '.env'));
101
+
102
+ console.log(`
103
+ ${B}${C}๐Ÿง  Baby Daemon โ€” Setup Guide${R}
104
+
105
+ ${B}Step 1: Get a Gemini API Key (free)${R}
106
+ ${D}Go to:${R} ${C}https://aistudio.google.com/apikey${R}
107
+ ${D}Click "Create API key" โ†’ copy it${R}
108
+
109
+ ${B}Step 2: Create a .env file${R}
110
+ ${D}In your project root, create a file called${R} ${C}.env${R} ${D}with:${R}
111
+
112
+ ${G}GEMINI_API_KEY=your_api_key_here${R}
113
+
114
+ ${envExists ? ` ${G}โœ“ .env file found in current directory${R}` : ` ${Y}โš  No .env file found in ${process.cwd()}${R}`}
115
+ ${hasApiKey ? ` ${G}โœ“ API key is loaded${R}` : ` ${RED}โœ— API key not detected yet${R}`}
116
+
117
+ ${B}Step 3: Create a logs folder${R}
118
+ ${D}This is where your AI agent chat logs go:${R}
119
+
120
+ ${C}mkdir logs${R}
121
+
122
+ ${B}Step 4: Start watching${R}
123
+
124
+ ${C}memory-watch ./logs${R}
125
+
126
+ ${D}Baby Daemon will now watch for new/changed files in ./logs,
127
+ extract structured memories via Gemini, and store them for search.${R}
128
+
129
+ ${B}Step 5 (Optional): Connect to Claude Desktop / Cursor${R}
130
+
131
+ ${C}baby-daemon mcp-config${R}
132
+ `);
133
+ }
134
+
135
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
136
+ // MCP-CONFIG: Show copy-paste MCP configuration
137
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
138
+
139
+ function handleMcpConfig() {
140
+ // Find the mcp-server.js path
141
+ const mcpServerPath = path.join(PACKAGE_ROOT, 'mcp-server.js');
142
+ const mcpServerExists = fs.existsSync(mcpServerPath);
143
+
144
+ // Format path for JSON (escape backslashes for Windows)
145
+ const escapedPath = mcpServerPath.replace(/\\/g, '\\\\');
146
+
147
+ console.log(`
148
+ ${B}${C}๐Ÿง  Baby Daemon โ€” MCP Server Configuration${R}
149
+
150
+ ${mcpServerExists ? `${G}โœ“ MCP server found at:${R}` : `${RED}โœ— MCP server not found at:${R}`}
151
+ ${D}${mcpServerPath}${R}
152
+
153
+ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
154
+
155
+ ${B}${M}Claude Desktop${R}
156
+ ${D}Add this to:${R} ${C}%APPDATA%\\Claude\\claude_desktop_config.json${R}
157
+ ${D}(Mac: ~/Library/Application Support/Claude/claude_desktop_config.json)${R}
158
+
159
+ ${G}{
160
+ "mcpServers": {
161
+ "baby-daemon": {
162
+ "command": "node",
163
+ "args": ["${escapedPath}"]
164
+ }
165
+ }
166
+ }${R}
167
+
168
+ ${D}Then restart Claude Desktop.${R}
169
+
170
+ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
171
+
172
+ ${B}${M}Cursor${R}
173
+ ${D}Go to: Settings โ†’ MCP โ†’ Add Server${R}
174
+ ${D}Command:${R} ${C}node${R}
175
+ ${D}Args:${R} ${C}${mcpServerPath}${R}
176
+
177
+ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
178
+
179
+ ${B}AVAILABLE TOOLS (auto-discovered by AI host):${R}
180
+ ${C}memory_search${R} ${D}โ€” Semantic search across all stored memories${R}
181
+ ${C}memory_store${R} ${D}โ€” Push text through summarization pipeline${R}
182
+ ${C}memory_read${R} ${D}โ€” Full project knowledge briefing${R}
183
+ ${C}memory_dump${R} ${D}โ€” Raw memory dump with filters${R}
184
+ ${C}memory_archive${R} ${D}โ€” Archive old memories${R}
185
+
186
+ ${B}RESOURCE:${R} ${C}memory://status${R} ${D}โ€” System health dashboard${R}
187
+ ${B}PROMPT:${R} ${C}continue_from_memory${R} ${D}โ€” Context-rich session bootstrap${R}
188
+ `);
189
+ }
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * memory-watch.js (the CLI entry point)
4
+ * โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
5
+ * WHAT THIS FILE DOES:
6
+ * This is the file that runs when you type `memory-watch` in the terminal.
7
+ * It reads the command-line arguments, validates them, and calls startWatcher().
8
+ * It's intentionally tiny โ€” a CLI entry point should ONLY parse args and delegate.
9
+ * All real logic lives in src/watcher.js.
10
+ *
11
+ * CONCEPT: #!/usr/bin/env node (the "shebang" line)
12
+ * The very first line starting with #! is called a "shebang" (or hashbang).
13
+ * On Unix/Mac, when you run a script file directly, the OS reads this line
14
+ * to know WHICH program should execute the file.
15
+ * #!/usr/bin/env node means: "find 'node' in the PATH and run this file with it"
16
+ * On Windows this line is ignored (Node handles it differently via the bin field
17
+ * in package.json), but we still include it for cross-platform compatibility.
18
+ *
19
+ * CONCEPT: process.argv
20
+ * Every Node.js process has a global 'process' object with useful info.
21
+ * process.argv is an array of command-line arguments:
22
+ * process.argv[0] = path to node executable (e.g., "C:/nodejs/node.exe")
23
+ * process.argv[1] = path to the script being run (e.g., "C:/proj101/bin/memory-watch.js")
24
+ * process.argv[2] = FIRST argument YOU passed (e.g., "./logs")
25
+ * process.argv[3] = second argument (if any)
26
+ * So when you run: memory-watch ./logs
27
+ * process.argv = ['node', 'memory-watch.js', './logs']
28
+ * And process.argv[2] = './logs'
29
+ *
30
+ * CONCEPT: ES Module imports
31
+ * We use: import { startWatcher } from '../src/watcher.js';
32
+ * This is the modern JS module system (ESM).
33
+ * The older system (CommonJS) used: const { startWatcher } = require('../src/watcher');
34
+ * We use ESM because we set "type": "module" in package.json.
35
+ * Key difference: ESM is static (imports resolved at parse time), CJS is dynamic.
36
+ */
37
+
38
+ import { startWatcher } from '../src/watcher.js';
39
+
40
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
41
+ // PARSE ARGUMENTS
42
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
43
+
44
+ const args = process.argv.slice(2);
45
+ // .slice(2) removes the first two items (node path + script path)
46
+ // leaving only the arguments the user actually typed
47
+
48
+ // Show help if user runs: memory-watch --help or memory-watch -h
49
+ if (args.includes('--help') || args.includes('-h')) {
50
+ printHelp();
51
+ process.exit(0);
52
+ }
53
+
54
+ // The watch path is the first real argument
55
+ const requireApproval = args.includes('--require-approval') || args.includes('-a');
56
+ const watchPath = args.find(arg => !arg.startsWith('-'));
57
+
58
+ if (!watchPath) {
59
+ console.error('\n โœ— Error: No folder path provided.\n');
60
+ printHelp();
61
+ process.exit(1);
62
+ }
63
+
64
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
65
+ // START THE WATCHER
66
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
67
+
68
+ startWatcher(watchPath, { requireApproval });
69
+
70
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
71
+ // HELP TEXT
72
+ // โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
73
+
74
+ function printHelp() {
75
+ console.log(`
76
+ Baby Daemon โ€” memory-watch (Phase 3)
77
+
78
+ USAGE:
79
+ memory-watch <folder-path> [options]
80
+
81
+ OPTIONS:
82
+ -a, --require-approval Prompt to confirm or reject each extracted memory
83
+
84
+ EXAMPLES:
85
+ memory-watch ./logs
86
+ memory-watch ./logs --require-approval
87
+ memory-watch . (watch current folder)
88
+
89
+ WHAT IT DOES:
90
+ Watches <folder-path> for new and modified files.
91
+ Extracts structured memories via Gemini API.
92
+ Saves memories to memory.jsonl and syncs with LanceDB vector database.
93
+ Skips duplicates using idempotency fingerprints.
94
+
95
+ STOP:
96
+ Press Ctrl+C to stop the watcher gracefully.
97
+ `);
98
+ }