A cross-platform terminal multiplexer for busy bees. Split panes, tabs, workspaces, themes, git status, notifications — all in one window.
Warning
This is a super early build. There are bugs, things are broken, and the paint is still very wet. Use with caution!
Helping out is always warranted. If you find a bug or have a suggestion, please open an issue or submit a pull request. Contributions of all kinds are welcome!
Built with Electron, Solid.js, and xterm.js.
- Split panes — Horizontal and vertical splits with draggable dividers and per-pane zoom
- Tabs — Multiple tabs per pane, drag-and-drop between panes, choose your shell per tab
- Workspaces — Organize terminals into named, color-coded workspaces with optional grouping
- 10 built-in themes + unlimited custom themes loaded from disk
- Git integration — Live branch name and dirty-state indicator per workspace
- Notifications — Detects OSC 9/99/777 escape sequences, desktop alerts, in-app badges, configurable sounds
- Session persistence — Auto-saves layout every 8 seconds, restores on relaunch
- Saved layouts — Snapshot and reload entire workspace arrangements by name
- Command palette — Fuzzy-searchable action list (Ctrl+K / Cmd+K)
- Find in terminal — Incremental search with match highlighting
- Auto-update — Checks for new releases on GitHub, notifies when an update is available
- Tab reordering — Drag-and-drop tabs to reorder within a pane
- Terminal context menu — Right-click for Copy, Paste, Clear, Reset
- Cross-platform — macOS, Linux, and Windows with native shell detection
Download the latest build for your platform from the Releases page:
| Platform | Format |
|---|---|
| macOS | .dmg (Intel + Apple Silicon) |
| Windows | .exe (NSIS installer) |
| Linux | .AppImage, .deb |
git clone https://github.com/mdeloughry/hivemux.git
cd hivemux
npm install
npm startRequires Node.js 20+ and a C++ toolchain for the
node-ptynative module (see Building from source for details).
- Launch hivemux — a workspace with a single terminal tab opens automatically.
- Press Ctrl+D (Cmd+D on macOS) to split the pane.
- Press Ctrl+T to open a new tab.
- Press Ctrl+N to create a new workspace.
- Press Ctrl+K to open the command palette and explore all available actions.
- Press ? to view the keyboard shortcut reference.
All shortcuts use Ctrl on Linux/Windows and Cmd on macOS.
| Shortcut | Action |
|---|---|
| Ctrl+N | New workspace |
| Ctrl+1–9 | Jump to workspace (9 = last) |
| Ctrl+B | Toggle sidebar |
| Shortcut | Action |
|---|---|
| Ctrl+D | Split horizontally |
| Ctrl+Shift+D | Split vertically |
| Ctrl+Shift+Enter | Toggle pane zoom |
| Shortcut | Action |
|---|---|
| Ctrl+T | New tab |
| Ctrl+Shift+T | New tab (choose shell) |
| Ctrl+W | Close tab |
| Ctrl+Tab | Next tab |
| Ctrl+Shift+Tab | Previous tab |
| Shortcut | Action |
|---|---|
| Ctrl+F | Find in terminal |
| Ctrl+L | Clear scrollback |
| Ctrl+= | Zoom in |
| Ctrl+- | Zoom out |
| Ctrl+0 | Reset zoom |
| Shortcut | Action |
|---|---|
| Ctrl+K | Command palette |
| Ctrl+Shift+U | Jump to notification |
| ? | Keyboard shortcuts reference |
All configuration lives in ~/.config/hivemux/ (or $XDG_CONFIG_HOME/hivemux/ if set).
~/.config/hivemux/
├── settings.json # App settings
├── sessions/
│ └── default.json # Auto-saved session state
├── layouts/ # Named layout snapshots
│ └── my-layout.json
└── themes/ # Custom themes
└── my-theme.json
Edit ~/.config/hivemux/settings.json or use the in-app settings panel. Changes are picked up automatically.
{
"themeId": "deloughry",
"notificationsEnabled": true,
"notificationSoundEnabled": true,
"notificationSound": "chime",
"fontFamily": "'Geist Mono', 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace",
"fontSize": 14,
"lineHeight": 1.2,
"cursorBlink": true,
"keybindings": {}
}| Setting | Type | Default | Description |
|---|---|---|---|
themeId |
string | "deloughry" |
Theme ID — built-in name or "custom:filename" |
notificationsEnabled |
boolean | true |
Enable terminal notification detection |
notificationSoundEnabled |
boolean | true |
Play a sound on notifications |
notificationSound |
string | "chime" |
Sound: chime, blip, ping, drop, or tap |
fontFamily |
string | (see above) | Terminal font stack |
fontSize |
number | 14 |
Terminal font size (8–32) |
lineHeight |
number | 1.2 |
Terminal line height (1.0–2.0) |
cursorBlink |
boolean | true |
Blinking cursor |
keybindings |
object | (see below) | Custom keyboard shortcut overrides |
Override any shortcut by adding a keybindings object to your settings. Only include the bindings you want to change — unspecified actions keep their defaults.
{
"keybindings": {
"splitHorizontal": { "mod": true, "shift": true, "key": "h" },
"splitVertical": { "mod": true, "shift": true, "key": "v" },
"commandPalette": { "mod": true, "key": "p" }
}
}Each binding supports these fields:
| Field | Type | Description |
|---|---|---|
mod |
boolean | Ctrl on Linux/Windows, Cmd on macOS |
ctrl |
boolean | Always Ctrl (regardless of platform) |
shift |
boolean | Shift modifier |
key |
string | Key name ("d", "Tab", "Enter", "=", etc.) |
All bindable actions and their defaults
| Action | Default |
|---|---|
splitHorizontal |
Ctrl+D |
splitVertical |
Ctrl+Shift+D |
newTab |
Ctrl+T |
closeTab |
Ctrl+W |
newWorkspace |
Ctrl+N |
toggleSidebar |
Ctrl+B |
commandPalette |
Ctrl+K |
newTabWithShell |
Ctrl+Shift+T |
jumpNotification |
Ctrl+Shift+U |
nextTab |
Ctrl+Tab |
prevTab |
Ctrl+Shift+Tab |
fontZoomIn |
Ctrl+= |
fontZoomOut |
Ctrl+- |
fontZoomReset |
Ctrl+0 |
clearScrollback |
Ctrl+L |
findInTerminal |
Ctrl+F |
togglePaneZoom |
Ctrl+Shift+Enter |
| Theme | Style |
|---|---|
| Hivemux | Warm dark with orange accent |
| Dark Blue | Dark with bright blue accent |
| Dracula | Dark purple |
| Monokai | Dark green |
| Solarized Dark | Classic dark blue |
| Nord | Cool cyan tones |
| Deloughry | Deep dark with cyan accent (default) |
| Light Default | Light theme |
| Solarized Light | Classic light |
| Rose Light | Soft pink light |
Drop a JSON file in ~/.config/hivemux/themes/:
{
"label": "My Theme",
"cssVars": {
"--bg": "#1a1b26",
"--bg-secondary": "#16161e",
"--bg-tertiary": "#1f2029",
"--fg": "#c0caf5",
"--fg-muted": "#9aa5ce",
"--fg-dim": "#565f89",
"--accent": "#7aa2f7",
"--accent-dim": "#3d59a1",
"--accent-hover": "#89b4fa",
"--sidebar-bg": "#16161e",
"--border": "#292e42",
"--danger": "#f7768e",
"--success": "#9ece6a",
"--warning": "#e0af68"
},
"xtermTheme": {
"background": "#1a1b26",
"foreground": "#c0caf5",
"cursor": "#7aa2f7",
"cursorAccent": "#1a1b26",
"selectionBackground": "#283457",
"black": "#15161e",
"red": "#f7768e",
"green": "#9ece6a",
"yellow": "#e0af68",
"blue": "#7aa2f7",
"magenta": "#bb9af7",
"cyan": "#7dcfff",
"white": "#a9b1d6",
"brightBlack": "#414868",
"brightRed": "#f7768e",
"brightGreen": "#9ece6a",
"brightYellow": "#e0af68",
"brightBlue": "#7aa2f7",
"brightMagenta": "#bb9af7",
"brightCyan": "#7dcfff",
"brightWhite": "#c0caf5"
}
}The theme ID is custom:<filename> (without the .json extension). Use the "Refresh Themes" button in settings after adding a new file, or restart the app.
hivemux detects terminal notifications sent via OSC escape sequences:
| Escape sequence | Standard |
|---|---|
\e]9;message\a |
iTerm2 (OSC 9) |
\e]99;params;message\a |
Kitty (OSC 99) |
\e]777;notify;title;body\a |
rxvt-unicode (OSC 777) |
When a notification is detected:
- A badge appears on the tab and workspace in the sidebar
- A desktop notification is shown
- An optional sound plays
Use Ctrl+Shift+U to jump to the first workspace with unread notifications.
# iTerm2 style
printf '\e]9;Build complete\a'
# rxvt style (title + body)
printf '\e]777;notify;Build;Your build finished successfully\a'- Node.js 20+
- npm (comes with Node.js)
- A C++ compiler toolchain for
node-pty:- macOS: Xcode Command Line Tools (
xcode-select --install) - Linux:
build-essentialandpython3(apt install build-essential python3) - Windows: Visual Studio Build Tools with the "Desktop development with C++" workload
- macOS: Xcode Command Line Tools (
# Install dependencies (also rebuilds node-pty for your platform)
npm install
# Start in development mode (Vite dev server + Electron)
npm run dev
# Run unit tests
npm test
# Run tests in watch mode
npm run test:watch
# Type-check
npx tsc --noEmit# Build renderer (Vite) + main process (esbuild)
npm run build
# Package for your current platform (outputs to release/)
npm run dist
# Package without installer (unpacked, for testing)
npm run packhivemux/
├── src/
│ ├── main/ # Electron main process
│ │ ├── index.ts # App entry point, window creation
│ │ ├── ipc-handlers.ts # IPC request handlers
│ │ ├── pty-manager.ts # node-pty lifecycle management
│ │ ├── workspace-store.ts # Server-side state
│ │ ├── shell-detect.ts # Cross-platform shell detection
│ │ ├── git-poller.ts # Branch + dirty state polling
│ │ ├── notification-scanner.ts # OSC escape sequence parsing
│ │ ├── cwd-tracker.ts # Working directory tracking
│ │ ├── session-persistence.ts # Auto-save/restore sessions
│ │ ├── saved-layouts.ts # Named layout snapshots
│ │ ├── settings-persistence.ts # Settings file I/O + watcher
│ │ ├── custom-themes.ts # Load themes from ~/.config
│ │ ├── update-checker.ts # GitHub Releases update check
│ │ ├── shell-integration.ts # --install-shell-integration CLI
│ │ └── preload.ts # Context bridge for renderer
│ ├── views/main/ # Renderer (Solid.js)
│ │ ├── App.tsx # Root component
│ │ ├── actions/ # Command palette actions
│ │ ├── hooks/ # Keyboard shortcuts
│ │ ├── stores/ # Reactive state (workspace, UI, terminal)
│ │ ├── components/
│ │ │ ├── Terminal/ # xterm.js pane + tab bar
│ │ │ ├── SplitPane/ # Recursive split container
│ │ │ ├── Sidebar/ # Workspace list, groups
│ │ │ ├── CommandPalette/ # Fuzzy action search
│ │ │ ├── Settings/ # Settings panel UI
│ │ │ ├── SearchBar/ # Find in terminal
│ │ │ ├── ShellPicker/ # Shell selection modal
│ │ │ ├── HelpPanel/ # Shortcut reference
│ │ │ ├── ContextMenu/ # Right-click menus
│ │ │ ├── TitleBar/ # Window controls
│ │ │ └── AboutModal/ # App info
│ │ └── ipc-client.ts # RPC client wrapping IPC
│ └── shared/ # Shared types and constants
│ ├── constants.ts # Shortcuts, colors, intervals
│ ├── themes.ts # Built-in theme definitions
│ ├── workspace-types.ts # AppState, Workspace, Settings
│ └── rpc-types.ts # IPC schema
├── scripts/
│ ├── dev.mjs # Dev mode launcher
│ └── build-main.mjs # esbuild config for main process
├── tests/ # Vitest unit tests
├── electron-builder.yml # Packaging configuration
├── vite.config.ts # Renderer build config
├── vitest.config.ts # Test config
└── package.json
┌─────────────────────────────────────────────────────┐
│ Electron Main Process │
│ │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ PTY │ │ Workspace│ │ Services │ │
│ │ Manager │ │ Store │ │ - Git poller │ │
│ │ (node-pty│ │ │ │ - Session autosave │ │
│ │ spawn, │ │ State + │ │ - Settings watcher │ │
│ │ resize, │ │ mutations│ │ - CWD tracker │ │
│ │ write) │ │ │ │ - Notif scanner │ │
│ └────┬─────┘ └────┬─────┘ └───────────────────┘ │
│ │ │ │
│ └──────┬───────┘ │
│ │ IPC (40+ handlers) │
├──────────────┼────────────────────────────────────────┤
│ │ Preload (context bridge) │
├──────────────┼────────────────────────────────────────┤
│ ▼ │
│ Renderer (Solid.js) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ Workspace│ │ UI Store │ │ Terminal Registry │ │
│ │ Store │ │ (modals, │ │ (xterm instances, │ │
│ │ (state │ │ focus, │ │ fit/search │ │
│ │ mirror) │ │ menus) │ │ addons) │ │
│ └──────────┘ └──────────┘ └──────────────────┘ │
│ │
│ Components: SplitPane, Sidebar, Terminal, Tabs ... │
└───────────────────────────────────────────────────────┘
The main process owns all state and PTY processes. The renderer receives state pushes and sends RPC requests over IPC. xterm.js Terminal instances are stored in a registry that survives component re-mounts, so terminals keep their scrollback when tabs or panes are rearranged.
See README-CI.md for full documentation on the GitHub Actions pipeline, required secrets, and how to trigger releases.
| Workflow | Trigger | Purpose |
|---|---|---|
test.yml |
Push / PR to main, develop |
Lint + tests on all platforms |
release.yml |
Manual | Bump version, build, publish release |
hivemux sets the following environment variables in spawned shells:
| Variable | Value | Description |
|---|---|---|
HIVEMUX |
1 |
Indicates the shell is running inside hivemux |
TERM_PROGRAM |
hivemux |
Identifies the terminal emulator |
TERM |
xterm-256color |
Terminal type for color support |
You can use these in your shell config to customize behavior when running inside hivemux:
# .bashrc / .zshrc
if [ "$HIVEMUX" = "1" ]; then
# hivemux-specific config
fihivemux tracks your terminal's working directory via OSC 7 escape sequences. Most modern shells don't emit these by default. You can install shell integration automatically:
# Install for all supported shells (bash, zsh, fish)
hivemux --install-shell-integration
# Install for specific shells only
hivemux --install-shell-integration bash zshThis appends a small snippet to your shell config file (.bashrc, .zshrc, or ~/.config/fish/conf.d/hivemux.fish). The snippet is guarded by $HIVEMUX so it only activates inside hivemux — it won't affect other terminals.
After installing, restart your shell or open a new tab. You should see the current working directory tracked in the tab title.
If you prefer to add it yourself:
bash (add to ~/.bashrc):
if [ "$HIVEMUX" = "1" ]; then
__hivemux_osc7() {
printf '\e]7;file://%s%s\a' "$HOSTNAME" "$PWD"
}
PROMPT_COMMAND="__hivemux_osc7${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
fizsh (add to ~/.zshrc):
if [[ "$HIVEMUX" = "1" ]]; then
__hivemux_osc7() {
printf '\e]7;file://%s%s\a' "$HOST" "$PWD"
}
autoload -Uz add-zsh-hook
add-zsh-hook precmd __hivemux_osc7
fifish (save as ~/.config/fish/conf.d/hivemux.fish):
if set -q HIVEMUX
function __hivemux_osc7 --on-variable PWD
printf '\e]7;file://%s%s\a' (hostname) "$PWD"
end
__hivemux_osc7
endTwo methods are available for creating demo recordings:
Records a scripted, reproducible demo using the actual app UI rendered in a headless browser. No window manager or display server needed.
# Record the demo (outputs demo.webm)
npm run demo:record
# Convert to GIF with ffmpeg
ffmpeg -i demo.webm -vf "fps=15,scale=1200:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=128[p];[s1][p]paletteuse=dither=bayer" docs/demo.gifThe demo script lives in scripts/demo/ — edit demo-page.html to change the choreography.
Record the real running app with ffmpeg. Requires a display server.
# Prerequisites (Arch / CachyOS)
sudo pacman -S ffmpeg slop xdotool
# Start hivemux first
npm run dev
# Record a 15-second demo (default)
./scripts/record-demo.sh
# Record a 20-second demo
./scripts/record-demo.sh 20The script prompts you to choose a capture mode (full screen, window, or region). Press q to stop early. Output is saved to docs/demo.gif.
The scripts/ directory includes eye-candy scripts that look great in a recording. Split a few panes and run one in each:
| Script | Description | Best in |
|---|---|---|
scripts/showcase-matrix.sh |
Matrix digital rain effect | Tall vertical pane |
scripts/showcase-hacker.sh |
Swordfish-style "hacking" sequence | Wide horizontal pane |
scripts/showcase-agent.sh |
Fake AI agent terminal interface | Standard or wide pane |
# Example: split into 3 panes and run all three
./scripts/showcase-matrix.sh # left pane
./scripts/showcase-hacker.sh # top-right pane
./scripts/showcase-agent.sh # bottom-right pane- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Run tests (
npm test) and type-check (npx tsc --noEmit) - Commit and push
- Open a pull request
This project is licensed under the GNU General Public License v3.0. You are free to use, modify, and distribute this software under the terms of the GPL. Any derivative works must also be distributed under the GPL.
