@appchy/jarvis 0.1.109 → 0.1.110
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/bin.js +132 -142
- package/dist/bin.js.map +1 -1
- package/package.json +4 -4
package/dist/bin.js
CHANGED
|
@@ -1387,10 +1387,78 @@ async function ensureGraphify(options = {}) {
|
|
|
1387
1387
|
);
|
|
1388
1388
|
}
|
|
1389
1389
|
|
|
1390
|
+
// src/graph/hook.ts
|
|
1391
|
+
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync, chmodSync } from "fs";
|
|
1392
|
+
import path7 from "path";
|
|
1393
|
+
var SIGNATURE = "# managed by jarvis";
|
|
1394
|
+
var SCRIPT = `#!/bin/sh
|
|
1395
|
+
${SIGNATURE} \u2014 keeps this repo's map current, so what an agent plans against is what is here.
|
|
1396
|
+
# Detached and silenced: git waits for a hook's output streams to close, so a build left on stdout
|
|
1397
|
+
# would hold up every commit by the length of a build. Never fails a commit.
|
|
1398
|
+
#
|
|
1399
|
+
# Run at the lowest priority the machine offers. A code commit still costs a real extract, and one
|
|
1400
|
+
# arriving at normal priority the instant you commit is felt as the machine going away for half a
|
|
1401
|
+
# minute \u2014 which is how a background job becomes something people turn off. Borrowed from the
|
|
1402
|
+
# docdoc-era hook in crispy, which had this right first.
|
|
1403
|
+
command -v jarvis >/dev/null 2>&1 || exit 0
|
|
1404
|
+
NICE=""
|
|
1405
|
+
command -v nice >/dev/null 2>&1 && NICE="nice -n 19"
|
|
1406
|
+
command -v taskpolicy >/dev/null 2>&1 && NICE="taskpolicy -b $NICE"
|
|
1407
|
+
( $NICE jarvis build graph >/dev/null 2>&1 & ) >/dev/null 2>&1
|
|
1408
|
+
exit 0
|
|
1409
|
+
`;
|
|
1410
|
+
function findRepoRoot(from) {
|
|
1411
|
+
let dir = path7.resolve(from);
|
|
1412
|
+
for (; ; ) {
|
|
1413
|
+
if (existsSync(path7.join(dir, ".git"))) return dir;
|
|
1414
|
+
const parent = path7.dirname(dir);
|
|
1415
|
+
if (parent === dir) return null;
|
|
1416
|
+
dir = parent;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
function installCommitHook(repoRoot) {
|
|
1420
|
+
const git4 = path7.join(repoRoot, ".git");
|
|
1421
|
+
const dir = path7.join(git4, "hooks");
|
|
1422
|
+
const file = path7.join(dir, "post-commit");
|
|
1423
|
+
if (!existsSync(git4)) return { installed: false, reason: "not-a-repo" };
|
|
1424
|
+
if (!statSync(git4).isDirectory()) return { installed: false, reason: "worktree" };
|
|
1425
|
+
if (!existsSync(path7.join(git4, "HEAD"))) return { installed: false, reason: "not-a-repo" };
|
|
1426
|
+
if (existsSync(file)) {
|
|
1427
|
+
try {
|
|
1428
|
+
if (!readFileSync(file, "utf8").includes(SIGNATURE))
|
|
1429
|
+
return { installed: false, reason: "foreign-hook", path: file };
|
|
1430
|
+
} catch {
|
|
1431
|
+
return { installed: false, reason: "unwritable", path: file };
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
try {
|
|
1435
|
+
mkdirSync(dir, { recursive: true });
|
|
1436
|
+
writeFileSync(file, SCRIPT, "utf8");
|
|
1437
|
+
chmodSync(file, 493);
|
|
1438
|
+
return { installed: true, path: file };
|
|
1439
|
+
} catch {
|
|
1440
|
+
return { installed: false, reason: "unwritable", path: file };
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
function describeCommitHook(outcome, repoRoot) {
|
|
1444
|
+
if (outcome.installed)
|
|
1445
|
+
return ` the map rebuilds itself on every commit here \u2713 (${path7.relative(repoRoot, outcome.path) || outcome.path})`;
|
|
1446
|
+
if (outcome.reason === "not-a-repo")
|
|
1447
|
+
return ` not a git repo, so there is no commit to rebuild on.
|
|
1448
|
+
Run this inside one, or rebuild by hand with 'jarvis build graph'.`;
|
|
1449
|
+
if (outcome.reason === "worktree")
|
|
1450
|
+
return ` this is a worktree or a submodule, and it shares the hooks of the checkout it
|
|
1451
|
+
was made from. Wire that one instead, or rebuild by hand with 'jarvis build graph'.`;
|
|
1452
|
+
if (outcome.reason === "foreign-hook")
|
|
1453
|
+
return ` a post-commit hook is already here and it is not ours \u2014 left untouched.
|
|
1454
|
+
Add this line to it to keep the map current: jarvis build graph >/dev/null 2>&1 &`;
|
|
1455
|
+
return ` could not write the hook \u2014 the map still builds, by hand, with 'jarvis build graph'.`;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1390
1458
|
// src/machine.ts
|
|
1391
1459
|
import crypto2 from "crypto";
|
|
1392
1460
|
import fs8 from "fs";
|
|
1393
|
-
import
|
|
1461
|
+
import path8 from "path";
|
|
1394
1462
|
var cached = null;
|
|
1395
1463
|
function getMachine() {
|
|
1396
1464
|
if (cached) return cached;
|
|
@@ -1405,7 +1473,7 @@ function getMachine() {
|
|
|
1405
1473
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1406
1474
|
schemaVersion: 1
|
|
1407
1475
|
};
|
|
1408
|
-
fs8.mkdirSync(
|
|
1476
|
+
fs8.mkdirSync(path8.dirname(file), { recursive: true });
|
|
1409
1477
|
fs8.writeFileSync(file, JSON.stringify(fresh, null, 2));
|
|
1410
1478
|
return cached = fresh;
|
|
1411
1479
|
}
|
|
@@ -1413,13 +1481,13 @@ function getMachine() {
|
|
|
1413
1481
|
// src/service.ts
|
|
1414
1482
|
import { execSync as execSync3, spawn } from "child_process";
|
|
1415
1483
|
import fs9 from "fs";
|
|
1416
|
-
import
|
|
1484
|
+
import path9 from "path";
|
|
1417
1485
|
import os4 from "os";
|
|
1418
1486
|
function serviceSuffix() {
|
|
1419
1487
|
const dir = getConfigDir();
|
|
1420
|
-
const base =
|
|
1488
|
+
const base = path9.join(os4.homedir(), ".jarvis");
|
|
1421
1489
|
if (dir === base) return "";
|
|
1422
|
-
const name = dir.startsWith(base +
|
|
1490
|
+
const name = dir.startsWith(base + path9.sep) ? dir.slice(base.length + 1) : path9.basename(dir);
|
|
1423
1491
|
return name.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
1424
1492
|
}
|
|
1425
1493
|
var SERVICE_SUFFIX = serviceSuffix();
|
|
@@ -1430,8 +1498,8 @@ function createServiceManager() {
|
|
|
1430
1498
|
return new FallbackService();
|
|
1431
1499
|
}
|
|
1432
1500
|
var PLIST_LABEL = `com.appchy.jarvis${SERVICE_SUFFIX ? `.${SERVICE_SUFFIX}` : ""}`;
|
|
1433
|
-
var PLIST_DIR =
|
|
1434
|
-
var PLIST_PATH =
|
|
1501
|
+
var PLIST_DIR = path9.join(os4.homedir(), "Library", "LaunchAgents");
|
|
1502
|
+
var PLIST_PATH = path9.join(PLIST_DIR, `${PLIST_LABEL}.plist`);
|
|
1435
1503
|
function escapeXml(s) {
|
|
1436
1504
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1437
1505
|
}
|
|
@@ -1585,7 +1653,7 @@ ${Object.entries(opts.env ?? {}).map(([k, v]) => ` <key>${escapeXml(k)}</key>
|
|
|
1585
1653
|
</plist>
|
|
1586
1654
|
`;
|
|
1587
1655
|
fs9.mkdirSync(PLIST_DIR, { recursive: true });
|
|
1588
|
-
fs9.mkdirSync(
|
|
1656
|
+
fs9.mkdirSync(path9.dirname(logFile), { recursive: true });
|
|
1589
1657
|
unloadAgent();
|
|
1590
1658
|
fs9.writeFileSync(PLIST_PATH, plist);
|
|
1591
1659
|
loadAgent();
|
|
@@ -1687,7 +1755,7 @@ var WindowsService = class {
|
|
|
1687
1755
|
</Task>
|
|
1688
1756
|
`;
|
|
1689
1757
|
const tmpDir = os4.tmpdir();
|
|
1690
|
-
const tmpFile =
|
|
1758
|
+
const tmpFile = path9.join(tmpDir, `jarvis-task-${Date.now()}.xml`);
|
|
1691
1759
|
fs9.writeFileSync(tmpFile, xml, { encoding: "utf-16le" });
|
|
1692
1760
|
try {
|
|
1693
1761
|
execSync3(`schtasks /Create /TN "${TASK_NAME}" /XML "${tmpFile}" /F`, {
|
|
@@ -1733,9 +1801,9 @@ var WindowsService = class {
|
|
|
1733
1801
|
}
|
|
1734
1802
|
}
|
|
1735
1803
|
};
|
|
1736
|
-
var SYSTEMD_DIR =
|
|
1804
|
+
var SYSTEMD_DIR = path9.join(os4.homedir(), ".config", "systemd", "user");
|
|
1737
1805
|
var UNIT_NAME = `jarvis${SERVICE_SUFFIX ? `-${SERVICE_SUFFIX}` : ""}.service`;
|
|
1738
|
-
var UNIT_PATH =
|
|
1806
|
+
var UNIT_PATH = path9.join(SYSTEMD_DIR, UNIT_NAME);
|
|
1739
1807
|
var LinuxService = class {
|
|
1740
1808
|
install(opts) {
|
|
1741
1809
|
const args = [opts.entryPath, "start", "--foreground", "--workspace", opts.workspacePath];
|
|
@@ -1764,7 +1832,7 @@ StandardError=append:${logFile}
|
|
|
1764
1832
|
WantedBy=default.target
|
|
1765
1833
|
`;
|
|
1766
1834
|
fs9.mkdirSync(SYSTEMD_DIR, { recursive: true });
|
|
1767
|
-
fs9.mkdirSync(
|
|
1835
|
+
fs9.mkdirSync(path9.dirname(logFile), { recursive: true });
|
|
1768
1836
|
if (this.isInstalled()) {
|
|
1769
1837
|
try {
|
|
1770
1838
|
execSync3(`systemctl --user stop ${UNIT_NAME}`, { stdio: "ignore" });
|
|
@@ -1844,9 +1912,9 @@ WantedBy=default.target
|
|
|
1844
1912
|
};
|
|
1845
1913
|
var FallbackService = class {
|
|
1846
1914
|
baseDir = getJarvisDir();
|
|
1847
|
-
pidFile =
|
|
1848
|
-
logFile =
|
|
1849
|
-
markerFile =
|
|
1915
|
+
pidFile = path9.join(this.baseDir, "agent.pid");
|
|
1916
|
+
logFile = path9.join(this.baseDir, "agent.log");
|
|
1917
|
+
markerFile = path9.join(this.baseDir, "service-installed");
|
|
1850
1918
|
install(opts) {
|
|
1851
1919
|
fs9.mkdirSync(this.baseDir, { recursive: true });
|
|
1852
1920
|
this.stop();
|
|
@@ -1921,11 +1989,11 @@ var FallbackService = class {
|
|
|
1921
1989
|
};
|
|
1922
1990
|
|
|
1923
1991
|
// src/hooks/install.ts
|
|
1924
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs";
|
|
1992
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, realpathSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1925
1993
|
import os5 from "os";
|
|
1926
|
-
import
|
|
1927
|
-
var SETTINGS_DIR =
|
|
1928
|
-
var SETTINGS_FILE =
|
|
1994
|
+
import path10 from "path";
|
|
1995
|
+
var SETTINGS_DIR = path10.join(os5.homedir(), ".claude");
|
|
1996
|
+
var SETTINGS_FILE = path10.join(SETTINGS_DIR, "settings.json");
|
|
1929
1997
|
var HOOK_STEMS = [
|
|
1930
1998
|
"pre-tool-use",
|
|
1931
1999
|
"session-start",
|
|
@@ -1943,7 +2011,7 @@ function jarvisHooks() {
|
|
|
1943
2011
|
];
|
|
1944
2012
|
}
|
|
1945
2013
|
function isJarvisCommand(command) {
|
|
1946
|
-
const name =
|
|
2014
|
+
const name = path10.basename(command);
|
|
1947
2015
|
return HOOK_STEMS.some((stem) => name === `${stem}.mjs` || name === `${stem}.dev.mjs`);
|
|
1948
2016
|
}
|
|
1949
2017
|
function getCliRoot() {
|
|
@@ -1956,22 +2024,22 @@ function getCliRoot() {
|
|
|
1956
2024
|
entry = realpathSync(binPath);
|
|
1957
2025
|
} catch {
|
|
1958
2026
|
}
|
|
1959
|
-
return
|
|
2027
|
+
return path10.resolve(path10.dirname(entry), "..");
|
|
1960
2028
|
}
|
|
1961
2029
|
function resolveHooks() {
|
|
1962
2030
|
const cliRoot = getCliRoot();
|
|
1963
2031
|
return jarvisHooks().map((h) => ({
|
|
1964
2032
|
...h,
|
|
1965
|
-
binAbsPath:
|
|
2033
|
+
binAbsPath: path10.join(cliRoot, "bin", h.binBasename)
|
|
1966
2034
|
}));
|
|
1967
2035
|
}
|
|
1968
2036
|
function ownsClaudeCode() {
|
|
1969
|
-
return getConfigDir() ===
|
|
2037
|
+
return getConfigDir() === path10.join(os5.homedir(), ".jarvis");
|
|
1970
2038
|
}
|
|
1971
2039
|
function readSettings() {
|
|
1972
|
-
if (!
|
|
2040
|
+
if (!existsSync2(SETTINGS_FILE)) return {};
|
|
1973
2041
|
try {
|
|
1974
|
-
const raw =
|
|
2042
|
+
const raw = readFileSync2(SETTINGS_FILE, "utf-8");
|
|
1975
2043
|
return raw.trim() ? JSON.parse(raw) : {};
|
|
1976
2044
|
} catch (err) {
|
|
1977
2045
|
logger.sys.warn("[hooks.install] settings.json unreadable", {
|
|
@@ -1982,8 +2050,8 @@ function readSettings() {
|
|
|
1982
2050
|
}
|
|
1983
2051
|
function writeSettings(s) {
|
|
1984
2052
|
try {
|
|
1985
|
-
|
|
1986
|
-
|
|
2053
|
+
mkdirSync2(SETTINGS_DIR, { recursive: true });
|
|
2054
|
+
writeFileSync2(SETTINGS_FILE, JSON.stringify(s, null, 2) + "\n");
|
|
1987
2055
|
return true;
|
|
1988
2056
|
} catch (err) {
|
|
1989
2057
|
logger.sys.warn("[hooks.install] settings.json unwritable", {
|
|
@@ -2028,7 +2096,7 @@ function claudeCodeHooksState() {
|
|
|
2028
2096
|
return {
|
|
2029
2097
|
type: hook.type,
|
|
2030
2098
|
bin: hook.binAbsPath,
|
|
2031
|
-
exists:
|
|
2099
|
+
exists: existsSync2(hook.binAbsPath),
|
|
2032
2100
|
...command ? { command } : {}
|
|
2033
2101
|
};
|
|
2034
2102
|
});
|
|
@@ -2050,10 +2118,10 @@ function installClaudeCodeHooks() {
|
|
|
2050
2118
|
expected: resolved.map((h) => ({
|
|
2051
2119
|
type: h.type,
|
|
2052
2120
|
bin: h.binAbsPath,
|
|
2053
|
-
exists:
|
|
2121
|
+
exists: existsSync2(h.binAbsPath)
|
|
2054
2122
|
}))
|
|
2055
2123
|
});
|
|
2056
|
-
const missing = resolved.filter((h) => !
|
|
2124
|
+
const missing = resolved.filter((h) => !existsSync2(h.binAbsPath));
|
|
2057
2125
|
if (missing.length === resolved.length) {
|
|
2058
2126
|
logger.sys.warn("[hooks.install] no bin shims found, skipping", {
|
|
2059
2127
|
configDir: configDir2,
|
|
@@ -2064,7 +2132,7 @@ function installClaudeCodeHooks() {
|
|
|
2064
2132
|
let settings = readSettings();
|
|
2065
2133
|
const installed = [];
|
|
2066
2134
|
for (const hook of resolved) {
|
|
2067
|
-
if (!
|
|
2135
|
+
if (!existsSync2(hook.binAbsPath)) {
|
|
2068
2136
|
logger.sys.warn("[hooks.install] bin shim missing, skipping hook", {
|
|
2069
2137
|
configDir: configDir2,
|
|
2070
2138
|
type: hook.type,
|
|
@@ -2232,93 +2300,8 @@ Open Claude Code in a repo that has a work/ tree to see them.`);
|
|
|
2232
2300
|
});
|
|
2233
2301
|
}
|
|
2234
2302
|
|
|
2235
|
-
// src/graph/hook.ts
|
|
2236
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2, chmodSync } from "fs";
|
|
2237
|
-
import path10 from "path";
|
|
2238
|
-
var SIGNATURE = "# managed by jarvis";
|
|
2239
|
-
var SCRIPT = `#!/bin/sh
|
|
2240
|
-
${SIGNATURE} \u2014 keeps this repo's map current, so what an agent plans against is what is here.
|
|
2241
|
-
# Detached and silenced: git waits for a hook's output streams to close, so a build left on stdout
|
|
2242
|
-
# would hold up every commit by the length of a build. Never fails a commit.
|
|
2243
|
-
#
|
|
2244
|
-
# Run at the lowest priority the machine offers. A code commit still costs a real extract, and one
|
|
2245
|
-
# arriving at normal priority the instant you commit is felt as the machine going away for half a
|
|
2246
|
-
# minute \u2014 which is how a background job becomes something people turn off. Borrowed from the
|
|
2247
|
-
# docdoc-era hook in crispy, which had this right first.
|
|
2248
|
-
command -v jarvis >/dev/null 2>&1 || exit 0
|
|
2249
|
-
NICE=""
|
|
2250
|
-
command -v nice >/dev/null 2>&1 && NICE="nice -n 19"
|
|
2251
|
-
command -v taskpolicy >/dev/null 2>&1 && NICE="taskpolicy -b $NICE"
|
|
2252
|
-
( $NICE jarvis build graph >/dev/null 2>&1 & ) >/dev/null 2>&1
|
|
2253
|
-
exit 0
|
|
2254
|
-
`;
|
|
2255
|
-
function findRepoRoot(from) {
|
|
2256
|
-
let dir = path10.resolve(from);
|
|
2257
|
-
for (; ; ) {
|
|
2258
|
-
if (existsSync2(path10.join(dir, ".git"))) return dir;
|
|
2259
|
-
const parent = path10.dirname(dir);
|
|
2260
|
-
if (parent === dir) return null;
|
|
2261
|
-
dir = parent;
|
|
2262
|
-
}
|
|
2263
|
-
}
|
|
2264
|
-
function installCommitHook(repoRoot) {
|
|
2265
|
-
const git4 = path10.join(repoRoot, ".git");
|
|
2266
|
-
const dir = path10.join(git4, "hooks");
|
|
2267
|
-
const file = path10.join(dir, "post-commit");
|
|
2268
|
-
if (!existsSync2(git4)) return { installed: false, reason: "not-a-repo" };
|
|
2269
|
-
if (!statSync(git4).isDirectory()) return { installed: false, reason: "worktree" };
|
|
2270
|
-
if (!existsSync2(path10.join(git4, "HEAD"))) return { installed: false, reason: "not-a-repo" };
|
|
2271
|
-
if (existsSync2(file)) {
|
|
2272
|
-
try {
|
|
2273
|
-
if (!readFileSync2(file, "utf8").includes(SIGNATURE))
|
|
2274
|
-
return { installed: false, reason: "foreign-hook", path: file };
|
|
2275
|
-
} catch {
|
|
2276
|
-
return { installed: false, reason: "unwritable", path: file };
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
try {
|
|
2280
|
-
mkdirSync2(dir, { recursive: true });
|
|
2281
|
-
writeFileSync2(file, SCRIPT, "utf8");
|
|
2282
|
-
chmodSync(file, 493);
|
|
2283
|
-
return { installed: true, path: file };
|
|
2284
|
-
} catch {
|
|
2285
|
-
return { installed: false, reason: "unwritable", path: file };
|
|
2286
|
-
}
|
|
2287
|
-
}
|
|
2288
|
-
function describeCommitHook(outcome, repoRoot) {
|
|
2289
|
-
if (outcome.installed)
|
|
2290
|
-
return ` the map rebuilds itself on every commit here \u2713 (${path10.relative(repoRoot, outcome.path) || outcome.path})`;
|
|
2291
|
-
if (outcome.reason === "not-a-repo")
|
|
2292
|
-
return ` not a git repo, so there is no commit to rebuild on.
|
|
2293
|
-
Run this inside one, or rebuild by hand with 'jarvis build graph'.`;
|
|
2294
|
-
if (outcome.reason === "worktree")
|
|
2295
|
-
return ` this is a worktree or a submodule, and it shares the hooks of the checkout it
|
|
2296
|
-
was made from. Wire that one instead, or rebuild by hand with 'jarvis build graph'.`;
|
|
2297
|
-
if (outcome.reason === "foreign-hook")
|
|
2298
|
-
return ` a post-commit hook is already here and it is not ours \u2014 left untouched.
|
|
2299
|
-
Add this line to it to keep the map current: jarvis build graph >/dev/null 2>&1 &`;
|
|
2300
|
-
return ` could not write the hook \u2014 the map still builds, by hand, with 'jarvis build graph'.`;
|
|
2301
|
-
}
|
|
2302
|
-
|
|
2303
|
-
// src/commands/repo.ts
|
|
2304
|
-
function register3(program) {
|
|
2305
|
-
const repo = program.command("repo").description("Set up the repo you are standing in \u2014 no pairing, no daemon, no network");
|
|
2306
|
-
repo.command("init").description("Keep this repo's map current by rebuilding it on every commit").action(() => {
|
|
2307
|
-
if (!setUpThisRepo()) process.exit(1);
|
|
2308
|
-
console.log(" It rebuilds from your next commit. To build one now: jarvis build graph\n");
|
|
2309
|
-
});
|
|
2310
|
-
}
|
|
2311
|
-
function setUpThisRepo() {
|
|
2312
|
-
const root = findRepoRoot(process.cwd()) ?? process.cwd();
|
|
2313
|
-
console.log(" \u25B8 Keeping this repo's map current");
|
|
2314
|
-
const outcome = installCommitHook(root);
|
|
2315
|
-
console.log(`${describeCommitHook(outcome, root)}
|
|
2316
|
-
`);
|
|
2317
|
-
return outcome.installed;
|
|
2318
|
-
}
|
|
2319
|
-
|
|
2320
2303
|
// src/commands/init.ts
|
|
2321
|
-
function
|
|
2304
|
+
function register3(program) {
|
|
2322
2305
|
program.command("init").description("Set this machine up to work in repos, and join an instance if you name one").option("--url <url>", "Also join the jarvis instance at this address").option("--skip-daemon", "Skip the background daemon install step").option("--force", "Re-ask all prompts even when config already has answers").action(async (opts) => {
|
|
2323
2306
|
const ok = await runInit({
|
|
2324
2307
|
url: opts.url,
|
|
@@ -2414,6 +2397,14 @@ async function setUpThisMachine(prompts) {
|
|
|
2414
2397
|
`
|
|
2415
2398
|
);
|
|
2416
2399
|
}
|
|
2400
|
+
function setUpThisRepo() {
|
|
2401
|
+
const root = findRepoRoot(process.cwd()) ?? process.cwd();
|
|
2402
|
+
console.log(" \u25B8 Keeping this repo's map current");
|
|
2403
|
+
const outcome = installCommitHook(root);
|
|
2404
|
+
console.log(`${describeCommitHook(outcome, root)}
|
|
2405
|
+
`);
|
|
2406
|
+
return outcome.installed;
|
|
2407
|
+
}
|
|
2417
2408
|
async function setUpMapTool(prompts) {
|
|
2418
2409
|
console.log(" \u25B8 The tool the map's code half is built from");
|
|
2419
2410
|
const state2 = resolveGraphify();
|
|
@@ -2476,7 +2467,7 @@ function reportSetUp(joined) {
|
|
|
2476
2467
|
console.log(" \u2714 Done. This machine works in any repo that has a work/ tree:");
|
|
2477
2468
|
console.log(" the board, the map, the session block, the rules that arrive on edit,");
|
|
2478
2469
|
console.log(" and 'jarvis serve' for any agent that speaks MCP.\n");
|
|
2479
|
-
console.log(" In a repo you have cloned: jarvis
|
|
2470
|
+
console.log(" In a repo you have cloned: jarvis init");
|
|
2480
2471
|
console.log(" jarvis build graph");
|
|
2481
2472
|
console.log(" jarvis work list\n");
|
|
2482
2473
|
if (joined) {
|
|
@@ -2695,7 +2686,7 @@ async function promptList(question, fallback) {
|
|
|
2695
2686
|
}
|
|
2696
2687
|
|
|
2697
2688
|
// src/commands/pair.ts
|
|
2698
|
-
function
|
|
2689
|
+
function register4(program) {
|
|
2699
2690
|
program.command("pair").description("Re-pair this machine (when token expired)").action(async () => {
|
|
2700
2691
|
try {
|
|
2701
2692
|
await runPair();
|
|
@@ -2809,7 +2800,7 @@ async function unpair() {
|
|
|
2809
2800
|
clearConfig();
|
|
2810
2801
|
return { attempted: true, serverStatus };
|
|
2811
2802
|
}
|
|
2812
|
-
function
|
|
2803
|
+
function register5(program) {
|
|
2813
2804
|
program.command("unpair").description("Unregister this env from cloud and wipe local config").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
|
|
2814
2805
|
try {
|
|
2815
2806
|
const config2 = loadConfig();
|
|
@@ -2864,7 +2855,7 @@ function getRoots() {
|
|
|
2864
2855
|
const cfg = readConfig();
|
|
2865
2856
|
return Array.isArray(cfg.roots) ? cfg.roots : [];
|
|
2866
2857
|
}
|
|
2867
|
-
function
|
|
2858
|
+
function register6(program) {
|
|
2868
2859
|
const cmd = program.command("roots").description("Manage code-root directories");
|
|
2869
2860
|
cmd.command("list", { isDefault: true }).description("List current roots").action(() => {
|
|
2870
2861
|
const roots = getRoots();
|
|
@@ -2909,7 +2900,7 @@ function readLocalConfig() {
|
|
|
2909
2900
|
return {};
|
|
2910
2901
|
}
|
|
2911
2902
|
}
|
|
2912
|
-
function
|
|
2903
|
+
function register7(program) {
|
|
2913
2904
|
program.command("settings").description("Show this env's settings (roots, repos map)").action(async () => {
|
|
2914
2905
|
try {
|
|
2915
2906
|
const config2 = loadConfig();
|
|
@@ -10291,7 +10282,7 @@ import { createRequire as createRequire2 } from "module";
|
|
|
10291
10282
|
var _require = createRequire2(import.meta.url);
|
|
10292
10283
|
var VERSION2 = _require("../package.json").version ?? "0.0.0";
|
|
10293
10284
|
var IS_DEV = String(_require("../package.json").name ?? "").endsWith("-dev");
|
|
10294
|
-
var SHA = "
|
|
10285
|
+
var SHA = "497a5e2";
|
|
10295
10286
|
var BUILT = "2026-09-12";
|
|
10296
10287
|
var BUILD = SHA ?? "source";
|
|
10297
10288
|
var BUILD_LABEL = `${SHA ? `${VERSION2} (${SHA}${BUILT ? ` ${BUILT}` : ""})` : `${VERSION2} (source)`}${IS_DEV ? " \u2014 development build" : ""}`;
|
|
@@ -10810,7 +10801,7 @@ async function fetchRoots(hubUrl, envId, token) {
|
|
|
10810
10801
|
}
|
|
10811
10802
|
|
|
10812
10803
|
// src/commands/start.ts
|
|
10813
|
-
function
|
|
10804
|
+
function register8(program) {
|
|
10814
10805
|
program.command("start").description("Start the local agent (authenticates, cleans up stale processes, starts fresh)").option("-w, --workspace <path>", "Workspace root path").option("--api-key <key>", "Anthropic API key (for local-only use)").option("--no-upstream", "Don't connect to cloud (local-only mode)").option("--foreground", "Run in foreground (don't daemonize)").option("--force", "Re-ask all prompts even when config has them").action(async (opts) => {
|
|
10815
10806
|
if (refuseWithoutInstance()) process.exit(1);
|
|
10816
10807
|
const config2 = loadConfig();
|
|
@@ -10947,7 +10938,7 @@ function buildUpstreamConfig(req) {
|
|
|
10947
10938
|
}
|
|
10948
10939
|
|
|
10949
10940
|
// src/commands/stop.ts
|
|
10950
|
-
function
|
|
10941
|
+
function register9(program) {
|
|
10951
10942
|
program.command("stop").description("Stop the running agent").action(() => {
|
|
10952
10943
|
uninstallClaudeCodeHooks();
|
|
10953
10944
|
const service = createServiceManager();
|
|
@@ -10974,7 +10965,7 @@ function register10(program) {
|
|
|
10974
10965
|
}
|
|
10975
10966
|
|
|
10976
10967
|
// src/commands/restart.ts
|
|
10977
|
-
function
|
|
10968
|
+
function register10(program) {
|
|
10978
10969
|
program.command("restart").description("Restart the agent (alias for start \u2014 start always does a clean restart)").action(async () => {
|
|
10979
10970
|
await program.parseAsync(["node", "jarvis", "start"]);
|
|
10980
10971
|
});
|
|
@@ -10983,7 +10974,7 @@ function register11(program) {
|
|
|
10983
10974
|
// src/commands/logs.ts
|
|
10984
10975
|
import { spawn as spawn2, execSync as execSync6 } from "child_process";
|
|
10985
10976
|
import fs16 from "fs";
|
|
10986
|
-
function
|
|
10977
|
+
function register11(program) {
|
|
10987
10978
|
program.command("logs").description("View agent logs").option("-f, --follow", "Follow log output (like tail -f)", true).option("-n, --lines <n>", "Number of lines to show", "50").action((opts) => {
|
|
10988
10979
|
const logFile = getLogFile();
|
|
10989
10980
|
if (!fs16.existsSync(logFile)) {
|
|
@@ -11058,7 +11049,7 @@ function portOf(url) {
|
|
|
11058
11049
|
// src/commands/status.ts
|
|
11059
11050
|
var GREEN2 = (text) => `\x1B[32m${text}\x1B[0m`;
|
|
11060
11051
|
var RED2 = (text) => `\x1B[31m${text}\x1B[0m`;
|
|
11061
|
-
function
|
|
11052
|
+
function register12(program) {
|
|
11062
11053
|
program.command("status").description("Show agent configuration and connection status").action(async () => {
|
|
11063
11054
|
const config2 = loadConfig();
|
|
11064
11055
|
const health = await getHealth();
|
|
@@ -11097,7 +11088,7 @@ function endpoint(probed) {
|
|
|
11097
11088
|
}
|
|
11098
11089
|
|
|
11099
11090
|
// src/commands/install.ts
|
|
11100
|
-
function
|
|
11091
|
+
function register13(program) {
|
|
11101
11092
|
program.command("install").description("Install as OS service for auto-start on login and crash recovery").option("-w, --workspace <path>", "Workspace root path").option("--no-upstream", "Don't connect to cloud").action(async (opts) => {
|
|
11102
11093
|
if (refuseWithoutInstance()) process.exit(1);
|
|
11103
11094
|
const config2 = loadConfig();
|
|
@@ -11146,7 +11137,7 @@ function register14(program) {
|
|
|
11146
11137
|
import fs17 from "fs";
|
|
11147
11138
|
import path19 from "path";
|
|
11148
11139
|
import { createInterface as createInterface5 } from "readline";
|
|
11149
|
-
function
|
|
11140
|
+
function register14(program) {
|
|
11150
11141
|
program.command("uninstall").description("Stop the agent, remove the OS service, and wipe local config + identity").option("--keep-data", "Skip the data-wipe prompt; preserve skills/prompts/cache/settings").option("--purge", "Skip the prompt and wipe ALL local data (skills, prompts, cache, settings)").action(async (opts) => {
|
|
11151
11142
|
try {
|
|
11152
11143
|
await runUninstall(opts);
|
|
@@ -11208,7 +11199,7 @@ function confirm2(prompt) {
|
|
|
11208
11199
|
}
|
|
11209
11200
|
|
|
11210
11201
|
// src/commands/logout.ts
|
|
11211
|
-
function
|
|
11202
|
+
function register15(program) {
|
|
11212
11203
|
program.command("logout").description("Clear saved configuration").action(() => {
|
|
11213
11204
|
clearConfig();
|
|
11214
11205
|
console.log("Configuration cleared.");
|
|
@@ -11239,7 +11230,7 @@ async function call(path23, method, body) {
|
|
|
11239
11230
|
}
|
|
11240
11231
|
return await resp.json();
|
|
11241
11232
|
}
|
|
11242
|
-
function
|
|
11233
|
+
function register16(program) {
|
|
11243
11234
|
const mcp = program.command("mcp").description("Connect an agent to this workspace's board");
|
|
11244
11235
|
mcp.command("token").description("Mint a personal token for the Jarvis MCP server").option("--name <name>", "Which machine this token is for, e.g. 'laptop'").option("--scopes <list>", "read | write | read,write", "read,write").option("--show", "Show the current token's details instead of minting").option("--revoke", "Revoke the current token").action(async (opts) => {
|
|
11245
11236
|
try {
|
|
@@ -11293,7 +11284,7 @@ function register17(program) {
|
|
|
11293
11284
|
}
|
|
11294
11285
|
|
|
11295
11286
|
// src/commands/model.ts
|
|
11296
|
-
function
|
|
11287
|
+
function register17(program) {
|
|
11297
11288
|
const model = program.command("model").description("Model access for the map's semantic search, on this machine");
|
|
11298
11289
|
model.command("key").argument("[key]", "The OpenAI key to store. Omit it to see what is set.").option("--show", "Say whether a key is set, without printing it").option("--clear", "Forget the stored key").description("Set the OpenAI key the map embeds with").action((key, opts) => {
|
|
11299
11290
|
const config2 = loadConfig();
|
|
@@ -11552,7 +11543,7 @@ function isStale(lockPath, staleMs) {
|
|
|
11552
11543
|
}
|
|
11553
11544
|
|
|
11554
11545
|
// src/commands/build.ts
|
|
11555
|
-
function
|
|
11546
|
+
function register18(program) {
|
|
11556
11547
|
const build2 = program.command("build").description("Build an artifact from this repo");
|
|
11557
11548
|
build2.command("graph").description("Read the repo's jarvis.config.ts, build the graph, and say what is wrong with it").option("--repo <path>", "The repo to map. Default: the working directory").option("--rebuild", "LAST RESORT: throw the graph away and re-extract from scratch").option("--label", "Re-name the detected communities through the configured labeler").option("--gate", "Fail when a governance class has more findings than this repo carries").action(async (opts) => {
|
|
11558
11549
|
const argv = [
|
|
@@ -11612,7 +11603,7 @@ function isRedirected(req) {
|
|
|
11612
11603
|
}
|
|
11613
11604
|
|
|
11614
11605
|
// src/commands/dev.ts
|
|
11615
|
-
function
|
|
11606
|
+
function register19(program) {
|
|
11616
11607
|
const dev = program.command("dev").description("Run a development build in a repo, without replacing the installed jarvis");
|
|
11617
11608
|
dev.command("use").argument("[where]", "'here' for the working directory, 'all' for every repo", "here").option("--root <path>", "The checkout to run. Default: the one already recorded").description("Point a repo at the development build").action((where, opts) => {
|
|
11618
11609
|
const current = readDevRedirect();
|
|
@@ -12329,7 +12320,7 @@ async function brief2(repo) {
|
|
|
12329
12320
|
}
|
|
12330
12321
|
|
|
12331
12322
|
// src/commands/serve.ts
|
|
12332
|
-
function
|
|
12323
|
+
function register20(program) {
|
|
12333
12324
|
program.command("serve").description("Serve this repo to an agent over stdio \u2014 what an .mcp.json launches").option("--repo <path>", "The repo to serve. Default: the working directory").action(async (opts) => {
|
|
12334
12325
|
const repo = resolveRepo(opts.repo);
|
|
12335
12326
|
const problem = harnessProblem();
|
|
@@ -12634,7 +12625,7 @@ function whenRebuilt(dir, reload) {
|
|
|
12634
12625
|
}
|
|
12635
12626
|
|
|
12636
12627
|
// src/commands/ui.ts
|
|
12637
|
-
function
|
|
12628
|
+
function register21(program) {
|
|
12638
12629
|
program.command("ui").description("Open this repo's board in a browser \u2014 nothing to configure, nothing to join").option("--repo <path>", "The repo to show. Default: the working directory").option("--port <number>", "The port to listen on. Default: 3402").option("--no-open", "Print the address instead of opening a browser").option("--packaged", "Serve the page this build shipped with, never a checkout's").action(async (opts) => {
|
|
12639
12630
|
const repo = resolveRepo(opts.repo);
|
|
12640
12631
|
const port = opts.port ? Number.parseInt(opts.port, 10) : 3402;
|
|
@@ -12704,7 +12695,7 @@ async function openWhenUp(port) {
|
|
|
12704
12695
|
|
|
12705
12696
|
// src/commands/work.ts
|
|
12706
12697
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
12707
|
-
function
|
|
12698
|
+
function register22(program) {
|
|
12708
12699
|
program.command("work").description("The board \u2014 take work, prove it, finish it").argument("[args...]", "Passed to the harness untouched").allowUnknownOption().passThroughOptions().helpOption(false).action((passed) => {
|
|
12709
12700
|
const problem = harnessProblem();
|
|
12710
12701
|
if (problem) {
|
|
@@ -12727,11 +12718,11 @@ function register23(program) {
|
|
|
12727
12718
|
// src/cli.ts
|
|
12728
12719
|
function createCli() {
|
|
12729
12720
|
const program = new Command().enablePositionalOptions().name("jarvis").description("Jarvis local agent \u2014 watches Claude Code sessions on your machine").version(BUILD_LABEL);
|
|
12730
|
-
register4(program);
|
|
12731
12721
|
register3(program);
|
|
12722
|
+
register4(program);
|
|
12732
12723
|
register5(program);
|
|
12733
|
-
register6(program);
|
|
12734
12724
|
register(program);
|
|
12725
|
+
register6(program);
|
|
12735
12726
|
register7(program);
|
|
12736
12727
|
register8(program);
|
|
12737
12728
|
register9(program);
|
|
@@ -12746,10 +12737,9 @@ function createCli() {
|
|
|
12746
12737
|
register18(program);
|
|
12747
12738
|
register19(program);
|
|
12748
12739
|
register20(program);
|
|
12749
|
-
register21(program);
|
|
12750
12740
|
register2(program);
|
|
12741
|
+
register21(program);
|
|
12751
12742
|
register22(program);
|
|
12752
|
-
register23(program);
|
|
12753
12743
|
return program;
|
|
12754
12744
|
}
|
|
12755
12745
|
|