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.
- package/README.md +134 -8
- package/bin/event-loop +7 -1
- package/bin/nuke-claude +80 -0
- package/bin/restart-claude +58 -0
- package/bin/setup +104 -0
- package/dashboard/dist/assets/index-6VG2qhXN.js +55 -0
- package/dashboard/dist/index.html +1 -1
- package/dist/__tests__/app-data-store.test.d.ts +2 -0
- package/dist/__tests__/app-data-store.test.d.ts.map +1 -0
- package/dist/__tests__/app-data-store.test.js +134 -0
- package/dist/__tests__/app-data-store.test.js.map +1 -0
- package/dist/__tests__/app-registry.test.d.ts +2 -0
- package/dist/__tests__/app-registry.test.d.ts.map +1 -0
- package/dist/__tests__/app-registry.test.js +109 -0
- package/dist/__tests__/app-registry.test.js.map +1 -0
- package/dist/__tests__/claude-code-registrar.test.d.ts +2 -0
- package/dist/__tests__/claude-code-registrar.test.d.ts.map +1 -0
- package/dist/__tests__/claude-code-registrar.test.js +67 -0
- package/dist/__tests__/claude-code-registrar.test.js.map +1 -0
- package/dist/__tests__/scaffolder.test.d.ts +2 -0
- package/dist/__tests__/scaffolder.test.d.ts.map +1 -0
- package/dist/__tests__/scaffolder.test.js +93 -0
- package/dist/__tests__/scaffolder.test.js.map +1 -0
- package/dist/app-data-store.d.ts +17 -0
- package/dist/app-data-store.d.ts.map +1 -0
- package/dist/app-data-store.js +78 -0
- package/dist/app-data-store.js.map +1 -0
- package/dist/app-registry.d.ts +25 -0
- package/dist/app-registry.d.ts.map +1 -0
- package/dist/app-registry.js +77 -0
- package/dist/app-registry.js.map +1 -0
- package/dist/backend.js +18 -0
- package/dist/backend.js.map +1 -1
- package/dist/compaction-manager.d.ts +7 -2
- package/dist/compaction-manager.d.ts.map +1 -1
- package/dist/compaction-manager.js +36 -1
- package/dist/compaction-manager.js.map +1 -1
- package/dist/dashboard/assets/index-CeGuwmXB.js +55 -0
- package/dist/dashboard/favicon.ico +0 -0
- package/dist/dashboard/favicon.png +0 -0
- package/dist/dashboard/index.html +15 -0
- package/dist/dashboard-server.d.ts +16 -0
- package/dist/dashboard-server.d.ts.map +1 -1
- package/dist/dashboard-server.js +617 -40
- package/dist/dashboard-server.js.map +1 -1
- package/dist/docs-index.d.ts +50 -0
- package/dist/docs-index.d.ts.map +1 -0
- package/dist/docs-index.js +357 -0
- package/dist/docs-index.js.map +1 -0
- package/dist/fact-extractor.d.ts +45 -0
- package/dist/fact-extractor.d.ts.map +1 -0
- package/dist/fact-extractor.js +165 -0
- package/dist/fact-extractor.js.map +1 -0
- package/dist/homaruscc.d.ts +14 -0
- package/dist/homaruscc.d.ts.map +1 -1
- package/dist/homaruscc.js +142 -2
- package/dist/homaruscc.js.map +1 -1
- package/dist/mcp-tools.d.ts.map +1 -1
- package/dist/mcp-tools.js +879 -0
- package/dist/mcp-tools.js.map +1 -1
- package/dist/plugin-loader.d.ts +41 -0
- package/dist/plugin-loader.d.ts.map +1 -0
- package/dist/plugin-loader.js +122 -0
- package/dist/plugin-loader.js.map +1 -0
- package/dist/plugins/needoh-tracker/amazon-check.d.ts +21 -0
- package/dist/plugins/needoh-tracker/amazon-check.d.ts.map +1 -0
- package/dist/plugins/needoh-tracker/amazon-check.js +130 -0
- package/dist/plugins/needoh-tracker/amazon-check.js.map +1 -0
- package/dist/plugins/needoh-tracker/index.d.ts +104 -0
- package/dist/plugins/needoh-tracker/index.d.ts.map +1 -0
- package/dist/plugins/needoh-tracker/index.js +448 -0
- package/dist/plugins/needoh-tracker/index.js.map +1 -0
- package/dist/plugins/needoh-tracker/store.d.ts +95 -0
- package/dist/plugins/needoh-tracker/store.d.ts.map +1 -0
- package/dist/plugins/needoh-tracker/store.js +267 -0
- package/dist/plugins/needoh-tracker/store.js.map +1 -0
- package/dist/plugins/needoh-tracker/target-api.d.ts +26 -0
- package/dist/plugins/needoh-tracker/target-api.d.ts.map +1 -0
- package/dist/plugins/needoh-tracker/target-api.js +120 -0
- package/dist/plugins/needoh-tracker/target-api.js.map +1 -0
- package/dist/plugins/record-collection/identifier.d.ts +58 -0
- package/dist/plugins/record-collection/identifier.d.ts.map +1 -0
- package/dist/plugins/record-collection/identifier.js +384 -0
- package/dist/plugins/record-collection/identifier.js.map +1 -0
- package/dist/plugins/record-collection/index.d.ts +399 -0
- package/dist/plugins/record-collection/index.d.ts.map +1 -0
- package/dist/plugins/record-collection/index.js +701 -0
- package/dist/plugins/record-collection/index.js.map +1 -0
- package/dist/plugins/record-collection/store.d.ts +83 -0
- package/dist/plugins/record-collection/store.d.ts.map +1 -0
- package/dist/plugins/record-collection/store.js +215 -0
- package/dist/plugins/record-collection/store.js.map +1 -0
- package/dist/record-identifier.d.ts +32 -0
- package/dist/record-identifier.d.ts.map +1 -0
- package/dist/record-identifier.js +199 -0
- package/dist/record-identifier.js.map +1 -0
- package/dist/record-store.d.ts +66 -0
- package/dist/record-store.d.ts.map +1 -0
- package/dist/record-store.js +185 -0
- package/dist/record-store.js.map +1 -0
- package/dist/sensor-bridge.d.ts +26 -0
- package/dist/sensor-bridge.d.ts.map +1 -0
- package/dist/sensor-bridge.js +94 -0
- package/dist/sensor-bridge.js.map +1 -0
- package/dist/session-extractor.d.ts +36 -0
- package/dist/session-extractor.d.ts.map +1 -0
- package/dist/session-extractor.js +290 -0
- package/dist/session-extractor.js.map +1 -0
- package/dist/spaces-manager.d.ts +115 -0
- package/dist/spaces-manager.d.ts.map +1 -0
- package/dist/spaces-manager.js +585 -0
- package/dist/spaces-manager.js.map +1 -0
- package/dist/telegram-adapter.d.ts +7 -0
- package/dist/telegram-adapter.d.ts.map +1 -1
- package/dist/telegram-adapter.js +112 -1
- package/dist/telegram-adapter.js.map +1 -1
- package/dist/telegram-command-handler.d.ts +27 -0
- package/dist/telegram-command-handler.d.ts.map +1 -0
- package/dist/telegram-command-handler.js +102 -0
- package/dist/telegram-command-handler.js.map +1 -0
- package/dist/timer-service.d.ts +7 -0
- package/dist/timer-service.d.ts.map +1 -1
- package/dist/timer-service.js +37 -1
- package/dist/timer-service.js.map +1 -1
- package/dist/tools/docs.d.ts +4 -0
- package/dist/tools/docs.d.ts.map +1 -0
- package/dist/tools/docs.js +114 -0
- package/dist/tools/docs.js.map +1 -0
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +11 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +5 -2
- 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
|
-
###
|
|
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
|
-
|
|
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
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
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/
|
|
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
|
-
|
|
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
|
*)
|
package/bin/nuke-claude
ADDED
|
@@ -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"
|