#!/usr/bin/env node // rnx CLI entry point. the full command and verb surface lives in the // registry at `packages/rnx-skills/src/cli/meta.ts` — help output, // website docs, and agent skills all read from there. do not duplicate // command listings in this file; run `rnx --help` for the canonical // surface. // // this file only routes. the hidden entry points below each take over the // whole process, so the CLI itself lives in `./main` and is imported only once // none of them has claimed the run. import { RNX_INTERNAL_COMMAND } from './internal-child' if (process.argv[2] === '__shell-init') { const { renderRnxShellInit } = await import('./shell-init') try { process.stdout.write(renderRnxShellInit(process.argv[3] ?? '')) process.exit(0) } catch (error) { process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`) process.exit(1) } } if (process.argv[2] === '__cloud-confirm') { try { const [{ confirmCloudSimulator }, { readCloudSession }] = await Promise.all([ import('./cloud-client'), import('./cloud-session'), ]) const session = readCloudSession() if (!session) throw new Error('RNX cloud confirmation has no shell session') // a box has no claim to keep alive: its simulator is held by the Box page // for as long as the box runs, so a shell on a box confirms nothing. if (session.service === 'sim') await confirmCloudSimulator(session) process.exit(0) } catch (error) { process.stderr.write( `RNX cloud confirmation failed: ${ error instanceof Error ? error.message : String(error) }\n`, ) process.exit(1) } } // child processes this CLI spawns as itself: the detached browser host, // playwright's installer, maestro's blocking fetch worker. unlike the two // above, these do not exit on the way out — the installer and the browser host // are still working when their handler returns, and the process ends when that // work does. so this is the branch that must skip the CLI rather than the CLI // that must skip it. if (process.argv[2] === RNX_INTERNAL_COMMAND) { const { runInternalChild } = await import('./internal-child') await runInternalChild(process.argv.slice(3)) } else { await import('./main') }