@hir4ta/mneme 0.17.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 (43) hide show
  1. package/.claude-plugin/plugin.json +29 -0
  2. package/.mcp.json +18 -0
  3. package/README.ja.md +400 -0
  4. package/README.md +410 -0
  5. package/bin/mneme.js +203 -0
  6. package/dist/lib/db.js +340 -0
  7. package/dist/lib/fuzzy-search.js +214 -0
  8. package/dist/lib/github.js +121 -0
  9. package/dist/lib/similarity.js +193 -0
  10. package/dist/lib/utils.js +62 -0
  11. package/dist/public/apple-touch-icon.png +0 -0
  12. package/dist/public/assets/index-BgqCALAg.css +1 -0
  13. package/dist/public/assets/index-EMvn4VEa.js +330 -0
  14. package/dist/public/assets/react-force-graph-2d-DWoBaKmT.js +46 -0
  15. package/dist/public/favicon-128-max.png +0 -0
  16. package/dist/public/favicon-256-max.png +0 -0
  17. package/dist/public/favicon-32-max.png +0 -0
  18. package/dist/public/favicon-512-max.png +0 -0
  19. package/dist/public/favicon-64-max.png +0 -0
  20. package/dist/public/index.html +15 -0
  21. package/dist/server.js +4791 -0
  22. package/dist/servers/db-server.js +30558 -0
  23. package/dist/servers/search-server.js +30366 -0
  24. package/hooks/default-tags.json +1055 -0
  25. package/hooks/hooks.json +61 -0
  26. package/hooks/post-tool-use.sh +96 -0
  27. package/hooks/pre-compact.sh +187 -0
  28. package/hooks/session-end.sh +567 -0
  29. package/hooks/session-start.sh +380 -0
  30. package/hooks/user-prompt-submit.sh +253 -0
  31. package/package.json +77 -0
  32. package/servers/db-server.ts +993 -0
  33. package/servers/search-server.ts +675 -0
  34. package/skills/AGENTS.override.md +5 -0
  35. package/skills/harvest/skill.md +295 -0
  36. package/skills/init-mneme/skill.md +101 -0
  37. package/skills/plan/skill.md +422 -0
  38. package/skills/report/skill.md +74 -0
  39. package/skills/resume/skill.md +278 -0
  40. package/skills/review/skill.md +419 -0
  41. package/skills/save/skill.md +482 -0
  42. package/skills/search/skill.md +175 -0
  43. package/skills/using-mneme/skill.md +185 -0
package/README.md ADDED
@@ -0,0 +1,410 @@
1
+ # mneme
2
+
3
+ > **⚠️ Breaking Change (v0.17.0)**: Renamed from `memoria` to `mneme`.
4
+ > If upgrading from `@hir4ta/memoria`, please reinstall:
5
+ > ```bash
6
+ > claude mcp remove mneme-search mneme-db
7
+ > claude plugin remove @hir4ta/memoria
8
+ > claude plugin add @hir4ta/mneme
9
+ > ```
10
+ > Data directory changed: `.memoria/` → `.mneme/`
11
+ > Rename manually: `mv .memoria .mneme`
12
+
13
+ Long-term memory plugin for Claude Code
14
+
15
+ Provides automatic session saving, intelligent memory search, and web dashboard management.
16
+
17
+ ## Features
18
+
19
+ ### Core Features
20
+ - **Auto-save interactions**: Conversations auto-saved at session end (jq-based, reliable)
21
+ - **Auto memory search**: Related past sessions/decisions automatically injected on each prompt
22
+ - **Backup on PreCompact**: Interactions backed up before Auto-Compact (context 95% full)
23
+ - **Full data extraction**: Save summary, decisions, patterns, and rules with `/mneme:save`
24
+ - **Memory-informed planning**: Design and plan with past knowledge via `/mneme:plan`
25
+ - **Session Resume**: Resume past sessions with `/mneme:resume` (with chain tracking)
26
+ - **Session Suggestion**: Recent 3 sessions shown at session start
27
+ - **Rule-based Review**: Code review based on `dev-rules.json` / `review-guidelines.json`
28
+ - **GitHub PR Review**: Review GitHub PRs with `/mneme:review <PR URL>`
29
+ - **Knowledge Harvesting**: Extract rules and patterns from PR comments with `/mneme:harvest`
30
+ - **Weekly Reports**: Auto-generate Markdown reports aggregating review results
31
+ - **Web Dashboard**: View sessions, decisions, patterns, and rules
32
+
33
+ ## Problems Solved
34
+
35
+ ### Common Issues in Claude Code Development
36
+
37
+ - **Context Loss**: Conversation context is lost on session end or Auto-Compact
38
+ - **Opaque Decisions**: "Why did we choose this design?" becomes untraceable
39
+ - **Repeated Mistakes**: Same errors solved multiple times without learning
40
+ - **Hard to Reuse Knowledge**: Past interactions and decisions are hard to search
41
+
42
+ ### What mneme Enables
43
+
44
+ - **Auto-save + Resume** enables context continuity across sessions
45
+ - **Auto memory search** brings relevant past knowledge to every conversation
46
+ - **Decision & Pattern Recording** tracks reasoning and error solutions
47
+ - **Search and Dashboard** for quick access to past records
48
+ - **Review Feature** for repository-specific code review
49
+
50
+ ### Team Benefits
51
+
52
+ - `.mneme/` JSON files are **Git-manageable**, enabling team sharing of decisions and session history
53
+ - Quickly understand background and context during onboarding or reviews
54
+
55
+ ## Installation
56
+
57
+ ### Prerequisites
58
+
59
+ - **jq**: Used for JSON processing in hooks
60
+
61
+ ```bash
62
+ # macOS
63
+ brew install jq
64
+
65
+ # Ubuntu/Debian
66
+ sudo apt-get install jq
67
+
68
+ # Windows (Chocolatey)
69
+ choco install jq
70
+
71
+ # Windows (Scoop)
72
+ scoop install jq
73
+
74
+ # Windows (winget)
75
+ winget install jqlang.jq
76
+ ```
77
+
78
+ ### Plugin Installation
79
+
80
+ Run the following in Claude Code:
81
+
82
+ ```bash
83
+ /plugin marketplace add hir4ta/mneme-marketplace
84
+ /plugin install mneme@mneme-marketplace
85
+ ```
86
+
87
+ Then initialize mneme in your project:
88
+
89
+ ```bash
90
+ # In Claude Code
91
+ /init-mneme
92
+
93
+ # Or from terminal
94
+ npx @hir4ta/mneme --init
95
+ ```
96
+
97
+ Restart Claude Code to complete installation.
98
+
99
+ ## Update
100
+
101
+ Run the following in Claude Code:
102
+
103
+ ```bash
104
+ /plugin marketplace update mneme-marketplace
105
+ ```
106
+
107
+ Restart Claude Code.
108
+
109
+ ### Enable Auto-Update (Recommended)
110
+
111
+ 1. Run `/plugin`
112
+ 2. Select Marketplaces tab
113
+ 3. Select `mneme-marketplace`
114
+ 4. Enable "Enable auto-update"
115
+
116
+ This will auto-update on Claude Code startup.
117
+
118
+ ## Usage
119
+
120
+ ### Session Auto-Save
121
+
122
+ **Interactions are auto-saved** at session end using jq (no Claude dependency). No configuration needed.
123
+
124
+ **PreCompact** backs up interactions to `preCompactBackups` before Auto-Compact (context 95% full). Summary is NOT auto-created.
125
+
126
+ ### Auto Memory Search
127
+
128
+ **On every prompt**, mneme automatically:
129
+ 1. Extracts keywords from your message
130
+ 2. Searches sessions/decisions/patterns
131
+ 3. Injects relevant context to Claude
132
+
133
+ This means past knowledge is always available without manual lookup.
134
+
135
+ ### Session Suggestion
136
+
137
+ At session start, recent 3 sessions are shown:
138
+
139
+ ```
140
+ **Recent sessions:**
141
+ 1. [abc123] JWT authentication implementation (2026-01-27, main)
142
+ 2. [def456] Dashboard UI improvements (2026-01-26, main)
143
+ 3. [ghi789] Bug fixes (2026-01-25, main)
144
+
145
+ Continue from a previous session? Use `/mneme:resume <id>`
146
+ ```
147
+
148
+ ### Commands
149
+
150
+ | Command | Description |
151
+ |---------|-------------|
152
+ | `/init-mneme` | Initialize mneme in current project |
153
+ | `/mneme:save` | Extract all data: summary, decisions, patterns, rules |
154
+ | `/mneme:plan [topic]` | Memory-informed design + Socratic questions + task breakdown |
155
+ | `/mneme:resume [id]` | Resume session (show list if ID omitted) |
156
+ | `/mneme:search "query"` | Search sessions, decisions, and patterns |
157
+ | `/mneme:review [--staged\|--all\|--diff=branch\|--full]` | Rule-based code review |
158
+ | `/mneme:review <PR URL>` | Review GitHub PR |
159
+ | `/mneme:harvest <PR URL>` | Extract knowledge from PR review comments |
160
+ | `/mneme:report [--from YYYY-MM-DD --to YYYY-MM-DD]` | Weekly review report |
161
+
162
+ ### Recommended Workflow
163
+
164
+ ```
165
+ plan → implement → save → review
166
+ ```
167
+
168
+ 1. **plan**: Design with memory lookup + Socratic questions + task breakdown
169
+ 2. **implement**: Follow the plan
170
+ 3. **save**: Extract decisions, patterns, rules
171
+ 4. **review**: Verify against plan and code quality
172
+
173
+ ### Dashboard
174
+
175
+ Run in your project directory:
176
+
177
+ ```bash
178
+ npx @hir4ta/mneme --dashboard
179
+ ```
180
+
181
+ Open <http://localhost:7777> in your browser.
182
+
183
+ Change port:
184
+
185
+ ```bash
186
+ npx @hir4ta/mneme --dashboard --port 8080
187
+ ```
188
+
189
+ #### Screens
190
+
191
+ - **Sessions**: List and view sessions
192
+ - **Decisions**: List and view technical decisions
193
+ - **Rules**: View dev rules and review guidelines
194
+ - **Patterns**: View learned patterns (good patterns, anti-patterns, error solutions)
195
+ - **Statistics**: View activity charts and session statistics
196
+ - **Graph**: Visualize session connections by shared tags
197
+
198
+ #### Language Switching
199
+
200
+ The dashboard supports English and Japanese. Click the language toggle (EN/JA) in the header to switch. The preference is saved to localStorage.
201
+
202
+ ### MCP Tools
203
+
204
+ mneme provides MCP servers with search and database tools callable directly from Claude Code:
205
+
206
+ | Server | Tool | Description |
207
+ |--------|------|-------------|
208
+ | mneme-search | `mneme_search` | Unified search (FTS5, tag alias resolution) |
209
+ | mneme-search | `mneme_get_session` | Get session details |
210
+ | mneme-search | `mneme_get_decision` | Get decision details |
211
+ | mneme-db | `mneme_list_projects` | List all projects |
212
+ | mneme-db | `mneme_cross_project_search` | Cross-project search |
213
+
214
+ ### Subagents
215
+
216
+ | Agent | Description |
217
+ |-------|-------------|
218
+ | `mneme-reviewer` | Rule-based code review (isolated context) |
219
+
220
+ ## How It Works
221
+
222
+ ```mermaid
223
+ flowchart TB
224
+ subgraph autosave [Auto-Save Interactions]
225
+ A[Session End] --> B[SessionEnd Hook]
226
+ B --> C[jq extracts from transcript]
227
+ C --> D[interactions + files + metrics]
228
+ end
229
+
230
+ subgraph autosearch [Auto Memory Search]
231
+ E[User Prompt] --> F[UserPromptSubmit Hook]
232
+ F --> G[Search sessions/decisions/patterns]
233
+ G --> H[Inject relevant context]
234
+ end
235
+
236
+ subgraph backup [PreCompact Backup]
237
+ I[Context 95% Full] --> J[PreCompact Hook]
238
+ J --> K[Backup interactions to preCompactBackups]
239
+ end
240
+
241
+ subgraph manual [Manual Actions]
242
+ L["mneme:save"] --> M[Extract decisions + patterns + rules]
243
+ N["mneme:plan"] --> O[Memory-informed design + tasks]
244
+ end
245
+
246
+ subgraph resume [Session Resume]
247
+ P["mneme:resume"] --> Q[Select from list]
248
+ Q --> R[Restore past context + set resumedFrom]
249
+ end
250
+
251
+ subgraph review [Review]
252
+ S["mneme:review"] --> T[Rule-based findings]
253
+ T --> U[Save review results]
254
+ end
255
+
256
+ subgraph dashboard [Dashboard]
257
+ V["npx @hir4ta/mneme -d"] --> W[Open in browser]
258
+ W --> X[View all data]
259
+ end
260
+
261
+ D --> P
262
+ H --> L
263
+ M --> V
264
+ U --> V
265
+ ```
266
+
267
+ ## Data Storage
268
+
269
+ mneme uses a **hybrid storage** approach for privacy and collaboration:
270
+
271
+ | Storage | Location | Purpose | Sharing |
272
+ |---------|----------|---------|---------|
273
+ | **JSON** | `.mneme/` | Summaries, decisions, patterns, rules | Git-managed (team shared) |
274
+ | **SQLite** | `.mneme/local.db` | Interactions, backups | Local only (gitignored) |
275
+
276
+ **Why hybrid?**
277
+ - **Privacy**: Conversation history (interactions) stays local (gitignored)
278
+ - **Lightweight**: JSON files reduced from 100KB+ to ~5KB (interactions excluded)
279
+ - **Future-ready**: Embeddings table prepared for semantic search
280
+
281
+ ### Directory Structure
282
+
283
+ **Project-local (`.mneme/`)**:
284
+ ```text
285
+ .mneme/
286
+ ├── local.db # SQLite with interactions (gitignored)
287
+ ├── tags.json # Tag master file (93 tags, prevents notation variations)
288
+ ├── sessions/ # Session metadata (YYYY/MM) - Git-managed
289
+ │ └── YYYY/MM/
290
+ │ └── {id}.json # Metadata only (interactions in local.db)
291
+ ├── decisions/ # Technical decisions (from /save) - Git-managed
292
+ │ └── YYYY/MM/
293
+ │ └── {id}.json
294
+ ├── patterns/ # Error patterns (from /save) - Git-managed
295
+ │ └── {user}.json
296
+ ├── rules/ # Dev rules / review guidelines - Git-managed
297
+ ├── reviews/ # Review results (YYYY/MM) - Git-managed
298
+ └── reports/ # Weekly reports (YYYY-MM) - Git-managed
299
+ ```
300
+
301
+ The `local.db` file is automatically added to `.mneme/.gitignore` to keep conversations private.
302
+
303
+ ### Session JSON Schema
304
+
305
+ Session metadata is stored in JSON (interactions are stored in SQLite for privacy):
306
+
307
+ ```json
308
+ {
309
+ "id": "abc12345",
310
+ "sessionId": "full-uuid-from-claude-code",
311
+ "createdAt": "2026-01-27T10:00:00Z",
312
+ "endedAt": "2026-01-27T12:00:00Z",
313
+ "title": "JWT authentication implementation",
314
+ "tags": ["auth", "jwt"],
315
+ "context": {
316
+ "branch": "feature/auth",
317
+ "projectDir": "/path/to/project",
318
+ "user": { "name": "tanaka", "email": "tanaka@example.com" }
319
+ },
320
+ "metrics": {
321
+ "userMessages": 5,
322
+ "assistantResponses": 5,
323
+ "thinkingBlocks": 5,
324
+ "toolUsage": [{"name": "Edit", "count": 3}, {"name": "Write", "count": 2}]
325
+ },
326
+ "files": [
327
+ { "path": "src/auth/jwt.ts", "action": "create" }
328
+ ],
329
+ "resumedFrom": "def45678",
330
+ "status": "complete",
331
+
332
+ "summary": {
333
+ "title": "JWT authentication implementation",
334
+ "goal": "Implement JWT-based auth with refresh token support",
335
+ "outcome": "success",
336
+ "description": "Implemented JWT auth with RS256 signing",
337
+ "sessionType": "implementation"
338
+ },
339
+
340
+ "plan": {
341
+ "tasks": ["[x] JWT signing method selection", "[x] Middleware implementation", "[ ] Add tests"],
342
+ "remaining": ["Add tests"]
343
+ },
344
+
345
+ "discussions": [
346
+ {
347
+ "topic": "Signing algorithm",
348
+ "decision": "Adopt RS256",
349
+ "reasoning": "Security considerations for production",
350
+ "alternatives": ["HS256 (simpler but requires shared secret)"]
351
+ }
352
+ ],
353
+
354
+ "errors": [
355
+ {
356
+ "error": "secretOrPrivateKey must be asymmetric",
357
+ "cause": "Using HS256 secret with RS256",
358
+ "solution": "Generate RS256 key pair"
359
+ }
360
+ ],
361
+
362
+ "handoff": {
363
+ "stoppedReason": "Test creation postponed to next session",
364
+ "notes": ["vitest configured", "Mock key pair in test/fixtures/"],
365
+ "nextSteps": ["Create jwt.test.ts", "Add E2E tests"]
366
+ },
367
+
368
+ "references": [
369
+ { "url": "https://jwt.io/introduction", "title": "JWT Introduction" }
370
+ ]
371
+ }
372
+ ```
373
+
374
+ ### Session Types
375
+
376
+ The `sessionType` field classifies the session type.
377
+
378
+ | Type | Description |
379
+ |------|-------------|
380
+ | `decision` | Decision cycle present (design choices, tech selection) |
381
+ | `implementation` | Code changes made |
382
+ | `research` | Research, learning, catchup |
383
+ | `exploration` | Codebase exploration |
384
+ | `discussion` | Discussion, consultation only |
385
+ | `debug` | Debugging, investigation |
386
+ | `review` | Code review |
387
+
388
+ ### Tags
389
+
390
+ Tags are selected from `.mneme/tags.json` to prevent notation variations (e.g., "フロント" → "frontend"). The master file contains 93 tags across 11 categories:
391
+
392
+ - **domain**: frontend, backend, api, db, infra, mobile, cli
393
+ - **phase**: feature, bugfix, refactor, test, docs
394
+ - **ai**: llm, ai-agent, mcp, rag, vector-db, embedding
395
+ - **cloud**: serverless, microservices, edge, wasm
396
+ - And more...
397
+
398
+ ## Versioning
399
+
400
+ This project follows [Semantic Versioning](https://semver.org/).
401
+
402
+ **⚠️ While in 0.x (pre-1.0), breaking changes may occur between minor versions.**
403
+
404
+ If you encounter issues after an update:
405
+ 1. Check the [releases](https://github.com/hir4ta/mneme/releases) for migration notes
406
+ 2. Re-initialize with `npx @hir4ta/mneme --init` if needed
407
+
408
+ ## License
409
+
410
+ MIT
package/bin/mneme.js ADDED
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { fork } from "node:child_process";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ // Suppress Node.js SQLite experimental warning (must be before dynamic import)
9
+ const originalEmit = process.emit;
10
+ process.emit = (name, data, ...args) => {
11
+ if (
12
+ name === "warning" &&
13
+ data?.name === "ExperimentalWarning" &&
14
+ data?.message?.includes("SQLite")
15
+ ) {
16
+ return false;
17
+ }
18
+ return originalEmit.call(process, name, data, ...args);
19
+ };
20
+
21
+ // Dynamic import to ensure warning suppression is active
22
+ const { DatabaseSync } = await import("node:sqlite");
23
+
24
+ const __filename = fileURLToPath(import.meta.url);
25
+ const __dirname = path.dirname(__filename);
26
+
27
+ const args = process.argv.slice(2);
28
+ const packageDir = path.dirname(__dirname);
29
+ const projectRoot = process.cwd();
30
+
31
+ function showHelp() {
32
+ console.log(`
33
+ mneme - Claude Code Long-term Memory Plugin
34
+
35
+ Usage:
36
+ mneme --init Initialize .mneme directory in current project
37
+ mneme --dashboard Start the web dashboard
38
+ mneme -d Same as above (short form)
39
+ mneme --port <port> Specify port (default: 7777)
40
+ mneme --help Show this help
41
+
42
+ Examples:
43
+ cd /path/to/your/project
44
+ npx @hir4ta/mneme --init
45
+ npx @hir4ta/mneme --dashboard
46
+ npx @hir4ta/mneme -d --port 8080
47
+ `);
48
+ }
49
+
50
+ function checkMnemeDir() {
51
+ const mnemeDir = path.join(projectRoot, ".mneme");
52
+ if (!fs.existsSync(mnemeDir)) {
53
+ console.log(`\nWARNING: .mneme directory not found: ${projectRoot}`);
54
+ console.log(" Run: npx @hir4ta/mneme --init");
55
+ }
56
+ }
57
+
58
+ function initMneme() {
59
+ const mnemeDir = path.join(projectRoot, ".mneme");
60
+ const sessionsDir = path.join(mnemeDir, "sessions");
61
+ const rulesDir = path.join(mnemeDir, "rules");
62
+ const patternsDir = path.join(mnemeDir, "patterns");
63
+ const tagsPath = path.join(mnemeDir, "tags.json");
64
+ const localDbPath = path.join(mnemeDir, "local.db");
65
+ const gitignorePath = path.join(mnemeDir, ".gitignore");
66
+
67
+ // Check if already initialized
68
+ if (fs.existsSync(mnemeDir)) {
69
+ console.log(`mneme is already initialized: ${mnemeDir}`);
70
+ return;
71
+ }
72
+
73
+ // Create directories
74
+ fs.mkdirSync(sessionsDir, { recursive: true });
75
+ fs.mkdirSync(rulesDir, { recursive: true });
76
+ fs.mkdirSync(patternsDir, { recursive: true });
77
+
78
+ // Copy default tags.json
79
+ const defaultTagsPath = path.join(packageDir, "hooks", "default-tags.json");
80
+ if (fs.existsSync(defaultTagsPath)) {
81
+ fs.copyFileSync(defaultTagsPath, tagsPath);
82
+ }
83
+
84
+ // Initialize rules files
85
+ const now = new Date().toISOString();
86
+ const rulesTemplate = JSON.stringify(
87
+ {
88
+ schemaVersion: 1,
89
+ createdAt: now,
90
+ updatedAt: now,
91
+ items: [],
92
+ },
93
+ null,
94
+ 2,
95
+ );
96
+
97
+ fs.writeFileSync(
98
+ path.join(rulesDir, "review-guidelines.json"),
99
+ rulesTemplate,
100
+ );
101
+ fs.writeFileSync(path.join(rulesDir, "dev-rules.json"), rulesTemplate);
102
+
103
+ // Create .gitignore for local.db
104
+ const gitignoreContent = `# Local SQLite database (private interactions)
105
+ local.db
106
+ local.db-wal
107
+ local.db-shm
108
+ `;
109
+ fs.writeFileSync(gitignorePath, gitignoreContent);
110
+
111
+ // Initialize local SQLite database
112
+ const schemaPath = path.join(packageDir, "lib", "schema.sql");
113
+ try {
114
+ const db = new DatabaseSync(localDbPath);
115
+ db.exec("PRAGMA journal_mode = WAL");
116
+ db.exec("PRAGMA busy_timeout = 5000");
117
+ db.exec("PRAGMA synchronous = NORMAL");
118
+ if (fs.existsSync(schemaPath)) {
119
+ const schema = fs.readFileSync(schemaPath, "utf-8");
120
+ db.exec(schema);
121
+ }
122
+ db.close();
123
+ } catch (error) {
124
+ console.error(
125
+ `Warning: Failed to initialize SQLite database: ${error.message}`,
126
+ );
127
+ }
128
+
129
+ console.log(`mneme initialized: ${mnemeDir}`);
130
+ console.log(`
131
+ Created:
132
+ ${sessionsDir}/
133
+ ${rulesDir}/
134
+ ${patternsDir}/
135
+ ${tagsPath}
136
+ ${rulesDir}/review-guidelines.json
137
+ ${rulesDir}/dev-rules.json
138
+ ${gitignorePath}
139
+ ${localDbPath}
140
+
141
+ You can now use mneme with Claude Code in this project.
142
+ `);
143
+ }
144
+
145
+ function getPort() {
146
+ const portIndex = args.indexOf("--port");
147
+ if (portIndex !== -1 && args[portIndex + 1]) {
148
+ return parseInt(args[portIndex + 1], 10) || 7777;
149
+ }
150
+ return 7777;
151
+ }
152
+
153
+ function startDashboard() {
154
+ checkMnemeDir();
155
+
156
+ const port = getPort();
157
+ const serverPath = path.join(packageDir, "dist", "server.js");
158
+
159
+ if (!fs.existsSync(serverPath)) {
160
+ console.error("ERROR: Server build not found.");
161
+ console.error(" The package may not be installed correctly.");
162
+ process.exit(1);
163
+ }
164
+
165
+ const child = fork(serverPath, [], {
166
+ cwd: packageDir,
167
+ env: {
168
+ ...process.env,
169
+ MNEME_PROJECT_ROOT: projectRoot,
170
+ PORT: port.toString(),
171
+ },
172
+ stdio: "inherit",
173
+ });
174
+
175
+ child.on("error", (err) => {
176
+ console.error("ERROR: Failed to start dashboard:", err.message);
177
+ process.exit(1);
178
+ });
179
+
180
+ child.on("close", (code) => {
181
+ process.exit(code || 0);
182
+ });
183
+
184
+ process.on("SIGINT", () => {
185
+ child.kill("SIGINT");
186
+ });
187
+ }
188
+
189
+ // Parse arguments
190
+ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
191
+ showHelp();
192
+ process.exit(0);
193
+ }
194
+
195
+ if (args.includes("--init")) {
196
+ initMneme();
197
+ } else if (args.includes("--dashboard") || args.includes("-d")) {
198
+ startDashboard();
199
+ } else {
200
+ console.error(`ERROR: Unknown option: ${args.join(" ")}`);
201
+ showHelp();
202
+ process.exit(1);
203
+ }