@guiho/runx 0.2.6 → 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.
Files changed (92) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/DOCS.md +128 -109
  3. package/README.md +58 -58
  4. package/devops/build-binaries.ts +44 -62
  5. package/devops/devops.xdocs.md +8 -5
  6. package/devops/install.ps1 +182 -152
  7. package/devops/install.sh +197 -262
  8. package/devops/installers.spec.ts +31 -0
  9. package/devops/verify-release-assets.ts +17 -0
  10. package/docs/decisions/decisions.xdocs.md +4 -0
  11. package/docs/decisions/interactive-init-manifest.md +187 -0
  12. package/docs/docs.xdocs.md +3 -1
  13. package/docs/plans/interactive-init-manifest.md +177 -0
  14. package/docs/plans/plans.xdocs.md +11 -0
  15. package/docs/plans/rfc-0034-cli-compliance-migration.md +586 -0
  16. package/docs/plans/upgrade-reliability-implementation.md +95 -0
  17. package/docs/reviews/implementation/implementation.xdocs.md +6 -0
  18. package/docs/reviews/implementation/interactive-init-manifest-review.md +69 -0
  19. package/docs/reviews/implementation/rfc-0034-cli-compliance-migration-review.md +59 -0
  20. package/docs/reviews/plans/interactive-init-manifest-review.md +82 -0
  21. package/docs/reviews/plans/plans.xdocs.md +10 -0
  22. package/docs/reviews/plans/rfc-0034-cli-compliance-migration-review.md +80 -0
  23. package/docs/reviews/plans/upgrade-reliability-implementation-review.md +65 -0
  24. package/docs/superpowers/specs/2026-07-15-upgrade-reliability-design.md +662 -0
  25. package/docs/superpowers/specs/specs.xdocs.md +24 -0
  26. package/docs/superpowers/superpowers.xdocs.md +21 -0
  27. package/docs/todo/rfc-0034-cli-compliance-migration-implementation.md +58 -0
  28. package/docs/todo/rfc-0034-cli-compliance-migration.md +151 -0
  29. package/docs/todo/todo.xdocs.md +6 -2
  30. package/docs/validation/interactive-init-manifest.md +79 -0
  31. package/docs/validation/rfc-0034-cli-compliance-migration.md +67 -0
  32. package/docs/validation/upgrade-reliability.md +124 -0
  33. package/docs/validation/validation.xdocs.md +9 -0
  34. package/library/agents.d.ts +28 -4
  35. package/library/agents.d.ts.map +1 -1
  36. package/library/agents.js +143 -41
  37. package/library/cli.d.ts.map +1 -1
  38. package/library/cli.js +297 -317
  39. package/library/configuration.d.ts +57 -0
  40. package/library/configuration.d.ts.map +1 -0
  41. package/library/configuration.js +111 -0
  42. package/library/embedded-resources.d.ts +6 -1
  43. package/library/embedded-resources.d.ts.map +1 -1
  44. package/library/embedded-resources.js +10 -4
  45. package/library/executor.d.ts +5 -1
  46. package/library/executor.d.ts.map +1 -1
  47. package/library/executor.js +10 -10
  48. package/library/help.d.ts +8 -4
  49. package/library/help.d.ts.map +1 -1
  50. package/library/help.js +70 -42
  51. package/library/init.d.ts +18 -0
  52. package/library/init.d.ts.map +1 -0
  53. package/library/init.js +43 -0
  54. package/library/manifest.d.ts +4 -40
  55. package/library/manifest.d.ts.map +1 -1
  56. package/library/manifest.js +4 -112
  57. package/library/path-utils.d.ts +13 -0
  58. package/library/path-utils.d.ts.map +1 -0
  59. package/library/path-utils.js +82 -0
  60. package/library/recovery.d.ts +7 -0
  61. package/library/recovery.d.ts.map +1 -0
  62. package/library/recovery.js +23 -0
  63. package/library/release-catalog.d.ts +32 -0
  64. package/library/release-catalog.d.ts.map +1 -0
  65. package/library/release-catalog.js +124 -0
  66. package/library/self-management.d.ts +24 -4
  67. package/library/self-management.d.ts.map +1 -1
  68. package/library/self-management.js +279 -99
  69. package/library/storage.d.ts +13 -0
  70. package/library/storage.d.ts.map +1 -0
  71. package/library/storage.js +38 -0
  72. package/library/types.d.ts +11 -16
  73. package/library/types.d.ts.map +1 -1
  74. package/library/types.js +3 -0
  75. package/library/update-cache.d.ts +21 -0
  76. package/library/update-cache.d.ts.map +1 -0
  77. package/library/update-cache.js +68 -0
  78. package/library/upgrade-reporting.d.ts +11 -0
  79. package/library/upgrade-reporting.d.ts.map +1 -0
  80. package/library/upgrade-reporting.js +67 -0
  81. package/library/upgrade-types.d.ts +72 -0
  82. package/library/upgrade-types.d.ts.map +1 -0
  83. package/library/upgrade-types.js +3 -0
  84. package/package.json +6 -3
  85. package/scripts/runx-bin.mjs +49 -0
  86. package/scripts/runx-bin.spec.ts +62 -0
  87. package/scripts/scripts.xdocs.md +3 -3
  88. package/skills/guiho-s-runx/SKILL.md +64 -59
  89. package/skills/guiho-s-runx/guiho-s-runx.xdocs.md +7 -4
  90. package/skills/skills.xdocs.md +1 -1
  91. package/docs/todo/implement-runx-alpha.md +0 -36
  92. package/scripts/runx-bin.ts +0 -24
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-reporting.d.ts","sourceRoot":"","sources":["../source/upgrade-reporting.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAwB,cAAc,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAE1H,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,CAAA;AAED,QAAA,MAAM,oBAAoB,QAAO,MAId,CAAA;AAEnB,QAAA,MAAM,iBAAiB,SAAU,WAAW,KAAG,MAS5B,CAAA;AAEnB,QAAA,MAAM,kBAAkB,UAAW,YAAY,KAAG,MAWjD,CAAA;AAED,QAAA,MAAM,mBAAmB,WAAY,eAAe,KAAG,MAWtD,CAAA;AAYD,QAAA,MAAM,oBAAoB,YAAa,cAAc,KAAG,MAavD,CAAA"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
3
+ */
4
+ export { renderReleaseCatalog, renderUpgradeEvent, renderUpgradeHeading, renderUpgradePlan, renderUpgradeResult, };
5
+ const renderUpgradeHeading = () => [
6
+ '------------------------------------------------------------',
7
+ ' Upgrading the CLI',
8
+ '------------------------------------------------------------',
9
+ ].join('\n') + '\n';
10
+ const renderUpgradePlan = (plan) => [
11
+ ` current : ${plan.currentVersion}`,
12
+ ` target : ${plan.targetVersion}`,
13
+ ` os : ${plan.os}`,
14
+ ` arch : ${plan.arch}`,
15
+ ` binary : ${plan.assetName}`,
16
+ ` path : ${plan.executablePath.replaceAll('\\', '/')}`,
17
+ ` url : ${plan.assetUrl}`,
18
+ '------------------------------------------------------------',
19
+ ].join('\n') + '\n';
20
+ const renderUpgradeEvent = (event) => {
21
+ if (event.status !== 'started' || event.phase === 'plan')
22
+ return '';
23
+ const labels = {
24
+ download: 'Downloading...',
25
+ validate: 'Validating...',
26
+ replace: 'Replacing...',
27
+ verify: 'Verifying...',
28
+ cleanup: 'Cleaning up...',
29
+ };
30
+ const label = labels[event.phase];
31
+ return label ? `${label}\n` : '';
32
+ };
33
+ const renderUpgradeResult = (result) => {
34
+ const summary = result.outcome === 'upgraded'
35
+ ? `Upgrade complete: ${result.plan?.currentVersion} -> ${result.plan?.targetVersion}`
36
+ : result.outcome === 'up-to-date'
37
+ ? `Already up to date: ${result.result?.installedVersion ?? result.recovery.targetVersion}`
38
+ : result.outcome === 'dry-run'
39
+ ? `Dry run complete: ${result.plan?.currentVersion} -> ${result.plan?.targetVersion}`
40
+ : result.outcome === 'rolled-back'
41
+ ? `Upgrade failed during ${result.error?.phase ?? 'replace'}; restored RunX ${result.result?.installedVersion ?? result.recovery.targetVersion}.`
42
+ : `Upgrade failed during ${result.error?.phase ?? 'plan'}.`;
43
+ return `${summary}\n\n${renderRecovery(result.recovery, result.outcome === 'failed' || result.outcome === 'rolled-back')}\n`;
44
+ };
45
+ const renderRecovery = (recovery, repair) => [
46
+ recovery.targetSource === 'fallback-current'
47
+ ? `Repair reinstall (target lookup failed; pinned to installed RunX ${recovery.targetVersion}):`
48
+ : `${repair ? 'To repair RunX' : 'If the new version is not active'}, install RunX ${recovery.targetVersion} directly:`,
49
+ ` ${recovery.installCommand}`,
50
+ '',
51
+ 'If RunX is still running and blocks installation, stop it first:',
52
+ ` ${recovery.stopProcessCommand}`,
53
+ ].join('\n');
54
+ const renderReleaseCatalog = (catalog) => {
55
+ const headers = ['VERSION', 'CHANNEL', 'PUBLISHED', 'CURRENT', 'LATEST', 'ASSET'];
56
+ const rows = catalog.releases.map((release) => [
57
+ release.version,
58
+ release.channel,
59
+ release.publishedAt?.slice(0, 10) ?? '-',
60
+ release.current ? 'yes' : '',
61
+ release.latestStable ? 'yes' : '',
62
+ release.compatibleAsset ? 'yes' : 'no',
63
+ ]);
64
+ const widths = headers.map((header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0)));
65
+ const line = (values) => values.map((value, index) => value.padEnd(widths[index] ?? value.length)).join(' ').trimEnd();
66
+ return ['AVAILABLE RUNX VERSIONS', '', line(headers), ...rows.map(line)].join('\n') + '\n';
67
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
3
+ */
4
+ export type UpgradeOs = 'windows' | 'darwin' | 'linux';
5
+ export type UpgradeArch = 'x64' | 'arm64';
6
+ export type UpgradeVariant = 'baseline' | 'default' | 'modern';
7
+ export type ReleaseAsset = {
8
+ name: string;
9
+ url: string;
10
+ };
11
+ export type ReleaseCatalogEntry = {
12
+ tag: string;
13
+ version: string;
14
+ channel: string;
15
+ prerelease: boolean;
16
+ publishedAt: string | null;
17
+ current: boolean;
18
+ latestStable: boolean;
19
+ compatibleAsset: ReleaseAsset | null;
20
+ };
21
+ export type ReleaseCatalog = {
22
+ schemaVersion: 1;
23
+ command: 'runx upgrade list';
24
+ currentVersion: string;
25
+ latestStableVersion: string | null;
26
+ releases: ReleaseCatalogEntry[];
27
+ };
28
+ export type RecoveryInstructions = {
29
+ targetVersion: string;
30
+ targetSource: 'resolved' | 'fallback-current';
31
+ installCommand: string;
32
+ stopProcessCommand: string;
33
+ };
34
+ export type UpgradePlan = {
35
+ currentVersion: string;
36
+ targetVersion: string;
37
+ os: UpgradeOs;
38
+ arch: UpgradeArch;
39
+ assetName: string;
40
+ assetUrl: string;
41
+ executablePath: string;
42
+ };
43
+ export type UpgradePhase = 'plan' | 'download' | 'validate' | 'replace' | 'verify' | 'cache' | 'cleanup';
44
+ export type UpgradePhaseStatus = 'started' | 'succeeded' | 'skipped' | 'failed';
45
+ export type UpgradeEvent = {
46
+ sequence: number;
47
+ phase: UpgradePhase;
48
+ status: UpgradePhaseStatus;
49
+ message?: string;
50
+ };
51
+ export type UpgradeOutcome = 'upgraded' | 'up-to-date' | 'dry-run' | 'rolled-back' | 'failed';
52
+ export type UpgradeResult = {
53
+ installedVersion: string;
54
+ cleanupDeferred: boolean;
55
+ };
56
+ export type UpgradeErrorCode = 'release_lookup_failed' | 'release_payload_invalid' | 'no_compatible_asset' | 'download_failed' | 'download_invalid' | 'backup_failed' | 'replace_failed' | 'verification_failed' | 'rollback_failed' | 'installer_verification_failed';
57
+ export type UpgradeError = {
58
+ code: UpgradeErrorCode;
59
+ phase: UpgradePhase;
60
+ message: string;
61
+ };
62
+ export type UpgradeEnvelope = {
63
+ schemaVersion: 1;
64
+ command: 'runx upgrade';
65
+ outcome: UpgradeOutcome;
66
+ plan: UpgradePlan | null;
67
+ events: UpgradeEvent[];
68
+ result: UpgradeResult | null;
69
+ recovery: RecoveryInstructions;
70
+ error: UpgradeError | null;
71
+ };
72
+ //# sourceMappingURL=upgrade-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-types.d.ts","sourceRoot":"","sources":["../source/upgrade-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /**
2
+ * @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
3
+ */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@guiho/runx",
3
3
  "description": "A language-agnostic, documented command catalog and local CLI executor.",
4
- "version": "0.2.6",
4
+ "version": "0.4.0",
5
5
  "type": "module",
6
6
  "main": "./library/guiho-runx.js",
7
7
  "types": "./library/guiho-runx.d.ts",
@@ -12,7 +12,7 @@
12
12
  }
13
13
  },
14
14
  "bin": {
15
- "runx": "scripts/runx-bin.ts"
15
+ "runx": "scripts/runx-bin.mjs"
16
16
  },
17
17
  "files": [
18
18
  "library/",
@@ -57,6 +57,7 @@
57
57
  "build": "rm -rf library && tsc -p .",
58
58
  "binary": "bun build source/guiho-runx-native-bin.ts --compile --outfile bin/runx",
59
59
  "binaries": "bun run devops/build-binaries.ts",
60
+ "verify-assets": "bun run devops/verify-release-assets.ts",
60
61
  "test": "bun test",
61
62
  "typecheck": "tsc -p . --noEmit",
62
63
  "check": "bun run typecheck && bun test",
@@ -69,10 +70,12 @@
69
70
  },
70
71
  "dependencies": {
71
72
  "@sinclair/typebox": "^0.34.52",
72
- "citty": "^0.2.2"
73
+ "citty": "^0.2.2",
74
+ "semver": "^7.8.5"
73
75
  },
74
76
  "devDependencies": {
75
77
  "@types/bun": "^1.3.14",
78
+ "@types/semver": "^7.7.1",
76
79
  "typescript": "^7.0.2"
77
80
  }
78
81
  }
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
5
+ */
6
+
7
+ import { spawn } from 'node:child_process'
8
+ import { chmod, mkdir, rename, rm, stat, writeFile } from 'node:fs/promises'
9
+ import { arch, homedir, platform } from 'node:os'
10
+ import { join } from 'node:path'
11
+
12
+ import packageJson from '../package.json' with { type: 'json' }
13
+
14
+ const os = platform() === 'win32' ? 'windows' : platform() === 'darwin' ? 'darwin' : platform() === 'linux' ? 'linux' : null
15
+ const cpu = arch() === 'x64' ? 'x64' : arch() === 'arm64' ? 'arm64' : null
16
+ if (!os || !cpu) fail(`Unsupported platform: ${platform()} ${arch()}`)
17
+
18
+ const suffix = os === 'windows' ? '.exe' : ''
19
+ const asset = cpu === 'arm64' ? `runx-${os}-arm64${suffix}` : `runx-${os}-x64-baseline${suffix}`
20
+ const cache = process.env.RUNX_NATIVE_CACHE || join(homedir(), '.guiho', 'runx', 'npm', packageJson.version)
21
+ const executable = join(cache, `runx${suffix}`)
22
+ const tag = encodeURIComponent(`@guiho/runx@${packageJson.version}`)
23
+ const downloadBase = (process.env.RUNX_DOWNLOAD_BASE_URL || 'https://github.com/CGuiho/runx/releases/download').replace(/\/$/, '')
24
+ const url = `${downloadBase}/${tag}/${asset}`
25
+
26
+ try {
27
+ await stat(executable)
28
+ } catch {
29
+ await mkdir(cache, { recursive: true })
30
+ const response = await fetch(url, { redirect: 'follow' })
31
+ if (!response.ok) fail(`Could not download ${asset}: HTTP ${response.status}`)
32
+ const temporary = `${executable}.${process.pid}.tmp`
33
+ await writeFile(temporary, new Uint8Array(await response.arrayBuffer()), { flag: 'wx' })
34
+ if (os !== 'windows') await chmod(temporary, 0o755)
35
+ await rename(temporary, executable)
36
+ }
37
+
38
+ const child = spawn(executable, process.argv.slice(2), { env: process.env, stdio: 'inherit' })
39
+ child.once('error', (error) => fail(error.message))
40
+ child.once('exit', (code, signal) => {
41
+ if (signal) process.kill(process.pid, signal)
42
+ else process.exit(code ?? 1)
43
+ })
44
+
45
+ function fail(message) {
46
+ process.stderr.write(`error: ${message}\n`)
47
+ void rm(executable, { force: true }).catch(() => undefined)
48
+ process.exit(1)
49
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @copyright Copyright © 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
3
+ */
4
+
5
+ import { afterEach, expect, test } from 'bun:test'
6
+ import { mkdtemp, rm } from 'node:fs/promises'
7
+ import { tmpdir } from 'node:os'
8
+ import { join } from 'node:path'
9
+
10
+ let directory = ''
11
+
12
+ afterEach(async () => {
13
+ if (directory) await rm(directory, { recursive: true, force: true })
14
+ directory = ''
15
+ })
16
+
17
+ test('packed npm bootstrap downloads and delegates with Node while Bun is absent from PATH', async () => {
18
+ const node = Bun.which('node')
19
+ if (!node) throw new Error('Node is required for the npm bootstrap test.')
20
+ directory = await mkdtemp(join(tmpdir(), 'runx-npm-'))
21
+ const root = Bun.fileURLToPath(new URL('..', import.meta.url))
22
+ const packed = Bun.spawn([process.execPath, 'pm', 'pack', '--destination', directory, '--ignore-scripts'], {
23
+ cwd: root,
24
+ stdout: 'pipe',
25
+ stderr: 'pipe',
26
+ })
27
+ const [packCode, packOutput, packError] = await Promise.all([
28
+ packed.exited,
29
+ new Response(packed.stdout).text(),
30
+ new Response(packed.stderr).text(),
31
+ ])
32
+ expect(packCode, packError).toBe(0)
33
+ const archiveName = [...new Bun.Glob('*.tgz').scanSync({ cwd: directory, onlyFiles: true })][0]
34
+ expect(archiveName, packOutput).toBeDefined()
35
+ const extraction = Bun.spawn(['tar', '-xzf', join(directory, archiveName), '-C', directory])
36
+ expect(await extraction.exited).toBe(0)
37
+
38
+ const server = Bun.serve({ port: 0, fetch: () => new Response(Bun.file(process.execPath)) })
39
+ try {
40
+ const wrapper = join(directory, 'package', 'scripts', 'runx-bin.mjs')
41
+ const child = Bun.spawn([node, wrapper, '--version'], {
42
+ cwd: join(directory, 'package'),
43
+ env: {
44
+ ...process.env,
45
+ PATH: join(node, '..'),
46
+ RUNX_NATIVE_CACHE: join(directory, 'native-cache'),
47
+ RUNX_DOWNLOAD_BASE_URL: `http://127.0.0.1:${server.port}`,
48
+ },
49
+ stdout: 'pipe',
50
+ stderr: 'pipe',
51
+ })
52
+ const [exitCode, stdout, stderr] = await Promise.all([
53
+ child.exited,
54
+ new Response(child.stdout).text(),
55
+ new Response(child.stderr).text(),
56
+ ])
57
+ expect(exitCode, stderr).toBe(0)
58
+ expect(stdout.trim()).toBe(process.versions.bun)
59
+ } finally {
60
+ server.stop(true)
61
+ }
62
+ })
@@ -4,7 +4,8 @@ description: Package-manager launcher scripts for RunX.
4
4
  parent: runx
5
5
  children: []
6
6
  files:
7
- runx-bin.ts: Executes a packaged native binary, the published compiled library launcher, or the source CLI fallback in a checkout.
7
+ runx-bin.mjs: Node-compatible npm bootstrap that downloads, caches, and delegates to the exact native release binary.
8
+ runx-bin.spec.ts: Packs the npm package and proves Node-only bootstrap download/delegation with Bun absent from PATH.
8
9
  documents: {}
9
10
  tags:
10
11
  - scripts
@@ -16,5 +17,4 @@ flags: []
16
17
  status: stable
17
18
  ---
18
19
 
19
- The package launcher preserves the `runx` bin command in installed npm packages
20
- and development checkouts without requiring unpublished source files.
20
+ The npm launcher contains no RunX domain logic and requires no Bun installation.
@@ -1,73 +1,78 @@
1
1
  ---
2
2
  name: guiho-s-runx
3
- purpose: Guide agents through safe inspection and execution of RunX command catalogs.
4
- description: Use when inspecting, creating, validating, organizing, documenting, or running a RunX `runx.yaml` command catalog. This includes listing available project commands, choosing a command by UID or selector, reviewing command descriptions, dry runs, confirmation-gated execution, and agent-safe project automation.
5
- created: 2026-07-12
6
- owner: guiho-s-runx
7
- flags: []
3
+ description: Use when inspecting, validating, documenting, or safely executing a RunX runx.yaml command catalog.
4
+ purpose: Teach agents the supported RunX catalog inspection and execution workflow.
5
+ created: 2026-07-18
6
+ flags:
7
+ - bundled
8
8
  tags:
9
- - agents
10
9
  - runx
10
+ - cli
11
11
  keywords:
12
- - runx
13
- - citty
12
+ - runx.yaml
14
13
  - command catalog
15
14
  - dry run
15
+ owner: guiho-s-runx
16
+ metadata:
17
+ version: "0.2.0"
16
18
  ---
17
19
 
18
20
  # GUIHO RunX
19
21
 
20
- Use RunX as the command catalog for a project. It documents executable local
21
- commands but does not make them inherently safe: a manifest is trusted code.
22
-
23
- ## Inspect Before Executing
24
-
25
- 1. From the intended project directory, run `runx check --format json`.
26
- 2. Run `runx list --format json` to inspect groups, UIDs, summaries, tags, and
27
- confirmation requirements.
28
- 3. Choose a stable `uid` for automation. An index is only for the current list
29
- and an unqualified ID can be ambiguous.
30
- 4. Run `runx describe <uid>` before an unfamiliar or high-impact command.
31
- 5. Run `runx run <uid> --dry-run` before a real execution when the command has
32
- filesystem, database, release, deployment, or production effects.
33
-
34
- ## Execute Safely
35
-
36
- - Use `runx run <uid>` or the short alias `runx r <uid>`.
37
- - `runx <selector>` is allowed as a human shorthand only when it cannot be
38
- confused with a built-in command; agents should prefer explicit `runx run`.
39
- - If `confirm: always` is set, RunX requires `--yes`.
40
- - Add `--yes` only after the user explicitly authorizes the specific command.
41
- - Do not treat a group name such as `development` or `operations` as a safety
42
- guarantee. Read the command description and command text.
43
- - Do not add secrets to `runx.yaml`. Use the project's existing environment or
44
- secret-management workflow.
45
- - Use `runx <command> --help` for command-specific Citty usage. `runx -h` and
46
- `runx -v` are global operations and do not require a manifest.
47
-
48
- ## Maintain Manifests
49
-
50
- - Keep `uid`, `id`, `group`, `summary`, `description`, and `command` present.
51
- - Keep UIDs stable; never reuse a UID for a materially different command.
52
- - Use a group for organization, a concise summary for listings, and a complete
53
- description for prerequisites, effects, and risk.
54
- - Set `confirm: always` for destructive, release, deployment, migration, and
55
- production-impacting commands when confirmation is useful.
56
- - Run `runx check` after every manifest change. It rejects unknown fields,
57
- duplicate UIDs/selectors, missing descriptions, invalid working directories,
58
- and unsupported shell choices.
59
-
60
- ## Useful Commands
22
+ ## Inspect Before Execution
23
+
24
+ 1. Run `runx check --format json`.
25
+ 2. Run `runx list --format json`.
26
+ 3. Prefer a stable UID for automation.
27
+ 4. Run `runx describe <uid>` before unfamiliar work.
28
+ 5. Run `runx run <uid> --dry-run` before any mutation or high-impact command.
29
+
30
+ RunX manifests are trusted executable code. A group name is not a safety
31
+ boundary. Never add `--yes` unless the developer explicitly authorizes the
32
+ specific confirmation-gated command.
33
+
34
+ ## Configuration
35
+
36
+ RunX resolves YAML only:
37
+
38
+ 1. `--config <path>`;
39
+ 2. effective-cwd `runx.yaml`;
40
+ 3. `~/.guiho/runx/runx.yaml`.
41
+
42
+ It does not search parent directories.
43
+
44
+ ## Execute
45
+
46
+ Use only:
61
47
 
62
48
  ```text
63
- runx Show the RunX home page and usage.
64
- runx -h Show generated command help.
65
- runx -v Show the installed version.
66
- runx list List the nearest manifest.
67
- runx describe <uid> Explain one command without execution.
68
- runx run <uid> --dry-run Inspect the execution plan.
69
- runx r <uid> Run through the short alias.
70
- runx agents install local Install this skill into .agents/skills.
71
- runx --help-tree Show the command hierarchy.
72
- runx --help-docs Show manifest documentation guidance.
49
+ runx run <uid>
73
50
  ```
51
+
52
+ Listing, describing, checking, help, agent operations, and dry runs must never
53
+ execute a manifest command. Preserve the child command's exact exit code.
54
+
55
+ ## Maintain Catalogs
56
+
57
+ - Keep `uid`, `id`, `group`, `summary`, `description`, and `command`.
58
+ - Keep UIDs stable and never reuse one for materially different behavior.
59
+ - Use `confirm: always` for destructive, release, deployment, migration, and
60
+ production-impacting operations.
61
+ - Do not place secrets in `runx.yaml`.
62
+ - Run `runx check` after every change.
63
+
64
+ ## Agent And Upgrade Commands
65
+
66
+ ```text
67
+ runx agent skill list
68
+ runx agent skill show guiho-s-runx
69
+ runx agent instruction show
70
+ runx agent prompt list --names
71
+ runx agent prompt show guiho-i-runx
72
+ runx upgrade check
73
+ runx upgrade list
74
+ runx upgrade --dry-run
75
+ ```
76
+
77
+ Use `--help`, `--help-tree`, or `--help-docs` at any command scope for the
78
+ current executable contract.
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  subject: guiho-s-runx
3
- description: Agent workflow for inspecting, validating, getting Citty usage for, and safely executing RunX manifest commands.
3
+ description: Agent workflow for safe RunX catalog execution and verified native upgrade/list/recovery operations.
4
4
  parent: runx-skills
5
5
  children: []
6
6
  files:
7
- SKILL.md: RunX-specific agent instructions, help aliases, and safe execution workflow.
7
+ SKILL.md: RFC-aligned RunX catalog inspection, execution safety, YAML precedence, agent, and upgrade guidance.
8
8
  documents:
9
- SKILL.md: RunX-specific agent instructions, Citty help/version guidance, and safe execution workflow.
9
+ SKILL.md: RunX-specific command execution and verified native self-upgrade workflow.
10
10
  tags:
11
11
  - agents
12
12
  - runx
@@ -15,9 +15,12 @@ keywords:
15
15
  - citty
16
16
  - command catalog
17
17
  - dry run
18
+ - runx upgrade
19
+ - recovery install
18
20
  flags: []
19
21
  status: stable
20
22
  ---
21
23
 
22
24
  The skill makes manifest inspection, UID selection, dry runs, and explicit
23
- confirmation the default agent workflow for RunX commands.
25
+ confirmation the default agent workflow for RunX commands and teaches agents
26
+ how to interpret transactional native upgrades and their recovery contract.
@@ -16,4 +16,4 @@ flags: []
16
16
  status: stable
17
17
  ---
18
18
 
19
- Bundled skills ship with RunX and can be installed through `runx agents install`.
19
+ Bundled skills ship with RunX and can be managed through `runx agent skill`.
@@ -1,36 +0,0 @@
1
- ---
2
- name: Implement RunX Alpha Command Catalog
3
- purpose: Define the expected outcome, constraints, and completion signals for task 1 in TODO.md.
4
- description: Describes the first RunX CLI release and the safety, documentation, and validation constraints that govern it.
5
- created: 2026-07-12
6
- flags:
7
- - implementation
8
- tags:
9
- - todo
10
- - cli
11
- keywords:
12
- - runx
13
- - alpha
14
- owner: runx-todo
15
- ---
16
-
17
- # Implement RunX Alpha Command Catalog
18
-
19
- ## Todo Index
20
-
21
- - Task: `1. Implement RunX Alpha Command Catalog`
22
- - Status: completed
23
- - Index: [TODO.md](../../TODO.md)
24
-
25
- ## Outcome
26
-
27
- Deliver a documented, locally executable RunX alpha that meets the approved
28
- command-catalog acceptance criteria without publishing a package.
29
-
30
- ## Watch-outs
31
-
32
- - Preserve read-only behavior for list, describe, check, and dry run paths.
33
- - Never place secrets in a manifest or run confirmation-gated commands without
34
- `--yes`.
35
- - Keep every new module and document represented by XDocs metadata.
36
- - Use Mirror for the version transition and keep commits one file at a time.
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- const args = process.argv.slice(2)
4
- const binaryPath = new URL(`../vendor/runx${process.platform === 'win32' ? '.exe' : ''}`, import.meta.url)
5
- const libraryPath = new URL('../library/guiho-runx-bin.js', import.meta.url)
6
- const sourcePath = new URL('../source/guiho-runx-bin.ts', import.meta.url)
7
-
8
- if (await Bun.file(binaryPath).exists()) {
9
- const child = Bun.spawn([Bun.fileURLToPath(binaryPath), ...args], { stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' })
10
- process.exit(await child.exited)
11
- }
12
-
13
- if (await Bun.file(libraryPath).exists()) {
14
- const child = Bun.spawn([process.execPath, Bun.fileURLToPath(libraryPath), ...args], { stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' })
15
- process.exit(await child.exited)
16
- }
17
-
18
- if (await Bun.file(sourcePath).exists()) {
19
- const child = Bun.spawn([process.execPath, Bun.fileURLToPath(sourcePath), ...args], { stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' })
20
- process.exit(await child.exited)
21
- }
22
-
23
- console.error('error: RunX executable is unavailable. Install an official native release or reinstall @guiho/runx.')
24
- process.exit(1)