A lightweight, powerful CLI framework for Ruby. Define commands using class inheritance or block DSL — both produce the same command tree.
An alternative to other similar utilities with a cleaner, more Ruby-native design.
Ruby 3.1+
gem "athena"require "athena"
class MyCLI < Athena::Tool
tool_name :mycli
version "1.0.0"
description "My awesome CLI tool"
command :greet do
description "Say hello"
option :name, String, short: :n, default: "world"
run { puts "Hello #{options[:name]}!" }
end
end
MyCLI.start(ARGV)$ mycli greet -n 'Johnny Appleseed'
Hello Johnny Appleseed!
$ mycli --help
My awesome CLI tool
Version: 1.0.0
Usage: mycli [options] [subcommand]
Subcommands:
greet Say hello
$ mycli greet --help
Say hello
Usage: greet [options]
Options:
-n, --name=VALUE (default: world)
Athena supports two equivalent styles for defining commands. Both produce the same underlying Command subclass.
Best for quick, self-contained commands:
class MyCLI < Athena::Tool
tool_name :mycli
version "1.0.0"
command :deploy do
description "Deploy the application"
option :env, String, short: :e, default: "staging"
flag :force, short: :f, description: "Skip confirmation"
run do |*targets|
puts "Deploying #{targets.join(', ')} to #{options[:env]}"
puts "Force mode!" if options[:force]
end
end
endBest for complex commands that need helper methods, mixins, or testing in isolation.
Defining a Tool automatically creates a MyCLI::Command base class for your commands to inherit from:
class Deploy < MyCLI::Command
self.command_name = :deploy
description "Deploy the application"
option :env, String, short: :e, default: "staging"
flag :force, short: :f, description: "Skip confirmation"
def run(*targets)
puts "Deploying #{targets.join(', ')} to #{options[:env]}"
puts "Force mode!" if options[:force]
end
private
def confirm?
return true if options[:force]
# ...
end
endBoth styles support nesting to arbitrary depth:
class MyCLI < Athena::Tool
tool_name :mycli
version "1.0.0"
command :server do
description "Server management"
command :start do
description "Start the server"
option :port, String, short: :p, default: "3000"
run { puts "Starting on port #{options[:port]}" }
end
command :stop do
description "Stop the server"
run { puts "Stopping server" }
end
end
end$ mycli server start -p 8080
Starting on port 8080
# Typed option (requires a value)
option :env, String, short: :e, description: "Target environment", default: "staging"
# Boolean flag (no value, defaults to false)
flag :verbose, short: :v, description: "Enable verbose output"
# Positional argument
argument :target, description: "Deploy target"Options are accessed via the options hash:
run do |*args|
puts options[:env] # => "staging"
puts options[:verbose] # => false
endFor larger CLIs, organize commands in separate files:
class MyCLI < Athena::Tool
tool_name :mycli
version "1.0.0"
load_commands(File.expand_path("commands/**/*.rb", __dir__))
endEach file defines a Command subclass that auto-registers via Ruby's inherited hook:
# commands/deploy.rb
class Deploy < MyCLI::Command
self.command_name = :deploy
description "Deploy the application"
def run(*targets)
# ...
end
endFor shared behavior across all commands, provide your own base class:
class MyBaseCommand < Athena::Command
self.abstract_class = true
flag :verbose, short: :v, description: "Verbose output"
def log(msg)
puts msg if options[:verbose]
end
end
class MyCLI < Athena::Tool
tool_name :mycli
version "1.0.0"
command_class MyBaseCommand
end
class Deploy < MyBaseCommand
self.command_name = :deploy
description "Deploy the application"
def run(*targets)
log "Deploying #{targets.join(', ')}"
end
endGroup related commands with shared options:
class DatabaseCommand < MyCLI::Command
self.abstract_class = true
option :database, String, short: :d, default: "primary"
end
class Migrate < DatabaseCommand
self.command_name = :migrate
description "Run migrations"
def run
puts "Migrating #{options[:database]}"
end
endAfter checking out the repo, run bundle to install dependencies. Then, run bundle exec rspec to run the tests.
Bug reports and pull requests are welcome on GitHub at https://github.com/TwilightCoders/athena. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.