-
Notifications
You must be signed in to change notification settings - Fork 4
fix: resolve bunfig preload conflict via postinstall symlink (#245) #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add postinstall.mjs that creates a symlink from bin/shuvcode to the platform-specific compiled binary, matching upstream opencode behavior. This ensures users execute the binary directly, bypassing Bun's bunfig.toml loading that causes preload resolution failures. Changes: - Add postinstall.mjs with platform detection and symlink creation - Update build.ts to enable autoloadTsconfig and autoloadPackageJson - Update publish.ts to include postinstall.mjs in published package
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4 files reviewed, 1 comment
| function findBinary() { | ||
| const { platform, arch } = detectPlatformAndArch() | ||
| const packageName = `shuvcode-${platform}-${arch}` | ||
| const binaryName = platform === "windows" ? "shuvcode.exe" : "shuvcode" | ||
|
|
||
| try { | ||
| // Use require.resolve to find the package | ||
| const packageJsonPath = require.resolve(`${packageName}/package.json`) | ||
| const packageDir = path.dirname(packageJsonPath) | ||
| const binaryPath = path.join(packageDir, "bin", binaryName) | ||
|
|
||
| if (!fs.existsSync(binaryPath)) { | ||
| throw new Error(`Binary not found at ${binaryPath}`) | ||
| } | ||
|
|
||
| return { binaryPath, binaryName } | ||
| } catch (error) { | ||
| throw new Error(`Could not find package ${packageName}: ${error.message}`) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Missing baseline variant fallback - will fail for baseline packages like shuvcode-linux-x64-baseline
The current implementation only tries the exact package name shuvcode-${platform}-${arch}, but the build script creates baseline variants (e.g., shuvcode-linux-x64-baseline). The existing bin/shuvcode launcher handles this by searching for any package that starts with the base name (line 57: if (!entry.startsWith(base))).
| function findBinary() { | |
| const { platform, arch } = detectPlatformAndArch() | |
| const packageName = `shuvcode-${platform}-${arch}` | |
| const binaryName = platform === "windows" ? "shuvcode.exe" : "shuvcode" | |
| try { | |
| // Use require.resolve to find the package | |
| const packageJsonPath = require.resolve(`${packageName}/package.json`) | |
| const packageDir = path.dirname(packageJsonPath) | |
| const binaryPath = path.join(packageDir, "bin", binaryName) | |
| if (!fs.existsSync(binaryPath)) { | |
| throw new Error(`Binary not found at ${binaryPath}`) | |
| } | |
| return { binaryPath, binaryName } | |
| } catch (error) { | |
| throw new Error(`Could not find package ${packageName}: ${error.message}`) | |
| } | |
| function findBinary() { | |
| const { platform, arch } = detectPlatformAndArch() | |
| const basePackageName = `shuvcode-${platform}-${arch}` | |
| const binaryName = platform === "windows" ? "shuvcode.exe" : "shuvcode" | |
| try { | |
| // Try exact package name first | |
| try { | |
| const packageJsonPath = require.resolve(`${basePackageName}/package.json`) | |
| const packageDir = path.dirname(packageJsonPath) | |
| const binaryPath = path.join(packageDir, "bin", binaryName) | |
| if (fs.existsSync(binaryPath)) { | |
| return { binaryPath, binaryName } | |
| } | |
| } catch (error) { | |
| // Exact match failed, try baseline variant | |
| } | |
| // Fallback: search for baseline variants (e.g., shuvcode-linux-x64-baseline) | |
| const nodeModulesPath = path.join(__dirname, "..", "node_modules") | |
| if (fs.existsSync(nodeModulesPath)) { | |
| const entries = fs.readdirSync(nodeModulesPath) | |
| for (const entry of entries) { | |
| if (entry.startsWith(basePackageName)) { | |
| const binaryPath = path.join(nodeModulesPath, entry, "bin", binaryName) | |
| if (fs.existsSync(binaryPath)) { | |
| return { binaryPath, binaryName } | |
| } | |
| } | |
| } | |
| } | |
| throw new Error(`No binary package found for ${basePackageName}`) | |
| } catch (error) { | |
| throw new Error(`Could not find package ${basePackageName}: ${error.message}`) | |
| } | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/opencode/postinstall.mjs
Line: 50:68
Comment:
**logic:** Missing baseline variant fallback - will fail for baseline packages like `shuvcode-linux-x64-baseline`
The current implementation only tries the exact package name `shuvcode-${platform}-${arch}`, but the build script creates baseline variants (e.g., `shuvcode-linux-x64-baseline`). The existing `bin/shuvcode` launcher handles this by searching for any package that **starts with** the base name (line 57: `if (!entry.startsWith(base))`).
```suggestion
function findBinary() {
const { platform, arch } = detectPlatformAndArch()
const basePackageName = `shuvcode-${platform}-${arch}`
const binaryName = platform === "windows" ? "shuvcode.exe" : "shuvcode"
try {
// Try exact package name first
try {
const packageJsonPath = require.resolve(`${basePackageName}/package.json`)
const packageDir = path.dirname(packageJsonPath)
const binaryPath = path.join(packageDir, "bin", binaryName)
if (fs.existsSync(binaryPath)) {
return { binaryPath, binaryName }
}
} catch (error) {
// Exact match failed, try baseline variant
}
// Fallback: search for baseline variants (e.g., shuvcode-linux-x64-baseline)
const nodeModulesPath = path.join(__dirname, "..", "node_modules")
if (fs.existsSync(nodeModulesPath)) {
const entries = fs.readdirSync(nodeModulesPath)
for (const entry of entries) {
if (entry.startsWith(basePackageName)) {
const binaryPath = path.join(nodeModulesPath, entry, "bin", binaryName)
if (fs.existsSync(binaryPath)) {
return { binaryPath, binaryName }
}
}
}
}
throw new Error(`No binary package found for ${basePackageName}`)
} catch (error) {
throw new Error(`Could not find package ${basePackageName}: ${error.message}`)
}
}
```
How can I resolve this? If you propose a fix, please make it concise.Apply Greptile suggestion to handle baseline packages like shuvcode-linux-x64-baseline by searching for packages that start with the base package name when exact match fails.
Summary
Fixes issue #245 where shuvcode fails with "preload not found @opentui/solid/preload" when run from directories with their own bunfig.toml.
Changes
Fixes
postinstall.mjsthat creates a symlink frombin/shuvcodeto the platform-specific compiled binary, matching upstream opencode behaviorbuild.tsto enableautoloadTsconfigandautoloadPackageJsoncompiler optionspublish.tsto include postinstall.mjs in the published package and configure the postinstall scriptDocumentation
CONTEXT/PLAN-245-bunfig-preload-conflict-fix-2026-01-02.mdexplaining the root cause analysis and solutionRoot Cause
The shuvcode package used a Node.js launcher script at
bin/shuvcode, while upstream opencode uses a symlink to the compiled ELF binary. When Bun executes the launcher script, it reads the CWD'sbunfig.tomland attempts to apply preloads before the actual binary runs.Breaking Changes
None
Testing
Manual testing required:
bun install -g shuvcodebunfig.tomlcontaining preloadsshuvcode- should launch successfully without preload errorsGreptile Summary
Fixes issue #245 by adding a postinstall script that creates a symlink from
bin/shuvcodeto the platform-specific compiled binary, matching upstreamopencode-aibehavior. This ensures the compiled ELF binary runs directly instead of through a Node.js launcher script, preventing Bun from loading the CWD'sbunfig.tomlconfiguration.Key changes:
postinstall.mjsthat detects platform/arch and creates symlink to the appropriate binary packagepublish.tsto include postinstall script and copypostinstall.mjsto published packagebuild.tsto enableautoloadTsconfigandautoloadPackageJsoncompiler optionsIssue found:
postinstall.mjsscript only tries to resolve the exact package name (e.g.,shuvcode-linux-x64) and will fail for baseline variants likeshuvcode-linux-x64-baseline. The existingbin/shuvcodelauncher handles this by searching for packages that start with the base name. The postinstall script needs similar fallback logic.Confidence Score: 3/5
packages/opencode/postinstall.mjs- missing baseline variant fallback will cause installation failures on some systemsImportant Files Changed
bin/shuvcodeto platform-specific binary; missing baseline variant fallback logicautoloadTsconfig: trueandautoloadPackageJson: trueto compiler optionspostinstall.mjsto published packageSequence Diagram
sequenceDiagram participant User participant Shell participant NPM as npm/bun participant PostInstall as postinstall.mjs participant BinDir as bin/shuvcode participant PlatformBinary as shuvcode-linux-x64/bin/shuvcode participant BunRuntime as Bun Runtime Note over User,BunRuntime: Installation Phase User->>NPM: bun install -g shuvcode NPM->>NPM: Install main package NPM->>NPM: Install optional dependency (shuvcode-linux-x64) NPM->>PostInstall: Run postinstall script PostInstall->>PostInstall: detectPlatformAndArch() PostInstall->>PostInstall: findBinary() - resolve shuvcode-linux-x64 PostInstall->>BinDir: Create bin/ directory PostInstall->>BinDir: fs.symlinkSync(PlatformBinary, bin/shuvcode) BinDir-->>PostInstall: Symlink created PostInstall-->>NPM: Success NPM-->>User: Installation complete Note over User,BunRuntime: Execution Phase (Before Fix) User->>Shell: shuvcode (in dir with bunfig.toml) Shell->>BinDir: Execute bin/shuvcode (Node launcher script) BinDir->>BunRuntime: #!/usr/bin/env node BunRuntime->>BunRuntime: Read CWD's bunfig.toml BunRuntime->>BunRuntime: Try to load preload "@opentui/solid/preload" BunRuntime-->>User: ERROR: preload not found Note over User,BunRuntime: Execution Phase (After Fix) User->>Shell: shuvcode (in dir with bunfig.toml) Shell->>BinDir: Resolve bin/shuvcode symlink BinDir->>PlatformBinary: Follow symlink to ELF binary PlatformBinary->>PlatformBinary: Execute compiled binary directly PlatformBinary->>PlatformBinary: autoloadBunfig: false (compiled in) PlatformBinary->>PlatformBinary: Ignore CWD's bunfig.toml PlatformBinary-->>User: TUI launches successfully