rex-claude 4.0.0 → 6.0.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 (38) hide show
  1. package/dist/agents-JIZXXASP.js +853 -0
  2. package/dist/app-3VWDSH5F.js +248 -0
  3. package/dist/audio-US2J627E.js +196 -0
  4. package/dist/audit-ZVTGE4L4.js +8 -0
  5. package/dist/call-AQZ3Z5SE.js +143 -0
  6. package/dist/chunk-5ND7JYY3.js +62 -0
  7. package/dist/chunk-6SRV2I2H.js +56 -0
  8. package/dist/{setup-AO3MW46W.js → chunk-A7ZLQUOX.js} +93 -16
  9. package/dist/chunk-E5UYN3W7.js +105 -0
  10. package/dist/chunk-HAHJD3QH.js +147 -0
  11. package/dist/{init-DLFEGD6O.js → chunk-KR7ISYZH.js} +328 -29
  12. package/dist/chunk-LTOM55UV.js +154 -0
  13. package/dist/chunk-PDX44BCA.js +11 -0
  14. package/dist/chunk-PPGYFMU5.js +67 -0
  15. package/dist/{chunk-7AGI43F5.js → chunk-WBMVBMWB.js} +4 -2
  16. package/dist/{context-FN5O5YBI.js → context-XNCG2M5Q.js} +2 -1
  17. package/dist/daemon-5KNSNFTD.js +208 -0
  18. package/dist/gateway-YLP66MCQ.js +2273 -0
  19. package/dist/hammerspoon/rex-call-watcher.lua +186 -0
  20. package/dist/index.js +309 -15
  21. package/dist/init-RDZFIBLA.js +30 -0
  22. package/dist/install-63JBDPRU.js +41 -0
  23. package/dist/{llm-YRORUH7E.js → llm-RALIPIMI.js} +2 -1
  24. package/dist/mcp_registry-DX4GGSP6.js +514 -0
  25. package/dist/migrate-GDO37TI5.js +87 -0
  26. package/dist/{optimize-UKMAGQQE.js → optimize-5TE5RKZV.js} +2 -1
  27. package/dist/paths-4SECM6E6.js +38 -0
  28. package/dist/preload-I3MYBVNU.js +78 -0
  29. package/dist/projects-V6TSLO7E.js +17 -0
  30. package/dist/{prune-2PPIVDXK.js → prune-B7F5B5OF.js} +2 -1
  31. package/dist/recategorize-YXYIMQLZ.js +155 -0
  32. package/dist/router-2JD34COX.js +12 -0
  33. package/dist/self-improve-YK7RCYF4.js +197 -0
  34. package/dist/setup-KNDTVFO6.js +8 -0
  35. package/dist/skills-AIWFY5NH.js +374 -0
  36. package/dist/voice-RITC3EVC.js +248 -0
  37. package/package.json +12 -3
  38. package/dist/gateway-EKMU5D7J.js +0 -784
@@ -0,0 +1,186 @@
1
+ -- REX Call Watcher
2
+ -- Detects known voice apps (Discord/Zoom/Meet/Slack/Teams/WhatsApp/FaceTime)
3
+ -- and writes a machine-readable state for local automations.
4
+
5
+ local M = {}
6
+
7
+ local HOME = os.getenv("HOME") or ""
8
+ local STATE_PATH = HOME .. "/.rex-memory/runtime/call-state.json"
9
+ local EVENTS_PATH = HOME .. "/.rex-memory/runtime/call-events.jsonl"
10
+
11
+ local VOICE_APPS = {
12
+ ["Discord"] = true,
13
+ ["zoom.us"] = true,
14
+ ["Microsoft Teams"] = true,
15
+ ["Slack"] = true,
16
+ ["WhatsApp"] = true,
17
+ ["FaceTime"] = true,
18
+ ["Telegram"] = true,
19
+ }
20
+
21
+ local BROWSER_APPS = {
22
+ ["Google Chrome"] = true,
23
+ ["Arc"] = true,
24
+ ["Brave Browser"] = true,
25
+ ["Safari"] = true,
26
+ ["Microsoft Edge"] = true,
27
+ }
28
+
29
+ local BROWSER_KEYWORDS = {
30
+ "google meet",
31
+ " meet",
32
+ " huddle",
33
+ "slack call",
34
+ "discord",
35
+ "voice",
36
+ "call",
37
+ }
38
+
39
+ local watcher = nil
40
+ local heartbeat = nil
41
+
42
+ local current = {
43
+ active = false,
44
+ app = "",
45
+ reason = "",
46
+ title = "",
47
+ startedAt = 0,
48
+ updatedAt = 0,
49
+ }
50
+
51
+ local function ensureRuntimeDir()
52
+ os.execute('mkdir -p "' .. HOME .. '/.rex-memory/runtime"')
53
+ end
54
+
55
+ local function writeState(state)
56
+ ensureRuntimeDir()
57
+ local f = io.open(STATE_PATH, "w")
58
+ if not f then return end
59
+ f:write(hs.json.encode(state))
60
+ f:close()
61
+ end
62
+
63
+ local function appendEvent(ev)
64
+ ensureRuntimeDir()
65
+ local f = io.open(EVENTS_PATH, "a")
66
+ if not f then return end
67
+ f:write(hs.json.encode(ev) .. "\n")
68
+ f:close()
69
+ end
70
+
71
+ local function titleLooksLikeCall(title)
72
+ if not title then return false end
73
+ local t = string.lower(title)
74
+ for _, kw in ipairs(BROWSER_KEYWORDS) do
75
+ if string.find(t, kw, 1, true) then
76
+ return true
77
+ end
78
+ end
79
+ return false
80
+ end
81
+
82
+ local function detectCall(appName)
83
+ if VOICE_APPS[appName] then
84
+ return true, "voice_app"
85
+ end
86
+
87
+ if BROWSER_APPS[appName] then
88
+ local win = hs.window.frontmostWindow()
89
+ local title = win and win:title() or ""
90
+ if titleLooksLikeCall(title) then
91
+ return true, "browser_title", title
92
+ end
93
+ end
94
+
95
+ return false, "", ""
96
+ end
97
+
98
+ local function updateFromFrontmost()
99
+ local app = hs.application.frontmostApplication()
100
+ local appName = app and app:name() or ""
101
+ local now = os.time()
102
+ local active, reason, title = detectCall(appName)
103
+
104
+ if active and not current.active then
105
+ current.active = true
106
+ current.app = appName
107
+ current.reason = reason
108
+ current.title = title or ""
109
+ current.startedAt = now
110
+ current.updatedAt = now
111
+
112
+ appendEvent({
113
+ type = "call_start",
114
+ app = current.app,
115
+ reason = current.reason,
116
+ title = current.title,
117
+ timestamp = now,
118
+ iso = os.date("!%Y-%m-%dT%H:%M:%SZ", now),
119
+ })
120
+ elseif active and current.active then
121
+ current.updatedAt = now
122
+ if current.app ~= appName then
123
+ current.app = appName
124
+ current.reason = reason
125
+ current.title = title or ""
126
+ end
127
+ elseif (not active) and current.active then
128
+ local duration = math.max(0, now - (current.startedAt or now))
129
+ appendEvent({
130
+ type = "call_end",
131
+ app = current.app,
132
+ reason = current.reason,
133
+ title = current.title,
134
+ duration = duration,
135
+ startedAt = current.startedAt,
136
+ endedAt = now,
137
+ iso = os.date("!%Y-%m-%dT%H:%M:%SZ", now),
138
+ })
139
+
140
+ current.active = false
141
+ current.app = ""
142
+ current.reason = ""
143
+ current.title = ""
144
+ current.startedAt = 0
145
+ current.updatedAt = now
146
+ end
147
+
148
+ writeState({
149
+ active = current.active,
150
+ app = current.app,
151
+ reason = current.reason,
152
+ title = current.title,
153
+ startedAt = current.startedAt,
154
+ updatedAt = current.updatedAt,
155
+ iso = os.date("!%Y-%m-%dT%H:%M:%SZ", now),
156
+ })
157
+ end
158
+
159
+ function M.start()
160
+ if watcher then return end
161
+
162
+ watcher = hs.application.watcher.new(function(_, eventType, _)
163
+ if eventType == hs.application.watcher.activated then
164
+ updateFromFrontmost()
165
+ end
166
+ end)
167
+ watcher:start()
168
+
169
+ -- Keep state fresh even if app title changes without app switch (browser tabs).
170
+ heartbeat = hs.timer.doEvery(5, updateFromFrontmost)
171
+ updateFromFrontmost()
172
+ hs.printf("REX Call Watcher started")
173
+ end
174
+
175
+ function M.stop()
176
+ if watcher then
177
+ watcher:stop()
178
+ watcher = nil
179
+ end
180
+ if heartbeat then
181
+ heartbeat:stop()
182
+ heartbeat = nil
183
+ end
184
+ end
185
+
186
+ return M
package/dist/index.js CHANGED
@@ -1,4 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ configureLogger,
4
+ createLogger
5
+ } from "./chunk-5ND7JYY3.js";
6
+ import {
7
+ DAEMON_LOG_PATH
8
+ } from "./chunk-6SRV2I2H.js";
9
+ import "./chunk-PDX44BCA.js";
2
10
 
3
11
  // ../core/dist/index.js
4
12
  import { homedir } from "os";
@@ -286,7 +294,7 @@ async function runAllChecks(claudeDir) {
286
294
  }
287
295
 
288
296
  // src/index.ts
289
- import { existsSync } from "fs";
297
+ import { existsSync, readFileSync } from "fs";
290
298
  import { join as join10 } from "path";
291
299
  var COLORS = {
292
300
  reset: "\x1B[0m",
@@ -354,8 +362,41 @@ ${thinLine}
354
362
  }
355
363
  async function main() {
356
364
  const command = process.argv[2] ?? "help";
365
+ const verbose = process.argv.includes("--verbose");
366
+ if (verbose) configureLogger({ level: "debug" });
367
+ const log = createLogger("cli");
357
368
  switch (command) {
358
369
  case "doctor": {
370
+ const fixMode = process.argv.includes("--fix");
371
+ if (fixMode) {
372
+ log.info("Doctor --fix started");
373
+ console.log(`
374
+ ${COLORS.bold}REX Doctor \u2014 Auto-fix mode${COLORS.reset}
375
+ `);
376
+ const { ensureRexDirs } = await import("./paths-4SECM6E6.js");
377
+ ensureRexDirs();
378
+ log.info("Directory structure ensured");
379
+ console.log(` ${COLORS.green}\u2713${COLORS.reset} Directory structure ensured`);
380
+ try {
381
+ const { migrate } = await import("./migrate-GDO37TI5.js");
382
+ await migrate();
383
+ } catch (e) {
384
+ console.log(` ${COLORS.yellow}!${COLORS.reset} Migration: ${e.message?.slice(0, 100)}`);
385
+ }
386
+ const { execSync: execSync3 } = await import("child_process");
387
+ try {
388
+ execSync3("rex ingest", { stdio: "inherit", timeout: 12e4 });
389
+ } catch {
390
+ }
391
+ try {
392
+ execSync3("rex recategorize --batch=50", { stdio: "inherit", timeout: 18e4 });
393
+ } catch {
394
+ }
395
+ log.info("Auto-fix complete, running doctor");
396
+ console.log(`
397
+ ${COLORS.green}Auto-fix complete.${COLORS.reset} Running doctor...
398
+ `);
399
+ }
359
400
  const report = await runAllChecks();
360
401
  console.log(formatReport(report));
361
402
  process.exit(report.status === "broken" ? 1 : 0);
@@ -371,10 +412,15 @@ async function main() {
371
412
  break;
372
413
  }
373
414
  case "init": {
374
- const { init } = await import("./init-DLFEGD6O.js");
415
+ const { init } = await import("./init-RDZFIBLA.js");
375
416
  await init();
376
417
  break;
377
418
  }
419
+ case "install": {
420
+ const { install } = await import("./install-63JBDPRU.js");
421
+ await install();
422
+ break;
423
+ }
378
424
  case "ingest": {
379
425
  try {
380
426
  const { execSync: execSync3 } = await import("child_process");
@@ -411,20 +457,36 @@ async function main() {
411
457
  break;
412
458
  }
413
459
  case "optimize": {
414
- const { optimize } = await import("./optimize-UKMAGQQE.js");
460
+ const { optimize } = await import("./optimize-5TE5RKZV.js");
415
461
  const applyFlag = process.argv.includes("--apply");
416
- await optimize(applyFlag);
462
+ const modelIdx = process.argv.indexOf("--model");
463
+ const modelFlag = modelIdx !== -1 ? process.argv[modelIdx + 1] : void 0;
464
+ await optimize(applyFlag, modelFlag);
417
465
  break;
418
466
  }
419
467
  case "prune": {
420
- const { prune } = await import("./prune-2PPIVDXK.js");
468
+ const { prune } = await import("./prune-B7F5B5OF.js");
421
469
  const statsFlag = process.argv.includes("--stats");
422
470
  await prune(statsFlag);
423
471
  break;
424
472
  }
425
473
  case "setup": {
426
- const { setup } = await import("./setup-AO3MW46W.js");
427
- await setup();
474
+ const { setup } = await import("./setup-KNDTVFO6.js");
475
+ const nonInteractive = process.argv.includes("--yes") || process.argv.includes("--non-interactive");
476
+ const skipTelegram = process.argv.includes("--skip-telegram");
477
+ await setup({ nonInteractive, skipTelegram, autoInstallDeps: nonInteractive });
478
+ break;
479
+ }
480
+ case "audit": {
481
+ const { audit } = await import("./audit-ZVTGE4L4.js");
482
+ const json = process.argv.includes("--json");
483
+ const strict = process.argv.includes("--strict");
484
+ await audit({ json, strict });
485
+ break;
486
+ }
487
+ case "migrate": {
488
+ const { migrate } = await import("./migrate-GDO37TI5.js");
489
+ await migrate();
428
490
  break;
429
491
  }
430
492
  case "llm": {
@@ -433,35 +495,203 @@ async function main() {
433
495
  console.error("Usage: rex llm <prompt>");
434
496
  process.exit(1);
435
497
  }
436
- const { llm } = await import("./llm-YRORUH7E.js");
498
+ const { llm } = await import("./llm-RALIPIMI.js");
437
499
  const result = await llm(prompt);
438
500
  console.log(result);
439
501
  break;
440
502
  }
441
503
  case "context": {
442
504
  const targetPath = process.argv[3] || process.cwd();
443
- const { context } = await import("./context-FN5O5YBI.js");
505
+ const { context } = await import("./context-XNCG2M5Q.js");
444
506
  await context(targetPath);
445
507
  break;
446
508
  }
447
509
  case "gateway": {
448
- const { gateway } = await import("./gateway-EKMU5D7J.js");
510
+ const { gateway } = await import("./gateway-YLP66MCQ.js");
449
511
  await gateway();
450
512
  break;
451
513
  }
514
+ case "app": {
515
+ const { app } = await import("./app-3VWDSH5F.js");
516
+ await app(process.argv.slice(3));
517
+ break;
518
+ }
519
+ case "update": {
520
+ const { app } = await import("./app-3VWDSH5F.js");
521
+ await app(["update", ...process.argv.slice(3)]);
522
+ break;
523
+ }
524
+ case "agents": {
525
+ const { agents } = await import("./agents-JIZXXASP.js");
526
+ await agents(process.argv.slice(3));
527
+ break;
528
+ }
529
+ case "skills": {
530
+ const { skills } = await import("./skills-AIWFY5NH.js");
531
+ await skills(process.argv.slice(3));
532
+ break;
533
+ }
534
+ case "mcp": {
535
+ const { mcpRegistry } = await import("./mcp_registry-DX4GGSP6.js");
536
+ await mcpRegistry(process.argv.slice(3));
537
+ break;
538
+ }
539
+ case "audio": {
540
+ const { audio } = await import("./audio-US2J627E.js");
541
+ await audio(process.argv.slice(3));
542
+ break;
543
+ }
544
+ case "call": {
545
+ const { call } = await import("./call-AQZ3Z5SE.js");
546
+ await call(process.argv.slice(3));
547
+ break;
548
+ }
549
+ case "voice": {
550
+ const { voice } = await import("./voice-RITC3EVC.js");
551
+ await voice(process.argv.slice(3));
552
+ break;
553
+ }
452
554
  case "startup": {
453
- const { installStartup } = await import("./init-DLFEGD6O.js");
555
+ const { installStartup } = await import("./init-RDZFIBLA.js");
454
556
  installStartup();
455
557
  break;
456
558
  }
457
559
  case "startup-remove": {
458
- const { uninstallStartup } = await import("./init-DLFEGD6O.js");
560
+ const { uninstallStartup } = await import("./init-RDZFIBLA.js");
459
561
  uninstallStartup();
460
562
  break;
461
563
  }
564
+ case "categorize": {
565
+ try {
566
+ const memDir = findMemoryPackage();
567
+ if (!memDir) {
568
+ console.log(`Memory package not found. Run from the REX monorepo.`);
569
+ process.exit(1);
570
+ }
571
+ const { execSync: execSync3 } = await import("child_process");
572
+ const modelArg = process.argv.find((a) => a.startsWith("--model=")) ?? (process.argv.includes("--model") ? `--model=${process.argv[process.argv.indexOf("--model") + 1]}` : "");
573
+ const batchArg = process.argv.find((a) => a.startsWith("--batch=")) ?? (process.argv.includes("--batch") ? `--batch=${process.argv[process.argv.indexOf("--batch") + 1]}` : "");
574
+ execSync3(`npx tsx src/categorize.ts ${modelArg} ${batchArg}`.trim(), { cwd: memDir, stdio: "inherit" });
575
+ } catch {
576
+ process.exit(1);
577
+ }
578
+ break;
579
+ }
580
+ case "list-memories": {
581
+ try {
582
+ const memDir = findMemoryPackage();
583
+ if (!memDir) {
584
+ console.log(`Memory package not found.`);
585
+ process.exit(1);
586
+ }
587
+ const { execSync: execSync3 } = await import("child_process");
588
+ const extraArgs = process.argv.slice(3).join(" ");
589
+ execSync3(`npx tsx src/categorize.ts list ${extraArgs}`.trim(), { cwd: memDir, stdio: "inherit" });
590
+ } catch {
591
+ process.exit(1);
592
+ }
593
+ break;
594
+ }
595
+ case "consolidate": {
596
+ try {
597
+ const memDir = findMemoryPackage();
598
+ if (!memDir) {
599
+ console.log(`Memory package not found. Run from the REX monorepo.`);
600
+ process.exit(1);
601
+ }
602
+ const { execSync: execSync3 } = await import("child_process");
603
+ const thresholdArg = process.argv.find((a) => a.startsWith("--threshold=")) ?? "";
604
+ const limitArg = process.argv.find((a) => a.startsWith("--limit=")) ?? "";
605
+ const modelArg = process.argv.find((a) => a.startsWith("--model=")) ?? "";
606
+ const dryRunArg = process.argv.includes("--dry-run") ? "--dry-run" : "";
607
+ execSync3(`npx tsx src/categorize.ts consolidate ${thresholdArg} ${limitArg} ${modelArg} ${dryRunArg}`.trim(), { cwd: memDir, stdio: "inherit" });
608
+ } catch {
609
+ process.exit(1);
610
+ }
611
+ break;
612
+ }
613
+ case "models": {
614
+ const { showModelRouter } = await import("./router-2JD34COX.js");
615
+ await showModelRouter();
616
+ break;
617
+ }
618
+ case "projects": {
619
+ const { scanProjects, saveProjectIndex } = await import("./projects-V6TSLO7E.js");
620
+ console.log(`${COLORS.cyan}Scanning projects...${COLORS.reset}`);
621
+ const projects = scanProjects();
622
+ saveProjectIndex(projects);
623
+ console.log(`
624
+ ${COLORS.bold}${projects.length} projects found${COLORS.reset}
625
+ `);
626
+ for (const p of projects) {
627
+ const dot = p.status === "active" ? `${COLORS.green}\u25CF${COLORS.reset}` : `${COLORS.dim}\u25CB${COLORS.reset}`;
628
+ console.log(` ${dot} ${COLORS.bold}${p.name.padEnd(20)}${COLORS.reset} ${p.stack.join(", ").padEnd(30)} ${COLORS.dim}${p.lastActive}${COLORS.reset}`);
629
+ }
630
+ break;
631
+ }
632
+ case "recategorize": {
633
+ const { recategorize } = await import("./recategorize-YXYIMQLZ.js");
634
+ const batchArg = process.argv.find((a) => a.startsWith("--batch="));
635
+ const batch = batchArg ? parseInt(batchArg.split("=")[1]) : 50;
636
+ const dryRun = process.argv.includes("--dry-run");
637
+ await recategorize({ batch, dryRun });
638
+ break;
639
+ }
640
+ case "preload": {
641
+ const { preload } = await import("./preload-I3MYBVNU.js");
642
+ const cwd = process.argv[3] || process.cwd();
643
+ const context = await preload(cwd);
644
+ if (context) console.log(context);
645
+ break;
646
+ }
647
+ case "self-review": {
648
+ const { selfReview } = await import("./self-improve-YK7RCYF4.js");
649
+ await selfReview();
650
+ break;
651
+ }
652
+ case "promote-rule": {
653
+ const { promoteRule } = await import("./self-improve-YK7RCYF4.js");
654
+ const idx = parseInt(process.argv[3]);
655
+ if (!idx) {
656
+ console.log("Usage: rex promote-rule <index>");
657
+ process.exit(1);
658
+ }
659
+ const ok = await promoteRule(idx);
660
+ console.log(ok ? `${COLORS.green}Rule promoted to ~/.claude/rules/${COLORS.reset}` : `${COLORS.red}Failed \u2014 invalid index or no suggested rule${COLORS.reset}`);
661
+ break;
662
+ }
663
+ case "daemon": {
664
+ const { daemon } = await import("./daemon-5KNSNFTD.js");
665
+ await daemon();
666
+ break;
667
+ }
668
+ case "logs": {
669
+ const lines = process.argv.find((a) => a.startsWith("--lines="));
670
+ const n = lines ? parseInt(lines.split("=")[1]) : 50;
671
+ const follow = process.argv.includes("--follow") || process.argv.includes("-f");
672
+ if (!existsSync(DAEMON_LOG_PATH)) {
673
+ console.log(`${COLORS.dim}No log file found at ${DAEMON_LOG_PATH}${COLORS.reset}`);
674
+ break;
675
+ }
676
+ if (follow) {
677
+ const { execSync: execSyncLocal } = await import("child_process");
678
+ try {
679
+ execSyncLocal(`tail -f "${DAEMON_LOG_PATH}"`, { stdio: "inherit" });
680
+ } catch {
681
+ }
682
+ } else {
683
+ const content = readFileSync(DAEMON_LOG_PATH, "utf-8");
684
+ const logLines = content.split("\n").filter(Boolean);
685
+ const tail = logLines.slice(-n);
686
+ for (const line of tail) console.log(line);
687
+ console.log(`
688
+ ${COLORS.dim}Showing last ${tail.length} of ${logLines.length} lines. Use --follow/-f for live tail.${COLORS.reset}`);
689
+ }
690
+ break;
691
+ }
462
692
  case "--version":
463
693
  case "-v":
464
- console.log("rex-claude v4.0.0");
694
+ console.log("rex-claude v6.0.0");
465
695
  break;
466
696
  case "help":
467
697
  default:
@@ -469,33 +699,96 @@ async function main() {
469
699
  ${COLORS.bold}REX${COLORS.reset} \u2014 Claude Code sous steroides
470
700
 
471
701
  ${COLORS.bold}Commands:${COLORS.reset}
702
+ rex install One-command setup (init + setup + audit)
472
703
  rex init Setup REX (guards, hooks, MCP, startup)
704
+ rex audit Run integration audit checks
473
705
  rex doctor Full health check (9 categories)
706
+ rex doctor --fix Auto-fix common issues then check
474
707
  rex status Quick one-line status
475
708
  rex startup Install LaunchAgent (auto-start on login)
476
709
  rex startup-remove Remove LaunchAgent
477
710
 
478
711
  ${COLORS.bold}Memory (requires Ollama):${COLORS.reset}
712
+ rex migrate Migrate ~/.rex-memory/ to ~/.claude/rex/ hub
479
713
  rex ingest Sync session history to vector DB
480
714
  rex search <query> Semantic search across past sessions
715
+ rex categorize Classify uncategorized memories
716
+ rex consolidate Merge similar memories (cosine clustering)
717
+ rex recategorize Re-classify session memories with AI
481
718
  rex optimize Analyze CLAUDE.md with local LLM
482
719
  rex optimize --apply Apply optimizations (with backup)
483
720
  rex prune Cleanup old/duplicate memories
484
721
  rex prune --stats Show memory database stats
722
+ rex self-review Extract lessons, detect error patterns
723
+ rex promote-rule N Promote rule candidate to ~/.claude/rules/
485
724
 
486
725
  ${COLORS.bold}LLM & Context:${COLORS.reset}
487
- rex setup Install Ollama + models + Telegram gateway
726
+ rex setup Install Ollama + models + Telegram gateway (interactive)
727
+ rex setup --yes Non-interactive setup (auto-install deps, env-based Telegram)
488
728
  rex llm <prompt> Query local LLM directly
729
+ rex models Show task-aware model routing table
730
+ rex preload [path] Show pre-loaded context for a path
489
731
  rex context [path] Analyze project, recommend MCP/skills
732
+ rex projects Scan and index all dev projects
733
+
734
+ ${COLORS.bold}Background:${COLORS.reset}
735
+ rex daemon Start persistent background daemon
736
+ rex logs Show recent daemon/CLI logs (--lines=N, --follow/-f)
490
737
 
491
738
  ${COLORS.bold}Telegram Gateway:${COLORS.reset}
492
739
  rex gateway Start Telegram bot (long-polling, interactive)
493
740
 
741
+ ${COLORS.bold}App:${COLORS.reset}
742
+ rex app update [--debug|--release] [--no-launch]
743
+ Build + install + relaunch app from current repo
744
+ rex app info Show installed app path + source repo/commit
745
+ rex app open Open installed app
746
+ rex update Alias for: rex app update
747
+
748
+ ${COLORS.bold}Autonomous Agents:${COLORS.reset}
749
+ rex agents profiles List built-in agent profiles
750
+ rex agents create <profile> Create agent (read/analysis/code-review/advanced/ultimate)
751
+ rex agents run <id> Start autonomous loop (daemon)
752
+ rex agents run <id> --once Run one cycle only
753
+ rex agents stop <id> Stop running agent
754
+ rex agents status [id] Show status
755
+ rex agents logs <id> Tail logs
756
+ rex agents chat <message> Chat with orchestrator
757
+ rex agents team [name] List teams / team members
758
+
759
+ ${COLORS.bold}Skills:${COLORS.reset}
760
+ rex skills list List installed skills
761
+ rex skills show <name> Show skill content
762
+ rex skills add <name> Create a new skill
763
+ rex skills delete <name> Remove a skill
764
+
765
+ ${COLORS.bold}MCP Registry:${COLORS.reset}
766
+ rex mcp list List MCP servers
767
+ rex mcp add <name> ... Add stdio MCP server
768
+ rex mcp add-url <name> <url> Add remote MCP server (sse/http)
769
+ rex mcp check <id> Check MCP connectivity
770
+ rex mcp discover <id|name> List tools exposed by an MCP server
771
+ rex mcp search <query> Search MCP marketplace cache
772
+ rex mcp install <name> Install MCP server from marketplace
773
+ rex mcp sync-claude Sync enabled stdio servers to ~/.claude/settings.json
774
+
775
+ ${COLORS.bold}Voice & Calls:${COLORS.reset}
776
+ rex call status Current call detection status (Hammerspoon)
777
+ rex call events --tail 20 Recent call start/end events
778
+ rex call watch Auto start/stop audio logger from call events
779
+ rex voice status Voice pipeline status (whisper + optimize)
780
+ rex voice set-optimize on Enable post-transcript optimize
781
+ rex voice transcribe Transcribe latest WAV recording
782
+ rex audio status Audio logger status
783
+ rex audio start Start audio capture (ffmpeg avfoundation)
784
+ rex audio stop Stop audio capture
785
+ rex audio list List saved recordings
786
+
494
787
  ${COLORS.bold}Info:${COLORS.reset}
495
788
  rex help Show this help
496
789
  rex --version Show version
497
790
 
498
- ${COLORS.dim}After install: rex init && rex setup \u2014 everything else is automatic.${COLORS.reset}
791
+ ${COLORS.dim}After install: rex install \u2014 everything else is automatic.${COLORS.reset}
499
792
  `);
500
793
  }
501
794
  }
@@ -503,6 +796,7 @@ function findMemoryPackage() {
503
796
  const thisDir = new URL(".", import.meta.url).pathname;
504
797
  const candidates = [
505
798
  join10(thisDir, "..", "..", "memory"),
799
+ join10(process.env.HOME || "~", "Documents", "Developer", "keiy", "rex", "packages", "memory"),
506
800
  join10(process.env.HOME || "~", ".rex-memory")
507
801
  ];
508
802
  for (const c of candidates) {
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ init,
4
+ installApp,
5
+ installCallWatchAgent,
6
+ installDaemonAgent,
7
+ installGatewayAgent,
8
+ installHammerspoonCallWatcher,
9
+ installIngestAgent,
10
+ installStartup,
11
+ uninstallCallWatchAgent,
12
+ uninstallGatewayAgent,
13
+ uninstallIngestAgent,
14
+ uninstallStartup
15
+ } from "./chunk-KR7ISYZH.js";
16
+ import "./chunk-PDX44BCA.js";
17
+ export {
18
+ init,
19
+ installApp,
20
+ installCallWatchAgent,
21
+ installDaemonAgent,
22
+ installGatewayAgent,
23
+ installHammerspoonCallWatcher,
24
+ installIngestAgent,
25
+ installStartup,
26
+ uninstallCallWatchAgent,
27
+ uninstallGatewayAgent,
28
+ uninstallIngestAgent,
29
+ uninstallStartup
30
+ };
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ init
4
+ } from "./chunk-KR7ISYZH.js";
5
+ import {
6
+ setup
7
+ } from "./chunk-A7ZLQUOX.js";
8
+ import {
9
+ audit
10
+ } from "./chunk-HAHJD3QH.js";
11
+ import "./chunk-PDX44BCA.js";
12
+
13
+ // src/install.ts
14
+ var COLORS = {
15
+ reset: "\x1B[0m",
16
+ green: "\x1B[32m",
17
+ bold: "\x1B[1m",
18
+ dim: "\x1B[2m"
19
+ };
20
+ async function install() {
21
+ const line = "\u2550".repeat(45);
22
+ console.log(`
23
+ ${line}`);
24
+ console.log(`${COLORS.bold} REX INSTALL \u2014 One Command${COLORS.reset}`);
25
+ console.log(`${line}
26
+ `);
27
+ await init();
28
+ await setup({
29
+ nonInteractive: true,
30
+ autoInstallDeps: true,
31
+ skipTelegram: process.env.REX_SKIP_TELEGRAM === "1"
32
+ });
33
+ console.log(`
34
+ ${COLORS.dim}Running post-install audit...${COLORS.reset}`);
35
+ await audit();
36
+ console.log(`
37
+ ${COLORS.green}${COLORS.bold}REX install complete.${COLORS.reset}`);
38
+ }
39
+ export {
40
+ install
41
+ };