### Create a new Rails app Source: https://terminalwire.com/docs/rails/getting-started Command to create a new Rails application. Assumes Rails is installed. ```bash rails new my-app cd my-app ``` -------------------------------- ### Install Terminalwire Rails Gem Source: https://terminalwire.com/docs/rails/getting-started Command to add the Terminalwire Rails gem to your application's Gemfile and install it. ```bash bundle add terminalwire-rails rails g terminalwire:install my-app ``` -------------------------------- ### Terminalwire Binary Stub Configuration Source: https://terminalwire.com/docs/rails/getting-started Configuration file for the Terminalwire executable stub used in development. Specifies the WebSocket URL for the server connection. ```shell #!/usr/bin/env terminalwire-exec url: "ws://localhost:3000" ``` -------------------------------- ### Configure Routes for Terminalwire Server Source: https://terminalwire.com/docs/rails/getting-started Mounts the Terminalwire::Thor::Server with the MainTerminal class to the '/terminal' endpoint using WebSocket for client connections. ```ruby # ./config/routes.rb Rails.application.routes.draw do match '/terminal', to: Terminalwire::Thor::Server.new(MainTerminal), via: [:get, :connect] end ``` -------------------------------- ### Define MainTerminal Commands in Rails Source: https://terminalwire.com/docs/rails/getting-started Defines application-specific commands (hello, login, whoami, logout) by inheriting from ApplicationTerminal and utilizing Terminalwire::Thor for session management and authentication. ```ruby # ./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 ``` -------------------------------- ### Test Terminalwire Integration in Rails Source: https://terminalwire.com/docs/rails/getting-started Command to test the Terminalwire integration by running a command through the generated binary stub. Assumes Rails server is running. ```bash ./bin/my-app version ``` -------------------------------- ### Configure ApplicationTerminal in Rails Source: https://terminalwire.com/docs/rails/getting-started Defines the base Thor command-line parser for Terminalwire, enabling IO streaming and user authentication. Requires Thor and Terminalwire::Thor. ```ruby # ./app/terminals/application_terminal.rb # Learn how to use Thor at http://whatisthor.com. class ApplicationTerminal < Thor # Enables IO Streaming. include Terminalwire::Thor # The name of your binary. Thor uses this for its help output. def self.basename = "<%= binary_name %>" 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 sytem. 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 ``` -------------------------------- ### One-off Installation by URL (terminalwire CLI) Source: https://terminalwire.com/docs/rails/distribution Performs a one-off installation of an application directly from a URL. Uses the Terminalwire CLI with the --url and --name flags. ```bash terminalwire install \ --url https://example.com/terminal \ --name my-app ``` -------------------------------- ### Install App (terminalwire CLI) Source: https://terminalwire.com/docs/rails/distribution Installs an application via the Terminalwire CLI, typically used with applications listed in the Terminalwire directory. ```bash terminalwire install my-app ``` -------------------------------- ### One-liner Curl Installer (bash) Source: https://terminalwire.com/docs/rails/distribution Provides a one-liner curl installer for distributing your application. Replace `my-app` with the actual binary name. ```bash curl -sSL https://my-app.terminalwire.sh | bash ``` -------------------------------- ### Write output to terminal using stdout (Ruby) Source: https://terminalwire.com/docs/rails/stdio Demonstrates how to send text to the client terminal using standard output. In Ruby, `puts` and `print` are redirected by Terminalwire to stream over WebSockets. Use for regular informational messages. ```Ruby # Print "Hello, World!" to the terminal and append a newline puts "Hello, World!" # Print "Hi!" to the terminal without a newline print "Hi!" ``` -------------------------------- ### Read user input from terminal using stdin (Ruby) Source: https://terminalwire.com/docs/rails/stdio Shows how to capture text entered by the user via standard input. Terminalwire forwards `$stdin.gets` calls to the client, allowing interactive prompts. Trim the newline withchomp` for clean values. ```Ruby print "What is your name?: " # Read a line of text from the terminal name = gets.chomp # chomp removes the newline character # Print a greeting to the terminal puts "Hello, #{name}!" ``` -------------------------------- ### Launch URL with Rails ApplicationTerminal Source: https://terminalwire.com/docs/rails/browser Demonstrates how to use `browser.launch` within a Rails `ApplicationTerminal` to open URLs in the client's default browser. The example shows launching the root URL of a Rails application when a user runs a command. ```ruby class MainTerminal < ApplicationTerminal desc "open", "Open in browser." def open # Launch's the root URL of a Rails app from the console browser.launch root_url end end ``` -------------------------------- ### GET /terminal/sessions/new Source: https://terminalwire.com/docs/rails/authentication Displays a form for the user to approve or deny access for a terminal application. This is the initial step in the terminal app authorization flow. ```APIDOC ## GET /terminal/sessions/new ### Description This endpoint renders the authorization form for a terminal application. It presents the user with a title, subtitle, and buttons to "Approve" or "Deny" the app's access request. The "Approve" button submits a POST request to the `create` action with the authorization token. ### Method GET ### Endpoint /terminal/sessions/new ### Parameters #### Query Parameters - **token** (string) - Required - A token provided by the terminal app, used to identify the authorization request. ### Request Example ``` GET /terminal/sessions/new?token=some_auth_token ``` ### Response #### Success Response (200 OK) - **HTML Form**: Renders an HTML form with fields for approval and denial. #### Response Example ```html
``` ``` -------------------------------- ### GET /terminal/session Source: https://terminalwire.com/docs/rails/authentication Displays a success message after a terminal application has been successfully authorized. ```APIDOC ## GET /terminal/session ### Description This endpoint displays a success message to the user indicating that the command-line application has been successfully authorized. It informs the user they can now close the window and continue using the CLI. ### Method GET ### Endpoint /terminal/session ### Parameters None ### Request Example ``` GET /terminal/session ``` ### Response #### Success Response (200 OK) - **HTML Page**: Renders a success message. #### Response Example ```html

Successfully authorized command line app

You may now close this window and continue using the command-line interface.

``` ``` -------------------------------- ### Prompt for password securely using getpass (Ruby) Source: https://terminalwire.com/docs/rails/stdio Uses the `getpass` helper provided by Thor/Terminalwire to read a password without echoing it to the terminal. This method returns the entered string, suitable authentication checks. No visible feedback is shown to the user while typing. ```Ruby puts "Login to your account" # Read a line of text from the terminal password = getpass # chomp removes the newline # Check if the password is correct. if password == "password" puts "You are logged in" else puts "Incorrect password" end ``` -------------------------------- ### Implement email and password login in Terminalwire (Ruby) Source: https://terminalwire.com/docs/rails/authentication Provides a Ruby method for logging in via email and password within a Terminalwire terminal. Uses `gets` for email input and `getpass` to securely read the password, then authenticates with Devise's `find_for_authentication` and `valid_password?`. Outputs success or error messages. ```Ruby # ./app/terminals/main_terminal.rb 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 ``` -------------------------------- ### Write error messages to terminal using stderr (Ruby) Source: https://terminalwire.com/docs/rails/stdio Illustrates sending error output to the client terminal via standard error. In Ruby, `warn` writes to `$stderr`, which Terminalwire streams to the user's console. Useful for reporting issues without interrupting normal output. ```Ruby # Write an error message to the users terminal warn "Oops, An error occurred" ``` -------------------------------- ### Implement web browser authentication command in Terminalwire (Ruby) Source: https://terminalwire.com/docs/rails/authentication Shows a Ruby class method that initiates a web-browser based authentication flow. Generates a secure nonce, creates a signed token with Rails secret key, constructs a URL, opens the browser, waits for the user to authorize, and retrieves the user ID to set the current user. Requires Rails, SecureRandom, ActiveSupport::MessageVerifier, and ActiveExchange. ```Ruby # ./app/terminals/main_terminal.rb class MainTerminal < ApplicationTerminal desc "login", "Login to application" def login # Create a nonce nonce = SecureRandom.hex # Encrypt it with Rails secret key verifier = ActiveSupport::MessageVerifier.new(Rails.application.secret_key_base) # Generate a token that expires in 10 minutes token = verifier.generate(nonce, expires_in: 10.minutes) # Generate a URL that the user can visit to authenticate url = new_terminal_session_url(token:) puts "Opening #{url} in your browser..." # How sign it with Rails and gem it into the URL... client.browser.launch(new_terminal_session_url(token:)) # Wait for the user to authenticate. This is a blocking call that waits # fot the user to successfully authenticate in the browser. authorization = ActiveExchange::Channel.new(name: "auth:#{nonce}") if user_id = JSON.parse(authorization.read).fetch("user_id") self.current_user = User.find(user_id) puts "Welcome #{current_user.email}" else puts "Well that didn't work" end end end ``` -------------------------------- ### Request Core License (terminalwire CLI) Source: https://terminalwire.com/docs/rails/distribution Requests a Core license for a personal application using the terminalwire CLI. Requires the URL of the web application and the --product core flag. ```bash terminalwire license request https://hobbyist.example.com/terminal \ --product core ``` -------------------------------- ### Create Distribution (terminalwire CLI) Source: https://terminalwire.com/docs/rails/distribution Creates a distribution for your application using the terminalwire CLI. Requires the app name and the URL where it can be accessed. ```bash terminalwire distribution create my-app \ --url https://example.com/terminal ``` -------------------------------- ### Request Pro License (terminalwire CLI) Source: https://terminalwire.com/docs/rails/distribution Requests a Pro license for a commercial web application using the terminalwire CLI. Requires the URL of the web application and the --product pro flag. ```bash terminalwire license request https://mega-corp.example.com/terminal \ --product pro ``` -------------------------------- ### Implement terminal app authorization controller in Ruby on Rails Source: https://terminalwire.com/docs/rails/authentication Defines a SessionsController with a before_action to ensure the user is logged in, inline New and Show view classes for rendering the approval form and success message, and a create action that verifies a signed token, broadcasts the user ID over a dynamic channel, and redirects to the terminal session URL. Requires ActiveSupport, ActiveExchange, and Superview gems. ```Ruby class Terminal::SessionsController < ApplicationController # If the user is not logged in, this will force them to login before they # can authorize the terminal app. before_action :authorize_user # Enabled inline rendering of the views below. layout false include Superview::Actions View = DeveloperView # Display a form asking the user to Approve or Deny the terminal app. class New < View def title = "Authorize command line app" def subtitle = "The terminal app is requesting access to your account. Do you approve?" def view_template form action: url_for(action: :create), method: :post, class: "flex flex-row gap-4" do input type: "hidden", value: helpers.params.fetch("token"), name: "token" input type: "submit", class: "btn btn-primary", value: "Approve" input type: "cancel", class: "btn btn-error", value: "Deny" end end end # Display a success message after the user has approved the terminal app. class Show < View def title = "Successfully authorized command line app" def subtitle = "You may now close this window and continue using the command-line interface." def view_template end end # The New view submits a form to this action. If the user approves the terminal authorization # it will send a message to the terminal app with the user's ID to the nonce they're listening on. def create verifier = ActiveSupport::MessageVerifier.new(Rails.application.secret_key_base) nonce = verifier.verified(helpers.params[:token]) message = JSON.generate(user_id: current_user.id) ActiveExchange::Channel.new(name: "auth:#{nonce}").broadcast(message) redirect_to terminal_session_url end end ``` -------------------------------- ### POST /terminal/sessions Source: https://terminalwire.com/docs/rails/authentication Creates a new terminal session by authorizing a terminal app. This endpoint is typically accessed via a form submission after the user has been prompted to approve or deny access. ```APIDOC ## POST /terminal/sessions ### Description This endpoint handles the submission of the terminal app authorization form. If the user approves, it verifies the provided token, broadcasts a message containing the user's ID to a specific channel, and redirects the user to the terminal session URL. ### Method POST ### Endpoint /terminal/sessions ### Parameters #### Query Parameters - **token** (string) - Required - A token used to verify the authorization request. ### Request Body - **token** (string) - Required - The authorization token provided by the terminal app. ### Request Example ```json { "token": "a_verified_token_string" } ``` ### Response #### Success Response (302 Redirect) - **Location** (string) - Redirects to the terminal session URL. #### Response Example ``` HTTP/1.1 302 Found Location: /terminal/session ``` ### Error Handling - If the token is invalid or expired, an appropriate error response will be returned (e.g., 400 Bad Request or 422 Unprocessable Entity, depending on implementation). - If the user is not authenticated, they will be redirected to the login page due to the `authorize_user` before_action. ``` -------------------------------- ### Reading Environment Variables in Terminalwire Ruby Source: https://terminalwire.com/docs/rails/environment-variables Demonstrates two methods to read environment variables from the client's workstation: directly via the ENV hash in context or using the environment_variables device. Requires TERMINALWIRE_HOME to be set; access to other vars needs client permission. Outputs the value of the specified variable; note potential typo in 'environmnent_variables'. ```ruby # Access the ENV hash context.ENV["TERMINALWIRE_HOME"] # Or use the env device context.environmnent_variables.read("TERMINALWIRE_HOME") ``` -------------------------------- ### Write file to client storage path Source: https://terminalwire.com/docs/rails/file-system Writes a file to the client's Terminalwire storage directory. The operation is restricted to the ~/.terminalwire/authorities/$AUTHORITY/storage path by default. Requires appropriate context and storage path variables to be defined. ```ruby # Write a file to the client's file system at # ~/.terminalwire/authorities/$AUTHORITY/storage/hello.txt context.file.write storage_path.join("hello.txt"), "Hello, World!" ``` -------------------------------- ### List files in client storage directory Source: https://terminalwire.com/docs/rails/file-system Lists all files in the client's Terminalwire storage path using directory globbing. This operation is restricted to the ~/.terminalwire/authorities/$AUTHORITY/storage path by default. Requires context and storage path variables to be defined. ```ruby # List all of the files in the client's file system in their Terminalwire storage path. context.dir.glob storage_path ``` -------------------------------- ### Perform Bulk Session Updates in Terminalwire Source: https://terminalwire.com/docs/rails/sessions This Ruby code illustrates how to efficiently update multiple session attributes in a single operation using the `session.edit` method with a block. This approach minimizes client-server communication by making all changes in one round-trip, ensuring data consistency. ```ruby session.edit |data| data["uuid"] = SecureRandom.uuid data["id"] = user.id data["expires_at"] = 1.month.from_now end ``` -------------------------------- ### Manage User Session in Rails Application Source: https://terminalwire.com/docs/rails/sessions This Ruby code demonstrates how to set and retrieve a user's ID within the Terminalwire session, mimicking Rails' approach to session management. It uses a `session` object, which acts like a hash, to store and retrieve the `user_id` after encrypting and signing it. ```ruby # Learn how to use Thor at http://whatisthor.com. class ApplicationTerminal < Thor # .. Code ... 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 sytem. 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 ``` -------------------------------- ### Override Default URL Options in Rails Source: https://terminalwire.com/docs/rails/browser Shows how to override the `default_url_options` method in your `ApplicationTerminal` to customize URL settings. This is useful for setting a custom host name. ```ruby class ApplicationTerminal < Thor include Terminalwire::Thor def default_url_options { host: 'your-custom-host.com' } end end ``` -------------------------------- ### Set Session Expiration and UUID Manually Source: https://terminalwire.com/docs/rails/sessions This Ruby code shows how to manually set session expiration and a unique identifier (UUID) within the session data using the `session.edit` block. This is necessary because Terminalwire sessions do not have built-in expiration or IDs like Rails sessions. ```ruby session.edit do |data| data["expires_at"] = 1.month.from_now data["uuid"] = SecureRandom.uuid end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.