{ lib, buildGoModule, fetchFromGitHub, makeWrapper, furrow, }: # codeaf carries a furrow inside itself: internal/furrowbin embeds whatever is # staged in internal/furrowbin/cache and, on first use, writes it out to # ~/.codeaf/bin/furrow-. Upstream stages the GitHub release asset there, # whose bytes are someone else's glibc-dynamic build that no Nix phase ever # touched, so the file that lands in the state root cannot start here. Staging a # rebuilt furrow is not an option either: upstream's fetcher re-checks the sha256 # named in internal/furrowbin/pin.json and would refuse one. So this build stages # nothing, and hands over ./furrow.nix through CODEAF_FURROW instead, which # internal/furrow reads before it looks at the embedded copy at all. Nothing of # furrow's ends up in the codeaf binary; without that variable codeaf looks for # furrow on PATH, the way a plain `go build` does. # # A codeaf run without this wrapper is not the same program: it has no furrow # unless one is on PATH. buildGoModule rec { pname = "codeaf"; version = "0.7.1"; src = fetchFromGitHub { owner = "Agent-Field"; repo = "CodeAF"; rev = "v${version}"; hash = "sha256-F4rRDNrTCF8/cj6g0KM41+gNdzvTWw5Vj2N0OJp+vCc="; }; vendorHash = "sha256-eIocnhp3uGk+wG0kprRie0Csms+Deqxy3K3HuI1vJyM="; env.CGO_ENABLED = 0; nativeBuildInputs = [ makeWrapper ]; # The shipped binary carries the packed manual rather than the raw Markdown. tags = [ "codeaf_packed_manual" ]; subPackages = [ "cmd/codeaf" ]; # Upstream's own suite is a CI matrix (make test / make check) with network # and timing assumptions; it is not buildGoModule-shaped. doCheck = false; # `make build` runs a host-side step before compiling: packing the manual into # what the codeaf_packed_manual tag embeds. It is built for the build machine # even when codeaf targets another platform, hence the unset GOOS/GOARCH. The # vendoring derivation runs preBuild too, before vendor/ exists, and this step # needs the vendored dependencies, so it waits for it. Upstream's other step, # staging the furrow release, is deliberately not run: see ./furrow.nix. preBuild = '' if [ -d vendor ]; then env -u GOOS -u GOARCH go generate ./internal/manual fi ''; postInstall = '' wrapProgram $out/bin/codeaf --set CODEAF_FURROW ${furrow}/bin/furrow ''; ldflags = [ "-s" "-w" "-X github.com/Agent-Field/codeaf/internal/buildinfo.rev=${version}" "-X github.com/Agent-Field/codeaf/internal/buildinfo.dirty=false" ]; passthru = { inherit furrow; category = "AI Coding Agents"; updateScript = [ "nix-update" "--flake" ".#codeaf" # furrow.nix is not a flake output, so nix-update never touches it: bump it # by hand alongside the version codeaf pins in internal/furrowbin/pin.json. ]; }; meta = with lib; { description = "Coding harness and software factory for open models: hand off work and watch every project from one terminal"; homepage = "https://github.com/Agent-Field/CodeAF"; changelog = "https://github.com/Agent-Field/CodeAF/blob/v${version}/CHANGELOG.md"; license = licenses.asl20; # Runs the furrow built from source by ./furrow.nix, not the release asset # upstream would have embedded. mainProgram = "codeaf"; platforms = platforms.linux ++ platforms.darwin; }; }