Hyper Terminal Emulator

repository·canary·Indexed 13 days ago

https://github.com/vercel/hyper

A highly extensible, web-standard-based terminal emulator designed for speed and stability. Built on open web standards, Hyper supports a rich developer experience with a plugin system manageable via its CLI and a configurable environment via hyper.json.

Tokens
11.1K
Snippets
45
Records
51
Agent score
99%

What's inside Hyper

  1. Register command handlers in Renderer or Main process

    canary

    After declaring keymaps, you must register handlers to execute logic.

    Renderer/Window (React Context)

    Use this.terms.registerCommands within a decorated component to execute logic in the renderer (e.g., dispatching Redux actions). The handler receives a React key event e.

    Main Process

    If no renderer handler exists for a command, an rpc message is emitted. Subscribe to these messages in the main process using rpc.on('command <command-name>', callback).

    // Renderer side registration
    this.terms.registerCommands({
      'pane:maximize': e => {
        this.props.onMaximizePane();
        e.preventDefault();
      }
    })
    
    // Main process subscription
    rpc.on('command pane:snapshot', () => {
      /* Awesome snapshot feature */
    });
  2. Decorate Hyper components with HOCs

    canary

    You can modify Hyper components by returning a Higher-Order Component (HOC). Because multiple plugins can decorate the same component, the Component passed to your decorator might already be wrapped by another plugin.

    To ensure you don't break the chain and to access the actual Hyper component, use the onDecorated prop. You must call this.props.onDecorated(instance) to propagate the handler down the chain.

    exports.decorateTerms = (Terms, {React}) => {
      return class extends React.Component {
        constructor(props, context) {
          super(props, context);
          this.terms = null;
          this.onDecorated = this.onDecorated.bind(this);
        }
    
        onDecorated(terms) {
          this.terms = terms;
          // Propagate to HOC chain to avoid breaking other plugins
          if (this.props.onDecorated) this.props.onDecorated(terms);
        }
    
        render() {
          return React.createElement(
            Terms,
            Object.assign({}, this.props, {
              onDecorated: this.onDecorated
            })
          );
        }
      }
    }
  3. Develop Hyper plugins in dev mode

    canary

    To develop plugins, run Hyper in dev mode to access React/Redux dev-tools and increased output.

    1. Clone the repository and follow the contributing guide on the canary branch.
    2. Create a dev config file: Copy your existing hyper.json to the root of the cloned repository. Hyper in dev mode will use this file.
    3. Setup your plugin directory: Create or symlink your plugin repository inside <repository_root>/plugins/local/.
    4. Register the plugin: Edit your dev config file to include your plugin name in the localPlugins array.
    5. Run the app: Use pnpm run app to launch Hyper. If successful, the terminal will log: Plugin <your-plugin-name> (<version>) loaded.
    module.exports = {
      config: {
        // ...
      },
      plugins: [],
      localPlugins: ['hyper-awesome-plugin'],
      // ...
    }
  4. Run Hyper in development mode

    canary

    After cloning the repository and installing dependencies with pnpm install, follow these steps to develop and test changes:

    1. Start the development server: Run pnpm run dev. This starts Webpack in watch mode, which rebuilds renderer code when changes are detected.
    2. Launch the application: In a separate terminal tab or window, run:
      pnpm run app
    3. Debugging in VS Code: Select the Launch Hyper configuration in the debugger to launch an instance with the debugger attached.
    4. Generate binaries: To test your code in a finished application build, run:
      pnpm run dist
      The resulting binaries will be located in the ./dist folder.
    pnpm install
    pnpm run dev
    # In another terminal:
    pnpm run app
  5. Install Hyper

    canary

    Hyper is a terminal emulator built on open web standards. You can install it using various package managers depending on your operating system:

    macOS

    Use Homebrew Cask:

    brew update
    brew install --cask hyper

    Windows

    Use Chocolatey:

    choco install hyper

    Linux

    • Arch and derivatives: Use an AUR helper like paru:
      paru -S hyper
    • NixOS: Use nix-env:
      nix-env -i hyper

    Note: Package manager versions may not always be the latest. For the most recent version, download directly from hyper.is.

    # macOS
    brew install --cask hyper
    
    # Windows
    choco install hyper
    
    # Arch Linux
    paru -S hyper
    
    # NixOS
    nix-env -i hyper
  6. Set up Hyper development environment

    canary

    To contribute to Hyper, you must have pnpm available. It is recommended to enable it via Corepack: corepack enable pnpm.

    1. Install OS-specific dependencies

    Windows

    Run the following from an elevated (Administrator) prompt:

    pnpm add --global windows-build-tools

    macOS

    No additional system packages are required if pnpm is enabled.

    Linux

    • RPM-based: Install GraphicsMagick, libicns-utils, and xz.
    • Debian-based: Install graphicsmagick, icnsutils, and xz-utils.
  7. Locate the Hyper configuration file

    canary

    Hyper looks for its configuration file at hyper.json. The location depends on your operating system and environment variables:

    • Linux/macOS: ~/.config/Hyper/hyper.json (or the path specified by XDG_CONFIG_HOME).
    • Windows: %APPDATA%/Hyper/hyper.json.
    • Development Mode: If NODE_ENV is not set to production and a hyper.json exists in the project root, that file is used instead.
  8. Notarize macOS builds using the notarize script

    canary

    The bin/notarize.js script is a utility designed to automate the Apple notarization process for macOS builds during the packaging lifecycle. It uses the @electron/notarize package to submit the application bundle to Apple.

    Requirements

    To successfully notarize, you must provide the following environment variables:

    • APPLE_ID: Your Apple ID email address.
    • APPLE_PASSWORD: An App-Specific Password generated from your Apple ID account.

    Behavior

    • The script only executes if the electronPlatformName is darwin (macOS).
    • It automatically identifies the application bundle path using the appOutDir and the productFilename from the packager context.
    • It uses the hardcoded appBundleId: co.zeit.hyper.
    // The script expects these environment variables to be set:
    // process.env.APPLE_ID
    // process.env.APPLE_PASSWORD
    
    // It is typically invoked within an Electron builder lifecycle hook:
    // exports.default = async function notarizing(context) { ... }
  9. Troubleshoot Hyper development issues

    canary

    Common issues encountered during development:

    node-pty build errors

    If you see alerts related to node-pty after building, attempt to rebuild the package:

    pnpm run rebuild-node-pty

    On macOS, this is often caused by Xcode issues. Ensure you have accepted the terms by running sudo xcodebuild after a fresh installation.

    C++ compiler errors on macOS

    If pnpm install fails with C++ compiler errors, set the CXX environment variable to clang++:

    export CXX=clang++

    codesign errors on macOS

    If the codesign step fails during pnpm run dist, you can temporarily disable local code signing for the current session:

    export CSC_IDENTITY_AUTO_DISCOVERY=false
  10. Compatibility Note: Hyper v2 and xterm.js

    canary

    Hyper v2 replaced hterm with xterm.js.

    • Rendering: PTY output is now rendered in a canvas element rather than a DOM structure.
    • Breaking Change: Plugins using TermCSS to modify text or link styles will no longer work. Use the configuration parameters passed to xterm.js instead.
    • API Changes: Any plugin deeply coupled with the hterm API is incompatible with v2.
  11. Track cursor position with decorateTerm

    canary

    If your plugin needs to monitor cursor movement, use decorateTerm. This provides a handler that is called on every cursor move, passing a cursorFrame object containing x, y, width, height, col, and row.

    exports.decorateTerm = (Term, { React, notify }) => {
      return class extends React.Component {
        onCursorMove (cursorFrame) {
          // Propagate to HOC chain
          if (this.props.onCursorMove) this.props.onCursorMove(cursorFrame);
    
          const { x, y, width, height, col, row } = cursorFrame;
          /* Awesome cursor feature */
        }
      }
    }
  12. Add keybindings using decorateKeymaps

    canary

    To add or modify keybindings, use the decorateKeymaps API. The format is command: hotkeys.

    • Command Naming: Use the convention <context>:<action> (e.g., pane:maximize).
    • Hotkeys: Use Mousetrap supported keys.
    • Prefix Feature: If a command ends with :prefix, Hyper automatically generates numbered commands. For example, 'pane:hide:prefix': 'ctrl+shift' generates pane:hide:1 through pane:hide:8, and pane:hide:last (mapped to 9).
    // Adding Keymaps
    exports.decorateKeymaps = keymaps => {
      const newKeymaps = {
        'pane:maximize': 'ctrl+shift+m',
        'pane:invert': 'ctrl+shift+i'
      }
      return Object.assign({}, keymaps, newKeymaps);
    }