feat: scripted install for npm-shipped agents#9
Conversation
Adds an Install action in the agents menu (and `--install` for `opper launch`) that runs `npm i -g <pkg>` for OpenCode, Claude Code, Codex, OpenClaw, and Pi instead of pointing the user at a docs URL. Replaces five throwing/missing install stubs with a single shared `npmInstallGlobal` helper that pre-checks `which npm`, uses `npm.cmd` on Windows, and surfaces a graceful error when an install is interrupted (Ctrl-C). Claude Desktop is intentionally left manual — it's a GUI app with no scripted installer.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6513399811
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (result.code === -1) { | ||
| throw new OpperError( | ||
| "AGENT_NOT_FOUND", | ||
| `npm install -g ${packageName} was interrupted before completion.`, | ||
| `Re-run to retry, or install manually from ${docsUrl}.`, |
There was a problem hiding this comment.
Distinguish spawn failures from user-interrupted installs
run() uses code: -1 for both signal interruption and process-spawn errors, but this branch treats every -1 as a Ctrl-C cancellation. In environments where npm exists on PATH but cannot be executed (for example permission-denied or transient command resolution failures), users will get a misleading “interrupted” message and lose the actionable error context. Handle -1 by inspecting the underlying error/stderr (or propagate it) so real execution failures are not misreported as user cancellation.
Useful? React with 👍 / 👎.
run() collapses both signal-killed children and spawn-time errors (EACCES on the npm binary, etc.) to code: -1. The previous patch treated every -1 as Ctrl-C, hiding the underlying error from users who actually had a real spawn failure. Use the stderr-non-emptiness heuristic that's reliable under inherit:true to split them: empty stderr ⇒ signal kill, non-empty ⇒ spawn error to surface. Reported by codex on PR #9.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6987e6347a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ); | ||
| } | ||
|
|
||
| const result = run(NPM, ["install", "-g", packageName], { inherit: true }); |
There was a problem hiding this comment.
Run npm installer via shell on Windows
This path calls run(NPM, ...) where NPM is npm.cmd on Windows, but run() uses spawnSync with no shell (src/util/run.ts), so the installer can fail to start on Windows even when npm is installed. Node's child_process docs for Windows state .cmd scripts must be invoked through a shell (or cmd.exe /c), so this new scripted install flow will consistently error with code -1 for Windows users instead of installing the agent.
Useful? React with 👍 / 👎.
Node's spawnSync refuses to execute .cmd files directly — even when given the explicit `npm.cmd` name — so the previous Windows fix would still have failed with code -1 for every Windows user. Route through cmd.exe via `shell: true` on Windows (PATHEXT then resolves the npm shim); POSIX still runs npm directly with no shell. Reported by codex on PR #9.
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep it up! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
# Conflicts: # src/agents/opencode.ts
Summary
opper launch <agent> --installflag) for the five agents whose upstream binary ships as a global npm package: OpenCode, Claude Code, Codex, OpenClaw, and Pi.src/agents/npm-install.tshelper that runsnpm i -g <pkg>with stdio inherited so the user sees npm progress live.which npm(clear error if Node.js isn't installed), usesnpm.cmdon Windows so spawnSync resolves the shim, and converts an interrupted install (Ctrl-C → exit code -1) into a polite "interrupted" error instead of "exited with code -1".Test plan
npx vitest run— 264 tests pass (added per-helper coverage intest/agents/npm-install.test.tsand a menu test that exercises the new install path)npx tsc --noEmit— cleanopper→ Agents → OpenCode → "Install OpenCode" actually installsnpmremoved from PATH, install action errors with the Node.js install hint instead of a crypticcode -1