Skip to content

fix(codex): install real native binary for aliased optional deps - #1982

Merged
shunkakinoki merged 1 commit into
mainfrom
fix/codex-native-binary-pin
Jul 4, 2026
Merged

fix(codex): install real native binary for aliased optional deps#1982
shunkakinoki merged 1 commit into
mainfrom
fix/codex-native-binary-pin

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Problem

Running `codex` failed with:

```
Error: Missing optional dependency @openai/codex-darwin-arm64. Reinstall Codex: bun install -g @openai/codex@latest
```

The wrapper (`codex.js`) resolves its native binary purely by path -
`require.resolve('@openai/codex-darwin-arm64/package.json')` then
`vendor/aarch64-apple-darwin/bin/codex`. "Missing" means that binary file
wasn't on disk.

Root cause: the `@openai/codex-*` optional pins were malformed.

version spec tarball contents
Correct (codex's own optionalDependencies) `npm:@openai/codex@0.142.3-darwin-arm64` native `vendor/.../bin/codex`
Dotfiles pin (before) `npm:@openai/codex@0.142.2` the generic JS wrapper again - no binary

The `-` version suffix was missing, so `install-npm-globals.sh`
faithfully installed the wrapper package under the platform dir name. The
subsequent `-d` presence check then cached the broken dir across every run.

Fix

  • package.json: pin the suffixed native packages (`0.142.5-`).
    A caret can't float a suffixed version (semver treats `-darwin-arm64` as a
    prerelease tag), so drift protection lives in the script instead.
  • install-npm-globals.sh (drift-proof self-heal for the aliased pattern):
    • reconstruct the `-` suffix from the dep name, so even a
      suffix-less pin installs the real binary package;
    • derive the version from the actually-installed parent, so pin drift
      can never desync the binary from the wrapper;
    • treat a dep as installed only when `package.json` exists and the
      version matches - tear down phantom/wrong-version dirs instead of trusting
      bare `-d`;
    • warn if the payload still didn't materialize after install.
  • spec: cover suffix reconstruction, parent-version derivation,
    phantom-dir reinstall, and correct-version skip.

Testing

  • `make shell-lint` - clean
  • `shellspec spec/npm_globals_spec.sh` - 50 examples, 0 failures (7 new)

Follow-up (not in this PR)

`codex` is declared in three places - bun global (package.json), the Homebrew
cask (`homebrew.nix`), and the nix overlay (`overlays/default.nix`). The bun
global wins on PATH. Consolidating to a single source would remove the
redundancy but is out of scope here.


Summary by cubic

Fixes Codex CLI failures by installing the real platform-native @openai/codex-* binary instead of the generic wrapper. Pins suffixed native packages and updates the installer to reconstruct the platform suffix, align with the installed parent version, and self-heal broken installs.

  • Bug Fixes

    • Reconstruct the -<triple> suffix for aliased optional deps.
    • Derive the native package version from the installed @openai/codex parent.
    • Treat installs as valid only if package.json exists and the version matches; remove phantom/wrong-version dirs.
    • Warn if the native payload is still missing after install.
    • Add shellspec coverage for suffix reconstruction, parent-version derivation, phantom-dir reinstall, and correct-version skip.
  • Dependencies

    • Pin @openai/codex-* optional deps to 0.142.5-<triple> suffixed versions.

Written for commit cbc9745. Summary will update on new commits.

Review in cubic

The @openai/codex-* optional pins used npm:@openai/codex@<ver> without the
platform-triple version suffix, so bun installed the generic JS wrapper under
the platform dir name instead of the tarball carrying vendor/.../bin/codex.
The CLI then died with 'Missing optional dependency @openai/codex-darwin-arm64'.

- package.json: pin the suffixed native packages (0.142.5-<triple>).
- install-npm-globals.sh: reconstruct the -<triple> suffix and derive the
  version from the actually-installed parent so pin drift can't desync the
  binary from the wrapper; reject phantom/wrong-version dirs instead of
  trusting bare -d; warn if the payload fails to materialize.
- spec: cover suffix reconstruction, parent-version derivation, phantom-dir
  reinstall, and correct-version skip.
@indent-zero

indent-zero Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor
PR Summary

The Codex CLI was dying at runtime with Missing optional dependency @openai/codex-darwin-arm64 because the aliased optional pins used npm:@openai/codex@<ver> (no -<triple> suffix), so bun fetched the generic JS wrapper tarball into the platform dir instead of the tarball that ships vendor/.../bin/codex. This PR both re-pins to the suffixed spec and hardens install-npm-globals.sh so pin drift, phantom dirs, and silent bun no-ops can't resurrect the bug.

  • package.json: bump the six @openai/codex-<triple> optional entries from npm:@openai/codex@0.142.2 to npm:@openai/codex@0.142.5-<triple> so the tarball actually carries the native binary.
  • install-npm-globals.sh: for npm:* aliases, reconstruct <base>@<ver>-<suffix> and prefer the installed parent wrapper's version over the pinned one so the binary tracks the wrapper across pin drift.
  • install-npm-globals.sh: replace the bare -d "already installed" check with a payload-aware check that reads ${dep}/package.json, tears down phantom (empty dir) and wrong-version installs, and warns to stderr when bun silently no-ops after bun add.
  • spec/npm_globals_spec.sh: add landmark-grep tests for the four new code paths plus an end-to-end integration Describe that drives a mock bun to verify suffix reconstruction from the installed parent, phantom-dir reinstall, and correct-version skip.

Issues

1 potential issue found:

  • Latent double-suffix: if ${GLOBAL_MODULES}/@openai/codex/package.json is absent when the optional loop runs, base_ver falls back to ${alias_spec##*@}, which for the new suffixed pins is already 0.142.5-darwin-arm64, so want_ver becomes 0.142.5-darwin-arm64-darwin-arm64 and the bun add spec is bogus. Trigger: the parent bun add failed silently earlier (the MISSING loop swallows errors with || echo "Install failed"), or @openai/codex is removed from dependencies while these optional pins remain — in either case the "Missing optional dependency" symptom this PR fixes reappears. → Autofix

CI Checks

Waiting for CI checks...


⚡ Autofix All Issues

@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved installation handling for native optional dependencies, including aliased packages, so the correct platform-specific package is installed and verified.
    • Fixed cases where an empty or incomplete install could be mistaken for a valid one, triggering a proper reinstall and warning if installation still doesn’t materialize.
    • Updated bundled native package versions across supported platforms.
  • Tests

    • Added coverage for aliased native binary installs, recovery from stale entries, and correct no-op behavior when a valid install already exists.

Walkthrough

The install script now reconstructs npm: alias specs by deriving base package version and platform suffix, and validates actual installed package.json payloads instead of relying on directory existence before deciding to reinstall. Codex optionalDependencies versions are bumped, and new spec tests cover the behavior.

Changes

Aliased Native Binary Install Self-Healing

Layer / File(s) Summary
Alias spec reconstruction
home-manager/modules/npm-globals/install-npm-globals.sh
Parses npm: alias entries and reconstructs install spec/want_ver using the base package's installed version and derived platform suffix.
Payload validation and reinstall logic
home-manager/modules/npm-globals/install-npm-globals.sh
Validates installed package.json version against want_ver, detects phantom/incomplete installs, strips stale optionalDependencies pins, removes bad directories, reinstalls via bun add --global, and warns on post-install payload mismatch.
Codex version bump
package.json
Updates @openai/codex-* optionalDependencies from 0.142.2 to 0.142.5 across all platforms.
Spec coverage
spec/npm_globals_spec.sh
Adds unit and integration tests for alias reconstruction, phantom detection, self-heal reinstall, and idempotent skip behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Script as install-npm-globals.sh
  participant FS as GLOBAL_MODULES/package.json
  participant Dotfiles as dotfiles package.json
  participant Bun as bun add --global

  Script->>FS: Read installed base package version
  Script->>Script: Reconstruct spec and want_ver for npm: alias
  Script->>FS: Check installed dep package.json version
  alt version matches want_ver
    Script->>Script: Skip install
  else phantom or incorrect version
    Script->>FS: Remove stale package directory
    Script->>Dotfiles: Strip dep from optionalDependencies
    Script->>Bun: Install dep with --minimum-release-age 0
    Bun-->>FS: Materialize package.json
    Script->>FS: Verify payload exists
    Script->>Script: Warn if payload still missing
  end
Loading

Possibly related PRs

  • shunkakinoki/dotfiles#1380: Both modify the same install script's version-check logic deciding whether to reinstall npm globals.
  • shunkakinoki/dotfiles#1408: Both modify install-npm-globals.sh and its spec to change global dependency install/validation logic.
  • shunkakinoki/dotfiles#1890: Both modify how codex native binary optionalDependencies specs are installed and verified in the same script.

Poem

A rabbit checked each package tight,
No phantom folder fools my sight! 🐰
Alias specs reborn anew,
want_ver matched, install true.
Codex hops to 0.142.5,
tests all green, my burrow thrives. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main fix: installing the real native binary for aliased optional dependencies.
Description check ✅ Passed The description is directly related to the changeset and explains the bug, fix, and tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/codex-native-binary-pin

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request enhances the global npm installation script to robustly handle aliased native binary dependencies (such as @openai/codex) by reconstructing platform-specific suffixes, resolving versions from installed parent packages, and ensuring phantom directories are reinstalled. It also updates package.json with explicit platform-suffixed versions and adds comprehensive integration tests. Feedback was provided to address edge cases in the shell script's alias parsing and version reconstruction to prevent potential syntax errors with scoped packages.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +271 to 296
if [[ $val == npm:* ]]; then
# Aliased native binary (codex pattern): npm:@openai/codex@<ver>.
# These packages are PUBLISHED as <base>@<ver>-<platform-suffix> (e.g.
# @openai/codex@0.142.5-darwin-arm64) and only that suffixed tarball
# carries the vendor binary. A bare <base>@<ver> pin (no suffix) silently
# reinstalls the generic JS wrapper under the platform dir name -- no
# binary -- and the CLI dies with "Missing optional dependency". So we
# reconstruct the suffixed spec here regardless of how package.json pins it.
alias_spec="${val#npm:}" # @openai/codex@0.142.2
base_name="${alias_spec%@*}" # @openai/codex
base_ver="${alias_spec##*@}" # 0.142.2 (fallback if parent not installed)
# Prefer the ACTUALLY INSTALLED parent version so the binary always matches
# the wrapper even when the package.json pins have drifted behind it.
base_pj="${GLOBAL_MODULES}/${base_name}/package.json"
if [ -f "$base_pj" ]; then
installed_base=$(jq -r '.version // empty' "$base_pj" 2>/dev/null || true)
[ -n "$installed_base" ] && base_ver="$installed_base"
fi
suffix="${dep#"${base_name}"-}" # darwin-arm64
if [ -n "$suffix" ] && [ "$suffix" != "$dep" ]; then
want_ver="${base_ver}-${suffix}"
else
want_ver="$base_ver"
fi
spec="${dep}@npm:${base_name}@${want_ver}"
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

There are a few potential edge cases in the parsing of the alias spec and version reconstruction:

  1. Robust Alias Parsing: If alias_spec does not contain a version (e.g., npm:@openai/codex), base_name will resolve to an empty string and base_ver will resolve to the package name itself. This is because ${alias_spec%@*} strips the entire string when there is only one @ (at the start of a scoped package).
  2. Invalid Version Suffixing: If base_ver is empty, appending the suffix results in -${suffix} (e.g., -darwin-arm64), which is an invalid version.
  3. Trailing @ in Spec: If want_ver is empty, constructing the spec as ${dep}@npm:${base_name}@${want_ver} results in a trailing @ (e.g., pkg@npm:base@), which is invalid npm/bun syntax.

We can make this more robust by checking if the stripped alias spec contains an @ before splitting, and only appending the suffix/version if they are non-empty.

    if [[ $val == npm:* ]]; then
      # Aliased native binary (codex pattern): npm:@openai/codex@<ver>.
      # These packages are PUBLISHED as <base>@<ver>-<platform-suffix> (e.g.
      # @openai/codex@0.142.5-darwin-arm64) and only that suffixed tarball
      # carries the vendor binary. A bare <base>@<ver> pin (no suffix) silently
      # reinstalls the generic JS wrapper under the platform dir name -- no
      # binary -- and the CLI dies with "Missing optional dependency". So we
      # reconstruct the suffixed spec here regardless of how package.json pins it.
      alias_spec="${val#npm:}"
      tmp="${alias_spec#@}"
      if [[ $tmp == *@* ]]; then
        base_name="${alias_spec%@*}"
        base_ver="${tmp#*@}"
      else
        base_name="$alias_spec"
        base_ver=""
      fi
      # Prefer the ACTUALLY INSTALLED parent version so the binary always matches
      # the wrapper even when the package.json pins have drifted behind it.
      base_pj="${GLOBAL_MODULES}/${base_name}/package.json"
      if [ -f "$base_pj" ]; then
        installed_base=$(jq -r '.version // empty' "$base_pj" 2>/dev/null || true)
        [ -n "$installed_base" ] && base_ver="$installed_base"
      fi
      suffix="${dep#"${base_name}"-}" # darwin-arm64
      if [ -n "$base_ver" ] && [ -n "$suffix" ] && [ "$suffix" != "$dep" ]; then
        want_ver="${base_ver}-${suffix}"
      else
        want_ver="$base_ver"
      fi
      if [ -n "$want_ver" ]; then
        spec="${dep}@npm:${base_name}@${want_ver}"
      else
        spec="${dep}@npm:${base_name}"
      fi
    fi
References
  1. When 'set -e' is enabled in Bash scripts, ensure that individual command failures within a loop do not prematurely abort the entire script. Handle potential failures gracefully, for example by appending '|| true'.

# reconstruct the suffixed spec here regardless of how package.json pins it.
alias_spec="${val#npm:}" # @openai/codex@0.142.2
base_name="${alias_spec%@*}" # @openai/codex
base_ver="${alias_spec##*@}" # 0.142.2 (fallback if parent not installed)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Latent double-suffix when parent wrapper isn't installed.

With the new suffixed pins in package.json (npm:@openai/codex@0.142.5-darwin-arm64), the alias-only fallback path here produces the wrong want_ver.

Walking it through:

alias_spec=@openai/codex@0.142.5-darwin-arm64
base_name=${alias_spec%@*}   # @openai/codex
base_ver=${alias_spec##*@}   # 0.142.5-darwin-arm64  <-- already has the suffix

The installed-parent override on lines 284–288 is what normally rescues this — it replaces base_ver with the clean parent version from ${GLOBAL_MODULES}/${base_name}/package.json. But when that file is missing, base_ver stays 0.142.5-darwin-arm64 and the block below computes:

suffix=darwin-arm64
want_ver=0.142.5-darwin-arm64-darwin-arm64
spec=@openai/codex-darwin-arm64@npm:@openai/codex@0.142.5-darwin-arm64-darwin-arm64

bun add on that spec fails, only the Warning: <dep> still missing after install line fires, and the Codex CLI is back to Missing optional dependency @openai/codex-darwin-arm64.

Triggers this can happen under:

  • The parent @openai/codex install in the MISSING loop (lines 197–201) failed transiently — the || echo "Install failed: $dep" swallows the error and the run continues to the optional loop with no parent on disk.
  • Someone drops @openai/codex from dependencies while keeping these npm:@openai/codex@<ver>-<triple> optional pins (the state this PR normalizes toward).

Strip the platform suffix from the fallback before appending it, e.g. after parsing:

# base_ver from the alias may already carry the -<triple> suffix under the new
# pinning scheme; drop it so the append below doesn't double it up.
base_ver=${base_ver%-"${PLATFORM_SUFFIX}"}
base_ver=${base_ver%-"${PLATFORM_MUSL_SUFFIX}"}

or pull the version out with a regex that stops at the first -.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
home-manager/modules/npm-globals/install-npm-globals.sh (1)

320-325: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Swallowed stderr hides the reason for install failures.

2>/dev/null on the bun add call discards bun's actual error output, leaving only a generic "Install failed" message. This would also mask diagnosis of issues like the double-suffix defect above (bun's "version not found" error would be invisible).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@home-manager/modules/npm-globals/install-npm-globals.sh` around lines 320 -
325, The `bun add` call in `install-npm-globals.sh` is swallowing stderr, which
hides the real failure reason. Remove the `2>/dev/null` redirection from the
`timeout 600 bun add --global "$spec" --minimum-release-age 0` command so bun’s
own error output is preserved, while keeping the existing fallback and
post-install verification around the `spec`/`dep` checks.
spec/npm_globals_spec.sh (1)

369-390: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Grep-based assertions only check that literal strings exist in the source, not behavior.

These four tests (want_ver, installed_base, phantom dir, still missing after install) merely grep the script for literal substrings rather than exercising behavior; the integration suite below does the real behavioral verification, so this is acceptable as a smoke-test layer. Consider adding one more integration case where the alias pin already includes the platform suffix (matching the new package.json format) and the parent's package.json is absent, to cover the double-suffix fallback path flagged in install-npm-globals.sh (lines 271-296).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@spec/npm_globals_spec.sh` around lines 369 - 390, The grep-only checks in the
aliased native binary spec are acceptable as smoke tests, but the missing
coverage is the double-suffix fallback path in install-npm-globals.sh. Add an
integration case that exercises the aliased native binary flow when the alias
pin already includes the platform suffix and the parent package.json is absent,
and assert the behavior through the existing npm globals install path rather
than only literal grep matches.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@home-manager/modules/npm-globals/install-npm-globals.sh`:
- Around line 271-296: The npm alias handling in install-npm-globals.sh is
appending the platform suffix twice when the parent package is missing and
base_ver already contains a suffix. Update the logic in the npm:* branch so the
spec construction around alias_spec, base_ver, suffix, and want_ver first
detects an already suffixed base_ver and avoids adding "-${suffix}" again before
setting spec for bun add.

---

Nitpick comments:
In `@home-manager/modules/npm-globals/install-npm-globals.sh`:
- Around line 320-325: The `bun add` call in `install-npm-globals.sh` is
swallowing stderr, which hides the real failure reason. Remove the `2>/dev/null`
redirection from the `timeout 600 bun add --global "$spec" --minimum-release-age
0` command so bun’s own error output is preserved, while keeping the existing
fallback and post-install verification around the `spec`/`dep` checks.

In `@spec/npm_globals_spec.sh`:
- Around line 369-390: The grep-only checks in the aliased native binary spec
are acceptable as smoke tests, but the missing coverage is the double-suffix
fallback path in install-npm-globals.sh. Add an integration case that exercises
the aliased native binary flow when the alias pin already includes the platform
suffix and the parent package.json is absent, and assert the behavior through
the existing npm globals install path rather than only literal grep matches.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 318bc9f9-d2e7-496c-872f-86e572bf3e02

📥 Commits

Reviewing files that changed from the base of the PR and between f8fbe68 and cbc9745.

📒 Files selected for processing (3)
  • home-manager/modules/npm-globals/install-npm-globals.sh
  • package.json
  • spec/npm_globals_spec.sh

Comment on lines +271 to 296
if [[ $val == npm:* ]]; then
# Aliased native binary (codex pattern): npm:@openai/codex@<ver>.
# These packages are PUBLISHED as <base>@<ver>-<platform-suffix> (e.g.
# @openai/codex@0.142.5-darwin-arm64) and only that suffixed tarball
# carries the vendor binary. A bare <base>@<ver> pin (no suffix) silently
# reinstalls the generic JS wrapper under the platform dir name -- no
# binary -- and the CLI dies with "Missing optional dependency". So we
# reconstruct the suffixed spec here regardless of how package.json pins it.
alias_spec="${val#npm:}" # @openai/codex@0.142.2
base_name="${alias_spec%@*}" # @openai/codex
base_ver="${alias_spec##*@}" # 0.142.2 (fallback if parent not installed)
# Prefer the ACTUALLY INSTALLED parent version so the binary always matches
# the wrapper even when the package.json pins have drifted behind it.
base_pj="${GLOBAL_MODULES}/${base_name}/package.json"
if [ -f "$base_pj" ]; then
installed_base=$(jq -r '.version // empty' "$base_pj" 2>/dev/null || true)
[ -n "$installed_base" ] && base_ver="$installed_base"
fi
suffix="${dep#"${base_name}"-}" # darwin-arm64
if [ -n "$suffix" ] && [ "$suffix" != "$dep" ]; then
want_ver="${base_ver}-${suffix}"
else
want_ver="$base_ver"
fi
spec="${dep}@npm:${base_name}@${want_ver}"
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm bash parameter-expansion behavior for the suffixed-alias fallback path.
val="npm:`@openai/codex`@0.142.5-darwin-arm64"
dep="`@openai/codex-darwin-arm64`"
alias_spec="${val#npm:}"
base_name="${alias_spec%@*}"
base_ver="${alias_spec##*@}"
suffix="${dep#"${base_name}"-}"
if [ -n "$suffix" ] && [ "$suffix" != "$dep" ]; then
  want_ver="${base_ver}-${suffix}"
else
  want_ver="$base_ver"
fi
echo "base_name=$base_name base_ver=$base_ver suffix=$suffix want_ver=$want_ver"

Repository: shunkakinoki/dotfiles

Length of output: 276


Avoid appending the platform suffix twice. If the alias pin already includes -darwin-arm64 and the parent package isn’t installed yet, base_ver stays suffixed and this code turns it into 0.142.5-darwin-arm64-darwin-arm64, which bun add can’t resolve. Guard against an already-suffixed base_ver before adding -${suffix}.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@home-manager/modules/npm-globals/install-npm-globals.sh` around lines 271 -
296, The npm alias handling in install-npm-globals.sh is appending the platform
suffix twice when the parent package is missing and base_ver already contains a
suffix. Update the logic in the npm:* branch so the spec construction around
alias_spec, base_ver, suffix, and want_ver first detects an already suffixed
base_ver and avoids adding "-${suffix}" again before setting spec for bun add.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="home-manager/modules/npm-globals/install-npm-globals.sh">

<violation number="1" location="home-manager/modules/npm-globals/install-npm-globals.sh:280">
P2: For a scoped package alias without an explicit version (e.g., `npm:@openai/codex` with no trailing `@<ver>`), this parameter expansion splits incorrectly: `${alias_spec%@*}` strips at the scope-level `@`, yielding `@openai` instead of the full package name, and `${alias_spec##*@}` yields `openai/codex` instead of empty. Consider checking whether the portion after the first `@` contains another `@` before splitting, to handle versionless alias specs gracefully.</violation>

<violation number="2" location="home-manager/modules/npm-globals/install-npm-globals.sh:291">
P2: The fallback `base_ver` (derived from the package.json alias spec via `##*@`) now contains the platform suffix because the new pins embed it (e.g., `npm:@openai/codex@0.142.5-darwin-arm64`). When the parent `@openai/codex` package isn't yet installed, this suffixed fallback version gets the platform suffix appended again, producing a double-suffixed version like `0.142.5-darwin-arm64-darwin-arm64`. The install then tries to fetch a non-existent npm version and fails.

This only triggers when the parent package is missing (edge case), since the script correctly overrides `base_ver` from the parent's `.version` field in the common path. Consider stripping the known suffix from `base_ver` before appending it, or extracting a clean base version from the alias spec.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

fi
suffix="${dep#"${base_name}"-}" # darwin-arm64
if [ -n "$suffix" ] && [ "$suffix" != "$dep" ]; then
want_ver="${base_ver}-${suffix}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: The fallback base_ver (derived from the package.json alias spec via ##*@) now contains the platform suffix because the new pins embed it (e.g., npm:@openai/codex@0.142.5-darwin-arm64). When the parent @openai/codex package isn't yet installed, this suffixed fallback version gets the platform suffix appended again, producing a double-suffixed version like 0.142.5-darwin-arm64-darwin-arm64. The install then tries to fetch a non-existent npm version and fails.

This only triggers when the parent package is missing (edge case), since the script correctly overrides base_ver from the parent's .version field in the common path. Consider stripping the known suffix from base_ver before appending it, or extracting a clean base version from the alias spec.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/modules/npm-globals/install-npm-globals.sh, line 291:

<comment>The fallback `base_ver` (derived from the package.json alias spec via `##*@`) now contains the platform suffix because the new pins embed it (e.g., `npm:@openai/codex@0.142.5-darwin-arm64`). When the parent `@openai/codex` package isn't yet installed, this suffixed fallback version gets the platform suffix appended again, producing a double-suffixed version like `0.142.5-darwin-arm64-darwin-arm64`. The install then tries to fetch a non-existent npm version and fails.

This only triggers when the parent package is missing (edge case), since the script correctly overrides `base_ver` from the parent's `.version` field in the common path. Consider stripping the known suffix from `base_ver` before appending it, or extracting a clean base version from the alias spec.</comment>

<file context>
@@ -262,27 +262,67 @@ if [ -n "$OPTIONAL_DEPS" ]; then
+      fi
+      suffix="${dep#"${base_name}"-}" # darwin-arm64
+      if [ -n "$suffix" ] && [ "$suffix" != "$dep" ]; then
+        want_ver="${base_ver}-${suffix}"
+      else
+        want_ver="$base_ver"
</file context>

# binary -- and the CLI dies with "Missing optional dependency". So we
# reconstruct the suffixed spec here regardless of how package.json pins it.
alias_spec="${val#npm:}" # @openai/codex@0.142.2
base_name="${alias_spec%@*}" # @openai/codex

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: For a scoped package alias without an explicit version (e.g., npm:@openai/codex with no trailing @<ver>), this parameter expansion splits incorrectly: ${alias_spec%@*} strips at the scope-level @, yielding @openai instead of the full package name, and ${alias_spec##*@} yields openai/codex instead of empty. Consider checking whether the portion after the first @ contains another @ before splitting, to handle versionless alias specs gracefully.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/modules/npm-globals/install-npm-globals.sh, line 280:

<comment>For a scoped package alias without an explicit version (e.g., `npm:@openai/codex` with no trailing `@<ver>`), this parameter expansion splits incorrectly: `${alias_spec%@*}` strips at the scope-level `@`, yielding `@openai` instead of the full package name, and `${alias_spec##*@}` yields `openai/codex` instead of empty. Consider checking whether the portion after the first `@` contains another `@` before splitting, to handle versionless alias specs gracefully.</comment>

<file context>
@@ -262,27 +262,67 @@ if [ -n "$OPTIONAL_DEPS" ]; then
+      # binary -- and the CLI dies with "Missing optional dependency". So we
+      # reconstruct the suffixed spec here regardless of how package.json pins it.
+      alias_spec="${val#npm:}"     # @openai/codex@0.142.2
+      base_name="${alias_spec%@*}" # @openai/codex
+      base_ver="${alias_spec##*@}" # 0.142.2 (fallback if parent not installed)
+      # Prefer the ACTUALLY INSTALLED parent version so the binary always matches
</file context>

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