- Go 99.6%
- JavaScript 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Three bugs, all from the same place: a remote pane's facts were reaching the verbs and not the clients. The machine was wiped on the first client sync. Every other daemon-owned per-window field is carried over by window id when a client sync omits it, because a client rebuilds the window set from what it draws and says nothing about any of them. I added Host to WindowState and did not add it to that list, so the first push from a client cleared it. Everything downstream then read the pane as local: the rail stopped naming the machine, and the file section asked this machine for a directory that is on another one. Which panes still showed a machine depended on when each last synced, which is why it looked inconsistent rather than broken. The directory never reached the client at all. The live facts, the title an application set and the directory its shell is in, were filled into the snapshot in GetState and nowhere else. A verb reads through GetState so `tuios list-windows` reported the directory, while the client drawing that same pane was pushed a snapshot without it. Local panes hid this completely: a shell that announces over OSC 7 reaches the client through its own emulator, so only a pane whose shell says nothing went without, and those are exactly the panes on another machine. The fill now runs on every snapshot that leaves the session. And the answer was cached before it existed. A remote pane's directory is fetched from the far machine in the background, so the push that created the window ran before the reply and cached an empty read for a second. The push that followed the reply then repeated that empty answer. The cache is dropped before publishing. A remote pane's directory changing now publishes, which it has to: nothing about the session changes when a shell elsewhere runs cd, so no mutation happens and no push follows, and the directory is on the snapshot clients are given. A local pane never needed this because its shell announces to every client directly. Each fix has the test that targets it, and each fails without it. The end-to-end one drives a real client against a second daemon over the link and reads the file section, because no part of this chain could be checked from either end alone. |
||
| .github | ||
| assets | ||
| clienttests | ||
| cmd | ||
| docs | ||
| e2e | ||
| examples | ||
| integrations/claude-code | ||
| internal | ||
| nix | ||
| pkg | ||
| scripts | ||
| skills | ||
| .dockerignore | ||
| .envrc | ||
| .gitattributes | ||
| .gitignore | ||
| .goreleaser.yml | ||
| .markdownlint.json | ||
| AGENTS.md | ||
| CITATION.cff | ||
| Dockerfile | ||
| flake.lock | ||
| flake.nix | ||
| FUNDING.yml | ||
| go.mod | ||
| go.sum | ||
| install-web.sh | ||
| install.sh | ||
| LICENSE | ||
| README.md | ||
| SECURITY.md | ||
| tuios.nix | ||
TUIOS is a modern terminal multiplexer and window manager built with Go. It provides a vim-like modal interface with multiple terminal panes, workspaces, BSP tiling, kitty graphics protocol support, and a command palette - all running inside your existing terminal.
Built on the Charm stack (Bubble Tea v2, Lipgloss v2), TUIOS features event-driven rendering for near-zero idle CPU usage, flicker-free kitty image passthrough, and comprehensive keyboard/mouse interaction.
Documentation
Full documentation is available at tuios-docs (hosted) or in the docs/ folder.
Quick Links
- Getting Started - Install and first session
- Keybindings - Default keys and how to rebind them
- BSP Tiling - Tiling with preselection and split control
- Layout Modes - BSP, master-stack and scrolling layouts, aggregate view, multifocus
- Configuration - Customize keybindings, themes, and behavior
- Hooks - Run shell commands on window and session events
- Themes - Built-in themes and custom theme JSON
- Glyph sets - The characters the chrome is drawn with
- CLI Reference - All command-line options
- Tape Scripting - Automate workflows
- Sessions - Daemon mode, attach/detach, and what survives
- Control Protocol - JSON verb protocol for driving the daemon
- Architecture - Technical design
Table of Contents
Installation
Package Managers
Homebrew (macOS/Linux):
brew tap Gaurav-Gosain/tap
brew install tuios
Arch Linux (AUR):
yay -S tuios-bin
Nix:
nix run github:Gaurav-Gosain/tuios#tuios
Other Methods
# Quick install script (Linux/macOS)
curl -fsSL https://raw.githubusercontent.com/Gaurav-Gosain/tuios/main/install.sh | bash
# Go install
go install github.com/Gaurav-Gosain/tuios/cmd/tuios@latest
# Docker
docker run -it --rm ghcr.io/gaurav-gosain/tuios:latest
GitHub Releases - Pre-built binaries for all platforms.
Updating. If you installed with the quick install script or a release
binary, tuios update fetches the newest release and puts it in place
(tuios update --check just reports). Everything else has a package manager
that owns the binary, so use that instead; tuios update detects which you have
and prints the right command rather than overwriting it.
Requirements: A terminal with true color support. Kitty graphics and sixel support recommended (Ghostty, Kitty, WezTerm).
Features
Core
- Multiple Terminal Panes - Create, resize, drag, and organize terminal sessions
- 9 Workspaces - Independent workspace isolation with instant switching
- Modal Interface - Vim-inspired Window Management and Terminal modes
- Command Palette - Fuzzy-searchable action launcher (Ctrl+P)
- Launcher - Fuzzy search everything on
$PATHplus your installed desktop apps (Alt+Space), ranked by what you actually run. Enter starts it; Tab opens a shell with the command typed but not entered, so you can add arguments. App icons are drawn where the terminal supports kitty graphics. - Pane Zoom - Fullscreen any pane with z (WM mode) or Prefix+z. Shared borders hidden when zoomed, dockbar shows Z indicator.
Tiling
- BSP Tiling - Binary Space Partitioning with spiral layout
- Scrolling Layout - niri-style columns on an infinite horizontal strip (docs)
- Master-Stack Layout - One master pane with the rest stacked beside it
- Smart Auto-Split - Aspect-ratio-aware splitting (opt-in)
- Shared Borders - tmux-style separator lines between panes (
--shared-borders) - Preselection - Control where the next pane spawns
- Equalize Splits - Reset all splits to balanced ratios
Scrollback & Copy Mode
- Vim-Style Copy Mode - Navigate 10,000-line scrollback with hjkl, search with
/, yank withy - Mouse Wheel Scrollback - The wheel scrolls history with no mode entered; typing or reaching the bottom returns to live output
- Interactive Scrollbar - Click or drag the right border to jump to scroll position
- Selection Auto-Scroll - Drag selection above/below pane to scroll
- Scrollback Browser - OSC 133-aware command/output block navigation
- Scroll Position Indicator - Shows offset/total on the bottom border
Graphics & Protocols
- Kitty Graphics Protocol - Full image rendering with flicker-free video playback.
mpv --vo=kittyworks (both shm and base64), and youterm works. - Sixel Graphics - Sixel image passthrough (experimental, no pixel-level clipping yet)
- Kitty Keyboard Protocol - Progressive enhancement (CSI u) with push/pop/query support. Fish 4.x compatible; Shift+printable bypasses the protocol and sends text directly.
- Synchronized Output - Mode 2026 prevents screen tearing
- Shared Memory Support -
t=spassthrough for mpv--vo-kitty-use-shm - Animation Frames - A guest's
a=fframe edits are forwarded to the host, so a program that patches its own image costs a rectangle instead of a whole bitmap. TUIOS also patches guests that only retransmit. Panes are told whether the host carries frame edits throughTUIOS_KITTY_ANIMATION, because the host's reply is not relayed back into the pane and a guest cannot find out for itself. - Terminal Queries - OSC 4 palette, OSC 10-12 colors, CSI 14/16/18t sizing, DA1/DA2
- Experimental - Kitty text sizing protocol (OSC 66) - basic passthrough works but has known issues with scrollback and window repositioning
- Kitty Animation Protocol - Frame transmission, composition, and control (a=f, a=a, a=c), with damage-patch streaming for animated guests
Session Management
- Daemon Mode - Persistent sessions with detach/reattach (like tmux)
- Session Resurrection - Sessions come back after a daemon restart or reboot with their structure and working directories (docs)
- Session Switcher - In-app session list (Prefix+S)
- Layout Templates - Save/load window arrangements with working directories and startup commands
- Layout CLI -
tuios layout list,tuios layout delete,tuios layout export
Automation
- Tape Scripting - DSL for recording and replaying terminal workflows
- Tape Recording - Record live sessions (Prefix+T r)
- Headless Execution -
tuios tape execruns a tape against a running daemon session - Layout Export - Convert layouts to tape scripts for sharing
Discovery & Navigation
- Which-Key Popup - Hold the prefix key to see the chords available (docs)
- App Launcher - Alt+Space runs anything on
$PATH, frecency-ranked, with desktop-entry names and icons - Keybind Manager - Prefix+k in-app, or
tuios keybinds doctorandtuios keybinds explain <key>from the shell - Aggregate View - Searchable list of every window across every workspace, with previews (docs)
- Multifocus - Broadcast typing to several panes at once,
Ctrl+Shift+click to select (docs)
More
- Showkeys Overlay - Display pressed keys for presentations
- Customizable Keybindings - TOML configuration with Kitty protocol support
- Hooks - Run shell commands on window create, close and focus events (docs)
- Mouse Support - Wheel scrollback, drag-to-select with copy on release, double-click word and triple-click line, window drag, resize, scrollbar
- SSH Server Mode - Remote terminal multiplexing
- Web Terminal Mode - Browser-based access (separate
tuios-webbinary) - Themes - Bundled themes plus custom themes from JSON (docs)
Quick Start
tuios # Launch TUIOS
tuios --show-keys # Launch with key overlay for learning
tuios --standalone # Launch without the daemon, for this run only
tuios attaches to a daemon-backed session, so the session outlives the
terminal window it started in. New panes are tiled. See
SESSIONS.md to turn either off.
Essential Keys
| Key | Action |
|---|---|
| Ctrl+P | Command palette - search and run any action |
| Alt+Space | Launcher - search and start a program (Enter runs it, Tab types it out) |
| n | New pane (Window Management mode) |
| i / Enter | Enter Terminal mode |
| Prefix+Esc or Alt+Esc | Back to Window Management mode (a bare Esc goes to the shell) |
| Prefix+d | Detach in a daemon session, otherwise back to Window Management mode |
| z (WM) or Prefix+z | Toggle pane zoom (fullscreen) |
| Prefix+Space | Toggle BSP tiling |
| Prefix+[ | Enter copy mode (vim scrollback) |
| Prefix+S | Session switcher |
| Prefix+L then l/s | Load/Save layout template |
| Prefix+? | Help overlay |
| Prefix+q | Quit |
The prefix key is Ctrl+B by default (configurable).
Daemon Mode
tuios new mysession # Create persistent session
tuios attach mysession # Reattach
tuios ls # List sessions
tuios kill-session mysession # Kill session
Layout Templates
# In-app: Ctrl+B, L, l to load / Ctrl+B, L, s to save
# Or via command palette: Ctrl+P → "Save Layout" / "Load Layout"
# CLI:
tuios layout list # List saved layouts
tuios layout delete mysetup # Delete a layout
tuios layout export mysetup # Export as tape script
Configuration
tuios config edit # Edit config in $EDITOR
tuios keybinds list # View all keybindings
See Configuration Guide for all options including show_clock, show_cpu, show_ram, shared_borders, window_button_style, window_button_position, custom themes, and keybinding customization.
Architecture
TUIOS follows the Model-View-Update pattern on Bubble Tea v2. For details, see Architecture Guide.
Key design decisions:
- Event-driven rendering - PTY reader goroutines signal bubbletea via a buffered channel. No fixed-rate ticking for terminal content.
- Kitty graphics passthrough - Image IDs are reused across frames for flicker-free video. Output is batched with the render cycle and wrapped in mode 2026 sync.
- BSP tiling - Binary space partitioning tree with configurable schemes (spiral, smart split). Shared borders mode overlaps window rects and draws separator lines as a separate layer.
- Copy mode - Full vim navigation over scrollback. Wheel scrolling and mouse selection borrow the same machinery through an implicit session that presents as nothing at all, plus scrollbar interaction and selection auto-scroll (timer-based continuous drag scrolling).
Core Components:
- Window Manager (
internal/app/os.go) - Central state, workspaces, overlays - Terminal Emulation (
internal/vt/) - ANSI parser with scrollback, kitty/sixel graphics, kitty keyboard protocol, OSC 133 - Rendering (
internal/app/render.go) - Layer composition, viewport culling, graphics batching - Input (
internal/input/) - Modal routing, 100+ configurable keybindings, mouse handling - Kitty Passthrough (
internal/app/kitty_passthrough.go) - Flicker-free image forwarding with ID reuse and sync output
Performance
- Event-driven rendering - Zero CPU at idle. Renders only when PTY data arrives or interaction occurs.
- Kitty graphics - Flicker-free via image ID reuse. Tearing-free via mode 2026 sync + render cycle batching.
- Fast unfocused render - Unfocused panes use emulator's built-in
Render()instead of cell-by-cell. - Style caching - LRU cache with sequence-based change detection (40-60% allocation reduction).
- Viewport culling - Off-screen and minimized panes skip rendering.
- Memory pooling - Pooled strings, buffers, and styles.
Development
git clone https://github.com/gaurav-gosain/tuios.git
cd tuios
go build -o tuios ./cmd/tuios
./tuios
To install a local build on your PATH instead, ./scripts/install.sh builds
and installs into ~/.local/bin. It defaults to the
ghostty emulator backend; ./scripts/install.sh pure
installs the pure Go one, and tuios --version says which is installed.
go test ./... # Run tests
go vet ./... # Lint
staticcheck ./... # Static analysis
Star History
License
MIT License - see LICENSE for details.


