safe-apt-install-evaluation
Preview an `apt install` transaction with `--simulate` and flag dangerous removals (kernel, NVIDIA, mesa, DKMS, desktop metapackages, `-common` packages) plus the repository origin before the user act
SKILL.mdclaude-skills/safe-apt-install-evaluation/SKILL.md
GitHubSafe apt install Evaluation
The user is a superuser on a shared Ubuntu machine and has previously had ubuntu-desktop / NVIDIA / DKMS torn out by a careless apt install. This skill runs the simulation, parses the output, and tells them whether the transaction is safe to proceed with — never run the real install yourself.
Core Recipe
Step 1 — Simulate the transaction
-s / --simulate does not need root and does not modify the system:
apt-get -s install <pkg> [<pkg>...]
Use apt-get (not apt) — its output is stable and machine-parseable; apt's output is intentionally user-facing and can change.
Step 2 — Check the repository origin
For each package the user named:
apt-cache policy <pkg>
The 500/1001/etc. priority lines and the URI tell you which repo a package will come from. Flag anything coming from a PPA, the NVIDIA CUDA repo, -proposed, or -backports — those are the usual sources of "shadowing" surprises, especially for nvidia-* where mixing providers causes pain.
Step 3 — Show current holds (context)
apt-mark showhold
Anything in the simulation's REMOVE list that is also on hold is a strong sign the resolver is fighting the user's intent. Mention it.
Step 4 — Parse the simulation output
Focus on these blocks from apt-get -s install stdout:
| Block | What it means | How to triage |
|---|---|---|
The following NEW packages will be installed: |
New deps being pulled in | Informational — list briefly |
The following packages will be upgraded: |
Version bumps | Informational unless a load-bearing pkg is in here (see danger list) |
The following packages will be REMOVED: |
DANGER — apt will rip these out | Match every entry against the danger patterns below |
The following packages have been kept back: |
Resolver gave up on these | Mention — often signals a conflict |
0 upgraded, N newly installed, M to remove |
Summary line | If M > 0, treat as suspicious until each removal is justified |
Step 5 — Match removals against danger patterns
Flag any removal matching these patterns as a stop-the-world finding:
linux-image-*,linux-headers-*,linux-generic,linux-modules-*,linux-hwe-*— kernelnvidia-*,libnvidia-*,cuda-*,nvidia-driver-*,nvidia-dkms-*— GPU stackmesa-*,libgl*,libegl*,libgles*,libdrm*,xserver-xorg-*— graphics stackubuntu-desktop,ubuntu-desktop-minimal,gnome-shell,gdm3,plasma-desktop,kde-plasma-*— desktop metapackages- Anything ending in
-common(xserver-common,libreoffice-common, etc.) — usually the seam that takes a metapackage with it - Anything containing
dkms— DKMS-built modules (NVIDIA, ZFS, VirtualBox, etc.) systemd,systemd-*,init,dbus,libc6,libc-bin— userspace base; removing these bricks the boot- The exact same package the user asked to install (sign of a conflict)
If nothing in the REMOVE list matches the danger list, the transaction is low-risk — say so explicitly.
Step 6 — Report to the user
Use this structure. Be concise — the user reads the verdict line first and the evidence only if they care.
Verdict: SAFE | CAUTION | DO NOT PROCEED
Command they should run:
sudo apt install <pkg> # if safe
(do not run yet) # if caution / unsafe
Removals: <N>
<pkg> — [DANGER: kernel | NVIDIA | desktop metapackage | etc.]
<pkg> — (benign, obsoleted transitional package)
Repository origin (apt-cache policy):
<pkg> → <repo URI> [flag if PPA / CUDA repo / -proposed]
Holds in play:
<list, or "none">
Other notes:
- <kept-back packages, if any>
- <upgrades of load-bearing packages, if any>
Verdict rules:
- DO NOT PROCEED — any danger-list match in REMOVE.
- CAUTION — any non-empty REMOVE list, OR any kept-back package, OR the package comes from a shadowing repo (PPA / CUDA / proposed) the user may not realize.
- SAFE — empty REMOVE list, no kept-back packages, origin is the main Ubuntu archive.
If verdict is not SAFE, suggest the recovery levers from the [[apt-best-practices]] context:
apt-mark hold <pkg>to pin the at-risk packages before retryingapt-cache policyto pick a different originaptitude install <pkg>— its solver often proposes a non-destructive alternative path thatapt's resolver won't find- A
timeshift/dpkg --get-selections > ~/packages-$(date +%F).listsnapshot before any destructive transaction - Consider whether the tool could live in a container (CUDA toolkit),
pipx,cargo install, or~/.localinstead of apt
Variations
- Multiple packages at once: pass them all to one
apt-get -s installcall. Apt's resolver works on the combined set; simulating them one-by-one hides interactions. full-upgrade/dist-upgradepreviews:apt-get -s full-upgradeis fair game with the same parsing rules. Default-recommend plainapt upgradeoverfull-upgradeon shared machines (the former is not allowed to remove packages to resolve deps).- Reverse — "what depends on this?": if you're worried about a removal,
apt-cache rdepends --installed <pkg>shows what would break. - Sanity check the system first: if
dpkg --auditreturns anything, the system is already in a half-configured state and the simulation may be misleading. Flag this before trusting the plan.
When Applying This Skill
- Did the user actually ask to evaluate, or to install? This skill only evaluates — never run the real
sudo apt install. End with a recommended command for the user to run themselves. - Did you pass every package the user named in a single
apt-get -s installcall? - Did you check
apt-cache policyfor every named package (not just the leaf install)? - Did you scan the REMOVED block against every danger pattern, not just kernel/NVIDIA?
- Did you note any kept-back packages? (Resolver giving up is a yellow flag even with an empty REMOVE list.)
- Did you give a single-word verdict line at the top so the user can decide in two seconds?