Published 2023-06-06.
    Last modified 2025-06-15.
            
Time to read: 5 minutes.
 
ruby collection.
Prior to first writing this article, I had written a command-line program (CLI) in Ruby. It was straightforward to write and worked well.
However, if I had used a special-purpose library for building CLIs, over the lifetime of my CLI program, the accumulated time spent on maintenance might have been much less. This could only be realized if the mythical CLI library:
- Was well-designed.
 - Had the necessary features.
 - Continued to be well maintained.
 - Had good documentation.
 
Unfortunately, open-source software rarely fits this description.
Writing Yet Another CLI
  A short time later, I wanted to write another CLI, which I called nugem.
  This new program needed to generate source code (scaffolding) for various types of Ruby gems.
  Unlike my previous CLI project, this one had the following criteria:
- The source code needed to be easy to understand.
 - The overall program needed to be flexible in how it could be used.
 - The resulting software needed to be easy to maintain.
 - Development and deployment needed to rely on stable technology.
 
  I found an old Ruby and Rails gem generator, creategem,
  written by Igor Jancev.
  Although the project had not been updated in seven years, it was well written.
  I decided to update the project and extend it for my own use.
  The project used the Thor gem.
  I could have used dry-cli or
  mercenary
  instead of Thor.
  The only way to gain experience with a library is to use it,
  and Thor seemed like it might be worth learning about.
  Nugem was first implemented using Thor.
  However, the experience of using Thor for a non-trivial task taught me that this library is unsuitable for general usage.
  Later, I converted nugem to use OptionParser,
  ERB and
  highline
  instead of Thor.
The Mighty Thor
Written by the Ruby on Rails programmers, Thor is an open-source toolkit for building command-line programs.
This software is a classic example of programmers scratching their own itch. These programmers are not motivated at all to help others learn how to use Thor. If you want to understand how to best use it, you should expect to spend time reading the source code for Thor.
  Despite the huge number of GitHub projects that are based on Thor,
  very few of them were written by humans.
  Instead, Ruby on Rails has used thor since Rails v3 for code generation.
  For example, commands like rails new, rails console, rails server,
  and rails routes are implemented with thor.
The above is not the full story.
Thor::Actions are helpers for your Thor tasks that make typical actions, like file system interaction or
  command-line user dialogue, easier.
  The Actions
  whose sole purpose is to interact with a user are:
  ask, indent,
  mute, mute?, no,
  print_in_columns, print_table, print_wrapped,
  say, say_error, set_color,
  terminal_width, and
  yes?.
My Evaluation
Thor is:
- Well designed
 - Well maintained
 - Useful and powerful
 - 
    Has no change log, and some features have changed a lot over the years.
    For example, the old 
optionstatement was renamed some years ago tomethod_option, but the oldoptionsvariable was not renamed. I have not found any mention of that in the documentation, and it makes looking at old code confusing. - Put to shame with out-of-date and dramatically incomplete user-oriented documentation.
 - 
    Has decent comments in the source code for 
Actionsand other portions of the code base. This means the RubyDoc for Thor is useful if you have time and the ability to put it all together in your mind. The RubyDoc does not provide any examples of how to use the API. - The RubyDoc is not a substitute for user-oriented documentation, and is severely lacking in accessible examples. If you have access to a working program, the task of learning the API becomes much easier.
 
I Wrote Some Docs
Thor CLI
  A command called thor was installed when the thor gem installed.
$ which thor /home/mslinn/.rbenv/shims/thor
$ thor help Commands: thor help [COMMAND] # Describe available commands or one specific command thor install NAME # Install an optionally named Thor file into your system commands thor installed # List the installed Thor modules and commands thor list [SEARCH] # List the available thor commands (--substring means .*SEARCH) thor uninstall NAME # Uninstall a named Thor module thor update NAME # Update a Thor file from its original location thor version # Show Thor version
  Unfortunately, the help message does not state what the thor command is for.
  Google brought me to the
  thor man page,
  which was weird because no such man page got installed on my Ubuntu system when I installed the thor gem,
  and apt does not have such a package available from the default Ubuntu 23.04 PPAs.
The man page says:
Thor is a scripting framework designed for command line utilities. It is supposed to be a replacement for
rake, sake and rubigen.
  Really?
  Thor is supposed to be a replacement for
  rake?
  I never would have known that from any other source.
  If this were true, I would expect at least some documentation on how to use Thor to replace rake.
  I call bullshit.
  BTW, rubigen
  is a defunct GitHub project that vanished without a trace.
  Sake was never anything to speak of.
  The above is a poor excuse for documentation.
  Boo!
  No one needs the thor command-line utility for any purpose,
  unless they want an example of how to use thor.
  If that is something you want, the command’s source is provided in
  lib/thor/runner.rb.
  Just keep in mind that this program contains a lot of use-case-specific code that probably does not match
  your needs, and their use case is not expressed anywhere.
  I humbly suggest that the initial release of nugem
  is a much better example to learn from.
  Nonetheless, thor is an interesting program,
  even if its creators are woefully misguided in the documentation department.
ERB Syntax
Other than the comments in the source code, accessible via RubyDoc, I have not found any user-accessible documentation on Thor templates.
However, I realized that templates use ERB syntax after I saw error messages from erb. Since Thor has no dependencies and ERB is built-in to Ruby, ERB syntax was apparently implemented.
Lineage
  The comment
  “This implementation is based in Templater actions”,
  found in the Actions module source code,
  suggests that this portion of the Thor source code was modified from the templater source code
  since Thor does not have the templater gem as a dependency.
  The templater RubyDoc
  seems to fit what I have noticed so far about Thor’s template capability.
  This does not qualify as proper documentation for thor,
  but it should help guide future detective work.
Actions
  Thor Actions
  can:
- Define Thor runtime options
 - Define paths for template sources
 - Transform template directory contents recursively.
 
  The code I inherited from Igor Jancev used the
  directory
  and template actions.
Undocumented Run Options
  The run command is
  documented
  as having options :verbose, :capture and :with.
  Examining the
  source for run,
  we see the following undocumented, yet very useful, additional options:
  :abort_on_failure, :capture, and :pretend.
  Some commands, like git-commit, do not return zero return codes on a successful invocation.
  To make them work without prematurely ending the Thor program, write:
run "git commit -aqm 'Initial commit'", abort_on_failure: false
A Few Useful Pointers
The following code shows a few handy techniques that you might find helpful:
- Exit with a non-zero return code on failure.
 - Display additional information in help messages.
 
require 'English'
require 'thor'
require_relative 'bogus_cli/version'
module BogusCli
  class CLI < Thor
    include Thor::Actions
    package_name 'BogusCli'
    # Return a non-zero status code on error. See https://github.com/rails/thor/issues/244
    def self.exit_on_failure?
      true
    end
    desc('build [FILE_NAME]', 'build the future')
    method_option :output, type: :string, required: false, desc: 'output file', aliases: '-o'
    def build(file_name)
      # Implementation does not matter for this example
    end
    # Display help with additional context
    def help(command = nil, subcommand: false)
      say <<~END_HELP
        This could be a detailed overview of the CLI...
      END_HELP
      super command, subcommand
    end
  end
end
Conclusion
  After using Thor to write a few CLIs, I find it awkward to programm with,
  and the generated code has an awkward syntax to invoke user help.
  I find that OptionParser
  is a much better choice for writing CLIs.
Thor was never meant to be a general-purpose CLI library. It was quickly hacked together by the Ruby on Rails team to generate scaffolding for Rails applications, and is unsupported for general users. Thor is not a good choice for general-purpose CLI programs.
  I am currently rewriting nugem to use OptionParser.
References
- 
    
ThorGitHub project - What is Thor? – does not mention templates
 - Thor Wiki
 - Thor RubyDoc
 - Embedded Ruby (ERB) template syntax
 - Tips for writing Rails tasks with Thor instead of Rake
 - Gem templates with Thor by Benjamin Fleischer
 - Making a command line utility with gems and thor by Will Schenk
 - Using Thor and Ruby to build a CLI by Derik Ramirez
 - 
    Supercharge Your Ruby CLI with Thor by Ian Hollander.
NB:optionwas renamed tomethod_option. - Introduction to Thor by Dhaivat Pandya
 - Testing Thor Ruby Required Options by Stefanni Brasil