Shell scripts for xbar can be written in any language, including Ruby! But I found that getting these scripts to run using a modern Ruby stack was a little tricky. Here’s what I figured out.
Xbar runs as a background service that does not have access to the user’s interactive shell environment. That means that a Ruby script will run using the system-provided Ruby by default. I don’t want to use the system Ruby on macOS, because it is extremely old (Ruby 2.6, as of macOS Ventura in March 2023), and has reached end-of-life status.
To make Ruby shell scripts use an rbenv-managed Ruby instead, I’m now using this shebang header:
When I first discovered xbar, I immediately thought of building scripts that would leverage external APIs (one of my first ideas was to display an air quality indicator using data from the airnow.gov API). To make those scripts easier to write, I would need to use some gems. Depending on the situation, I’ve learned there are a couple different ways to manage gems with Bundler in a shell script.
Bundler can be embedded directly into a shell script using
bundler/inline. Whenever the script is run, Bundler will download and install the specified gems automatically, as needed.
In the scenario where multiple shell scripts use the same gem dependencies, an alternative is to place a separate
Gemfile in the same directory as the scripts and reference it within each script like so:
bundle install needs to be run manually to ensure the gems are downloaded and installed prior to running the script.
xbar is a plugin system for custom menubar items on macOS. Given a shell script (which can be written in any language), xbar will execute the script at regular intervals and turn the script’s stdout into a dynamic menubar item.