TRMNL faced the daunting challenge of turning a successful Kickstarter idea into real hardware, shipped to thousands of eager customers. On top of that, they needed to deliver a developer SDK with a command-line interface—but building one from scratch wasn’t an option because the company didn’t have enough developers to build it.
Fortunately, the founder of TRMNL, Ryan Kulp, found Terminalwire.
TRMNL knew they wanted to ship a command-line interface for their SDK because they’re fast, efficient, can be scripted, and loved by developers. Ryan thought building a CLI that would require the resources of a Series B company—then he discovered Terminalwire.
Took less than an hour to get to that “aha” moment
Ryan installed the Terminalwire Rails gem, ran the rails g terminalwire:install
command, added a few commands, and had a working command-line interface that he put in front of his customers for feedback.
Developers manage TRMNL plugins from the command-line
trmnl
Commands:
trmnl go # Interact with your TRMNL account + native plugins
trmnl help [COMMAND] # Describe available commands or one specific command
trmnl login # Log in to your account
trmnl logout # Log out of your account
trmnl plugins # Interact with your custom plugins
trmnl version # Displays current CLI version.
trmnl whoami # Displays current user information.
Terminalwire is the type of tooling that makes Rails and Ruby thrive.
Soon after Ryan shipped the first iteration of the command-line app, a customer reported that two-factor authentication was missing. Ryan built the feature and deployed it to production in under two hours—something that would have taken days with the traditional way of building command-lines.
When Ryan needed to add new features to trmnl
, he wrote CLI code that looked like CLI code.
# The `trmnl whoami` command displays login state. desc "whoami", "Displays current user information." def whoami if current_user puts "Logged in as #{current_user.email}." else puts "Not logged in. Run `#{self.class.basename} login` to log in." end end
The Terminalwire Server streams stdio
and stores an encrypted cookie for current_user
on the users’ workstations in a way that’s familiar to web developers.
You want another feature? Just write another Ruby function.
Terminalwire made it possible for Ryan to implement this feature, and many other features, in a few minutes by eliminating the time-consuming toil of building, integration testing, and deploying changes to a client and server repo.
The bulk of the work here is NOT thinking about CLIs, it’s not speed or backward compatibility—it’s really just about design. How can we make it intuitive?
Ryan quickly realized with Terminalwire, more time could be spent focusing on designing the developer experience instead of worrying about all the plumbing traditionally associated with command-line interface apps.
One reason TRMNL can move so fast with their command-line interface is because of all the heavy lifting Terminalwire does for them, including cross-platform binaries, installers, and software updates.
This type of tooling is the smarter, not harder … it’s what bootstrappers need. I need to get the whole thing live on my own.
These standard Terminalwire features did all the heavy lifting so TRMNL could focus on their core product:
The only thing TRMNL customers have to do to install the trmnl
CLI is run the following from their workstation.
Install the `trmnl` CLI
curl -Ls https://trmnl.terminalwire.sh | bash
Terminalwire detects which operating system the user is running, installs the appropriate Terminalwire thin-client, then points it at TRMNL’s CLI server.
All TRMNL has to do is tell their customers to copy the command and paste it into their terminal.
The Terminalwire thin client runs on macOS, Linux, and Windows Linux Subsystem.
Someone can spend a few hours building a CLI and look attractive to their customers against an incumbent
When TRMNL wants to add a feature to their command-line they make changes to code in their Rails app, deploy it to their server, and customers instantly get the new updates streamed to their Terminalwire Client.
Terminalwire was designed to be familiar to people who build web apps. Want to implement login? Terminalwire has a session
feature that lets TRMNL store their users’ login state, and other session data, in an encrypted, signed file on their users’ workstations.
class ApplicationTerminal < Thor include Terminalwire::Thor def authenticate_user! return true if current_user shell.say "Must be logged in to do this." false end def current_user=(user) session["user_id"] = user.id end def current_user @current_user ||= User.find_by_id(session["user_id"]) end end
Direct connections between TRMNL and their customers are over encrypted WebSockets—nothing passes through Terminalwire.
stripe
and github
Someone can spend a few hours building a CLI and look attractive to their customers against an incumbent
Not only does Terminalwire make it possible for companies and startups to ship CLIs quickly and easily, it also opens up completely new opportunities and capabilities.
Terminalwire isn’t a sprawl, it’s a flex. It’s the series B thing. Now it can be worked into the model sooner.
Before Ryan discovered Terminalwire, he thought building and shipping a CLI would require a team that only a Series B round of fundraising could afford—it wasn’t even something that was on the table at such an early stage.
We can open-source our CLI and let people PR into it.
Not only did Terminalwire make it possible for TRMNL to deploy a CLI at such an early stage, but it opened up completely new capabilities like open-sourcing it on Github so they could better engage with their developer community.
TRMNL now has a command-line app that rivals the polish of Stripe and GitHub—but built in days, not months. More importantly, their CLI is now a key part of their product strategy, giving their developers the tools they need for very little effort.