summaryrefslogtreecommitdiffhomepage
path: root/nix
diff options
context:
space:
mode:
authorCaleb Norton <[email protected]>2026-01-18 11:14:13 -0600
committerGitHub <[email protected]>2026-01-18 11:14:13 -0600
commitdac099a4892689d11abedb0fcc1098b50e0958c8 (patch)
treeb47a7a4bae294e0d4222fac21605a380d54b3341 /nix
parent5009f10406c15c4b69c04fa626756ee7bf81b300 (diff)
downloadopencode-dac099a4892689d11abedb0fcc1098b50e0958c8.tar.gz
opencode-dac099a4892689d11abedb0fcc1098b50e0958c8.zip
feat(nix): overhaul nix flake and packages (#9032)
Diffstat (limited to 'nix')
-rw-r--r--nix/bundle.ts40
-rw-r--r--nix/desktop.nix191
-rw-r--r--nix/node-modules.nix62
-rw-r--r--nix/opencode.nix211
-rw-r--r--nix/scripts/bun-build.ts120
-rw-r--r--nix/scripts/patch-wasm.ts43
6 files changed, 183 insertions, 484 deletions
diff --git a/nix/bundle.ts b/nix/bundle.ts
deleted file mode 100644
index effb1dff7..000000000
--- a/nix/bundle.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env bun
-
-import solidPlugin from "./node_modules/@opentui/solid/scripts/solid-plugin"
-import path from "path"
-import fs from "fs"
-
-const dir = process.cwd()
-const parser = fs.realpathSync(path.join(dir, "node_modules/@opentui/core/parser.worker.js"))
-const worker = "./src/cli/cmd/tui/worker.ts"
-const version = process.env.OPENCODE_VERSION ?? "local"
-const channel = process.env.OPENCODE_CHANNEL ?? "local"
-
-fs.rmSync(path.join(dir, "dist"), { recursive: true, force: true })
-
-const result = await Bun.build({
- entrypoints: ["./src/index.ts", worker, parser],
- outdir: "./dist",
- target: "bun",
- sourcemap: "none",
- tsconfig: "./tsconfig.json",
- plugins: [solidPlugin],
- external: ["@opentui/core"],
- define: {
- OPENCODE_VERSION: `'${version}'`,
- OPENCODE_CHANNEL: `'${channel}'`,
- // Leave undefined so runtime picks bundled/dist worker or fallback in code.
- OPENCODE_WORKER_PATH: "undefined",
- OTUI_TREE_SITTER_WORKER_PATH: 'new URL("./cli/cmd/tui/parser.worker.js", import.meta.url).href',
- },
-})
-
-if (!result.success) {
- console.error("bundle failed")
- for (const log of result.logs) console.error(log)
- process.exit(1)
-}
-
-const parserOut = path.join(dir, "dist/src/cli/cmd/tui/parser.worker.js")
-fs.mkdirSync(path.dirname(parserOut), { recursive: true })
-await Bun.write(parserOut, Bun.file(parser))
diff --git a/nix/desktop.nix b/nix/desktop.nix
index 9fb73b563..9625f75c2 100644
--- a/nix/desktop.nix
+++ b/nix/desktop.nix
@@ -2,166 +2,99 @@
lib,
stdenv,
rustPlatform,
- bun,
pkg-config,
- dbus ? null,
- openssl,
- glib ? null,
- gtk3 ? null,
- libsoup_3 ? null,
- webkitgtk_4_1 ? null,
- librsvg ? null,
- libappindicator-gtk3 ? null,
+ cargo-tauri,
+ bun,
+ nodejs,
cargo,
rustc,
- makeBinaryWrapper,
- copyDesktopItems,
- makeDesktopItem,
- nodejs,
jq,
+ wrapGAppsHook4,
+ makeWrapper,
+ dbus,
+ glib,
+ gtk4,
+ libsoup_3,
+ librsvg,
+ libappindicator,
+ glib-networking,
+ openssl,
+ webkitgtk_4_1,
+ gst_all_1,
+ opencode,
}:
-args:
-let
- scripts = args.scripts;
- mkModules =
- attrs:
- args.mkNodeModules (
- attrs
- // {
- canonicalizeScript = scripts + "/canonicalize-node-modules.ts";
- normalizeBinsScript = scripts + "/normalize-bun-binaries.ts";
- }
- );
-in
-rustPlatform.buildRustPackage rec {
+rustPlatform.buildRustPackage (finalAttrs: {
pname = "opencode-desktop";
- version = args.version;
+ inherit (opencode)
+ version
+ src
+ node_modules
+ patches
+ ;
- src = args.src;
-
- # We need to set the root for cargo, but we also need access to the whole repo.
- postUnpack = ''
- # Update sourceRoot to point to the tauri app
- sourceRoot+=/packages/desktop/src-tauri
- '';
-
- cargoLock = {
- lockFile = ../packages/desktop/src-tauri/Cargo.lock;
- allowBuiltinFetchGit = true;
- };
-
- node_modules = mkModules {
- version = version;
- src = src;
- };
+ cargoRoot = "packages/desktop/src-tauri";
+ cargoLock.lockFile = ../packages/desktop/src-tauri/Cargo.lock;
+ buildAndTestSubdir = finalAttrs.cargoRoot;
nativeBuildInputs = [
pkg-config
+ cargo-tauri.hook
bun
- makeBinaryWrapper
- copyDesktopItems
+ nodejs # for patchShebangs node_modules
cargo
rustc
- nodejs
jq
- ];
-
- # based on packages/desktop/src-tauri/release/appstream.metainfo.xml
- desktopItems = lib.optionals stdenv.isLinux [
- (makeDesktopItem {
- name = "ai.opencode.opencode";
- desktopName = "OpenCode";
- comment = "Open source AI coding agent";
- exec = "opencode-desktop";
- icon = "opencode";
- terminal = false;
- type = "Application";
- categories = [ "Development" "IDE" ];
- startupWMClass = "opencode";
- })
- ];
-
- buildInputs = [
- openssl
+ makeWrapper
]
- ++ lib.optionals stdenv.isLinux [
+ ++ lib.optionals stdenv.hostPlatform.isLinux [ wrapGAppsHook4 ];
+
+ buildInputs = lib.optionals stdenv.isLinux [
dbus
glib
- gtk3
+ gtk4
libsoup_3
- webkitgtk_4_1
librsvg
- libappindicator-gtk3
+ libappindicator
+ glib-networking
+ openssl
+ webkitgtk_4_1
+ gst_all_1.gstreamer
+ gst_all_1.gst-plugins-base
+ gst_all_1.gst-plugins-good
];
- preBuild = ''
- # Restore node_modules
- pushd ../../..
-
- # Copy node_modules from the fixed-output derivation
- # We use cp -r --no-preserve=mode to ensure we can write to them if needed,
- # though we usually just read.
- cp -r ${node_modules}/node_modules .
- cp -r ${node_modules}/packages .
+ strictDeps = true;
- # Ensure node_modules is writable so patchShebangs can update script headers
- chmod -R u+w node_modules
- # Ensure workspace packages are writable for tsgo incremental outputs (.tsbuildinfo)
- chmod -R u+w packages
- # Patch shebangs so scripts can run
+ preBuild = ''
+ cp -a ${finalAttrs.node_modules}/{node_modules,packages} .
+ chmod -R u+w node_modules packages
patchShebangs node_modules
+ patchShebangs packages/desktop/node_modules
- # Copy sidecar
mkdir -p packages/desktop/src-tauri/sidecars
- targetTriple=${stdenv.hostPlatform.rust.rustcTarget}
- cp ${args.opencode}/bin/opencode packages/desktop/src-tauri/sidecars/opencode-cli-$targetTriple
-
- # Merge prod config into tauri.conf.json
- if ! jq -s '.[0] * .[1]' \
- packages/desktop/src-tauri/tauri.conf.json \
- packages/desktop/src-tauri/tauri.prod.conf.json \
- > packages/desktop/src-tauri/tauri.conf.json.tmp; then
- echo "Error: failed to merge tauri.conf.json with tauri.prod.conf.json" >&2
- exit 1
- fi
- mv packages/desktop/src-tauri/tauri.conf.json.tmp packages/desktop/src-tauri/tauri.conf.json
-
- # Build the frontend
- cd packages/desktop
-
- # The 'build' script runs 'bun run typecheck && vite build'.
- bun run build
-
- popd
+ cp ${opencode}/bin/opencode packages/desktop/src-tauri/sidecars/opencode-cli-${stdenv.hostPlatform.rust.rustcTarget}
'';
- # Tauri bundles the assets during the rust build phase (which happens after preBuild).
- # It looks for them in the location specified in tauri.conf.json.
-
- postInstall = lib.optionalString stdenv.isLinux ''
- # Install icon
- mkdir -p $out/share/icons/hicolor/128x128/apps
- cp ../../../packages/desktop/src-tauri/icons/prod/128x128.png $out/share/icons/hicolor/128x128/apps/opencode.png
+ # see publish-tauri job in .github/workflows/publish.yml
+ tauriBuildFlags = [
+ "--config"
+ "tauri.prod.conf.json"
+ "--no-sign" # no code signing or auto updates
+ ];
- # Wrap the binary to ensure it finds the libraries
- wrapProgram $out/bin/opencode-desktop \
- --prefix LD_LIBRARY_PATH : ${
- lib.makeLibraryPath [
- gtk3
- webkitgtk_4_1
- librsvg
- glib
- libsoup_3
- ]
- }
+ # FIXME: workaround for concerns about case insensitive filesystems
+ # should be removed once binary is renamed or decided otherwise
+ # darwin output is a .app bundle so no conflict
+ postFixup = lib.optionalString stdenv.hostPlatform.isLinux ''
+ mv $out/bin/OpenCode $out/bin/opencode-desktop
+ sed -i 's|^Exec=OpenCode$|Exec=opencode-desktop|' $out/share/applications/OpenCode.desktop
'';
- meta = with lib; {
+ meta = {
description = "OpenCode Desktop App";
homepage = "https://opencode.ai";
- license = licenses.mit;
- maintainers = with maintainers; [ ];
+ license = lib.licenses.mit;
mainProgram = "opencode-desktop";
- platforms = platforms.linux ++ platforms.darwin;
+ inherit (opencode.meta) platforms;
};
-}
+}) \ No newline at end of file
diff --git a/nix/node-modules.nix b/nix/node-modules.nix
deleted file mode 100644
index 2a8f0a47c..000000000
--- a/nix/node-modules.nix
+++ /dev/null
@@ -1,62 +0,0 @@
-{
- hash,
- lib,
- stdenvNoCC,
- bun,
- cacert,
- curl,
- bunCpu,
- bunOs,
-}:
-args:
-stdenvNoCC.mkDerivation {
- pname = "opencode-node_modules";
- inherit (args) version src;
-
- impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
- "GIT_PROXY_COMMAND"
- "SOCKS_SERVER"
- ];
-
- nativeBuildInputs = [
- bun
- cacert
- curl
- ];
-
- dontConfigure = true;
-
- buildPhase = ''
- runHook preBuild
- export HOME=$(mktemp -d)
- export BUN_INSTALL_CACHE_DIR=$(mktemp -d)
- bun install \
- --cpu="${bunCpu}" \
- --os="${bunOs}" \
- --frozen-lockfile \
- --ignore-scripts \
- --no-progress \
- --linker=isolated
- bun --bun ${args.canonicalizeScript}
- bun --bun ${args.normalizeBinsScript}
- runHook postBuild
- '';
-
- installPhase = ''
- runHook preInstall
- mkdir -p $out
- while IFS= read -r dir; do
- rel="''${dir#./}"
- dest="$out/$rel"
- mkdir -p "$(dirname "$dest")"
- cp -R "$dir" "$dest"
- done < <(find . -type d -name node_modules -prune | sort)
- runHook postInstall
- '';
-
- dontFixup = true;
-
- outputHashAlgo = "sha256";
- outputHashMode = "recursive";
- outputHash = hash;
-}
diff --git a/nix/opencode.nix b/nix/opencode.nix
index 714aabe09..4d6f8e9b4 100644
--- a/nix/opencode.nix
+++ b/nix/opencode.nix
@@ -2,60 +2,115 @@
lib,
stdenvNoCC,
bun,
- ripgrep,
+ sysctl,
makeBinaryWrapper,
+ models-dev,
+ ripgrep,
+ installShellFiles,
+ versionCheckHook,
+ writableTmpDirAsHomeHook,
+ rev ? "dirty",
}:
-args:
let
- inherit (args) scripts;
- mkModules =
- attrs:
- args.mkNodeModules (
- attrs
- // {
- canonicalizeScript = scripts + "/canonicalize-node-modules.ts";
- normalizeBinsScript = scripts + "/normalize-bun-binaries.ts";
- }
- );
+ packageJson = lib.pipe ../packages/opencode/package.json [
+ builtins.readFile
+ builtins.fromJSON
+ ];
in
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "opencode";
- inherit (args) version src;
+ version = "${packageJson.version}-${rev}";
+
+ src = lib.fileset.toSource {
+ root = ../.;
+ fileset = lib.fileset.intersection (lib.fileset.fromSource (lib.sources.cleanSource ../.)) (
+ lib.fileset.unions [
+ ../packages
+ ../bun.lock
+ ../package.json
+ ../patches
+ ../install
+ ]
+ );
+ };
- node_modules = mkModules {
+ node_modules = stdenvNoCC.mkDerivation {
+ pname = "${finalAttrs.pname}-node_modules";
inherit (finalAttrs) version src;
+
+ impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
+ "GIT_PROXY_COMMAND"
+ "SOCKS_SERVER"
+ ];
+
+ nativeBuildInputs = [
+ bun
+ ];
+
+ dontConfigure = true;
+
+ buildPhase = ''
+ runHook preBuild
+ export HOME=$(mktemp -d)
+ export BUN_INSTALL_CACHE_DIR=$(mktemp -d)
+ bun install \
+ --cpu="${if stdenvNoCC.hostPlatform.isAarch64 then "arm64" else "x64"}" \
+ --os="${if stdenvNoCC.hostPlatform.isLinux then "linux" else "darwin"}" \
+ --frozen-lockfile \
+ --ignore-scripts \
+ --no-progress \
+ --linker=isolated
+ bun --bun ${./scripts/canonicalize-node-modules.ts}
+ bun --bun ${./scripts/normalize-bun-binaries.ts}
+ runHook postBuild
+ '';
+
+ installPhase = ''
+ runHook preInstall
+
+ mkdir -p $out
+ find . -type d -name node_modules -exec cp -R --parents {} $out \;
+
+ runHook postInstall
+ '';
+
+ dontFixup = true;
+
+ outputHashAlgo = "sha256";
+ outputHashMode = "recursive";
+ outputHash =
+ (lib.pipe ./hashes.json [
+ builtins.readFile
+ builtins.fromJSON
+ ]).nodeModules.${stdenvNoCC.hostPlatform.system};
};
nativeBuildInputs = [
bun
+ installShellFiles
makeBinaryWrapper
+ models-dev
+ writableTmpDirAsHomeHook
];
- env.MODELS_DEV_API_JSON = args.modelsDev;
- env.OPENCODE_VERSION = args.version;
- env.OPENCODE_CHANNEL = "stable";
- dontConfigure = true;
+ configurePhase = ''
+ runHook preConfigure
- buildPhase = ''
- runHook preBuild
+ cp -R ${finalAttrs.node_modules}/. .
- cp -r ${finalAttrs.node_modules}/node_modules .
- cp -r ${finalAttrs.node_modules}/packages .
+ runHook postConfigure
+ '';
- (
- cd packages/opencode
+ env.MODELS_DEV_API_JSON = "${models-dev}/dist/_api.json";
+ env.OPENCODE_VERSION = finalAttrs.version;
+ env.OPENCODE_CHANNEL = "local";
- chmod -R u+w ./node_modules
- mkdir -p ./node_modules/@opencode-ai
- rm -f ./node_modules/@opencode-ai/{script,sdk,plugin}
- ln -s $(pwd)/../../packages/script ./node_modules/@opencode-ai/script
- ln -s $(pwd)/../../packages/sdk/js ./node_modules/@opencode-ai/sdk
- ln -s $(pwd)/../../packages/plugin ./node_modules/@opencode-ai/plugin
+ buildPhase = ''
+ runHook preBuild
- cp ${./bundle.ts} ./bundle.ts
- chmod +x ./bundle.ts
- bun run ./bundle.ts
- )
+ cd ./packages/opencode
+ bun --bun ./script/build.ts --single --skip-install
+ bun --bun ./script/schema.ts schema.json
runHook postBuild
'';
@@ -63,76 +118,52 @@ stdenvNoCC.mkDerivation (finalAttrs: {
installPhase = ''
runHook preInstall
- cd packages/opencode
- if [ ! -d dist ]; then
- echo "ERROR: dist directory missing after bundle step"
- exit 1
- fi
-
- mkdir -p $out/lib/opencode
- cp -r dist $out/lib/opencode/
- chmod -R u+w $out/lib/opencode/dist
-
- # Select bundled worker assets deterministically (sorted find output)
- worker_file=$(find "$out/lib/opencode/dist" -type f \( -path '*/tui/worker.*' -o -name 'worker.*' \) | sort | head -n1)
- parser_worker_file=$(find "$out/lib/opencode/dist" -type f -name 'parser.worker.*' | sort | head -n1)
- if [ -z "$worker_file" ]; then
- echo "ERROR: bundled worker not found"
- exit 1
- fi
-
- main_wasm=$(printf '%s\n' "$out"/lib/opencode/dist/tree-sitter-*.wasm | sort | head -n1)
- wasm_list=$(find "$out/lib/opencode/dist" -maxdepth 1 -name 'tree-sitter-*.wasm' -print)
- for patch_file in "$worker_file" "$parser_worker_file"; do
- [ -z "$patch_file" ] && continue
- [ ! -f "$patch_file" ] && continue
- if [ -n "$wasm_list" ] && grep -q 'tree-sitter' "$patch_file"; then
- # Rewrite wasm references to absolute store paths to avoid runtime resolve failures.
- bun --bun ${scripts + "/patch-wasm.ts"} "$patch_file" "$main_wasm" $wasm_list
- fi
- done
-
- mkdir -p $out/lib/opencode/node_modules
- cp -r ../../node_modules/.bun $out/lib/opencode/node_modules/
- mkdir -p $out/lib/opencode/node_modules/@opentui
-
- mkdir -p $out/bin
- makeWrapper ${bun}/bin/bun $out/bin/opencode \
- --add-flags "run" \
- --add-flags "$out/lib/opencode/dist/src/index.js" \
- --prefix PATH : ${lib.makeBinPath [ ripgrep ]} \
- --argv0 opencode
+ install -Dm755 dist/opencode-*/bin/opencode $out/bin/opencode
+ install -Dm644 schema.json $out/share/opencode/schema.json
+
+ wrapProgram $out/bin/opencode \
+ --prefix PATH : ${
+ lib.makeBinPath (
+ [
+ ripgrep
+ ]
+ # bun runs sysctl to detect if dunning on rosetta2
+ ++ lib.optional stdenvNoCC.hostPlatform.isDarwin sysctl
+ )
+ }
runHook postInstall
'';
- postInstall = ''
- for pkg in $out/lib/opencode/node_modules/.bun/@opentui+core-* $out/lib/opencode/node_modules/.bun/@opentui+solid-* $out/lib/opencode/node_modules/.bun/@opentui+core@* $out/lib/opencode/node_modules/.bun/@opentui+solid@*; do
- if [ -d "$pkg" ]; then
- pkgName=$(basename "$pkg" | sed 's/@opentui+\([^@]*\)@.*/\1/')
- ln -sf ../.bun/$(basename "$pkg")/node_modules/@opentui/$pkgName \
- $out/lib/opencode/node_modules/@opentui/$pkgName
- fi
- done
+ postInstall = lib.optionalString (stdenvNoCC.buildPlatform.canExecute stdenvNoCC.hostPlatform) ''
+ # trick yargs into also generating zsh completions
+ installShellCompletion --cmd opencode \
+ --bash <($out/bin/opencode completion) \
+ --zsh <(SHELL=/bin/zsh $out/bin/opencode completion)
'';
- dontFixup = true;
+ nativeInstallCheckInputs = [
+ versionCheckHook
+ writableTmpDirAsHomeHook
+ ];
+ doInstallCheck = true;
+ versionCheckKeepEnvironment = [ "HOME" ];
+ versionCheckProgramArg = "--version";
+
+ passthru = {
+ jsonschema = "${placeholder "out"}/share/opencode/schema.json";
+ };
meta = {
- description = "AI coding agent built for the terminal";
- longDescription = ''
- OpenCode is a terminal-based agent that can build anything.
- It combines a TypeScript/JavaScript core with a Go-based TUI
- to provide an interactive AI coding experience.
- '';
- homepage = "https://github.com/anomalyco/opencode";
+ description = "The open source coding agent";
+ homepage = "https://opencode.ai/";
license = lib.licenses.mit;
+ mainProgram = "opencode";
platforms = [
"aarch64-linux"
"x86_64-linux"
"aarch64-darwin"
"x86_64-darwin"
];
- mainProgram = "opencode";
};
})
diff --git a/nix/scripts/bun-build.ts b/nix/scripts/bun-build.ts
deleted file mode 100644
index e607676cb..000000000
--- a/nix/scripts/bun-build.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-import solidPlugin from "./packages/opencode/node_modules/@opentui/solid/scripts/solid-plugin"
-import path from "path"
-import fs from "fs"
-
-const version = "@VERSION@"
-const pkg = path.join(process.cwd(), "packages/opencode")
-const parser = fs.realpathSync(path.join(pkg, "./node_modules/@opentui/core/parser.worker.js"))
-const worker = "./src/cli/cmd/tui/worker.ts"
-const target = process.env["BUN_COMPILE_TARGET"]
-
-if (!target) {
- throw new Error("BUN_COMPILE_TARGET not set")
-}
-
-process.chdir(pkg)
-
-const manifestName = "opencode-assets.manifest"
-const manifestPath = path.join(pkg, manifestName)
-
-const readTrackedAssets = () => {
- if (!fs.existsSync(manifestPath)) return []
- return fs
- .readFileSync(manifestPath, "utf8")
- .split("\n")
- .map((line) => line.trim())
- .filter((line) => line.length > 0)
-}
-
-const removeTrackedAssets = () => {
- for (const file of readTrackedAssets()) {
- const filePath = path.join(pkg, file)
- if (fs.existsSync(filePath)) {
- fs.rmSync(filePath, { force: true })
- }
- }
-}
-
-const assets = new Set<string>()
-
-const addAsset = async (p: string) => {
- const file = path.basename(p)
- const dest = path.join(pkg, file)
- await Bun.write(dest, Bun.file(p))
- assets.add(file)
-}
-
-removeTrackedAssets()
-
-const result = await Bun.build({
- conditions: ["browser"],
- tsconfig: "./tsconfig.json",
- plugins: [solidPlugin],
- sourcemap: "external",
- entrypoints: ["./src/index.ts", parser, worker],
- define: {
- OPENCODE_VERSION: `'@VERSION@'`,
- OTUI_TREE_SITTER_WORKER_PATH: "/$bunfs/root/" + path.relative(pkg, parser).replace(/\\/g, "/"),
- OPENCODE_CHANNEL: "'latest'",
- },
- compile: {
- target,
- outfile: "opencode",
- autoloadBunfig: false,
- autoloadDotenv: false,
- //@ts-ignore (bun types aren't up to date)
- autoloadTsconfig: true,
- autoloadPackageJson: true,
- execArgv: ["--user-agent=opencode/" + version, "--use-system-ca", "--"],
- windows: {},
- },
-})
-
-if (!result.success) {
- console.error("Build failed!")
- for (const log of result.logs) {
- console.error(log)
- }
- throw new Error("Compilation failed")
-}
-
-const assetOutputs = result.outputs?.filter((x) => x.kind === "asset") ?? []
-for (const x of assetOutputs) {
- await addAsset(x.path)
-}
-
-const bundle = await Bun.build({
- entrypoints: [worker],
- tsconfig: "./tsconfig.json",
- plugins: [solidPlugin],
- target: "bun",
- outdir: "./.opencode-worker",
- sourcemap: "none",
-})
-
-if (!bundle.success) {
- console.error("Worker build failed!")
- for (const log of bundle.logs) {
- console.error(log)
- }
- throw new Error("Worker compilation failed")
-}
-
-const workerAssets = bundle.outputs?.filter((x) => x.kind === "asset") ?? []
-for (const x of workerAssets) {
- await addAsset(x.path)
-}
-
-const output = bundle.outputs.find((x) => x.kind === "entry-point")
-if (!output) {
- throw new Error("Worker build produced no entry-point output")
-}
-
-const dest = path.join(pkg, "opencode-worker.js")
-await Bun.write(dest, Bun.file(output.path))
-fs.rmSync(path.dirname(output.path), { recursive: true, force: true })
-
-const list = Array.from(assets)
-await Bun.write(manifestPath, list.length > 0 ? list.join("\n") + "\n" : "")
-
-console.log("Build successful!")
diff --git a/nix/scripts/patch-wasm.ts b/nix/scripts/patch-wasm.ts
deleted file mode 100644
index 88a06c2bd..000000000
--- a/nix/scripts/patch-wasm.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env bun
-
-import fs from "fs"
-import path from "path"
-
-/**
- * Rewrite tree-sitter wasm references inside a JS file to absolute paths.
- * argv: [node, script, file, mainWasm, ...wasmPaths]
- */
-const [, , file, mainWasm, ...wasmPaths] = process.argv
-
-if (!file || !mainWasm) {
- console.error("usage: patch-wasm <file> <mainWasm> [wasmPaths...]")
- process.exit(1)
-}
-
-const content = fs.readFileSync(file, "utf8")
-const byName = new Map<string, string>()
-
-for (const wasm of wasmPaths) {
- const name = path.basename(wasm)
- byName.set(name, wasm)
-}
-
-let next = content
-
-for (const [name, wasmPath] of byName) {
- next = next.replaceAll(name, wasmPath)
-}
-
-next = next.replaceAll("tree-sitter.wasm", mainWasm).replaceAll("web-tree-sitter/tree-sitter.wasm", mainWasm)
-
-// Collapse any relative prefixes before absolute store paths (e.g., "../../../..//nix/store/...")
-const nixStorePrefix = process.env.NIX_STORE || "/nix/store"
-next = next.replace(/(\.\/)+/g, "./")
-next = next.replace(
- new RegExp(`(\\.\\.\\/)+\\/{1,2}(${nixStorePrefix.replace(/^\//, "").replace(/\//g, "\\/")}[^"']+)`, "g"),
- "/$2",
-)
-next = next.replace(new RegExp(`(["'])\\/{2,}(\\/${nixStorePrefix.replace(/\//g, "\\/")}[^"']+)(["'])`, "g"), "$1$2$3")
-next = next.replace(new RegExp(`(["'])\\/\\/(${nixStorePrefix.replace(/\//g, "\\/")}[^"']+)(["'])`, "g"), "$1$2$3")
-
-if (next !== content) fs.writeFileSync(file, next)