Skip to content

bun update -g -i leaves opencode global symlink stale after bin target changes to opencode.exe #28114

Description

@alexaka1

Description

After updating opencode-ai globally with Bun using bun update -g -i, the opencode command stopped working even though the package installed successfully.

The update command reported:

bun update -g -i
✓ Selected 2 packages to update

Installing updates...

+ opencode-ai@1.15.4
+ vercel@54.1.0

24 packages installed [6.79s]

Afterward:

opencode
zsh: command not found: opencode

The installed package metadata and files did not match Bun's global symlink.

Installed package metadata:

node -p "JSON.stringify(require('$HOME/.bun/install/global/node_modules/opencode-ai/package.json').bin, null, 2)"
{
  "opencode": "./bin/opencode.exe"
}

Package-local bin directory:

ls -la ~/.bun/install/global/node_modules/opencode-ai/bin
-rwxr-xr-x ... opencode.exe

But Bun's global command link still pointed to the old path:

readlink ~/.bun/bin/opencode
../install/global/node_modules/opencode-ai/bin/opencode

That target no longer existed:

test -e ~/.bun/install/global/node_modules/opencode-ai/bin/opencode || echo "missing"
missing

So after the update, the installed package declared and contained:

~/.bun/install/global/node_modules/opencode-ai/bin/opencode.exe

but the global command shim still pointed at:

~/.bun/install/global/node_modules/opencode-ai/bin/opencode

I also reproduced this in an isolated BUN_INSTALL using the actual interactive update flow.

Initial install:

BUN_INSTALL=/tmp/opencode-bun-update-repro.LZI9nB \
PATH="/tmp/opencode-bun-update-repro.LZI9nB/bin:$PATH" \
bun install -g opencode-ai@1.15.0

Initial state:

package: 1.15.0 {"opencode":"./bin/opencode"}
symlink: ../install/global/node_modules/opencode-ai/bin/opencode
target exists

Then update:

BUN_INSTALL=/tmp/opencode-bun-update-repro.LZI9nB \
PATH="/tmp/opencode-bun-update-repro.LZI9nB/bin:$PATH" \
bun update -g -i

I selected opencode-ai, and Bun installed:

+ opencode-ai@1.15.4

Final state:

package: 1.15.4 {"opencode":"./bin/opencode.exe"}
bin dir contains: opencode.exe

But the symlink was still stale:

readlink /tmp/opencode-bun-update-repro.LZI9nB/bin/opencode
../install/global/node_modules/opencode-ai/bin/opencode

Verification:

test -e /tmp/opencode-bun-update-repro.LZI9nB/install/global/node_modules/opencode-ai/bin/opencode && echo "old target exists" || echo "old target missing"
test -e /tmp/opencode-bun-update-repro.LZI9nB/install/global/node_modules/opencode-ai/bin/opencode.exe && echo "new target exists" || echo "new target missing"
test -e /tmp/opencode-bun-update-repro.LZI9nB/bin/opencode && echo "global command resolves to existing target" || echo "global command symlink is broken"
old target missing
new target exists
global command symlink is broken

This appears specific to bun update -g -i. A clean direct global install/upgrade path did relink correctly in a separate test, but the interactive global update path did not. This is regardless of if postinstall scripts are trusted or not.

Plugins

No response

OpenCode version

1.15.4

Steps to reproduce

  1. Create an isolated Bun global install root:
tmpdir="$(mktemp -d /tmp/opencode-bun-update-repro.XXXXXX)"
  1. Install opencode-ai@1.15.0 globally into that isolated root:
BUN_INSTALL="$tmpdir" PATH="$tmpdir/bin:$PATH" bun install -g opencode-ai@1.15.0
  1. Confirm the initial symlink points to bin/opencode:
readlink "$tmpdir/bin/opencode"

Expected:

../install/global/node_modules/opencode-ai/bin/opencode
  1. Run the interactive global update:
BUN_INSTALL="$tmpdir" PATH="$tmpdir/bin:$PATH" bun update -g -i
  1. Select opencode-ai and let it update to 1.15.4.

  2. Inspect the installed package metadata:

node -p "const p=require('$tmpdir/install/global/node_modules/opencode-ai/package.json'); p.version + ' ' + JSON.stringify(p.bin)"

Actual:

1.15.4 {"opencode":"./bin/opencode.exe"}
  1. Inspect the global symlink:
readlink "$tmpdir/bin/opencode"

Actual:

../install/global/node_modules/opencode-ai/bin/opencode
  1. Verify the symlink is broken:
test -e "$tmpdir/install/global/node_modules/opencode-ai/bin/opencode" && echo "old target exists" || echo "old target missing"
test -e "$tmpdir/install/global/node_modules/opencode-ai/bin/opencode.exe" && echo "new target exists" || echo "new target missing"
test -e "$tmpdir/bin/opencode" && echo "global command resolves to existing target" || echo "global command symlink is broken"

Actual:

old target missing
new target exists
global command symlink is broken

Screenshot and/or share link

No response

Operating System

macOS 15.7.5 (Build 24G624), arm64

Terminal

not relevant

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions