Skip to content

Install Codex and Pi without requiring Node.js - #5930

Closed
brsbl wants to merge 18 commits into
mainfrom
bb/windows-agent-install-needs-node
Closed

brsbl wants to merge 18 commits into
mainfrom
bb/windows-agent-install-needs-node

Conversation

@brsbl

@brsbl brsbl commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Human comments

What was wrong

Setup used npm to install Codex and Pi, so Install failed on machines without Node.js. Pi also needs a runtime after installation.

What changed

  • Codex installs through OpenAI's native installer and is discovered before PATH refresh.
  • Pi keeps its normal Install button and installs privately using bb's existing runtime and bundled npm.
  • Pi's version checks, sign-in and sessions use that runtime without requiring Node.js on PATH.
Why reuse bb's runtime

bb already includes npm and runs its packaged backend through Electron's Node mode on Windows, macOS and Linux. Headless bb already has a Node runtime. Both satisfy Pi's runtime requirement, so a separate Node download adds no needed capability.

The installer uses a private writable prefix and disables lifecycle scripts, which Pi's official distribution supports. It reads Pi's executable from the installed package manifest. Managed desktop launches explicitly use Electron's Node mode. Windows RPC launches run directly; Linux sign-in launchers retain the stable AppImage path and handle its sandbox argument.

How you verified

  • Windows regression before the fix: setup fails to offer Pi's Install button.
  • Linux Chrome: both Install buttons install real executables without Node or npm on PATH; unauthenticated status survives reload.
  • Windows setup e2e: passed; Pi Install, executable version, and installed/not-signed-in status with Node.js and npm off PATH.
  • Packaged Electron smoke: passed; real Pi install, version and RPC with an empty PATH.
  • Final remote CI: all checks passed.
  • Full Slop Cop: PASS WITH FOLLOW-UPS; all P0/P1 findings resolved and fixes checked at the final head.
P2 follow-ups
  • Windows sign-in quoting should handle typographic apostrophes and launcher encoding should support non-ASCII paths.
  • A per-session external Pi supplied only through a child PATH override should take precedence over an existing managed Pi.
  • Codex executable discovery should skip directories and nonexecutable PATH entries.
  • Codex update discovery and command display should handle native installations consistently.

Before: b28bbc2c195b027e58a43e6328dadfd118f0d908 · After: 533c77cdb98b100195de83c83b9a2bb76125bf1e · Chrome, 2× density. Fresh fixtures without Node.js, npm or credentials. Captures focus on setup's agent rows.

Screen / state Viewport Before After
Setup / agent step Desktop · 1440×900 Before Setup / agent step on desktop After Setup / agent step on desktop
Setup / agent step Mobile · 390×844 Before Setup / agent step on mobile After Setup / agent step on mobile
Setup / after Install Codex Desktop · 1440×900 Before Setup / after Install Codex on desktop After Setup / after Install Codex on desktop
Setup / after Install Codex Mobile · 390×844 Before Setup / after Install Codex on mobile After Setup / after Install Codex on mobile
Setup / after Install Pi Desktop · 1440×900 Before Setup / after Install Pi on desktop After Setup / after Install Pi on desktop
Setup / after Install Pi Mobile · 390×844 Before Setup / after Install Pi on mobile After Setup / after Install Pi on mobile

BB-Thread-ID: thr_k52en5smyw

BB-Thread-ID: thr_fveuzb32dm

BB-Thread-ID: thr_7jmxshwfd2

AGENT GENERATED

brsbl and others added 4 commits October 20, 2026 23:04
Codex and Pi setup offers an npm global install even when npm is not on PATH, so a machine without Node.js gets an Install button that always fails. Add an optional missingPrerequisite field to the installation status contracts and tests that expect it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex and Pi now report missingPrerequisite "nodejs" and no install action when npm is not available. Setup's agent row shows "Needs Node.js to install" with a Get Node.js button instead of an Install button that always fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex setup now runs OpenAI's install.sh / install.ps1 instead of npm install -g, so it needs no Node.js on any OS. bb finds a native install in ~/.local/bin or %LOCALAPPDATA%\Programs\OpenAI\Codex\bin before PATH picks it up, so post-install verification and thread launch both work right away. Pi keeps the Node.js next step until it moves to bb's bundled runtime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…verywhere

OpenAI's installer ends with an interactive "Start Codex now?" prompt that never gets an answer inside bb's install terminal, so set CODEX_NON_INTERACTIVE on both the sh and PowerShell paths. Codex health, usage and sign-in commands now use the same native-binary resolution as installation status, so a native install outside PATH is not reported as missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brsbl
brsbl marked this pull request as ready for review October 20, 2026 23:52
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T23:56:52.642666Z 1260156 Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

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

Copy link
Copy Markdown

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

ℹ️ 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 on lines +208 to +210
? missingPrerequisite === null
? "install"
: null

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 Surface the Node.js prerequisite outside onboarding

When Pi is selected on a host without npm, these lines deliberately remove its install action. Onboarding consumes missingPrerequisite, but RootComposeView only offers an action when hasProviderCliAction succeeds, and bb updates ignores the new field, so users who encounter Pi after onboarding are blocked by generic install text with no explanation or route to get Node.js. Propagate the prerequisite and its remediation through the composer and CLI surfaces.

AGENTS.md reference: AGENTS.md:L26-L26

Useful? React with 👍 / 👎.

"codex.exe",
);
}
return path.posix.join(env.HOME ?? os.homedir(), ".local", "bin", "codex");

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 Honor the installer’s custom destination

When the daemon inherits CODEX_INSTALL_DIR and that directory is not already on PATH, the downloaded installer writes Codex there, but this resolver checks only ~/.local/bin. The official installer assigns BIN_DIR="${CODEX_INSTALL_DIR:-$HOME/.local/bin}", so the command can succeed while bb's verification and subsequent health checks still report Codex as missing. Resolve CODEX_INSTALL_DIR before falling back to the platform default, including in the Windows branch.

Useful? React with 👍 / 👎.

Comment on lines +38 to +40
extensions.some((extension) =>
existsSync(path.join(directory, `${command}${extension}`)),
),

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 Require PATH candidates to be executable

If an earlier PATH directory contains a non-executable file or directory named codex while a valid native standalone installation exists, existsSync makes this function return the bare command. The later executable probe and app-server launch then reject that candidate instead of using the native binary, causing Codex to be reported missing or fail to start. Check executable-file semantics rather than existence alone.

Useful? React with 👍 / 👎.

bb's sign-in terminal passes the login command to PowerShell as text, and a quoted absolute path followed by arguments is a parse error there. Prefix '& ' when the resolved Codex executable is an absolute Windows path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brsbl
brsbl removed this pull request from stack #5945 October 21, 2026 16:52
@brsbl
brsbl added this pull request to stack #6053 October 21, 2026 16:52
ymichael added a commit that referenced this pull request Oct 27, 2026
… defaults (#6194)

## Human comments

## What was wrong

bb launches child processes from many places (server, daemon, desktop,
launcher, plugins), and each one found executables and built PATH its
own way. Under a macOS launchd service or a GUI launch, PATH is minimal,
so several things broke:

- Plugins could not run `bb` because the CLI's Node was not on PATH
(#5807).
- Daemon self-update went through a mise npm wrapper that exits 127
after a successful install, so bb treated the update as failed (#6079).
- Homebrew upgrades deleted the running Node, and bb kept using the dead
path to start workers (#5295).
- The Claude Code installation check searched only PATH, so a native
install in `~/.local/bin` that was not on PATH was reported missing and
bb kept offering to reinstall it (#6284).
- Node ignored corporate proxies and OS-trusted certificates because
`NODE_USE_ENV_PROXY` and `NODE_USE_SYSTEM_CA` were never set (#5260,
#3239).

## What changed

- **One resolver:** `HostToolchain` in
`packages/process-utils/src/host-toolchain.ts` owns executable lookup,
the child PATH and proxy/CA environment, npm selection, and replacement
of a deleted Node.
- It reads the login-shell PATH, or the user and machine registry PATH
on Windows, plus proxy variables from the shell.
- It adds the running Node runtime's directory (never the Electron
app's) and standard user tool directories (`~/.local/bin`, mise/asdf
shims, Volta, and Homebrew on macOS).
- Discovery runs in the background and is coalesced. Launches never wait
for it.
- `ENOENT`, exit 127 and lookup misses start a background refresh.
Commands are never replayed.
- **Launch helpers:** `spawnHostProcess`, `forkHostProcess`,
`execHostFile`, `execHostFileCallback`, `execHostFileBuffer` and
`prepareHostPtyCommand` in `host-process.ts` use the resolver. Core call
sites across the server, daemon, desktop, CLI, launcher, host-workspace,
host-watcher, local-open-targets and the provider kits now use these
helpers instead of `node:child_process`. The per-package lookup code is
deleted: desktop `desktop-shell-path`, daemon `runtime-shell-env`
shell/registry parsing, `selectResolvedExecutable`, and the plugin-local
`bb`/`claude` candidate lists.
- **Child environments:**
- Every child PATH gets the login-shell PATH and the standard tool
folders. When the PATH is the one bb started with, the login-shell PATH
comes first; when a caller passes a different PATH, the caller's entries
stay first. bb never infers that a PATH was meant to be exact.
- Scripts that start with `#!/usr/bin/env node` run with the `node` on
PATH.
- `npm` and `npx` run as found on PATH. Daemon self-update instead runs
`npm-cli.js` with the Node installation that owns it
(`hostToolchain.npmCli`), which avoids version-manager wrappers. Inside
the Electron desktop runtime, bb never substitutes its own runtime for
npm.
- **Network defaults:** the packaged server/daemon launchers start bb's
own Node processes with `--use-system-ca` and `--use-env-proxy`
(`@bb/config/node-network`), each only when the runtime accepts it, and
bb's forked workers and provider bridge workers inherit them. They are
flags rather than exported variables, so terminals, provider CLIs and
agent shells keep the user's own Node networking settings. Setting
`NODE_USE_SYSTEM_CA=0` or `NODE_USE_ENV_PROXY=0` opts out. `bb-app env
set` treats the proxy and CA keys as startup-only.
- **Startup:** the daemon and the packaged desktop app wait for
discovery at startup. The server starts it in the background. The `bb`
CLI never runs it.
- **Plugin SDK:** new `@get-bb/plugin-sdk/process` entry point exports
`experimental_hostToolchain`, `experimental_spawnHostProcess`,
`experimental_forkHostProcess`, `experimental_execHostFile` and
`experimental_execHostFileCallback`. Core uses the same implementation.
- SDK bumped to 0.6.86. Plugins that import the entry point now require
`>=0.6.86`.
  - `check-plugin-sdk-version.mjs` now watches `src/process.ts`.
- Added an entry to `docs/api_to_audit.md` and the Plugin Guide's
Provider bridges card.
- **Plugins:** MCP, automations, browser automation, GitHub, keep-awake,
storage retention (including the external worktree scanner), account
pool, and the Claude Code, Codex and Pi providers use the SDK helpers.
- **CLI startup:** the `bb` entry imports
`@bb/process-utils/host-process` rather than the package barrel, so
startup does not load execa.
- **Docs:** `docs/configuration.md` covers proxies and certificates and
how executable discovery works.
- **No wire changes:** `HOST_DAEMON_PROTOCOL_VERSION` is unchanged.

Behavior differences from main:

- Proxy variables set in the user's login shell now reach child
processes when the caller's environment does not set them.
- Children receive the caller's PATH extended with the login-shell PATH
and the standard tool directories.

Not addressed:

- Daemon WebSocket connections still ignore the proxy (#4957).
- Node releases without built-in environment-proxy support (before 22.21
and 24.5) still connect directly (#3239).
- A real corporate proxy or CA deployment has not been verified; the
proxy checks used local proxies and mitmproxy.
- Codex native installer (#5930) and Pi bundled-runtime install (#5943)
remain separate follow-ups.

This supersedes #6081, #6083, #5997 and #5948.

## How you verified

- New process-utils tests (`host-toolchain.test.ts`,
`host-toolchain-windows.test.ts`) cover:
  - npm install through a mise-style wrapper that exits 127 (#6079)
  - recovery of a deleted Homebrew Node (#5295)
- Claude Code installation status finding a native install outside PATH
(#6284; fails on main)
  - running a `bb` Node script with a minimal service PATH (#5807)
  - a new command found after the login PATH changes
  - retaining the last good PATH when discovery fails
  - bounded probes and no repeated probing of missing commands
  - non-blocking discovery
- caller PATH entries kept first, with the standard folders added after
them
  - caller proxy variables winning over login-shell ones in either case
  - `#!/usr/bin/env node` scripts not run through the bb runtime
- npm paired with the Node that owns it, and the PATH npm used for
ordinary launches
  - a tool in a standard folder found when the caller's PATH lacks it
  - byte-exact buffered output
  - no replay after exit 127
  - Windows registry PATH expansion and retention
- bb-app tests start the server and daemon with real environment proxies
and check that `NO_PROXY` bypasses them (#3239), and that explicit
opt-outs are kept (#5260).
- Reproduced before these fixes, and verified after:
- The launcher's `bb --version` took 1.7 s because of a synchronous
login-shell probe. It now takes 0.08 s.
- A binary git blob came back corrupted (64 bytes in, 121 out). It now
comes back byte-exact.
- `pnpm exec turbo run typecheck lint --filter='...[origin/main]'`
passes.
- `pnpm exec turbo run test --filter='[origin/main]'` passes for every
changed package except the desktop Electron smoke test below. Under that
parallel load, the MCP timeout test and the server builtin hot-reload
test missed their timing windows; both pass when run alone.
- `check-plugin-sdk-version.mjs` and `oxfmt --check` pass.
- Desktop `preload-build` (Electron smoke) times out locally with both
this branch's and main's desktop sources, so it is environmental.
- Manual checks on real installs:
- **Windows 11 ARM64 VM** (bb-app from this branch, started by its
sign-in scheduled task): Codex (`codex.exe`), Claude Code (`claude.exe`)
and Pi (`pi.cmd`) are detected with their on-disk names. Updating Pi
through bb (`bb machine provider-cli install <host> pi --action update`)
ran `npm.cmd` in a pty and moved Pi from 1.3.0 to 1.4.0. Signed-in
Claude Code and Codex turns run `node`, `npm` and `bb`, and `where.exe`
finds node, npm, bb, claude, codex and pi. A bb terminal resolves
`codex`, `claude`, `pi`, `node` and `npm` from the registry PATH.
- **Packaged macOS desktop app launched with launchd's environment**
(`PATH=/usr/bin:/bin:/usr/sbin:/sbin`): the server and daemon receive
the login-shell PATH; Codex under `~/.bun/bin` and Pi under nvm are
detected; Claude Code, Codex and Pi turns each run `git --version`,
`node --version` and `bb --version` successfully. The packaged `bb` CLI
runs with `PATH=/usr/bin:/bin` (#5807). This check found that exporting
`NODE_USE_*` made `bb --version` inside agent shells print proxy
warnings and system-certificate errors; switching to flags fixed it.
- **Main vs branch environment diff** (both packaged apps launched with
launchd's environment): in a bb terminal, Claude Code and Codex agent
shells, and the server, daemon, bridge, Claude and Codex processes, the
only differences are the added PATH fallbacks and the network flags on
bb's own processes. `node`, `npm`, `git`, `bb`, `codex`, `claude` and
`pi` resolve to the same files. This check found the Electron app
directory on child PATHs; it is now excluded.
- **Proxy:** with `HTTPS_PROXY` in the data directory's `env.json`, the
branch routes the server's npm version check and the bridge workers'
Claude, Codex, Cursor and OpenCode usage fetches through the proxy; main
sends the same requests directly. On Linux, a TLS-intercepting mitmproxy
whose CA is only in the system store works with the default flags and
fails with `NODE_USE_SYSTEM_CA=0`. This check found that bridge workers
lacked the flags; they now inherit them.
- **Linux** (Ubuntu 24.04 container, Node from mise only on the
login-shell PATH, launched with systemd's default PATH): providers are
found through mise shims, a Pi update through bb ran mise's npm, a bb
terminal resolves every tool, and a machine running its daemon like the
systemd unit self-updated from protocol 255 to a bumped 256 server and
reconnected.
- **Daemon self-update:** a machine enrolled with the manual installer,
running a supervised `--auto-update` daemon under launchd's PATH,
updated from protocol 252 to a locally bumped 253 server: it installed
the server's package into its private prefix with the Node-owned npm,
restarted, and reconnected. The global npm prefix was untouched.

Fixes #6079
Fixes #5807
Fixes #5295
Fixes #5260
Fixes #6284

> AGENT GENERATED

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: review <review@local>
@blacksmith-sh

This comment has been minimized.

@blacksmith-sh

This comment has been minimized.

@brsbl brsbl changed the title Install Codex without Node.js, and ask for Node.js before a Pi install that can't run Install Codex and Pi without requiring Node.js Oct 28, 2026
@github-actions github-actions Bot closed this Nov 4, 2026
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

This is an automated message. We have closed this pull request because it has been open for more than two weeks.

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