opencode.nix 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. { lib, stdenvNoCC, bun, ripgrep, makeBinaryWrapper }:
  2. args:
  3. let
  4. scripts = args.scripts;
  5. mkModules =
  6. attrs:
  7. args.mkNodeModules (
  8. attrs
  9. // {
  10. canonicalizeScript = scripts + "/canonicalize-node-modules.ts";
  11. normalizeBinsScript = scripts + "/normalize-bun-binaries.ts";
  12. }
  13. );
  14. in
  15. stdenvNoCC.mkDerivation (finalAttrs: {
  16. pname = "opencode";
  17. version = args.version;
  18. src = args.src;
  19. node_modules = mkModules {
  20. version = finalAttrs.version;
  21. src = finalAttrs.src;
  22. };
  23. nativeBuildInputs = [
  24. bun
  25. makeBinaryWrapper
  26. ];
  27. env.MODELS_DEV_API_JSON = args.modelsDev;
  28. env.OPENCODE_VERSION = args.version;
  29. env.OPENCODE_CHANNEL = "stable";
  30. dontConfigure = true;
  31. buildPhase = ''
  32. runHook preBuild
  33. cp -r ${finalAttrs.node_modules}/node_modules .
  34. cp -r ${finalAttrs.node_modules}/packages .
  35. (
  36. cd packages/opencode
  37. chmod -R u+w ./node_modules
  38. mkdir -p ./node_modules/@opencode-ai
  39. rm -f ./node_modules/@opencode-ai/{script,sdk,plugin}
  40. ln -s $(pwd)/../../packages/script ./node_modules/@opencode-ai/script
  41. ln -s $(pwd)/../../packages/sdk/js ./node_modules/@opencode-ai/sdk
  42. ln -s $(pwd)/../../packages/plugin ./node_modules/@opencode-ai/plugin
  43. cp ${./bundle.ts} ./bundle.ts
  44. chmod +x ./bundle.ts
  45. bun run ./bundle.ts
  46. )
  47. runHook postBuild
  48. '';
  49. installPhase = ''
  50. runHook preInstall
  51. cd packages/opencode
  52. if [ ! -d dist ]; then
  53. echo "ERROR: dist directory missing after bundle step"
  54. exit 1
  55. fi
  56. mkdir -p $out/lib/opencode
  57. cp -r dist $out/lib/opencode/
  58. chmod -R u+w $out/lib/opencode/dist
  59. # Select bundled worker assets deterministically (sorted find output)
  60. worker_file=$(find "$out/lib/opencode/dist" -type f \( -path '*/tui/worker.*' -o -name 'worker.*' \) | sort | head -n1)
  61. parser_worker_file=$(find "$out/lib/opencode/dist" -type f -name 'parser.worker.*' | sort | head -n1)
  62. if [ -z "$worker_file" ]; then
  63. echo "ERROR: bundled worker not found"
  64. exit 1
  65. fi
  66. main_wasm=$(printf '%s\n' "$out"/lib/opencode/dist/tree-sitter-*.wasm | sort | head -n1)
  67. wasm_list=$(find "$out/lib/opencode/dist" -maxdepth 1 -name 'tree-sitter-*.wasm' -print)
  68. for patch_file in "$worker_file" "$parser_worker_file"; do
  69. [ -z "$patch_file" ] && continue
  70. [ ! -f "$patch_file" ] && continue
  71. if [ -n "$wasm_list" ] && grep -q 'tree-sitter' "$patch_file"; then
  72. # Rewrite wasm references to absolute store paths to avoid runtime resolve failures.
  73. bun --bun ${scripts + "/patch-wasm.ts"} "$patch_file" "$main_wasm" $wasm_list
  74. fi
  75. done
  76. mkdir -p $out/lib/opencode/node_modules
  77. cp -r ../../node_modules/.bun $out/lib/opencode/node_modules/
  78. mkdir -p $out/lib/opencode/node_modules/@opentui
  79. mkdir -p $out/bin
  80. makeWrapper ${bun}/bin/bun $out/bin/opencode \
  81. --add-flags "run" \
  82. --add-flags "$out/lib/opencode/dist/src/index.js" \
  83. --prefix PATH : ${lib.makeBinPath [ ripgrep ]} \
  84. --argv0 opencode
  85. runHook postInstall
  86. '';
  87. postInstall = ''
  88. 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
  89. if [ -d "$pkg" ]; then
  90. pkgName=$(basename "$pkg" | sed 's/@opentui+\([^@]*\)@.*/\1/')
  91. ln -sf ../.bun/$(basename "$pkg")/node_modules/@opentui/$pkgName \
  92. $out/lib/opencode/node_modules/@opentui/$pkgName
  93. fi
  94. done
  95. '';
  96. dontFixup = true;
  97. meta = {
  98. description = "AI coding agent built for the terminal";
  99. longDescription = ''
  100. OpenCode is a terminal-based agent that can build anything.
  101. It combines a TypeScript/JavaScript core with a Go-based TUI
  102. to provide an interactive AI coding experience.
  103. '';
  104. homepage = "https://github.com/sst/opencode";
  105. license = lib.licenses.mit;
  106. platforms = [
  107. "aarch64-linux"
  108. "x86_64-linux"
  109. "aarch64-darwin"
  110. "x86_64-darwin"
  111. ];
  112. mainProgram = "opencode";
  113. };
  114. })