Smol is a lightweight framework for building command-line applications in Ruby. It handles both single-command execution and interactive shell modes. No dependencies beyond the standard library.
Why it exists
Building CLI tools in Ruby usually goes one of two ways. Either you reach for Thor or Optparse and end up with a lot of boilerplate for simple things, or you roll your own and spend more time on argument parsing than actual functionality.
Or, like me, you just build your own.
I wanted something smaller. Define commands with a DSL, get a REPL for free, add health checks without ceremony. The framework should stay out of the way until you need it.
How it works
An App holds commands, configuration, and mounted sub-apps. Commands are classes that define a single action with arguments and options. Checks are simple pass/fail health checks you can run from the CLI or REPL.
Commands auto-register to their parent app by walking the Ruby module hierarchy. No manual wiring required unless you want it.
Dual-mode execution
Every Smol app can run two ways:
# Single command
myapp deploy --env=production
# Interactive shell
myapp
> deploy --env=production
> help
> exit
The REPL includes readline support, command history saved across sessions, and tab completion. Both modes can be enabled or disabled independently.
Auto-registration
This is the part I’m most pleased with. Define a command inside your app’s namespace and it just works:
class MyApp::Commands::Deploy < Smol::Command
desc "Deploy the application"
option :env, type: :string, default: "staging"
def run
output.success "Deploying to #{options[:env]}"
end
end
Smol finds the parent app by examining class names. No register calls, no inheritance chains to trace. You can still wire things manually if you prefer explicit over magic.
Health checks
Same pattern as commands:
class MyApp::Checks::Database < Smol::Check
title "Database connection"
def run
ActiveRecord::Base.connection.execute("SELECT 1")
pass "Connected"
rescue => e
fail "Cannot connect: #{e.message}"
end
end
Run myapp check to see them all. Useful for deploy verification or debugging production issues.
Configuration
Settings defined once, read from environment variables automatically:
class MyApp < Smol::App
setting :api_key, type: :string
setting :timeout, type: :integer, default: 30
setting :verbose, type: :boolean, default: false
end
API_KEY in your environment becomes config.api_key in your code. The REPL has a built-in config command to inspect current values.
Sub-apps
Mount apps inside other apps for nested command structures:
class AdminApp < Smol::App
banner "Admin commands"
end
class MyApp < Smol::App
mount AdminApp, as: :admin
end
In the REPL, type admin to enter the sub-app’s context. Or run myapp admin:users:list directly from the shell.
The output helpers
Colored output, tables, and interactive prompts are included but not required.