feat(cli): support package-name setup wizard

This commit is contained in:
morluto 2026-07-18 13:37:19 +08:00
parent b537ebfa34
commit 1b90e7f992
10 changed files with 93 additions and 24 deletions

View File

@ -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
```

View File

@ -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 أو برنامج التثبيت تأكيدًا، فأكمل الخطوة ثم شغّل الأمر نفسه مرة أخرى.

View File

@ -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 やインストーラーから確認を求められた場合は、その操作を完了してから同じコマンドをもう一度実行してください。

View File

@ -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나 설치 프로그램이 확인을 요청하면 해당 절차를 완료하고 같은 명령을 다시 실행하세요.

View File

@ -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 或安装程序要求确认,请完成提示,然后再次运行同一命令。

View File

@ -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:

3
package-lock.json generated
View File

@ -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",

View File

@ -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"

View File

@ -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);
}

View File

@ -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"]');