github Gaurav-Gosain/tuios v0.9.0

4 hours ago

tuios 0.9.0 is a big one: about 490 commits since v0.8.5. Any program can now tell tuios what it is doing, your config can live in more than one file, and yanks stay around as paste buffers. You can take a session for yourself with attach -d, your ssh agent follows you into your panes, and images show up even on a terminal with no graphics at all.

tuios-v0.9.0-hero.mp4

Before you upgrade, read Upgrading. The daemon protocol gained new messages, so restart the daemon after you install.

The full list is at tuios.dev/releases.

Watch

Six short clips, narrated by Tilly. Click one to play it, or watch them all with captions on the release page.

Program status
Program status
Split the config
Split the config
Paste buffers
Paste buffers
One client per session
One client per session
Your ssh agent follows you
Your ssh agent follows you
Images without graphics
Images without graphics

Install

brew install tuios                     # Homebrew (macOS, Linux)
yay -S tuios-bin                       # AUR (tuios-web-bin for the web server)
nix run github:Gaurav-Gosain/tuios     # Nix
curl -fsSL https://raw.githubusercontent.com/Gaurav-Gosain/tuios/main/install.sh | bash
go install github.com/Gaurav-Gosain/tuios/cmd/tuios@v0.9.0
docker run -it --rm ghcr.io/gaurav-gosain/tuios:v0.9.0
  • A binary installed by the script or from an archive updates with tuios update.
  • The ghostty build on Homebrew. brew install gaurav-gosain/tap/tuios-ghostty installs tuios built with libghostty-vt, on Linux. It installs a binary with the same name as the tuios formula, so run brew uninstall tuios first. On macOS, take the tuios-ghostty_*_Darwin_* archive from this page.
  • The tuios cask is deprecated. brew install tuios gives you the homebrew-core formula. If you installed the cask from my tap, move to the formula with brew uninstall --cask tuios && brew install tuios.

Highlights

  • Program status (OSC 7501). Any program in a pane can report that it is working, blocked, done or failed, with the Program Status Protocol. A build, a deploy script or brew then shows on the rail and in the Inbox like an agent, with no hook or plugin (#546). Docs: Program Status.
  • Split the config. include = [...] in config.toml and a config.d folder let you keep machine-only settings, such as hosts, out of your shared dotfiles. A read-only file from Nix or home-manager stays read-only, and the settings page writes its changes to a file it may change (#547, asked for in #518). Docs: Split the Config.
  • Paste buffers. Each yank is kept as a paste buffer, as in tmux. Ctrl+B ] pastes the newest one and Ctrl+B # lists them all. list-buffers, set-buffer, paste-buffer and the tmux shim use the same buffers (#550, asked for in #514). Docs: Paste buffers.
  • One client per session. tuios attach -d NAME detaches every other client as you attach, as tmux attach -d does. tuios detach-client detaches clients without an attach, and [daemon] single_client = true makes every attach work like -d (#551). Docs: Detaching other clients.
  • Your ssh agent follows you. With [daemon] ssh_agent = "follow", new panes use the ssh agent of the client you attached from, and they move with you when you attach from another machine. This also works through a remote host, when your ssh link forwards the agent (#552). Docs: SSH Agent.
  • Images without graphics. On a terminal with no sixel or kitty graphics, such as kmscon, the Linux console or a plain SSH client, tuios now draws pane images with block glyphs. kmscon gets octants, the Linux console gets half blocks, and everything else gets quadrants (#548). Docs: Images Without Graphics.
  • Agents and the Inbox.
    • Crush permission prompts wait in the Inbox like the others (#320). Docs: herdr Compatibility.
    • tuios checkpoint saves an agent's work tree at the end of each turn, and puts it back when you ask. Docs: Checkpoints.
    • tuios ship commits, merges, pushes and opens the pull request for a worktree. The rail shows the pull request and its checks. Docs: Ship.
    • The Inbox can send push notifications through ntfy, Pushover or a webhook. Try it with tuios notify test. Docs: Push Notifications.
    • [agents] enabled = false turns off every agent feature, if you want a plain multiplexer (#387). Docs: Turn Off Agent Features.
    • The settings page has an Agents tab that installs and updates the harness integrations (#474).
  • The rail. The sidebar is now shared by every client of a session, and the panes retile when you hide it (#350). You can add your own section fed by a command (#419), copy a folder's path, and turn on session numbers with appearance.sidebar.show_numbers (#544). Docs: Session Rail.
  • Find a pane. Ctrl+B / opens a navigator over every pane in every session, on this machine and on your hosts. Search names, folders, commands and the text on screen, with a live preview in the pane's own colours (#473, #505). Ctrl+B Q labels the panes so that you can jump to one with a key (#472). Docs: Finding a pane.
  • herdr. tuios now hosts herdr plugins: their actions go in the palette and their panes open in tuios (#435). The herdr socket also answers the pane, agent and client methods that plugins still missed (#433). Docs: herdr Compatibility.
  • tmux shim. The shim accepts command prefixes, reads the tmux 3.4 format language, and adds wait-for, display-popup, run-shell, if-shell, pane and window moves, buffers, the environment and detach-client. About 90 format cases are checked against a real tmux. Docs: tmux Shim.
  • Speed. Panes draw on one frame clock, so an animation at 120 Hz shows at 120 Hz. max_fps now goes up to 240, or "auto" to follow your display (#407, #520). Copy-mode search went from 150 ms to 11 ms a key, an idle client uses less than half the CPU it did, and the daemon gives memory back after you close a lot of panes. Docs: max_fps.

More new things

Panes, layouts and workspaces

  • Neovim navigation. The same keys move between nvim splits and tuios panes, with appearance.nvim_navigation (#318). Thanks to @Tim4c.
  • Borderless zoom. appearance.zoom_borderless makes a zoomed pane fill the whole pane area with no border (#531).
  • Splits over ssh. split_ssh_horizontal, split_ssh_vertical and new_window_ssh open the new pane on the machine the pane is ssh'd into. appearance.new_window_follow_ssh makes the normal split keys do it (#471).
  • Last pane. last_pane (; in window mode) flips between the last two panes (#469). Thanks to @davidreuss.
  • Session keys. switch_session_1 to switch_session_9, and rename_workspace (#464). Thanks to @davidreuss.
  • Empty workspaces. When the last pane on the workspace closes, tuios goes back to the workspace you showed before (#427). [workspaces] new_window_when_empty = true opens a pane when you switch to an empty workspace (#485).
  • Scrolling layout. A column can fill the whole screen (#402). Thanks to @alnav3.

Dock

  • Compact dock. appearance.dock_compact draws the dock as one row (#461).
  • Rounded pills. The dock pills are rounded by default (#458).
  • Mode icons. dock_mode_icon_window, dock_mode_icon_terminal and dock_mode_icon_tiling set the mode pill icons (#529).
  • Labels. appearance.dock_workspace_label_max caps a workspace label, and a minimized pane keeps its name while there is room (#499). Thanks to @davidreuss.
  • Mode keys. The keys of the current mode show as a legend in the dock.

Sessions, hosts and the CLI

  • Sessions from the CLI. tuios new --cwd DIR starts a session in a folder, and tuios switch-session [HOST:]NAME moves your client to another session (#457).
  • Clients. tuios list-clients lists the clients of the daemon, and a client-session-changed event says when one switches (#410). Thanks to @zer0ken.
  • Hosts. tuios hosts sync installs this version on every host (#431). --start starts the daemon on a host (#450). A Tailscale SSH check now says "sign in" and opens the page (#465, #513).
  • Explorers. tuios help -i, tuios config browse and tuios keybinds browse let you search the commands, the options and the keys (#436).
  • Keys reload. A key you save in config.toml works at the next key press, with no restart (#454). Thanks to @davidreuss.
  • Scripts. More list commands take --json, the help is accurate, and errors say what to do (#430). tuios close-window is new (#438).
  • Tapes. A tape can run any action and wait on conditions, and tape exec plays a tape to the end and reports the first failure (#437).
  • Launcher. launcher.gui_command starts graphical desktop entries (#346).
  • MCP. The MCP server speaks protocol versions 2025-11-25 and 2026-07-28.

Copy mode and links

  • Links. Ctrl+click opens a link, and OSC 8 links reach your outer terminal. Docs: Links.
  • Home and End go to the start and end of the line in copy mode (#528).

Terminal emulation

  • tuios answers XTVERSION, DA3, XTGETTCAP and DECRQSS, and supports xterm's modifyOtherKeys, the 1005 and 1015 mouse encodings and the title stack.
  • Each pane gets its own key encoding, with releases, repeats and lock state as kitty sends them (#377).
  • A pane that turns on focus reporting is told when it has focus (#337).
  • A graphics pane is paced to its fastest client (#345).

Fixes

  • A Mac config on Linux. opt+ keys now work on every platform, and one bad key no longer makes tuios drop the whole file (#559). This fixes #556.
  • Bare attach. tuios attach with no name goes to the session you used last (#495). Before, it picked one at random. This fixes #486.
  • Clipboard. A pane's OSC 52 copy now uses pbcopy and the other native tools when the terminal cannot take it (#494). Thanks to @juancely.
  • OpenCode V2. The OpenCode integration works with OpenCode V2 (#526). Thanks to @j4ng5y.
  • NetBSD. tuios builds on NetBSD again (#490). Thanks to @ci4ic4.
  • Dock meters follow a live settings change (#525). Thanks to @drawde-nadroj.
  • Zoom retiles when the canvas is not active (#398). Thanks to @fonnesbeck.
  • A stuck client. A client wedged by a signal now exits instead of hanging (#207). Thanks to @masshirodev.
  • The pointer shape goes back to normal when your terminal loses focus (#507). Thanks to @davidreuss.
  • The skill parses in strict YAML readers (#481). Thanks to @chenxin-yan.
  • Folders. A new window opens in the folder your shell reports with OSC 7 (#497). A session keeps its start folder across a restart (#482).
  • Keys. Shift+Up and Shift+Down reach nvim, less and htop. send-keys keeps capital letters and uses the encoding the pane asked for (#444).
  • Layouts. Master-stack splits stay even across a retile (#403, #405). Shared borders hold through a resize and in the scrolling layout (#470).
  • Copy mode keeps the whitespace a copy covers, and leaves out the pad of a wide character at a wrap (#527).
  • Restore. One pane's screen is no longer painted into another while a session restores. Daemon replies now match their request.
  • Hidden workspaces. Panes on a hidden workspace close and stream as they should (#384).
  • Popups close when their command exits, in any session (#483).
  • Config saves are atomic, so a reload never reads a half-written file (#409).
  • The which-key menus list the keys you actually have (#530).
  • The dock CPU meter works on Windows and the BSDs (#560).
  • Crashes. The status line and a theme with no cursor colour no longer crash (#378).
  • Windows paths. The rail reads MSYS2 and Cygwin folders (#416).

Security and robustness

  • Typing over a host link. A pane on one machine can no longer answer a prompt on another machine unless that machine's link policy allows respond (#389).
  • Daemon memory. The daemon checks a frame's size before it reads the frame, and all frames and requests share one read budget. A process that can reach the socket can no longer make the daemon hold a gigabyte (#557, #498).
  • Paste buffers have an owner. A pane without admin sees only its own buffers, never yours.
  • herdr plugins wait for you before they run, and only a pane with admin reads the plugin log.
  • Dock components. Their output is bounded, and unsafe characters are removed (#404).
  • ssh. A followed ssh agent socket must pass the same folder checks as OpenSSH. A split that follows ssh keeps only known connection options.
  • ship and checkpoints. ship pushes the commit you allowed, not the branch tip. A restore that would overwrite ignored files is refused. Notifications refuse a redirect to another host.
  • MCP. Tools that change state are no longer marked read-only.
  • Events. tuios subscribe refuses an event type it does not know, instead of printing nothing (#438).
  • No curl. Notifications and tuios update use Go's own HTTP client. tuios no longer needs curl at run time.
  • Fuzzing. Every fuzz target now runs in the nightly job (#503).

Upgrading

Restart the daemon

The protocol gained new messages for detach, session use, the shared sidebar, image glyphs, the ssh agent and request ids. Restart the daemon after you upgrade:

tuios kill-server

This closes every pane in every session, so save your work first. For your remote hosts, tuios hosts sync --restart installs this version and restarts each daemon. An older daemon ignores attach -d, and tuios attach -d warns you when that happens.

Config

  • opt+ is alt+ everywhere. A key such as opt+1 now reads as alt+1 on Linux too, so one config.toml works on a Mac and on Linux. On macOS, opt+ keys work as before.

  • One bad key drops only that key. tuios keeps the rest of the file and shows "N config problems, see the log viewer". Before, one bad key put every setting back to its default.

  • config.toml is sparse. tuios now writes only the keys you changed, so that included files can apply. An older config.toml that lists every key holds every default too, and those keys win over your included files. To clean it, run:

    tuios config prune --dry-run   # see what it removes
    tuios config prune

    It keeps your comments and [startup], and asks before it removes a key that another file sets.

Images

  • chafa, timg and yazi now send sixel on hosts without graphics. tuios tells panes that they can draw sixel and draws the image as glyphs. These tools then send sixel instead of their own text art. To go back to the box, set appearance.image_symbols = "off".

Changed defaults

  • Agent checkpoints are on. At the end of each turn that changes a file, tuios saves the agent's work tree under refs/tuios/checkpoints/ in that repository. To turn it off, set [agents.checkpoints] enabled = false.
  • The dock pills are rounded. Set appearance.dock_pill_caps = false for the flat dock.
  • An empty workspace goes back. When its last pane closes, tuios shows the workspace you used before. Set [workspaces] return_when_empty = false to stay.
  • A bare tuios attach goes to the session you used last.
  • tuios new starts the session in the folder you run it from. Before, it used the daemon's folder.
  • New default keys: Ctrl+B ] pastes a buffer, Ctrl+B # lists the buffers, Ctrl+B / opens the pane navigator and Ctrl+B Q labels the panes. tuios keybinds doctor names any clash with your own keys.
  • Shift+Up and Shift+Down scroll only a pane on the main screen with no mouse mode. A full-screen program gets the keys.
  • Mode keys show as a legend in the dock, not as a message.

For scripts

  • A pane's TERM is now one that this machine has a terminfo entry for. DA1 reports only what the emulator does: 62;22, or 62;4;22 with sixel.
  • Tapes stop at the first failure. tape play exits non-zero after a failed tape.
  • tuios subscribe --types refuses an unknown event type.
  • Typing over a host link into a pane that waits on a prompt needs respond in that host's [hosts] link policy.

Contributors

Thank you to everyone who sent a pull request for this release:

And thanks to everyone who asked for things and reported bugs: @adamcstephens for the config includes (#518) and the ssh agent and single client ideas (#549), @iTerminate for paste buffers (#514), @Smithx10 for the navigator, ssh splits, the compact dock and the xpanes return (#467, #468, #459, #273), @chenxin-yan for the attach and empty workspace reports (#486, #477), and @stonevil for the config report (#556).


Full Changelog: v0.8.5...v0.9.0

Don't miss a new tuios release

NewReleases is sending notifications on new releases.