dotfiles

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 flagsinventory → confirm (unless -Y) → upgrade → residual retry → cleanup/caches
-N / --dry-runplan only
-C / --clean-onlycleanup / caches / optional dev-prune / doctor
-S / --storage-planclassified report only
docker/gem pruneopt-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

ModeWhen
auto (default)Live dashboard on a TTY; lines otherwise
liveSame as auto. FRESHEN_FORCE_LIVE=1 is test-only and requires FRESHEN_UNDER_TEST
linesAppend-only phase lines, color when allowed
plainAppend-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-run never upgrades, cleans, prunes, or updates apps.
  • Non-interactive mutations require --yes (bare freshen implies --yes).
  • Cask upgrades preflight sudo once so the password prompt does not land inside the dashboard.
  • --dev-prune uses gomi only (no rm fallback), skips caches newer than 14 days (FRESHEN_DEV_PRUNE_MIN_AGE_DAYS, 0 disables), and skips the live workspace.
  • --storage-plan labels surfaces cache-prune / review / report-only. Unique models, app libraries, Kopia, and Docker volumes that exist are do-not-touch. It may probe docker system df, nix store gc --dry-run, and kopia repository status (no password on argv). It does not prune, invoke mo, or run files-buddy.

Automation

freshen --yes --progress=plain --no-color
ExitMeaning
0Enabled work completed or was intentionally skipped
1Degraded or failed work — read Attention
2Usage error
127Required dependency missing
130Interrupted

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/.

On this page