get-claudia 1.2.5 → 1.2.7

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
@@ -43,39 +43,36 @@ Say hi. She'll introduce herself and set things up for you.
43
43
 
44
44
  ---
45
45
 
46
+ ## What's New in v1.2.5
47
+
48
+ **Fully automatic memory system** - No more manual steps after install:
49
+
50
+ - **Works after reboot** - Ollama and the memory daemon auto-start on login (macOS LaunchAgent)
51
+ - **Python 3.13 support** - sqlite-vec now works on all Python versions
52
+ - **Boot resilience** - Daemon waits for Ollama to start instead of failing silently
53
+ - **Better diagnostics** - Run `~/.claudia/diagnose.sh` to check all services
54
+
55
+ The memory system just works now. Install, reboot, and everything comes back up.
56
+
57
+ ---
58
+
46
59
  ## Already Have Claudia? Add Memory.
47
60
 
48
- If you installed Claudia before the memory system existed, you can upgrade:
61
+ If you installed Claudia before the memory system existed, just run the installer again:
49
62
 
50
63
  ```bash
51
- # Clone the repo (or pull latest if you have it)
52
- git clone https://github.com/kbanc/claudia.git
53
- cd claudia/memory-daemon
54
-
55
- # Run the installer
56
- ./scripts/install.sh
64
+ npx get-claudia
57
65
  ```
58
66
 
59
- The installer will:
67
+ When prompted, say **yes** to install the memory system. The installer will:
60
68
  - Set up the memory daemon at `~/.claudia/daemon/`
61
- - Install Ollama for local embeddings (optional but recommended)
62
- - Configure auto-start so the daemon runs on login
63
- - Show you what to add to your `.mcp.json`
64
-
65
- After installing, add this to your Claudia project's `.mcp.json`:
66
-
67
- ```json
68
- {
69
- "mcpServers": {
70
- "claudia-memory": {
71
- "command": "~/.claudia/daemon/venv/bin/python",
72
- "args": ["-m", "claudia_memory.mcp.server"]
73
- }
74
- }
75
- }
76
- ```
69
+ - Install Ollama for semantic search (optional but recommended)
70
+ - Configure auto-start so everything runs on login
71
+ - Pull the embedding model automatically
72
+ - Verify all services are working
73
+ - Update your `.mcp.json` automatically
77
74
 
78
- Restart Claude Code, and Claudia now has persistent memory.
75
+ Restart Claude Code in a new terminal, and Claudia now has persistent memory.
79
76
 
80
77
  ---
81
78
 
@@ -83,11 +80,12 @@ Restart Claude Code, and Claudia now has persistent memory.
83
80
 
84
81
  | Traditional AI | Claudia |
85
82
  |----------------|---------|
86
- | Forgets everything between sessions | **Persistent memory** — SQLite + vector search, never forgets |
83
+ | Forgets everything between sessions | **Persistent memory** — SQLite + vector search, survives reboots |
87
84
  | Treats conversations as isolated | **Tracks relationships** — People files, not just tasks |
88
85
  | Waits for instructions | **Proactive** — Surfaces risks before they become problems |
89
86
  | One-size-fits-all | **Personalized** — Structure generated for your work style |
90
87
  | Cloud-based, data harvested | **Local** — Runs on your machine, your context stays yours |
88
+ | Breaks after system updates | **Resilient** — Auto-starts on boot, retries on failure |
91
89
 
92
90
  ---
93
91
 
@@ -256,6 +254,44 @@ See what she surfaces. Then tell her about a person you work with.
256
254
 
257
255
  ---
258
256
 
257
+ ## Troubleshooting
258
+
259
+ **Memory tools not appearing?**
260
+ ```bash
261
+ # Check all services
262
+ ~/.claudia/diagnose.sh
263
+
264
+ # Common fixes:
265
+ # 1. Restart Claude Code in a NEW terminal (it reads .mcp.json at startup)
266
+ # 2. Check daemon health: curl http://localhost:3848/health
267
+ # 3. View logs: tail -f ~/.claudia/daemon-stderr.log
268
+ ```
269
+
270
+ **Ollama not running after reboot?**
271
+ ```bash
272
+ # Load the LaunchAgent
273
+ launchctl load ~/Library/LaunchAgents/com.ollama.serve.plist
274
+
275
+ # Or start manually
276
+ ollama serve
277
+ ```
278
+
279
+ **Vector search not working?**
280
+ ```bash
281
+ # Check if sqlite-vec is installed
282
+ ~/.claudia/daemon/venv/bin/python -c "import sqlite_vec; print('ok')"
283
+
284
+ # If not, install it
285
+ ~/.claudia/daemon/venv/bin/pip install sqlite-vec
286
+ ```
287
+
288
+ **Pull the embedding model**
289
+ ```bash
290
+ ollama pull all-minilm:l6-v2
291
+ ```
292
+
293
+ ---
294
+
259
295
  ## License
260
296
 
261
297
  Apache 2.0 — Use it, modify it, make it yours.
package/bin/index.js CHANGED
@@ -56,37 +56,55 @@ async function main() {
56
56
  const args = process.argv.slice(2);
57
57
  const arg = args[0];
58
58
 
59
- // Support "." for current directory
60
- const isCurrentDir = arg === '.';
59
+ // Support "." or "upgrade" for current directory
60
+ const isCurrentDir = arg === '.' || arg === 'upgrade';
61
61
  const targetDir = isCurrentDir ? '.' : (arg || 'claudia');
62
62
  const targetPath = isCurrentDir ? process.cwd() : join(process.cwd(), targetDir);
63
63
  const displayDir = isCurrentDir ? 'current directory' : targetDir;
64
64
 
65
65
  // Check if directory already exists and has conflicting files
66
+ let isUpgrade = false;
67
+
66
68
  if (existsSync(targetPath)) {
67
69
  const contents = readdirSync(targetPath);
68
70
  const hasConflict = contents.some(f => f === 'CLAUDE.md' || f === '.claude');
71
+
69
72
  if (hasConflict) {
70
- console.log(`\n${colors.yellow}⚠${colors.reset} Claudia files already exist in ${displayDir}.`);
71
- console.log(` Remove CLAUDE.md and .claude/ first, or choose a different location.\n`);
72
- process.exit(1);
73
+ // Check if this is an upgrade (existing memories to migrate)
74
+ const hasExistingMemories = existsSync(join(targetPath, 'context', 'me.md')) ||
75
+ existsSync(join(targetPath, 'context', 'learnings.md')) ||
76
+ existsSync(join(targetPath, 'context', 'patterns.md')) ||
77
+ existsSync(join(targetPath, 'people'));
78
+
79
+ if (hasExistingMemories) {
80
+ console.log(`\n${colors.cyan}✓${colors.reset} Found existing Claudia instance with memories.`);
81
+ isUpgrade = true;
82
+ // Don't exit - proceed to memory installation
83
+ } else {
84
+ // Fresh install conflict - exit as before
85
+ console.log(`\n${colors.yellow}⚠${colors.reset} Claudia files already exist in ${displayDir}.`);
86
+ console.log(` Remove CLAUDE.md and .claude/ first, or choose a different location.\n`);
87
+ process.exit(1);
88
+ }
73
89
  }
74
90
  }
75
91
 
76
- // Create target directory if not current dir
77
- if (!isCurrentDir) {
92
+ // Create target directory if not current dir (only for fresh installs)
93
+ if (!isCurrentDir && !isUpgrade) {
78
94
  mkdirSync(targetPath, { recursive: true });
79
95
  }
80
96
 
81
- // Copy template files (v2 - minimal seed)
82
- const templatePath = join(__dirname, '..', 'template-v2');
97
+ // Copy template files (v2 - minimal seed) - skip for upgrades
98
+ if (!isUpgrade) {
99
+ const templatePath = join(__dirname, '..', 'template-v2');
83
100
 
84
- try {
85
- cpSync(templatePath, targetPath, { recursive: true });
86
- console.log(`${colors.green}✓${colors.reset} Installed in ${displayDir}`);
87
- } catch (error) {
88
- console.error(`\n${colors.yellow}⚠${colors.reset} Error copying files: ${error.message}`);
89
- process.exit(1);
101
+ try {
102
+ cpSync(templatePath, targetPath, { recursive: true });
103
+ console.log(`${colors.green}✓${colors.reset} Installed in ${displayDir}`);
104
+ } catch (error) {
105
+ console.error(`\n${colors.yellow}⚠${colors.reset} Error copying files: ${error.message}`);
106
+ process.exit(1);
107
+ }
90
108
  }
91
109
 
92
110
  // Ask about enhanced memory system
@@ -113,10 +131,14 @@ async function main() {
113
131
 
114
132
  if (existsSync(memoryDaemonPath)) {
115
133
  try {
116
- // Run the install script
134
+ // Run the install script, passing project path for upgrades
117
135
  const result = spawn('bash', [memoryDaemonPath], {
118
136
  stdio: 'inherit',
119
- shell: true
137
+ shell: true,
138
+ env: {
139
+ ...process.env,
140
+ CLAUDIA_PROJECT_PATH: isUpgrade ? targetPath : ''
141
+ }
120
142
  });
121
143
 
122
144
  result.on('close', (code) => {
@@ -93,16 +93,34 @@ random_message() {
93
93
  echo "${MESSAGES[$RANDOM % ${#MESSAGES[@]}]}"
94
94
  }
95
95
 
96
- # Check Python
97
- echo -e "${BOLD}Step 1/7: Environment Check${NC}"
96
+ # Check Python - prefer Homebrew Python on macOS (supports SQLite extensions)
97
+ echo -e "${BOLD}Step 1/8: Environment Check${NC}"
98
98
  echo
99
- if command -v python3 &> /dev/null; then
100
- PYTHON=$(command -v python3)
99
+ PYTHON=""
100
+ if [[ "$OSTYPE" == "darwin"* ]]; then
101
+ # Homebrew Python supports SQLite extension loading (needed for vector search)
102
+ if [ -x "/opt/homebrew/bin/python3" ]; then
103
+ PYTHON="/opt/homebrew/bin/python3"
104
+ echo -e " ${GREEN}✓${NC} Using Homebrew Python (vector search supported)"
105
+ elif [ -x "/usr/local/bin/python3" ]; then
106
+ PYTHON="/usr/local/bin/python3"
107
+ echo -e " ${GREEN}✓${NC} Using Homebrew Python (vector search supported)"
108
+ fi
109
+ fi
110
+
111
+ if [ -z "$PYTHON" ]; then
112
+ if command -v python3 &> /dev/null; then
113
+ PYTHON=$(command -v python3)
114
+ fi
115
+ fi
116
+
117
+ if [ -n "$PYTHON" ]; then
101
118
  PYTHON_VERSION=$($PYTHON --version 2>&1 | awk '{print $2}')
102
- echo -e " ${GREEN}✓${NC} Python $PYTHON_VERSION"
119
+ echo -e " ${GREEN}✓${NC} Python $PYTHON_VERSION ($PYTHON)"
103
120
  else
104
121
  echo -e " ${RED}✗${NC} Python 3 not found"
105
122
  echo -e " Please install Python 3.10 or later"
123
+ echo -e " ${DIM}On macOS: brew install python${NC}"
106
124
  exit 1
107
125
  fi
108
126
 
@@ -181,7 +199,7 @@ echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━
181
199
  echo
182
200
 
183
201
  # Pull embedding model
184
- echo -e "${BOLD}Step 2/7: AI Models${NC}"
202
+ echo -e "${BOLD}Step 2/8: AI Models${NC}"
185
203
  echo
186
204
  if [ "$OLLAMA_AVAILABLE" = true ]; then
187
205
  # Ensure Ollama is running before pulling model
@@ -230,7 +248,7 @@ echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━
230
248
  echo
231
249
 
232
250
  # Create directories
233
- echo -e "${BOLD}Step 3/7: Creating Home${NC}"
251
+ echo -e "${BOLD}Step 3/8: Creating Home${NC}"
234
252
  echo
235
253
  mkdir -p "$DAEMON_DIR"
236
254
  mkdir -p "$MEMORY_DIR"
@@ -247,10 +265,11 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
247
265
  SOURCE_DIR="$(dirname "$SCRIPT_DIR")"
248
266
 
249
267
  # Copy daemon files
250
- echo -e "${BOLD}Step 4/7: Installing Core${NC}"
268
+ echo -e "${BOLD}Step 4/8: Installing Core${NC}"
251
269
  echo
252
270
  echo -e " ${CYAN}◐${NC} Copying memory system files..."
253
271
  cp -r "$SOURCE_DIR/claudia_memory" "$DAEMON_DIR/"
272
+ cp -r "$SOURCE_DIR/scripts" "$DAEMON_DIR/"
254
273
  cp "$SOURCE_DIR/pyproject.toml" "$DAEMON_DIR/"
255
274
  cp "$SOURCE_DIR/requirements.txt" "$DAEMON_DIR/"
256
275
  echo -e " ${GREEN}✓${NC} Core files installed"
@@ -265,7 +284,7 @@ echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━
265
284
  echo
266
285
 
267
286
  # Create virtual environment
268
- echo -e "${BOLD}Step 5/7: Python Environment${NC}"
287
+ echo -e "${BOLD}Step 5/8: Python Environment${NC}"
269
288
  echo
270
289
  echo -e " ${CYAN}◐${NC} Creating isolated environment..."
271
290
  $PYTHON -m venv "$VENV_DIR"
@@ -290,7 +309,7 @@ echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━
290
309
  echo
291
310
 
292
311
  # Configure auto-start
293
- echo -e "${BOLD}Step 6/7: Auto-Start Setup${NC}"
312
+ echo -e "${BOLD}Step 6/8: Auto-Start Setup${NC}"
294
313
  echo
295
314
 
296
315
  if [[ "$OSTYPE" == "darwin"* ]]; then
@@ -375,8 +394,40 @@ echo
375
394
  echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
376
395
  echo
377
396
 
397
+ # Memory Migration (for upgrades)
398
+ echo -e "${BOLD}Step 7/8: Memory Migration${NC}"
399
+ echo
400
+
401
+ if [ -n "$CLAUDIA_PROJECT_PATH" ]; then
402
+ # Check if there are memories to migrate
403
+ if [ -d "$CLAUDIA_PROJECT_PATH/context" ] || [ -d "$CLAUDIA_PROJECT_PATH/people" ]; then
404
+ echo -e " ${CYAN}◐${NC} Found existing memories to migrate..."
405
+
406
+ # Wait a moment for daemon to start
407
+ sleep 2
408
+
409
+ # Run migration in quiet mode
410
+ "$VENV_DIR/bin/python" "$DAEMON_DIR/scripts/migrate_markdown.py" --quiet "$CLAUDIA_PROJECT_PATH"
411
+
412
+ if [ $? -eq 0 ]; then
413
+ echo -e " ${GREEN}✓${NC} Memories migrated to database"
414
+ else
415
+ echo -e " ${YELLOW}!${NC} Migration had issues (memories still in markdown)"
416
+ echo -e " ${DIM}You can retry manually: ~/.claudia/daemon/venv/bin/python -m claudia_memory.scripts.migrate_markdown $CLAUDIA_PROJECT_PATH${NC}"
417
+ fi
418
+ else
419
+ echo -e " ${DIM}No existing memories found to migrate${NC}"
420
+ fi
421
+ else
422
+ echo -e " ${DIM}Fresh install - no migration needed${NC}"
423
+ fi
424
+
425
+ echo
426
+ echo -e "${DIM}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
427
+ echo
428
+
378
429
  # Verify all services
379
- echo -e "${BOLD}Step 7/7: Verification${NC}"
430
+ echo -e "${BOLD}Step 8/8: Verification${NC}"
380
431
  echo
381
432
  echo -e " ${CYAN}◐${NC} Checking all services..."
382
433
  sleep 3
@@ -346,13 +346,22 @@ def main():
346
346
  action="store_true",
347
347
  help="Enable debug logging",
348
348
  )
349
+ parser.add_argument(
350
+ "--quiet",
351
+ action="store_true",
352
+ help="Non-interactive mode (for automated migration)",
353
+ )
349
354
 
350
355
  args = parser.parse_args()
351
356
 
352
- logging.basicConfig(
353
- level=logging.DEBUG if args.debug else logging.INFO,
354
- format="%(asctime)s - %(levelname)s - %(message)s",
355
- )
357
+ if args.quiet:
358
+ # Suppress all logging in quiet mode
359
+ logging.basicConfig(level=logging.ERROR)
360
+ else:
361
+ logging.basicConfig(
362
+ level=logging.DEBUG if args.debug else logging.INFO,
363
+ format="%(asctime)s - %(levelname)s - %(message)s",
364
+ )
356
365
 
357
366
  # Initialize database
358
367
  db = get_db()
@@ -363,8 +372,24 @@ def main():
363
372
  if not args.path.exists():
364
373
  logger.error(f"Path not found: {args.path}")
365
374
  sys.exit(1)
375
+
376
+ if not args.quiet:
377
+ print(f"Migrating: {args.path}")
378
+
366
379
  stats = migrate_instance(args.path, args.dry_run)
367
- print(f"\nMigrated: {stats}")
380
+
381
+ if args.quiet:
382
+ # Quiet mode - minimal output for automated migration
383
+ total = sum(stats.values())
384
+ if total > 0:
385
+ print(f" - Migrated {stats['me']} items from context/me.md") if stats.get('me') else None
386
+ print(f" - Migrated {stats['learnings']} items from context/learnings.md") if stats.get('learnings') else None
387
+ print(f" - Migrated {stats['patterns']} items from context/patterns.md") if stats.get('patterns') else None
388
+ print(f" - Migrated {stats['commitments']} items from context/commitments.md") if stats.get('commitments') else None
389
+ if stats.get('people'):
390
+ print(f" - Migrated {stats['people']} people with {stats.get('memories', 0)} facts")
391
+ else:
392
+ print(f"\nMigrated: {stats}")
368
393
 
369
394
  elif args.all:
370
395
  # Migrate all instances
@@ -373,11 +398,12 @@ def main():
373
398
  logger.info("No Claudia instances found")
374
399
  sys.exit(0)
375
400
 
376
- print(f"Found {len(instances)} Claudia instance(s):\n")
377
- for i, instance in enumerate(instances, 1):
378
- print(f" {i}. {instance}")
401
+ if not args.quiet:
402
+ print(f"Found {len(instances)} Claudia instance(s):\n")
403
+ for i, instance in enumerate(instances, 1):
404
+ print(f" {i}. {instance}")
379
405
 
380
- if not args.dry_run:
406
+ if not args.dry_run and not args.quiet:
381
407
  confirm = input("\nMigrate all? (y/n) ")
382
408
  if confirm.lower() != "y":
383
409
  sys.exit(0)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "get-claudia",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "An AI assistant who learns how you work.",
5
5
  "keywords": [
6
6
  "claudia",