@rness/cli 0.6.0 → 0.6.2
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 +38 -4
- package/dist/bin/rness.js +1 -1
- package/dist/{chunk-NY3WV7X5.js → chunk-7TOHFPW6.js} +183 -135
- package/dist/chunk-7TOHFPW6.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/scaffold/.github/workflows/validate.yml +2 -2
- package/dist/chunk-NY3WV7X5.js.map +0 -1
|
@@ -45,6 +45,75 @@ async function writeFileAtomic(p, text) {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
// src/core/pm.ts
|
|
49
|
+
import { execFile } from "child_process";
|
|
50
|
+
import { promisify } from "util";
|
|
51
|
+
var execFileP = promisify(execFile);
|
|
52
|
+
var PACKAGE_MANAGERS = [
|
|
53
|
+
"npm",
|
|
54
|
+
"pnpm",
|
|
55
|
+
"yarn",
|
|
56
|
+
"bun"
|
|
57
|
+
];
|
|
58
|
+
function isPackageManager(value) {
|
|
59
|
+
return PACKAGE_MANAGERS.includes(value);
|
|
60
|
+
}
|
|
61
|
+
function detectPackageManager(userAgent = process.env["npm_config_user_agent"] ?? "") {
|
|
62
|
+
const name = userAgent.split("/")[0] ?? "";
|
|
63
|
+
return isPackageManager(name) ? name : "npm";
|
|
64
|
+
}
|
|
65
|
+
function firstLine(text) {
|
|
66
|
+
return text.split("\n").find((l) => l.trim() !== "")?.trim() ?? "unknown error";
|
|
67
|
+
}
|
|
68
|
+
async function packageManagerVersion(pm) {
|
|
69
|
+
try {
|
|
70
|
+
const { stdout } = await execFileP(pm, ["--version"]);
|
|
71
|
+
return stdout.trim();
|
|
72
|
+
} catch (e) {
|
|
73
|
+
throw new Error(`${pm} is not available on PATH`, { cause: e });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function rnessRunner(pm, version) {
|
|
77
|
+
if (pm === "pnpm") return "pnpm dlx @rness/cli";
|
|
78
|
+
if (pm === "bun") return "bunx @rness/cli";
|
|
79
|
+
if (pm === "yarn" && Number(version?.split(".")[0]) >= 2)
|
|
80
|
+
return "yarn dlx @rness/cli";
|
|
81
|
+
return "npx @rness/cli";
|
|
82
|
+
}
|
|
83
|
+
function rnessCommand(env = process.env) {
|
|
84
|
+
const agent = env["npm_config_user_agent"] ?? "";
|
|
85
|
+
if (agent === "") return "rness";
|
|
86
|
+
const pm = detectPackageManager(agent);
|
|
87
|
+
const [name, version] = (agent.split(" ")[0] ?? "").split("/");
|
|
88
|
+
return rnessRunner(pm, name === pm ? version ?? null : null);
|
|
89
|
+
}
|
|
90
|
+
var BARE_NPM_CODE = /^npm (error|ERR!) code \S+$/;
|
|
91
|
+
function installErrorLine(stderr) {
|
|
92
|
+
const lines = stderr.split("\n").map((l) => l.trim()).filter((l) => l !== "");
|
|
93
|
+
return lines.find((l) => !BARE_NPM_CODE.test(l)) ?? firstLine(stderr);
|
|
94
|
+
}
|
|
95
|
+
var FROZEN = {
|
|
96
|
+
npm: ["ci"],
|
|
97
|
+
pnpm: ["install", "--frozen-lockfile"],
|
|
98
|
+
yarn: ["install", "--immutable"],
|
|
99
|
+
bun: ["install", "--frozen-lockfile"]
|
|
100
|
+
};
|
|
101
|
+
function frozenArgs(pm) {
|
|
102
|
+
return [...FROZEN[pm]];
|
|
103
|
+
}
|
|
104
|
+
async function installDependencies(pm, dir, opts = {}) {
|
|
105
|
+
const args = opts.frozen === true ? frozenArgs(pm) : ["install"];
|
|
106
|
+
try {
|
|
107
|
+
await execFileP(pm, args, { cwd: dir, maxBuffer: 16 * 1024 * 1024 });
|
|
108
|
+
} catch (e) {
|
|
109
|
+
const err = e;
|
|
110
|
+
throw new Error(
|
|
111
|
+
`${pm} ${args.join(" ")} failed in ${dir}: ${installErrorLine(err.stderr ?? err.message)}`,
|
|
112
|
+
{ cause: e }
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
48
117
|
// src/core/auth.ts
|
|
49
118
|
import { chmod, mkdir, open, readFile as readFile2, rm as rm2, stat } from "fs/promises";
|
|
50
119
|
import { homedir } from "os";
|
|
@@ -298,7 +367,7 @@ async function resolveToken(deps = {}) {
|
|
|
298
367
|
await clearAuth();
|
|
299
368
|
(deps.notify ?? ((l) => process.stderr.write(`${l}
|
|
300
369
|
`)))(
|
|
301
|
-
|
|
370
|
+
`your GitHub login expired; run ${rnessCommand()} login`
|
|
302
371
|
);
|
|
303
372
|
return null;
|
|
304
373
|
}
|
|
@@ -313,7 +382,7 @@ async function resolveToken(deps = {}) {
|
|
|
313
382
|
var DEFAULT_GITHUB_API = "https://api.github.com";
|
|
314
383
|
var MAX_PAGES = 50;
|
|
315
384
|
var PER_PAGE = 100;
|
|
316
|
-
var
|
|
385
|
+
var addLater = () => `; add repositories later with ${rnessCommand()} add <repo>`;
|
|
317
386
|
var NEXT = /<[^>]*>\s*;\s*rel="next"/;
|
|
318
387
|
function isRepository(value) {
|
|
319
388
|
if (value === null || typeof value !== "object") return false;
|
|
@@ -357,12 +426,12 @@ function httpError(page, path) {
|
|
|
357
426
|
return new Error("GitHub rejected the token (401)", { cause });
|
|
358
427
|
if (page.status === 429 || page.status === 403 && (page.headers.get("x-ratelimit-remaining") === "0" || page.headers.has("retry-after"))) {
|
|
359
428
|
return new Error(
|
|
360
|
-
|
|
429
|
+
`GitHub API rate limit reached; set GITHUB_TOKEN or add repositories later with ${rnessCommand()} add`,
|
|
361
430
|
{ cause }
|
|
362
431
|
);
|
|
363
432
|
}
|
|
364
433
|
return new Error(
|
|
365
|
-
`GitHub API answered ${page.status} for ${path}${
|
|
434
|
+
`GitHub API answered ${page.status} for ${path}${addLater()}`,
|
|
366
435
|
{ cause }
|
|
367
436
|
);
|
|
368
437
|
}
|
|
@@ -403,7 +472,7 @@ async function listRepositories(owner, options) {
|
|
|
403
472
|
page = await getPage(url(kind, n), headers, timeoutMs);
|
|
404
473
|
if (page.status === 404) {
|
|
405
474
|
throw new Error(
|
|
406
|
-
`GitHub has no organization or user named "${owner}" (or it is not visible to you)${
|
|
475
|
+
`GitHub has no organization or user named "${owner}" (or it is not visible to you)${addLater()}`,
|
|
407
476
|
{ cause: { status: 404, path: kind.path } }
|
|
408
477
|
);
|
|
409
478
|
}
|
|
@@ -599,10 +668,10 @@ async function githubProvider(apiBase) {
|
|
|
599
668
|
import { spawn } from "child_process";
|
|
600
669
|
|
|
601
670
|
// src/core/git.ts
|
|
602
|
-
import { execFile } from "child_process";
|
|
671
|
+
import { execFile as execFile2 } from "child_process";
|
|
603
672
|
import { dirname as dirname2, resolve } from "path";
|
|
604
|
-
import { promisify } from "util";
|
|
605
|
-
var
|
|
673
|
+
import { promisify as promisify2 } from "util";
|
|
674
|
+
var execFileP2 = promisify2(execFile2);
|
|
606
675
|
var ENV_HELPER = '!f() { test "$1" = get && printf "username=%s\\npassword=%s\\n" "$RNESS_GIT_USERNAME" "$RNESS_GIT_TOKEN"; }; f';
|
|
607
676
|
function withCredentials(credentials) {
|
|
608
677
|
if (credentials === null || credentials === void 0)
|
|
@@ -618,7 +687,7 @@ function withCredentials(credentials) {
|
|
|
618
687
|
async function git(args, cwd, credentials) {
|
|
619
688
|
const auth = withCredentials(credentials);
|
|
620
689
|
try {
|
|
621
|
-
const { stdout } = await
|
|
690
|
+
const { stdout } = await execFileP2("git", [...auth.args, ...args], {
|
|
622
691
|
...cwd === void 0 ? {} : { cwd },
|
|
623
692
|
env: {
|
|
624
693
|
...process.env,
|
|
@@ -709,7 +778,7 @@ var NOT_FOUND = [
|
|
|
709
778
|
/repository .*not found/i,
|
|
710
779
|
/does not appear to be a git repository/i
|
|
711
780
|
];
|
|
712
|
-
function
|
|
781
|
+
function firstLine2(text) {
|
|
713
782
|
return text.split("\n").find((l) => l.trim() !== "")?.trim() ?? "unknown error";
|
|
714
783
|
}
|
|
715
784
|
function classifyProbe(url, exitCode, stderr) {
|
|
@@ -717,10 +786,10 @@ function classifyProbe(url, exitCode, stderr) {
|
|
|
717
786
|
if (AUTH.some((r) => r.test(stderr)))
|
|
718
787
|
return {
|
|
719
788
|
kind: "error",
|
|
720
|
-
message: `cannot access ${url}: ${
|
|
789
|
+
message: `cannot access ${url}: ${firstLine2(stderr)}`
|
|
721
790
|
};
|
|
722
791
|
if (NOT_FOUND.some((r) => r.test(stderr))) return { kind: "not-found" };
|
|
723
|
-
return { kind: "error", message: `cannot reach ${url}: ${
|
|
792
|
+
return { kind: "error", message: `cannot reach ${url}: ${firstLine2(stderr)}` };
|
|
724
793
|
}
|
|
725
794
|
var STDERR_FLUSH_MS = 200;
|
|
726
795
|
async function probeRemote(url, timeoutMs = 6e4, credentials) {
|
|
@@ -1149,7 +1218,7 @@ var GREETING = /^Hi ([^!\s]+)! You've successfully authenticated/m;
|
|
|
1149
1218
|
function parseSshGreeting(stderr) {
|
|
1150
1219
|
return GREETING.exec(stderr)?.[1] ?? null;
|
|
1151
1220
|
}
|
|
1152
|
-
function
|
|
1221
|
+
function firstLine3(text) {
|
|
1153
1222
|
return text.split("\n").find((l) => l.trim() !== "")?.trim() ?? null;
|
|
1154
1223
|
}
|
|
1155
1224
|
var STDERR_FLUSH_MS2 = 200;
|
|
@@ -1189,7 +1258,7 @@ async function detectGithubSsh(opts) {
|
|
|
1189
1258
|
settle(
|
|
1190
1259
|
login !== null ? { ok: true, login } : {
|
|
1191
1260
|
ok: false,
|
|
1192
|
-
reason:
|
|
1261
|
+
reason: firstLine3(stderr2) ?? `ssh exited with code ${code ?? "?"}`
|
|
1193
1262
|
}
|
|
1194
1263
|
);
|
|
1195
1264
|
};
|
|
@@ -1254,7 +1323,7 @@ var INSTEAD_OF_LINES = [
|
|
|
1254
1323
|
' git config --global url."https://github.com/".insteadOf git@github.com:'
|
|
1255
1324
|
];
|
|
1256
1325
|
function httpsFlagLine(spec) {
|
|
1257
|
-
return `or clone this repository over HTTPS:
|
|
1326
|
+
return `or clone this repository over HTTPS: ${rnessCommand()} add ${spec} --https`;
|
|
1258
1327
|
}
|
|
1259
1328
|
|
|
1260
1329
|
// src/core/workspace.ts
|
|
@@ -1568,6 +1637,17 @@ function mergeBlock(existing, block) {
|
|
|
1568
1637
|
}
|
|
1569
1638
|
return { ok: true, text, changed: text !== existing };
|
|
1570
1639
|
}
|
|
1640
|
+
var POINTER = "@AGENTS.md";
|
|
1641
|
+
function claudeMdAtRoot(existing, block) {
|
|
1642
|
+
if (existing === null) return mergeBlock(null, block);
|
|
1643
|
+
const lines = existing.split(/\r?\n/);
|
|
1644
|
+
if (!lines.some((l) => l.trim() === POINTER))
|
|
1645
|
+
return mergeBlock(existing, block);
|
|
1646
|
+
const eol = existing.includes("\r\n") ? "\r\n" : "\n";
|
|
1647
|
+
const rest = lines.filter((l) => l.trim() !== POINTER).join(eol);
|
|
1648
|
+
const merged = mergeBlock(rest.trim() === "" ? null : rest, block);
|
|
1649
|
+
return merged.ok ? { ...merged, changed: merged.text !== existing } : merged;
|
|
1650
|
+
}
|
|
1571
1651
|
async function ensureClaudeMd(dir) {
|
|
1572
1652
|
const file = join8(dir, "CLAUDE.md");
|
|
1573
1653
|
if (await isSymlink(file)) return "unchanged";
|
|
@@ -1780,6 +1860,18 @@ function targetsOf(manifest, root, only) {
|
|
|
1780
1860
|
}
|
|
1781
1861
|
return targets;
|
|
1782
1862
|
}
|
|
1863
|
+
async function syncBlockFile(file, block, check, rootClaudeMd = false) {
|
|
1864
|
+
const existing = await readOrNull(file);
|
|
1865
|
+
const existingLines = existing === null ? [] : existing.split(/\r?\n/);
|
|
1866
|
+
const span = findBlock(existingLines);
|
|
1867
|
+
const current = span.kind === "one" && isCurrentBlock(existingLines.slice(span.begin, span.end + 1), block.hash) && !(rootClaudeMd && existingLines.some((l) => l.trim() === "@AGENTS.md"));
|
|
1868
|
+
const merged = current ? { ok: true, text: existing ?? "", changed: false } : rootClaudeMd ? claudeMdAtRoot(existing, block.text) : mergeBlock(existing, block.text);
|
|
1869
|
+
if (!merged.ok) return { error: merged.error };
|
|
1870
|
+
if (!merged.changed) return "unchanged";
|
|
1871
|
+
if (check) return "stale";
|
|
1872
|
+
await writeFileAtomic(file, merged.text);
|
|
1873
|
+
return "updated";
|
|
1874
|
+
}
|
|
1783
1875
|
var SELECT_ALL = "*";
|
|
1784
1876
|
async function askWhatToSync(input) {
|
|
1785
1877
|
if (!input.terminal.isTty()) {
|
|
@@ -1916,7 +2008,7 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1916
2008
|
}
|
|
1917
2009
|
if (notCloned.size > 0)
|
|
1918
2010
|
lines.push(
|
|
1919
|
-
`not cloned: ${[...notCloned].join(", ")} (
|
|
2011
|
+
`not cloned: ${[...notCloned].join(", ")} (${rnessCommand()} add <name>, or ${rnessCommand()} sync --all)`
|
|
1920
2012
|
);
|
|
1921
2013
|
const scoped = new Set(
|
|
1922
2014
|
Object.values(manifest.scopes).map((s) => s.path.split("/")[1])
|
|
@@ -1926,7 +2018,7 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1926
2018
|
);
|
|
1927
2019
|
if (undeclared.length > 0)
|
|
1928
2020
|
lines.push(
|
|
1929
|
-
`not in rness.json: ${undeclared.join(", ")} (
|
|
2021
|
+
`not in rness.json: ${undeclared.join(", ")} (${rnessCommand()} add <name> declares it)`
|
|
1930
2022
|
);
|
|
1931
2023
|
if (!await exists(join9(ws.root, "org"))) {
|
|
1932
2024
|
lines.push(["skipped", "blocks (no org/ directory here)"]);
|
|
@@ -1939,10 +2031,11 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1939
2031
|
lines.push(["skipped", `${t.label} (directory not present)`]);
|
|
1940
2032
|
continue;
|
|
1941
2033
|
}
|
|
1942
|
-
const
|
|
2034
|
+
const [agentsLinked, claudeLinked] = await Promise.all(
|
|
1943
2035
|
MANAGED_FILES.map((f) => isSymlink(join9(t.dir, f)))
|
|
1944
2036
|
);
|
|
1945
|
-
|
|
2037
|
+
const atRoot = t.scope === null;
|
|
2038
|
+
if (!atRoot && (agentsLinked === true || claudeLinked === true)) {
|
|
1946
2039
|
lines.push(["skipped", `${t.label} (symlink)`]);
|
|
1947
2040
|
continue;
|
|
1948
2041
|
}
|
|
@@ -1962,35 +2055,37 @@ async function syncCommand(opts, deps = {}) {
|
|
|
1962
2055
|
`${t.label}: block is ${Math.round(block.bytes / 1024)} KB (over 32 KB)`
|
|
1963
2056
|
);
|
|
1964
2057
|
}
|
|
1965
|
-
const
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
const span = findBlock(existingLines);
|
|
1969
|
-
const current = span.kind === "one" && isCurrentBlock(
|
|
1970
|
-
existingLines.slice(span.begin, span.end + 1),
|
|
1971
|
-
block.hash
|
|
1972
|
-
);
|
|
1973
|
-
const merged = current ? { ok: true, text: existing ?? "", changed: false } : mergeBlock(existing, block.text);
|
|
1974
|
-
if (!merged.ok) {
|
|
1975
|
-
problems.push(`${t.label}: ${merged.error}`);
|
|
2058
|
+
const agents = agentsLinked === true ? "skipped" : await syncBlockFile(join9(t.dir, "AGENTS.md"), block, check);
|
|
2059
|
+
if (typeof agents === "object") {
|
|
2060
|
+
problems.push(`${t.label}: ${agents.error}`);
|
|
1976
2061
|
continue;
|
|
1977
2062
|
}
|
|
1978
|
-
|
|
1979
|
-
|
|
2063
|
+
lines.push(
|
|
2064
|
+
agents === "skipped" ? ["skipped", `${t.label} (symlink)`] : [agents, t.label]
|
|
2065
|
+
);
|
|
2066
|
+
if (agents === "stale") differences += 1;
|
|
2067
|
+
if (!atRoot) {
|
|
1980
2068
|
if (!check) await ensureClaudeMd(t.dir);
|
|
1981
2069
|
continue;
|
|
1982
2070
|
}
|
|
1983
|
-
if (
|
|
1984
|
-
|
|
1985
|
-
|
|
2071
|
+
if (claudeLinked === true) continue;
|
|
2072
|
+
const claude = await syncBlockFile(
|
|
2073
|
+
join9(t.dir, "CLAUDE.md"),
|
|
2074
|
+
block,
|
|
2075
|
+
check,
|
|
2076
|
+
true
|
|
2077
|
+
);
|
|
2078
|
+
if (typeof claude === "object") {
|
|
2079
|
+
problems.push(`CLAUDE.md: ${claude.error}`);
|
|
1986
2080
|
continue;
|
|
1987
2081
|
}
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
lines.push(["updated", `${t.label}`]);
|
|
2082
|
+
if (claude === "stale") differences += 1;
|
|
2083
|
+
if (claude !== agents) lines.push([claude, "CLAUDE.md"]);
|
|
1991
2084
|
}
|
|
1992
2085
|
if (check && differences > 0)
|
|
1993
|
-
problems.push(
|
|
2086
|
+
problems.push(
|
|
2087
|
+
`${differences} block(s) out of date \u2014 run ${rnessCommand()} sync`
|
|
2088
|
+
);
|
|
1994
2089
|
}
|
|
1995
2090
|
return problems.length > 0 ? 1 : 0;
|
|
1996
2091
|
} finally {
|
|
@@ -2230,7 +2325,7 @@ async function contextCommand(opts) {
|
|
|
2230
2325
|
}
|
|
2231
2326
|
|
|
2232
2327
|
// src/version.ts
|
|
2233
|
-
var VERSION = "0.6.
|
|
2328
|
+
var VERSION = "0.6.2";
|
|
2234
2329
|
|
|
2235
2330
|
// src/core/delegate.ts
|
|
2236
2331
|
import { readFile as readFile6 } from "fs/promises";
|
|
@@ -2279,72 +2374,6 @@ async function findDelegate(cwd, ownVersion) {
|
|
|
2279
2374
|
return { entry: join11(pinned.dir, "dist", "index.js"), version, root };
|
|
2280
2375
|
}
|
|
2281
2376
|
|
|
2282
|
-
// src/core/pm.ts
|
|
2283
|
-
import { execFile as execFile2 } from "child_process";
|
|
2284
|
-
import { promisify as promisify2 } from "util";
|
|
2285
|
-
var execFileP2 = promisify2(execFile2);
|
|
2286
|
-
var PACKAGE_MANAGERS = [
|
|
2287
|
-
"npm",
|
|
2288
|
-
"pnpm",
|
|
2289
|
-
"yarn",
|
|
2290
|
-
"bun"
|
|
2291
|
-
];
|
|
2292
|
-
function isPackageManager(value) {
|
|
2293
|
-
return PACKAGE_MANAGERS.includes(value);
|
|
2294
|
-
}
|
|
2295
|
-
function detectPackageManager(userAgent = process.env["npm_config_user_agent"] ?? "") {
|
|
2296
|
-
const name = userAgent.split("/")[0] ?? "";
|
|
2297
|
-
return isPackageManager(name) ? name : "npm";
|
|
2298
|
-
}
|
|
2299
|
-
function firstLine3(text) {
|
|
2300
|
-
return text.split("\n").find((l) => l.trim() !== "")?.trim() ?? "unknown error";
|
|
2301
|
-
}
|
|
2302
|
-
async function packageManagerVersion(pm) {
|
|
2303
|
-
try {
|
|
2304
|
-
const { stdout } = await execFileP2(pm, ["--version"]);
|
|
2305
|
-
return stdout.trim();
|
|
2306
|
-
} catch (e) {
|
|
2307
|
-
throw new Error(`${pm} is not available on PATH`, { cause: e });
|
|
2308
|
-
}
|
|
2309
|
-
}
|
|
2310
|
-
function rnessRunner(pm, version) {
|
|
2311
|
-
if (pm === "pnpm") return "pnpm dlx @rness/cli";
|
|
2312
|
-
if (pm === "bun") return "bunx @rness/cli";
|
|
2313
|
-
if (pm === "yarn" && Number(version?.split(".")[0]) >= 2)
|
|
2314
|
-
return "yarn dlx @rness/cli";
|
|
2315
|
-
return "npx @rness/cli";
|
|
2316
|
-
}
|
|
2317
|
-
async function rnessRunnerFor(pm) {
|
|
2318
|
-
const version = pm === "yarn" ? await packageManagerVersion(pm).catch(() => null) : null;
|
|
2319
|
-
return rnessRunner(pm, version);
|
|
2320
|
-
}
|
|
2321
|
-
var BARE_NPM_CODE = /^npm (error|ERR!) code \S+$/;
|
|
2322
|
-
function installErrorLine(stderr) {
|
|
2323
|
-
const lines = stderr.split("\n").map((l) => l.trim()).filter((l) => l !== "");
|
|
2324
|
-
return lines.find((l) => !BARE_NPM_CODE.test(l)) ?? firstLine3(stderr);
|
|
2325
|
-
}
|
|
2326
|
-
var FROZEN = {
|
|
2327
|
-
npm: ["ci"],
|
|
2328
|
-
pnpm: ["install", "--frozen-lockfile"],
|
|
2329
|
-
yarn: ["install", "--immutable"],
|
|
2330
|
-
bun: ["install", "--frozen-lockfile"]
|
|
2331
|
-
};
|
|
2332
|
-
function frozenArgs(pm) {
|
|
2333
|
-
return [...FROZEN[pm]];
|
|
2334
|
-
}
|
|
2335
|
-
async function installDependencies(pm, dir, opts = {}) {
|
|
2336
|
-
const args = opts.frozen === true ? frozenArgs(pm) : ["install"];
|
|
2337
|
-
try {
|
|
2338
|
-
await execFileP2(pm, args, { cwd: dir, maxBuffer: 16 * 1024 * 1024 });
|
|
2339
|
-
} catch (e) {
|
|
2340
|
-
const err = e;
|
|
2341
|
-
throw new Error(
|
|
2342
|
-
`${pm} ${args.join(" ")} failed in ${dir}: ${installErrorLine(err.stderr ?? err.message)}`,
|
|
2343
|
-
{ cause: e }
|
|
2344
|
-
);
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
2347
|
-
|
|
2348
2377
|
// src/core/scaffold.ts
|
|
2349
2378
|
import { statSync } from "fs";
|
|
2350
2379
|
import { dirname as dirname4, join as join12 } from "path";
|
|
@@ -2480,8 +2509,8 @@ async function offerSetupGit(opts, terminal, bin, ui) {
|
|
|
2480
2509
|
const changed = await setupGit(process.execPath, bin);
|
|
2481
2510
|
ui.line(
|
|
2482
2511
|
changed ? "updated" : "unchanged",
|
|
2483
|
-
|
|
2484
|
-
|
|
2512
|
+
`git: rness answers for https://github.com (${rnessCommand()} logout undoes it)`,
|
|
2513
|
+
`git now asks rness for your github.com login over HTTPS (${rnessCommand()} logout undoes it)`
|
|
2485
2514
|
);
|
|
2486
2515
|
}
|
|
2487
2516
|
async function loginCommand(opts, deps = {}) {
|
|
@@ -2498,7 +2527,7 @@ async function loginCommand(opts, deps = {}) {
|
|
|
2498
2527
|
if (stored !== null && await resolveToken() !== null) {
|
|
2499
2528
|
ui.line(
|
|
2500
2529
|
"logged in",
|
|
2501
|
-
`as ${stored.login} (github.com);
|
|
2530
|
+
`as ${stored.login} (github.com); ${rnessCommand()} logout to switch`
|
|
2502
2531
|
);
|
|
2503
2532
|
await offerSetupGit(opts, terminal, bin, ui);
|
|
2504
2533
|
if (own) ui.outro("Nothing to do", "idle");
|
|
@@ -2761,7 +2790,7 @@ async function syncPinned(root, shown, fallback) {
|
|
|
2761
2790
|
if (installed === null) {
|
|
2762
2791
|
if (fallback !== void 0) return fallback();
|
|
2763
2792
|
process.stderr.write(
|
|
2764
|
-
`@rness/cli is not installed in ${shown}/.rness; install in .rness/, then
|
|
2793
|
+
`@rness/cli is not installed in ${shown}/.rness; install in .rness/, then ${rnessCommand()} sync
|
|
2765
2794
|
`
|
|
2766
2795
|
);
|
|
2767
2796
|
return 1;
|
|
@@ -2818,8 +2847,8 @@ async function targetProblem(cwd, root, pm) {
|
|
|
2818
2847
|
if (!await exists(root)) return null;
|
|
2819
2848
|
if (await exists(join15(root, ".rness", "rness.json"))) {
|
|
2820
2849
|
if (!await exists(join15(root, ".rness", "node_modules")))
|
|
2821
|
-
return `${shown} holds an rness workspace whose dependencies are not installed; cd ${shown}/.rness && ${pm} install, then
|
|
2822
|
-
return `${shown} already holds an rness workspace (.rness/); run
|
|
2850
|
+
return `${shown} holds an rness workspace whose dependencies are not installed; cd ${shown}/.rness && ${pm} install, then ${rnessCommand()} sync`;
|
|
2851
|
+
return `${shown} already holds an rness workspace (.rness/); run ${rnessCommand()} add inside it to add repositories`;
|
|
2823
2852
|
}
|
|
2824
2853
|
if (!(await stat3(root)).isDirectory()) return `${shown} is not a directory`;
|
|
2825
2854
|
if (!await isEmptyDir(root)) return `${shown} is not empty`;
|
|
@@ -2879,6 +2908,8 @@ async function commitContext(input) {
|
|
|
2879
2908
|
|
|
2880
2909
|
// src/core/sync-blocks.ts
|
|
2881
2910
|
async function syncBlocks(ui, root, shown, inPlace, sshWorks) {
|
|
2911
|
+
if (process.env["RNESS_NO_DELEGATE"] === "1" && inPlace !== void 0)
|
|
2912
|
+
return inPlace();
|
|
2882
2913
|
if (!ui.session)
|
|
2883
2914
|
return ui.step(
|
|
2884
2915
|
{ doing: "syncing the blocks", git: true },
|
|
@@ -2895,7 +2926,7 @@ async function syncBlocks(ui, root, shown, inPlace, sshWorks) {
|
|
|
2895
2926
|
if (result === null) {
|
|
2896
2927
|
if (inPlace !== void 0) return inPlace();
|
|
2897
2928
|
ui.error(
|
|
2898
|
-
`@rness/cli is not installed in ${shown}/.rness; install in .rness/, then
|
|
2929
|
+
`@rness/cli is not installed in ${shown}/.rness; install in .rness/, then ${rnessCommand()} sync`
|
|
2899
2930
|
);
|
|
2900
2931
|
return 1;
|
|
2901
2932
|
}
|
|
@@ -2985,7 +3016,7 @@ async function createBlank(input) {
|
|
|
2985
3016
|
const next = [
|
|
2986
3017
|
`cd ${shown}`,
|
|
2987
3018
|
"# bring a repository in: <owner>/<repo> on GitHub, or any git URL",
|
|
2988
|
-
`${
|
|
3019
|
+
`${rnessCommand()} add <owner>/<repo>`,
|
|
2989
3020
|
'# to share it: set "org" in .rness/rness.json, then push .rness to github.com/<org>/.rness'
|
|
2990
3021
|
];
|
|
2991
3022
|
if (ui.session) {
|
|
@@ -3055,11 +3086,11 @@ async function pickRepositories(input) {
|
|
|
3055
3086
|
listed = listing.repositories;
|
|
3056
3087
|
if (listing.owner === "user")
|
|
3057
3088
|
ui.hint(
|
|
3058
|
-
`only public repositories of ${org} are listed; add private ones later with
|
|
3089
|
+
`only public repositories of ${org} are listed; add private ones later with ${rnessCommand()} add <repo>`
|
|
3059
3090
|
);
|
|
3060
3091
|
else if (!provider.authenticated)
|
|
3061
3092
|
ui.hint(
|
|
3062
|
-
|
|
3093
|
+
`only public repositories are listed; ${rnessCommand()} login lists the private ones you can access`
|
|
3063
3094
|
);
|
|
3064
3095
|
if (listing.truncated)
|
|
3065
3096
|
ui.hint(`listed the first ${MAX_PAGES * PER_PAGE} repositories of ${org}`);
|
|
@@ -3290,7 +3321,6 @@ async function createCommand(opts, deps = {}) {
|
|
|
3290
3321
|
return 2;
|
|
3291
3322
|
}
|
|
3292
3323
|
let pm = opts.pm !== void 0 && isPackageManager(opts.pm) ? opts.pm : detectPackageManager();
|
|
3293
|
-
const launchedWith = pm;
|
|
3294
3324
|
const interactive = opts.yes !== true && terminal.isTty();
|
|
3295
3325
|
const ui = interactive ? await makeUi(terminal) : { ...plainUi };
|
|
3296
3326
|
let sshTest;
|
|
@@ -3523,7 +3553,7 @@ async function createCommand(opts, deps = {}) {
|
|
|
3523
3553
|
const remaining = Object.keys(catalogue.repos).filter(
|
|
3524
3554
|
(name2) => !cloned.has(name2)
|
|
3525
3555
|
);
|
|
3526
|
-
const rness2 =
|
|
3556
|
+
const rness2 = rnessCommand();
|
|
3527
3557
|
const next2 = [
|
|
3528
3558
|
`cd ${shown}`,
|
|
3529
3559
|
// The comment above its command, as the new-workspace note does: a
|
|
@@ -3583,7 +3613,7 @@ ${next2.map((l) => ` ${l}`).join("\n")}
|
|
|
3583
3613
|
url: contextUrl
|
|
3584
3614
|
}) : false;
|
|
3585
3615
|
if (published === null) return cancelled(ui);
|
|
3586
|
-
const rness =
|
|
3616
|
+
const rness = rnessCommand();
|
|
3587
3617
|
const next = [
|
|
3588
3618
|
`cd ${shown}/.rness`,
|
|
3589
3619
|
// What was asked for and did not happen, as the command that retries
|
|
@@ -3597,7 +3627,9 @@ ${next2.map((l) => ` ${l}`).join("\n")}
|
|
|
3597
3627
|
"# or, with the GitHub CLI (gh) installed, in one step:",
|
|
3598
3628
|
`gh repo create ${org}/.rness --private --source . --push`
|
|
3599
3629
|
],
|
|
3600
|
-
|
|
3630
|
+
// How this command was launched (npm when rness was typed directly),
|
|
3631
|
+
// whatever --pm installed with.
|
|
3632
|
+
`# then, for every teammate: ${detectPackageManager()} create rness ${org}`
|
|
3601
3633
|
];
|
|
3602
3634
|
if (ui.session) {
|
|
3603
3635
|
ui.note("Next steps", next);
|
|
@@ -3687,7 +3719,7 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal) {
|
|
|
3687
3719
|
const pin = await readPin(ws.rnessDir);
|
|
3688
3720
|
if (pin === null) {
|
|
3689
3721
|
process.stderr.write(
|
|
3690
|
-
`no @rness/cli entry in ${label}/package.json; add it to devDependencies, then run
|
|
3722
|
+
`no @rness/cli entry in ${label}/package.json; add it to devDependencies, then run ${rnessCommand()} upgrade
|
|
3691
3723
|
`
|
|
3692
3724
|
);
|
|
3693
3725
|
return 1;
|
|
@@ -3708,7 +3740,8 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal) {
|
|
|
3708
3740
|
);
|
|
3709
3741
|
if (target === null) {
|
|
3710
3742
|
process.stderr.write(
|
|
3711
|
-
|
|
3743
|
+
`cannot reach the registry; name the version: ${rnessCommand()} upgrade <version>
|
|
3744
|
+
`
|
|
3712
3745
|
);
|
|
3713
3746
|
return 1;
|
|
3714
3747
|
}
|
|
@@ -3722,7 +3755,7 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal) {
|
|
|
3722
3755
|
const downgrading = EXACT_VERSION.test(pin.spec) && compareVersions(target, pin.spec) < 0;
|
|
3723
3756
|
if (downgrading && version === void 0) {
|
|
3724
3757
|
process.stderr.write(
|
|
3725
|
-
`${label} pins @rness/cli ${pin.spec}, newer than the latest release ${target}; to downgrade:
|
|
3758
|
+
`${label} pins @rness/cli ${pin.spec}, newer than the latest release ${target}; to downgrade: ${rnessCommand()} upgrade ${target}
|
|
3726
3759
|
`
|
|
3727
3760
|
);
|
|
3728
3761
|
return 1;
|
|
@@ -3863,13 +3896,17 @@ async function checkBlocks({
|
|
|
3863
3896
|
checks
|
|
3864
3897
|
});
|
|
3865
3898
|
if (!await exists(join19(root, "org"))) return derive();
|
|
3866
|
-
const targets = [
|
|
3899
|
+
const targets = [
|
|
3900
|
+
{ scope: null, dir: root, depth: 0, file: "AGENTS.md", label: "AGENTS.md" },
|
|
3901
|
+
{ scope: null, dir: root, depth: 0, file: "CLAUDE.md", label: "CLAUDE.md" }
|
|
3902
|
+
];
|
|
3867
3903
|
for (const [name, entry] of Object.entries(manifest.scopes)) {
|
|
3868
3904
|
const segments = entry.path.split("/");
|
|
3869
3905
|
targets.push({
|
|
3870
3906
|
scope: name,
|
|
3871
3907
|
dir: join19(root, ...segments),
|
|
3872
3908
|
depth: segments.length,
|
|
3909
|
+
file: "AGENTS.md",
|
|
3873
3910
|
label: `${entry.path}/AGENTS.md`
|
|
3874
3911
|
});
|
|
3875
3912
|
}
|
|
@@ -3882,14 +3919,14 @@ async function checkBlocks({
|
|
|
3882
3919
|
);
|
|
3883
3920
|
continue;
|
|
3884
3921
|
}
|
|
3885
|
-
const text = await readOrNull(join19(t.dir,
|
|
3922
|
+
const text = await readOrNull(join19(t.dir, t.file));
|
|
3886
3923
|
const lines = text === null ? [] : text.split(/\r?\n/);
|
|
3887
3924
|
const found = findBlock(lines);
|
|
3888
3925
|
if (found.kind === "none") {
|
|
3889
3926
|
note(
|
|
3890
3927
|
t.label,
|
|
3891
3928
|
"no-block",
|
|
3892
|
-
`${t.label}: no rness block yet (run
|
|
3929
|
+
`${t.label}: no rness block yet (run ${rnessCommand()} sync)`
|
|
3893
3930
|
);
|
|
3894
3931
|
continue;
|
|
3895
3932
|
}
|
|
@@ -3908,10 +3945,15 @@ async function checkBlocks({
|
|
|
3908
3945
|
depth: t.depth,
|
|
3909
3946
|
context
|
|
3910
3947
|
});
|
|
3911
|
-
|
|
3948
|
+
const pointerLeft = t.file === "CLAUDE.md" && lines.some((l) => l.trim() === "@AGENTS.md");
|
|
3949
|
+
if (isCurrentBlock(lines.slice(found.begin, found.end + 1), fresh2.hash) && !pointerLeft)
|
|
3912
3950
|
note(t.label, "current");
|
|
3913
3951
|
else
|
|
3914
|
-
note(
|
|
3952
|
+
note(
|
|
3953
|
+
t.label,
|
|
3954
|
+
"stale",
|
|
3955
|
+
`${t.label}: stale rness block (run ${rnessCommand()} sync)`
|
|
3956
|
+
);
|
|
3915
3957
|
}
|
|
3916
3958
|
return derive();
|
|
3917
3959
|
}
|
|
@@ -3999,7 +4041,13 @@ async function validateCommand(opts, deps = {}) {
|
|
|
3999
4041
|
return 0;
|
|
4000
4042
|
}
|
|
4001
4043
|
ui.intro(`Validate ${org}`);
|
|
4002
|
-
|
|
4044
|
+
const rootStatus = blocks.checks.find(
|
|
4045
|
+
(c) => c.label === "AGENTS.md"
|
|
4046
|
+
)?.status;
|
|
4047
|
+
const shown = blocks.checks.filter(
|
|
4048
|
+
(c) => !(c.label === "CLAUDE.md" && c.status === rootStatus)
|
|
4049
|
+
);
|
|
4050
|
+
for (const c of shown)
|
|
4003
4051
|
if (c.message === null) ui.line("current", c.label);
|
|
4004
4052
|
else if (c.status === "stale" || c.status === "malformed")
|
|
4005
4053
|
ui.error(c.message);
|
|
@@ -4215,6 +4263,11 @@ export {
|
|
|
4215
4263
|
exists,
|
|
4216
4264
|
readOrNull,
|
|
4217
4265
|
writeFileAtomic,
|
|
4266
|
+
PACKAGE_MANAGERS,
|
|
4267
|
+
isPackageManager,
|
|
4268
|
+
detectPackageManager,
|
|
4269
|
+
packageManagerVersion,
|
|
4270
|
+
installDependencies,
|
|
4218
4271
|
GitHubOAuthProvider,
|
|
4219
4272
|
githubProvider,
|
|
4220
4273
|
DEFAULT_HOST,
|
|
@@ -4259,11 +4312,6 @@ export {
|
|
|
4259
4312
|
contextCommand,
|
|
4260
4313
|
VERSION,
|
|
4261
4314
|
findDelegate,
|
|
4262
|
-
PACKAGE_MANAGERS,
|
|
4263
|
-
isPackageManager,
|
|
4264
|
-
detectPackageManager,
|
|
4265
|
-
packageManagerVersion,
|
|
4266
|
-
installDependencies,
|
|
4267
4315
|
SCAFFOLD_FILES,
|
|
4268
4316
|
scaffoldDir,
|
|
4269
4317
|
copyScaffold,
|
|
@@ -4279,4 +4327,4 @@ export {
|
|
|
4279
4327
|
OWN_COMMANDS,
|
|
4280
4328
|
catchUp
|
|
4281
4329
|
};
|
|
4282
|
-
//# sourceMappingURL=chunk-
|
|
4330
|
+
//# sourceMappingURL=chunk-7TOHFPW6.js.map
|