Auto-updating software: Diving into oh-my-zsh

Published: October 12, 2016


Recently I’ve been working on a little side project called pngarbage. It’s a command line tool for scanning webpages and identifying image bloat. The tool is written in Go which allows me to distribute a single binary with no dependencies. I’m just in the infancy of the project and plan on (ok…hope to be) adding a bunch of new features. With that in mind, one thing I’ve been thinking about recently is auto-updating strategies.

I spent some time thinking about tools I use daily that implement auto-updating. The first one that came to mind is oh-my-zsh, one of the most starred repos on Github. If you’ve used it before you’re probably pretty familiar with this screen…

oh-my-zsh auto-update prompt

I spent a bit of time reviewing how oh-my-zsh goes about auto-updating and thought it would be worthwhile to do a short write up of my findings.

How It Works

oh-my-zsh works by source-ing ~/.oh-my-zsh/ in ~/.zshrc.

export ZSH=$HOME/.oh-my-zsh
source $ZSH/

If you look at that file you’ll see that the first thing it does is run ~/.oh-my-zsh/tools/ (unless you’ve disabled auto updating).

# Check for updates on initial load...
if [ "$DISABLE_AUTO_UPDATE" != "true" ]; then
fi checks for the presence of a file called ~/.zsh-update. If it is not there (e.g. the first time you launch a shell after installing oh-my-zsh) it executes _update_zsh_update.

if [ -f ~/.zsh-update ]
  # Code to execute if ~/.zsh-update is present
  # create the zsh file

_update_zsh_update simply writes the current date (represented as the number of days since the epoch to the ~/.zsh-update file.

function _update_zsh_update() {
  echo "LAST_EPOCH=$(_current_epoch)" >! ~/.zsh-update

If ~/.zsh-update does exist it will be sourced which will set LAST_EPOCH as an environment variable.

if [ -f ~/.zsh-update ]
  . ~/.zsh-update
  # Rest of the code to execute
  # Code to execute if ~/.zsh-update isn't present

It then gets the current epoch and checks if the difference in days between the last epoch is greater than $epoch_target.

epoch_diff=$(($(_current_epoch) - $LAST_EPOCH))
if [ $epoch_diff -gt $epoch_target ]
  # Oh boy, updating time

$epoch_target either comes from the UPDATE_ZSH_DAYS environment variable (intended to be set in ~/.zshrc) or defaults to 13.

if [[ -z "$epoch_target" ]]; then
  # Default to old behavior

If it’s time for an update the next condition it checks is whether or not it should prompt you. This is, again, done by checking an environment variable (DISABLE_UPDATE_PROMPT).

if [ "$DISABLE_UPDATE_PROMPT" = "true" ]
  # No need to prompt
  # Need to prompt

If the prompt is disabled or you answer the prompt with “Y” it goes ahead and auto-updates which ultimately executes a git pull in ~/.oh-my-zsh/tools/

$ git pull --rebase --stat origin master

It then updates ~/.zsh-update to note the latest date the update happened.

If the update prompt shows up and you dismiss it with “n” it does not execute the auto-update, but still updates ~/.zsh-update with the current date, which will defer the prompt until $epoch_target has elapsed again.

if [ "$DISABLE_UPDATE_PROMPT" = "true" ]
  echo "[Oh My Zsh] Would you like to check for updates? [Y/n]: \c"
  read line
  if [[ "$line" == Y* ]] || [[ "$line" == y* ]] || [ -z "$line" ]; then

Default Behavior

By default, oh-my-zsh behaves like this…

My Thoughts

I chose to investigate oh-my-zsh because I feel like they got auto-updating right. Here’s what I like about it…

I’m looking to implement a similar auto-update strategy for pngarbage.


If you have any comments on auto-updating, feel free to drop a note comments below. Of course, as always, you can reach me on Twitter as well.

Max Chadwick Hi, I'm Max!

I'm a software developer who mainly works in PHP, but also dabbles in Ruby and Go. Technical topics that interest me are monitoring, security and performance.

During the day I solve challenging technical problems at Something Digital where I mainly work with the Magento platform. I also blog about tech, work on open source and hunt for bugs.

If you'd like to get in touch with me the best way is on Twitter.