One command, up, refreshes, upgrades and cleans every package manager on your Linux, macOS or Windows machine.
up finds the managers you have (apt, dnf, pacman, brew, winget, flatpak, snap and more), asks for sudo or a UAC prompt once if one of them needs it, runs each in turn and prints one summary. It runs on bash on Linux and macOS and on PowerShell on Windows. Nothing else is installed.
Every configuration and environment variable, the JSON fields and the plugin API are in the documentation and the man page man/up.1, which install.sh installs (man up).
- Clone the repository:
git clone https://github.com/MasterCruelty/eMerger && cd eMerger. - Run
./install.sh(Linux, macOS) or.\install.ps1(Windows PowerShell). - Open a new terminal.
- Run
up -nto see what would run. Nothing changes. - Run
upto update.
$ up
◆ Debian GNU/Linux 13 · x86_64 · 2026-10-16 10:12 · eMerger v3.0.0
🌀 apt ~40s ──────────────────────────────────────── ▰▱ 1/2
✔ update ···················· 6.8s
⠉ full-upgrade .:::. 0:14 Unpacking libssl3 ...
📦 flatpak ────────────────────────────────────────── ▰▰ 2/2
✔ update ···················· 12.4s 5 refreshed
╭─ eMerger summary ──────────────────────────╮
│ managers ✔ apt ✔ flatpak │
│ time 0m42s │
│ freed 812.0MB │
│ status ✔ all good │
╰────────────────────────────────────────────╯
Do not run sudo up: under sudo, user-level packages (pip --user, Homebrew, npm -g) land in root's home. up asks for sudo itself.
| platform | required | optional |
|---|---|---|
| Linux | bash 4.4 or later, coreutils, git, sudo | curl (-w, --doctor), flock, timeout, pkill (stops --parallel managers on Ctrl-C), notify-send, fwupdmgr, snapper or timeshift or btrfs-progs, reflector or netselect-apt |
| macOS | bash 4.4 or later first in PATH (/bin/bash 3.2 is too old: brew install bash), Xcode Command Line Tools |
Homebrew, mas |
| Windows | PowerShell 5.1 or 7, Git for Windows | winget, scoop, choco, the PSWindowsUpdate and BurntToast modules |
up installs none of these. It uses what it finds.
./install.sh:
- adds
alias up='bash "/path/to/eMerger/src/emerger.sh"'to your bash, zsh and fish startup files (~/.zshrcfirst on macOS); - installs completions for bash, zsh and fish, and the man page in
~/.local/share/man/man1/(man up); - creates
~/.config/emerger/withconfig.sh,ignore.list,hooks/andprofiles.d/.
A checkout path containing ', ", $, a backquote, %, \ or a newline is refused: move the checkout first.
.\install.ps1 needs no administrator rights:
- if the
CurrentUserexecution policy isRestrictedorUndefined, it asks before settingRemoteSigned; - it adds an
upfunction to$PROFILE.CurrentUserAllHosts; - it creates
%APPDATA%\emerger\withconfig.ps1,hooks\andprofiles.d\.
Without the install script, point an alias at the entry point: alias up='bash /path/to/eMerger/src/emerger.sh', or in PowerShell function up { & 'C:\path\to\eMerger\src\emerger.ps1' @args }.
up # update everything
up -n -v # preview, with each manager's output
up --security -y # unattended, security updates only
up --dev --firmware # also dev toolchains and firmware (Linux)
up --only apt,flatpak # these managers only
up --except snap # every manager but snap
up --download-only -y # download now, install on a later run
up --changed # what the last run added, removed, upgraded
up --history # the last runs
up --doctor # check the environment
up -au # install a weekly unattended runup -au runs up -y -q -nl -ni every Sunday at 10:00: a systemd user timer or cron on Linux, cron on macOS, Task Scheduler on Windows (a manager that needs admin raises a UAC prompt at that time). On Linux, a user timer needs a login session: run loginctl enable-linger $USER once to let it fire without one.
up --help prints the same list. A flag that takes a value accepts --flag VALUE or --flag=VALUE. -- ends the options. Short flags from the set h V n v q y w bundle: -nv is -n -v.
On Windows, a flag marked "Unix" prints a warning. The run goes on without it, except --changed, --changelog and --rollback, which exit 0 without updating.
| flag | effect | platforms |
|---|---|---|
-h, --help |
Show the help | all |
-V, --version |
Show the version | all |
--doctor |
Check the environment; exit non-zero on a warning | all |
-n, --dry-run |
Print the commands, change nothing | all |
-v, --verbose |
Stream each manager's output | all |
-q, --quiet |
One quieter level per use | all |
-qq |
Summary line only | all |
-qqq |
Nothing, exit code only | all |
-y, --yes |
Answer yes to every prompt | all |
--json |
One JSON summary on stdout | all |
--security |
Security updates only; managers without them are skipped | all |
--accept-licenses |
Let softwareupdate, winget, choco and Windows Update accept licence agreements; without it they only list updates |
macOS, Windows |
--firmware |
Include fwupdmgr and the Raspberry Pi bootloader |
Unix |
--no-firmware |
Skip firmware, even when the config sets --firmware |
Unix |
--dev |
Include rustup, cargo, npm, pnpm, pip, gem |
all |
--parallel |
Run user-space managers at the same time | Unix |
--profile NAME |
Load a profile before the flags | all |
--list-profiles |
List the profiles | all |
--only LIST |
Run only these managers (comma-separated) | all |
--except LIST |
Skip these managers; adds to the config's list | all |
--snapshot |
Take a snapper, timeshift or btrfs snapshot first, or exit 1 | Unix |
--rollback |
Revert to the latest eMerger snapshot | Unix |
--refresh-mirrors |
Re-rank the mirrors first | Unix |
--resume |
Skip the managers the last run finished | Unix |
--reboot |
Reboot now if the system needs it | all |
--reboot-exit |
Exit 4 instead of 0 when a reboot is pending | all |
--download-only |
Download without installing (apt, dnf, pacman, zypper, softwareupdate); skip every other manager | Unix |
-nl, --no-logo |
Hide the logo | all |
-ni, --no-info |
Hide the system line | all |
-w, --weather |
Show a weather line from wttr.in | all |
--ascii |
ASCII glyphs only | all |
-nc, --keep-cache |
Skip user cache cleaning (Windows: %TEMP%) |
all |
-nt, --keep-trash |
Skip trash cleaning (Windows: Recycle Bin) | all |
--deep-clean |
Also clean the journal, old kernels, leftover configs, snap revisions, container images, crash dumps, npm and Go caches, asking for each | Unix |
--changed |
Show the last run's package changes | Unix |
--changelog PKG |
Show the upstream changelog of PKG |
Unix |
--history |
Show the last runs | all |
--metrics FILE |
Export the last run as a Prometheus textfile | all |
-err, --errors |
Show logged errors | all |
-up, --self-update |
Update eMerger with git pull --ff-only |
all |
-au, --auto-update |
Install the weekly run | all |
-rc, --rebuild-cache |
Clear the manager detection cache (Windows keeps none) | all |
~/.config/emerger/config.sh (Windows: %APPDATA%\emerger\config.ps1) runs before the flags, so it sets your defaults. The flags win.
# ~/.config/emerger/config.sh
ARG_DEV=1 # as --dev on every run
ARG_EXCEPT="snap" # as --except snap
DISK_MIN_FREE_MB=2048 # ask before updating with less free space
QUIET_HOURS="23:00-07:00" # a run with -y inside this window does nothing# %APPDATA%\emerger\config.ps1
$script:ArgsGlobal.Dev = $true
$script:MANAGER_TIMEOUT = 3600Everything you can customize lives in ~/.config/emerger/ (Windows: %APPDATA%\emerger\, with .ps1 files):
| put this | in | and you get |
|---|---|---|
| your fixed settings | config.sh |
defaults for every run, such as "always skip snap" |
| a named set of settings | profiles.d/NAME.sh |
up --profile NAME applies it; work, home, server and safe ship ready to use |
| your own scripts | hooks/pre.d/, hooks/post.d/ |
they run before or after the update, in name order (a backup first, a notification after) |
a package manager up does not know |
managers.d/NAME.sh (Unix) |
up updates it like the others; share/plugins/example.sh is a template |
| packages to leave alone | ignore.list (Linux) |
pacman never upgrades them |
up loads a config file, profile, hook or plugin only when you own it and no other user can write to it.
Every variable, its default and the plugin API: the documentation, section Configuration.
| file | Linux and macOS | Windows |
|---|---|---|
| config | ~/.config/emerger/config.sh |
%APPDATA%\emerger\config.ps1 |
| profiles | ~/.config/emerger/profiles.d/, shipped share/profiles/ |
%APPDATA%\emerger\profiles.d\, shipped share\profiles\ |
| hooks | ~/.config/emerger/hooks/pre.d/, hooks/post.d/ |
%APPDATA%\emerger\hooks\pre.d\, hooks\post.d\ |
| plugins | ~/.config/emerger/managers.d/ |
none |
| ignore list | ~/.config/emerger/ignore.list |
none |
| detection cache | ~/.cache/emerger/detected |
none |
| log | ~/.local/state/emerger/emerger.log |
%LOCALAPPDATA%\emerger\state\emerger.log |
| run history | ~/.local/state/emerger/history.jsonl |
%LOCALAPPDATA%\emerger\state\history.jsonl |
| package lists | ~/.local/state/emerger/pkgs.before, pkgs.after, pkgs.diff |
none |
| resume cursor | ~/.local/state/emerger/resume |
none |
| run lock | ~/.local/state/emerger/emerger.lock |
%LOCALAPPDATA%\emerger\state\run.lock, elevated.lock |
| parallel output | ~/.local/state/emerger/parallel-*.log |
none |
XDG_CONFIG_HOME, XDG_CACHE_HOME and XDG_STATE_HOME move the Unix directories.
| code | meaning |
|---|---|
| 0 | success |
| 1 | runtime failure (sudo, lock, disk, interrupted), or aborted (a declined safety prompt, no snapshot taken with --snapshot) |
| 2 | bad argument |
| 3 | one or more managers failed |
| 4 | reboot pending, only with --reboot-exit |
upchanges only what you ask for. Cleaning the cache, the Trash and--deep-cleanask before deleting anything.- On its own,
upgoes online only for--weather,--self-update,--firmware,--refresh-mirrorsand one connectivity check in--doctor. All other traffic comes from your package managers. upruns withsudo, so keep the eMerger folder writable by you alone. If other users can write to it,uprefuses to start.- Your config, profiles, plugins and hooks follow the same rule:
upskips any that another user could change.
- Update: run
up --self-update. It never overwrites your own changes. - Remove: run
./uninstall.sh(Windows:.\uninstall.ps1). It removes everything the install script added, then asks whether to delete your settings, history and cache too (no by default). Then delete the eMerger folder.
"Another eMerger run is in progress": another up is still running. Wait for it to finish. Do not delete the lock file.
A manager failed (exit code 3): run up --errors to see why, and up --doctor to check your system. Usually the manager needs a repair first (for apt: sudo dpkg --configure -a), then run up again.
It stops at "User cache" or "Trash": it is asking yes or no. After 60 seconds it answers no. Use -y to answer yes.
Emoji show up as boxes: install a color-emoji font, or run up --ascii.
macOS says "cannot read the Trash": give your terminal Full Disk Access in System Settings, Privacy & Security.
Windows does not recognize up: open a new PowerShell window.
Windows says "running scripts is disabled": run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned.
More answers are in the documentation, section Troubleshooting.
- Tests:
bats tests/. Some tests needpwsh,zsh,fishorshellcheck, and are skipped when the tool is missing. - Lint:
shopt -s globstar; shellcheck -S error install.sh uninstall.sh src/emerger.sh src/lib/**/*.sh share/plugins/*.sh share/profiles/*.sh completions/up.bash(the same check CI runs). - Documentation: edit doc/documentation.tex, then run
pdflatex documentation.textwice insidedoc/(the second run fills in the table of contents and the section references). - Code:
src/emerger.shand src/lib/ for Linux and macOS,src/emerger.ps1and src/pslib/ for Windows. Both halves must behave the same. - Adding a package manager: see the documentation, section Development.
- Third-party material: reference/third-party.md.
- Contributing: CONTRIBUTING.md.
MIT, see LICENSE.
