| name | nix-profile-cleanup |
| description | Use when migrating packages from `nix profile list` into this dotfiles repo, especially when some packages are already declaratively managed and local profile entries must only be removed after a verified build. |
Nix Profile Cleanup
Overview
This repo wants packages managed declaratively. The safe order is:
- inventory the current profile,
- trace the current host's import chain,
- classify each package,
- edit the reachable Nix files,
- verify the host build,
- only then clean the local profile.
Never remove profile packages first.
When to Use
- A user wants to move imperatively installed packages into this repo.
nix profile list shows tools that should live in roles/, profiles/, or machines/.
- Some packages may already be managed here, and you need to avoid duplicates.
- The user wants a smaller or empty local profile after migration.
Do not use this for throwaway packages the user does not want in dotfiles.
Safety Rules
- Save the full
nix profile list output before changing anything.
- Never edit
archive/.
- Never guess that
Name: or a store-path suffix maps cleanly to pkgs.<name>.
- Never treat a commented-out package as already managed.
- Never auto-uncomment a commented-out package.
- Never remove profile packages until the declarative edits build successfully.
- If the user wants to remove everything, prefer
nix profile remove --all after verification rather than removing shifting numeric indices one by one.
- When editing an existing file, match that file's accessor and comment style.
Host Reachability Check
Before routing packages, determine what the current machine actually imports.
- Run
hostname.
- Read
machines/<host>/default.nix.
- Follow imports until you know whether the host reaches:
roles/core
roles/dev
roles/desktop
- specific
profiles/*.nix
- Only place packages in files reachable from that host.
Important repo facts:
roles/desktop already imports ../dev; do not add roles/dev directly to machine configs unless there is a real exception.
- New files in
roles/, profiles/, and apps/ still need explicit imports.
hm is available in this repo, but older files still use home-manager.users.alex; match the target file's style.
- Package placement rules live in the repo
AGENTS.md; use that shared routing guidance instead of inventing a new destination.
Inventory and Classification
- Run
nix profile list and keep the full output for rollback.
- Normalize packages from the
Name: field first.
- Search
roles/, profiles/, machines/, and modules/ for each package, excluding archive/.
- Classify each package into one of these states:
| State | Meaning | Action |
|---|
| active | Already managed in live code or by programs.*.enable | Do not add it again; only mark it for later profile cleanup |
| commented | Present only as a commented-out line | Show the user the file and line; ask whether to re-enable it or keep it out |
| absent | No live declaration exists | Route it to the correct repo location |
| uncertain | Name or attribute mapping is unclear | Stop and confirm before editing |
Treat programs.<tool>.enable = true as active management even if the package is not listed in home.packages.
If a package comes from overlays, pinned channels, or unusual attribute names, confirm the attribute instead of guessing. Examples already present in this repo include stable.ripgrep-all, gastown, beads, and dolt.
Migration Workflow
- Build a per-package plan with:
- package name,
- state (
active, commented, absent, uncertain),
- proposed destination from the repo
AGENTS.md package-placement guidance,
- whether the package should become permanent dotfiles state or simply disappear from the local profile.
- Present that plan before editing whenever packages are
commented, absent, or uncertain.
- For
active packages, do not touch the repo unless the existing declaration is clearly wrong.
- For
commented packages, never auto-uncomment. Ask whether to re-enable the existing line, add a new live declaration elsewhere, or drop it.
- For
absent packages, make the smallest repo-consistent edit.
- If you create a new file, import it from the correct parent file.
- Match the local style of the file you edit:
- existing file -> match its current accessor style (
hm, home-manager.users.alex, etc.)
- new file -> match nearby siblings in the same directory
- Format and verify the result. Prefer:
treefmt
nh os build
- or
nixos-rebuild build --flake .#<hostname> when you need an explicit host build
- Only after a successful build and explicit confirmation that any unmanaged packages may be dropped, remove the profile entries.
- If the user wants a completely clean profile after migration, run
nix profile remove --all last.
Verification Gate Before Removal
Do not clean the profile until all of these are true:
- the target files were edited in reachable modules,
- any new files were imported,
- the build succeeded for the current host,
- the user has seen the migration plan for non-trivial additions,
- you still have the original
nix profile list output available for rollback.
Common Mistakes
- Dumping every package into one file without checking whether it belongs in core, dev, desktop, a profile, or a machine file.
- Treating a commented-out package as already managed.
- Putting packages into
roles/dev/default.nix on a host that does not import roles/dev.
- Guessing
pkgs.<name> for packages with non-obvious attributes.
- Ignoring
programs.*.enable declarations and adding duplicate package lines.
- Creating a new file and forgetting to import it.
- Removing packages from the profile before the build succeeds.
Quick Checklist