···1-#!/usr/bin/env bash
23-export DIRENV_WARN_TIMEOUT=20s
45-eval "$(devenv direnvrc)"
67-# `use devenv` supports the same options as the `devenv shell` command.
8-#
9-# To silence all output, use `--quiet`.
10-#
11-# Example usage: use devenv --quiet --impure --option services.postgres.enable:bool true
12-use devenv
···1+# #!/usr/bin/env bash
23+# export DIRENV_WARN_TIMEOUT=20s
45+# eval "$(devenv direnvrc)"
67+# # `use devenv` supports the same options as the `devenv shell` command.
8+# #
9+# # To silence all output, use `--quiet`.
10+# #
11+# # Example usage: use devenv --quiet --impure --option services.postgres.enable:bool true
12+# use devenv
···14cp .env.example .env # configure environment variables
15```
1617+### Nix Package Hash (`pnpmDeps`)
18+19+`nix/package.nix` contains a `hash =` for `pnpm_9.fetchDeps`. This hash must be updated every time `pnpm-lock.yaml` changes.
20+21+**Why it changes:** `pnpm_9.fetchDeps` is a Nix fixed-output derivation (FOD) that downloads packages via pnpm in a sandbox. When the lockfile changes, the set of downloaded packages changes, so the hash changes. Platform-specific optional packages (e.g. `@esbuild/linux-arm64`) mean macOS and Linux produce different hashes — the hash in the repo must match what the Linux build produces.
22+23+**How to update it:** Run the helper script **on a Linux machine** (or with a Linux remote Nix builder configured):
24+25+```sh
26+pnpm nix:update-hash
27+# or directly:
28+bash scripts/update-pnpmdeps-hash.sh
29+```
30+31+The script:
32+1. Replaces the current hash with `lib.fakeHash` (a known-invalid placeholder)
33+2. Runs `nix build .#packages.x86_64-linux.default` — which fails with the correct hash in the error
34+3. Parses that hash and writes it back to `nix/package.nix`
35+36+**On macOS without a Linux builder:** Push your branch to CI, copy the correct hash from the build failure output, and update `nix/package.nix` manually.
37+38### Auto-Fixing Lint Issues
3940Before committing, auto-fix safe lint violations:
···1+#!/usr/bin/env bash
2+set -eo pipefail
3+4+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
6+PACKAGE_NIX="$PROJECT_ROOT/nix/package.nix"
7+8+# lib.fakeHash — a structurally valid but incorrect sha256 that forces Nix
9+# to report the actual hash of whatever it fetches.
10+FAKE_HASH="sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
11+12+# ---------------------------------------------------------------------------
13+# Platform check
14+# ---------------------------------------------------------------------------
15+# The Nix flake only targets x86_64-linux / aarch64-linux. pnpm fetchDeps
16+# downloads platform-specific optional packages (e.g. @esbuild/darwin-arm64
17+# vs @esbuild/linux-arm64), so a macOS pnpm fetch produces a different hash
18+# than a Linux one. This script must run on Linux or use a remote Linux
19+# Nix builder to produce the correct hash.
20+# ---------------------------------------------------------------------------
21+if [[ "$(uname)" == "Darwin" ]]; then
22+ echo "WARNING: This script should run on Linux (or via a Linux Nix remote builder)."
23+ echo ""
24+ echo "The Nix flake targets x86_64-linux/aarch64-linux only. When pnpm fetches"
25+ echo "on macOS it downloads darwin-specific optional packages (@esbuild/darwin-arm64,"
26+ echo "etc.), producing a different hash than the Linux build expects."
27+ echo ""
28+ echo "Options:"
29+ echo " 1. SSH into a Linux machine and run this script there"
30+ echo " 2. Configure a Linux Nix remote builder in ~/.config/nix/nix.conf"
31+ echo " 3. Push to CI, copy the correct hash from the build error output,"
32+ echo " then update nix/package.nix manually"
33+ echo ""
34+ read -p "Continue anyway (e.g. you have a remote builder configured)? [y/N] " -n 1 -r
35+ echo
36+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
37+ exit 0
38+ fi
39+fi
40+41+echo "Updating pnpmDeps hash in nix/package.nix..."
42+43+# Extract current hash
44+CURRENT_HASH=$(grep -oP '(?<=hash = ")[^"]+' "$PACKAGE_NIX")
45+echo " Current: $CURRENT_HASH"
46+47+# Swap in the fake hash so Nix is forced to compute and report the real one
48+if [[ "$(uname)" == "Darwin" ]]; then
49+ sed -i '' "s|$CURRENT_HASH|$FAKE_HASH|" "$PACKAGE_NIX"
50+else
51+ sed -i "s|$CURRENT_HASH|$FAKE_HASH|" "$PACKAGE_NIX"
52+fi
53+54+echo " Running: nix build .#packages.x86_64-linux.default"
55+echo " (Nix will fail with a hash mismatch — that is expected)"
56+57+BUILD_OUTPUT=$(nix build .#packages.x86_64-linux.default 2>&1 || true)
58+59+# Nix prints: " got: sha256-<actual hash>"
60+NEW_HASH=$(echo "$BUILD_OUTPUT" | grep "got:" | awk '{print $NF}' | head -1)
61+62+if [ -z "$NEW_HASH" ]; then
63+ echo ""
64+ echo "ERROR: Could not parse the correct hash from nix output."
65+ echo ""
66+ echo "Full build output:"
67+ echo "$BUILD_OUTPUT"
68+ echo ""
69+ echo "Restoring original hash..."
70+ if [[ "$(uname)" == "Darwin" ]]; then
71+ sed -i '' "s|$FAKE_HASH|$CURRENT_HASH|" "$PACKAGE_NIX"
72+ else
73+ sed -i "s|$FAKE_HASH|$CURRENT_HASH|" "$PACKAGE_NIX"
74+ fi
75+ exit 1
76+fi
77+78+# Write the real hash back
79+if [[ "$(uname)" == "Darwin" ]]; then
80+ sed -i '' "s|$FAKE_HASH|$NEW_HASH|" "$PACKAGE_NIX"
81+else
82+ sed -i "s|$FAKE_HASH|$NEW_HASH|" "$PACKAGE_NIX"
83+fi
84+85+echo " Updated: $NEW_HASH"
86+echo ""
87+echo "Commit the change:"
88+echo " git add nix/package.nix && git commit -m 'chore: adjust pnpmdeps hash'"