This guide assumes you have Ruby and Rails installed on your workstation.
Create a Rails app
If you don’t already have a Rails app, create one.
rails new my-app
cd my-app
Install Terminalwire in Rails
Add the Terminalwire Rails gem to your app.
bundle add terminalwire-rails
Then install Terminalwire in your Rails app.
rails g terminalwire:install my-app
Configure the terminal
The rails g terminalwire:install my-app command creates files that you may configure for your application’s needs.
Terminal command-line classes
The ./app/terminals folder contains two files that define your command-line interface.
ApplicationTerminal
The application_terminal.rb file is the base class for your terminal application. It includes the Terminalwire::Thor module to enable I/O streaming, sets the basename for help output, and provides helper methods like current_user for authentication.
# ./app/terminals/application_terminal.rb class ApplicationTerminal < Thor # Enables IO Streaming. include Terminalwire::Thor # The name of your binary. Thor uses this for its help output. def self.basename = "my-app" private def current_user=(user) # The Session object is a hash-like object that encrypts and signs a hash that's # stored on the client's file system. Conceptually, it's similar to Rails signed # and encrypted client-side cookies. session["user_id"] = user.id end def current_user @current_user ||= User.find(session["user_id"]) end end
MainTerminal
The main_terminal.rb file is where you define your application’s commands. You can add, remove, or modify commands as needed. This file inherits from ApplicationTerminal to access I/O streaming and authentication features.
# ./app/terminals/main_terminal.rb class MainTerminal < ApplicationTerminal desc "hello NAME", "say hello to NAME" def hello(name) puts "Hello #{name}" end desc "login", "Login to your account" def login print "Email: " email = gets.chomp print "Password: " password = getpass # Replace this with your own authentication logic; this is an example # of how you might do this with Devise. user = User.find_for_authentication(email: email) if user && user.valid_password?(password) self.current_user = user puts "Successfully logged in as #{current_user.email}." else puts "Could not find a user with that email and password." end end desc "whoami", "Displays current user information." def whoami if self.current_user puts "Logged in as #{current_user.email}." else puts "Not logged in. Run `#{self.class.basename} login` to login." end end desc "logout", "Logout of your account" def logout session.reset puts "Successfully logged out." end end
These commands use Thor, a Ruby command-line parser. You’ll learn more about defining commands, arguments, and options in the Command-Line Parsers chapter.
Routes configuration
The ./config/routes.rb file mounts the MainTerminal in a Terminalwire::Thor::Server WebSocket server to the /terminal endpoint. This is the URL your client will connect to.
# ./config/routes.rb Rails.application.routes.draw do match '/terminal', to: Terminalwire::Thor::Server.new(MainTerminal), via: [:get, :connect] end
Terminalwire binary stub configuration
Terminalwire generates a binary stub in the Rails ./bin folder that you may use to interact with your application in a development environment. You may need to change the host if the server is running on a different port.
!/usr/bin/env terminalwire-exec
url: "ws://localhost:3000"
Test the integration
To test the integration, restart your Rails server, then run ./bin/my-app hello World in your terminal and you should see the following:
./bin/my-app hello World
Hello World
You can also view all available commands by running:
./bin/my-app help
Commands:
my-app hello NAME # say hello to NAME
my-app help [COMMAND] # Describe available commands or one specific command
my-app login # Login to your account
my-app logout # Logout of your account
my-app whoami # Displays current user information
Congratulations, you’ve successfully built a Terminalwire command-line application! 🎉
Next steps
At this point you could deploy it to production and distribute it to your users, but first you’ll want to learn how to build more powerful command-line interfaces.
Continue to the next chapter to learn about Command-Line Parsers, where you’ll discover how to define commands with arguments and options, create subcommands, and customize help output.