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 gems to your app’s Gemfile. Terminalwire ships the v1 server gems and the v2 terminalwire gem from one git source, so a single block pulls in everything you need to serve both the v2 Go client and legacy v1 clients:
# Gemfile git "https://github.com/terminalwire/ruby", branch: "main", glob: "{gem/terminalwire-*,v2/ruby}/*.gemspec" do gem "terminalwire-rails" gem "terminalwire", require: false # v2 end
Install them:
bundle install
Then scaffold your terminal classes:
rails g terminalwire:install my-app
The generator writes your terminal classes and a development launcher. It also adds a starter terminalwire gem line and a route—you can remove the duplicate gem line (the block above already includes it) and replace the route with the dual-protocol one shown below.
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
Mount the MainTerminal at the /terminal endpoint with Terminalwire::V2::Rails.dual_terminal. This is the URL your client connects to. dual_terminal serves both protocols from the same MainTerminal: it routes the v2 Go client to the v2 server and any legacy v1 client to the v1 handler. It’s the same URL and the same CLI for both. Add the require at the top of the file so the v2 server loads (the terminalwire gem is require: false in your Gemfile).
# ./config/routes.rb require "terminalwire/v2/rails" Rails.application.routes.draw do match "/terminal", to: Terminalwire::V2::Rails.dual_terminal(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/terminal"
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.