diff options
| author | Caleb Norton <[email protected]> | 2026-01-18 11:14:13 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-01-18 11:14:13 -0600 |
| commit | dac099a4892689d11abedb0fcc1098b50e0958c8 (patch) | |
| tree | b47a7a4bae294e0d4222fac21605a380d54b3341 /nix/opencode.nix | |
| parent | 5009f10406c15c4b69c04fa626756ee7bf81b300 (diff) | |
| download | opencode-dac099a4892689d11abedb0fcc1098b50e0958c8.tar.gz opencode-dac099a4892689d11abedb0fcc1098b50e0958c8.zip | |
feat(nix): overhaul nix flake and packages (#9032)
Diffstat (limited to 'nix/opencode.nix')
| -rw-r--r-- | nix/opencode.nix | 211 |
1 files changed, 121 insertions, 90 deletions
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"; }; }) |
