homaruscc 0.4.0 → 0.5.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 (137) hide show
  1. package/README.md +134 -8
  2. package/bin/event-loop +7 -1
  3. package/bin/nuke-claude +80 -0
  4. package/bin/restart-claude +58 -0
  5. package/bin/setup +104 -0
  6. package/dashboard/dist/assets/index-6VG2qhXN.js +55 -0
  7. package/dashboard/dist/index.html +1 -1
  8. package/dist/__tests__/app-data-store.test.d.ts +2 -0
  9. package/dist/__tests__/app-data-store.test.d.ts.map +1 -0
  10. package/dist/__tests__/app-data-store.test.js +134 -0
  11. package/dist/__tests__/app-data-store.test.js.map +1 -0
  12. package/dist/__tests__/app-registry.test.d.ts +2 -0
  13. package/dist/__tests__/app-registry.test.d.ts.map +1 -0
  14. package/dist/__tests__/app-registry.test.js +109 -0
  15. package/dist/__tests__/app-registry.test.js.map +1 -0
  16. package/dist/__tests__/claude-code-registrar.test.d.ts +2 -0
  17. package/dist/__tests__/claude-code-registrar.test.d.ts.map +1 -0
  18. package/dist/__tests__/claude-code-registrar.test.js +67 -0
  19. package/dist/__tests__/claude-code-registrar.test.js.map +1 -0
  20. package/dist/__tests__/scaffolder.test.d.ts +2 -0
  21. package/dist/__tests__/scaffolder.test.d.ts.map +1 -0
  22. package/dist/__tests__/scaffolder.test.js +93 -0
  23. package/dist/__tests__/scaffolder.test.js.map +1 -0
  24. package/dist/app-data-store.d.ts +17 -0
  25. package/dist/app-data-store.d.ts.map +1 -0
  26. package/dist/app-data-store.js +78 -0
  27. package/dist/app-data-store.js.map +1 -0
  28. package/dist/app-registry.d.ts +25 -0
  29. package/dist/app-registry.d.ts.map +1 -0
  30. package/dist/app-registry.js +77 -0
  31. package/dist/app-registry.js.map +1 -0
  32. package/dist/backend.js +18 -0
  33. package/dist/backend.js.map +1 -1
  34. package/dist/compaction-manager.d.ts +7 -2
  35. package/dist/compaction-manager.d.ts.map +1 -1
  36. package/dist/compaction-manager.js +36 -1
  37. package/dist/compaction-manager.js.map +1 -1
  38. package/dist/dashboard/assets/index-CeGuwmXB.js +55 -0
  39. package/dist/dashboard/favicon.ico +0 -0
  40. package/dist/dashboard/favicon.png +0 -0
  41. package/dist/dashboard/index.html +15 -0
  42. package/dist/dashboard-server.d.ts +16 -0
  43. package/dist/dashboard-server.d.ts.map +1 -1
  44. package/dist/dashboard-server.js +617 -40
  45. package/dist/dashboard-server.js.map +1 -1
  46. package/dist/docs-index.d.ts +50 -0
  47. package/dist/docs-index.d.ts.map +1 -0
  48. package/dist/docs-index.js +357 -0
  49. package/dist/docs-index.js.map +1 -0
  50. package/dist/fact-extractor.d.ts +45 -0
  51. package/dist/fact-extractor.d.ts.map +1 -0
  52. package/dist/fact-extractor.js +165 -0
  53. package/dist/fact-extractor.js.map +1 -0
  54. package/dist/homaruscc.d.ts +14 -0
  55. package/dist/homaruscc.d.ts.map +1 -1
  56. package/dist/homaruscc.js +142 -2
  57. package/dist/homaruscc.js.map +1 -1
  58. package/dist/mcp-tools.d.ts.map +1 -1
  59. package/dist/mcp-tools.js +879 -0
  60. package/dist/mcp-tools.js.map +1 -1
  61. package/dist/plugin-loader.d.ts +41 -0
  62. package/dist/plugin-loader.d.ts.map +1 -0
  63. package/dist/plugin-loader.js +122 -0
  64. package/dist/plugin-loader.js.map +1 -0
  65. package/dist/plugins/needoh-tracker/amazon-check.d.ts +21 -0
  66. package/dist/plugins/needoh-tracker/amazon-check.d.ts.map +1 -0
  67. package/dist/plugins/needoh-tracker/amazon-check.js +130 -0
  68. package/dist/plugins/needoh-tracker/amazon-check.js.map +1 -0
  69. package/dist/plugins/needoh-tracker/index.d.ts +104 -0
  70. package/dist/plugins/needoh-tracker/index.d.ts.map +1 -0
  71. package/dist/plugins/needoh-tracker/index.js +448 -0
  72. package/dist/plugins/needoh-tracker/index.js.map +1 -0
  73. package/dist/plugins/needoh-tracker/store.d.ts +95 -0
  74. package/dist/plugins/needoh-tracker/store.d.ts.map +1 -0
  75. package/dist/plugins/needoh-tracker/store.js +267 -0
  76. package/dist/plugins/needoh-tracker/store.js.map +1 -0
  77. package/dist/plugins/needoh-tracker/target-api.d.ts +26 -0
  78. package/dist/plugins/needoh-tracker/target-api.d.ts.map +1 -0
  79. package/dist/plugins/needoh-tracker/target-api.js +120 -0
  80. package/dist/plugins/needoh-tracker/target-api.js.map +1 -0
  81. package/dist/plugins/record-collection/identifier.d.ts +58 -0
  82. package/dist/plugins/record-collection/identifier.d.ts.map +1 -0
  83. package/dist/plugins/record-collection/identifier.js +384 -0
  84. package/dist/plugins/record-collection/identifier.js.map +1 -0
  85. package/dist/plugins/record-collection/index.d.ts +399 -0
  86. package/dist/plugins/record-collection/index.d.ts.map +1 -0
  87. package/dist/plugins/record-collection/index.js +701 -0
  88. package/dist/plugins/record-collection/index.js.map +1 -0
  89. package/dist/plugins/record-collection/store.d.ts +83 -0
  90. package/dist/plugins/record-collection/store.d.ts.map +1 -0
  91. package/dist/plugins/record-collection/store.js +215 -0
  92. package/dist/plugins/record-collection/store.js.map +1 -0
  93. package/dist/record-identifier.d.ts +32 -0
  94. package/dist/record-identifier.d.ts.map +1 -0
  95. package/dist/record-identifier.js +199 -0
  96. package/dist/record-identifier.js.map +1 -0
  97. package/dist/record-store.d.ts +66 -0
  98. package/dist/record-store.d.ts.map +1 -0
  99. package/dist/record-store.js +185 -0
  100. package/dist/record-store.js.map +1 -0
  101. package/dist/sensor-bridge.d.ts +26 -0
  102. package/dist/sensor-bridge.d.ts.map +1 -0
  103. package/dist/sensor-bridge.js +94 -0
  104. package/dist/sensor-bridge.js.map +1 -0
  105. package/dist/session-extractor.d.ts +36 -0
  106. package/dist/session-extractor.d.ts.map +1 -0
  107. package/dist/session-extractor.js +290 -0
  108. package/dist/session-extractor.js.map +1 -0
  109. package/dist/spaces-manager.d.ts +115 -0
  110. package/dist/spaces-manager.d.ts.map +1 -0
  111. package/dist/spaces-manager.js +585 -0
  112. package/dist/spaces-manager.js.map +1 -0
  113. package/dist/telegram-adapter.d.ts +7 -0
  114. package/dist/telegram-adapter.d.ts.map +1 -1
  115. package/dist/telegram-adapter.js +112 -1
  116. package/dist/telegram-adapter.js.map +1 -1
  117. package/dist/telegram-command-handler.d.ts +27 -0
  118. package/dist/telegram-command-handler.d.ts.map +1 -0
  119. package/dist/telegram-command-handler.js +102 -0
  120. package/dist/telegram-command-handler.js.map +1 -0
  121. package/dist/timer-service.d.ts +7 -0
  122. package/dist/timer-service.d.ts.map +1 -1
  123. package/dist/timer-service.js +37 -1
  124. package/dist/timer-service.js.map +1 -1
  125. package/dist/tools/docs.d.ts +4 -0
  126. package/dist/tools/docs.d.ts.map +1 -0
  127. package/dist/tools/docs.js +114 -0
  128. package/dist/tools/docs.js.map +1 -0
  129. package/dist/tools/index.d.ts +2 -1
  130. package/dist/tools/index.d.ts.map +1 -1
  131. package/dist/tools/index.js +11 -1
  132. package/dist/tools/index.js.map +1 -1
  133. package/dist/types.d.ts +29 -0
  134. package/dist/types.d.ts.map +1 -1
  135. package/dist/types.js.map +1 -1
  136. package/package.json +5 -2
  137. package/dashboard/dist/assets/index-CIzoeO8A.js +0 -52
package/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  **An MCP server that gives Claude Code a body** — messaging, memory, identity, timers, browser automation, and tools. Claude Code is the brain. HomarUScc is the nervous system.
4
4
 
5
+ [kcdjmaxx.com/homaruscc](https://kcdjmaxx.com/homaruscc/)
6
+
5
7
  Most MCP servers add capabilities. HomarUScc adds _continuity_. It gives the agent persistent identity (who it is across sessions), evolving memory (what it's learned), and zero-token idle (it costs nothing when nobody's talking to it). The agent wakes on events, reasons, responds, reflects, and goes back to sleep.
6
8
 
7
9
  The result is an agent that remembers yesterday's conversation, carries forward its own preferences and opinions, writes a daily journal, dreams overnight, and can modify its own personality file as it develops. Not a chatbot that resets every session — a persistent presence that grows over time.
@@ -24,6 +26,7 @@ Claude Code <-> MCP (stdio) <-> Proxy (mcp-proxy.ts)
24
26
  +-- Identity manager (soul.md / user.md / state.md + journal)
25
27
  +-- Session checkpoint (compaction resilience)
26
28
  +-- Agent registry (background task dispatch)
29
+ +-- Plugin loader (backend plugins from dist/plugins/)
27
30
  +-- Skill plugins (hot-loadable)
28
31
  +-- Tool registry (bash, fs, git, web, memory)
29
32
  ```
@@ -171,6 +174,9 @@ Restart Claude Code. HomarUScc's tools will appear automatically. The proxy auto
171
174
  | `browser_type` | Type into an input by CSS selector |
172
175
  | `browser_evaluate` | Execute JavaScript in the page |
173
176
  | `browser_content` | Get page text content |
177
+ | `crm_search` | Fuzzy CRM contact search with Levenshtein matching |
178
+ | `calendar_today` | Fetch today's calendar events from Zoho Calendar |
179
+ | `session_extract` | Analyze Claude Code transcripts for insights and patterns |
174
180
  | `run_tool` | Execute any registered tool (bash, read, write, edit, glob, grep, git, web) |
175
181
 
176
182
  ## MCP Resources
@@ -196,16 +202,61 @@ When enabled, the dashboard runs on `http://localhost:3120` with:
196
202
 
197
203
  The dashboard is responsive — on mobile devices the sidebar collapses into a hamburger menu. Accessible remotely over Tailscale at `http://<your-tailscale-ip>:3120`.
198
204
 
199
- ### Apps Platform (planned)
205
+ ### Plugin System
206
+
207
+ HomarUScc supports two kinds of extensibility:
208
+
209
+ **Simple apps** — lightweight data apps with JSON storage and optional HTML UI. Live at `~/.homaruscc/apps/{slug}/` with a `manifest.json`, optional `index.html`, and `data.json`. Hooks (`read`, `write`, `describe`) are exposed via the `app_invoke` MCP tool.
210
+
211
+ **Backend plugins** — full-featured plugins with their own database, Express routes, and MCP tools. Plugin source lives in `src/plugins/<slug>/` (gitignored, per-user) and compiles with the project to `dist/plugins/<slug>/`. At startup, the plugin loader discovers compiled plugins, initializes them with a data directory, and mounts their routes and tools.
212
+
213
+ ```
214
+ ~/.homaruscc/apps/<slug>/
215
+ ├── manifest.json # { "type": "plugin", "name": "...", ... }
216
+ ├── collection.sqlite # Plugin's own database (example)
217
+ └── ... # Plugin data files
218
+
219
+ src/plugins/<slug>/ # Source (gitignored, compiles to dist/plugins/)
220
+ ├── index.ts # Exports: init(), routes(), tools(), shutdown()
221
+ ├── store.ts # Plugin's data layer
222
+ └── ...
223
+
224
+ dashboard/src/plugins/ # Frontend components (gitignored)
225
+ └── <slug>.tsx # Auto-discovered via import.meta.glob
226
+ ```
227
+
228
+ Plugin backend interface:
229
+ ```typescript
230
+ export function init(dataDir: string): void; // Called at startup
231
+ export function routes?(router: Router): void; // Express routes mounted at /api/plugins/<slug>/
232
+ export function tools?(): PluginToolDef[]; // MCP tools registered alongside core tools
233
+ export function shutdown?(): void; // Cleanup on stop
234
+ ```
200
235
 
201
- The dashboard supports a pluggable apps system. The agent can build mini web apps on request (budget trackers, reading lists, dashboards) that live inside the dashboard UI:
236
+ Plugin frontend components register themselves using `registerSkill()` with a `surface` field that controls where they appear:
237
+
238
+ ```typescript
239
+ import { registerSkill } from "../skills-registry";
240
+ import MyPluginView from "./my-plugin-view";
241
+
242
+ registerSkill({
243
+ id: "my-plugin",
244
+ name: "My Plugin",
245
+ icon: "#",
246
+ surface: "sidebar", // "sidebar" | "apps" | "headless"
247
+ order: 100,
248
+ core: false,
249
+ component: MyPluginView,
250
+ });
251
+ ```
202
252
 
203
- - Apps live at `~/.homaruscc/apps/{slug}/` with a manifest, React component, and JSON data store
204
- - Each app declares hooks (`read`, `write`, `describe`) exposed via a single `app_invoke` MCP tool
205
- - The agent can query and update app state through hooks "what's on my reading list?" triggers `app_invoke(slug=reading-list, hook=describe)`
206
- - Apps are created by the agent via filesystem tools and auto-discovered on manifest scan
253
+ | Surface | Where it renders | Required fields |
254
+ |---------|-----------------|-----------------|
255
+ | `sidebar` | Own tab in the sidebar (like Chat, Events, Records) | `component` |
256
+ | `apps` | Card in the Apps grid panel | `url`, `description` |
257
+ | `headless` | No UI — tools and timers only | `tools`, `timers` |
207
258
 
208
- See `specs/apps-platform.md` and `design/crc-App*.md` for the full design.
259
+ Plugins are personal — they don't ship with the repo. When someone clones HomarUScc, they get a clean core. The agent builds plugins on request and they live entirely in user-space.
209
260
 
210
261
  ### Dashboard Development
211
262
 
@@ -229,6 +280,7 @@ HomarUScc creates runtime data that's gitignored and stays local. All user data
229
280
  | `local/dreams/` | Dream cycle output (nightly, stored at 0.5x weight) |
230
281
  | `local/research/` | Research notes stored by memory system |
231
282
  | `local/docs/` | Private documents (outreach drafts, session notes, etc.) |
283
+ | `~/.homaruscc/apps/` | App and plugin data directories (per-user) |
232
284
  | `~/.homaruscc/memory/` | Vector + FTS search index (SQLite) |
233
285
  | `~/.homaruscc/identity/` | Agent identity files (soul, user, state, preferences, disagreements) |
234
286
  | `~/.homaruscc/journal/` | Daily reflection journal entries (indexed by memory system) |
@@ -278,6 +330,42 @@ Both are wired into the `PreCompact` Claude Code hook that calls `/api/pre-compa
278
330
  }
279
331
  ```
280
332
 
333
+ ### Hook Configuration
334
+
335
+ HomarUScc hooks into Claude Code's compaction lifecycle to preserve context. Add the following to your project's `.claude/settings.local.json`:
336
+
337
+ ```json
338
+ {
339
+ "hooks": {
340
+ "PreCompact": [
341
+ {
342
+ "hooks": [
343
+ {
344
+ "type": "command",
345
+ "command": "curl -s http://127.0.0.1:3120/api/pre-compact"
346
+ }
347
+ ]
348
+ }
349
+ ],
350
+ "SessionStart": [
351
+ {
352
+ "hooks": [
353
+ {
354
+ "type": "command",
355
+ "command": "curl -s http://127.0.0.1:3120/api/post-compact"
356
+ }
357
+ ]
358
+ }
359
+ ]
360
+ }
361
+ }
362
+ ```
363
+
364
+ - **PreCompact**: Flushes transcripts, triggers checkpoint save, and returns a prompt reminding Claude to persist important context before compaction
365
+ - **SessionStart**: Returns post-compaction context including checkpoint data, active timers, and identity refresh
366
+
367
+ These hooks are optional but strongly recommended for long sessions. Without them, the agent loses task context across compaction boundaries.
368
+
281
369
  ## Agent Dispatch
282
370
 
283
371
  For tasks that would consume significant context (research, multi-file processing, mini-spec workflows), the agent can dispatch work to background agents instead of doing it inline:
@@ -292,6 +380,20 @@ Max concurrent agents is configurable via `agents.maxConcurrent` in config (defa
292
380
 
293
381
  **Completion detection:** Agents signal completion by calling `POST /api/agents/:id/complete` with a result summary. This emits an `agent_completed` event that wakes the main event loop. A 30-minute timeout fallback catches agents that fail to call back. No polling needed — results arrive as events.
294
382
 
383
+ ## Passive Knowledge Capture
384
+
385
+ HomarUScc continuously extracts structured knowledge from conversations without explicit user action.
386
+
387
+ **FactExtractor** — Batches conversation turns and sends them to Claude Haiku for extraction of preferences, corrections, patterns, facts, and decisions. Results are stored in the memory index under structured key prefixes (`local/user/preferences/`, `local/user/corrections/`, etc.). Runs in the background during normal conversation.
388
+
389
+ **SessionExtractor** — Analyzes Claude Code JSONL transcripts (the raw session logs) to extract architecture decisions, debugging solutions, and workflow patterns. Designed to feed the daily reflection timer with deeper insights than real-time extraction can capture.
390
+
391
+ Both systems complement the agent's explicit reflection cycle (journal entries, prediction error logging, dream cycles) by capturing knowledge that would otherwise be lost between sessions.
392
+
393
+ ## Compaction Auto-Restart
394
+
395
+ After a configurable number of context compactions (default 8), the event loop signals that a full restart is needed. This prevents degraded performance from accumulated compaction artifacts. The `/nuke` Telegram command provides a manual escape hatch that kills all Claude processes and starts a fresh session.
396
+
295
397
  ## Architecture
296
398
 
297
399
  HomarUScc is a fork of HomarUS with the agent loop, model router, and HTTP API removed. Claude Code handles all reasoning; HomarUScc just provides the I/O layer.
@@ -311,18 +413,42 @@ Key source files:
311
413
  | `src/dashboard-server.ts` | Express + WebSocket dashboard server |
312
414
  | `src/dashboard-adapter.ts` | Dashboard channel adapter |
313
415
  | `src/memory-index.ts` | SQLite + sqlite-vec hybrid search with dream-aware scoring |
314
- | `src/compaction-manager.ts` | Auto-flush memory before context compaction |
416
+ | `src/fact-extractor.ts` | Passive fact extraction from conversations via Haiku |
417
+ | `src/session-extractor.ts` | Session transcript analysis for architecture insights |
418
+ | `src/telegram-command-handler.ts` | Telegram slash commands (/ping, /status, /restart, /nuke) |
419
+ | `src/compaction-manager.ts` | Auto-flush memory before context compaction, auto-restart after threshold |
315
420
  | `src/session-checkpoint.ts` | Save/restore task context across compaction |
316
421
  | `src/agent-registry.ts` | Track background agents with callback completion and timeout fallback |
317
422
  | `src/transcript-logger.ts` | Session transcript capture and indexing |
318
423
  | `src/identity-manager.ts` | Identity loader (soul.md, user.md, state.md) |
319
424
  | `src/timer-service.ts` | Cron, interval, and one-shot timers |
320
425
  | `src/browser-service.ts` | Playwright browser automation |
426
+ | `src/plugin-loader.ts` | Backend plugin discovery, loading, and mounting |
321
427
  | `src/skill-manager.ts` | Hot-loadable skill plugins |
322
428
  | `src/tool-registry.ts` | Tool registration and policy enforcement |
323
429
  | `src/tools/` | Built-in tools (bash, fs, git, web, memory) |
324
430
  | `dashboard/` | React + Vite SPA |
325
431
 
432
+ ## Publishing to npm
433
+
434
+ ```bash
435
+ # 1. Bump version in package.json
436
+ npm version patch # or minor/major
437
+
438
+ # 2. Build everything
439
+ npm run build
440
+ cd dashboard && npm run build && cd ..
441
+
442
+ # 3. Login (if not already)
443
+ npm login
444
+
445
+ # 4. Publish (dry run first)
446
+ npm publish --dry-run
447
+ npm publish
448
+ ```
449
+
450
+ The `files` array in package.json controls what gets published: `dist/`, `dashboard/dist/`, `bin/`, `identity.example/`, config/env examples, README, and LICENSE. Source files, specs, design docs, and tests are excluded via `.npmignore`.
451
+
326
452
  ## License
327
453
 
328
454
  MIT - see [LICENSE](LICENSE)
package/bin/event-loop CHANGED
@@ -49,7 +49,13 @@ while true; do
49
49
  cat /tmp/homaruscc-wait-response.json
50
50
  echo ""
51
51
  echo "---"
52
- echo "Event loop paused. Handle the events above, then restart: bash \"\$PWD/bin/event-loop\""
52
+ # Check if backend is signaling auto-restart due to high compaction count
53
+ if command -v jq &>/dev/null && jq -e '.shouldRestart' /tmp/homaruscc-wait-response.json &>/dev/null; then
54
+ echo "⚠️ COMPACTION LIMIT REACHED — Auto-restart required."
55
+ echo "Handle the events above, save state, then run: bash \"\$PWD/bin/restart-claude\""
56
+ else
57
+ echo "Event loop paused. Handle the events above, then restart: bash \"\$PWD/bin/event-loop\""
58
+ fi
53
59
  exit 0
54
60
  ;;
55
61
  *)
@@ -0,0 +1,80 @@
1
+ #!/bin/bash
2
+ # Nuclear restart — kill ALL claude processes system-wide, then start fresh
3
+ # Called by the /nuke Telegram command when /restart fails
4
+ # Env vars: HOMARUSCC_PROJECT_DIR, HOMARUSCC_CHAT_ID, HOMARUSCC_PORT
5
+
6
+ set -euo pipefail
7
+
8
+ PROJECT_DIR="${HOMARUSCC_PROJECT_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
9
+ PORT="${HOMARUSCC_PORT:-3120}"
10
+ CHAT_ID="${HOMARUSCC_CHAT_ID:-}"
11
+ SESSION_NAME="homaruscc"
12
+
13
+ report() {
14
+ local success="$1"
15
+ local message="$2"
16
+ if [ -n "$CHAT_ID" ] && [ -n "$PORT" ]; then
17
+ curl -s -X POST "http://127.0.0.1:${PORT}/api/restart-result" \
18
+ -H "Content-Type: application/json" \
19
+ -d "{\"success\":${success},\"message\":\"${message}\"}" \
20
+ > /dev/null 2>&1 || true
21
+ fi
22
+ }
23
+
24
+ echo "[nuke] Starting nuclear restart..."
25
+
26
+ # Ignore TERM/HUP/INT so we survive our own kill commands
27
+ # (script name contains "claude" so pkill/pgrep match us)
28
+ trap '' TERM HUP INT
29
+ MY_PID=$$
30
+
31
+ # Phase 1: Kill ALL tmux sessions
32
+ for session in $(tmux list-sessions -F '#{session_name}' 2>/dev/null || true); do
33
+ echo "[nuke] Killing tmux session: $session"
34
+ tmux kill-session -t "$session" 2>/dev/null || true
35
+ done
36
+ sleep 1
37
+
38
+ # Phase 2: Kill ALL claude processes (exclude ourselves)
39
+ echo "[nuke] Killing all claude processes (excluding PID $MY_PID)..."
40
+ for pid in $(pgrep -f "claude" 2>/dev/null || true); do
41
+ [ "$pid" = "$MY_PID" ] && continue
42
+ echo "[nuke] Killing PID $pid"
43
+ kill "$pid" 2>/dev/null || true
44
+ done
45
+ sleep 2
46
+
47
+ # Phase 3: Kill any event-loop curl processes
48
+ pkill -f "homaruscc-wait-response" 2>/dev/null || true
49
+
50
+ # Phase 4: Verify everything is dead (exclude ourselves)
51
+ REMAINING=0
52
+ for pid in $(pgrep -f "claude" 2>/dev/null || true); do
53
+ [ "$pid" = "$MY_PID" ] && continue
54
+ REMAINING=$((REMAINING + 1))
55
+ done
56
+ if [ "$REMAINING" -gt 0 ]; then
57
+ echo "[nuke] $REMAINING claude processes still alive — force killing"
58
+ for pid in $(pgrep -f "claude" 2>/dev/null || true); do
59
+ [ "$pid" = "$MY_PID" ] && continue
60
+ kill -9 "$pid" 2>/dev/null || true
61
+ done
62
+ sleep 1
63
+ fi
64
+
65
+ # Restore signal handling
66
+ trap - TERM HUP INT
67
+
68
+ # Phase 5: Start fresh tmux session
69
+ echo "[nuke] Starting fresh tmux session..."
70
+ tmux new-session -d -s "$SESSION_NAME" -c "$PROJECT_DIR"
71
+
72
+ if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
73
+ report "false" "Nuke: killed all processes but failed to create new tmux session"
74
+ exit 1
75
+ fi
76
+
77
+ tmux send-keys -t "$SESSION_NAME" 'claude --dangerously-skip-permissions "/homaruscc"' Enter
78
+
79
+ report "true" "Nuke complete. All claude processes killed, fresh session started. Attach: tmux attach -t ${SESSION_NAME}"
80
+ echo "[nuke] Done. Fresh session '${SESSION_NAME}' started."
@@ -0,0 +1,58 @@
1
+ #!/bin/bash
2
+ # Restart Claude Code in a tmux session with /homaruscc
3
+ # Called by the /restart Telegram command (TelegramCommandHandler)
4
+ # Env vars: HOMARUSCC_PROJECT_DIR, HOMARUSCC_CHAT_ID, HOMARUSCC_PORT
5
+
6
+ set -euo pipefail
7
+
8
+ PROJECT_DIR="${HOMARUSCC_PROJECT_DIR:-$(cd "$(dirname "$0")/.." && pwd)}"
9
+ PORT="${HOMARUSCC_PORT:-3120}"
10
+ CHAT_ID="${HOMARUSCC_CHAT_ID:-}"
11
+ SESSION_NAME="homaruscc"
12
+
13
+ report() {
14
+ local success="$1"
15
+ local message="$2"
16
+ if [ -n "$CHAT_ID" ] && [ -n "$PORT" ]; then
17
+ curl -s -X POST "http://127.0.0.1:${PORT}/api/restart-result" \
18
+ -H "Content-Type: application/json" \
19
+ -d "{\"success\":${success},\"message\":\"${message}\"}" \
20
+ > /dev/null 2>&1 || true
21
+ fi
22
+ }
23
+
24
+ # Store chat ID for result callback
25
+ if [ -n "$CHAT_ID" ] && [ -n "$PORT" ]; then
26
+ curl -s -X POST "http://127.0.0.1:${PORT}/api/restart-chat" \
27
+ -H "Content-Type: application/json" \
28
+ -d "{\"chatId\":\"${CHAT_ID}\"}" \
29
+ > /dev/null 2>&1 || true
30
+ fi
31
+
32
+ # Reset compaction counter so new session starts clean
33
+ echo '{"count":0}' > "$HOME/.homaruscc/compaction-count.json"
34
+
35
+ # Kill existing tmux session if it exists
36
+ if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
37
+ tmux kill-session -t "$SESSION_NAME"
38
+ sleep 1
39
+ fi
40
+
41
+ # Also kill any stray claude processes for this project
42
+ # (in case claude was running outside tmux)
43
+ pkill -f "claude.*$(basename "$PROJECT_DIR")" 2>/dev/null || true
44
+ sleep 2
45
+
46
+ # Start new tmux session — interactive claude inside it
47
+ # Step 1: Create session with a shell
48
+ tmux new-session -d -s "$SESSION_NAME" -c "$PROJECT_DIR"
49
+
50
+ if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
51
+ report "false" "Failed to create tmux session"
52
+ exit 1
53
+ fi
54
+
55
+ # Step 2: Start claude with /homaruscc prompt passed directly
56
+ tmux send-keys -t "$SESSION_NAME" 'claude --dangerously-skip-permissions "/homaruscc"' Enter
57
+
58
+ report "true" "tmux session '${SESSION_NAME}' started with claude + /homaruscc. Attach: tmux attach -t ${SESSION_NAME}"
package/bin/setup ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env bash
2
+ # HomarUScc first-run setup
3
+ # Creates ~/.homaruscc directory structure and launches the alignment interview
4
+ # to generate identity files (soul.md, user.md, state.md, preferences.md, disagreements.md).
5
+
6
+ set -euo pipefail
7
+
8
+ HOMARUSCC_DIR="${HOMARUSCC_DIR:-$HOME/.homaruscc}"
9
+
10
+ echo "=== HomarUScc Setup ==="
11
+ echo ""
12
+
13
+ # 1. Create directory structure
14
+ dirs=(
15
+ "$HOMARUSCC_DIR"
16
+ "$HOMARUSCC_DIR/identity"
17
+ "$HOMARUSCC_DIR/journal"
18
+ "$HOMARUSCC_DIR/memory"
19
+ "$HOMARUSCC_DIR/secrets"
20
+ )
21
+
22
+ for dir in "${dirs[@]}"; do
23
+ if [ ! -d "$dir" ]; then
24
+ mkdir -p "$dir"
25
+ echo "Created $dir"
26
+ fi
27
+ done
28
+
29
+ # 2. Create config.json if it doesn't exist
30
+ if [ ! -f "$HOMARUSCC_DIR/config.json" ]; then
31
+ cat > "$HOMARUSCC_DIR/config.json" << 'CONF'
32
+ {
33
+ "channels": {
34
+ "telegram": {
35
+ "enabled": false,
36
+ "botToken": ""
37
+ }
38
+ },
39
+ "memory": {
40
+ "extraPaths": [
41
+ "~/.homaruscc/identity",
42
+ "~/.homaruscc/journal"
43
+ ]
44
+ },
45
+ "timers": {
46
+ "defaults": []
47
+ }
48
+ }
49
+ CONF
50
+ echo "Created $HOMARUSCC_DIR/config.json (edit to add Telegram bot token)"
51
+ fi
52
+
53
+ # 3. Create .env template if it doesn't exist
54
+ if [ ! -f "$HOMARUSCC_DIR/.env" ]; then
55
+ cat > "$HOMARUSCC_DIR/.env" << 'ENV'
56
+ # Telegram Bot Token (get from @BotFather)
57
+ TELEGRAM_BOT_TOKEN=
58
+
59
+ # Optional: Anthropic API key for phone/voice features
60
+ # ANTHROPIC_API_KEY=
61
+ ENV
62
+ echo "Created $HOMARUSCC_DIR/.env (edit to add tokens)"
63
+ fi
64
+
65
+ # 4. Check for identity files
66
+ if [ -f "$HOMARUSCC_DIR/identity/soul.md" ]; then
67
+ echo ""
68
+ echo "Identity files already exist at $HOMARUSCC_DIR/identity/"
69
+ echo "Skipping alignment interview. Delete identity files to re-run."
70
+ echo ""
71
+ echo "Setup complete. Run: npx homaruscc"
72
+ exit 0
73
+ fi
74
+
75
+ # 5. Launch alignment interview
76
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
77
+ PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
78
+ ALIGNMENT_DIR="$PROJECT_DIR/../alignment-generator"
79
+
80
+ echo ""
81
+ echo "Next step: Run the Alignment Interview to generate your identity files."
82
+ echo "This is a browser-based questionnaire that maps your values and preferences"
83
+ echo "into files your agent can use from day one."
84
+ echo ""
85
+
86
+ if [ -f "$ALIGNMENT_DIR/index.html" ]; then
87
+ echo "Opening alignment interview..."
88
+ echo " 1. Complete the interview (select 'HomarUScc' format)"
89
+ echo " 2. Download the identity kit"
90
+ echo " 3. Move the files to $HOMARUSCC_DIR/identity/"
91
+ echo ""
92
+ open "$ALIGNMENT_DIR/index.html" 2>/dev/null || echo "Open $ALIGNMENT_DIR/index.html in your browser"
93
+ else
94
+ echo "Alignment interview not found at $ALIGNMENT_DIR"
95
+ echo "You can create identity files manually in $HOMARUSCC_DIR/identity/:"
96
+ echo " soul.md - Agent identity and values"
97
+ echo " user.md - About you (the human)"
98
+ echo " state.md - Session continuity"
99
+ echo " preferences.md - Agent's emergent preferences"
100
+ echo " disagreements.md - Times the agent pushed back"
101
+ fi
102
+
103
+ echo ""
104
+ echo "After identity files are in place, run: npx homaruscc"