# Upgrading nixpkgs Procedure for the periodic upgrade of all four nixpkgs channels (`unstable`, `stable`, `mine`, `mine-stable`) and home-manager. Written to be followed by a person or any coding agent; a Claude Code entry point exists at `.claude/skills/upgrade-nixpkgs/` but the steps below are the canonical source. The upgrade is **guided, not automated**: do the mechanical and investigative steps, but stop at the judgment points (marked ⏸) — pushing the fork, resolving rebase conflicts, editing the `flake.nix` stable pins, and deleting version guards. Report findings and let the maintainer decide. Keep a running summary and present it before any push or commit. Work the phases in order; skip one only if explicitly scoped to a subset. ## Setup facts - **Fork checkout:** `~/documents/projects/nixpkgs` — remotes `origin` (`devplayer0/nixpkgs`) and `upstream` (`NixOS/nixpkgs`). Confirm the path exists; if not, ask. - **Fork branches:** `devplayer0` (tracks `nixos-unstable`) and `devplayer0-stable` (tracks the current NixOS stable). Each is a small stack of local patches rebased onto upstream. - **Flake pins** in `flake.nix` (`inputs`): - `nixpkgs-unstable.url = "nixpkgs/nixos-unstable"` - `nixpkgs-stable.url = "nixpkgs/nixos-"` (e.g. `nixos-26.05`) - `nixpkgs-mine.url = "github:devplayer0/nixpkgs/devplayer0"` - `nixpkgs-mine-stable.url = "github:devplayer0/nixpkgs/devplayer0-stable"` - `home-manager-unstable.url = "home-manager"` - `home-manager-stable.url = "home-manager/release-"` - **Devshell commands:** `update-nixpkgs` = `nix flake update nixpkgs-{unstable,stable,mine,mine-stable}`; `update-home-manager` = `nix flake update home-manager-{unstable,stable}`. - **Validation:** prefer `check-system ` and `nix flake check --no-build` over full builds. ## Phase 1 — Determine the current NixOS stable Do this first: everything downstream (the fork's `devplayer0-stable` rebase target, the `flake.nix` stable pins) has to agree on one NixOS stable release, so establish it up front. 1. Find the latest NixOS stable release branch — check `git branch -r` on `upstream` for the newest `release-YY.NN`, or the NixOS release schedule. 2. Compare it to `` in the `flake.nix` `nixpkgs-stable` / `home-manager-stable` URLs. 3. **If they already match** (no new stable): note "stable is current" and carry `` into the later phases. 4. ⏸ **If a newer stable has cut:** stop and report the coordinated change set before proceeding — the pieces must all move to the same release together: - Rebase `devplayer0-stable` onto the new `upstream/release-YY.NN` (Phase 2 uses this target). - Edit `flake.nix`: `nixpkgs-stable.url` and `home-manager-stable.url` → the new release. - Bump each system's `stateVersion` / `home.stateVersion` only if the maintainer explicitly wants to — that is a separate, deliberate decision; never auto-bump. Don't edit `flake.nix` here without confirmation. ## Phase 2 — Rebase the nixpkgs fork For **both** branches — `devplayer0` onto `upstream/nixos-unstable`, and `devplayer0-stable` onto `upstream/release-` (the release established in Phase 1): 1. In `~/documents/projects/nixpkgs`, confirm a clean working tree (`git status`). If dirty, stop and report — don't stash silently. 2. `git fetch upstream --prune` and `git fetch origin --prune`. If the checkout has been idle a long time this fetch can be large and slow; let it finish. 3. Enumerate the patch stack before rebasing: `git log --oneline upstream/nixos-unstable..origin/devplayer0` (and the stable equivalent against `upstream/release-`). For each commit, check whether it has landed upstream or been superseded — e.g. `git log --oneline upstream/nixos-unstable -- ` or grep the upstream tree for the package/option. Note any patch that now looks redundant. 4. Rebase: `git switch devplayer0 && git rebase upstream/nixos-unstable` (and the stable branch onto `upstream/release-`). - ⏸ **Conflicts:** stop. Report which patch conflicts and against what upstream change; let the maintainer resolve, or drop the patch if it has been upstreamed. - Clean rebase: continue. 5. Summarize: which patches still apply, which are now redundant (candidate to drop), which conflicted. 6. ⏸ **Push:** only after confirmation. `git push --force-with-lease origin devplayer0 devplayer0-stable` (force needed — rebase rewrites history). ## Phase 3 — Update the pinned inputs Run together (they move as a set): ``` update-nixpkgs update-home-manager ``` Then show the `flake.lock` diff for the nixpkgs/home-manager entries so the old→new revisions are visible. ## Phase 4 — Sweep version-gated behavior The repo carries branch-conditional logic and TODOs keyed to specific nixpkgs versions; some become removable after an upgrade, especially after a stable bump. Surface them: ``` grep -rn "versionAtLeast\|versionOlder\|when 2[0-9]\.[0-9][0-9]\|TODO.*2[0-9]\.[0-9][0-9]" \ --include=*.nix nixos home-manager lib pkgs flake.nix ``` Known example: `nixos/modules/common.nix` carries a `# TODO: Remove if-else when 26.11 releases` guard. For each hit, evaluate whether the now-current versions make the guard removable and list candidates. ⏸ Don't delete guards without confirmation — some protect the still-supported stable. ## Phase 5 — Review remaining flake inputs Don't blanket-update. Walk the other inputs deliberately: 1. List inputs and locked revisions from `flake.lock` (or `nix flake metadata`). 2. For each meaningful input (`libnetRepo`, `devshell`, `determinate-nix`, `ragenix`, `deploy-rs`, `impermanence`, and the packaged apps like `boardie`, `harmonia`, `copyparty`, `sharry`, …), compare the locked revision to upstream and summarize notable changes (breaking changes, relevant fixes). Many inputs `follows` `nixpkgs-unstable` and already moved in Phase 3. 3. Propose a per-input update list with reasons; update the approved ones with targeted `nix flake update `, not a global update. ## Phase 6 — Validate 1. `nix flake check --no-build` (broad eval; reproduces CI's cheap checks). 2. `check-system ` on a representative box, and one exercising the stable channel if the boxes mix channels. 3. Report eval/build results honestly. On failure, surface the error and stop rather than papering over it. ## Wrap-up Present a final summary: fork rebase outcome (patches kept/dropped/conflicted), whether a stable bump is pending or was applied, the lock diff, version-gate cleanup candidates, inputs updated, and validation results. Leave committing to the maintainer unless asked; if committing, follow the repo's `area/scope: Capitalized summary` convention.