diff --git a/README.md b/README.md index 6db4595f8..d7289bddc 100644 --- a/README.md +++ b/README.md @@ -85,20 +85,21 @@ REA shows how it reached its conclusions. It does not claim to recover original ## Quick start -### Install the CLI — recommended +### Run setup — recommended ```bash -npm install --global rea-agents -rea setup +npx rea-agents setup ``` -Installing the CLI does not update Homebrew, Node.js, npm, Hopper, or agent -configuration. `rea setup` opens with the work it enables: investigate local -apps from an agent, recover evidence through a deep-analysis provider, and -reuse REA's guided workflow. It summarizes the detected agents, then offers -**Set up all available capabilities (recommended)**, **Customize**, or -**No thanks**. Customize shows every concrete target with an `MCP`, `provider`, -or `skill` label. +The npm package-runner prompt, when shown, approves downloading REA for this +invocation; it does not approve any setup changes. The REA wizard separately +shows its complete plan and asks before applying it. Setup does not update +Homebrew, Node.js, or npm. `npx rea-agents setup` opens with the work it +enables: investigate local apps from an agent, recover evidence through a +deep-analysis provider, and reuse REA's guided workflow. It summarizes the +detected agents, then offers **Set up all available capabilities +(recommended)**, **Customize**, or **No thanks**. Customize shows every +concrete target with an `MCP`, `provider`, or `skill` label. REA keeps the journey inline so its history remains in the terminal. Before anything changes, it validates existing configuration, prints exact paths and @@ -138,7 +139,7 @@ Review the setup plan, approve it if appropriate, then describe the app or featu ### From Terminal — no installation ```bash -npx -y rea-agents@latest setup +npx rea-agents setup npx -y rea-agents@latest doctor npx -y rea-agents@latest analyze /Applications/Notes.app ``` diff --git a/README_ar.md b/README_ar.md index 7da1b5f8e..d8de3ce0b 100644 --- a/README_ar.md +++ b/README_ar.md @@ -90,7 +90,7 @@ npx skills add morluto/rea ```bash curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash -npx -y rea-agents@latest setup +npx rea-agents setup ``` إذا طلب macOS أو برنامج التثبيت تأكيدًا، فأكمل الخطوة ثم شغّل الأمر نفسه مرة أخرى. diff --git a/README_ja.md b/README_ja.md index ef7ea6772..c1bf4ea24 100644 --- a/README_ja.md +++ b/README_ja.md @@ -91,7 +91,7 @@ Ubuntu 24.04+、Fedora 41+、64 ビット Arch Linux では、REA が公式の D ```bash # 1. REA をセットアップ curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash -npx -y rea-agents@latest setup +npx rea-agents setup ``` macOS やインストーラーから確認を求められた場合は、その操作を完了してから同じコマンドをもう一度実行してください。 diff --git a/README_ko.md b/README_ko.md index 94f0fe530..feaee7f13 100644 --- a/README_ko.md +++ b/README_ko.md @@ -91,7 +91,7 @@ Ubuntu 24.04+, Fedora 41+, 64비트 Arch Linux에서 REA는 공식 DEB, RPM 또 ```bash # 1. REA 설정 curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash -npx -y rea-agents@latest setup +npx rea-agents setup ``` macOS나 설치 프로그램이 확인을 요청하면 해당 절차를 완료하고 같은 명령을 다시 실행하세요. diff --git a/README_zh.md b/README_zh.md index f7dfe1544..8d9ed066e 100644 --- a/README_zh.md +++ b/README_zh.md @@ -91,7 +91,7 @@ npx skills add morluto/rea ```bash # 1. 安装和配置 REA curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash -npx -y rea-agents@latest setup +npx rea-agents setup ``` 如果 macOS 或安装程序要求确认,请完成提示,然后再次运行同一命令。 diff --git a/docs/installation.md b/docs/installation.md index c7e398d43..a035fc707 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -2,21 +2,26 @@ REA separates installing its CLI from configuring external software and agents. -## Install the CLI +## Start setup -The recommended installation is: +The recommended setup entrypoint is: ```bash -npm install --global rea-agents -rea setup +npx rea-agents setup ``` +If npm asks to download and run the package, that approval applies only to the +current package-runner invocation. REA still prints its own setup plan and asks +for separate approval before changing agent configuration or installing a +product-owned component. + REA supports Node.js 22.19+ and 24.11+ (including newer releases). It uses the npm already paired with that runtime and never upgrades Node.js, npm, or Homebrew. Running `npm install rea-agents` without `--global` installs the executable only in the current project's `node_modules/.bin`; it does not make `rea` available -on the shell `PATH`. Use `npx -y rea-agents@latest` for one-off commands or the -global installation above for a shell-visible `rea` command. +on the shell `PATH`. Use `npx rea-agents setup` for the guided setup journey, +`npx -y rea-agents@latest` for unattended one-off commands, or install globally +with `npm install --global rea-agents` for a shell-visible `rea` command. The optional curl wrapper installs only the global npm package: diff --git a/package-lock.json b/package-lock.json index 2c4a8e99a..e1193d251 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,8 @@ "zod": "4.4.3" }, "bin": { - "rea": "scripts/rea.mjs" + "rea": "scripts/rea.mjs", + "rea-agents": "scripts/rea.mjs" }, "devDependencies": { "@fast-check/vitest": "0.4.1", diff --git a/package.json b/package.json index 63c06de04..61da67acd 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ }, "type": "module", "bin": { - "rea": "scripts/rea.mjs" + "rea": "scripts/rea.mjs", + "rea-agents": "scripts/rea.mjs" }, "engines": { "node": "^22.19.0 || >=24.11.0" diff --git a/scripts/verify-package.mjs b/scripts/verify-package.mjs index adfb70514..0e67076a9 100644 --- a/scripts/verify-package.mjs +++ b/scripts/verify-package.mjs @@ -14,6 +14,7 @@ import { join } from "node:path"; import { pathToFileURL } from "node:url"; import { promisify } from "node:util"; +import { spawn } from "@lydell/node-pty"; import { Client } from "@modelcontextprotocol/client"; import { StdioClientTransport } from "@modelcontextprotocol/client/stdio"; import { TextReader, Uint8ArrayWriter, ZipWriter } from "@zip.js/zip.js"; @@ -48,6 +49,11 @@ try { packedManifest.dependencies?.["@lydell/node-pty"] !== "1.1.0" ) throw new Error("package retained a lifecycle-dependent PTY installation"); + if ( + packedManifest.bin?.rea !== "scripts/rea.mjs" || + packedManifest.bin?.["rea-agents"] !== "scripts/rea.mjs" + ) + throw new Error("package did not expose both rea command entry points"); if ( packedFiles.some( (path) => path.includes("__pycache__") || path.endsWith(".pyc"), @@ -143,6 +149,7 @@ try { { env: environment }, ); const cli = join(prefix, "bin", "rea"); + const packageRunnerCli = join(prefix, "bin", "rea-agents"); const processCaptureCapabilityUrl = pathToFileURL( join( prefix, @@ -216,6 +223,12 @@ try { `packaged CLI did not degrade without the optional PTY binary: ${JSON.stringify(noOptionalCapability)}`, ); const help = await run(cli, ["--help"], environment); + const packageRunnerHelp = await run( + packageRunnerCli, + ["--help"], + environment, + ); + await verifyInteractiveSetup(packageRunnerCli, environment); const llms = await run(cli, ["--llms"], environment); const doctorExecution = await runWithStatus( cli, @@ -228,6 +241,7 @@ try { const expectedDoctorHealth = doctor.checks?.every(({ ok }) => ok) === true; if ( !help.includes("setup") || + !packageRunnerHelp.includes("setup") || !help.includes("upgrade") || !help.includes("inventory-artifact") || !help.includes("extract-artifact") || @@ -1157,6 +1171,53 @@ async function runWithStatus(command, args, env) { throw cause; } } +async function verifyInteractiveSetup(command, env) { + await new Promise((resolvePromise, reject) => { + let output = ""; + let cancelled = false; + let settled = false; + const terminal = spawn(command, ["setup"], { + cwd: root, + env: { ...env, NO_COLOR: "1", TERM: "xterm-256color" }, + name: "xterm-256color", + cols: 120, + rows: 40, + }); + const timeout = setTimeout(() => { + terminal.kill(); + finish( + new Error(`packaged setup wizard timed out after output: ${output}`), + ); + }, 20_000); + + terminal.onData((data) => { + output += data; + if (!cancelled && output.includes("Choose a setup")) { + cancelled = true; + terminal.write("\u0003"); + } + }); + terminal.onExit(() => { + if (!cancelled || !output.includes("No changes were made.")) { + finish( + new Error( + `packaged rea-agents setup did not open and cancel the wizard: ${output}`, + ), + ); + return; + } + finish(); + }); + + function finish(error) { + if (settled) return; + settled = true; + clearTimeout(timeout); + if (error === undefined) resolvePromise(); + else reject(error); + } + }); +} function json(text) { return JSON.parse(text); } diff --git a/tests/readmeConsistency.test.ts b/tests/readmeConsistency.test.ts index b83aaf66c..6f31a3fe8 100644 --- a/tests/readmeConsistency.test.ts +++ b/tests/readmeConsistency.test.ts @@ -61,7 +61,7 @@ describe("localized README product facts", () => { expect(content).toContain( "curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash", ); - expect(content).toContain("npx -y rea-agents@latest setup"); + expect(content).toContain("npx rea-agents setup"); expect(content).toContain("npx -y rea-agents@latest doctor"); expect(content).toContain("rea uninstall"); expect(content).toContain('"args": ["-y", "rea-agents@latest", "mcp"]');