get-claudia 1.42.1 → 1.42.3

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
@@ -5,7 +5,7 @@
5
5
  <h3 align="center">A thinking partner who tracks relationships, not just tasks.</h3>
6
6
 
7
7
  <p align="center">
8
- Catches commitments. Remembers context. Connects the dots across your network.
8
+ Remembers your people. Catches your commitments. Learns how you work.
9
9
  </p>
10
10
 
11
11
  <p align="center">
@@ -17,6 +17,7 @@ Catches commitments. Remembers context. Connects the dots across your network.
17
17
  <p align="center">
18
18
  <a href="#try-it-in-30-seconds"><strong>Try the Demo</strong></a> ·
19
19
  <a href="#what-makes-claudia-different">Why Claudia</a> ·
20
+ <a href="#how-her-mind-works">Her Mind</a> ·
20
21
  <a href="#quick-start">Install</a> ·
21
22
  <a href="#how-it-works">How It Works</a>
22
23
  </p>
@@ -42,26 +43,53 @@ You make a promise in a meeting. Nobody tracks it. You promise a deliverable on
42
43
  <p>Say "I'll send that by Friday" and she tracks it. On Friday morning, she reminds you.</p>
43
44
  </td>
44
45
  <td width="33%" align="center">
45
- <h3>🔗 Remembers Relationships</h3>
46
- <p>Mention Sarah from Acme and Claudia surfaces: last conversation, open promises, sentiment.</p>
46
+ <h3>🔗 Knows Your People</h3>
47
+ <p>Every person she meets gets a living profile: relationship health, contact trends, connected entities. Ask about anyone and she has the full picture.</p>
47
48
  </td>
48
49
  <td width="33%" align="center">
49
- <h3>⚠️ Warns Before Things Slip</h3>
50
- <p>Haven't talked to your best client in 3 weeks? She tells you before it's a problem.</p>
50
+ <h3>⚠️ Spots Patterns You Miss</h3>
51
+ <p>Overcommitting again? A key relationship going cold? The same mistake twice? She sees it forming and speaks up.</p>
51
52
  </td>
52
53
  </tr>
53
54
  <tr>
54
55
  <td width="33%" align="center">
55
- <h3>📄 Shows Her Work</h3>
56
+ <h3>📄 Shows Her Sources</h3>
56
57
  <p>Every fact traces to its source. Ask "how do you know that?" and she shows the receipt.</p>
57
58
  </td>
58
59
  <td width="33%" align="center">
59
- <h3>🧠 Obsidian Vault Sync</h3>
60
- <p>Memory syncs to an Obsidian vault as markdown notes with wikilinks. Graph view visualizes your entire network. Plain files you own forever.</p>
60
+ <h3>🧠 Second Brain in Obsidian</h3>
61
+ <p>Memory syncs to an Obsidian vault organized by activity: Active projects, Relationships, Reference, Archive. Graph view maps your world. Plain markdown you own forever.</p>
61
62
  </td>
62
63
  <td width="33%" align="center">
63
- <h3>🔒 Fully Local</h3>
64
- <p>Everything runs on your machine. Your data never leaves. Delete anything, anytime.</p>
64
+ <h3>🌙 Learns in the Background</h3>
65
+ <p>Overnight, old memories fade, near-duplicates merge, and patterns surface. Each morning she knows a little more than yesterday.</p>
66
+ </td>
67
+ </tr>
68
+ </table>
69
+
70
+ ---
71
+
72
+ ## How Her Mind Works
73
+
74
+ <table>
75
+ <tr>
76
+ <td width="50%" align="center">
77
+ <h3>💾 Remember</h3>
78
+ <p>Every fact is stored with who said it, when, and how confident she is. Embeddings capture <em>meaning</em>, not just keywords, so "we pushed the launch" and "timeline shifted" connect naturally.</p>
79
+ </td>
80
+ <td width="50%" align="center">
81
+ <h3>🔍 Recall</h3>
82
+ <p>Search blends meaning similarity, importance, recency, and full-text matching. Accessing a memory strengthens it, just like the rehearsal effect in human cognition.</p>
83
+ </td>
84
+ </tr>
85
+ <tr>
86
+ <td width="50%" align="center">
87
+ <h3>🌙 Consolidate</h3>
88
+ <p>Overnight background jobs fade old memories, merge near-duplicates, and surface patterns: cooling relationships, overdue commitments, repeated behaviors. She wakes up sharper.</p>
89
+ </td>
90
+ <td width="50%" align="center">
91
+ <h3>📓 Vault</h3>
92
+ <p>Memory syncs to an Obsidian vault organized with PARA: Active projects, Relationships, Reference material, Archive. Graph view shows how your world connects. Plain markdown you own forever.</p>
65
93
  </td>
66
94
  </tr>
67
95
  </table>
@@ -153,7 +181,37 @@ Claudia: Sarah Chen is CEO at Meridian Ventures. You met at SaaStr 2025.
153
181
  Source: Call notes from Jan 28, Email thread Jan 30
154
182
  ```
155
183
 
156
- From here, every conversation builds on the last. She remembers.
184
+ **Morning brief pulls everything together:**
185
+
186
+ ```
187
+ You: /morning-brief
188
+
189
+ Claudia: ☀️ Morning Brief — Wednesday, Feb 19
190
+
191
+ ⚠️ Needs Attention:
192
+ • Send updated pitch deck to Sarah Chen [OVERDUE]
193
+ • Quarterly review with Acme Corp is tomorrow
194
+
195
+ 👀 Watch:
196
+ • Haven't spoken to Marcus in 18 days (usually weekly)
197
+ • Two new commitments this week, zero closed
198
+
199
+ 📊 Today: 3 meetings, 2 open commitments
200
+ ```
201
+
202
+ **Pattern detection works across weeks, not just moments:**
203
+
204
+ ```
205
+ Claudia: I've noticed something across the last few weeks.
206
+ You've taken on 4 new commitments without closing any.
207
+ Last time this happened (early January), two slipped
208
+ past deadline.
209
+
210
+ Want me to flag the lowest-priority ones so you can
211
+ decide what to defer?
212
+ ```
213
+
214
+ Every conversation builds on the last. She remembers.
157
215
 
158
216
  ---
159
217
 
@@ -180,8 +238,9 @@ Claudia detects your work style and generates structure that fits:
180
238
  | `/meeting-prep [person]` | One-page briefing before a call |
181
239
  | `/capture-meeting` | Process notes into decisions, commitments, action items |
182
240
  | `/what-am-i-missing` | Surface risks, overdue items, cooling relationships |
183
- | `/inbox-check` | Review Telegram and webhook messages |
184
- | `/gateway` | Manage external message gateway |
241
+ | `/sync-vault` | Sync memory to Obsidian vault |
242
+ | `/brain` | Launch 3D brain visualizer |
243
+ | `/deep-context [topic]` | Full-context deep analysis |
185
244
  | `/memory-audit` | See everything Claudia knows, with source chains |
186
245
 
187
246
  <details>
@@ -196,8 +255,10 @@ Claudia detects your work style and generates structure that fits:
196
255
  | `/new-person [name]` | Create a relationship file |
197
256
  | `/pipeline-review` | Active deals, capacity, pipeline health |
198
257
  | `/client-health` | Status across all client relationships |
199
- | `/setup-gateway` | Configure external message gateway |
200
- | `/setup-telegram` | Connect Telegram bot integration |
258
+ | `/inbox-check` | Review messages from connected channels |
259
+ | `/meditate` | End-of-session reflection and persistent learnings |
260
+ | `/fix-duplicates` | Find and merge duplicate entities |
261
+ | `/memory-health` | Check memory system health |
201
262
  | `/diagnose` | Check memory daemon health and troubleshoot |
202
263
 
203
264
  </details>
@@ -224,12 +285,14 @@ You ──► Claude Code ──► Reads Claudia's templates ──► Becomes
224
285
 
225
286
  Memory daemon (local) ◄── MCP tools
226
287
 
227
- ┌──────┴──────┐
228
-
229
- SQLite + vectors + Ollama Obsidian vault
230
- (all local) (markdown notes)
288
+ ┌──────┼──────┐
289
+
290
+ SQLite Ollama Obsidian vault
291
+ +vectors (PARA structure)
231
292
  ```
232
293
 
294
+ **Local extraction, zero API calls.** Paste a meeting transcript or email thread. A local language model (Qwen3, SmolLM3, or Llama 3.2 via Ollama) extracts entities, commitments, and decisions in seconds. Claude reviews the extractions and applies judgment. No data leaves your machine.
295
+
233
296
  <details>
234
297
  <summary><strong>Technical deep dive</strong></summary>
235
298
 
@@ -249,26 +312,13 @@ For full architecture diagrams, see [ARCHITECTURE.md](ARCHITECTURE.md).
249
312
 
250
313
  </details>
251
314
 
252
- <details>
253
- <summary><strong>Cognitive tools (local LLM extraction)</strong></summary>
254
-
255
- Paste a meeting transcript. A local language model extracts structured data (entities, facts, commitments) in seconds. Claude reviews and applies judgment.
256
-
257
- - Runs locally via [Ollama](https://ollama.com), no API keys
258
- - Models: Qwen3-4B (recommended), SmolLM3-3B, Llama 3.2-3B
259
- - Falls back gracefully when no model installed
260
-
261
- Four extraction modes: **meeting**, **email**, **document**, **general**.
262
-
263
- </details>
264
-
265
315
  ---
266
316
 
267
317
  ## Privacy and Safety
268
318
 
269
319
  - **Fully local.** Memory, embeddings, cognitive tools run on your machine. No external APIs for storage.
270
320
  - **No external actions without approval.** Every email, calendar event, external action requires your explicit "yes."
271
- - **Your data in two formats.** SQLite database (`~/.claudia/memory/`) for fast semantic search, plus plain markdown files in your Obsidian vault for reading and graph navigation. Two independent copies you own forever.
321
+ - **Your data in two formats.** SQLite database (`~/.claudia/memory/`) for fast semantic search, plus a PARA-organized Obsidian vault for reading and graph navigation. Two independent copies you own forever.
272
322
  - **Delete anything, anytime.** Full control over your data. No lock-in, no cloud dependency.
273
323
 
274
324
  ---
package/bin/index.js CHANGED
@@ -376,7 +376,7 @@ async function main() {
376
376
  stdio: 'inherit',
377
377
  env: {
378
378
  ...process.env,
379
- CLAUDIA_PROJECT_PATH: isUpgrade ? targetPath : '',
379
+ CLAUDIA_PROJECT_PATH: targetPath,
380
380
  CLAUDIA_NONINTERACTIVE: '1'
381
381
  }
382
382
  });
@@ -160,6 +160,31 @@ class HealthCheckHandler(BaseHTTPRequestHandler):
160
160
  else:
161
161
  self.send_error(404, "Not Found")
162
162
 
163
+ def do_POST(self):
164
+ """Handle POST requests"""
165
+ if self.path == "/backup":
166
+ self._send_backup_response()
167
+ else:
168
+ self.send_error(405, "Method Not Allowed")
169
+
170
+ def _send_backup_response(self):
171
+ """Trigger a database backup and return the path."""
172
+ try:
173
+ db = get_db()
174
+ path = db.backup()
175
+ self._send_json({"status": "ok", "path": str(path)})
176
+ except Exception as e:
177
+ logger.exception("Error triggering backup")
178
+ self._send_json({"status": "error", "message": str(e)}, code=500)
179
+
180
+ def _send_json(self, data: dict, code: int = 200):
181
+ """Helper to send a JSON response."""
182
+ body = json.dumps(data).encode()
183
+ self.send_response(code)
184
+ self.send_header("Content-Type", "application/json")
185
+ self.end_headers()
186
+ self.wfile.write(body)
187
+
163
188
  def _send_health_response(self):
164
189
  """Send basic health check response"""
165
190
  health = {
@@ -722,6 +722,19 @@ async def list_tools() -> ListToolsResult:
722
722
  "properties": {},
723
723
  },
724
724
  ),
725
+ Tool(
726
+ name="memory.backup",
727
+ title="Trigger Database Backup",
728
+ description=(
729
+ "Trigger an immediate backup of the memory database. Returns the path "
730
+ "of the newly created backup file. Backups use a timestamp suffix and "
731
+ "older backups are pruned automatically per the retention policy."
732
+ ),
733
+ inputSchema={
734
+ "type": "object",
735
+ "properties": {},
736
+ },
737
+ ),
725
738
  Tool(
726
739
  name="memory.project_health",
727
740
  title="Project Health Check",
@@ -2587,8 +2600,14 @@ async def call_tool(name: str, arguments: Dict[str, Any]) -> CallToolResult:
2587
2600
  )
2588
2601
 
2589
2602
  elif name == "memory.system_health":
2590
- from ..daemon.health import build_status_report
2591
- report = build_status_report()
2603
+ import urllib.request, urllib.error
2604
+ report = None
2605
+ try:
2606
+ with urllib.request.urlopen("http://localhost:3848/status", timeout=2) as resp:
2607
+ report = json.loads(resp.read().decode())
2608
+ except (urllib.error.URLError, OSError):
2609
+ from ..daemon.health import build_status_report
2610
+ report = build_status_report()
2592
2611
  embedding_svc = get_embedding_service()
2593
2612
  if hasattr(embedding_svc, '_model_mismatch') and embedding_svc._model_mismatch:
2594
2613
  if "components" not in report:
@@ -2603,6 +2622,28 @@ async def call_tool(name: str, arguments: Dict[str, Any]) -> CallToolResult:
2603
2622
  ]
2604
2623
  )
2605
2624
 
2625
+ elif name == "memory.backup":
2626
+ import urllib.request, urllib.error
2627
+ result = None
2628
+ try:
2629
+ req = urllib.request.Request(
2630
+ "http://localhost:3848/backup", method="POST", data=b""
2631
+ )
2632
+ with urllib.request.urlopen(req, timeout=10) as resp:
2633
+ result = json.loads(resp.read().decode())
2634
+ except (urllib.error.URLError, OSError):
2635
+ # Daemon not running — trigger backup directly
2636
+ backup_path = get_db().backup()
2637
+ result = {"status": "ok", "path": str(backup_path)}
2638
+ return CallToolResult(
2639
+ content=[
2640
+ TextContent(
2641
+ type="text",
2642
+ text=json.dumps(result, indent=2),
2643
+ )
2644
+ ]
2645
+ )
2646
+
2606
2647
  elif name == "memory.sync_vault":
2607
2648
  from ..config import _project_id
2608
2649
  from ..services.vault_sync import run_vault_sync
@@ -2010,6 +2010,49 @@ class ConsolidateService:
2010
2010
 
2011
2011
  logger.debug(f"Merged reflection {duplicate['id']} into {primary['id']}")
2012
2012
 
2013
+ def close_stale_episodes(self) -> int:
2014
+ """Auto-close orphan episodes that have no end_session call.
2015
+
2016
+ Single-turn sessions and interrupted sessions leave episodes with
2017
+ ``ended_at IS NULL``. After 24 hours these will never be closed
2018
+ naturally, so this pass marks them as summarized with a synthetic
2019
+ summary to prevent them from appearing as false positives in health
2020
+ reports.
2021
+
2022
+ Returns the number of episodes closed.
2023
+ """
2024
+ cutoff = (datetime.utcnow() - timedelta(hours=24)).isoformat()
2025
+ try:
2026
+ # Find stale open episodes and close them. ended_at is set to the
2027
+ # timestamp of the latest buffered turn if one exists, otherwise to
2028
+ # started_at itself (single-turn / empty sessions).
2029
+ self.db.execute(
2030
+ """
2031
+ UPDATE episodes
2032
+ SET
2033
+ ended_at = COALESCE(
2034
+ (
2035
+ SELECT MAX(created_at) FROM turn_buffer
2036
+ WHERE turn_buffer.session_id = episodes.session_id
2037
+ ),
2038
+ started_at
2039
+ ),
2040
+ is_summarized = 1,
2041
+ summary = 'Auto-closed: session ended without explicit end_session call'
2042
+ WHERE ended_at IS NULL
2043
+ AND started_at < ?
2044
+ """,
2045
+ (cutoff,),
2046
+ )
2047
+ rows = self.db.execute("SELECT changes()", fetch=True)
2048
+ count = rows[0][0] if rows else 0
2049
+ if count:
2050
+ logger.info(f"Auto-closed {count} stale open episode(s)")
2051
+ return count
2052
+ except Exception as e:
2053
+ logger.warning(f"close_stale_episodes failed: {e}")
2054
+ return 0
2055
+
2013
2056
  def run_retention_cleanup(self) -> Dict[str, int]:
2014
2057
  """Clean up old data per retention policies.
2015
2058
 
@@ -2018,6 +2061,7 @@ class ConsolidateService:
2018
2061
  - Expired predictions past retention window
2019
2062
  - Archived turn_buffer from old episodes
2020
2063
  - Old metrics rows
2064
+ - Auto-closes stale open episodes (no end_session after 24 h)
2021
2065
  """
2022
2066
  results = {}
2023
2067
  now = datetime.utcnow()
@@ -2074,6 +2118,9 @@ class ConsolidateService:
2074
2118
  logger.warning(f"Metrics cleanup failed: {e}")
2075
2119
  results["metrics_deleted"] = 0
2076
2120
 
2121
+ # Auto-close orphan episodes (no end_session after 24 h)
2122
+ results["stale_episodes_closed"] = self.close_stale_episodes()
2123
+
2077
2124
  logger.info(f"Retention cleanup: {results}")
2078
2125
  return results
2079
2126
 
@@ -366,9 +366,13 @@ try {
366
366
  }
367
367
 
368
368
  # Create the scheduled task action
369
+ $taskArgs = "-m claudia_memory --standalone"
370
+ if ($env:CLAUDIA_PROJECT_PATH) {
371
+ $taskArgs += " --project-dir `"$($env:CLAUDIA_PROJECT_PATH)`""
372
+ }
369
373
  $action = New-ScheduledTaskAction `
370
374
  -Execute $VENV_PYTHON `
371
- -Argument "-m claudia_memory --standalone" `
375
+ -Argument $taskArgs `
372
376
  -WorkingDirectory $DAEMON_DIR
373
377
 
374
378
  # Trigger: at logon for current user
@@ -518,7 +518,7 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
518
518
  <string>$VENV_DIR/bin/python</string>
519
519
  <string>-m</string>
520
520
  <string>claudia_memory</string>
521
- <string>--standalone</string>
521
+ <string>--standalone</string>$(if [ -n "$CLAUDIA_PROJECT_PATH" ]; then printf '\n <string>--project-dir</string>\n <string>%s</string>' "$CLAUDIA_PROJECT_PATH"; fi)
522
522
  </array>
523
523
  <key>WorkingDirectory</key>
524
524
  <string>$DAEMON_DIR</string>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "get-claudia",
3
- "version": "1.42.1",
3
+ "version": "1.42.3",
4
4
  "description": "An AI assistant who learns how you work.",
5
5
  "keywords": [
6
6
  "claudia",