The letter A styled as Alchemists logo. lchemists
Published February 1, 2021 Updated October 13, 2025
Cover
Machine Upkeep

In the book The 7 Habits of Highly Effective People, Stephen Covey writes about Sharpening the Saw which emphasizes keeping your skills sharp but can be applied to your tools as well. I’ll show you, with a little macOS automation, how you and adapt and keep your machine up-to-date in your own workflow.

Frequency

As a rule of thumb, performing machine maintenance on a two-day basis with a weekly fallback, if otherwise, is a good practice. Sometimes, depending community activity, I’ll update my machine daily to pick up changes based on news in my feed reader.

Your mileage may vary so figure out what works best for you and stick with it!

Shell Script

If you’re like me, any kind of manual maintenance will make your hair stand on end. Automation is key to making machine maintenance frictionless as possible. In my case, I’ve automated the full process via a single Bash function: eup. The function name is a mnemonic shorthand for: [e]nvironment + [up]date = eup. Here’s the Bash source code:

# Label: Environment Update
# Description: Update environment with latest software.
eup() {
  softwareupdate --all --install --agree-to-license
  xcode-select --install
  hbsu
  rustup update
  cargo install-update --all
  tldr --update
  docker system prune --force
  docker buildx prune --force
  gpua
  gvaca
  gemuc
  bca
  bua
  noti --title "Environment Update"
}

The above messages several aliases and functions. To demystify, I’ll walk you through each line of the script.

macOS

The first couple of lines ensure macOS and Xcode are up-to-date.

Homebrew

The next line messages the hbsu Homebrew alias. Here’s the source code:

# [h]ome[b]rew + [s]oftware + [u]date = hbsu
alias hbsu="brew update && brew upgrade && brew cleanup"

This alias:

  1. Updates Homebrew by pulling down recent updates to formulas and casks.

  2. Upgrades all formulas and casks to their latest versions.

  3. Deletes old formulas and casks so you only have the latest versions on your system in order to reduce disk space consumed.

When using Homebrew, there are several environment variables you’ll want to configure in order to optimize your Homebrew experience. I recommend adding the following to your .bashrc file:

# Ensure Homebrew in your path.
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"

# Enable Bat colorization.
export HOMEBREW_BAT=1

# Retry the connection three times before giving up.
export HOMEBREW_CURL_RETRIES=3

# Default to using Homebrew managed `curl`.
export HOMEBREW_FORCE_BREWED_CURL=1

# Default to using Homebrew managed `git`.
export HOMEBREW_FORCE_BREWED_GIT=1

# Disable analytics tracking.
export HOMEBREW_NO_ANALYTICS=1

# Disable auto-update so you can control manually.
export HOMEBREW_NO_AUTO_UPDATE=1

# Disable any kind of insecure redirect.
export HOMEBREW_NO_INSECURE_REDIRECT=1

# Disable auto-cleanup so you can control manually.
export HOMEBREW_NO_INSTALL_CLEANUP=1

# Enhance alias/function performance by defining your own prefix.
export HOMEBREW_PREFIX="$(brew --prefix)"

💡 Bat is a super charged cat with color coding, syntax highlighting, and much more. Highly recommend, if not using already.

Rust

The next couple of lines message the rustup Rust command for ensuring you’re running the latest version of Rust. This includes use of the install-update crate for keeping all globally installed crates up-to-date and the tldr crate for keeping documentation up-to-date.

Docker

The next couple of lines use the docker Docker command to ensure all unused images are forcefully pruned. Docker images (and cross platform images) can consume a large portion disk space so always good to keep this under control.

Git

The next couple of lines are devoted to Git repository maintenance. The first, gpua, is short for Git Pull All to ensure all projects are up-to-date with the remote repository. The second, gvaca, is for cleaning the repository. Here’s the source code:

# Label: Git Verify and Clean (all)
# Description: Verify and clean objects for projects in current directory.
gvaca() {
  while read -r project; do
    (
      cd "$project"

      if [[ -d ".git" ]]; then
        printf "\n33[36m${project}33[m:\n" # Outputs in cyan color.
        git fsck && git repack -Ad && git maintenance run --task=gc && git rerere gc
      fi
    )
  done < <(ls -A1)
}

The above walks through each open source project as follows:

  1. fsck - Verifies the connectivity and validity of all repository objects so I’ll know immediately if anything is corrupt.

  2. repack - Packs unpacked objects into a single pack and removes redundant packs.

  3. maintenance - Handles garbage collection by removing unnecessary repository files and optimizing the repository for improved performance. It does all of this by respecting the object database lock as described further in the Git Maintenance article.

  4. rerere - Prunes old records of conflicted merges no longer necessary. If you’ve read my Git Rebase article you’ll know why rerere is so valuable.

RubyGems

The next line messages the gemuc RubyGems alias. Here’s the source code:

# [g]em + [u]pdate + [c]lean = gemuc
gem update --system && gem update && gem cleanup

Much like the Homebrew alias, this performs the following for all RubyGems on your system:

  1. Updates RubyGems to the latest version for the entire system.

  2. Updates all gems for the current version of Ruby you are using.

  3. Deletes older versions of gems recently updated in order to reduce disk space consumed.

Bundler

The next couple focus on Bundler. The first function called is: bca. Here’s the source code:

# Label: Bundle Clean (all)
# Description: Clean projects of gem artifacts (i.e. pkg folder).
bca() {
  while read -r project; do
    (
      cd "$project"
      if [[ -f "Gemfile.lock" ]]; then
        printf "33[36m${project}33[m: " # Outputs project in cyan color.

        # Print status if found, otherwise a checkmark for passing status.
        if [[ -d "pkg" ]]; then
          rm -rf pkg
          printf "%s\n" "Cleaned gem artifacts."
        else
          printf "✓\n"
        fi
      fi
    )
  done < <(ls -A1)
}

The above function cleans up all disk space consumed from publishing new gem versions of my open source work. Take, for instance, the Git Lint project. Every time I publish a new version of Git Lint, I’ll end up with the following artifact:

git-lint/pkg/git-lint-x.x.x.gem

Once published, you don’t need to keep this binary around so is safe to delete. When managing multiple projects, you can end up with a lot of artifacts over time and this is a nice way to reduce the number of packages on your system.

The second function is bua and here’s the source code:

# Label: Bundle Update (all)
# Description: Update gems for projects in current directory.
bua() {
  while read -r project; do
    (
      cd "$project"
      if [[ -f "Gemfile.lock" ]]; then
        rm -f Gemfile.lock
        bundle install --quiet

        # Print project status if Bundler activity is detected, otherwise a checkmark for passing status.
        printf "33[36m${project}33[m: " # Outputs project in cyan color.
        if [[ $(git diff | wc -l | tr -d ' ') -gt 0 ]]; then
          printf "↑\n"
        else
          printf "✓\n"
        fi
      fi
    )
  done < <(ls -A1)
}

Much like the bca function, this ensures all open source projects are updated to the latest gem dependencies. It’s one of the fastest ways to ensure all of your open source work is up to date and works as an early warning sign to know if there are breaking changes that need addressing.

Noti

The last line uses Noti so you get a notification when the script is done.

Conclusion

Being proactive, instead of reactive about, your machine maintenance allows you to be the first to know of breaking changes, course correct, and quickly update as needed. Lack of maintenance gets costly quickly so avoid this burden by tackling the cost in small increments as they pop up. Make it a habit and you’ll never have to spend weeks or, worse, months digging yourself out the hole you’ve built due to neglect.