get-claudia 1.40.0 → 1.40.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.
@@ -180,11 +180,21 @@ def run_daemon(mcp_mode: bool = True, debug: bool = False, project_id: str = Non
180
180
  if project_id:
181
181
  logger.info(f"Project isolation enabled: {project_id}")
182
182
 
183
- # Acquire lockfile before touching the database -- prevents concurrent
184
- # daemon instances from both writing to the same SQLite file, which is
185
- # the root cause of "database disk image is malformed" errors.
186
183
  config = get_config()
187
- _acquire_daemon_lock(Path(config.db_path).parent / "claudia.lock")
184
+
185
+ if not mcp_mode:
186
+ # Only enforce singleton for the standalone background daemon.
187
+ # The lock prevents two long-running background processes from
188
+ # concurrently running scheduled jobs (decay, consolidation) against
189
+ # the same SQLite file, which caused "database disk image is malformed"
190
+ # errors.
191
+ #
192
+ # MCP servers are ephemeral, session-bound processes spawned by Claude
193
+ # Code. They must NOT compete for the same lock as a running standalone
194
+ # daemon (e.g., installed via LaunchAgent/systemd). SQLite WAL mode
195
+ # handles concurrent read/write access safely across processes.
196
+ _acquire_daemon_lock(Path(config.db_path).parent / "claudia.lock")
197
+
188
198
  _check_and_repair_database(Path(config.db_path))
189
199
 
190
200
  # Set up signal handlers
@@ -197,13 +207,17 @@ def run_daemon(mcp_mode: bool = True, debug: bool = False, project_id: str = Non
197
207
  db.initialize()
198
208
  logger.info(f"Database initialized at {get_config().db_path}")
199
209
 
200
- # Start health server
201
- start_health_server()
202
- logger.info(f"Health server started on port {get_config().health_port}")
203
-
204
- # Start background scheduler
205
- start_scheduler()
206
- logger.info("Background scheduler started")
210
+ # Start health server and scheduler - ONLY in standalone mode.
211
+ # MCP server processes are ephemeral and session-bound; the standalone
212
+ # daemon (LaunchAgent/systemd) owns port 3848 and handles scheduling.
213
+ # Starting these here in MCP mode causes [Errno 48] Address already in
214
+ # use and double-scheduling alongside the running standalone daemon.
215
+ if not mcp_mode:
216
+ start_health_server()
217
+ logger.info(f"Health server started on port {get_config().health_port}")
218
+
219
+ start_scheduler()
220
+ logger.info("Background scheduler started")
207
221
 
208
222
  if mcp_mode:
209
223
  # Run MCP server (blocks until stdin closes)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "get-claudia",
3
- "version": "1.40.0",
3
+ "version": "1.40.2",
4
4
  "description": "An AI assistant who learns how you work.",
5
5
  "keywords": [
6
6
  "claudia",
@@ -14,9 +14,9 @@
14
14
  ],
15
15
  "on_missing_me": "trigger_onboarding",
16
16
  "memory_verification": {
17
- "step_1_check_tools": "BEFORE anything else, verify you have access to memory.* MCP tools. If no memory tools are available, inform the user: 'Memory daemon not connected. Run the /diagnose command or check ~/.claudia/daemon-stderr.log for errors.'",
17
+ "step_1_check_tools": "BEFORE anything else, verify you have access to mcp__claudia-memory__* tools (check your available tools list). If no memory tools are available: (1) Do NOT fall back to plugin:episodic-memory, mcp__plugin_episodic-memory_*, or any other memory search tool as a substitute — these give inferior, unrelated results and mask the real problem. (2) Tell the user: 'My memory tools are not registered in this session. The daemon likely just auto-restarted — please restart Claude Code (close and reopen the window) to reconnect. Your context files are preserved.' (3) Continue with context files only (context/me.md, etc.) until restarted.",
18
18
  "step_2_health_check": "Call memory.session (operation=\"context\"). If it fails or returns an error, the daemon may be crashed. Suggest: 'Memory daemon may need restart. Check: curl http://localhost:3848/health'",
19
- "fallback": "If memory tools unavailable, proceed with markdown-only mode but WARN the user that memories won't persist."
19
+ "fallback": "If mcp__claudia-memory__* tools are not available: (1) Do NOT use plugin:episodic-memory or any other memory search tool as a substitute. (2) Tell the user: 'My memory tools are not registered in this session. The daemon may have just restarted — please restart Claude Code to reconnect. Your context files are preserved.' (3) Read context files directly (context/me.md, context/commitments.md, context/learnings.md, context/patterns.md, context/waiting.md) as the fallback. Make clear to the user they are in degraded mode with no semantic search or cross-session learning."
20
20
  },
21
21
  "enhanced_memory": {
22
22
  "context_load": "Call memory.session (operation=\"context\") to get a formatted context block with recent memories, commitments, and unsummarized session alerts.",
@@ -74,7 +74,7 @@
74
74
  ],
75
75
  "notes": {
76
76
  "implementation": "These hooks define intended behaviors. Claude Code will execute them as behavioral guidelines rather than traditional script execution.",
77
- "memory_verification": "CRITICAL: At session start, verify memory tools are available BEFORE proceeding. If memory.* tools don't appear in available tools, the daemon isn't connected. This is a hard requirement for full Claudia functionality.",
77
+ "memory_verification": "CRITICAL: At session start, verify mcp__claudia-memory__* tools are available BEFORE proceeding. If tools don't appear, do NOT use plugin:episodic-memory as a substitute. Tell the user to restart Claude Code — the daemon auto-restarts but MCP tools only register at session start. Fall back to context files only (context/me.md, etc.) in the meantime.",
78
78
  "session_start": "At session start: (1) Verify memory tools available, (2) Call memory.session (operation=\"context\"), (3) Read context files, (4) Check for unsummarized sessions. If me.md is missing, trigger onboarding.",
79
79
  "session_end": "Before session ends, Claudia should generate a session summary (enhanced memory) or update context files (markdown fallback). The summary includes both a free-form narrative and structured extractions.",
80
80
  "first_run": "The absence of context/me.md signals a first-run scenario requiring onboarding.",
@@ -51,6 +51,23 @@ def _get_status_summary():
51
51
  return None
52
52
 
53
53
 
54
+ def _read_user_profile():
55
+ """Read context/me.md from CLAUDE_PROJECT_DIR if it exists. Returns snippet or empty string."""
56
+ project_dir = os.environ.get('CLAUDE_PROJECT_DIR', '')
57
+ if not project_dir:
58
+ return ''
59
+ me_path = Path(project_dir) / 'context' / 'me.md'
60
+ if not me_path.exists():
61
+ return ''
62
+ try:
63
+ content = me_path.read_text(encoding='utf-8', errors='replace')
64
+ if len(content) > 2000:
65
+ content = content[:2000]
66
+ return f'\n\nUser profile (from context/me.md):\n{content}'
67
+ except OSError:
68
+ return ''
69
+
70
+
54
71
  def check_health():
55
72
  context_parts = []
56
73
 
@@ -102,9 +119,19 @@ def check_health():
102
119
  pass
103
120
  if restarted:
104
121
  status_msg = _get_status_summary()
105
- msg = "Memory daemon was stopped but has been restarted automatically."
122
+ user_profile = _read_user_profile()
123
+ msg = (
124
+ "IMPORTANT: Memory daemon was stopped and has been auto-restarted. "
125
+ "However, the memory MCP tools (mcp__claudia-memory__*) are NOT available in this session "
126
+ "because MCP tools connect at session start, before the restart happened. "
127
+ "Tell the user: 'The memory daemon was just restarted. Please restart Claude Code "
128
+ "(close and reopen the window) to reconnect your memory tools. "
129
+ "Your context files are preserved.' "
130
+ "Do NOT use plugin:episodic-memory as a substitute."
131
+ )
106
132
  if status_msg:
107
- msg = f"{msg} {status_msg}"
133
+ msg = f"{msg} Daemon status: {status_msg}"
134
+ msg = msg + user_profile
108
135
  print(json.dumps({"additionalContext": msg}))
109
136
  return
110
137
  context_parts.append(
@@ -138,9 +165,19 @@ def check_health():
138
165
  pass
139
166
  if restarted:
140
167
  status_msg = _get_status_summary()
141
- msg = "Memory daemon was stopped but has been restarted automatically."
168
+ user_profile = _read_user_profile()
169
+ msg = (
170
+ "IMPORTANT: Memory daemon was stopped and has been auto-restarted. "
171
+ "However, the memory MCP tools (mcp__claudia-memory__*) are NOT available in this session "
172
+ "because MCP tools connect at session start, before the restart happened. "
173
+ "Tell the user: 'The memory daemon was just restarted. Please restart Claude Code "
174
+ "(close and reopen the window) to reconnect your memory tools. "
175
+ "Your context files are preserved.' "
176
+ "Do NOT use plugin:episodic-memory as a substitute."
177
+ )
142
178
  if status_msg:
143
- msg = f"{msg} {status_msg}"
179
+ msg = f"{msg} Daemon status: {status_msg}"
180
+ msg = msg + user_profile
144
181
  print(json.dumps({"additionalContext": msg}))
145
182
  return
146
183
  context_parts.append(
@@ -194,7 +231,8 @@ def check_health():
194
231
  pass
195
232
 
196
233
  output = " ".join(context_parts)
197
- print(json.dumps({"additionalContext": output}))
234
+ user_profile = _read_user_profile()
235
+ print(json.dumps({"additionalContext": output + user_profile}))
198
236
 
199
237
 
200
238
  if __name__ == "__main__":
@@ -50,6 +50,27 @@ except Exception:
50
50
  exit 0
51
51
  fi
52
52
 
53
+ # Helper: emit JSON for unhealthy-daemon states, appending context/me.md if available
54
+ emit_with_profile() {
55
+ local MSG="$1"
56
+ local PROFILE=""
57
+ if [ -n "${CLAUDE_PROJECT_DIR:-}" ] && [ -f "${CLAUDE_PROJECT_DIR}/context/me.md" ]; then
58
+ PROFILE=$(head -c 2000 "${CLAUDE_PROJECT_DIR}/context/me.md" 2>/dev/null || true)
59
+ fi
60
+ if [ -n "$PROFILE" ] && command -v python3 &>/dev/null; then
61
+ CLAUDIA_MSG="$MSG" CLAUDIA_PROFILE="$PROFILE" python3 -c "
62
+ import json, os
63
+ msg = os.environ.get('CLAUDIA_MSG', '')
64
+ profile = os.environ.get('CLAUDIA_PROFILE', '')
65
+ if profile:
66
+ msg = msg + '\n\nUser profile (from context/me.md):\n' + profile
67
+ print(json.dumps({'additionalContext': msg}))"
68
+ else
69
+ MSG_ESC=$(echo "$MSG" | sed 's/"/\\"/g')
70
+ echo "{\"additionalContext\": \"$MSG_ESC\"}"
71
+ fi
72
+ }
73
+
53
74
  # Daemon is NOT healthy. Figure out why and provide actionable guidance.
54
75
  CONTEXT="IMPORTANT: Memory daemon is NOT running. Without it, you lose semantic search, pattern detection, cross-session learning, and proactive predictions. You MUST surface this to the user and offer to help fix it."
55
76
 
@@ -79,12 +100,11 @@ except Exception:
79
100
  pass
80
101
  " <<< "$STATUS_JSON" 2>/dev/null)
81
102
  fi
82
- MSG="Memory daemon was stopped but has been restarted automatically."
103
+ MSG="IMPORTANT: Memory daemon was stopped and has been auto-restarted. However, the memory MCP tools (mcp__claudia-memory__*) are NOT available in this session because MCP tools connect at session start, before the restart happened. Tell the user: 'The memory daemon was just restarted. Please restart Claude Code (close and reopen the window) to reconnect your memory tools. Your context files are preserved.' Do NOT use plugin:episodic-memory as a substitute."
83
104
  if [ -n "$STATUS_SUMMARY" ]; then
84
- MSG="$MSG $STATUS_SUMMARY"
105
+ MSG="$MSG Daemon status: $STATUS_SUMMARY"
85
106
  fi
86
- STATUS_ESC=$(echo "$MSG" | sed 's/"/\\"/g')
87
- echo "{\"additionalContext\": \"$STATUS_ESC\"}"
107
+ emit_with_profile "$MSG"
88
108
  exit 0
89
109
  fi
90
110
  CONTEXT="$CONTEXT Daemon is installed (LaunchAgent exists) but could not be auto-restarted. Suggest: 'Your memory daemon is stopped. Please run: launchctl load ~/Library/LaunchAgents/com.claudia.memory.plist'"
@@ -116,12 +136,11 @@ except Exception:
116
136
  pass
117
137
  " <<< "$STATUS_JSON" 2>/dev/null)
118
138
  fi
119
- MSG="Memory daemon was stopped but has been restarted automatically."
139
+ MSG="IMPORTANT: Memory daemon was stopped and has been auto-restarted. However, the memory MCP tools (mcp__claudia-memory__*) are NOT available in this session because MCP tools connect at session start, before the restart happened. Tell the user: 'The memory daemon was just restarted. Please restart Claude Code (close and reopen the window) to reconnect your memory tools. Your context files are preserved.' Do NOT use plugin:episodic-memory as a substitute."
120
140
  if [ -n "$STATUS_SUMMARY" ]; then
121
- MSG="$MSG $STATUS_SUMMARY"
141
+ MSG="$MSG Daemon status: $STATUS_SUMMARY"
122
142
  fi
123
- STATUS_ESC=$(echo "$MSG" | sed 's/"/\\"/g')
124
- echo "{\"additionalContext\": \"$STATUS_ESC\"}"
143
+ emit_with_profile "$MSG"
125
144
  exit 0
126
145
  fi
127
146
  CONTEXT="$CONTEXT Daemon is installed (systemd service exists) but could not be auto-restarted. Suggest: 'Your memory daemon is stopped. Please run: systemctl --user restart claudia-memory'"
@@ -149,5 +168,5 @@ if [ -f "$HOME/.claudia/daemon-stderr.log" ]; then
149
168
  fi
150
169
  fi
151
170
 
152
- echo "{\"additionalContext\": \"$CONTEXT\"}"
171
+ emit_with_profile "$CONTEXT"
153
172
  exit 0
@@ -372,6 +372,7 @@ Even without the explicit command, these principles apply whenever I'm processin
372
372
  - Make moral judgments about users
373
373
  - Share information inappropriately
374
374
  - Use em dashes (the hallmark of lazy AI writing)
375
+ - Reference internal implementation details in conversation: skill files, rule files, hook names, MCP tool IDs (like `mcp__claudia-memory__*`), or internal system names. These are part of who I am - I follow them silently without narrating them.
375
376
 
376
377
  ---
377
378
 
@@ -0,0 +1,46 @@
1
+ # Memory Availability Rule
2
+
3
+ This rule is always active and applies to every session. Follow it silently - do not cite this file, mention rule names, or reference internal tool IDs in your response to the user.
4
+
5
+ ---
6
+
7
+ ## When Memory Tools Are Missing
8
+
9
+ If `mcp__claudia-memory__*` tools are **not listed in your available tools**, follow these rules strictly:
10
+
11
+ ### Do NOT substitute with other memory tools
12
+
13
+ Do not use any of the following as a replacement for missing memory tools:
14
+ - `plugin:episodic-memory` / `mcp__plugin_episodic-memory_*`
15
+ - Any other cross-session memory or search tool not in the `mcp__claudia-memory__*` family
16
+
17
+ These tools access a different, unrelated memory system. Using them gives the user the wrong memories, masks the real connectivity problem, and creates confusion about what Claudia actually knows.
18
+
19
+ ### Do tell the user clearly
20
+
21
+ Say something like:
22
+
23
+ > "My memory tools aren't connected in this session. The daemon is likely running but the MCP connection isn't registered yet. To fix this, restart Claude Code (close and reopen the window). Your context files are preserved and I can work from those in the meantime."
24
+
25
+ ### Do fall back to context files only
26
+
27
+ Read the following files directly as the fallback:
28
+ - `context/me.md`
29
+ - `context/commitments.md`
30
+ - `context/learnings.md`
31
+ - `context/patterns.md`
32
+ - `context/waiting.md`
33
+
34
+ Make clear to the user they are in degraded mode: no semantic search, no pattern detection, no cross-session learning. This is the honest and correct behavior.
35
+
36
+ ### The fix is one action
37
+
38
+ The user only needs to do one thing: **restart Claude Code**. The daemon auto-restarts via launchctl/systemctl. There is no command to type. Just close and reopen the Claude Code window.
39
+
40
+ ---
41
+
42
+ ## Background (for context only, not to be surfaced verbatim)
43
+
44
+ The most common cause of missing memory tools is a registration timing issue, not a crashed daemon. MCP tools register at session initialization. If the daemon restarted after the session started, the tools simply aren't registered yet - the daemon is up, but a Claude Code restart is the only fix.
45
+
46
+ Substituting with another memory plugin gives the wrong data from a different system and hides the real problem from the user. The honest answer is always to acknowledge the degraded state and point to the one action that fixes it.
@@ -63,7 +63,7 @@ Use the appropriate command set below (macOS/Linux or Windows).
63
63
  **macOS/Linux:**
64
64
 
65
65
  ```bash
66
- # Check if daemon process is running
66
+ # Check if daemon process is running (and whether in standalone mode)
67
67
  ps aux | grep claudia_memory | grep -v grep
68
68
 
69
69
  # Check health endpoint
@@ -75,6 +75,11 @@ tail -20 ~/.claudia/daemon-stderr.log 2>/dev/null || echo "No daemon log found"
75
75
  # Check database exists and has data
76
76
  ls -la ~/.claudia/memory/*.db 2>/dev/null || echo "No database found"
77
77
  sqlite3 ~/.claudia/memory/claudia.db "SELECT COUNT(*) as memories FROM memories; SELECT COUNT(*) as entities FROM entities;" 2>/dev/null || echo "Cannot query database"
78
+
79
+ # Check for standalone/MCP conflict (pre-v1.36 issue)
80
+ # If you see a process with --standalone AND no MCP tools, this is the cause
81
+ STANDALONE_RUNNING=$(ps aux | grep "claudia_memory.*standalone" | grep -v grep | wc -l | tr -d ' ')
82
+ echo "Standalone daemon processes: $STANDALONE_RUNNING"
78
83
  ```
79
84
 
80
85
  **Windows (PowerShell):**
@@ -188,6 +193,24 @@ powershell -ExecutionPolicy Bypass -File memory-daemon\scripts\install.ps1
188
193
  2. Restart Claude Code (this restarts the MCP server)
189
194
  3. Check logs: `Get-Content -Tail 50 "$env:USERPROFILE\.claudia\daemon-stderr.log"`
190
195
 
196
+ ### Issue: Standalone daemon running but MCP tools not registered (pre-v1.36)
197
+
198
+ **Symptoms:** Daemon process running with `--standalone`, health endpoint healthy, 0 memory tools in Claude Code
199
+
200
+ **Cause (pre-v1.36):** The LaunchAgent/systemd service starts the daemon with `--standalone`, which acquires a singleton lock. When Claude Code spawns the MCP server, it hits the same lock, sees another daemon running, and exits immediately (exit code 0). Claude Code sees the clean exit and thinks the MCP server started, but no tools register.
201
+
202
+ **Fix:** Upgrade Claudia to v1.36+ where this conflict is resolved:
203
+ ```bash
204
+ npx get-claudia .
205
+ ```
206
+ After upgrading, restart Claude Code. The MCP server no longer competes with the standalone daemon's lock.
207
+
208
+ **If upgrade isn't possible:** Restart Claude Code. If tools still don't register, stop the standalone daemon temporarily:
209
+ ```bash
210
+ launchctl unload ~/Library/LaunchAgents/com.claudia.memory.plist
211
+ ```
212
+ Then restart Claude Code (which will spawn the MCP server cleanly). Note: background jobs won't run until you reload the LaunchAgent.
213
+
191
214
  ### Issue: .mcp.json uses wrong entry point
192
215
 
193
216
  **Detection:** Check the `args` array in `.mcp.json` for the `claudia-memory` server. If it says `claudia_memory.mcp.server` instead of `claudia_memory`, it bypasses project isolation, the health server, and background scheduling.
@@ -80,20 +80,19 @@ Check for `context/me.md` at the start of any session. If it doesn't exist, this
80
80
 
81
81
  At the start of every session (after confirming `context/me.md` exists):
82
82
 
83
- 1. **Verify memory tools** - Check that `memory.*` MCP tools are available in your tool list
84
- - If NO memory tools: **Don't just warn. Offer to fix it.** Check the session-health-check hook output:
85
- - Daemon installed but stopped Offer to start it (platform-specific command)
86
- - Daemon not installed Offer to run the installer
87
- - Briefly explain what's lost: semantic search, pattern detection, cross-session learning, proactive predictions
88
- - If user agrees to start it, they'll need to restart Claude Code afterward for MCP tools to register
89
- - If memory tools present: Continue to step 2
83
+ 1. **Check available tools** - Look for `memory.*` tools in your available tool list BEFORE greeting.
84
+ - If memory tools ARE present: continue to step 2
85
+ - If memory tools are NOT present:
86
+ a. Read `context/me.md` directly using the Read tool -- do this IMMEDIATELY as your first action, before saying anything to the user
87
+ b. Also read `context/commitments.md`, `context/learnings.md`, `context/patterns.md`, `context/waiting.md`
88
+ c. Greet the user naturally using whatever context you found in those files
89
+ d. Let them know memory tools aren't connected and ask if they want to troubleshoot
90
+ e. If they already restarted Claude Code and tools are STILL missing, the issue is likely MCP configuration (not a timing issue). Suggest running `/diagnose` to check.
90
91
  2. **Load context** - Call `memory.session` (operation: "context") to get recent memories, predictions, commitments, and unsummarized session alerts
91
92
  - If this call fails: The daemon may have crashed. Suggest checking `~/.claudia/daemon-stderr.log`
92
93
  3. **Catch up** - If unsummarized sessions are reported, generate retroactive summaries using `memory.end_session`
93
94
  4. **Greet naturally** - Use the loaded context to inform your greeting and surface urgent items
94
95
 
95
- **Fallback mode:** If memory tools aren't available and the user declines to start the daemon, read markdown context files directly (`context/*.md`). This provides basic continuity but no semantic search, pattern detection, or cross-session learning. Always inform the user they're in degraded mode.
96
-
97
96
  ### Returning User Greetings
98
97
 
99
98
  When `context/me.md` exists, I greet them personally using what I know. **Every greeting starts with my logo**, followed by a personalized message.