Tracks upstream Wave Terminal and adds a curated set of features — a real Git view, inline terminal images, remote file transfer, cross-machine config sync, desktop notifications, and live UI theming — each reimplemented cleanly on Wave's own architecture and built to work locally and over SSH alike.
- Git view — branch switcher, staged/unstaged/untracked file lists, inline diff, commit &
push — all running over
wshremote, so it works on the local machine and remote SSH hosts. The branch field takes as much of the toolbar as it needs (longfeat/…names stay readable), and the switcher shows the branch you are on in bold. - Per-hunk stage / unstage — stage or revert individual hunks straight from the diff, powered
by
git apply --cached(git does the splitting, so patches always apply cleanly). - Multi-file review mode — a Review action walks every changed file in one flow; F7 / Shift+F7 to jump between files, Esc to exit.
- Push authentication — HTTPS push prompts for a username / token, stores it in Wave's
secret store (host-keyed), and supplies it to git via a temporary
GIT_ASKPASShelper — the token never touches a command line.
- Hard-wrap aware copy & links — TUI programs (Claude Code, tmux,
less, …) print real newlines at the terminal width, which used to shred copied text into width-sized lines and cut URLs in half. Copying now re-joins those hard-wrapped lines (settingterm:copyunwrap, with a Copy Raw escape hatch in the context menu), and a URL split across lines is clickable again, tooltip included. - Inline images — Sixel and the iTerm2 inline-image protocol (IIP) render pictures right in
the terminal. Nothing renders until something emits an image, so install a producer
(
brew install chafa,apt install chafa, …) and usechafa -f sixel—chafa -f iterm2wraps TIFF, which browsers cannot decode. - Remote file transfer — paste or drop an image/file into a remote SSH terminal and it's uploaded to that host, with the remote path pasted back (upload indicator included).
- Non-blocking SSH auth prompts — password / passphrase / keyboard-interactive prompts appear as an overlay scoped to the connection that asked, shown only on the tabs using it, so the rest of the UI stays fully interactive. Answered prompts dismiss everywhere at once, and a prompt raised during startup or a wake-time reconnect isn't lost before a window is listening.
- Resume a Claude session — a terminal remembers the Claude Code session run in it; once that session stops, a Resume session button in the block header brings it back in one click. Tracked per block, so several terminals in one repo each keep their own, and it follows a resume done from inside claude — including one that outlived a Wave restart, where it used to hand back the session from before the restart. Nothing to configure on the Claude side.
- Remote sessions survive sleep — closing the lid on an SSH session no longer freezes the process on the far end for hours waiting on a TCP keepalive; the stall is bounded to seconds, and output produced while you were away is kept on disk and replayed when you reconnect.
- Tab activity indicator — an output-driven "working" spinner and a "done" badge on tabs, so a
glance tells you which terminal is busy. Long-running dev servers (
shopify theme dev,vite,rails server,npm run dev, …) are recognized and leave the tab clean instead of spinning forever. AI agents spin while they work and flip to a ✓ the moment their turn ends — even in setups where the agent never rings the terminal bell and no lifecycle hook is wired. - Badge rotation —
wsh badge --rotation <deg>spins a badge icon for animated status cues.
- Config sync — a last-writer-wins merge engine (
wsync) that converges settings across machines over WebDAV or a credential-free local-folder mode (drop it in a Nextcloud / Drive folder). Background scheduler, a Sync now action, and a native folder picker. - Session save / load — snapshot all windows, tabs and block layouts to the same sync
transport and restore them on another machine — nested splits, sizes, focus and window
positions survive exactly. Block locations travel machine-neutrally (named path roots +
~-form paths), so a layout saved on Linux opens the right folders on Windows or macOS. - Duplicate a tab — right-click a tab → Duplicate: a copy opens immediately to its right with the same arrangement and the same block settings (cwd, connection, theme), and fresh shells. Nested splits survive intact.
- Undo close tab — Cmd/Ctrl+Shift+T reopens the tab you closed last, back at the position it was closed from, with its split layout and its terminal scrollback. Right-click a tab for Reopen Closed Tab to pick an older one by name. Upstream deletes a closed tab outright; here the last 10 per workspace are kept for a week. The shells themselves are gone — but a reopened terminal starts in the same directory, and its Claude session is still resumable.
- Folder bookmarks ("projects") — bookmark folders and reach them from the Files view, the connection dropdown, and a Connections & Projects settings panel.
- Desktop notifications — get a system notification when a long command finishes while the
window is unfocused; plus an agent-waiting state that flags a tab as "waiting for you"
across Claude, Gemini & Codex — driven by agent hooks (
wsh agentstate) with a process-tree fallback, and sticky until you actually answer (an idle agent's TUI repaints can't clear it). - Auto-updates from this fork's releases — the built-in updater runs against this repo's
GitHub Releases on a dedicated
pjchannel: new fork versions download in the background and install on restart (on Linux the app relaunches itself once the old instance is really gone). Apj.Nbadge in the tab bar always shows which build you're on — click it for the full version.
- UI theme picker — app-wide themes (Dracula, Dark+/Light+, One Dark, Monokai, Nord, Solarized …) switchable live from the block gear menu, with a full Themes editor and live color pickers; the terminal palette follows the active theme.
- Named tab flags — Finder-tags-style labeled, colored flags you can pin to a tab; edit a flag's color and every flagged tab updates live.
- Polish — configurable default terminal font size, a live-synced GUI/JSON settings split, and refined light-mode theming across the tab bar, sidebar, AI panel, and system graphs.
Under the hood — reliability fixes that keep all of the above solid
- Current Electron — the fork runs on Electron 44 (Chromium 152 / Node 24); upstream is still on Electron 41, which went end-of-life in August 2026. Requires macOS 13 (Ventura) or newer.
- Ports of stalled upstream PRs — upstream's
mainhas not moved since July 2026 while ~40 community pull requests sit open, so the fork cherry-picks the useful ones: SSH agent forwarding, configurable keybindings (keybindings.json), tmux auto-attach on remote blocks, an Excalidraw widget, file/document bookmarks in the preview, restore-all-windows, and a fix forCtrl+[sending the wrong control byte on non-US keyboard layouts. See FORK.md for the list and the fork-side deviations. - Correct icon in the Linux dock — GNOME identifies a window through the systemd scope
Chromium moves itself into, which Electron names after the app rather than after the installed
.desktopentry; the fork pins that name, so the window docks onto its own launcher instead of appearing as a second, blank icon. - Background tabs cost (almost) nothing — background tab renderers are now actually hidden
and Chromium-throttled instead of running at full speed off-screen: a flooding terminal drops
from ~17% renderer CPU to under 1% the moment its tab goes to the background, and webview-heavy
tabs (Jira, GitHub…) stop burning CPU entirely. Made possible by moving command-done /
agent-waiting notifications into the electron main process (badges were already backend-driven),
so nothing depends on a live background renderer anymore. Webview guests — which Electron
cannot throttle at all natively — get an injected polyfill that parks
requestAnimationFrameand clamps timers while their tab is hidden (measured 120 rAF/s → 0), with audible pages exempt so background music keeps playing; git status polling, sysinfo plot rebuilds, and the tab-bar spinner's repaint rate are similarly gated. - No more grey window — coming back from a minimize, a workspace switch or a locked screen
could leave the active tab painted as a flat grey rectangle until you switched tabs. The
compositor surface gets evicted when the OS unmaps the window, and a leftover
backgroundThrottling: falseon tab views suppressed the hide/show bookkeeping Chromium uses to ask for a fresh frame — so nobody ever requested one. Throttling now switches on as soon as a tab is on screen (visible tabs are never throttled anyway), and windowshow/restoreplus screen-unlock and system-resume force a repaint as a backstop. - Terminal write batching — streaming output (an agent thinking, a build log) coalesces into ≤30 renders/s, cutting a visible streaming terminal from ~40% to ~13% renderer CPU without adding any typing latency.
- Terminal escape hygiene — dark/light color-scheme reports (
DECSET 2031subscribers like Claude Code) fire only on real theme changes, and a restarted shell clears the stale subscription — no more literal997;1njunk typed into the prompt when switching windows. - Git panel auto-refresh — explicit RPC timeouts plus a client-side settle timer keep the 2s status poll alive across sleep/wake and reconnects, with a toolbar warning when refresh fails; history gets an All | Branch switch showing only the current branch's own commits.
sudokeeps working after an update (Linux) — Electron's post-update relauncher starts the new app through Chromium's process launcher, which stampsPR_SET_NO_NEW_PRIVSon it. The flag is inherited by wavesrv, by every terminal below it and by everything those terminals run, and it can never be cleared in a running process — so from the first auto-update on,sudoand every other setuid binary failed in every Wave shell. The fork restarts itself as a transientsystemd --userservice instead, the one launch method the flag does not survive.- WPS broker — user-input events are buffered so a password prompt fired during startup or a reconnect is never lost, and locked route-matching was split to remove a reentrant-lock deadlock.
- SSH — fork-side reconnect / sleep-wake robustness on top of upstream's handling: a send timeout that stops a sleeping laptop from freezing the remote process, disk-backed scrollback across a disconnect, overlay hysteresis so brief blips don't flash a banner, retries that give up on permanent failures instead of hammering, and one password prompt at a time per window.
- Terminal — rendering restored after sleep/resume, term-file corruption fixed on stream supersession and sequence gaps, a stream-reader goroutine leak closed on reconnect, background sessions get resize events, and native copy keeps ESC while trimming trailing spaces.
- Features that landed upstream in the meantime (SSH port forwarding, auto-reconnect, the base git RPCs) are intentionally not re-added — this fork builds on top of them rather than around them.
Grab the latest build from Releases.
| Platform | Notes |
|---|---|
| macOS (arm64 / x64) | .dmg / .zip, signed with a Developer ID and notarized — opens normally, no right-click dance. macOS 13+. |
| Linux | .deb, .AppImage, .rpm, and .pacman. |
| Windows | NSIS installer (.exe) plus a portable .zip. |
Want to run this fork side by side with a stock Wave? Each release also ships a Wave (Dev) build with its own app identity and data directory — install both without conflict.
Prerequisites: Go, Node, Task, and Zig (for the wsh
cross-compile).
task init # one-time: install dependencies
task dev # run the dev app with hot reload
task package # build an installer for the current OS → ./maketask package builds for the OS it runs on, so a full release is produced per-platform. See
BUILDING.md for per-OS detail.
mainmirrors upstreamwavetermdev/wavetermand never carries fork work.releaseis the integration branch — everything here is built and shipped from it.- Each feature lives on a focused
feat/*branch, kept as a clean, rebaseable series.
Deeper notes on what the fork adds and how it's maintained live in FORK.md; day-to-day build/release detail is in BUILDING.md.
Apache-2.0, same as upstream Wave Terminal — see LICENSE. A personal, unofficial fork, not affiliated with or endorsed by Command Line Inc.