Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit 7344358

Browse files
Honarekram1-node
andauthored
fix: resolve bun/pnpm global install failures on Windows (anomalyco#4275)
Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
1 parent 609ab06 commit 7344358

3 files changed

Lines changed: 36 additions & 74 deletions

File tree

packages/opencode/script/build.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ const allTargets: {
6666
avx2: false,
6767
},
6868
{
69-
os: "windows",
69+
os: "win32",
7070
arch: "x64",
7171
},
7272
{
73-
os: "windows",
73+
os: "win32",
7474
arch: "x64",
7575
avx2: false,
7676
},
@@ -88,7 +88,8 @@ await $`bun install --os="*" --cpu="*" @parcel/watcher@${pkg.dependencies["@parc
8888
for (const item of targets) {
8989
const name = [
9090
pkg.name,
91-
item.os,
91+
// changing to win32 flags npm for some reason
92+
item.os === "win32" ? "windows" : item.os,
9293
item.arch,
9394
item.avx2 === false ? "baseline" : undefined,
9495
item.abi === undefined ? undefined : item.abi,
@@ -127,7 +128,7 @@ for (const item of targets) {
127128
{
128129
name,
129130
version: Script.version,
130-
os: [item.os === "windows" ? "win32" : item.os],
131+
os: [item.os],
131132
cpu: [item.arch],
132133
},
133134
null,

packages/opencode/script/postinstall.mjs

Lines changed: 3 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,6 @@ function prepareBinDirectory(binaryName) {
8585
return { binDir, targetPath }
8686
}
8787

88-
function copyBinary(sourcePath, binaryName) {
89-
const { targetPath } = prepareBinDirectory(binaryName)
90-
91-
fs.copyFileSync(sourcePath, targetPath)
92-
console.log(`opencode binary installed: ${targetPath}`)
93-
94-
// Verify the file exists after operation
95-
if (!fs.existsSync(targetPath)) {
96-
throw new Error(`Failed to copy binary to ${targetPath}`)
97-
}
98-
}
99-
10088
function symlinkBinary(sourcePath, binaryName) {
10189
const { targetPath } = prepareBinDirectory(binaryName)
10290

@@ -109,64 +97,12 @@ function symlinkBinary(sourcePath, binaryName) {
10997
}
11098
}
11199

112-
async function regenerateWindowsCmdWrappers() {
113-
console.log("Windows + npm detected: Forcing npm to rebuild bin links")
114-
115-
try {
116-
const { execSync } = require("child_process")
117-
const pkgPath = path.join(__dirname, "..")
118-
119-
// npm_config_global is string | undefined
120-
// if it exists, the value is true
121-
const isGlobal = process.env.npm_config_global === "true" || pkgPath.includes(path.join("npm", "node_modules"))
122-
123-
// The npm rebuild command does 2 things - Execute lifecycle scripts and rebuild bin links
124-
// We want to skip lifecycle scripts to avoid infinite loops, so we use --ignore-scripts
125-
const cmd = `npm rebuild opencode-ai --ignore-scripts${isGlobal ? " -g" : ""}`
126-
const opts = {
127-
stdio: "inherit",
128-
shell: true,
129-
...(isGlobal ? {} : { cwd: path.join(pkgPath, "..", "..") }), // For local, run from project root
130-
}
131-
132-
console.log(`Running: ${cmd}`)
133-
execSync(cmd, opts)
134-
console.log("Successfully rebuilt npm bin links")
135-
} catch (error) {
136-
console.error("Error rebuilding npm links:", error.message)
137-
console.error("npm rebuild failed. You may need to manually run: npm rebuild opencode-ai --ignore-scripts")
138-
}
139-
}
140-
141100
async function main() {
142101
try {
143102
if (os.platform() === "win32") {
144-
// NPM eg format - npm/11.4.2 node/v24.4.1 win32 x64
145-
// Bun eg format - bun/1.2.19 npm/? node/v24.3.0 win32 x64
146-
// pnpm eg format - pnpm/8.10.0 npm/? node/v20.10.0 win32 x64
147-
const userAgent = process.env.npm_config_user_agent || ""
148-
149-
if (userAgent.startsWith("npm")) {
150-
await regenerateWindowsCmdWrappers()
151-
return
152-
}
153-
154-
if (userAgent.startsWith("bun")) {
155-
console.log("Windows + bun detected: Setting up binary")
156-
const { binaryPath, binaryName } = findBinary()
157-
copyBinary(binaryPath, binaryName)
158-
return
159-
}
160-
161-
if (userAgent.startsWith("pnpm")) {
162-
console.log("Windows + pnpm detected: Setting up binary")
163-
const { binaryPath, binaryName } = findBinary()
164-
copyBinary(binaryPath, binaryName)
165-
return
166-
}
167-
168-
// Unknown package manager on Windows
169-
console.log("Windows detected but unknown package manager, skipping postinstall")
103+
// On Windows, the .exe is already included in the package and bin field points to it
104+
// No postinstall setup needed
105+
console.log("Windows detected: binary setup not needed (using packaged .exe)")
170106
return
171107
}
172108

packages/opencode/script/publish.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
import { $ } from "bun"
33
import pkg from "../package.json"
44
import { Script } from "@opencode-ai/script"
5+
import { fileURLToPath } from "url"
6+
import fs from "fs"
57

6-
const dir = new URL("..", import.meta.url).pathname
8+
const dir = fileURLToPath(new URL("..", import.meta.url))
79
process.chdir(dir)
810

911
const { binaries } = await import("./build.ts")
@@ -15,14 +17,29 @@ const { binaries } = await import("./build.ts")
1517

1618
await $`mkdir -p ./dist/${pkg.name}`
1719
await $`cp -r ./bin ./dist/${pkg.name}/bin`
20+
21+
// Copy Windows .exe if any Windows binaries were built
22+
let hasWindowsBinary = false
23+
for (const binaryName of Object.keys(binaries)) {
24+
if (binaryName.includes("win32")) {
25+
const winBinaryPath = `./dist/${binaryName}/bin/opencode.exe`
26+
if (fs.existsSync(winBinaryPath)) {
27+
await $`cp ${winBinaryPath} ./dist/${pkg.name}/bin/opencode.exe`
28+
hasWindowsBinary = true
29+
break
30+
}
31+
}
32+
}
33+
1834
await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs`
1935
await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs`
36+
2037
await Bun.file(`./dist/${pkg.name}/package.json`).write(
2138
JSON.stringify(
2239
{
2340
name: pkg.name + "-ai",
2441
bin: {
25-
[pkg.name]: `./bin/${pkg.name}`,
42+
[pkg.name]: hasWindowsBinary ? `./bin/${pkg.name}.exe` : `./bin/${pkg.name}`,
2643
},
2744
scripts: {
2845
preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs",
@@ -36,7 +53,15 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write(
3653
),
3754
)
3855
for (const [name] of Object.entries(binaries)) {
39-
await $`cd dist/${name} && chmod 777 -R . && bun publish --access public --tag ${Script.channel}`
56+
try {
57+
process.chdir(`./dist/${name}`)
58+
if (process.platform !== "win32") {
59+
await $`chmod 755 -R .`
60+
}
61+
await $`bun publish --access public --tag ${Script.channel}`
62+
} finally {
63+
process.chdir(dir)
64+
}
4065
}
4166
await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${Script.channel}`
4267

0 commit comments

Comments
 (0)