The Ur Project

Documenting the craft of stacking things so they remain stacked. For a very long time.

pkg-autoremove(1)

NAME

pkg-autoremove - remove installed packages no selection root still reaches

SYNOPSIS

pkg autoremove [--dry-run] [--force]

DESCRIPTION

Install something big, remove it again, and the dependencies it pulled in are still sitting there. Nothing needs them anymore, but nothing removed them either. This command cleans that up.

It works from what you asked for. Every package and set you named to pkg-install(1) is recorded as a selection root. autoremove follows the roots through their dependencies, and everything installed that it can't reach from them gets removed. Put as a rule:

remove = installed - closure(roots)

That's the whole algorithm. See pkg-sets(7) for what records the roots and where they live.

When does it refuse to guess?

There are two cases where autoremove does nothing at all, and that's on purpose. Both are cases where following the rule literally would do real damage.

No roots recorded

An empty roots file means "we don't know what was wanted", not "nothing was wanted". Apply the rule literally and it removes everything installed. So nothing is removed, and the command says:

no selection roots recorded -- nothing to converge against (0 removed). Mark what you want kept with pkg install <name>.

That's the safe answer for a machine that predates root tracking, or one whose last root was just dropped.

A set root that doesn't resolve

If a set root can't be resolved against the current chain (its sets.json is unreachable, the set was removed upstream, or its expansion loops), the whole sweep is held, and nothing is removed. Letting that set contribute no members would orphan everything it wanted. This one is an error, because you have something to fix:

error: set: set root +xfce is not resolvable in the current chain (its sets.json is unreachable, or the set was removed); holding the converge -- nothing removed

Fix the chain (re-enable a repository, get the network back) and run it again, or drop the stale root with pkg remove +name.

An empty roots file exits 0: declining isn't failing. A held set root exits 1, because the chain is broken and you should hear about it.

OPTIONS

--dry-run
Compute and print the sweep, and remove nothing.
--force
I know, do it anyway. Proceeds past a pre-flight GC blocker on a removal: a running process maps an outgoing file, an installed binary still needs a soname, a kernel module is loaded. Everything it bypasses is reported, never silenced, and passing it makes the command ask for confirmation.

All global options apply; see pkg(1).

CONFIRMATION

autoremove is an explicit deletion, so it asks at the default confirm level, destructive.

OUTPUT

When there's nothing to sweep:

0 orphans -- nothing to remove.

Otherwise you get the plan and the completion line of pkg-install(1).

JSON

When nothing is swept, because no roots are recorded or because there are no orphans:

{ "ok": true, "kind": "autoremove", "removed": [] }

Otherwise the plan and completion shapes of pkg-install(1).

EXAMPLES

The safe loop

pkg autoremove --dry-run pkg autoremove

After removing something big

pkg remove build-toolchain pkg autoremove --dry-run

What's keeping this package around?

There's no direct query for this. The two halves are:

cat /var/lib/pkg/roots.toml pkg set show +console

A package that's reachable from a package root, or from any member of any set root, is kept.

Starting roots on a machine that has none

pkg autoremove --dry-run

If it reports no roots, mark what the machine is for before you sweep:

pkg install +console pkg install vim htop pkg autoremove --dry-run

Non-interactive

pkg --yes autoremove pkg --json --yes autoremove | jq '.removed_count // 0'

How big is the keep set?

pkg -v autoremove --dry-run

The -v line reports how many names the roots expanded to.

Sweeping a mounted image instead of the live system

pkg --state-root /mnt/image/var/lib/pkg autoremove --dry-run

EXIT STATUS

0 on success, including when no roots are recorded. 1 on any failure, including a set root that doesn't resolve and a declined confirmation.

SEE ALSO

pkg(1), pkg-remove(1), pkg-install(1), pkg-list-sets(1), pkg-set(1), pkg-state(5), pkg-sets(7)

docs/design/package-sets.md