opencode.nix 4.0 KB

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