Skip to content

Conversation

@Alb-O
Copy link
Contributor

@Alb-O Alb-O commented Nov 4, 2025

Adds Nix flake (+ supporting CI tools) to build OpenCode from source.

To enable this, a few tweaks were done to the core TS codebase that shouldn't impact non-nix builds/runtimes:

  • packages/opencode/src/cli/cmd/tui/thread.ts
    • Nix builds produce a standalone binary with a pre-bundled worker (opencode-worker.js) next to the executable. The new logic checks for this bundled worker and prefers it over the development-time worker.ts URL.
    • Wrap worker instantiation in try-catch to handle worker init failures. If the worker fails (e.g., missing worker bundle), falls back to an inline server instance; the binary should work even if the worker bundle is missing/incompatible with the platform.
  • packages/opencode/src/provider/models-macro.ts
    • Checks for MODELS_DEV_API_JSON env var pointing to a pre-fetched copy of the models API JSON. During Nix builds, process the pre-fetched json and inject its path via this env var. Allows builds to complete without network calls.
  • packages/sdk/js/src/gen/client/utils.gen.ts
    • Adds string coercion for config.baseUrl to handles cases where baseUrl might be a URL object or other non-string type during Nix builds, where bundling/compilation may preserve different object types.
  • packages/opencode/src/tool/bash.ts
    • Previously used relative URLs in compiled bundles causing the runtime not being able to resolve wasm assets if they were packaged differently. We now resolve those URLs to absolute paths regardless of packaging method.

GitHub workflow CI:

  • update-nix-hashes.yml triggers whenever updates to package/lock files are pushed/merged.
  • The job forces a rebuild of the node_modules FOD to get the new hash, and commits the result to hashes.json

relates to:
#3540
#3739
#462
#1903

@lrittel
Copy link

lrittel commented Nov 5, 2025

I'm in no position to properly review this, but I'd have two suggestions:

  • the version is hardcoded in the flake.nix, maybe it's an idea to builtins.fromJSON the version from a package.json file (e.g. packages/opencode/package.json)?
  • maybe a GitHub Actions workflow so that breakages can be detected early? These tend to eat a few minutes, though.

@rekram1-node
Copy link
Collaborator

thanks for ur feedback @lrittel

I think some people in the discord are also taking looks at it.

@Alb-O
Copy link
Contributor Author

Alb-O commented Nov 5, 2025

Currently working on the github workflow to automatically update hashes of build deps in flake.nix. Any preferences around this, i.e. triggers or commits from bot?

@rekram1-node
Copy link
Collaborator

rekram1-node commented Nov 5, 2025

prolly the same way we do it for automatic version updates of package.json files? woudl that work

@Alb-O
Copy link
Contributor Author

Alb-O commented Nov 5, 2025

Oh boy it was fun trying to get the node modules perfectly reproducible with Bun’s symlink tree, think I found a way though, it builds in github CI and on my local machine now. Next up is support for darwin builds and configuring the workflow automation

@rekram1-node
Copy link
Collaborator

amazing thank you @Alb-O

@Alb-O Alb-O force-pushed the nix-support branch 3 times, most recently from dd18731 to 9b5c324 Compare November 6, 2025 01:07
@delafthi
Copy link
Contributor

delafthi commented Nov 6, 2025

Thank you for your work on this! It looks amazing, and I'm really looking forward to it. Resources like this are incredibly helpful as I work on improving the nixpkgs release - something I've been struggling with lately.

@Alb-O Alb-O force-pushed the nix-support branch 3 times, most recently from 12166f5 to d39c9d3 Compare November 7, 2025 01:29
@gabrielrinaldi
Copy link

Thank you for the work on this, can't wait to have a proper non-hacked/patched solution for nix!

@Alb-O
Copy link
Contributor Author

Alb-O commented Nov 7, 2025

@rekram1-node Ready for reviewing/testing now (especially Mac+Nix users would be good)

nix run github:Alb-O/opencode/nix-support

For specific architectures:

nix run github:Alb-O/opencode/nix-support#packages.aarch64-linux.default
nix run github:Alb-O/opencode/nix-support#packages.x86_64-linux.default
nix run github:Alb-O/opencode/nix-support#packages.aarch64-darwin.default
nix run github:Alb-O/opencode/nix-support#packages.x86_64-darwin.default

@delafthi
Copy link
Contributor

delafthi commented Nov 7, 2025

@rekram1-node Ready for reviewing/testing now (especially Mac+Nix users would be good)

On aarch64-darwin

 > nix run github:Alb-O/opencode/nix-support
error: hash mismatch in fixed-output derivation '/nix/store/09wqyqc7dvm6s8va3hbwc176py3wrnbi-opencode-node_modules-1.0.39.drv':
         specified: sha256-AwTmHj8CvTBllQUnP4atM58b0bVMjvXi9yRZt1YTVbE=
            got:    sha256-Vu1drIvA5tImD4ajk152AE4HQ6yGE/8SaEgsKwgC4zM=
error: Cannot build '/nix/store/pl7kjk0sb72vq2qhzvwyvxp2fm5w2px6-opencode-1.0.39.drv'.
       Reason: 1 dependency failed.
       Output paths:
         /nix/store/r8sqgkwycljr82kfnpjmqgww9yvpamzl-opencode-1.0.39

It seems something's not right. Running it with

 > nix run github:Alb-O/opencode/nix-support#packages.aarch64-darwin.default
error: hash mismatch in fixed-output derivation '/nix/store/09wqyqc7dvm6s8va3hbwc176py3wrnbi-opencode-node_modules-1.0.39.drv':
         specified: sha256-AwTmHj8CvTBllQUnP4atM58b0bVMjvXi9yRZt1YTVbE=
            got:    sha256-6tHiBvO1ke1m7iEhU2WBqDlxleWdBKtZjhHz/Qh6Fmc=
error: Cannot build '/nix/store/pl7kjk0sb72vq2qhzvwyvxp2fm5w2px6-opencode-1.0.39.drv'.
       Reason: 1 dependency failed.
       Output paths:
         /nix/store/r8sqgkwycljr82kfnpjmqgww9yvpamzl-opencode-1.0.39

yields a different hash.

x86_64-darwin on the other hand worked 🎉

@Alb-O
Copy link
Contributor Author

Alb-O commented Nov 7, 2025

yields a different hash.

Thank you for testing, these tiny, tiny, differences between the GitHub runner environment and actual user hardware that results in a different hash is driving me a bit mental, but I'll look into it nonetheless. I had it working well on linux x86_64 (exact same hashes between runner and my machine), so maybe an OS/darwin issue? Would be good to know if linux builds are working consistently

Edit: I just realized you meant there was a hash difference between the two different commands which really should give the exact same result. Hm this is a good clue

@Alb-O
Copy link
Contributor Author

Alb-O commented Nov 7, 2025

Ok, may have found the culprit, hopefully this extra optional package pinning solves this. Please test again, same build/run commands as before

@delafthi
Copy link
Contributor

delafthi commented Nov 7, 2025

Please test again

The situation has reversed: aarch64-darwin now works, but x86_64-darwin fails with a hash mismatch:

> nix run github:Alb-O/opencode/nix-support#packages.x86_64-darwin.default
error: hash mismatch in fixed-output derivation '/nix/store/n8vbgmr3lsn5qixq9gk9y73i673rq3rc-opencode-node_modules-1.0.39.drv':
         specified: sha256-MTZm3ogq4XgsglNzaUCFD3RoHFsjGkaTnyoU4fEn+rI=
            got:    sha256-q1uEMWquAaV1Xd0bzKZKm+S4/uW3xpwadBQU3RPl53U=
error: Cannot build '/nix/store/0yxv492hr4zf4dyjps9m5g5m1wlvngp6-opencode-1.0.39.drv'.
       Reason: 1 dependency failed.
       Output paths:
         /nix/store/231qf56dni35fx7176vd8x5pilc9fpbi-opencode-1.0.39

The x86_64-darwin build produces the same hash on repeated runs, indicating a consistent mismatch.

@ndrwstn
Copy link

ndrwstn commented Nov 7, 2025

aarch64-darwin is failing on the models.dev api.json hash as well:

> nix run github:Alb-O/opencode/nix-support#packages.aarch64-darwin.default
error: hash mismatch in fixed-output derivation '/nix/store/gky155qq5bc9ilwas8r43c5p41gxnhkn-api.json.drv':
         specified: sha256-Q82BpJzo/Gla3M3RHAwhATYV0NxamkdwoVL3iEUbaec=
            got:    sha256-dTUM9lSUErd28jMw/YVWwpD0mZWfTRgzfysfq5KhKjg=

Given that models.dev is external to this repo, I don't think you can have a hard match to api.json that will be sustainable. I think you just have to accept the non-declarativeness of fetching it and taking whatever you're given, maybe with a null fallback, since if you're trying to use opencode in an airgapped environment you probably either know what you're doing or shouldn't be doing it anyway.

@delafthi
Copy link
Contributor

delafthi commented Nov 7, 2025

I encountered this exact issue when I first packaged OpenCode for nixpkgs. The problem stems from fetching from a link which doesn't pin a specific version - whenever api.json gets updated on the server, you'll get a hash mismatch. In other words, the output of that fetchContent isn't consistent.

I solved this by packaging models-dev separately (see the package definition) and then using that as a dependency.

@ndrwstn
Copy link

ndrwstn commented Nov 7, 2025

I don't understand the opencode architecture choice, but it seems like (I just asked an agent; I didn't verify:) opencode will crash on first run if api.json isn't accessible (e.g. offline). As a result, it's included in the build even though it's not really needed (or even desirable, frankly).

I think the right answer is to fix the application to check for connectivity and cleanly error on first-run instead of forcing a download on build, but that's well beyond the scope of making a nix flake. For the moment, since it doesn't matter, you just need to pick a deterministic way of giving opencode something on first-run, whether you refer to nixpkgs models-dev or just pass a null.

@rekram1-node
Copy link
Collaborator

@ndrwstn the macro is needed so there is a copy of available models when you run opencode

@Alb-O Alb-O force-pushed the nix-support branch 3 times, most recently from d16f435 to 5c78c98 Compare November 8, 2025 05:50
@Alb-O
Copy link
Contributor Author

Alb-O commented Nov 13, 2025

Hash inconsistency issues seem to be finally resolved, pinpointing the issue to symlinked binaries in node_modules/.bun and .bin, and normalizing these paths during nix builds. Looking nice and stable now 🤞

@rekram1-node rekram1-node changed the title Add full Nix flake support with an async, hands-off GitHub workflow feat: nix support for the nix folks Nov 18, 2025
@rekram1-node
Copy link
Collaborator

@Alb-O is the goat

@rekram1-node
Copy link
Collaborator

/oc run ./packages/sdk/js/script/build.ts and then commit the changes

@opencode-agent
Copy link
Contributor

opencode-agent bot commented Nov 18, 2025

Build completed and changes committed. The SDK build script ran successfully and updated the generated client utilities.

New%20session%20-%202025-11-18T06%3A15%3A02.938Z
opencode session  |  github run

@rekram1-node rekram1-node merged commit 5e13527 into anomalyco:dev Nov 18, 2025
2 of 3 checks passed
ndrwstn pushed a commit to ndrwstn/dotnix that referenced this pull request Nov 18, 2025
Point opencode input to the official sst/opencode dev branch (PR #3924 merged) and refresh flake.lock so pinned revisions and narHashes are updated across inputs (nixpkgs, nixpkgs-darwin, nixpkgs-unstable, nixvim, NUR, opencode).

Refs anomalyco/opencode#3924
@Mic92
Copy link

Mic92 commented Nov 21, 2025

Triggeres the same bug on macOS that I have seen before when doing my own packaging. I opened #4575 for discussion.

@ck3mp3r
Copy link

ck3mp3r commented Nov 24, 2025

Something is not quite right... this is what happens on an M3 MBP, how do you generate the hash for the fixed output derivation? Only for one architecture?

❯ nix run github:sst/opencode
[1/0/2 built, 5 copied (246.6 MiB), 91.0 MiB DL] building opencode-node_modules-1.0.108 (inst
error: hash mismatch in fixed-output derivation '/nix/store/xmy6279nf207pidmm3cxnq24zhr89l0k-opencode-node_modules-1.0.108.drv':
         specified: sha256-m7hL9Uzqk+oa2/FtgkzEPgi+m/VZP1SvjpgYHNjiS1c=
            got:    sha256-83nrKWOCUJhSHqtSApFuXxggEwO86rIWhy5d2vtfz4Y=
error: Cannot build '/nix/store/jjc87gkbwkhdajzca6g653ay0w20kppm-opencode-1.0.108.drv'.
       Reason: 1 dependency failed.
       Output paths:
         /nix/store/lxacjg2y1gcyqbbqb7cbhpz6axl7kq14-opencode-1.0.108

@gabrielrinaldi
Copy link

I think you just got in between the job that generates the hash for nix not having run yet, at least for me if I wait a little it usually works, the release is out before the new hash is updated. (this is my understanding of the process by looking at the commits and personal experience)

@rekram1-node
Copy link
Collaborator

rekram1-node commented Nov 24, 2025

I don't know anything about nix but I know why it keeps behaving weird to some degree Ill try to fix it today, think it just involves moving stuff around

@ck3mp3r
Copy link

ck3mp3r commented Nov 25, 2025

I guess for now I will stick to my own nix build of opencode until this one is more stable.

❯ nix run github:sst/opencode
[1/0/1 built] building opencode-1.0.110 (fixupPhase): _: line 2: patchelf: command not found

Note: it did build after quite a while even with the error. My approach is to use the pre-built binaries from the release page as non flake inputs, which avoids the entire build and also avoids any fixed output derivation hashes.
I also symlink the contents instead of copying them on first run... feel free to have a look if you want github:ck3mp3r/flakes?dir=opencode. I also change the cache directory to something else like ~/.cache-nix/opencode I run opencode via a wrapper script with the same name.
I'm sure my version needs some optimisation, but it does the trick for me reproducibly and reliably. Also, because my workflow caches the entire output as derivations on my nix cache, the machines consuming this never need to run any builds, nor do they need to interact with npmjs et al.

@Alb-O
Copy link
Contributor Author

Alb-O commented Nov 25, 2025

Yes, you can simply fetch/patch release tarballs. But this flake is targeted mainly for contributor usage where building and running the dev work tree which doesn't have a release yet is a must. It also helps out the nixpkgs maintainers who prefer packages to be built from source (and cached)

@ck3mp3r
Copy link

ck3mp3r commented Nov 25, 2025

Yes, you can simply fetch/patch release tarballs. But this flake is targeted mainly for contributor usage where building and running the dev work tree which doesn't have a release yet is a must. It also helps out the nixpkgs maintainers who prefer packages to be built from source (and cached)

yes, this flake should definitely become the source of the upstream nix package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants