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.
- package/dist/agents-JIZXXASP.js +853 -0
- package/dist/app-3VWDSH5F.js +248 -0
- package/dist/audio-US2J627E.js +196 -0
- package/dist/audit-ZVTGE4L4.js +8 -0
- package/dist/call-AQZ3Z5SE.js +143 -0
- package/dist/chunk-5ND7JYY3.js +62 -0
- package/dist/chunk-6SRV2I2H.js +56 -0
- package/dist/{setup-AO3MW46W.js → chunk-A7ZLQUOX.js} +93 -16
- package/dist/chunk-E5UYN3W7.js +105 -0
- package/dist/chunk-HAHJD3QH.js +147 -0
- package/dist/{init-DLFEGD6O.js → chunk-KR7ISYZH.js} +328 -29
- package/dist/chunk-LTOM55UV.js +154 -0
- package/dist/chunk-PDX44BCA.js +11 -0
- package/dist/chunk-PPGYFMU5.js +67 -0
- package/dist/{chunk-7AGI43F5.js → chunk-WBMVBMWB.js} +4 -2
- package/dist/{context-FN5O5YBI.js → context-XNCG2M5Q.js} +2 -1
- package/dist/daemon-5KNSNFTD.js +208 -0
- package/dist/gateway-YLP66MCQ.js +2273 -0
- package/dist/hammerspoon/rex-call-watcher.lua +186 -0
- package/dist/index.js +309 -15
- package/dist/init-RDZFIBLA.js +30 -0
- package/dist/install-63JBDPRU.js +41 -0
- package/dist/{llm-YRORUH7E.js → llm-RALIPIMI.js} +2 -1
- package/dist/mcp_registry-DX4GGSP6.js +514 -0
- package/dist/migrate-GDO37TI5.js +87 -0
- package/dist/{optimize-UKMAGQQE.js → optimize-5TE5RKZV.js} +2 -1
- package/dist/paths-4SECM6E6.js +38 -0
- package/dist/preload-I3MYBVNU.js +78 -0
- package/dist/projects-V6TSLO7E.js +17 -0
- package/dist/{prune-2PPIVDXK.js → prune-B7F5B5OF.js} +2 -1
- package/dist/recategorize-YXYIMQLZ.js +155 -0
- package/dist/router-2JD34COX.js +12 -0
- package/dist/self-improve-YK7RCYF4.js +197 -0
- package/dist/setup-KNDTVFO6.js +8 -0
- package/dist/skills-AIWFY5NH.js +374 -0
- package/dist/voice-RITC3EVC.js +248 -0
- package/package.json +12 -3
- 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-
|
|
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-
|
|
460
|
+
const { optimize } = await import("./optimize-5TE5RKZV.js");
|
|
415
461
|
const applyFlag = process.argv.includes("--apply");
|
|
416
|
-
|
|
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-
|
|
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-
|
|
427
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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
|
+
};
|