@rness/cli 0.3.0 → 0.4.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 CHANGED
@@ -6,6 +6,7 @@ Not an agent — no LLM loop.
6
6
 
7
7
  ## Install
8
8
 
9
+ npm create rness <org> # start a workspace for github.com/<org>, or join its .rness
9
10
  npm i -g @rness/cli # the command is `rness`
10
11
  npx @rness/cli --help
11
12
 
@@ -14,14 +15,31 @@ Inside a workspace, every `rness` delegates to the copy pinned in
14
15
 
15
16
  ## Commands
16
17
 
17
- rness context [--scope <name>] [--json] Resolve the context for a scope
18
- rness validate Check .rness/ and every generated block
19
- rness sync [--scope <name>] [--check] [--pull] -y Clone repositories, write the blocks
18
+ rness create <org> [--dir <path>] [--repos a,b] [--pm npm|pnpm|yarn|bun] [--ssh] [--skip-install] -y
19
+ rness add <repo> [--scopes apps/web,packages/ui] [--ssh] -y
20
+ rness sync [--scope <name>] [--check] [--pull] -y
21
+ rness context [--scope <name>] [--json]
22
+ rness validate
20
23
 
21
- Exit codes: 0 success, 1 handled error, 2 bad usage. `RNESS_DEBUG=1` adds
22
- stack traces; `RNESS_NO_DELEGATE=1` skips the delegation. `sync` asks for
23
- confirmation in a terminal; pass `-y`/`--yes` in scripts. `--check` writes
24
- nothing and exits 1 when a block is out of date — use it in CI.
24
+ `create` never runs inside a workspace. `add`, `sync` and `create` ask for
25
+ confirmation in a terminal; pass `-y`/`--yes` in scripts. `sync --check`
26
+ writes nothing and exits 1 when a block is out of date — use it in CI.
27
+
28
+ Exit codes: 0 success, 1 failure, 2 usage — or a refusal without a TTY.
29
+ `RNESS_DEBUG=1` adds stack traces; `RNESS_NO_DELEGATE=1` skips the delegation.
30
+
31
+ ## 0.4.0 — create, add, the shims
32
+
33
+ - `npm create rness <org>` starts a new workspace for `github.com/<org>` or
34
+ joins its existing `.rness`.
35
+ - `rness add <repo>` clones (or adopts) a repository under `org/`, declares
36
+ it and any `--scopes` sub-directories, then syncs.
37
+ - `create-rness` and `@rness/create` are two-file shims pinned to the exact
38
+ same version as `@rness/cli`, so the short `npm create` commands run this
39
+ CLI.
40
+ - A new workspace's scaffold ships a `pnpm-workspace.yaml`
41
+ (`minimumReleaseAgeExclude: ['@rness/cli']`) — pnpm 12 otherwise refuses a
42
+ version published less than 24h earlier.
25
43
 
26
44
  ## 0.3.0 — what changed for a 0.2.0 workspace
27
45
 
package/dist/bin/rness.js CHANGED
@@ -1,38 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  VERSION,
4
- findWorkspace,
4
+ findDelegate,
5
5
  reportError,
6
6
  run
7
- } from "../chunk-4KNZT4G4.js";
7
+ } from "../chunk-IW5IHSPC.js";
8
8
 
9
9
  // src/bin/rness.ts
10
10
  import { pathToFileURL } from "url";
11
11
 
12
- // src/core/delegate.ts
13
- import { readFile } from "fs/promises";
14
- import { join } from "path";
15
- async function findDelegate(cwd, ownVersion) {
16
- let root;
17
- let rnessDir;
18
- try {
19
- const ws = await findWorkspace(cwd);
20
- root = ws.root;
21
- rnessDir = ws.rnessDir;
22
- } catch {
23
- return null;
24
- }
25
- const pkgDir = join(rnessDir, "node_modules", "@rness", "cli");
26
- let version;
27
- try {
28
- version = JSON.parse(await readFile(join(pkgDir, "package.json"), "utf8")).version;
29
- } catch {
30
- return null;
31
- }
32
- if (typeof version !== "string" || version === ownVersion) return null;
33
- return { entry: join(pkgDir, "dist", "index.js"), version, root };
34
- }
35
-
36
12
  // src/core/node-version.ts
37
13
  var MIN_NODE_MAJOR = 24;
38
14
  function nodeMajor(version) {
@@ -50,18 +26,24 @@ process.stdout.on("error", (e) => {
50
26
  });
51
27
  async function main() {
52
28
  if (!isSupportedNode(process.versions.node)) {
53
- process.stderr.write(`rness needs Node ${MIN_NODE_MAJOR} or newer (running ${process.version})
54
- `);
29
+ process.stderr.write(
30
+ `rness needs Node ${MIN_NODE_MAJOR} or newer (running ${process.version})
31
+ `
32
+ );
55
33
  return 1;
56
34
  }
57
35
  const argv = process.argv.slice(2);
58
36
  const skipDelegation = argv[0] === "create" || process.env["RNESS_NO_DELEGATE"] === "1";
59
37
  const delegate = skipDelegation ? null : await findDelegate(process.cwd(), VERSION);
60
38
  if (delegate !== null) {
61
- const broken = (reason) => new Error(`@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`);
39
+ const broken = (reason) => new Error(
40
+ `@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`
41
+ );
62
42
  if (process.env["RNESS_DEBUG"] === "1") {
63
- process.stderr.write(`rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})
64
- `);
43
+ process.stderr.write(
44
+ `rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})
45
+ `
46
+ );
65
47
  }
66
48
  let mod;
67
49
  try {
@@ -69,7 +51,8 @@ async function main() {
69
51
  } catch (e) {
70
52
  throw broken(e instanceof Error ? e.message : String(e));
71
53
  }
72
- if (typeof mod["run"] !== "function") throw broken("dist/index.js does not export run");
54
+ if (typeof mod["run"] !== "function")
55
+ throw broken("dist/index.js does not export run");
73
56
  const delegateRun = mod["run"];
74
57
  const code = await delegateRun(argv);
75
58
  return typeof code === "number" ? code : 1;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/rness.ts","../../src/core/delegate.ts","../../src/core/node-version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { pathToFileURL } from 'node:url'\nimport { run } from '../cli.ts'\nimport { VERSION } from '../version.ts'\nimport { findDelegate } from '../core/delegate.ts'\nimport { isSupportedNode, MIN_NODE_MAJOR } from '../core/node-version.ts'\nimport { reportError } from '../report.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(`rness needs Node ${MIN_NODE_MAJOR} or newer (running ${process.version})\\n`)\n return 1\n }\n const argv = process.argv.slice(2)\n const skipDelegation = argv[0] === 'create' || process.env['RNESS_NO_DELEGATE'] === '1'\n const delegate = skipDelegation ? null : await findDelegate(process.cwd(), VERSION)\n if (delegate !== null) {\n const broken = (reason: string): Error =>\n new Error(`@rness/cli ${delegate.version} pinned in ${delegate.root}/.rness is not installed correctly (${reason}); reinstall in .rness/`)\n if (process.env['RNESS_DEBUG'] === '1') {\n process.stderr.write(`rness: delegating to @rness/cli ${delegate.version} (${delegate.entry})\\n`)\n }\n let mod: Record<string, unknown>\n try {\n mod = (await import(pathToFileURL(delegate.entry).href)) as Record<string, unknown>\n } catch (e) {\n throw broken(e instanceof Error ? e.message : String(e))\n }\n if (typeof mod['run'] !== 'function') 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","import { readFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { findWorkspace } from './workspace.ts'\n\nexport interface Delegate {\n /** Absolute path of the pinned copy's `dist/index.js`. */\n entry: string\n version: string\n /** Workspace root (the directory holding `.rness/`). */\n root: string\n}\n\n/**\n * The `@rness/cli` pinned in `<workspace>/.rness/package.json` (installed under\n * `.rness/node_modules`), when it exists and is not the running version. The\n * pinned copy is the only one that should ever act on a workspace.\n */\nexport async function findDelegate(cwd: string, ownVersion: string): Promise<Delegate | null> {\n let root: string\n let rnessDir: string\n try {\n const ws = await findWorkspace(cwd)\n root = ws.root\n rnessDir = ws.rnessDir\n } catch {\n return null\n }\n const pkgDir = join(rnessDir, 'node_modules', '@rness', 'cli')\n let version: unknown\n try {\n version = (JSON.parse(await readFile(join(pkgDir, 'package.json'), 'utf8')) as { version?: unknown }).version\n } catch {\n return null\n }\n if (typeof version !== 'string' || version === ownVersion) return null\n return { entry: join(pkgDir, 'dist', 'index.js'), version, root }\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;;;ACD9B,SAAS,gBAAgB;AACzB,SAAS,YAAY;AAgBrB,eAAsB,aAAa,KAAa,YAA8C;AAC5F,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,cAAc,GAAG;AAClC,WAAO,GAAG;AACV,eAAW,GAAG;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,SAAS,KAAK,UAAU,gBAAgB,UAAU,KAAK;AAC7D,MAAI;AACJ,MAAI;AACF,cAAW,KAAK,MAAM,MAAM,SAAS,KAAK,QAAQ,cAAc,GAAG,MAAM,CAAC,EAA4B;AAAA,EACxG,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,OAAO,YAAY,YAAY,YAAY,WAAY,QAAO;AAClE,SAAO,EAAE,OAAO,KAAK,QAAQ,QAAQ,UAAU,GAAG,SAAS,KAAK;AAClE;;;ACpCO,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;;;AFGA,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,MAAM,oBAAoB,cAAc,sBAAsB,QAAQ,OAAO;AAAA,CAAK;AACjG,WAAO;AAAA,EACT;AACA,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,QAAM,iBAAiB,KAAK,CAAC,MAAM,YAAY,QAAQ,IAAI,mBAAmB,MAAM;AACpF,QAAM,WAAW,iBAAiB,OAAO,MAAM,aAAa,QAAQ,IAAI,GAAG,OAAO;AAClF,MAAI,aAAa,MAAM;AACrB,UAAM,SAAS,CAAC,WACd,IAAI,MAAM,cAAc,SAAS,OAAO,cAAc,SAAS,IAAI,uCAAuC,MAAM,yBAAyB;AAC3I,QAAI,QAAQ,IAAI,aAAa,MAAM,KAAK;AACtC,cAAQ,OAAO,MAAM,mCAAmC,SAAS,OAAO,KAAK,SAAS,KAAK;AAAA,CAAK;AAAA,IAClG;AACA,QAAI;AACJ,QAAI;AACF,YAAO,MAAM,OAAO,cAAc,SAAS,KAAK,EAAE;AAAA,IACpD,SAAS,GAAG;AACV,YAAM,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACzD;AACA,QAAI,OAAO,IAAI,KAAK,MAAM,WAAY,OAAM,OAAO,mCAAmC;AACtF,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":[]}
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 { 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 argv[0] === 'create' || process.env['RNESS_NO_DELEGATE'] === '1'\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;;;ADIA,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,KAAK,CAAC,MAAM,YAAY,QAAQ,IAAI,mBAAmB,MAAM;AAC/D,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":[]}