Add opencode package and install via base role
Some checks failed
CI / check (push) Successful in 2m50s
CI / build-and-cache (push) Failing after 8m7s

- Add packages/opencode with pre-built binaries from GitHub releases (v1.4.0)
- Support all 4 platforms (aarch64-darwin, x86_64-darwin, x86_64-linux, aarch64-linux)
- Add update-opencode flake app for automated version bumps
- Install opencode via home.roles.base so it's available on all machines
- Reformat flake.nix and packages with nixfmt
This commit is contained in:
2026-04-08 11:33:40 -07:00
parent ddd21454b7
commit 785561367e
5 changed files with 575 additions and 294 deletions

616
flake.nix
View File

@@ -58,7 +58,7 @@
perles = {
url = "github:zjrosen/perles";
flake = false; # No flake.nix upstream yet
flake = false; # No flake.nix upstream yet
};
nix-doom-emacs-unstraightened = {
@@ -68,308 +68,352 @@
};
};
outputs = { self, nixpkgs, nixpkgs-unstable, ... } @ inputs: let
# Shared overlay function to reduce duplication across module sets
# Parameters:
# unstableOverlays: Additional overlays to apply when importing nixpkgs-unstable
mkBaseOverlay = { unstableOverlays ? [] }: (final: prev: {
unstable = import nixpkgs-unstable {
system = prev.stdenv.hostPlatform.system;
config.allowUnfree = true;
overlays = unstableOverlays;
};
# Separate nixpkgs for qt5webengine-heavy packages to avoid rebuild churn
qt-pinned = import inputs.nixpkgs-qt {
system = prev.stdenv.hostPlatform.system;
config = {
allowUnfree = true;
permittedInsecurePackages = [ "qtwebengine-5.15.19" ];
};
};
custom = prev.callPackage ./packages {};
# Compatibility: bitwarden renamed to bitwarden-desktop in unstable
bitwarden-desktop = prev.bitwarden-desktop or prev.bitwarden;
});
# Shared home-manager configuration factory
# Parameters:
# sharedModules: Additional modules to include in home-manager.sharedModules
mkHomeManagerConfig = { sharedModules ? [] }: {
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.sharedModules = sharedModules ++ [
inputs.nix-doom-emacs-unstraightened.homeModule
];
home-manager.extraSpecialArgs = {
globalInputs = inputs;
};
};
# Shared unstable overlays for custom package builds
customUnstableOverlays = [
# Override claude-code in unstable to use our custom GCS-based build
# (needed for corporate networks that block npm registry)
(ufinal: uprev: {
claude-code = uprev.callPackage ./packages/claude-code {};
})
# Pin dolt to v1.82.4 (gastown requires >= 1.82.4)
(ufinal: uprev: {
dolt = uprev.dolt.overrideAttrs (old: rec {
version = "1.82.4";
src = uprev.fetchFromGitHub {
owner = "dolthub";
repo = "dolt";
tag = "v${version}";
hash = "sha256-mavL3y+Kv25hzFlDFXk7W/jeKVKlCBjlc67GkL3Jcwk=";
};
vendorHash = "sha256-K1KzsqptZxO5OraWKIXeqKuVSzb6E/Mjy3c5PQ7Rs9k=";
});
})
];
nixosModules = [
./roles
inputs.home-manager.nixosModules.home-manager
{
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig {
sharedModules = [ inputs.plasma-manager.homeModules.plasma-manager ];
})
];
# Modules for unstable-based systems (like nix-deck)
nixosModulesUnstable = [
./roles
inputs.home-manager-unstable.nixosModules.home-manager
inputs.jovian.nixosModules.jovian
{
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig {
sharedModules = [ inputs.plasma-manager-unstable.homeModules.plasma-manager ];
})
];
darwinModules = [
./roles/darwin.nix
inputs.home-manager.darwinModules.home-manager
{
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig { sharedModules = []; })
];
in {
nixosConfigurations.nix-book = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/nix-book/configuration.nix
outputs =
{
self,
nixpkgs,
nixpkgs-unstable,
...
}@inputs:
let
# Shared overlay function to reduce duplication across module sets
# Parameters:
# unstableOverlays: Additional overlays to apply when importing nixpkgs-unstable
mkBaseOverlay =
{
home-manager.users.johno = {
imports = [ ./home/home-laptop-compact.nix ];
# Machine-specific overrides
home.roles.i3_sway.extraSwayConfig = {
output.eDP-1.scale = "1.75";
unstableOverlays ? [ ],
}:
(final: prev: {
unstable = import nixpkgs-unstable {
system = prev.stdenv.hostPlatform.system;
config.allowUnfree = true;
overlays = unstableOverlays;
};
# Separate nixpkgs for qt5webengine-heavy packages to avoid rebuild churn
qt-pinned = import inputs.nixpkgs-qt {
system = prev.stdenv.hostPlatform.system;
config = {
allowUnfree = true;
permittedInsecurePackages = [ "qtwebengine-5.15.19" ];
};
};
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
custom = prev.callPackage ./packages { };
# Compatibility: bitwarden renamed to bitwarden-desktop in unstable
bitwarden-desktop = prev.bitwarden-desktop or prev.bitwarden;
});
nixosConfigurations.boxy = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/boxy/configuration.nix
# Shared home-manager configuration factory
# Parameters:
# sharedModules: Additional modules to include in home-manager.sharedModules
mkHomeManagerConfig =
{
home-manager.users.johno = import ./home/home-media-center.nix;
# kodi user: AVR volume control + minimal Plasma config for Bigscreen session
home-manager.users.kodi = import ./home/home-kodi.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
sharedModules ? [ ],
}:
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.sharedModules = sharedModules ++ [
inputs.nix-doom-emacs-unstraightened.homeModule
];
home-manager.extraSpecialArgs = {
globalInputs = inputs;
};
};
nixosConfigurations.zix790prors = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/zix790prors/configuration.nix
# Shared unstable overlays for custom package builds
customUnstableOverlays = [
# Override claude-code in unstable to use our custom GCS-based build
# (needed for corporate networks that block npm registry)
(ufinal: uprev: {
claude-code = uprev.callPackage ./packages/claude-code { };
})
# Pin dolt to v1.82.4 (gastown requires >= 1.82.4)
(ufinal: uprev: {
dolt = uprev.dolt.overrideAttrs (old: rec {
version = "1.82.4";
src = uprev.fetchFromGitHub {
owner = "dolthub";
repo = "dolt";
tag = "v${version}";
hash = "sha256-mavL3y+Kv25hzFlDFXk7W/jeKVKlCBjlc67GkL3Jcwk=";
};
vendorHash = "sha256-K1KzsqptZxO5OraWKIXeqKuVSzb6E/Mjy3c5PQ7Rs9k=";
});
})
];
nixosModules = [
./roles
inputs.home-manager.nixosModules.home-manager
{
home-manager.users.johno = {
imports = [ ./home/home-desktop.nix ];
home.roles.i3_sway.extraSwayConfig = {
output = {
"DP-1" = {
mode = "3440x1440@164.900Hz";
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig {
sharedModules = [ inputs.plasma-manager.homeModules.plasma-manager ];
})
];
# Modules for unstable-based systems (like nix-deck)
nixosModulesUnstable = [
./roles
inputs.home-manager-unstable.nixosModules.home-manager
inputs.jovian.nixosModules.jovian
{
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig {
sharedModules = [ inputs.plasma-manager-unstable.homeModules.plasma-manager ];
})
];
darwinModules = [
./roles/darwin.nix
inputs.home-manager.darwinModules.home-manager
{
nixpkgs.overlays = [ (mkBaseOverlay { unstableOverlays = customUnstableOverlays; }) ];
}
(mkHomeManagerConfig { sharedModules = [ ]; })
];
in
{
nixosConfigurations.nix-book = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/nix-book/configuration.nix
{
home-manager.users.johno = {
imports = [ ./home/home-laptop-compact.nix ];
# Machine-specific overrides
home.roles.i3_sway.extraSwayConfig = {
output.eDP-1.scale = "1.75";
};
};
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
nixosConfigurations.boxy = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/boxy/configuration.nix
{
home-manager.users.johno = import ./home/home-media-center.nix;
# kodi user: AVR volume control + minimal Plasma config for Bigscreen session
home-manager.users.kodi = import ./home/home-kodi.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
nixosConfigurations.zix790prors = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/zix790prors/configuration.nix
{
home-manager.users.johno = {
imports = [ ./home/home-desktop.nix ];
home.roles.i3_sway.extraSwayConfig = {
output = {
"DP-1" = {
mode = "3440x1440@164.900Hz";
};
};
};
};
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Live USB ISO configuration
nixosConfigurations.live-usb = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/live-usb/configuration.nix
{
home-manager.users.nixos = import ./home/home-live-usb.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Steam Deck configuration (using unstable for better Jovian compatibility)
nixosConfigurations.nix-deck = nixpkgs-unstable.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModulesUnstable ++ [
./machines/nix-deck/configuration.nix
{
home-manager.users.johno = import ./home/home-desktop.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# ZFS/NFS server configuration
nixosConfigurations.john-endesktop = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/john-endesktop/configuration.nix
inputs.home-manager.nixosModules.home-manager
{
home-manager.users.johno = import ./home/home-server.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Darwin/macOS configurations
darwinConfigurations."BLKFV4YF49KT7" = inputs.nix-darwin.lib.darwinSystem rec {
system = "aarch64-darwin";
modules = darwinModules ++ [
./machines/johno-macbookpro/configuration.nix
{
home-manager.users.johno = import ./home/home-darwin-work.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Packages for CI caching (custom packages, flake inputs, and qt-pinned)
packages = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ] (
system:
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
overlays = [ (mkBaseOverlay { }) ];
};
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Live USB ISO configuration
nixosConfigurations.live-usb = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/live-usb/configuration.nix
{
home-manager.users.nixos = import ./home/home-live-usb.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Steam Deck configuration (using unstable for better Jovian compatibility)
nixosConfigurations.nix-deck = nixpkgs-unstable.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModulesUnstable ++ [
./machines/nix-deck/configuration.nix
{
home-manager.users.johno = import ./home/home-desktop.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# ZFS/NFS server configuration
nixosConfigurations.john-endesktop = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = nixosModules ++ [
./machines/john-endesktop/configuration.nix
inputs.home-manager.nixosModules.home-manager
{
home-manager.users.johno = import ./home/home-server.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Darwin/macOS configurations
darwinConfigurations."BLKFV4YF49KT7" = inputs.nix-darwin.lib.darwinSystem rec {
system = "aarch64-darwin";
modules = darwinModules ++ [
./machines/johno-macbookpro/configuration.nix
{
home-manager.users.johno = import ./home/home-darwin-work.nix;
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
# Packages for CI caching (custom packages, flake inputs, and qt-pinned)
packages = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ] (system:
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
overlays = [ (mkBaseOverlay {}) ];
};
pkgsQt = import inputs.nixpkgs-qt {
inherit system;
config = {
allowUnfree = true;
permittedInsecurePackages = [ "qtwebengine-5.15.19" ];
pkgsQt = import inputs.nixpkgs-qt {
inherit system;
config = {
allowUnfree = true;
permittedInsecurePackages = [ "qtwebengine-5.15.19" ];
};
};
};
# Version strings for flake input packages
beadsRev = builtins.substring 0 8 (inputs.beads.rev or "unknown");
gastownRev = builtins.substring 0 8 (inputs.gastown.rev or "unknown");
in {
"custom-claude-code" = pkgs.custom.claude-code;
"custom-app-launcher-server" = pkgs.custom.app-launcher-server;
"custom-mcrcon-rbw" = pkgs.custom.mcrcon-rbw;
"custom-tea-rbw" = pkgs.custom.tea-rbw;
"custom-rclone-torbox-setup" = pkgs.custom.rclone-torbox-setup;
"custom-nextcloud-talk-desktop" = pkgs.custom.nextcloud-talk-desktop;
"qt-pinned-jellyfin-media-player" = pkgsQt.jellyfin-media-player;
"qt-pinned-stremio" = pkgsQt.stremio;
# Flake input packages (beads, gastown) - these get version from input rev
"custom-beads" = pkgs.callPackage ./packages/beads {
inherit (pkgs.unstable) buildGoModule;
src = inputs.beads;
version = "0.52.0-${beadsRev}";
};
"custom-gastown" = pkgs.callPackage ./packages/gastown {
src = inputs.gastown;
version = "unstable-${gastownRev}";
};
"custom-perles" = pkgs.callPackage ./packages/perles {
inherit (pkgs.unstable) buildGoModule;
src = inputs.perles;
version = "unstable-${builtins.substring 0 8 (inputs.perles.rev or "unknown")}";
};
} // (if system == "x86_64-linux" then {
# nix-deck kernel from Jovian-NixOS (Steam Deck) - expensive to build
"nix-deck-kernel" = self.nixosConfigurations.nix-deck.config.boot.kernelPackages.kernel;
} else {})
);
# Version strings for flake input packages
beadsRev = builtins.substring 0 8 (inputs.beads.rev or "unknown");
gastownRev = builtins.substring 0 8 (inputs.gastown.rev or "unknown");
in
{
"custom-claude-code" = pkgs.custom.claude-code;
"custom-app-launcher-server" = pkgs.custom.app-launcher-server;
"custom-mcrcon-rbw" = pkgs.custom.mcrcon-rbw;
"custom-tea-rbw" = pkgs.custom.tea-rbw;
"custom-rclone-torbox-setup" = pkgs.custom.rclone-torbox-setup;
"custom-nextcloud-talk-desktop" = pkgs.custom.nextcloud-talk-desktop;
"custom-opencode" = pkgs.custom.opencode;
"qt-pinned-jellyfin-media-player" = pkgsQt.jellyfin-media-player;
"qt-pinned-stremio" = pkgsQt.stremio;
# Flake input packages (beads, gastown) - these get version from input rev
"custom-beads" = pkgs.callPackage ./packages/beads {
inherit (pkgs.unstable) buildGoModule;
src = inputs.beads;
version = "0.52.0-${beadsRev}";
};
"custom-gastown" = pkgs.callPackage ./packages/gastown {
src = inputs.gastown;
version = "unstable-${gastownRev}";
};
"custom-perles" = pkgs.callPackage ./packages/perles {
inherit (pkgs.unstable) buildGoModule;
src = inputs.perles;
version = "unstable-${builtins.substring 0 8 (inputs.perles.rev or "unknown")}";
};
}
// (
if system == "x86_64-linux" then
{
# nix-deck kernel from Jovian-NixOS (Steam Deck) - expensive to build
"nix-deck-kernel" = self.nixosConfigurations.nix-deck.config.boot.kernelPackages.kernel;
}
else
{ }
)
);
# Flake apps
apps = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] (system:
let
pkgs = import nixpkgs { inherit system; };
commonDeps = [ pkgs.curl pkgs.jq pkgs.nix pkgs.git pkgs.gnused pkgs.gnugrep pkgs.coreutils pkgs.gawk ];
# Flake apps
apps = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] (
system:
let
pkgs = import nixpkgs { inherit system; };
commonDeps = [
pkgs.curl
pkgs.jq
pkgs.nix
pkgs.git
pkgs.gnused
pkgs.gnugrep
pkgs.coreutils
pkgs.gawk
];
update-doomemacs = pkgs.writeShellScriptBin "update-doomemacs" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/update-doomemacs.sh}
'';
update-doomemacs = pkgs.writeShellScriptBin "update-doomemacs" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/update-doomemacs.sh}
'';
update-claude-code = pkgs.writeShellScriptBin "update-claude-code" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./packages/claude-code/update.sh}
'';
update-claude-code = pkgs.writeShellScriptBin "update-claude-code" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./packages/claude-code/update.sh}
'';
rotate-wallpaper = pkgs.writeShellScriptBin "rotate-wallpaper" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/rotate-wallpaper.sh}
'';
update-opencode = pkgs.writeShellScriptBin "update-opencode" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./packages/opencode/update.sh}
'';
upgrade = pkgs.writeShellScriptBin "upgrade" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/upgrade.sh}
'';
rotate-wallpaper = pkgs.writeShellScriptBin "rotate-wallpaper" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/rotate-wallpaper.sh}
'';
bootstrap = pkgs.writeShellScriptBin "bootstrap" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/bootstrap.sh}
'';
upgrade = pkgs.writeShellScriptBin "upgrade" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/upgrade.sh}
'';
build-liveusb = pkgs.writeShellScriptBin "build-liveusb" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/build-liveusb.sh}
'';
in {
update-doomemacs = {
type = "app";
program = "${update-doomemacs}/bin/update-doomemacs";
};
update-claude-code = {
type = "app";
program = "${update-claude-code}/bin/update-claude-code";
};
rotate-wallpaper = {
type = "app";
program = "${rotate-wallpaper}/bin/rotate-wallpaper";
};
upgrade = {
type = "app";
program = "${upgrade}/bin/upgrade";
};
bootstrap = {
type = "app";
program = "${bootstrap}/bin/bootstrap";
};
build-liveusb = {
type = "app";
program = "${build-liveusb}/bin/build-liveusb";
};
}
);
};
bootstrap = pkgs.writeShellScriptBin "bootstrap" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/bootstrap.sh}
'';
build-liveusb = pkgs.writeShellScriptBin "build-liveusb" ''
export PATH="${pkgs.lib.makeBinPath commonDeps}:$PATH"
${builtins.readFile ./scripts/build-liveusb.sh}
'';
in
{
update-doomemacs = {
type = "app";
program = "${update-doomemacs}/bin/update-doomemacs";
};
update-claude-code = {
type = "app";
program = "${update-claude-code}/bin/update-claude-code";
};
update-opencode = {
type = "app";
program = "${update-opencode}/bin/update-opencode";
};
rotate-wallpaper = {
type = "app";
program = "${rotate-wallpaper}/bin/rotate-wallpaper";
};
upgrade = {
type = "app";
program = "${upgrade}/bin/upgrade";
};
bootstrap = {
type = "app";
program = "${bootstrap}/bin/bootstrap";
};
build-liveusb = {
type = "app";
program = "${build-liveusb}/bin/build-liveusb";
};
}
);
};
}

View File

@@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
with lib;
@@ -24,6 +29,7 @@ in
tmux
tree
watch
custom.opencode
];
# Automatic garbage collection for user profile (home-manager generations).

View File

@@ -1,10 +1,11 @@
{ pkgs, ... }:
{
tea-rbw = pkgs.callPackage ./tea-rbw {};
app-launcher-server = pkgs.callPackage ./app-launcher-server {};
claude-code = pkgs.callPackage ./claude-code {};
mcrcon-rbw = pkgs.callPackage ./mcrcon-rbw {};
rclone-torbox-setup = pkgs.callPackage ./rclone-torbox-setup {};
pi-coding-agent = pkgs.callPackage ./pi-coding-agent {};
nextcloud-talk-desktop = pkgs.callPackage ./nextcloud-talk-desktop {};
tea-rbw = pkgs.callPackage ./tea-rbw { };
app-launcher-server = pkgs.callPackage ./app-launcher-server { };
claude-code = pkgs.callPackage ./claude-code { };
mcrcon-rbw = pkgs.callPackage ./mcrcon-rbw { };
rclone-torbox-setup = pkgs.callPackage ./rclone-torbox-setup { };
pi-coding-agent = pkgs.callPackage ./pi-coding-agent { };
nextcloud-talk-desktop = pkgs.callPackage ./nextcloud-talk-desktop { };
opencode = pkgs.callPackage ./opencode { };
}

View File

@@ -0,0 +1,82 @@
{
lib,
stdenv,
fetchzip,
patchelf,
glibc,
}:
let
version = "1.4.0";
srcs = {
aarch64-darwin = {
url = "https://github.com/anomalyco/opencode/releases/download/v${version}/opencode-darwin-arm64.zip";
sha256 = "0m97j2vln8yhhvnsjl92phx6dac24y7hgh75csmbkbhawkz9xm4l";
};
x86_64-darwin = {
url = "https://github.com/anomalyco/opencode/releases/download/v${version}/opencode-darwin-x64.zip";
sha256 = "17n04j06pdc2raxjm91y6p87gwpnra0liabpbjwdmyd1iqgqv0q8";
};
x86_64-linux = {
url = "https://github.com/anomalyco/opencode/releases/download/v${version}/opencode-linux-x64.tar.gz";
sha256 = "16117lwfj2lb8wjbq5cyf77vhi52ada5ys3212hjqw3qw3wrcc0r";
};
aarch64-linux = {
url = "https://github.com/anomalyco/opencode/releases/download/v${version}/opencode-linux-arm64.tar.gz";
sha256 = "06lvm1qiji74xdd3psqn6lwxak65gqsbmkib1pjb4n65f9246jwm";
};
};
src =
srcs.${stdenv.hostPlatform.system} or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
in
stdenv.mkDerivation {
pname = "opencode";
inherit version;
src = fetchzip {
inherit (src) url sha256;
};
# Bun standalone binaries have JS code appended after the ELF sections
# stripping/patching would remove or corrupt this appended data
dontStrip = true;
dontPatchELF = true;
nativeBuildInputs = lib.optionals stdenv.isLinux [ patchelf ];
installPhase = ''
runHook preInstall
install -Dm755 $src/opencode $out/bin/opencode
runHook postInstall
'';
# Manually patch the interpreter for bun standalone binaries on Linux
postFixup = lib.optionalString stdenv.isLinux ''
interpreter="${glibc}/lib/${
if stdenv.hostPlatform.system == "aarch64-linux" then
"ld-linux-aarch64.so.1"
else
"ld-linux-x86-64.so.2"
}"
patchelf --set-interpreter "$interpreter" $out/bin/opencode
'';
meta = with lib; {
description = "Terminal-based AI coding assistant";
homepage = "https://opencode.ai";
license = licenses.mit;
maintainers = [ ];
platforms = [
"aarch64-darwin"
"x86_64-darwin"
"x86_64-linux"
"aarch64-linux"
];
mainProgram = "opencode";
};
}

148
packages/opencode/update.sh Executable file
View File

@@ -0,0 +1,148 @@
#!/usr/bin/env bash
set -euo pipefail
DRY_RUN=false
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run|-n)
DRY_RUN=true
shift
;;
--help|-h)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --dry-run, -n Show what would be updated without making changes"
echo " --help, -h Show this help message"
exit 0
;;
*)
echo "Unknown option: $1"
echo "Use --help for usage information"
exit 1
;;
esac
done
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
NIX_FILE="$REPO_ROOT/packages/opencode/default.nix"
echo "Fetching latest opencode version from GitHub API..."
RELEASE_INFO=$(curl -fsSL https://api.github.com/repos/anomalyco/opencode/releases/latest)
NEW_VERSION=$(echo "$RELEASE_INFO" | jq -r '.tag_name' | sed 's/^v//')
if [ -z "$NEW_VERSION" ] || [ "$NEW_VERSION" = "null" ]; then
echo -e "${RED}Error: Failed to fetch version from GitHub API${NC}"
exit 1
fi
CURRENT_VERSION=$(grep -m1 'version = ' "$NIX_FILE" | sed -E 's/.*version = "([^"]+)".*/\1/')
if [ "$CURRENT_VERSION" = "$NEW_VERSION" ]; then
echo -e "${GREEN}Already up to date: $CURRENT_VERSION${NC}"
exit 0
fi
echo -e "${YELLOW}Updating from $CURRENT_VERSION to $NEW_VERSION${NC}"
# Compute SHA256 hashes for each platform
# fetchzip hashes the unpacked directory, so we need to extract and hash
compute_unpacked_hash() {
local url="$1"
local ext="$2"
local tmpdir=$(mktemp -d)
local archive="/tmp/opencode-archive.$ext"
curl -fsSL "$url" -o "$archive"
if [ "$ext" = "zip" ]; then
(cd "$tmpdir" && unzip -q "$archive")
else
(cd "$tmpdir" && tar xzf "$archive")
fi
local sri_hash=$(nix hash path "$tmpdir")
local nix32_hash=$(nix hash convert --hash-algo sha256 --to nix32 "$sri_hash")
rm -rf "$tmpdir" "$archive"
echo "$nix32_hash"
}
echo "Computing SHA256 hashes (this may take a moment)..."
SHA_DARWIN_ARM=$(compute_unpacked_hash "https://github.com/anomalyco/opencode/releases/download/v${NEW_VERSION}/opencode-darwin-arm64.zip" "zip")
echo " aarch64-darwin: $SHA_DARWIN_ARM"
SHA_DARWIN_X64=$(compute_unpacked_hash "https://github.com/anomalyco/opencode/releases/download/v${NEW_VERSION}/opencode-darwin-x64.zip" "zip")
echo " x86_64-darwin: $SHA_DARWIN_X64"
SHA_LINUX_X64=$(compute_unpacked_hash "https://github.com/anomalyco/opencode/releases/download/v${NEW_VERSION}/opencode-linux-x64.tar.gz" "tar.gz")
echo " x86_64-linux: $SHA_LINUX_X64"
SHA_LINUX_ARM64=$(compute_unpacked_hash "https://github.com/anomalyco/opencode/releases/download/v${NEW_VERSION}/opencode-linux-arm64.tar.gz" "tar.gz")
echo " aarch64-linux: $SHA_LINUX_ARM64"
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}DRY RUN - No changes will be made${NC}"
echo ""
echo "Would update:"
echo " Version: $CURRENT_VERSION -> $NEW_VERSION"
echo " aarch64-darwin SHA: $SHA_DARWIN_ARM"
echo " x86_64-darwin SHA: $SHA_DARWIN_X64"
echo " x86_64-linux SHA: $SHA_LINUX_X64"
echo " aarch64-linux SHA: $SHA_LINUX_ARM64"
exit 0
fi
# Update version
sed -i.tmp "s/version = \".*\";/version = \"$NEW_VERSION\";/" "$NIX_FILE"
# Update SHA256 hashes using awk
awk -v sha_arm="$SHA_DARWIN_ARM" -v sha_x64="$SHA_DARWIN_X64" -v sha_linux_x64="$SHA_LINUX_X64" -v sha_linux_arm="$SHA_LINUX_ARM64" '
/aarch64-darwin = {/ { in_arm = 1 }
/x86_64-darwin = {/ { in_x64 = 1; in_arm = 0 }
/x86_64-linux = {/ { in_linux_x64 = 1; in_x64 = 0 }
/aarch64-linux = {/ { in_linux_arm = 1; in_linux_x64 = 0 }
/};/ {
in_arm = 0
in_x64 = 0
in_linux_x64 = 0
in_linux_arm = 0
}
/sha256 = / {
if (in_arm) {
sub(/sha256 = ".*";/, "sha256 = \"" sha_arm "\";")
} else if (in_x64) {
sub(/sha256 = ".*";/, "sha256 = \"" sha_x64 "\";")
} else if (in_linux_x64) {
sub(/sha256 = ".*";/, "sha256 = \"" sha_linux_x64 "\";")
} else if (in_linux_arm) {
sub(/sha256 = ".*";/, "sha256 = \"" sha_linux_arm "\";")
}
}
{ print }
' "$NIX_FILE" > "$NIX_FILE.new"
mv "$NIX_FILE.new" "$NIX_FILE"
rm -f "$NIX_FILE.tmp"
echo -e "${GREEN}Successfully updated to version $NEW_VERSION${NC}"
echo ""
echo "Updated SHA256 hashes:"
echo " aarch64-darwin: $SHA_DARWIN_ARM"
echo " x86_64-darwin: $SHA_DARWIN_X64"
echo " x86_64-linux: $SHA_LINUX_X64"
echo " aarch64-linux: $SHA_LINUX_ARM64"
echo ""
echo "Next steps:"
echo " 1. Review changes: git diff $NIX_FILE"
echo " 2. Test build: nix build .#custom-opencode"
echo " 3. Verify version: ./result/bin/opencode --version"
echo " 4. Commit: git add $NIX_FILE && git commit -m 'opencode: Update to version $NEW_VERSION'"