A modern, cross-platform terminal hub for managing multiple connections.
termiHub provides a VS Code-like interface for managing multiple terminal connections — local shells, SSH, serial, telnet, Docker containers, and WSL distributions — with split views, drag-and-drop tabs, SSH tunneling, and organized connection management. A shared Rust core (termihub-core) powers both the desktop app and a remote agent for persistent sessions on headless servers. Built with Tauri, React, and Rust.
Download the latest release for your platform from the GitHub Releases page. Release assets follow the naming pattern termiHub-<version>-<platform>.<ext> (for example, termiHub-0.1.0-macos-arm64.dmg).
Beta note: v0.1.0 binaries are unsigned. macOS Gatekeeper and Windows SmartScreen will warn on first launch — the per-platform steps below explain how to proceed.
- Download the
.dmgfor your architecture —termiHub-0.1.0-macos-arm64.dmg(Apple Silicon) ortermiHub-0.1.0-macos-x64.dmg(Intel). - Open the DMG and drag termiHub into your Applications folder.
- Because the app is unsigned, a normal double-click is blocked by Gatekeeper on first launch. Instead, right-click (or Control-click) the app → Open → Open. macOS remembers this choice for subsequent launches.
- Download
termiHub-0.1.0-windows-x64.msi. - Run the installer and follow the prompts.
- SmartScreen may warn about an unrecognized app. Click More info → Run anyway to continue.
Pick either the AppImage (portable, no install) or the Debian package.
AppImage — download termiHub-0.1.0-linux-x64.AppImage, then:
chmod +x termiHub-0.1.0-linux-x64.AppImage
./termiHub-0.1.0-linux-x64.AppImageDebian package (.deb) — download termiHub-0.1.0-linux-x64.deb, then:
sudo dpkg -i termiHub-0.1.0-linux-x64.debAppImage is not built for ARM64, so use the Debian package. Download termiHub-0.1.0-linux-arm64.deb, then:
sudo dpkg -i termiHub-0.1.0-linux-arm64.deb- Unsigned binaries — macOS shows a Gatekeeper prompt (right-click → Open) and Windows shows a SmartScreen warning (More info → Run anyway); see the per-platform steps above.
- No auto-update — download new versions manually from the Releases page.
- Serial port support requires platform-specific drivers — see Serial Port Setup.
- Telnet connections are unencrypted by protocol design; avoid them over untrusted networks.
Prefer to build it yourself? See Development below.
- Local shells — zsh, bash, PowerShell, cmd, Git Bash with automatic shell detection
- SSH — Remote terminal sessions with key-based and password authentication
- Serial — Direct serial port connections for hardware debugging and IoT devices
- Telnet — Classic telnet connections with IAC protocol support
- Docker — Connect to running containers or start new ones
- WSL — Windows Subsystem for Linux distribution sessions (Windows only)
- Remote agent — Persistent sessions on headless servers via auto-deployed
termihub-agent
- Split views — Arrange terminals in horizontal and vertical splits with drag-and-drop
- Tab management — Drag-and-drop tabs between panels, per-tab colors, CWD tracking
- Connection management — Organize connections in folder hierarchies with import/export from external files
- File browser — Browse, upload, download, and edit remote files via SFTP
- SSH tunneling — Local, remote, and dynamic (SOCKS5) port forwarding with session pooling
- X11 forwarding — Forward remote GUI applications to your local X server
- System monitoring — Real-time CPU, memory, disk, and network stats for remote hosts
- VS Code-inspired layout — Activity bar, sidebar, status bar with customizable positions
- Themes — Dark, Light, and System (auto-detects OS preference) themes
- Layout presets — Default, Focus (no sidebar), and Zen (minimal UI) modes
- Built-in editor — Edit local and remote files with Monaco Editor (syntax highlighting, search, minimap)
- Schema-driven settings — Connection types declare their own settings; the UI renders them automatically
- Credential storage — Optional credential encryption via platform keychain, master password, or prompt-only mode
- Auto-lock — Configurable timeout for credential store locking
- Authored multi-step workflows — Save named, ordered sequences of steps that run against a terminal session
- Step types —
send-command(type a command),run-script(stream a multi-line script),run-macro(replay a saved macro),wait(delay), andrun-local-process(run a local program — see the security callout below) - Triggers — Run manually (command palette / sidebar), via a hotkey, or automatically on-connect when a chosen connection opens a session
- Sidebar + editor — Manage, edit, and organize workflows from the Workflows panel; import and export workflows as portable JSON
⚠️ run-local-processruns on your LOCAL machine. Every other step type sends text into the terminal session (i.e. runs on the remote host when you are connected).run-local-processinstead launches a program on the computer running termiHub. It is off by default and stays inert until you explicitly opt in under Settings → Security, and each program must be authorized via a per-program allowlist / per-run confirmation. Arguments are passed as a discrete list (no shell interpretation). This is a power-user orchestration capability — safe to ignore entirely if you don't use it. Imported workflows are never auto-authorized.The Workflows panel is experimental and behind the experimental-features toggle — enable Settings → General → Allow Experimental Features to use it. Design reference:
docs/concepts/backlog/workflow-automation.html.
- Cross-platform — Windows, Linux, and macOS
- Shared core —
termihub-coreRust library shared between desktop and remote agent
termiHub uses a VS Code-inspired three-column layout:
┌──────────┬────────────────┬──────────────────────────────────────────┐
│ Activity │ Sidebar │ Terminal View │
│ Bar │ │ ┌──────┬──────┬──────┐ │
│ │ Connections │ │ Tab1 │ Tab2 │ Tab3 │ │
│ [Con] │ File Browser │ ├──────┴──────┴──────┤ │
│ [File] │ Settings │ │ │ │
│ │ │ │ Terminal Content │ │
│ │ │ │ │ │
│ │ │ │ │ │
│ │ │ └────────────────────┘ │
│ [Gear] │ │ Status Bar │
└──────────┴────────────────┴──────────────────────────────────────────┘
- Activity Bar — The narrow left column with icon buttons: Connections (network), File Browser (folder), and a gear icon at the bottom for settings, import/export. Click an active icon to toggle the sidebar.
- Sidebar — Shows the view selected in the Activity Bar.
- Terminal View — The main area with a tab bar, terminal content, toolbar (New Terminal, Split, Close Panel), and status bar.
- Click Connections in the Activity Bar, then + to create a new connection
- Fill in Name, Folder, Type (Local Shell / SSH / Serial / Telnet), and type-specific settings
- Click Save
Right-click a connection for: Connect, Ping Host (SSH/Telnet), Edit, Duplicate, Delete. Double-click to connect immediately.
Folders — Create folders via the toolbar icon. Drag and drop connections between folders. Deleting a folder moves children to the parent.
Import/Export — Use the gear icon to export connections to JSON or import from a JSON file.
External Connection Files — Load shared connection configs from external JSON files (e.g., from a git repo). Add them in Settings > External Connection Files. External connections appear read-only with a git-folder icon.
Environment Variable Placeholders — Use ${VAR} syntax in any connection field to substitute environment variables at connect time (e.g., ${HOME}/.ssh/id_rsa). Unknown variables expand to an empty string. A leading ~ is also expanded to the user's home directory.
- Local Shell — Opens a local terminal using an auto-detected shell (zsh, bash, sh on macOS/Linux; PowerShell, cmd, Git Bash on Windows). Select the shell in the connection editor.
- SSH — Remote terminal via SSH. See SSH Configuration below for authentication, X11 forwarding, and SFTP details.
- Telnet — Remote terminal via Telnet protocol. Configure host and port (default: 23).
- Serial — Connect to serial devices (USB-to-serial adapters, IoT, networking equipment). Configure port, baud rate, data/stop bits, parity, and flow control. See Serial Port Setup below for platform-specific instructions.
Open terminals appear as tabs with type-specific icons and optional colored borders. Actions:
- Click to switch, drag to reorder or move between panels
- Right-click a tab for: Save to File, Copy to Clipboard, Clear Terminal, Horizontal Scrolling, Set Color
Each connection also has terminal options: horizontal scrolling and tab color, configurable in the editor or via the tab context menu.
Split the terminal area into multiple panels:
- Click the Split button in the toolbar, or drag a tab to the edge of a panel
- Drag the divider to resize panels
- Close Panel (X) removes a panel and moves its tabs to an adjacent one
- Splits can be nested (horizontal within vertical and vice versa)
- Drag tabs between panels or to panel edges to create new splits
The sidebar file browser operates in different modes based on the active tab:
| Active Tab | Mode | Description |
|---|---|---|
| Local shell | Local | Browses the local filesystem |
| SSH | SFTP | Browses the remote server |
| Serial / Telnet | None | File browser unavailable |
| Editor/Settings | — | Retains the last active mode |
Toolbar: Up (parent dir), Refresh, Upload (SFTP), New File, New Folder, Disconnect (SFTP).
Context menu: Files — Edit, Open in VS Code, Download (SFTP), Rename, Delete. Directories — Open, Rename, Delete.
Drag-and-drop upload: In SFTP mode, drag files from your OS file manager onto the browser to upload.
Double-click a file in the file browser (or right-click > Edit) to open it in a Monaco-powered editor tab:
- Syntax highlighting with automatic language detection
- Search and replace (Ctrl+F / Ctrl+H)
- Save with Ctrl+S / Cmd+S, unsaved changes shown as a red dot
- Status bar shows cursor position, language, EOL type, tab size, and encoding
| Shortcut | Action |
|---|---|
Ctrl+Shift+`` (`` ``) |
New local terminal |
Ctrl+W / Cmd+W |
Close active tab |
Ctrl+Tab |
Next tab |
Ctrl+Shift+Tab |
Previous tab |
Ctrl+S / Cmd+S |
Save file (in editor) |
On macOS, Cmd can be used in place of Ctrl.
Click the gear icon > Settings to open the settings tab. termiHub stores configuration in a platform-specific directory. Override with the TERMIHUB_CONFIG_DIR environment variable:
TERMIHUB_CONFIG_DIR=./my-project/termihub-config pnpm tauri dev- Quick connect — Double-click any connection to open it immediately
- Organize by project — Use folders to group connections by project or environment
- Color-code tabs — Assign colors to distinguish production, staging, and dev
- Share configs — Use external connection files in a git repo for team-wide connection lists
- Env var placeholders — Use
${VAR}so shared configs work across machines - Split for comparison — Split the view to compare output from two sessions side by side
- Auto-SFTP — The file browser auto-connects to SFTP when you click an SSH tab
termiHub supports Password and SSH Key authentication:
- Password — termiHub prompts for the password each time you connect. Passwords are never stored in the configuration file (optionally stored in the credential store).
- SSH Key — Provide a path to your private key file. Recommended for frequent connections.
Generate a key pair if you don't have one:
ssh-keygen -t ed25519 -C "your_email@example.com"This creates ~/.ssh/id_ed25519 (private) and ~/.ssh/id_ed25519.pub (public). You can also use RSA: ssh-keygen -t rsa -b 4096.
Install the public key on the server:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostnameIn termiHub, set Auth Method to SSH Key and Key Path to ~/.ssh/id_ed25519.
macOS — Add your key to the SSH agent and Keychain:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519Linux — Start the SSH agent and add your key:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519Ensure correct permissions: chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519
Windows — Enable the OpenSSH Authentication Agent service in Services (services.msc), set it to Automatic, then:
ssh-add $env:USERPROFILE\.ssh\id_ed25519X11 forwarding lets you run graphical applications on a remote server and display them locally. Enable it in the SSH connection editor (Enable X11 Forwarding checkbox).
Platform requirements:
- macOS — Install XQuartz (
brew install --cask xquartz), then log out and back in - Linux — Install
xauth(sudo apt install xauthon Ubuntu/Debian) - Windows — Not currently supported (relies on Unix domain sockets)
The SSH server must also have X11Forwarding yes in /etc/ssh/sshd_config and xauth installed.
When you click on an SSH terminal tab, the sidebar file browser auto-connects via SFTP. You can browse, upload, download, create, rename, and delete remote files. Edit remote files in the built-in Monaco editor — changes are saved back via SFTP.
| Field | Description | Default |
|---|---|---|
| Host | Server hostname or IP address | — |
| Port | SSH port | 22 |
| Username | Remote username | — |
| Auth Method | password or key |
password |
| Key Path | Path to private key (when using key auth) | — |
| Enable X11 Forwarding | Forward remote GUI apps to local display | Off |
- "Connection refused" — Verify the SSH server is running (
systemctl status sshd), check the port, test withssh -p 22 user@host - "Authentication failed" — Verify credentials; for key auth, ensure the public key is in
~/.ssh/authorized_keysand the private key has600permissions - "Host key verification failed" — Connect once with
ssh user@hostnameand accept the key - X11 not working — Ensure XQuartz (macOS) or xauth (Linux) is installed and the server has
X11Forwarding yes - SFTP fails — Ensure
Subsystem sftpis configured in/etc/ssh/sshd_config
macOS — Devices appear under /dev/tty.*:
| Device | Path |
|---|---|
| USB-to-serial adapter | /dev/tty.usbserial-* |
| FTDI adapter | /dev/tty.usbserial-FTDI* |
| CH340 adapter | /dev/tty.wchusbserial* |
| Arduino | /dev/tty.usbmodem* |
Most USB-to-serial adapters work out of the box. If not, download drivers from the chipset manufacturer (FTDI, CH340, CP210x). Run ls /dev/tty.* to list devices.
Linux — Devices appear under /dev/ttyUSB* or /dev/ttyACM*:
| Device | Path |
|---|---|
| USB-to-serial adapter | /dev/ttyUSB0 |
| Arduino / ACM device | /dev/ttyACM0 |
| Built-in serial port | /dev/ttyS0 |
Add your user to the dialout group for serial port access:
sudo usermod -a -G dialout $USER
# Log out and back in for the change to take effectWindows — Devices appear as COM ports (e.g., COM3). Find them in Device Manager > Ports (COM & LPT). Drivers are usually installed automatically via Windows Update.
| Parameter | Options | Default | Description |
|---|---|---|---|
| Port | Auto-detected or manual | — | Serial port path |
| Baud Rate | 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 | 9600 | Data transfer speed (bits/second) |
| Data Bits | 5, 6, 7, 8 | 8 | Number of data bits per frame |
| Stop Bits | 1, 2 | 1 | Number of stop bits per frame |
| Parity | None, Odd, Even | None | Error-checking method |
| Flow Control | None, Hardware (RTS/CTS), Software (XON/XOFF) | None | Data flow regulation |
Common configurations: Most embedded devices (Arduino, ESP32, STM32) use 115200/8/1/None/None. Legacy devices typically use 9600/8/1/None/None.
For testing without physical hardware, use the virtual serial port setup in examples/serial/:
# Install socat (macOS: brew install socat, Linux: sudo apt install socat)
cd examples/serial
./setup-virtual-serial.sh # Creates /tmp/termihub-serial-a and /tmp/termihub-serial-b
python3 serial-echo-server.py # Echo server on port BConnect termiHub to /tmp/termihub-serial-a to test.
- Port not appearing — Unplug/replug the device, click Refresh. On Linux, check
dialoutgroup membership. - Garbled output — Baud rate mismatch (most common cause). Verify it matches your device.
- "Permission denied" (Linux) —
sudo usermod -a -G dialout $USER, then log out and back in. - "Port is busy" — Another application has the port open. Serial ports can only be used by one application at a time.
- Node.js v18+ — nodejs.org
- pnpm —
npm install -g pnpm - Rust — rustup.rs
- Tauri prerequisites — Follow the Tauri v2 prerequisites guide for your platform
Platform-specific dependencies:
- macOS — Xcode Command Line Tools:
xcode-select --install - Linux (Ubuntu/Debian) —
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev libssh2-1-dev libudev-dev pkg-config - Linux (Fedora) —
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file libxdo-devel libappindicator-gtk3-devel librsvg2-devel libssh2-devel systemd-devel pkg-config - Linux (Arch) —
sudo pacman -S --needed webkit2gtk-4.1 base-devel curl wget file openssl xdotool libappindicator-gtk3 librsvg libssh2 pkg-config - Windows — Visual Studio Build Tools ("Desktop development with C++" workload), WebView2 (pre-installed on Win 10 1803+)
git clone https://github.com/armaxri/termiHub.git
cd termiHub
./scripts/setup.sh # Install deps + initial build
./scripts/dev.sh # Start dev mode with hot-reloadOr manually: pnpm install && pnpm tauri dev
All scripts live in scripts/ with .sh (Unix/macOS) and .cmd (Windows) variants:
| Script | Purpose |
|---|---|
./scripts/setup.sh |
Install all dependencies and do an initial build |
./scripts/dev.sh |
Start the app in dev mode with hot-reload |
./scripts/build.sh |
Build for production (creates platform installer) |
./scripts/test.sh |
Run all unit tests (frontend + backend + agent) |
./scripts/check.sh |
Read-only quality checks mirroring CI (formatting, linting, clippy) |
./scripts/format.sh |
Auto-fix all formatting issues (Prettier + cargo fmt) |
./scripts/clean.sh |
Remove all build artifacts for a fresh start |
./scripts/test-system-py.sh |
Run the Python bridge system-test harness (build, fixtures, pytest) |
Typical workflow:
./scripts/dev.sh # Daily development
./scripts/format.sh # Before pushing
./scripts/test.sh # Run all tests
./scripts/check.sh # Quality checks (mirrors CI)# Frontend
pnpm run lint # ESLint
pnpm run format:check # Prettier check
pnpm test # Vitest single run
pnpm test:watch # Vitest watch mode
pnpm test:coverage # Vitest with coverage
pnpm build # TypeScript check + Vite build
# Rust workspace
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-featurespnpm tauri buildOutput by platform:
- macOS —
src-tauri/target/release/bundle/dmg/termiHub_<version>_aarch64.dmg(or_x64.dmg) - Linux —
src-tauri/target/release/bundle/deb/termihub_<version>_amd64.deband.AppImage - Windows —
src-tauri\target\release\bundle\msi\termiHub_<version>_x64_en-US.msiand_x64-setup.exe
Quick start — The examples/ directory provides simple Docker-based test servers:
cd examples
./start-test-environment.sh # Start SSH (port 2214) + Telnet (port 2323) servers
./stop-test-environment.sh # Stop serversComprehensive testing — The tests/docker/ directory provides 13 Docker containers for system testing (SSH variants, telnet, serial, SFTP stress, network fault injection). See tests/docker/README.md.
- Architecture — Full arc42 architecture documentation (building blocks, runtime views, ADRs)
- Contributing — Development workflow, coding standards, agent development, releasing, and performance profiling
- Testing — Automated testing strategy and manual test procedures
- Remote Protocol — Desktop-to-agent JSON-RPC specification
- Tauri 2 — Desktop application framework
- React 18 — UI framework
- Rust — Backend language
- xterm.js — Terminal emulator component
- Monaco Editor — Code editor component
- Zustand — State management
- dnd kit — Drag and drop
- react-resizable-panels — Split view layout
This project is licensed under the MIT License — see the LICENSE file for details.
The MIT License is a short, permissive license that allows free use, modification, and distribution. For a plain-language explanation, see Choose a License: MIT by GitHub.