Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

241 changes: 241 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
{
description = "Nix package and development shell for agent-tty";

inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";

outputs = {
self,
nixpkgs,
...
}: let
systems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
];
forAllSystems = nixpkgs.lib.genAttrs systems;
in {
packages = forAllSystems (system: let
pkgs = import nixpkgs {inherit system;};
lib = pkgs.lib;
nodejs = pkgs.nodejs_26;

dependencySource = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions [
./package.json
./aube-lock.yaml
./pnpm-workspace.yaml
];
};

packageSource = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions [
./package.json
./aube-lock.yaml
./pnpm-workspace.yaml
./tsconfig.json
./tsconfig.build.json
./src
./scripts
./skills
./skill-data
];
};

# Aube's lockfile contains integrity hashes for every package, while this
# fixed-output derivation pins the complete downloaded cache. The package
# derivation below must then install with --offline.
dependencyCache = pkgs.stdenvNoCC.mkDerivation {
pname = "agent-tty-aube-cache";
version = "0.5.0";
src = dependencySource;

nativeBuildInputs = [
pkgs.aube
pkgs.cacert
];

dontConfigure = true;
dontFixup = true;

buildPhase = ''
runHook preBuild

# Use Nixpkgs' pinned Aube. Package-manager self-switching would make
# the fetched tool another undeclared dependency of the build.
substituteInPlace package.json \
--replace-fail ' "packageManager": "aube@1.2.0",' ""

export HOME="$TMPDIR/home"
export XDG_CACHE_HOME="$TMPDIR/cache"
export XDG_DATA_HOME="$TMPDIR/data"
mkdir -p "$HOME" "$XDG_CACHE_HOME" "$XDG_DATA_HOME"

aube fetch --frozen-lockfile --reporter append-only

runHook postBuild
'';

installPhase = ''
runHook preInstall
mkdir -p "$out/cache" "$out/data"
cp -R "$XDG_CACHE_HOME"/. "$out/cache"/
cp -R "$XDG_DATA_HOME"/. "$out/data"/
runHook postInstall
'';

outputHashMode = "recursive";
outputHashAlgo = "sha256";
outputHash = "sha256-U5oksqBtoQTDwVKwEXjgc9z3WRaMv7MVPyeK3/195oc=";
};

agent-tty = pkgs.stdenvNoCC.mkDerivation {
pname = "agent-tty";
version = "0.5.0";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive the Nix package version from package.json

When the next automated release updates package.json, this hard-coded value—and the duplicate cache version at line 52—will remain 0.5.0, because release-please-config.json:10 only registers README.md as an extra versioned file. The resulting Nix package will therefore expose stale derivation metadata even though the bundled CLI reports the new version; derive this value from package.json or add both occurrences to the release update process.

Useful? React with 👍 / 👎.

src = packageSource;

nativeBuildInputs = [
pkgs.aube
nodejs
pkgs.python3
pkgs.stdenv.cc
pkgs.gnumake
pkgs.pkg-config
pkgs.node-gyp
pkgs.makeWrapper
];

dontConfigure = true;

buildPhase = ''
runHook preBuild

substituteInPlace package.json \
--replace-fail ' "packageManager": "aube@1.2.0",' ""

export HOME="$TMPDIR/home"
export XDG_CACHE_HOME="$TMPDIR/cache"
export XDG_DATA_HOME="$TMPDIR/data"
mkdir -p "$HOME" "$XDG_CACHE_HOME" "$XDG_DATA_HOME"
cp -R ${dependencyCache}/cache/. "$XDG_CACHE_HOME"/
cp -R ${dependencyCache}/data/. "$XDG_DATA_HOME"/
chmod -R u+w "$XDG_CACHE_HOME" "$XDG_DATA_HOME"

aube install \
--offline \
--frozen-lockfile \
--ignore-scripts \
--disable-global-virtual-store \
--package-import-method copy \
--reporter append-only

# node-pty has no Linux prebuild in the locked package. Build it with
# Nixpkgs' node-gyp so Aube never bootstraps a tool from the network.
(
cd node_modules/node-pty
node-gyp rebuild
)
npm run build

runHook postBuild
'';

installPhase = ''
runHook preInstall

app="$out/lib/agent-tty"
production="$TMPDIR/production"
mkdir -p "$app" "$out/bin"

# Build tools are devDependencies, so compile first and then create a
# fresh production graph. Aube's in-place prune currently leaves
# dangling virtual-store links behind.
mkdir -p "$production"
cp package.json aube-lock.yaml pnpm-workspace.yaml "$production"/
(
cd "$production"
aube install \
--prod \
--offline \
--frozen-lockfile \
--ignore-scripts \
--disable-global-virtual-store \
--package-import-method copy \
--reporter append-only

cd node_modules/node-pty
node-gyp rebuild
)

cp -R dist package.json skills skill-data "$app"/
cp -R "$production/node_modules" "$app"/

makeWrapper ${nodejs}/bin/node "$out/bin/agent-tty" \
--add-flags "$app/dist/cli/main.js"

runHook postInstall
'';

meta = {
description = "Drive, inspect, and record terminal sessions from the CLI";
homepage = "https://github.com/coder/agent-tty";
license = lib.licenses.asl20;
mainProgram = "agent-tty";
platforms = systems;
};
};
in {
default = agent-tty;
inherit agent-tty;
});

checks = forAllSystems (system: let
pkgs = import nixpkgs {inherit system;};
package = self.packages.${system}.default;
in {
inherit package;

smoke =
pkgs.runCommand "agent-tty-smoke" {
nativeBuildInputs = [
package
pkgs.jq
];
} ''
export HOME="$TMPDIR/home"
mkdir -p "$HOME"

agent-tty version --json > version.json
doctor_exit=0
agent-tty --home "$TMPDIR/agent-tty-home" doctor --json > doctor.json || doctor_exit=$?
printf '%s\n' "$doctor_exit" > doctor-exit-status
jq -e '.result.checks.environment[] | select(.name == "pty-spawn" and .status == "pass")' doctor.json

mkdir -p "$out"
cp version.json doctor.json doctor-exit-status "$out"/
'';
});

devShells = forAllSystems (system: let
pkgs = import nixpkgs {inherit system;};
in {
default = pkgs.mkShell {
packages = [
pkgs.nodejs_26
pkgs.aube
pkgs.zig_0_15
pkgs.python3
pkgs.stdenv.cc
pkgs.gnumake
pkgs.pkg-config
pkgs.git
pkgs.cacert
];
};
});

formatter = forAllSystems (system: (import nixpkgs {inherit system;}).alejandra);
};
}