Overview
Write a command-line app on your server. Terminalwire streams it to a tiny client your users install once. It's like a browser, but for the terminal.
class BlogCLI < Terminalwire::CLI desc "posts", "List your posts" def posts current_user.posts.each { puts _1.title } end desc "login", "Sign in" def login browser.launch login_url puts "signed in as #{current_user.email}" endend
Authorize your terminal
then back to your terminal
No API to build· No client to ship· No updates to push
You just saw a command print and open a browser. The same round trip reaches their files, their environment, and whatever they pipe in. Every bit of it is gated by the user's grant.
Pipe a file (or a whole folder) straight into a command. The bytes stream up to your server and your code reads them from stdin. No prompts, because the user chose what to send.
desc "import", "Import posts piped in"def import Post.import_markdown stdin.read puts "imported #{Post.count} posts"end
Files are gated like a browser download. The first write is denied; your code rescues it and prints the exact grant command. The user runs it once, then the write goes through.
desc "export", "Save posts to a file"def export file.write "posts.csv", current_user.posts.to_csvrescue Terminalwire::Denied puts "Run: terminalwire-exec policy grant ./posts.csv"end
Secrets stay on the user's machine until they allow them. Your CLI asks for the variable; the first run prints the entitlement to grant, and after that the server reads it on every run.
desc "deploy", "Deploy with your token"def deploy Deploy.run! token: env.fetch("BLOG_TOKEN")rescue Terminalwire::Denied puts "Run: terminalwire-exec policy grant --env BLOG_TOKEN"end
Pipe anything to a command. The bytes stream up to your server, your code renders them, and --preview pops the result open in their browser.
desc "post", "Create a post from stdin"def post body = stdin.read preview = render_preview(body) browser.launch preview.urlend
Install & updates
You build your CLI once, on your server, and it runs on macOS, Linux, and Windows. There's no installer to write, nothing to code-sign, and no software updates to push. None of it is your problem.
Terminalwire hosts the one-line install at blog.terminalwire.sh and keeps the client current on all three platforms. After that, the client talks straight to your server and streams your latest CLI on every run, so everyone is always on the current version. You write commands. We handle distribution.
# macOS & Linux $ curl blog.terminalwire.sh | sh installing the blog client… ✓ installed blog # Windows (PowerShell) > irm blog.terminalwire.sh | iex ✓ installed blog
The hard questions
The server is open source and runs in your infrastructure. The client is sandboxed like a browser, and updates only run when they verify against our offline root key.