Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Hyper Admin & Developer Guide

Generated June 2026 from vercel/hyper at da0c401

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is the complete operational and architectural reference for Hyper, the extensible terminal built on Electron, React, Redux, and xterm.js. It is written for administrators packaging or deploying Hyper, plugin authors building on its extension API, and developers who need to understand or reproduce its internals. Every fact, default, file path, configuration key, and IPC channel documented here is derived directly from Hyper's source code.

Note

Reference version: Hyper 4.0.0-canary.5. Hyper 4 changed the configuration format from Hyper 3's JavaScript ~/.hyper.js to a JSON hyper.json file in a platform-specific config directory; the migration path is documented in Configuration Migration.


1. Executive Summary

Hyper is a cross-platform desktop terminal emulator. It is a thin, plugin-driven Electron application: a Node-powered main process owns the OS-level concerns (windows, pseudo-terminals, config, plugin installation, auto-update, native menus), and a React + Redux renderer draws the terminal using xterm.js. The two halves communicate over a per-window RPC bridge built on Electron IPC.

Attribute Value
Product Hyper ("A terminal built on web technologies")
Version 4.0.0-canary.5
Author / owner ZEIT, Inc. / Vercel
License MIT
App ID co.zeit.hyper
Platforms macOS, Windows, Linux (x64 + arm64)
Runtime Electron 22.3.25 (Chromium + Node)
UI stack React 18.2, Redux 4.2 (+ react-redux, redux-thunk, reselect, seamless-immutable)
Terminal engine xterm.js 5.3 + addons (fit, search, web-links, webgl, unicode11, image, ligatures, canvas)
PTY node-pty 1.0
Language TypeScript 5.4
Package manager pnpm 10.33
Config file hyper.json (JSON)
Extensibility npm-published plugins/themes via a ~40-method extension API

Important

Hyper deliberately runs its renderer with nodeIntegration: true and contextIsolation: false, and enables @electron/remote. This is the opposite of the modern hardened-Electron posture, and it exists so that plugins (arbitrary npm packages) can require Node modules directly in the renderer. The security consequences of this design are covered in Security Model.


2. Architecture

2.1 Two-process design

                          ┌───────────────────────────────────────────┐
                          │                Hyper (Electron)            │
                          │                                            │
  ~/.config/Hyper/        │   ┌──────────────────┐   IPC/RPC   ┌─────┐ │
  hyper.json  ───watch───▶│   │   MAIN PROCESS   │◀──(uuid)───▶│ R   │ │
                          │   │   (app/, Node)   │   channel   │ E   │ │
  node-pty ──spawn──────▶ │   │                  │             │ N   │ │
   │  shell (zsh/bash/…)  │   │  • windows       │             │ D   │ │
   │                      │   │  • sessions(PTY) │             │ E   │ │
   ▼                      │   │  • config loader │             │ R   │ │
  PTY data ──batched────▶ │   │  • plugin loader │             │ E   │ │
   (16ms / 200KB)         │   │  • auto-updater  │             │ R   │ │
                          │   │  • native menus  │             │  (lib/, React+Redux+xterm.js)
                          │   └──────────────────┘             └─────┘ │
                          └───────────────────────────────────────────┘
Layer Source dir Responsibilities
Main process app/ App lifecycle, BrowserWindow management, node-pty sessions, config load/watch, plugin install + loading, auto-update, native menus, OS integration (CLI install, ssh:// protocol, context menu)
Renderer lib/ React UI, Redux store, xterm.js terminal, tab/pane (term-group) layout, dispatching user intents back to main via RPC
CLI cli/ Standalone hyper command for plugin management and launching
Type contracts typings/ Shared .d.ts definitions: config, hyper, common, action constants

2.2 Repository structure

hyper/
├── app/                      # Electron MAIN process (TypeScript)
│   ├── index.ts              # Main entry: app lifecycle, window creation
│   ├── config.ts             # Config facade: profiles, watch/reload, decorate
│   ├── config/               # Config subsystem
│   │   ├── config-default.json   # Default settings (ground truth for defaults)
│   │   ├── schema.json           # Generated JSON Schema for hyper.json
│   │   ├── import.ts / init.ts    # Load + merge user/default config
│   │   ├── migrate.ts            # Hyper 3 → Hyper 4 migration
│   │   ├── paths.ts              # All config/plugin/CLI paths per platform
│   │   ├── open.ts               # Open hyper.json in editor
│   │   └── windows.ts            # Window position/size persistence (electron-store)
│   ├── session.ts            # PTY session (node-pty) + DataBatcher
│   ├── rpc.ts                # Per-window RPC Server (IPC bridge)
│   ├── plugins.ts            # Plugin loading, npm install, decorate hooks
│   ├── plugins/              # extensions.ts (API surface) + install.ts (yarn)
│   ├── commands.ts           # Command map (keymap → action) for the main process
│   ├── menus/                # Native menu builders (per platform + per section)
│   ├── keymaps/              # Default key bindings: darwin/linux/win32 JSON
│   ├── ui/                   # window.ts (BrowserWindow), contextmenu.ts
│   ├── updater.ts            # Auto-update feed + channel logic
│   ├── auto-updater-linux.ts # Custom Linux update-check implementation
│   ├── notifications.ts      # Remote "news" notifications
│   ├── notify.ts             # Native desktop notifications
│   └── utils/                # cli-install, colors, map-keys, shell-fallback, …
├── lib/                      # RENDERER (React + Redux + xterm.js)
│   ├── index.tsx             # Renderer entry: store + RPC wiring
│   ├── command-registry.ts   # Renderer-side command handlers
│   ├── actions/              # Redux action creators (sessions, term-groups, ui, …)
│   ├── reducers/             # Redux reducers (sessions, term-groups, ui)
│   ├── containers/           # Connected React containers (hyper, terms, header, …)
│   ├── components/           # React components (term, tabs, split-pane, searchBox, …)
│   ├── store/                # Store config + write-middleware
│   ├── selectors.ts          # reselect selectors
│   └── utils/                # config, plugins, ipc, rpc, paste, term-groups, …
├── cli/                      # hyper CLI (api.ts + index.ts)
├── typings/                  # Shared TypeScript definitions
├── electron-builder.json     # Packaging/distribution config
├── webpack.config.ts         # Renderer bundling
└── package.json              # Root (build) + app/package.json (runtime deps)

2.3 The RPC bridge (the API surface)

Communication between renderer and main is a custom event emitter layered over Electron IPC. Each window gets a Server instance (app/rpc.ts) keyed by a freshly generated UUID channel. On did-finish-load, the main process sends an init message carrying the channel id and profile name; thereafter both sides emit/on typed events.

Because Hyper has no HTTP API and no class-based route handlers, the RPC event table is the authoritative API surface — AST extraction reports zero endpoints, which is expected for this architecture. The principal events:

Renderer → Main (the user's intents):

Event Effect in main process
new Create a session (spawn PTY), optional split direction/profile
exit Terminate a session by uid
data ({uid, data, escaped}) Write bytes to a session's PTY
resize ({uid, cols, rows}) Resize the PTY
maximize / unmaximize / minimize / close Window state
open external ({url}) Open a URL in the default browser
open context menu (selection) Pop up the terminal context menu
open hamburger menu ({x, y}) Pop up the application menu (Win/Linux)
command (name) Execute a named command in the main process
quit and install Trigger an in-place app update

Main → Renderer (results and OS events): init, session add, session data, session exit, termgroup add req, split request horizontal/vertical, session clear req, session search, reset/increase/ decrease fontSize req, move left/right req, move jump req, next/prev pane req, open file, open ssh, update available, add notification, enter/ leave full screen, windowGeometry change, plus a family of session move/del … req events that send line-editing escape sequences.

In addition, the main process registers ipcMain.handle request/response endpoints used by the renderer and plugins:

IPC handle Returns
child_process.exec Result of running a command (for plugins)
child_process.execFile Result of running a file
getDecoratedConfig (profile) Final config after plugin decoration
getDecoratedKeymaps Final keymaps after plugin decoration
getLoadedPluginVersions Loaded plugin name/version list
getPaths / getBasePaths Plugin directory paths
getDeprecatedConfig Plugins using deprecated config CSS

2.4 Terminal session data pipeline

shell (PTY) ──onData──▶ DataBatcher ──flush (16ms or 200KB)──▶ Session 'data'
   ▲                      (prefixes each batch with the                │
   │                       session uid; utf8 StringDecoder)            ▼
   │                                                          rpc.emit('session data')
keystrokes ◀── pty.write ◀── rpc 'data' ◀──── renderer (xterm.js onData) ◀┘
  • Each Session (app/session.ts) wraps a node-pty PTY.
  • A DataBatcher accumulates PTY output and flushes it to the renderer at most every 16 ms or when the buffer reaches 200 KB, prefixing each batch with the 36-character session UUID. This batching minimizes IPC calls and GC pressure. The renderer strips the UUID prefix and feeds the rest to xterm.js.
  • On the renderer side, tabs are root term-groups and panes are nested term-groups (lib/actions/term-groups.ts, lib/reducers/term-groups.ts).

Note

Line-editing commands (move/delete by word or line, break, stop, quit, tmux prefix) are implemented in lib/index.tsx by writing raw escape/control sequences to the active session — e.g. \x1bb (move word left), \x03 (Ctrl+C / break), \x02 (tmux prefix). They are not shell-specific keybindings.


3. System Requirements

Runtime (end users)

Requirement Detail
OS macOS, Windows 10+, or a mainstream Linux distribution
Architecture x64 or arm64
Disk Electron app bundle (~150–250 MB depending on platform)
Network Optional — used for plugin install, update checks, and remote notifications

Build / development

Requirement Detail
Node.js Compatible with @types/node 18 (Node 18.x toolchain)
pnpm 10.33+ (enable via corepack enable pnpm)
Native build tools Required to compile node-pty
Windows pnpm add --global windows-build-tools from an elevated prompt
macOS Xcode CLT (agree to license: sudo xcodebuild)
Linux (RPM-based) GraphicsMagick, libicns-utils, xz
Linux (Debian-based) graphicsmagick, icnsutils, xz-utils

4. Configuration Reference

Hyper's entire configuration is the hyper.json file. This section documents the file's structure and every key under config, with type, default, and meaning, as defined by typings/config.d.ts, app/config/schema.json, and app/config/config-default.json.

4.1 File location and load order

app/config/paths.ts resolves the config directory as follows:

Condition Config directory
XDG_CONFIG_HOME is set $XDG_CONFIG_HOME/Hyper
Windows Electron userData directory
macOS / Linux ~/.config/Hyper

The config file is hyper.json within that directory. In development (NODE_ENV !== production), if a hyper.json exists at the repo root, that file is used instead — so developers can keep their personal config separate.

Load sequence (app/config/import.ts → init.ts):

  1. Ensure plugin directories exist (plugins/, plugins/local/).
  2. Run Hyper 3 → 4 migration if needed.
  3. Read config-default.json (the baseline).
  4. Overlay the platform's default keymap JSON.
  5. Read the user's hyper.json; on parse failure, notify and fall back to defaults.
  6. Deep-merge user config over defaults; normalize profiles; merge keymaps; filter out empty plugin entries.

Hyper watches hyper.json with chokidar and reloads ~100 ms after any change, notifying subscribers and re-running plugin installation if the plugin list changed (app/config.ts).

4.2 Top-level keys

Key Type Purpose
config object All terminal/appearance/behavior settings
plugins string[] npm packages to install + load ([@org/]project[#version])
localPlugins string[] Local plugin folder names under plugins/local/
keymaps object Command → shortcut(s) overrides

4.3 Root-level config options

These are application-wide (not per-profile) settings.

Key Type Default Description
updateChannel 'stable' | 'canary' stable Release channel: polished vs. frequent
disableAutoUpdates boolean false If true, never check for app updates
autoUpdatePlugins boolean | string true Auto-update plugins every 5 h (or a custom interval like 1d, 2h)
defaultSSHApp boolean true Register Hyper as the default ssh:// protocol client
useConpty boolean (unset) Force ConPTY on/off on Windows; if unset, node-pty decides

4.4 Profile (terminal) config options

These can be set at the root and overridden per profile (see Profiles). Defaults below come from config-default.json.

Key Type Default Description
fontSize number 12 Font size in px
fontFamily string Menlo, "DejaVu Sans Mono", Consolas, "Lucida Console", monospace Font stack
fontWeight FontWeight normal Normal-text weight (100–900, normal, bold)
fontWeightBold FontWeight bold Bold-text weight
lineHeight number 1 Relative line height
letterSpacing number 0 Relative letter spacing
uiFontFamily string (unset) Font for Hyper's own UI chrome
cursorColor string rgba(248,28,229,0.8) Cursor color/opacity
cursorAccentColor string #000 Text color under a BLOCK cursor
cursorShape 'BEAM'|'UNDERLINE'|'BLOCK' BLOCK Cursor shape
cursorBlink boolean false Blinking cursor
foregroundColor string #fff Default text color
backgroundColor string #000 Terminal background (opacity macOS-only)
selectionColor string rgba(248,28,229,0.3) Selection highlight
borderColor string #333 Window/tab border
colors ColorMap 16-color palette ANSI 16-color map (see default in User Guide)
css string "" Custom CSS for the main window
termCSS string "" Custom CSS for the terminal area
padding string 12px 14px CSS padding around the terminal
workingDirectory string "" Absolute startup directory
showHamburgerMenu boolean | '' "" Show hamburger menu (Win/Linux); ''→default true
showWindowControls boolean | 'left' | '' "" Window controls visibility/side
scrollback number 1000 Lines of scrollback buffer
shell string "" Shell binary path (empty = login shell)
shellArgs string[] ["--login"] Shell arguments
env object {} Extra environment variables
bell 'SOUND' | false SOUND Audible bell or off
bellSound string | null null Base64-encoded bell sound
bellSoundURL string | null null Absolute path to a bell sound file
copyOnSelect boolean false Copy selection to clipboard automatically
defaultSSHApp boolean true (root) see above
quickEdit boolean false Right-click copy/paste (default true on Windows; disables context menu)
macOptionSelectionMode string vertical vertical column mode or force
webGLRenderer boolean false WebGL vs. canvas (canvas supports transparency)
webLinksActivationKey 'ctrl'|'alt'|'meta'|'shift'|'' "" Modifier required to click links
disableLigatures boolean true false enables font ligatures
screenReaderMode boolean false Enable screen-reader access
imageSupport boolean true Sixel + iTerm2 inline image protocol
preserveCWD boolean true New tabs/splits inherit the active pane's CWD
modifierKeys object (unset) { altIsMeta, cmdIsMeta }
windowSize [number, number] (unset) Initial window size in px

Important

Negative knowledge (prevents fabrication): Hyper does not read any system-wide config file, has no HTTP/REST API, no webhooks, and accepts no behavior-changing command-line arguments (hyper --help/--version only print diagnostics). All configuration flows through hyper.json. There is no telemetry endpoint; the only outbound calls are plugin-registry queries, the update feed, and the remote "news" notification fetch.

4.5 Profiles

defaultProfile (string) names the profile used for new sessions; profiles is an array of { name, config } where config is a partial set of the profile options above. app/config.ts:getProfileConfig() merges a profile's overrides onto the base config (objects are shallow-merged; scalars replaced). If defaultProfile doesn't match any profile, the first profile's name is used; an empty profile list is normalized to a single default profile.

4.6 Keymaps

keymaps maps a command name to one shortcut (string) or several (array). User keymaps are merged over the platform defaults. app/utils/map-keys.ts normalizes every binding to an array, rewrites deprecated cmd → command, and expands any command ending in :prefix into nine generated bindings (…:1……:8, …:last) by appending digits 1–9 to the prefix shortcut. The complete default keymaps for each platform are listed in the User Guide; the full command catalog is in Command Reference.

4.7 Window state persistence

Window position and size are persisted separately from hyper.json via electron-store (app/config/windows.ts), defaulting to position [50, 50] and size [540, 380]. They are recorded on window close and restored on next launch (validated against connected displays in app/utils/window-utils.ts).


5. Plugin Extension API

Plugins are npm packages (or local folders) that export one or more recognized extension methods. The complete set of recognized methods is defined in app/plugins/extensions.ts as availableExtensions. A package that exports none of these is rejected with "does not expose any Hyper extension API methods."

5.1 Extension method catalog

Category Methods
Main-process lifecycle onApp, onWindow, onWindowClass, onUnload, onRendererWindow
Config / environment decorateConfig, decorateKeymaps, decorateEnv, decorateMenu, decorateBrowserOptions
Session / window classes decorateSessionClass, decorateSessionOptions, decorateWindowClass
Redux store middleware, reduceUI, reduceSessions, reduceTermGroups
React component HOCs decorateTerm, decorateHyper, decorateHyperTerm (compat), decorateHeader, decorateTerms, decorateTab, decorateTabs, decorateNotification, decorateNotifications, decorateTermGroup, decorateSplitPane
Component prop getters getTermProps, getTabProps, getTabsProps, getTermGroupProps
State / dispatch mappers mapHyperTermState, mapTermsState, mapHeaderState, mapNotificationsState, mapHyperTermDispatch, mapTermsDispatch, mapHeaderDispatch, mapNotificationsDispatch

5.2 How decoration works

app/plugins.ts loads each plugin module, records its _name and _version, and chains decorators: for a given hook key, every plugin that exports it is called in order, each receiving the previous result. Object-returning hooks (decorateConfig, decorateMenu, decorateEnv, etc.) must return an object; class hooks (decorateSessionClass) must return a function/class. Invalid returns produce a "invalid return type" notification and are skipped. The decorated results feed the IPC handles getDecoratedConfig / getDecoratedKeymaps and the window/session constructors.

For backward compatibility, the main process patches Node's Module._load so plugins can require('react'), require('react-dom'), require('hyper/component'), require('hyper/decorate'), etc. (these specific requires are deprecated).

5.3 Plugin installation

plugins entries are synced into an auto-generated package.json inside the plugin base directory and installed with a bundled standalone Yarn (bin/yarn-standalone.js) run through Electron-as-Node (ELECTRON_RUN_AS_NODE=true), serialized through a single-concurrency queue with a 5-minute timeout (app/plugins/install.ts). Installation is triggered on launch (when the plugin set changed), on config change, on the periodic autoUpdatePlugins interval, and on demand via the plugins:update command.

5.4 Plugin directories

app/config/paths.ts defines (relative to the config dir):

Path Purpose
plugins/ Base: auto-generated package.json + npm-installed node_modules
plugins/local/ Local (unpublished) plugins listed in localPlugins
plugins/cache/ Yarn cache folder used during install

Tip

Plugin development workflow (PLUGINS.md): run Hyper in dev mode on the canary branch, copy your hyper.json to the repo root, drop or symlink your plugin into plugins/local/, and add its folder name to localPlugins. A successful load logs Plugin <name> (<version>) loaded. Renderer-side console.log appears in the Electron DevTools; main-process logging appears in the launching terminal.


6. Operations

6.1 Running and lifecycle

The main process (app/index.ts) initializes config, enables @electron/remote, and on the ready event creates the first window. It installs React/Redux DevTools in dev mode, wires the activate/window-all-closed/open-file/open-url handlers, builds the native menu, loads plugins (onApp), and (in production) registers/deregisters the ssh:// protocol client and installs the CLI.

OS event Behavior
activate (macOS dock click, no windows) Create a new window
window-all-closed Quit, except on macOS
open-file Send the path to a window (open file)
open-url Parse an ssh:// URL and open a session (open ssh)

6.2 Auto-update

app/updater.ts builds an update feed URL and polls it 10 s after launch and every 30 minutes thereafter (unless disableAutoUpdates is set):

https://{releases|releases-canary}.hyper.is/update/{platform}{_arm64?}/{version}
  • releases-canary is used when updateChannel is canary; switching channels at runtime re-points the feed and re-checks.
  • _arm64 is appended on Apple Silicon / ARM64 (including Rosetta-translated runs).
  • On Linux, the platform segment is deb and a custom AutoUpdater (app/auto-updater-linux.ts) fetches release metadata over HTTP. Linux cannot install in place (quitAndInstall is unimplemented), so canInstall is false and users are only notified.
  • On macOS/Windows, Electron's native autoUpdater downloads and installs; the renderer's quit and install RPC triggers quitAndInstall().

6.3 Remote notifications

app/notifications.ts fetches https://hyper-news.now.sh on launch and every 30 minutes, sending X-Hyper-Version and X-Hyper-Platform headers. A returned message is surfaced in the UI; malformed responses raise Bad response.

6.4 CLI installation into PATH

app/utils/cli-install.ts installs the hyper command on first run:

Platform Mechanism
macOS / Linux Symlink bin/hyper → /usr/local/bin/hyper; on EACCES, offers an elevated sudo ln -sf … via sudo-prompt or copies the command to the clipboard
Linux AppImage Skipped (AppImage mounts at a temporary path)
Windows Adds the bin directory to the user PATH via the HKCU\Environment registry key, removing stale Squirrel-era paths

6.5 Windows system context menu

app/utils/system-context-menu.ts adds/removes "Open Hyper here" entries under HKCU\Software\Classes\…\shell\Hyper for directory background, directory, and drive, via Tools → Add/Remove Hyper to system context menu.

6.6 Logs and diagnostics

  • Open DevTools: Cmd+Alt+I (macOS) / Ctrl+Shift+I (Win/Linux), or View → Developer Tools.
  • Enable verbose Electron logging by launching via the CLI with --verbose (sets ELECTRON_ENABLE_LOGGING=1).
  • Help → Report Issue generates a GitHub issue pre-filled with version, OS, arch, Electron version, LANG, SHELL, TERM, and the contents of hyper.json and the plugin list (large payloads are copied to the clipboard instead).

7. Security Model

Caution

Hyper's renderer runs with nodeIntegration: true, contextIsolation: false, and @electron/remote enabled (app/ui/window.ts). This is an intentional trade-off that grants renderer code — including every installed plugin — full Node.js and OS access. It is not the hardened contextBridge model recommended for Electron apps that load untrusted remote content.

7.1 Trust boundary

Hyper loads only local content (file://…/index.html) — it never navigates to remote web pages — so the classic remote-code-execution risk of nodeIntegration is mitigated by what is loaded. The real trust surface is plugins: a plugin is arbitrary npm code that executes with full privileges in both processes. Administrators deploying Hyper in sensitive environments should treat the plugins/localPlugins lists as a code-allowlist and review plugins as dependencies.

7.2 Navigation and external content

app/ui/window.ts constrains navigation:

  • will-navigate and setWindowOpenHandler intercept drag-dropped/clicked URLs: file:// paths are inserted as escaped shell input; http(s):// URLs are passed through; other navigations are denied. This prevents the terminal window from navigating away from the app.
  • open external routes URLs through shell.openExternal (the OS browser), not an in-app webview.

7.3 Shell input escaping

When the renderer sends data with escaped: true (e.g. dropped file paths), the main process quotes it for the target shell — wrapping in double quotes for cmd.exe, single-quotes (with '\\'' escaping) otherwise (app/ui/window.ts).

7.4 Environment hygiene

app/session.ts strips Electron's injected GOOGLE_API_KEY from the shell environment (so it isn't leaked to child processes) and, on AppImage installs, fixes PATH so the bundled CLI isn't shadowed by the AppImage mount point.

7.5 Packaging hardening (macOS)

The macOS build is notarized (afterSign: ./bin/notarize.js) and ships an entitlements file (build/mac/entitlements.plist). The app declares a full set of NS…UsageDescription strings because plugins may invoke OS capabilities (AppleScript, camera, contacts, etc.). Linux snap uses classic confinement.


8. Build & Distribution

8.1 Build pipeline

Script Action
pnpm run dev Concurrent webpack -w (renderer) + tsc --build --watch (types/main)
pnpm run app Launch the built app via electronmon (auto-restart on change)
pnpm run build Production webpack + tsc -b + Babel-minify the renderer bundle
pnpm run dist build then electron-builder (produces installers)
pnpm run rebuild-node-pty Rebuild the native node-pty for Electron
pnpm run v8-snapshot Build V8 startup snapshots (x64 + arm64) for faster boot
pnpm run generate-schema Regenerate app/config/schema.json from typings/config.d.ts
pnpm run lint / test:unit / test:e2e ESLint / AVA unit tests / AVA + Playwright e2e

The renderer is bundled by webpack.config.ts (entry lib/index.tsx); the main process is type-checked and emitted by the TypeScript project references. Babel (with @babel/preset-react + @babel/preset-typescript) handles the renderer's JSX/TS. tsconfig.base.json targets ES2022, strict: true, jsx: react, CommonJS modules.

8.2 Distribution matrix (electron-builder.json)

Platform Targets Arch Signing / notes
macOS default (dmg + zip) x64, arm64 Notarized (afterSign), entitlements, dark-mode support, registers folder & Unix-executable document types
Windows nsis x64, arm64 RFC-3161 timestamp; installer is non-one-click, per-user, allows changing the install dir; custom installer.nsh
Linux deb, AppImage, rpm, snap, pacman — Category TerminalEmulator; deb uses bzip2 + after-install hook; snap uses classic confinement (published to GitHub)

Other packaging facts:

  • appId: co.zeit.hyper; artifact name ${productName}-${version}-${arch}.${ext}.
  • The packaged app directory is target/; extra resources include bin/yarn-standalone.js, bin/cli.js, and the per-OS hyper* CLI binaries.
  • afterPack copies the V8 snapshot (bin/cp-snapshot.js).
  • A dedicated electron-builder-linux-ci.json extends the base config but disables afterSign and npmRebuild for CI Linux builds.
  • The ssh URL scheme is registered as an app protocol (protocols).
  • release.js is an electron-builder release-notes hook that prompts for a one-line summary and prepends it to the generated changelog.

9. Command Reference

Commands are named actions bound to keyboard shortcuts and menu items. Main-process commands are defined in app/commands.ts (each emits an RPC event or performs an OS action); some are handled in the renderer (lib/command-registry.ts).

9.1 Window & application

Command Action
window:new Create a new window
window:minimize / window:zoom / window:close Window state (Electron roles)
window:toggleFullScreen Toggle full screen
window:reload Hot-reload the renderer/plugins (RPC reload)
window:reloadFull Full webContents.reload()
window:devtools Toggle detached DevTools
window:preferences Open hyper.json
window:hamburgerMenu Pop up the app menu (Win/Linux)
window:toggleKeepOnTop Toggle always-on-top

9.2 Tabs & panes

Command Action
tab:new New tab (or new window if none focused)
tab:next / tab:prev Cycle tabs
tab:jump:1…8, tab:jump:last Jump to a tab (generated from tab:jump:prefix)
pane:splitRight / pane:splitDown Split vertically / horizontally
pane:close Close the active pane
pane:next / pane:prev Cycle pane focus

9.3 Editor (terminal input)

Command Action / sequence
editor:clearBuffer Clear the scrollback
editor:selectAll Select all text
editor:search / editor:search-close Open / close the find bar
editor:movePreviousWord / moveNextWord ESC b / ESC f
editor:moveBeginningLine / moveEndLine ESC O H / ESC O F
editor:deletePreviousWord / deleteNextWord ESC DEL / ESC d
editor:deleteBeginningLine / deleteEndLine ESC w / \x10B
editor:break / editor:stop / editor:quit Ctrl+C / Ctrl+Z / Ctrl+\
editor:tmux tmux prefix Ctrl+B
editor:undo/redo/cut/copy/paste Native Electron roles

9.4 Zoom, plugins, CLI, OS

Command Action
zoom:in / zoom:out / zoom:reset Adjust renderer font size
plugins:update Force a plugin update
cli:install Install the hyper CLI into PATH
systemContextMenu:add / remove Windows Explorer context-menu entries
window:new:<profile>, tab:new:<profile>, pane:splitRight:<profile>, pane:splitDown:<profile> Per-profile variants (generated per profile)

Note

Some commands (window:close, editor:undo/redo/cut/copy/paste/selectAll, window:minimize/zoom/toggleFullScreen) are executed directly by Electron menu roles. lib/command-registry.ts marks these as roleCommands and does not prevent their default, so the OS handles them.

9.5 Native menu structure

app/menus/menu.ts assembles the menu from per-section builders, injecting the first shortcut for each command as the accelerator:

Menu Items
Hyper (macOS only) About, Preferences…, services, hide/quit
Shell (macOS) / File (Win/Linux) New Tab, New Window, Split Down/Right, per-profile submenus, Close, Close Window/Quit
Edit Undo/Redo/Cut/Copy/Paste, Select All, Move to…, Delete…, Clear Buffer, Search (+ Preferences… off-mac)
View Reload, Full Reload, Developer Tools, Zoom Reset/In/Out
Tools Update plugins, Install Hyper CLI in PATH, (Windows) context-menu add/remove
Window Minimize, Zoom, Select Tab (incl. tab-jump 1–9), Select Pane, Front, Toggle Always on Top, Full Screen
Help Hyper Website, Report Issue, (off-mac) About

The same Edit + Shell builders also produce the in-terminal right-click context menu (app/ui/contextmenu.ts), filtering Cut/Copy to appear only when there's a selection.


10. Dependency Reference

10.1 Renderer / shared (root package.json)

Dependency Version Role
react, react-dom 18.2.0 UI framework
redux, react-redux, redux-thunk, reselect 4.2.1 / 8.1.3 / 2.4.2 / 4.1.8 State management
seamless-immutable 7.1.4 Immutable term-group state
xterm + addons 5.3.0 Terminal engine (canvas, fit, image, ligatures, search, unicode11, web-links, webgl)
@electron/remote 2.1.2 Renderer→main object bridge
mousetrap (fork) Keyboard shortcut handling
styled-jsx, stylis, clsx, color — Styling
args, chalk, columnify, got, open, ora — CLI tooling

10.2 Main process (app/package.json)

Dependency Version Role
node-pty 1.0.0 Pseudo-terminal spawning
electron-store 8.2.0 Window-state persistence
chokidar ^3.6.0 Config file watching
default-shell, shell-env, os-locale — Shell/env resolution
electron-is-dev, electron-fetch, git-describe — Runtime helpers
recast, @babel/parser, ast-types — Hyper 3 → 4 config migration (AST transform)
native-process-working-directory ^1.0.2 CWD inheritance for splits
native-reg (optional), sudo-prompt — Windows registry / elevated CLI install
async-retry, queue, fs-extra, ms, uuid, semver — Utilities

10.3 Build toolchain (devDependencies)

Electron 22.3.25, electron-builder, electron-rebuild, electron-mksnapshot, electron-link, electronmon, webpack 5.91 + webpack-cli, Babel 7.24, TypeScript 5.4.5, ESLint 8.57 (+ TypeScript/React/import/prettier plugins), AVA 6.1 + Playwright 1.43 (tests), Husky, Prettier, Terser.


11. Code Quality & Patterns

  • Strict TypeScript end to end (strict: true, ES2022). Shared contracts in typings/ keep the IPC event payloads, config shape, and Redux actions type-safe across the process boundary (MainEvents/RendererEvents typed emitters in rpc.ts).
  • Redux with thunks + effects. Action creators return objects carrying an effect() callback executed by custom store middleware (lib/store/), used to bridge dispatched actions to RPC emits — a clean separation of state change from side effect.
  • Immutable term-group tree. Tabs/panes form a tree of term-groups kept in seamless-immutable state; pane navigation and closing recompute the active session by walking the tree (lib/actions/term-groups.ts).
  • Decorator chains for extensibility. Every customizable surface — config, keymaps, menus, env, sessions, windows, React components — runs through the same decorateEntity chain, giving plugins uniform, composable hooks.
  • Performance. PTY output batching (16 ms / 200 KB), V8 startup snapshots, and an imperative terms registry for hot-path term access (lib/terms.ts) target responsiveness under heavy output.

Known tech-debt signals (from source)

  • Several plugin require aliases (react, react-dom, hyper/component, hyper/decorate) are explicitly marked DEPRECATED but retained for compatibility (app/plugins.ts).
  • The extendKeymaps plugin hook is deprecated; plugins using it are warned at load time.
  • A webLinksActivationKey TODO notes that link-activation changes don't apply without restarting the terminal (typings/config.d.ts).
  • Pre-xterm.js CSS selectors are detected and flagged as deprecated rather than removed (app/config.ts:getDeprecatedCSS).

12. Potential Improvements

These are observations for maintainers and downstream packagers, grounded in the current source:

  • [ ] Revisit the renderer security posture. With nodeIntegration: true / contextIsolation: false, consider whether a contextBridge-based plugin API could preserve extensibility while shrinking the renderer's privilege — at minimum, document the plugin trust model prominently for enterprise deployers.
  • [ ] Plugin provenance. There is no signature/integrity check on installed plugins beyond npm resolution; an allowlist or lockfile-pinning story would help managed environments.
  • [ ] Linux in-place updates. auto-updater-linux only notifies; a packaged updater (or clearer per-format guidance) would close the gap with macOS/Windows.
  • [ ] Deprecation cleanup. The deprecated require aliases and extendKeymaps hook could be removed in a future major, with a migration note for plugin authors.

13. Quick Reference

Item Value
Config file hyper.json
Config dir (mac/Linux) ~/.config/Hyper/
Config dir (Windows) Electron userData dir
Config dir (XDG) $XDG_CONFIG_HOME/Hyper/
Plugin dirs plugins/, plugins/local/, plugins/cache/
Default shell args ["--login"]
Default window size 540 × 380 (min 370 × 190)
Scrollback default 1000 lines
PTY batch flush 16 ms or 200 KB
Update feed https://releases[-canary].hyper.is/update/{platform}{_arm64}/{version}
App ID co.zeit.hyper
CLI binary hyper (symlink /usr/local/bin/hyper on Unix; PATH entry on Windows)
Open config Cmd+, / Ctrl+,
DevTools Cmd+Alt+I / Ctrl+Shift+I
Plugin update Cmd+Shift+U / Ctrl+Shift+U
Build installers pnpm run dist
Regenerate schema pnpm run generate-schema
Related repos hyper-site, hyperpower (sample ext), hyperyellow (sample theme), Awesome Hyper