freshen
Brew/mas helper; live TTY board.
rig/home/dot_zsh/functions/freshen → ~/.zsh/functions/ (Chezmoi). Autoload plus aliases fr / frn / frc / frs (see Shell).
Bare freshen is -Y -P --dev-prune-root=$HOME/dev -v -D -R=auto (live dashboard on a TTY, no confirm). It inventories outdated Homebrew formulae, casks, and Mac App Store apps, then applies upgrades, optional stale-dev prune under ~/dev, and brew doctor. It can clean caches, print a classified storage plan, and run brew doctor. It is a TTY operator, not a web UI.
Commands
fr # same as bare freshen (live apply defaults)
frn # dry-run, plain, no color
freshen -N --progress=plain --no-color
freshen # apply; live board on a TTY
frc # clean-only, plain; still confirms unless -Y
frs # storage-plan
freshen --yes --progress=plain --no-color # automation
freshen --replace # take over a stuck lock
just check-freshen| Mode | |
|---|---|
bare freshen / fr | --yes, --dev-prune under $HOME/dev, verbose, doctor, --progress=auto |
| default with flags | inventory → confirm (unless -Y) → upgrade → residual retry → cleanup/caches |
-N / --dry-run | plan only |
-C / --clean-only | cleanup / caches / optional dev-prune / doctor |
-S / --storage-plan | classified report only |
| docker/gem prune | opt-in only |
Default cask inventory still uses --greedy. Apps whose live version is already newer than Homebrew’s tap version are skipped so a greedy reinstall cannot downgrade them. Equal versions still upgrade.
Progress
| Mode | When |
|---|---|
auto (default) | Live dashboard on a TTY; lines otherwise |
live | Same as auto. FRESHEN_FORCE_LIVE=1 is test-only and requires FRESHEN_UNDER_TEST |
lines | Append-only phase lines, color when allowed |
plain | Append-only, no color, no cursor controls — logs and screen readers |
Live draws on the terminal alt-screen as a dashboard: a PHASES rail plus a NOW pane. NOW includes an OVERALL discovery graph (inventory fans out into per-package formula/cask/app nodes, then cleanup → caches → doctor), a short package list, and the last brew child lines (Downloading / Pouring / Installing). The frame sizes from the real TTY (stty on /dev/tty), not a stale $COLUMNS=80. Identical frames are skipped so the board does not blink.
Sudo preflight and the confirm prompt pause that board so the password/[Y/n/q] line is not wiped. Recap reuses the same rounded box. FRESHEN_LOW_POWER=1 forces plain and skips the bell/notification. --progress=plain --no-color never emits ANSI cursor, color, bells, or animation — including the apply path.
A degraded apply run prints Attention and Next actions first, then the phase Summary. Dry-run has no Attention block. Status words (attempted / confirmed / unresolved / degraded / failed / done / cleaned) are part of the contract — do not restyle them.
A second freshen lists the lock holder and offers to replace it (y / --replace). It interrupts the in-shell run and takes the lock; it does not SIGKILL a login zsh.
Safety
--dry-runnever upgrades, cleans, prunes, or updates apps.- Non-interactive mutations require
--yes(barefreshenimplies--yes). - Cask upgrades preflight
sudoonce so the password prompt does not land inside the dashboard. --dev-pruneusesgomionly (normfallback), skips caches newer than 14 days (FRESHEN_DEV_PRUNE_MIN_AGE_DAYS,0disables), and skips the live workspace.--storage-planlabels surfacescache-prune/review/report-only. Unique models, app libraries, Kopia, and Docker volumes that exist are do-not-touch. It may probedocker system df,nix store gc --dry-run, andkopia repository status(no password on argv). It does not prune, invokemo, or run files-buddy.
Automation
freshen --yes --progress=plain --no-color| Exit | Meaning |
|---|---|
| 0 | Enabled work completed or was intentionally skipped |
| 1 | Degraded or failed work — read Attention |
| 2 | Usage error |
| 127 | Required dependency missing |
| 130 | Interrupted |
Logs: $FRESHEN_STATE_DIR/freshen → $XDG_STATE_HOME/freshen → ~/Library/Logs/freshen → ~/.local/state/freshen. Filenames: <timestamp>.<pid>.log. Credential-shaped output is redacted. Do not commit raw logs or live inventories.
Full flags and FRESHEN_* knobs: freshen --help. Tests: rig/home/dot_zsh/functions/tests/.