CLI tools at Aha!
Tags: cli, devops, ruby
Published: 2023-08-14 16:55:19

---
title: CLI tools at Aha!
published: true
description: We like to make our CLI apps as visually pleasing as possible at Aha!; here are some of the Rubygems that help make that possible.
tags:
  - cli
  - devops
  - ruby
---
## 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](https://github.com/rails/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!](https://www.aha.io/) 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](https://github.com/ruby/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](https://github.com/Shopify/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](https://aws.amazon.com/codedeploy/) tasks running in parallel. Here's some code to simulate deployment:

```ruby
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](https://www.aha.io/baf52e98af2c4903879f13f75de87fd8/deploy-spinners.gif)

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](https://github.com/tj/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:

```ruby
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](https://www.aha.io/dee07efcb63f8df006cae598f2b31c38/terminal-table.png)

Not too shabby!

## 3. `ombre`

Finally, here is a nice little gem created by Aha! director of software engineering, [Justin Paulson](https://www.aha.io/blog/my-name-is-justin-paulson-this-is-why-i-joined-aha). [Ombre](https://github.com/justinpaulson/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:

```ruby
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](https://www.aha.io/1f28a93256a33f9b3f0bed64331a19eb/ombre-example.png)

We use Ombre to display a banner when we launch CLI tools that help us create [pull requests](https://www.aha.io/engineering/articles/12-tools-for-quality-pull-requests):

![ombre aha](https://www.aha.io/09b8000c1f6092c2384047a4ff8ff246/ombre-aha.png)

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.