Skip to content

Instantly share code, notes, and snippets.

@hiendinhngoc
Last active December 15, 2025 09:24
Show Gist options
  • Select an option

  • Save hiendinhngoc/ac06b43149f81b2650a8fe16e6948c7c to your computer and use it in GitHub Desktop.

Select an option

Save hiendinhngoc/ac06b43149f81b2650a8fe16e6948c7c to your computer and use it in GitHub Desktop.
fizzy-cli overview

The repo: https://github.com/robzolkos/fizzy-cli

The fizzy-cli application uses the Thor gem to create a structured and modular command-line interface. Here's an explanation of how the commands are created and used, based on the analysis of the codebase.

  1. The Core Framework: Thor

The application is built on top of Thor, a powerful toolkit for building CLIs in Ruby. Thor provides a simple way to define commands, options, and subcommands, and it automatically generates help text.

The main entry point is the Fizzy::CLI class in lib/fizzy/cli.rb. This class inherits from Thor and is responsible for setting up global options and registering the main command groups.

  1 # lib/fizzy/cli.rb
  2 # frozen_string_literal: true
  3 
  4 require_relative 'commands/auth'
  5 # ... other requires
  6 
  7 module Fizzy
  8   class CLI < Thor
  9     # ...
 10   end
 11 end
  1. The Three-Tiered Command Structure

The application has a well-organized three-tiered structure for managing commands:

  • Tier 1: The Main CLI (lib/fizzy/cli.rb) This is the top-level router. It defines global options that can be used with any command (e.g., --token) and registers the available command "groups" (like board, card, etc.) using Thor's subcommand method.
 1     # lib/fizzy/cli.rb
 2     module Fizzy
 3       class CLI < Thor
 4         # ...
 5         desc "board SUBCOMMAND", "Manage boards"
 6         subcommand "board", Commands::Board
 7         # ...
 8       end
 9     end
  • Tier 2: The Base Command (lib/fizzy/commands/base.rb) This is a crucial abstract base class that all command groups inherit from. It provides essential shared functionality, preventing code duplication and ensuring a consistent experience across all commands. Its key responsibilities include:
    • API Client Initialization: It provides a client method that all subcommands can use to make API calls.
    • Configuration Access: It offers a config method to access global configuration settings.
    • Standardized Output: It includes output and output_error methods to ensure that all commands return results in a consistent JSON format.
  1     # lib/fizzy/commands/base.rb
  2     module Fizzy
  3       module Commands
  4         class Base < Thor
  5           # ...
  6           private
  7 
  8           def client
  9             # ... initializes and returns an API client
 10           end
 11 
 12           def config
 13             # ... returns the configuration
 14           end
 15 
 16 
 17 
 18           def output(data)
 19             # ... prints data as JSON
 20           end
 21           # ...
 22         end
 23       end
 24     end
  • Tier 3: The Command Groups (lib/fizzy/commands/*.rb) Each file in the lib/fizzy/commands/ directory defines a class for a specific command group (e.g., Fizzy::Commands::Board). These classes inherit from Fizzy::Commands::Base and define the actual subcommands.

    Within each class, public methods map directly to subcommands. For example, the list method in the Fizzy::Commands::Board class becomes the fizzy board list command. Thor's desc method is used to provide a description for each subcommand, which is shown in the help text.

  1     # lib/fizzy/commands/board.rb
  2     module Fizzy
  3       module Commands
  4         class Board < Base
  5           desc "list", "List all boards"
  6           def list
  7             response = client.get("boards")
  8             output(response)
  9           end
 10 
 11           # ... other subcommands like show, create, etc.
 12         end
 13       end
 14     end

How to Add a New Command

Adding a new command group (e.g., for managing "projects") is straightforward:

  1. Create the Command File: Create a new file, lib/fizzy/commands/project.rb.

  2. Define the Class: Inside the new file, define the class and inherit from the base class:

  1     # lib/fizzy/commands/project.rb
  2     module Fizzy
  3       module Commands
  4         class Project < Base
  5           desc "list", "List all projects"
  6           def list
  7             response = client.get("projects")
  8             output(response)
  9           end
 10 
 11           # Add other subcommands here...
 12         end
 13       end
 14     end
  1. Load the File: In lib/fizzy.rb, add the following line to ensure the new command file is loaded:

1 # lib/fizzy.rb 2 require_relative "fizzy/commands/project"

  1. Register the Command: In lib/fizzy/cli.rb, register the new command group so that Thor knows about it:
1     # lib/fizzy/cli.rb
2     module Fizzy
3       class CLI < Thor
4         # ...
5         desc "project SUBCOMMAND", "Manage projects"
6         subcommand "project", Commands::Project
7         # ...
8       end
9     end

By following this pattern, the fizzy-cli application can be easily extended with new commands while maintaining a clean and organized codebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment