Smart app updates. Stable system.
pacSelect is a selective, session‑safe updater for Arch‑based systems including CachyOS, EndeavourOS, Manjaro, and plain Arch. It updates everyday applications like browsers, terminals, media players, and development tools while skipping kernel, KDE, and other system‑critical packages that would require a reboot or log‑out to apply safely.
Normal pacman -Syu is great for intentional full upgrades. pacSelect is for everything in between: staying current on applications daily without touching the kernel, drivers, Plasma session, or systemd.
A typical update batch on a KDE / CachyOS system might include:
linux-cachyos-bore(kernel bump → needs reboot)kwin 6.23 → 6.24(KDE minor release → needs log-out)plasma-workspace(running session → unstable if hot-swapped)pipewire(live audio server → disruptive)firefox,ghostty,zen-browser-bin(safe to update now)
pacSelect separates these automatically. You get the app updates immediately; the system updates wait for when you next choose to do a full upgrade.
| Feature | Detail |
|---|---|
| Safe-app detection | Uses checkupdates (read-only, never touches pacman state) to find pending updates, then classifies each package |
| System/core filter | Blocks kernel, initramfs, systemd, glibc, audio pipeline, and ~80 other system packages |
| Graphics filter | Separate category covering the full graphics stack: Mesa (all sub-packages), NVIDIA/AMD/Intel drivers, Vulkan/GL dispatch libs, Xorg, Wayland |
| KDE core filter | Unconditionally blocks session-critical packages: kwin, plasma-*, sddm, kscreenlocker, etc. |
| KDE version-bump detection | Detects the installed KDE Frameworks version at runtime and skips any KDE ecosystem package moving to a new minor release line (e.g. 6.23 → 6.24) |
| Group-based safety net | After name-pattern classification, runs a single pacman -Si over all safe packages and demotes any whose pacman group (e.g. xorg, plasma, base) implies system membership |
| Package descriptions | Shows a short description from pacman -Si below each safe package — no extra process calls |
| AUR updates | Queries paru or yay (if installed) for AUR-only pending updates; displayed in a separate section in the update list |
| AUR filtering | AUR-installed packages (including an AUR-built mesa, GPU driver, or any other foreign package) pass through all the same name-pattern, group, and dependency filters as official packages — filtering is based on package name and group, not package origin |
| Self-update check | At startup, warns if pacselect itself has a pending AUR update and offers to install it via your AUR helper before proceeding |
| Dependency safety check | Reuses the same pacman -Si batch; any safe package that depends on a skipped package is blocked to prevent partial upgrades |
| Grouped skipped display | Deferred packages are shown grouped by category (system, graphics, kde, user, partial) so you can see at a glance what part of the system is held back |
| History log | Appends every run to ~/.local/share/pacselect/history.log |
| JSON output | --json emits machine-readable output — designed as the backend for a future KDE system-tray app |
| User filter patterns | Config file or --skip flag to permanently exclude extra packages, with glob support |
| Config upgrade | --upgrade-config merges new default keys into an existing config file without overwriting any values you've already set |
| Full pacman output | pacman's stdout and stderr are passed through directly — post-install notes, .pacnew warnings, and configuration change notices are never suppressed |
sudo pacman -S pacman-contrib # provides checkupdates
sudo pacman -S rust # only needed to build from sourcegit clone https://github.com/ryansinn/pacselect.git
cd pacselect
cargo build --release
sudo cp target/release/pacselect /usr/local/bin/git clone https://github.com/ryansinn/pacselect.git
cd pacselect
makepkg -siThis builds, runs tests, and installs via pacman so it is tracked and removable with sudo pacman -R pacselect.
Download the pacselect binary from the Releases page and copy it to /usr/local/bin/.
pacselect [OPTIONS]
# Check, show what would change, ask to confirm, then install
pacselect
# See exactly why each package is SAFE or SKIPped
pacselect --verbose
# Preview only — nothing is installed
pacselect --dry-run
# No confirmation prompt
pacselect --yes
# Skip an extra package (glob supported)
pacselect --skip "spotify" --skip "proprietary-*"
# Machine-readable JSON output (implies dry-run)
pacselect --json
# Full system upgrade — includes deferred system/core and KDE packages
pacselect --full-upgrade
# Print all built-in filter patterns
pacselect --list-filters
# Dump a sample config file
pacselect --gen-config > ~/.config/pacselect/config.toml| Flag | Short | Description |
|---|---|---|
--dry-run |
-n |
Show what would happen; install nothing |
--yes |
-y |
Skip the confirmation prompt |
--verbose |
-v |
Per-package SAFE/SKIP classification with reasons |
--no-descriptions |
Hide the description line shown below each safe package | |
--json |
Machine-readable JSON output (implies dry-run) | |
--skip PATTERN |
Extra glob pattern to always skip; repeatable | |
--no-system-filter |
Disable the system/core filter (dangerous) | |
--no-kde-filter |
Disable KDE core + version-bump filters | |
--full-upgrade |
Run pacman -Syu — full upgrade, all filters bypassed |
|
--no-self-update |
Don't check for a pacselect update on startup | |
--config PATH |
Use an alternate config file | |
--list-filters |
Print all built-in blocked patterns and exit | |
--gen-config |
Print a sample config file to stdout and exit | |
--upgrade-config |
Add missing keys to your config file, preserving existing values |
pacSelect reads ~/.config/pacselect/config.toml on startup. Generate a commented template with:
pacselect --gen-config > ~/.config/pacselect/config.tomlIf you already have a config from an older version, bring it up to date without losing your settings:
pacselect --upgrade-config# ~/.config/pacselect/config.toml
[filter_sets]
# Block kernel, systemd, glibc, audio pipeline, storage, and other core packages
system_core = true
# Block KDE core session packages and version-line bumps
kde_core = true
[filters]
# Extra package patterns to ALWAYS skip, on top of the built-in lists.
extra_skip = [
# "spotify",
# "proprietary-*",
]
[display]
# Show a short description below each safe package in the update list
descriptions = true
# Show per-package SAFE/SKIP classification with reasons (same as --verbose)
verbose = false
[behavior]
# Skip the confirmation prompt (same as --yes)
auto_confirm = false
# Never install, only show what would happen (same as --dry-run)
dry_run = false
# Check for a pacselect update on startup and offer to install it first.
# Disable with --no-self-update.
self_update_check = trueAll CLI flags take precedence over config values when both are set.
Each pending update passes through filter layers in order:
1. User filters → extra_skip in config / --skip flags
2. Graphics → Mesa (all sub-packages), NVIDIA/AMD/Intel drivers,
Vulkan/GL dispatch, Xorg, Wayland, libpciaccess
3. System/core → kernel, boot, glibc, systemd, audio, network, storage, …
4. KDE core → session-critical: kwin, plasma-*, sddm, kscreenlocker, …
5. KDE version bump → any KDE ecosystem package (k*, attica, solid, …)
moving to a new minor release line vs. what's installed
After initial classification, a second pass over the safe set queries pacman -Si (one batch call) and:
- Demotes packages whose pacman group (e.g.
xorg,plasma,base) implies system membership - Demotes packages whose runtime dependencies include a skipped package (partial-upgrade prevention)
A package that clears all layers and both post-classification checks is safe and will be installed.
At startup pacSelect runs pacman -Q kcoreaddons (falling back to karchive, kconfig, then the kf6- prefixed variants) to determine the installed KDE Frameworks minor version (e.g. 6.23).
Any package in the KDE ecosystem whose update moves from that minor line to a new one (e.g. 6.24) is deferred. Patch-level updates within the same minor line (e.g. 6.23.0 → 6.23.1) are not blocked. The header at startup shows the detected version:
Desktop: KDE Plasma · KDE Frameworks 6.23
Before displaying the install list, pacSelect syncs the pacman sync database once (sudo pacman -Sy) and then queries pacman -Si for all safe packages to check their runtime dependencies. The sync happens before both the dependency query and the install step — the install command itself does not re-sync the database. This matches the Arch Linux guidance to never run pacman -Sy <packages> without a full -u, since a mid-flight sync can expose newer library versions and create partial-upgrade breakage for deferred packages.
If a safe package depends on a skipped package, it is blocked and moved into the skipped list rather than installed:
SKIP firefox 120.0-1 → 121.0-1
(partial upgrade risk — needs skipped: nss)
This prevents partial upgrades entirely. The summary bar reflects the count:
Safe to install: 4 17 skipped (system: 8 graphics: 5 kde: 4)
The skipped section groups packages by category:
Skipped (17) — use --verbose for details:
system: systemd glibc openssl pipewire
graphics: opencl-mesa vulkan-mesa-implicit-layers nvidia-utils wayland
kde: kwin plasma-workspace karchive
pacselect --dry-run --json (or just --json) emits a JSON object designed to be consumed by automation, scripts, or a future KDE system-tray app:
{
"desktop": "KDE Plasma",
"kde_frameworks": "6.23",
"safe": [
{
"name": "firefox",
"old": "120.0-1",
"new": "121.0-1",
"aur": false
}
],
"skipped": [
{
"name": "linux-cachyos-bore",
"old": "6.12.1-1",
"new": "6.12.2-1",
"reason": "system/core",
"aur": false
},
{
"name": "karchive",
"old": "6.23.0-1.1",
"new": "6.24.0-1.1",
"reason": "KDE version bump 6.23 → 6.24",
"aur": false
},
{
"name": "firefox",
"old": "120.0-1",
"new": "121.0-1",
"reason": "partial upgrade risk — needs skipped: nss",
"aur": false
}
]
}The tray app can poll this on a timer and badge when safe is non-empty.
Every run is appended to ~/.local/share/pacselect/history.log:
[2026-03-16 14:32:05]
UPDATED (3): firefox ghostty zen-browser-bin
SKIPPED (17): linux-cachyos-bore plasma-workspace kwin ...
[2026-03-16 18:10:44] [aborted]
UPDATED (0):
SKIPPED (12): linux-cachyos-bore kwin ...
Modes: normal, [dry-run], [aborted].
- It does not modify pacman, its hooks, or its configuration in any way
- It does not prevent you from running
sudo pacman -Syuat any time - It does not hold packages back in the pacman database
- It does not replace
pacman -Syu— use that for intentional full system upgrades
pacSelect is entirely self-contained. Uninstalling it has zero effect on your system's package state.
-
--upgrade-kdeflag — explicitly include KDE core + version bumps (for intentional log-out upgrades) - Named filter presets in config (e.g.
[presets.gaming]to also hold Mesa/Vulkan) - KDE system-tray app consuming
--jsonoutput - AUR helper integration (
paru,yay) for AUR package updates
GNU General Public License v3.0 — see LICENSE.