Aha! Develop is for healthy agile development teams — connect to the roadmap, optimize workload, and streamline reporting.


Learn more
2023-08-10

CLI tools at Aha!

Take your command-line utilities to the next level with these Ruby gems

Ruby has always been a great general-purpose scripting language and is often used to create command-line utilities. Many of these use the excellent Thor gem to parse command-line options, but there's no escaping one fact: command-line utilities just aren't interesting. Never have been, never will be.

However, since Ruby was released in 1995, developers have created some clever and useful libraries for making command-line utilities simpler to use, look at, and code.

I love creating command-line utilities

I am part of the Aha! platform team. Our primary focus is ensuring system reliability, but we are also responsible for providing developer tooling for the rest of the engineering team. One of our main tools is the ops command-line utility that performs many mundane yet important tasks to simplify processes for our engineers. Here are a few examples:

  • ops ecs deploy deploys an application to an AWS ECS environment
  • ops ecs ssh launches a shell on an existing application container
  • ops ecs shell spins up a new application container and launches a shell there

As we make updates to our ops and similar CLI utilities, we often improve the user experience by taking advantage of various Ruby gems. With little effort compared to low-level coding with curses, our command-line utilities that used to be cryptic and confusing are now interactive, easy to use, and — dare I say — elegant.

Let's talk about a few of these "gems." 😆

1. cli-ui

I really enjoy using the cli-ui gem. It offers a lot of powerful, intuitive features including:

  • spinners: provide feedback that something is happening (e.g., track the progress of multi-threaded operations)
  • frames: clearly demarcate logical groups of output including the ability to nest frames within each other
  • prompts: provide a powerful UI for displaying and selecting a list of choices
  • text formatting: provides several helpers to make text formatting quick and easy

When we deploy code at Aha! we kick off a number of AWS CodeDeploy tasks running in parallel. Here's some code to simulate deployment:

require 'cli/ui'

def deploy(build)
  CLI::UI::StdoutRouter.enable
  CLI::UI::Frame.open("Deploying Aha! build #{build}", color: :blue) do
    CLI::UI::SpinGroup.new do |spin_group|
      spin_group.add("pod1") { sleep 2 }
      spin_group.add("pod2") { sleep 3 }
      spin_group.add("pod3") { sleep 1 }
    end
  end
  puts ;
rescue StandardError => e
  puts CLI::UI.fmt "{{red:Deploy failed: #{e.message}}}"
end

deploy "123"

This produces the following output:

deploy-spinners

Obviously, our deploys aren't quite this fast or simple. But you can imagine how useful it would be to see output with feedback like this when you have dozens of long-running threads executing in parallel, like our real deploys.

2. terminal-table

I used to write a lot of custom code to format tabular data in my CLI utilities. Thankfully, that stopped once I discovered terminal-table.

This gem is very easy to use and can process arrays as well as CSV data. Here's a quick example showing how simple it is to create nicely-formatted tabular data:

require 'terminal-table'

table = Terminal::Table.new do |t|
  t.title = "Shipment Summary"
  t.style = { border: :unicode_round }
  t.headings = ["Product", "Quantity", "Unit Price"]
  t.rows = [
    ["Apples", 500, "$1.99"],
    ["Milk 2% 4l", 100, "$4.99"],
    ["Rye Bread", 25, "$3.99"],
  ]
  t.align_column(1, :right)
  t.align_column(2, :right)
end
puts table

The output is simple yet quite aesthetically pleasing:

terminal table

Not too shabby!

3. ombre

Finally, here is a nice little gem created by Aha! director of software engineering, Justin Paulson. Ombre provides a fun way to spice up your output by rendering text with a gradient. Here's an example that prints zombie ipsum with a red, white, and blue tint:

require 'ombre'

puts Ombre.horizontal(<<TEXT, ["FF0000", "FFFFFF", "0000FF"])
**********************************************
* Zombie ipsum brains reversus ab cerebellum *
* viral inferno, brein nam rick mend grimes  *
* malum cerveau cerebro. De carne cerebro    *
* lumbering animata cervello corpora         *
* quaeritis. Summus thalamus brains sit,     *
* morbo basal ganglia vel maleficia?         *
**********************************************
TEXT

This produces a colorful output:

Ombre example

We use Ombre to display a banner when we launch CLI tools that help us create pull requests:

ombre aha

While this banner doesn't add any measurable value to our utility, it helps reinforce a sense of team spirit every time it's displayed.

Be sure to add these new gems to your Ruby command-line arsenal. They have great documentation — and are fun to use — adding a little panache to your command-line utilities.

Steve Lamotte

Steve Lamotte

Steve is an engineering lead at Aha! — the world’s #1 product development software. Working on the platform team, Steve enjoys infrastructure work and helping his teammates stay productive and happy in their roles.

Follow Aha!

Follow Steve