Skip to content

feat: scripted install for npm-shipped agents#9

Merged
joch merged 4 commits into
mainfrom
opencode-install
May 7, 2026
Merged

feat: scripted install for npm-shipped agents#9
joch merged 4 commits into
mainfrom
opencode-install

Conversation

@joch
Copy link
Copy Markdown
Member

@joch joch commented May 7, 2026

Summary

  • Adds an Install <Agent> action to the agents menu (and wires the existing opper launch <agent> --install flag) for the five agents whose upstream binary ships as a global npm package: OpenCode, Claude Code, Codex, OpenClaw, and Pi.
  • Replaces five throwing/missing install stubs with a single shared src/agents/npm-install.ts helper that runs npm i -g <pkg> with stdio inherited so the user sees npm progress live.
  • Hardening in the helper: pre-checks which npm (clear error if Node.js isn't installed), uses npm.cmd on 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".
  • Claude Desktop intentionally untouched — GUI app with no scripted installer.

Test plan

  • npx vitest run — 264 tests pass (added per-helper coverage in test/agents/npm-install.test.ts and a menu test that exercises the new install path)
  • npx tsc --noEmit — clean
  • Manual: opper → Agents → OpenCode → "Install OpenCode" actually installs
  • Manual: same for Claude Code, Codex, OpenClaw, Pi
  • Manual: with npm removed from PATH, install action errors with the Node.js install hint instead of a cryptic code -1

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.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/agents/npm-install.ts
Comment on lines +31 to +35
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}.`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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.
@joch
Copy link
Copy Markdown
Member Author

joch commented May 7, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/agents/npm-install.ts Outdated
);
}

const result = run(NPM, ["install", "-g", packageName], { inherit: true });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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.
@joch
Copy link
Copy Markdown
Member Author

joch commented May 7, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

ℹ️ 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".

@joch joch merged commit 36d20c2 into main May 7, 2026
3 checks passed
@joch joch deleted the opencode-install branch May 7, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant