@rness/cli 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -2
- package/dist/bin/rness.js +6 -40
- package/dist/bin/rness.js.map +1 -1
- package/dist/{chunk-P4YG6P7I.js → chunk-NY3WV7X5.js} +587 -345
- package/dist/chunk-NY3WV7X5.js.map +1 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scaffold/.github/dependabot.yml +8 -0
- package/dist/chunk-P4YG6P7I.js.map +0 -1
package/README.md
CHANGED
|
@@ -6,8 +6,12 @@ Not an agent — no LLM loop.
|
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
|
-
npm create rness #
|
|
9
|
+
npm create rness # asks how to start: a GitHub organization, or a blank workspace
|
|
10
10
|
npm create rness acme # the organization github.com/acme, no first prompt
|
|
11
|
+
pnpm create rness demo --blank # ./demo with no GitHub step; npm: npm create rness demo -- --blank
|
|
12
|
+
pnpm create rness # the same with pnpm, yarn or bun: `.rness/` is
|
|
13
|
+
yarn create rness # installed with the manager that ran the command
|
|
14
|
+
bun create rness
|
|
11
15
|
npm i -g @rness/cli # the command is `rness`
|
|
12
16
|
npx @rness/cli --help
|
|
13
17
|
|
|
@@ -17,6 +21,7 @@ Inside a workspace, every `rness` delegates to the copy pinned in
|
|
|
17
21
|
## Commands
|
|
18
22
|
|
|
19
23
|
rness create [<org>] [--repos a,b] [--pm npm|pnpm|yarn|bun] [--ssh|--https] [--skip-install] -y
|
|
24
|
+
rness create <name> --blank [--pm npm|pnpm|yarn|bun] [--skip-install] -y
|
|
20
25
|
rness add <repo> [--scopes apps/web,packages/ui] [--ssh|--https] -y
|
|
21
26
|
rness sync [--all] [--scope <name>] [--check] [--pull] -y
|
|
22
27
|
rness upgrade [<version>] -y
|
|
@@ -29,6 +34,12 @@ Inside a workspace, every `rness` delegates to the copy pinned in
|
|
|
29
34
|
confirmation in a terminal; pass `-y`/`--yes` in scripts. `sync --check`
|
|
30
35
|
writes nothing and exits 1 when a block is out of date — use it in CI.
|
|
31
36
|
|
|
37
|
+
`create --blank` needs no GitHub organization, account or login: it writes
|
|
38
|
+
`<name>/.rness/` (a `rness.json` without `"org"`, committed), an empty
|
|
39
|
+
`<name>/org/` and the root `AGENTS.md` and `CLAUDE.md`. Only the install of
|
|
40
|
+
`.rness/` goes to the network. Bring repositories in with
|
|
41
|
+
`rness add <owner>/<repo>` or a git URL — a bare name needs an `"org"`.
|
|
42
|
+
|
|
32
43
|
### Log in
|
|
33
44
|
|
|
34
45
|
rness login # shows a code and https://github.com/login/device
|
|
@@ -110,11 +121,20 @@ clean — and carries on: nothing to remember, nothing to run.
|
|
|
110
121
|
container image, or a machine that cannot install. A workspace still on 0.5.0
|
|
111
122
|
has no such catch-up: moving it to 0.5.1 is the last manual install.
|
|
112
123
|
|
|
124
|
+
The catch-up needs one of two things: a launcher — the `rness` you typed,
|
|
125
|
+
usually the global install — at 0.5.1 or later, or an installed copy at 0.5.3
|
|
126
|
+
or later, which checks for itself whatever launched it. With an older global
|
|
127
|
+
and a workspace below 0.5.3, a pin that moved is neither installed nor
|
|
128
|
+
announced: `npm i -g @rness/cli@latest` once.
|
|
129
|
+
|
|
113
130
|
Usually nobody runs `upgrade` at all. A workspace ships
|
|
114
131
|
`.github/dependabot.yml`, so each release opens a pull request on the
|
|
115
132
|
organization's `.rness`: the pin and the lockfile in the diff, `validate`
|
|
116
133
|
running on the new version, review, merge. `upgrade` writes that file into
|
|
117
|
-
workspaces created before 0.5.1.
|
|
134
|
+
workspaces created before 0.5.1. The pull request arrives 3 to 10 days after
|
|
135
|
+
a release: the check is weekly, and Dependabot holds any new version back for
|
|
136
|
+
3 days by default, a guard against a compromised release. The file's header
|
|
137
|
+
says how to lift that delay for `@rness/cli`.
|
|
118
138
|
|
|
119
139
|
`upgrade` is never delegated to the pinned copy, which is what it replaces
|
|
120
140
|
— so a workspace pinned below 0.5.0, whose copy has no such command, starts
|
|
@@ -127,6 +147,41 @@ its content does.
|
|
|
127
147
|
Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
|
|
128
148
|
`RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
|
|
129
149
|
|
|
150
|
+
## 0.6.0 — a workspace without GitHub
|
|
151
|
+
|
|
152
|
+
- `rness create <name> --blank` writes `<name>/.rness/` (a `rness.json`
|
|
153
|
+
without `"org"`, committed), an empty `<name>/org/` and the root
|
|
154
|
+
`AGENTS.md` and `CLAUDE.md`, with no login, SSH test or GitHub request.
|
|
155
|
+
With `npm create`, flags go after `--`: `npm create rness demo -- --blank`.
|
|
156
|
+
- In a terminal, `create` with no organization and no `--repos` first asks
|
|
157
|
+
how to start: from a GitHub organization, as before, or a blank local
|
|
158
|
+
workspace.
|
|
159
|
+
- A `rness.json` without `"org"` is no longer a warning in `sync`, `add` and
|
|
160
|
+
`validate`. In such a workspace `rness add <repo>` exits 2 and asks for
|
|
161
|
+
`<owner>/<repo>` or a git URL: it used to take the directory name as the
|
|
162
|
+
owner, a repository that almost never exists.
|
|
163
|
+
- The next steps `create` prints are written with the package manager that
|
|
164
|
+
ran it: `npx @rness/cli`, `pnpm dlx @rness/cli`, `yarn dlx @rness/cli`
|
|
165
|
+
(npx on Yarn 1), `bunx @rness/cli`, and `<pm> create rness <org>` for
|
|
166
|
+
teammates. They said `rness …`, a command `npm create` never installs.
|
|
167
|
+
- Blocks are unchanged: no `rness sync` is needed after upgrading.
|
|
168
|
+
|
|
169
|
+
## 0.5.3 — catching up no longer depends on the global install
|
|
170
|
+
|
|
171
|
+
- After a pull that moved the pin, the next `rness` command installs it. That
|
|
172
|
+
check ran in the launcher only, so a global `@rness/cli` below 0.5.1 — which
|
|
173
|
+
delegates to the installed copy without looking — left the old version in
|
|
174
|
+
place and said nothing: `sync --check` answered `unchanged` with 0.5.1
|
|
175
|
+
blocks under a 0.5.2 pin. The installed copy now checks as well.
|
|
176
|
+
- Reach: the check lives in the installed copy, so it works from the first pin
|
|
177
|
+
move after a workspace holds 0.5.3. The move to 0.5.3 itself still needs a
|
|
178
|
+
launcher at 0.5.1 or later.
|
|
179
|
+
- The scaffold's `dependabot.yml` says why the pin's pull request arrives 3 to
|
|
180
|
+
10 days after a release (a weekly check, plus Dependabot's default 3-day
|
|
181
|
+
cooldown) and gives the three lines that lift it for `@rness/cli`. The
|
|
182
|
+
default stays: for an adopting organization the CLI is a third-party
|
|
183
|
+
package, and the cooldown guards against a compromised release.
|
|
184
|
+
|
|
130
185
|
## 0.5.2 — the block points at a file that exists
|
|
131
186
|
|
|
132
187
|
- The generated block told agents to read `.rness/STATUS.md`, a file neither
|
package/dist/bin/rness.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
OWN_COMMANDS,
|
|
3
4
|
VERSION,
|
|
4
|
-
|
|
5
|
-
ensureInstalled,
|
|
5
|
+
catchUp,
|
|
6
6
|
findDelegate,
|
|
7
|
-
findWorkspace,
|
|
8
|
-
pinDrift,
|
|
9
|
-
pinnedBinPath,
|
|
10
7
|
reportError,
|
|
11
8
|
run
|
|
12
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-NY3WV7X5.js";
|
|
13
10
|
|
|
14
11
|
// src/bin/rness.ts
|
|
15
|
-
import { spawnSync } from "child_process";
|
|
16
12
|
import { pathToFileURL } from "url";
|
|
17
13
|
|
|
18
14
|
// src/core/node-version.ts
|
|
@@ -39,39 +35,9 @@ async function main() {
|
|
|
39
35
|
return 1;
|
|
40
36
|
}
|
|
41
37
|
const argv = process.argv.slice(2);
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"update",
|
|
46
|
-
"login",
|
|
47
|
-
"logout",
|
|
48
|
-
"git-credential"
|
|
49
|
-
].includes(argv[0] ?? "");
|
|
50
|
-
const noDelegate = process.env["RNESS_NO_DELEGATE"] === "1";
|
|
51
|
-
const skipDelegation = own || noDelegate;
|
|
52
|
-
const command = argv[0];
|
|
53
|
-
if (command !== void 0 && !command.startsWith("-") && !skipDelegation) {
|
|
54
|
-
const ws = await findWorkspace(process.cwd()).catch(() => null);
|
|
55
|
-
const outcome = ws === null ? null : await ensureInstalled(ws.rnessDir, {
|
|
56
|
-
announce: (pin) => process.stderr.write(`installing @rness/cli ${pin} in .rness\u2026
|
|
57
|
-
`)
|
|
58
|
-
});
|
|
59
|
-
if (outcome !== null && !outcome.installed) {
|
|
60
|
-
const warning = await driftWarning(process.cwd());
|
|
61
|
-
if (warning !== null) process.stderr.write(`${warning}
|
|
62
|
-
`);
|
|
63
|
-
}
|
|
64
|
-
if (ws !== null && outcome?.installed === true && await pinDrift(ws.rnessDir) === null) {
|
|
65
|
-
const pinnedBin = await pinnedBinPath(ws.rnessDir);
|
|
66
|
-
if (pinnedBin !== null) {
|
|
67
|
-
const { status } = spawnSync(process.execPath, [pinnedBin, ...argv], {
|
|
68
|
-
cwd: process.cwd(),
|
|
69
|
-
stdio: "inherit"
|
|
70
|
-
});
|
|
71
|
-
return status ?? 1;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
38
|
+
const skipDelegation = OWN_COMMANDS.includes(argv[0] ?? "") || process.env["RNESS_NO_DELEGATE"] === "1";
|
|
39
|
+
const handedOff = await catchUp(argv);
|
|
40
|
+
if (handedOff !== null) return handedOff;
|
|
75
41
|
const delegate = skipDelegation ? null : await findDelegate(process.cwd(), VERSION);
|
|
76
42
|
if (delegate !== null) {
|
|
77
43
|
const broken = (reason) => new Error(
|
package/dist/bin/rness.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/bin/rness.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { pathToFileURL } from 'node:url'\n\nimport { run } from '../cli.ts'\nimport { OWN_COMMANDS, catchUp } from '../core/catch-up.ts'\nimport { findDelegate } from '../core/delegate.ts'\nimport { MIN_NODE_MAJOR, isSupportedNode } from '../core/node-version.ts'\nimport { reportError } from '../report.ts'\nimport { VERSION } from '../version.ts'\n\n// `rness context | head`: once the reader has its lines it closes the pipe and\n// every further write emits EPIPE on stdout. Nothing is left to deliver, so end\n// quietly with success. This is the one process.exit() in the code base — it\n// runs only when there is no output left to drain (see main() below).\nprocess.stdout.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'EPIPE') process.exit(0)\n throw e\n})\n\n// Set process.exitCode rather than calling process.exit(): process.exit()\n// terminates before Node drains an async stdout pipe, truncating piped output\n// at the ~64 KiB pipe buffer (breaks `rness context --json | jq`, `$(...)`).\nasync function main(): Promise<number> {\n if (!isSupportedNode(process.versions.node)) {\n process.stderr.write(\n `rness needs Node ${MIN_NODE_MAJOR} or newer (running ${process.version})\\n`\n )\n return 1\n }\n const argv = process.argv.slice(2)\n const skipDelegation =\n OWN_COMMANDS.includes(argv[0] ?? '') ||\n process.env['RNESS_NO_DELEGATE'] === '1'\n // A pin that moved is installed first, and the fresh copy runs the command\n // as its own process (spec 0008 §4).\n const handedOff = await catchUp(argv)\n if (handedOff !== null) return handedOff\n const delegate = skipDelegation\n ? null\n : await findDelegate(process.cwd(), VERSION)\n if (delegate !== null) {\n const broken = (reason: string): Error =>\n new Error(\n `@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`\n )\n if (process.env['RNESS_DEBUG'] === '1') {\n process.stderr.write(\n `rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})\\n`\n )\n }\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(delegate.entry).href)) as Record<\n string,\n unknown\n >\n } catch (e) {\n throw broken(e instanceof Error ? e.message : String(e))\n }\n if (typeof mod['run'] !== 'function')\n throw broken('dist/index.js does not export run')\n const delegateRun = mod['run'] as (argv: string[]) => Promise<unknown>\n const code = await delegateRun(argv)\n return typeof code === 'number' ? code : 1\n }\n return run(argv)\n}\n\nmain()\n .then((code) => {\n process.exitCode = code\n })\n .catch((e: unknown) => {\n process.exitCode = reportError(e)\n })\n","export const MIN_NODE_MAJOR = 24\n\nexport function nodeMajor(version: string): number {\n const major = Number.parseInt(version.split('.')[0] ?? '', 10)\n return Number.isNaN(major) ? 0 : major\n}\n\nexport function isSupportedNode(version: string): boolean {\n return nodeMajor(version) >= MIN_NODE_MAJOR\n}\n"],"mappings":";;;;;;;;;;;AACA,SAAS,qBAAqB;;;ACDvB,IAAM,iBAAiB;AAEvB,SAAS,UAAU,SAAyB;AACjD,QAAM,QAAQ,OAAO,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE;AAC7D,SAAO,OAAO,MAAM,KAAK,IAAI,IAAI;AACnC;AAEO,SAAS,gBAAgB,SAA0B;AACxD,SAAO,UAAU,OAAO,KAAK;AAC/B;;;ADKA,QAAQ,OAAO,GAAG,SAAS,CAAC,MAA6B;AACvD,MAAI,EAAE,SAAS,QAAS,SAAQ,KAAK,CAAC;AACtC,QAAM;AACR,CAAC;AAKD,eAAe,OAAwB;AACrC,MAAI,CAAC,gBAAgB,QAAQ,SAAS,IAAI,GAAG;AAC3C,YAAQ,OAAO;AAAA,MACb,oBAAoB,cAAc,sBAAsB,QAAQ,OAAO;AAAA;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AACA,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,QAAM,iBACJ,aAAa,SAAS,KAAK,CAAC,KAAK,EAAE,KACnC,QAAQ,IAAI,mBAAmB,MAAM;AAGvC,QAAM,YAAY,MAAM,QAAQ,IAAI;AACpC,MAAI,cAAc,KAAM,QAAO;AAC/B,QAAM,WAAW,iBACb,OACA,MAAM,aAAa,QAAQ,IAAI,GAAG,OAAO;AAC7C,MAAI,aAAa,MAAM;AACrB,UAAM,SAAS,CAAC,WACd,IAAI;AAAA,MACF,cAAc,SAAS,OAAO,cAAc,SAAS,IAAI,uCAAuC,MAAM;AAAA,IACxG;AACF,QAAI,QAAQ,IAAI,aAAa,MAAM,KAAK;AACtC,cAAQ,OAAO;AAAA,QACb,mCAAmC,SAAS,OAAO,KAAK,SAAS,KAAK;AAAA;AAAA,MACxE;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,YAAO,MAAM,OAAO,cAAc,SAAS,KAAK,EAAE;AAAA,IAIpD,SAAS,GAAG;AACV,YAAM,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACzD;AACA,QAAI,OAAO,IAAI,KAAK,MAAM;AACxB,YAAM,OAAO,mCAAmC;AAClD,UAAM,cAAc,IAAI,KAAK;AAC7B,UAAM,OAAO,MAAM,YAAY,IAAI;AACnC,WAAO,OAAO,SAAS,WAAW,OAAO;AAAA,EAC3C;AACA,SAAO,IAAI,IAAI;AACjB;AAEA,KAAK,EACF,KAAK,CAAC,SAAS;AACd,UAAQ,WAAW;AACrB,CAAC,EACA,MAAM,CAAC,MAAe;AACrB,UAAQ,WAAW,YAAY,CAAC;AAClC,CAAC;","names":[]}
|