Open Source · C++20 · GPL v3

naTE

// not another Terminal Emulator

A graphical terminal emulator built for people who live in SSH sessions.

Tiling layouts, tabbed sessions, persistent named workspaces, and a full suite of SSH features — agent forwarding, X11 forwarding, ProxyJump, MFA, SFTP — without ever touching the command line. Built from scratch in modern C++20 with a hand-written VT100/ANSI parser and ports-and-adapters architecture.

Active development 196+ commits GPL v3 licensed
naTE — graphical terminal emulator with tiling layouts, tabs, and SSH sessions

A terminal that treats sessions as first-class objects.

Most terminal emulators treat SSH as an afterthought — something you type into the prompt, configure once, and forget. But for anyone who maintains production systems, juggles a dozen remote hosts, or hops between bastion servers all day, the terminal is SSH. naTE was built with that workflow as the starting point, not the edge case.

Tiling, tabs, persistent workspaces, broadcast input, and a connection manager that auto-loads ~/.ssh/config — hosts, identity files, ProxyJump rules, the whole inventory. MFA challenges (Duo, YubiKey, PAM) are handled natively in the GUI. Agent and X11 forwarding work without flags. SFTP file transfer is a built-in dialog with a remote directory browser; the Edit Remote File workflow lets you open remote files in your local editor with automatic re-upload on save.

If you manage remote servers, work with serial consoles, or just want a terminal that doesn't forget your sessions when you close it, naTE is built for you. Free and open source under GPL v3, distributed as a single Linux AppImage with no installation required.

Built around how real terminal work happens.

Four thematic areas. Each capability is present because the workflow that needs it is common in production engineering environments.

SSH — The Killer Feature

Full libssh2 integration, native

  • Authentication: password, public key, SSH agent, keyboard-interactive (MFA — Duo, YubiKey, PAM)
  • SSH agent forwarding (-A); SSH agent identity hints for multi-key setups
  • X11 forwarding per connection profile — Xauthority cookie generated automatically
  • ProxyJump / bastion hop, auto-detected from ~/.ssh/config
  • Auto-populate from ~/.ssh/config — hosts, identity files, ProxyJump rules
  • SFTP file transfer over the existing authenticated session — send, receive, remote directory browser, no re-authentication
  • Working-directory tracking — shells emitting OSC 7 update the tracked CWD continuously; a pwd subchannel captures the final CWD at disconnect for accurate session restore
  • Keepalive and optional connection compression
  • Reconnect bar when a connection drops — resume without re-entering credentials

Tiling, Tabs & Sessions

Sessions as first-class objects

  • Each window holds one or more tiles in a grid; each tile has its own tab strip
  • Drag tabs between tiles or onto other windows; drag the tile header to relocate the whole tile
  • Broadcast input — send the same keystrokes to multiple sessions simultaneously
  • Auto-save and restore open sessions on launch; named workspaces save and switch between layouts
  • Horizontal or vertical tiling direction set per window, with a global default
  • Session initialization — per-connection working directory, environment variables, env-file loading, and a login-shell option; profile titles override dynamic hostnames for clearer tab identity
  • Confirm-close protection — a dialog warns before closing a window with active sessions; auto-suppressed for single-session close, with a per-dialog "Don't ask again" option

Terminal Internals

A real, complete VT implementation

  • Hand-written VT100 / ANSI parser — SGR attributes, OSC sequences
  • UTF-8 rendering with wide / CJK character support — double-width characters occupy two cells, with per-glyph drawing that avoids font-fallback advance drift
  • Configurable scrollback buffer (default 100,000 lines)
  • Alternate screen support for full-screen TUI apps (vim, htop, tmux) — with a manual toggle button in the tile title bar
  • Find in Terminal (Ctrl+Shift+F) — case-insensitive search across the full scrollback with match highlighting and forward/backward navigation; pre-populates from the active selection
  • Mouse selection — click-drag to select; double-click selects the word under the cursor (configurable regex word-boundary); triple-click selects the line
  • Bracketed paste with optional confirmation dialog; URL detection and click-to-open

Serial, Themes & Appearance

Customizable down to the cell

  • Serial console support — configurable baud rate, data bits, stop bits, parity, flow control
  • Optional dial script executed before I/O (for modem-style connections)
  • Built-in themes: Solarized Dark, Solarized Light, xterm
  • 250+ community themes via drop-in base16 YAML — both v0.x flat format and v2 nested format supported; pull from tinted-theming/base16-schemes directly
  • Custom .ini theme format with independent regular/bright variants, dropped into ~/.nate/themes/
  • Font family and size picker (monospace only); cursor styles (block, bar, underline) with optional blink
  • Bell modes: none, visual flash, audible; configurable cell padding
  • Per-profile word-wrap and column-width overrides in the connection manager

Feature spotlight

Wrap mode and column width — actually decoupled

In a classic terminal, the shell's reported width equals the window width. Any output beyond that column is silently truncated and lost. naTE decouples these.

You can set a column width — what the shell believes the terminal is, e.g. 220 columns — independently of the visible tile width. Long lines are captured in full rather than discarded. The wrap button in the tile title bar then controls how those lines are presented: wrap on reflows them into the visible area; wrap off lets the viewport scroll horizontally so each line stays on one row. Per-connection column-width overrides are available in the connection profile, so high-throughput log monitoring on a specific host doesn't get clipped by your local window size.

Feature spotlight

Edit Remote File — your local editor, on remote files

Editing remote files used to mean either learning vim well enough to live in it over SSH, or running scp to pull a file, editing locally, then pushing it back. naTE eliminates the choice.

Terminal → Edit Remote File downloads the file to a temporary path, opens it in your configured local editor ($EDITOR or a path set in Preferences), and then watches the temp file via inotify. Every time you save, naTE re-uploads automatically. It handles both direct-save editors like vim and nano and atomic-rename editors like VSCode and gedit transparently. The remote authentication context is reused — no second login, no extra credentials.

An architecture that stays maintainable.

naTE is a deliberate exercise in clean architecture for desktop software. The boundaries between domain logic and UI are explicit and enforceable.

The application uses ports-and-adapters (hexagonal) architecture. The headless core — terminal parsing (src/parser/), document model (src/document/), session management (src/session/), and transport backends (src/transport/) — has zero dependencies on the wxWidgets presentation layer. The UI is one implementation of the presentation layer and is, in principle, swappable.

The parser is a state machine written from spec, not generated from a grammar tool. The document model is a 100,000-line scrollback structure with separate column-width and viewport tracking. The session layer abstracts over local PTYs, SSH connections via libssh2, and serial devices behind a unified interface. Persistence goes through a thin JSON repository (src/db/) so the storage format can change without touching business logic.

The build is plain CMake driven by Ninja, with preset configurations for debug and release. wxWidgets, libssh2, and nlohmann/json are fetched automatically by CMake at configure time — no system-level dependency management beyond GTK 3 dev headers, OpenSSL, and a C++20 compiler. CI runs on GitHub Actions, producing AppImage artifacts on release.

Stack at a glance

LanguageC++20 (98%+)
UIwxWidgets (GTK 3)
Networklibssh2
ParserHand-written VT100
PersistenceJSON (nlohmann)
BuildCMake + Ninja
TestsCatch2
CIGitHub Actions
DistributionAppImage
ArchitecturePorts & Adapters
LicenseGPL v3

Roadmap.

Features currently in design or under development. Suggestions, issues, and pull requests welcome at the GitHub repository.

SSH

Local port forwarding (-L)

Forward a local port through an SSH connection to a remote host.

SSH

Remote port forwarding (-R)

Expose a local port on the remote host through the SSH tunnel.

Try naTE.

Releases are published on GitHub as a single Linux AppImage — no installation required. Make it executable and run it. Source is freely available under GPL v3; build-from-source instructions are in the repository README.

Linux naTE-x86_64.AppImage
← See naTE in the context of my full work