Keybindings
Every default key in TUIOS for window mode, terminal mode, prefix commands, copy mode and the mouse, grouped by the config section that owns it.
TUIOS has two modes. Window mode is for managing panes. Terminal mode sends your keys to the focused pane. A new session starts in window mode.
The leader key is Ctrl+B. Press it, release it, then press a command key. The leader works in both modes.
To send the leader key to the program in the pane, press it two times in terminal mode. The pane gets the leader that you configured, such as Ctrl+A.
Every table on this page names the config section that holds the binding and the action name to use in it. Every action is rebindable. See Customizing at the end.
Try it live: Learn tuios has you press these keys in the real app, in your browser. Free play has a cheat sheet you can click.
Check your own bindings
This page lists the defaults. tuios keybinds list, tuios keybinds explain <key> and the keybind manager (Ctrl+B k) show what is bound on your machine.
Search every default binding, or read the tables by section below:
319 of 319 actions
[keybindings.global]- Ctrl+POpen the command palette
command_palette - Alt+SpaceOpen the app launcher
launcher
[keybindings.window_management]- worxClose window
close_window - cCopy selection to clipboard
copy_selection - sFocus sidebar
focus_sidebar - ;Back to the previous pane
last_pane - mMinimize window
minimize_window - NMake a session, asking which machine
new_session - nNew window
new_window - Alt+Shift+nNext session
next_session - TabNext window
next_window - Alt+Shift+pPrevious session
prev_session - Shift+TabPrevious window
prev_window - rRename window
rename_window - MRestore all minimized
restore_all - 1Select window 1
select_window_1 - 2Select window 2
select_window_2 - 3Select window 3
select_window_3 - 4Select window 4
select_window_4 - 5Select window 5
select_window_5 - 6Select window 6
select_window_6 - 7Select window 7
select_window_7 - 8Select window 8
select_window_8 - 9Select window 9
select_window_9 - SStart the screen saver now
start_screensaver - pPin or unpin the picture-in-picture view
toggle_pip - zToggle zoom (fullscreen)
toggle_zoom
[keybindings.workspaces]- Alt+Shift+1Move to workspace 1 and follow
move_and_follow_1 - Alt+Shift+2Move to workspace 2 and follow
move_and_follow_2 - Alt+Shift+3Move to workspace 3 and follow
move_and_follow_3 - Alt+Shift+4Move to workspace 4 and follow
move_and_follow_4 - Alt+Shift+5Move to workspace 5 and follow
move_and_follow_5 - Alt+Shift+6Move to workspace 6 and follow
move_and_follow_6 - Alt+Shift+7Move to workspace 7 and follow
move_and_follow_7 - Alt+Shift+8Move to workspace 8 and follow
move_and_follow_8 - Alt+Shift+9Move to workspace 9 and follow
move_and_follow_9 - Alt+1Switch to workspace 1
switch_workspace_1 - Alt+2Switch to workspace 2
switch_workspace_2 - Alt+3Switch to workspace 3
switch_workspace_3 - Alt+4Switch to workspace 4
switch_workspace_4 - Alt+5Switch to workspace 5
switch_workspace_5 - Alt+6Switch to workspace 6
switch_workspace_6 - Alt+7Switch to workspace 7
switch_workspace_7 - Alt+8Switch to workspace 8
switch_workspace_8 - Alt+9Switch to workspace 9
switch_workspace_9
[keybindings.layout]- =Equalize all split ratios
equalize_splits - jFocus the window below
focus_down - kFocus the window above
focus_up - Alt+jPreselect down for next window
preselect_down - Alt+hPreselect left for next window
preselect_left - Alt+lPreselect right for next window
preselect_right - Alt+kPreselect up for next window
preselect_up - }orShift+]Increase focused window height
resize_height_grow - ]Increase focused window height from top edge
resize_height_grow_top - {orShift+[Decrease focused window height
resize_height_shrink - [Decrease focused window height from top edge
resize_height_shrink_top - >orShift+.Increase master width
resize_master_grow - .Increase master width from left edge
resize_master_grow_left - <orShift+,Decrease master width
resize_master_shrink - RRotate split
rotate_split - fFullscreen
snap_fullscreen - hSnap or focus left
snap_left - lSnap or focus right
snap_right - -Split window horizontally (top/bottom)
split_horizontal - |or\Split window vertically (left/right)
split_vertical - JorCtrl+DownSwap down
swap_down - HorCtrl+LeftSwap left
swap_left - LorCtrl+RightSwap right
swap_right - KorCtrl+UpSwap up
swap_up - tToggle tiling mode
toggle_tiling - uUnsnap
unsnap
[keybindings.mode_control]- iorEnterEnter terminal mode
enter_terminal_mode - EscEnter window management mode
enter_window_mode - ,Open settings
open_settings - qQuit
quit - ?Toggle help
toggle_help
[keybindings.system]- BToggle spotlight
toggle_spotlight
[keybindings.restore_minimized]- Shift+1or!restore minimized 1
restore_minimized_1 - Shift+2or@restore minimized 2
restore_minimized_2 - Shift+3or#restore minimized 3
restore_minimized_3 - Shift+4or$restore minimized 4
restore_minimized_4 - Shift+5or%restore minimized 5
restore_minimized_5 - Shift+6or^restore minimized 6
restore_minimized_6 - Shift+7or&restore minimized 7
restore_minimized_7 - Shift+8or*restore minimized 8
restore_minimized_8 - Shift+9or(restore minimized 9
restore_minimized_9
[keybindings.terminal_mode]- Alt+EscExit terminal mode (to window mode)
terminal_exit_mode - Alt+DownFocus the pane below
terminal_focus_down - Alt+LeftFocus the pane to the left
terminal_focus_left - Alt+RightFocus the pane to the right
terminal_focus_right - Alt+UpFocus the pane above
terminal_focus_up - Alt+nNext window (terminal mode)
terminal_next_window - Ctrl+Shift+VorSuper+vorShift+Super+vPaste from the host clipboard
terminal_paste_host - Alt+pPrevious window (terminal mode)
terminal_prev_window - Shift+DownScroll back down toward live output
terminal_scroll_down - Shift+UpScroll into the pane's scrollback
terminal_scroll_up
- caccent
accent - Enteractivate
activate - fagents filter
agents_filter - oagents sort
agents_sort - horLeftcollapse
collapse - jorDowncursor down
cursor_down - korUpcursor up
cursor_up - Escorsexit
exit - lorRightexpand
expand - Ctrl+FSearch files below the folder the sidebar shows
file_search - gorHomefirst
first - ?help
help - 1jump 1
jump_1 - 2jump 2
jump_2 - 3jump 3
jump_3 - 4jump 4
jump_4 - 5jump 5
jump_5 - 6jump 6
jump_6 - 7jump 7
jump_7 - 8jump 8
jump_8 - 9jump 9
jump_9 - xkill
kill - GorEndlast
last - imail
mail - mmenu
menu - <narrow
narrow - nMake a session, asking which machine
new_session - tNew window
new_window - /palette
palette - rrename
rename - JorShift+DownRail: move this session or machine down
reorder_down - KorShift+UpRail: move this session or machine up
reorder_up - TaborShift+Tabsection
section - >widen
widen
- yFiles: copy this file
file_copy - YFiles: copy the path of this file or folder
file_copy_path - aFiles: new file, or a folder with a trailing /
file_create - xFiles: cut this file
file_cut - dFiles: delete this file
file_delete - DFiles: delete for good, with no trash
file_delete_forever - Shift+EnterFiles: edit this text file in a new pane
file_edit - EnterFiles: open this folder, or copy this file's path
file_open - pFiles: paste into this folder
file_paste - rFiles: rename this file
file_rename
- xAgents: drop the newest queued message
agent_cancel_queued - rAgents: reply to the agent
agent_reply - vAgents: review the pane's changes
agent_review - zAgents: snooze the pane's Inbox item
agent_snooze - uAgents: mark the pane's finished turn unread
agent_unread
[keybindings.inbox]- EscorqInbox: close
inbox_close - nInbox: deny the approval or plan with a reason
inbox_deny_reason - JorCtrl+DInbox: scroll the detail down
inbox_detail_down - KorCtrl+UInbox: scroll the detail up
inbox_detail_up - dorDeleteInbox: dismiss the item
inbox_dismiss - jorDownorCtrl+NInbox: next item
inbox_down - fInbox: show one kind, then the next
inbox_filter - gorHomeInbox: first item
inbox_first - EnterInbox: go to the item's pane, or open its mail
inbox_go - GorEndInbox: last item
inbox_last - mInbox: open the whole mailbox
inbox_mailbox - PgDnInbox: ten items down
inbox_page_down - PgUpInbox: ten items up
inbox_page_up - pInbox: pass held mail on to the agent it was for
inbox_pass_on - SpaceInbox: read the prompt here and answer it
inbox_peek - rInbox: reply to the mail
inbox_reply - yInbox: resume the conversation in its pane
inbox_resume - vInbox: review the changes in the item's pane
inbox_review - /Inbox: narrow the list with a selector
inbox_select - SInbox: show or hide snoozed items
inbox_show_snoozed - zInbox: snooze the item, then 1 to 4 for how long
inbox_snooze - uInbox: undo the last dismiss or snooze
inbox_undo - korUporCtrl+PInbox: previous item
inbox_up
[keybindings.inbox_peek]- aInbox prompt: approve
peek_approve - AInbox prompt: approve and do not ask again
peek_approve_always - EscorqorSpaceInbox prompt: back to the list
peek_back - dInbox prompt: deny
peek_deny - EnterInbox prompt: go to the pane
peek_go - rInbox prompt: read the prompt again
peek_read_again - TabInbox prompt: type an answer
peek_type
[keybindings.mail]- EscorqMailbox: back, or close
mail_back - jorDownorCtrl+NMailbox: next thread
mail_down - oMailbox: go to the pane that last wrote
mail_focus_pane - nMailbox: write a new message to an agent
mail_new - EnterMailbox: open the thread, or reply in an open one
mail_open - PgDnMailbox: ten threads down
mail_page_down - PgUpMailbox: ten threads up
mail_page_up - rMailbox: reply in the open thread
mail_reply - korUporCtrl+PMailbox: previous thread
mail_up
[keybindings.prefix_mode]- Ctrl+B/Find a pane in every session and go to it
choose_tree - Ctrl+BQLabel the panes and focus one by its label
display_panes - Ctrl+BFLabel the text on the pane to copy it
hints - Ctrl+BaOpen the app launcher
launcher - Ctrl+B)Next session
next_session - Ctrl+BVPaste the clipboard image as a file path
paste_image - Ctrl+BXClose session and panes
prefix_close_session - Ctrl+BxClose current window
prefix_close_window - Ctrl+BPOpen the command palette
prefix_command_palette - Ctrl+BDEnter debug prefix
prefix_debug - Ctrl+BdDetach, leave running
prefix_detach - Ctrl+B=Equalize all splits
prefix_equalize_splits - Ctrl+BEscLeave terminal mode
prefix_exit_mode - Ctrl+BeFocus/leave sidebar
prefix_explore - Ctrl+BfSearch files below the focused pane's directory
prefix_file_search - Ctrl+BzFullscreen current window
prefix_fullscreen - Ctrl+B?Toggle help
prefix_help - Ctrl+BiOpen the Inbox
prefix_inbox - Ctrl+BjJump to newest message
prefix_jump_notif - Ctrl+BkOpen the keybind manager
prefix_keybinds - Ctrl+BNShow the last message in full
prefix_last_message - Ctrl+BLEnter layout prefix
prefix_layout - Ctrl+BMOpen the Inbox on its mail
prefix_mail - Ctrl+BmEnter minimize prefix
prefix_minimize - Ctrl+BcCreate new window
prefix_new_window - Ctrl+BoJump to the oldest item needing you
prefix_next_attention - Ctrl+BOJump to the newest unseen finished turn
prefix_next_finished - Ctrl+BnorCtrl+BTabNext window
prefix_next_window - Ctrl+BporCtrl+BShift+TabPrevious window
prefix_prev_window - Ctrl+BqQuit (daemon: kills session)
prefix_quit - Ctrl+BrRename window
prefix_rename_window - Ctrl+BvReview the focused pane's changes
prefix_review - Ctrl+BRRotate split
prefix_rotate_split - Ctrl+BCTake a screenshot
prefix_screenshot - Ctrl+BsOpen the scrollback browser
prefix_scrollback - Ctrl+B0Jump to window 0
prefix_select_0 - Ctrl+B1Jump to window 1
prefix_select_1 - Ctrl+B2Jump to window 2
prefix_select_2 - Ctrl+B3Jump to window 3
prefix_select_3 - Ctrl+B4Jump to window 4
prefix_select_4 - Ctrl+B5Jump to window 5
prefix_select_5 - Ctrl+B6Jump to window 6
prefix_select_6 - Ctrl+B7Jump to window 7
prefix_select_7 - Ctrl+B8Jump to window 8
prefix_select_8 - Ctrl+B9Jump to window 9
prefix_select_9 - Ctrl+B[Enter copy/scrollback mode
prefix_selection - Ctrl+BSOpen the session switcher
prefix_session_switcher - Ctrl+B,Open settings
prefix_settings - Ctrl+B-Split window horizontally
prefix_split_horizontal - Ctrl+B|orCtrl+B\Split window vertically
prefix_split_vertical - Ctrl+BTEnter tape manager prefix
prefix_tape - Ctrl+BbToggle the session sidebar
prefix_toggle_sidebar - Ctrl+BBToggle spotlight
prefix_toggle_spotlight - Ctrl+BSpaceToggle tiling mode
prefix_toggle_tiling - Ctrl+BtEnter window prefix
prefix_window - Ctrl+BwEnter workspace prefix
prefix_workspace - Ctrl+BWOpen the workspace switcher
prefix_workspace_switcher - Ctrl+B(Previous session
prev_session - Ctrl+BDownFocus the pane below
terminal_focus_down - Ctrl+BLeftFocus the pane to the left
terminal_focus_left - Ctrl+BRightFocus the pane to the right
terminal_focus_right - Ctrl+BUpFocus the pane above
terminal_focus_up - Ctrl+BgShow or hide the scratch terminal
toggle_scratch
[keybindings.window_prefix]- Ctrl+BtEscwindow prefix cancel
window_prefix_cancel - Ctrl+Btxwindow prefix close
window_prefix_close - Ctrl+Btnwindow prefix new
window_prefix_new - Ctrl+BtTabwindow prefix next
window_prefix_next - Ctrl+BtShift+Tabwindow prefix prev
window_prefix_prev - Ctrl+Btrwindow prefix rename
window_prefix_rename - Ctrl+Bttwindow prefix tiling
window_prefix_tiling
[keybindings.minimize_prefix]- Ctrl+BmEscminimize prefix cancel
minimize_prefix_cancel - Ctrl+Bmmminimize prefix focused
minimize_prefix_focused - Ctrl+Bm1minimize prefix restore 1
minimize_prefix_restore_1 - Ctrl+Bm2minimize prefix restore 2
minimize_prefix_restore_2 - Ctrl+Bm3minimize prefix restore 3
minimize_prefix_restore_3 - Ctrl+Bm4minimize prefix restore 4
minimize_prefix_restore_4 - Ctrl+Bm5minimize prefix restore 5
minimize_prefix_restore_5 - Ctrl+Bm6minimize prefix restore 6
minimize_prefix_restore_6 - Ctrl+Bm7minimize prefix restore 7
minimize_prefix_restore_7 - Ctrl+Bm8minimize prefix restore 8
minimize_prefix_restore_8 - Ctrl+Bm9minimize prefix restore 9
minimize_prefix_restore_9 - Ctrl+BmMminimize prefix restore all
minimize_prefix_restore_all
[keybindings.workspace_prefix]- Ctrl+BwEscworkspace prefix cancel
workspace_prefix_cancel - Ctrl+Bw!workspace prefix move 1
workspace_prefix_move_1 - Ctrl+Bw@workspace prefix move 2
workspace_prefix_move_2 - Ctrl+Bw#workspace prefix move 3
workspace_prefix_move_3 - Ctrl+Bw$workspace prefix move 4
workspace_prefix_move_4 - Ctrl+Bw%workspace prefix move 5
workspace_prefix_move_5 - Ctrl+Bw^workspace prefix move 6
workspace_prefix_move_6 - Ctrl+Bw&workspace prefix move 7
workspace_prefix_move_7 - Ctrl+Bw*workspace prefix move 8
workspace_prefix_move_8 - Ctrl+Bw(workspace prefix move 9
workspace_prefix_move_9 - Ctrl+BwrRename workspace
workspace_prefix_rename - Ctrl+Bw1workspace prefix switch 1
workspace_prefix_switch_1 - Ctrl+Bw2workspace prefix switch 2
workspace_prefix_switch_2 - Ctrl+Bw3workspace prefix switch 3
workspace_prefix_switch_3 - Ctrl+Bw4workspace prefix switch 4
workspace_prefix_switch_4 - Ctrl+Bw5workspace prefix switch 5
workspace_prefix_switch_5 - Ctrl+Bw6workspace prefix switch 6
workspace_prefix_switch_6 - Ctrl+Bw7workspace prefix switch 7
workspace_prefix_switch_7 - Ctrl+Bw8workspace prefix switch 8
workspace_prefix_switch_8 - Ctrl+Bw9workspace prefix switch 9
workspace_prefix_switch_9
[keybindings.debug_prefix]- Ctrl+BDaToggle animations
debug_prefix_animations - Ctrl+BDcToggle cache statistics
debug_prefix_cache - Ctrl+BDEscCancel debug prefix
debug_prefix_cancel - Ctrl+BDlToggle log viewer
debug_prefix_logs - Ctrl+BDkToggle showkeys overlay
debug_prefix_showkeys
[keybindings.tape_prefix]- Ctrl+BTEscCancel tape prefix
tape_prefix_cancel - Ctrl+BTmOpen tape manager
tape_prefix_manager - Ctrl+BTrStart recording
tape_prefix_record - Ctrl+BTtReview project tape
tape_prefix_review - Ctrl+BTsStop recording
tape_prefix_stop
[keybindings.layout_prefix]- Ctrl+BLiMake one more pane a master pane
add_master - Ctrl+BLoMove the master panes to the next side: left, right, top, bottom, center
cycle_master_position - Ctrl+BLmFocus the master pane
focus_master - Ctrl+BLEscCancel layout prefix
layout_prefix_cancel - Ctrl+BLlOpen the layout picker
layout_prefix_load - Ctrl+BLsSave the current layout
layout_prefix_save - Ctrl+BLdMake one pane fewer a master pane
remove_master - Ctrl+BLShift+5Set focused window height to 50%
resize_height_50 - Ctrl+BLShift+6Set focused window height to 60%
resize_height_60 - Ctrl+BLShift+7Set focused window height to 70%
resize_height_70 - Ctrl+BLShift+8Set focused window height to 80%
resize_height_80 - Ctrl+BLShift+9Set focused window height to 90%
resize_height_90 - Ctrl+BL5Set focused window width to 50%
resize_width_50 - Ctrl+BL6Set focused window width to 60%
resize_width_60 - Ctrl+BL7Set focused window width to 70%
resize_width_70 - Ctrl+BL8Set focused window width to 80%
resize_width_80 - Ctrl+BL9Set focused window width to 90%
resize_width_90 - Ctrl+BL1Snap to top-left
snap_corner_1 - Ctrl+BL2Snap to top-right
snap_corner_2 - Ctrl+BL3Snap to bottom-left
snap_corner_3 - Ctrl+BL4Snap to bottom-right
snap_corner_4 - Ctrl+BLEnterSwap the focused pane with the master pane
swap_with_master
[keybindings.script]- Ctrl+PPause or resume the playing tape
script_pause
tuios keybinds doctor --json at c35d2942. Your own bindings: tuios keybinds list, or Ctrl+B k in a session.Modes
Section: [keybindings.mode_control]. These keys work in window mode.
| Key | Action | Does |
|---|---|---|
| i, Enter | enter_terminal_mode | Enter terminal mode |
| Esc | enter_window_mode | Enter window mode |
| ? | toggle_help | Toggle the help overlay |
| , | open_settings | Open the settings page |
| q | quit | Quit. In a daemon session it opens the quit menu |
| none | hold_window_mode | Window mode while the key is held. Unbound by default |
To leave terminal mode, press Ctrl+B Esc, or the direct key from Terminal mode.
hold_window_mode needs a terminal that speaks the Kitty keyboard protocol (Ghostty, kitty, WezTerm, foot, Alacritty), because only that protocol reports key releases. Bind it to an ordinary spare key, such as an unused function key from f1 to f12. Binding a modifier such as leftalt also works, but then every keystroke in the session arrives as an escape code.
Window mode
Windows
Section: [keybindings.window_management].
| Key | Action | Does |
|---|---|---|
| n | new_window | New window |
| N | new_session | New session. Asks which machine when there is more than one |
| w, x | close_window | Close the focused window |
| r | rename_window | Rename the focused window |
| m | minimize_window | Minimize the focused window |
| M | restore_all | Restore all minimized windows |
| z | toggle_zoom | Zoom the focused window, or unzoom it |
| p | toggle_pip | Pin the focused window as the picture-in-picture view, or unpin the pinned one |
| Tab | next_window | Focus the next window |
| Shift+Tab | prev_window | Focus the previous window |
| ; | last_pane | Go back to the pane that had focus before. Press it again to return |
| 1 to 9 | select_window_1 to select_window_9 | Focus a window by number |
| c | copy_selection | Copy the mouse selection |
| s | focus_sidebar | Give the keyboard to the session rail |
| S | start_screensaver | Start the screen saver now |
| Alt+Shift+N | next_session | Next session |
| Alt+Shift+P | prev_session | Previous session |
| none | switch_session_1 to switch_session_9 | Attach the session at that position in the rail. Unbound by default. A position with no session shows a message |
Section [keybindings.restore_minimized] restores one minimized window by position:
| Key | Action |
|---|---|
| Shift+1 to Shift+9 (also ! to () | restore_minimized_1 to restore_minimized_9 |
Section [keybindings.system] has one binding: B is toggle_spotlight, which lights one part of the screen and dims the rest. See Spotlight.
Workspaces
Section: [keybindings.workspaces]. There are nine workspaces. The modifier is Option on macOS and Alt elsewhere.
| Key | Action | Does |
|---|---|---|
| Alt+1 to Alt+9 | switch_workspace_1 to switch_workspace_9 | Show a workspace |
| Alt+Shift+1 to Alt+Shift+9 | move_and_follow_1 to move_and_follow_9 | Move the focused window there and follow it |
rename_workspace opens the rename editor on the current workspace. It has no default key. Ctrl+B w r does the same from the prefix.
Layout and snapping
Section: [keybindings.layout].
| Key | Action | Does |
|---|---|---|
| t | toggle_tiling | Turn tiling on or off |
| h | snap_left | Snap to the left half. In tiling, focus left |
| l | snap_right | Snap to the right half. In tiling, focus right |
| j | focus_down | Focus the window below |
| k | focus_up | Focus the window above |
| f | snap_fullscreen | Fill the screen |
| u | unsnap | Restore the size before the snap |
| H, Ctrl+← | swap_left | Swap with the window to the left |
| L, Ctrl+→ | swap_right | Swap with the window to the right |
| K, Ctrl+↑ | swap_up | Swap with the window above |
| J, Ctrl+↓ | swap_down | Swap with the window below |
| < | resize_master_shrink | Narrow the master area |
| > | resize_master_grow | Widen the master area |
| { | resize_height_shrink | Shorten the focused window from the bottom edge |
| } | resize_height_grow | Lengthen the focused window from the bottom edge |
| . | resize_master_grow_left | Widen the master area from the left edge |
| [ | resize_height_shrink_top | Shorten the focused window from the top edge |
| ] | resize_height_grow_top | Lengthen the focused window from the top edge |
| none | resize_master_shrink_left | Narrow the master area from the left edge. Unbound by default |
resize_master_shrink_left has no default because , opens settings. Bind it to a free key if you want it.
Corner snapping is on the layout prefix, not on the bare digits.
Moving focus
Four keys move focus to the window in a direction. Each direction has a key in window mode, in terminal mode and after the prefix.
| Direction | Window mode | Terminal mode | After Ctrl+B |
|---|---|---|---|
| Left | h | Alt+← | ← |
| Down | j | Alt+↓ | ↓ |
| Up | k | Alt+↑ | ↑ |
| Right | l | Alt+→ | → |
Focus goes to the nearest window in that direction that faces the focused window. At the edge of a tiled layout, focus stays where it is. With tiling off, a window that does not face the focused window can also get focus.
With tiling off, h and l snap the focused window to the left or right half of the screen. j and k always move focus.
In the scrolling layout, left and right move between columns. Up and down move between the windows in one column.
If your config already binds j or k in a window mode section, TUIOS keeps your binding and gives focus_down or focus_up no key. tuios keybinds doctor tells you when this happens.
Neovim pane navigation
The optional tuios-nvim-navigator plugin lets the terminal-mode focus keys move through Neovim splits first. At the edge of a split, TUIOS moves to the next pane. The feature is off by default. Turn it on:
[appearance]
nvim_navigation = trueThe plugin tells TUIOS when it is active, so the same keys keep their normal TUIOS action in shells and other programs. By default, both projects use Alt+←, Alt+↓, Alt+↑ and Alt+→. If you change the keys on one side, change the other to match terminal_focus_left, terminal_focus_down, terminal_focus_up and terminal_focus_right.
The plugin sends private OSC 7777 messages. TUIOS reads them and never shows them in the pane:
OSC 7777 ; tuios-nvim-navigator ; state ; active BEL
OSC 7777 ; tuios-nvim-navigator ; state ; inactive BEL
OSC 7777 ; tuios-nvim-navigator ; focus ; <direction> BEL<direction> is left, down, up or right. Another Neovim integration can send the same messages. TUIOS accepts a focus request only from the focused pane in terminal mode, and only just after it sent the matching focus key to that pane. Window mode always keeps the focus keys for TUIOS.
BSP splits
Also in [keybindings.layout]. See BSP Tiling.
| Key | Action | Does |
|---|---|---|
| - | split_horizontal | Split the focused pane top and bottom |
| |, \ | split_vertical | Split the focused pane left and right |
| R | rotate_split | Flip the split direction |
| = | equalize_splits | Make every split equal. In master-stack, also put the master back at master_ratio |
| Alt+h / j / k / l | preselect_left, preselect_down, preselect_up, preselect_right | Choose where the next window opens |
The preselect keys use Option on macOS. The prefix menu has its own copies of the four split actions, and rebinding one set does not change the other.
Terminal mode
Section: [keybindings.terminal_mode]. These keys work in terminal mode with no prefix. Everything else goes to the pane.
| Key | Action | Does |
|---|---|---|
| Alt+n | terminal_next_window | Focus the next window |
| Alt+p | terminal_prev_window | Focus the previous window |
| Alt+Esc | terminal_exit_mode | Go to window mode |
| Alt+arrows | terminal_focus_left, _right, _up, _down | Focus the pane in that direction |
| Shift+↑ | terminal_scroll_up | Scroll into the pane's scrollback |
| Shift+↓ | terminal_scroll_down | Scroll back toward live output |
| Ctrl+Shift+V, Super+V | terminal_paste_host | Paste from the host clipboard. An image is pasted as a file path. See Paste an image |
| Key | Action | Does |
|---|---|---|
| Option+Tab, Alt+n | terminal_next_window | Focus the next window |
| Option+Shift+Tab, Alt+p | terminal_prev_window | Focus the previous window |
| Option+Esc | terminal_exit_mode | Go to window mode |
| Alt+arrows | terminal_focus_left, _right, _up, _down | Focus the pane in that direction |
| Shift+↑ | terminal_scroll_up | Scroll into the pane's scrollback |
| Shift+↓ | terminal_scroll_down | Scroll back toward live output |
| Ctrl+Shift+V, Super+V | terminal_paste_host | Paste from the host clipboard. An image is pasted as a file path. See Paste an image |
Alt+Left and Alt+Right cost you word motions
Readline, fish and zsh use Alt+← and Alt+→ to move a word at a time. To give them back, run tuios keybinds free alt+left and tuios keybinds free alt+right. Ctrl+B then an arrow still moves focus.
Plain Ctrl+V is not bound. It reaches the pane, so vim's visual block mode works.
Shift+↑ and Shift+↓ scroll the pane into its history only when the program is on the main screen and did not turn on a mouse mode. In other panes, TUIOS sends the keys to the program, so nvim, less and htop get them. In copy mode the keys scroll. This is the same rule as for the mouse wheel, and the same rule as in kitty.
Paste an image
Ctrl+B V pastes the image on your clipboard into the focused pane. TUIOS saves the image to a file on the machine where the pane runs. Then it pastes the path of that file into the pane. The pane can run on this machine or on a host. Claude Code, Codex and other agents read an image from a path in the prompt. The action is paste_image, and the command palette has it too.
The paste key also pastes an image. When the clipboard holds an image and no text, the paste key pastes the image. When the clipboard holds text, the paste key pastes the text. Some terminals send an empty paste when the clipboard holds only an image. TUIOS then pastes the image.
A browser can put a link or text beside a copied image. The paste key then pastes the text. Ctrl+B V always pastes the image.
The paste key waits at most 0.3 seconds for the list of clipboard types. When the clipboard tool is slower, or cannot list the clipboard, the paste key pastes text. It then does not ask the tool again until TUIOS restarts.
Ctrl+V alone goes to the program in the pane. Claude Code reads the clipboard on Ctrl+V itself, and that only works in a pane on this machine. For a pane on a host, use Ctrl+B V.
TUIOS reads the image with the clipboard tool of your system:
| System | Tool |
|---|---|
| Linux, Wayland | wl-paste from wl-clipboard |
| Linux, X11 | xclip. xsel cannot read an image |
| macOS | osascript, or pngpaste when it is installed |
| Windows | PowerShell |
The file is a PNG, JPEG, GIF, WebP, BMP or TIFF image of 8 MB or less. Only you can read it. TUIOS deletes it after one hour, or when the daemon stops. The paste folder next to the TUIOS socket keeps at most 50 images and 100 MB. When it is full, TUIOS deletes the oldest image.
TUIOS does not read the clipboard when the client runs in a browser, when it runs on another machine through tuios ssh, or when the paste comes from send-keys. Inside ssh, TUIOS reads only an X display that ssh -X forwards. Any other clipboard there is the other machine's.
Keys sent to the pane are encoded the way a real terminal encodes them. When the program in the pane turns on application cursor keys (DECCKM), as zsh's line editor does, the arrows, Home and End are sent in their SS3 form (ESC O H for Home) instead of the CSI form (ESC [ H), so the program's bindings for them work. tuios send-keys follows the same rule.
tuios send-keys also encodes a named key or a chord in the keyboard mode the program asked for. A program that asked for the kitty keyboard protocol or modifyOtherKeys gets that encoding, the same as for a key you press. Vim then reads Ctrl+H as Ctrl+H, not as Backspace.
Global keys
Section: [keybindings.global]. These keys work in window mode and terminal mode.
| Key | Action | Does |
|---|---|---|
| Ctrl+P | command_palette | Open the command palette |
| Alt+Space | launcher | Open the app launcher |
The command palette searches commands, sessions and windows. Start the query with @ to filter panes by agent state (@n for needs input), or with # to search actions to rebind.
The app launcher lists every executable on $PATH, ranked by use. Enter runs the selection in a new pane with no shell in between. Tab types the command into the focused shell instead, so you can add arguments.
These two keys take Ctrl+P from fish and vim and Alt+Space from readline. Set an action to [] to give its key back. On macOS, Option+Space types a non-breaking space, so use Ctrl+B a for the launcher.
Prefix commands
Press Ctrl+B, then the key. Section: [keybindings.prefix_mode].
| Key | Action | Does |
|---|---|---|
| c | prefix_new_window | New window |
| x | prefix_close_window | Close the focused window |
| r | prefix_rename_window | Rename the focused window |
| n, Tab | prefix_next_window | Next window |
| p, Shift+Tab | prefix_prev_window | Previous window |
| 0 to 9 | prefix_select_0 to prefix_select_9 | Jump to a window |
| arrows | terminal_focus_left, _right, _up, _down | Focus the pane in that direction |
| ) | next_session | Next session |
| ( | prev_session | Previous session |
| Space | prefix_toggle_tiling | Turn tiling on or off |
| z | prefix_fullscreen | Zoom the focused window |
| - | prefix_split_horizontal | Split top and bottom |
| |, \ | prefix_split_vertical | Split left and right |
| R | prefix_rotate_split | Flip the split direction |
| = | prefix_equalize_splits | Make every split equal. In master-stack, also put the master back at master_ratio |
| [ | prefix_selection | Enter copy mode |
| F | hints | Label the text on the pane to copy it. See Hints |
| none | hints_all_panes | Label the text on every pane of the workspace. See All panes |
| Q | display_panes | Put a label on each pane and focus one by its label. See Pane labels |
| / | choose_tree | Find a pane in every session and go to it. See The pane navigator |
| s | prefix_scrollback | Open the scrollback browser |
| C | prefix_screenshot | Take a screenshot |
| P | prefix_command_palette | Open the command palette |
| a | launcher | Open the app launcher |
| , | prefix_settings | Open the settings page |
| k | prefix_keybinds | Open the keybind manager |
| b | prefix_toggle_sidebar | Show or hide the session rail |
| B | prefix_toggle_spotlight | Turn the spotlight on or off |
| V | paste_image | Paste the clipboard image as a file path. See Paste an image |
| g | toggle_scratch | Show or hide the scratch terminal |
| e | prefix_explore | Move the keyboard to the rail, or back |
| S | prefix_session_switcher | Open the session switcher |
| W | prefix_workspace_switcher | Open the workspace switcher |
| j | prefix_jump_notif | Jump to the pane of the newest message |
| N | prefix_last_message | Show the last message in full. See Messages |
| i | prefix_inbox | Open the Inbox |
| o | prefix_next_attention | Go to the oldest Inbox item that needs you. o again goes to the next |
| O | prefix_next_finished | Go to the newest finished turn nobody has seen. O again goes to the next older one |
| v | prefix_review | Review the focused pane's changes |
| A | prefix_agents_settings | Open the Agents tab of the settings page |
| M | prefix_mail | Open the Inbox on its mail. m there opens the whole mailbox |
| t | prefix_window | Window prefix |
| m | prefix_minimize | Minimize prefix |
| w | prefix_workspace | Workspace prefix |
| L | prefix_layout | Layout prefix |
| T | prefix_tape | Tape prefix |
| D | prefix_debug | Debug prefix |
| d | prefix_detach | Detach. The session keeps running |
| X | prefix_close_session | Close the session and its panes |
| Esc | prefix_exit_mode | Leave terminal mode. Never detaches |
| q | prefix_quit | Quit. In a daemon session it opens the quit menu: detach, switch session, or kill the session |
| ? | prefix_help | Toggle help |
In terminal mode, pressing the leader twice sends one literal Ctrl+B to the pane.
The which-key popup that opens after the leader shows the keys of your config. A key that you rebind shows in its new place. An action that you unbind has no row. A row for a range of keys, such as 1-9, shows only the keys that are bound. For example, if you unbind the key for workspace 5, the row shows 1-4/6-9. Set appearance.whichkey_enabled = false to turn the popup off.
After a command worth repeating, such as an arrow, o or O, the prefix stays armed for 500 ms. Ctrl+B then ← ← ← moves three panes. Change this with appearance.prefix_repeat_time. 0 turns it off.
Scratch terminal
Ctrl+B g shows the scratch terminal, a small layout of panes in a box over the current layout. Press it again, also from inside the box, to hide it. The shells keep running between shows. Inside the box the window keys act on its panes: split, move the focus, resize, swap, zoom and close. [scratch] sets the size of the box. See Scratch terminal.
Window prefix
Ctrl+B t, then the key. Section: [keybindings.window_prefix].
| Key | Action | Does |
|---|---|---|
| n | window_prefix_new | New window |
| x | window_prefix_close | Close the focused window |
| r | window_prefix_rename | Rename the focused window |
| Tab | window_prefix_next | Next window |
| Shift+Tab | window_prefix_prev | Previous window |
| t | window_prefix_tiling | Turn tiling on or off |
| Esc | window_prefix_cancel | Cancel |
Minimize prefix
Ctrl+B m, then the key. Section: [keybindings.minimize_prefix].
| Key | Action | Does |
|---|---|---|
| m | minimize_prefix_focused | Minimize the focused window |
| 1 to 9 | minimize_prefix_restore_1 to minimize_prefix_restore_9 | Restore a minimized window by position |
| M | minimize_prefix_restore_all | Restore all minimized windows |
| Esc | minimize_prefix_cancel | Cancel |
Workspace prefix
Ctrl+B w, then the key. Section: [keybindings.workspace_prefix].
| Key | Action | Does |
|---|---|---|
| 1 to 9 | workspace_prefix_switch_1 to workspace_prefix_switch_9 | Show a workspace |
| ! @ # $ % ^ & * ( | workspace_prefix_move_1 to workspace_prefix_move_9 | Move the focused window there and follow it |
| r | workspace_prefix_rename | Rename the current workspace |
| Esc | workspace_prefix_cancel | Cancel |
Layout prefix
Ctrl+B L, then the key. Section: [keybindings.layout_prefix].
| Key | Action | Does |
|---|---|---|
| l | layout_prefix_load | Open the layout picker |
| s | layout_prefix_save | Save the current layout as a template |
| 1 to 4 | snap_corner_1 to snap_corner_4 | Snap to the top-left, top-right, bottom-left or bottom-right quarter. Floating mode only |
| 5 to 9 | resize_width_50 to resize_width_90 | Set the focused window's width to 50% to 90% |
| Shift+5 to Shift+9 | resize_height_50 to resize_height_90 | Set its height to 50% to 90% |
| Esc | layout_prefix_cancel | Cancel |
Actions resize_width_10 to resize_width_40 and resize_height_10 to resize_height_40 also exist, with no default key.
Loading a layout moves the existing windows into place. It does not close any. Extra windows are minimized. tuios layout manages saved templates from the shell.
Tape prefix
Ctrl+B T, then the key. Section: [keybindings.tape_prefix]. See Tape Recording.
| Key | Action | Does |
|---|---|---|
| m | tape_prefix_manager | Open the tape manager |
| r | tape_prefix_record | Start recording |
| s | tape_prefix_stop | Stop recording |
| t | tape_prefix_review | Review the project tape found in this directory |
| Esc | tape_prefix_cancel | Cancel |
While a tape plays, section [keybindings.script] is active: Ctrl+P is script_pause and pauses or resumes playback.
Debug prefix
Ctrl+B D, then the key. Section: [keybindings.debug_prefix].
| Key | Action | Does |
|---|---|---|
| l | debug_prefix_logs | Toggle the log viewer |
| c | debug_prefix_cache | Toggle style cache statistics |
| k | debug_prefix_showkeys | Toggle the showkeys overlay |
| a | debug_prefix_animations | Toggle animations |
| Esc | debug_prefix_cancel | Cancel |
Session rail
Section: [keybindings.sidebar]. Active while the rail has the keyboard: press s in window mode, or Ctrl+B e.
| Key | Action | Does |
|---|---|---|
| j, ↓ | cursor_down | Move down |
| k, ↑ | cursor_up | Move up |
| g, Home | first | First row |
| G, End | last | Last row |
| l, → | expand | Go to the next section |
| h, ← | collapse | Go to the previous section |
| Enter | activate | Open the row |
| J, Shift+↓ | reorder_down | Move the session or machine down |
| K, Shift+↑ | reorder_up | Move the session or machine up |
| Tab, Shift+Tab | section | Cycle the sessions, terminals and agents sections |
| 1 to 9 | jump_1 to jump_9 | Jump to a row by number |
| n | new_session | New session |
| t | new_window | New window |
| r | rename | Rename the pane or session |
| c | accent | Set the session's accent colour |
| x | kill | Open the row's close menu |
| m | menu | Open the row's menu |
| i | mail | Open the mailbox for the pane under the cursor |
| f | agents_filter | Agents section: every session, or only this one |
| o | agents_sort | Agents section: sort by what needs you, by priority, or by recency |
| / | palette | Open the command palette |
| < | narrow | Narrow the rail |
| > | widen | Widen the rail |
| ? | help | Show the rail's help |
| Esc, s | exit | Give the keyboard back |
When the cursor is on a row in the files section, section [keybindings.sidebar_files] answers first:
| Key | Action | Does |
|---|---|---|
| Enter | file_open | Open the folder, or copy the file's path |
| a | file_create | New file. End the name with / for a folder |
| r | file_rename | Rename |
| d | file_delete | Delete to the trash |
| D | file_delete_forever | Delete with no trash |
| y | file_copy | Copy |
| x | file_cut | Cut |
| p | file_paste | Paste into this folder |
| Y | file_copy_path | Copy the absolute path of the file or folder. A folder's context menu has a Copy path row too |
See The files section.
When the cursor is on an agent row, section [keybindings.sidebar_agents] answers first. So r and x act on the agent there, and keep their rail meaning on every other row:
| Key | Action | Does |
|---|---|---|
| r | agent_reply | Reply to the agent. The message is queued and typed when the agent is at rest |
| v | agent_review | Review the pane's changes |
| u | agent_unread | Mark the pane's finished turn unread again, for every client |
| z | agent_snooze | Open the Inbox on the pane's item, ready to snooze it |
| x | agent_cancel_queued | Drop the newest queued message. u within 10 seconds queues it again. With nothing queued, x opens the row's menu as usual |
Enter on the +N at rest line shows the agent rows folded there.
Inbox and mailbox
The Inbox lists everything waiting for you in every session. Open it with Ctrl+B i. Its keys are in [keybindings.inbox]:
| Key | Action | Does |
|---|---|---|
| j, ↓, Ctrl+N | inbox_down | Move down |
| k, ↑, Ctrl+P | inbox_up | Move up |
| PgDn, PgUp | inbox_page_down, inbox_page_up | Move a page |
| g, Home / G, End | inbox_first, inbox_last | First or last item |
| Enter | inbox_go | Go to the item's pane, or open a mail thread |
| Space | inbox_peek | Read an approval's or a question's prompt and answer it from the Inbox |
| d, Delete | inbox_dismiss | Dismiss the item. u undoes it for 10 seconds |
| r | inbox_reply | Reply to mail, or to the agent of a finished or errored item |
| y | inbox_resume | On a resume row, type the conversation's resume command in its pane |
| p | inbox_pass_on | Pass on mail held from another machine |
| f | inbox_filter | Show one kind, then the next, then all |
| / | inbox_select | Narrow the list with a selector, such as harness:codex needs:you |
| m | inbox_mailbox | Open the mailbox |
| v | inbox_review | Review the changes in the item's pane |
| z | inbox_snooze | Snooze the item: then 1 15 minutes, 2 an hour, 3 until 9:00 tomorrow, 4 until it changes. On a snoozed item, wake it |
| u | inbox_undo | Undo the last dismiss or snooze, within 10 seconds |
| S | inbox_show_snoozed | Show or hide the snoozed items |
| n | inbox_deny_reason | Deny a held approval, or keep a plan planning, with a reason you type |
| J, Ctrl+D / K, Ctrl+U | inbox_detail_down, inbox_detail_up | Scroll the detail under the list, such as a long plan |
| Esc, q | inbox_close | Close |
On an approval the Inbox holds for you, 1 allows it once, 2 always allows it and 3 denies it. On a question put with ask-human, a digit picks that answer. The digits are not bindings.
The prompt that Space opens has its own section, [keybindings.inbox_peek]:
| Key | Action | Does |
|---|---|---|
| a | peek_approve | Approve |
| A | peek_approve_always | Approve and do not ask again, when the menu offers it |
| d | peek_deny | Deny |
| Tab | peek_type | Type an answer |
| r | peek_read_again | Read the prompt again |
| Enter | peek_go | Go to the pane instead |
| Esc, q, Space | peek_back | Back to the list |
A digit chooses that numbered option of the prompt.
The mailbox (m in the Inbox) uses [keybindings.mail]: j/k (mail_down, mail_up), PgDn/PgUp (mail_page_down, mail_page_up), Enter opens a thread (mail_open), r replies (mail_reply), o goes to the pane (mail_focus_pane), n writes a new message to an agent (mail_new) and Esc or q goes back (mail_back).
The footers name whatever key your config binds. Until an agent has been seen, the prefix menu, the help and the palette leave out the agent keys and entries, so a person who runs no agents is not shown them. The keys work before that too, except Ctrl+B O, which types O into the pane until then.
The review overlay
Ctrl+B v, or v in the Inbox or on a rail agent row, opens the diff of a pane's changes over the whole screen. See Reviewing an agent's changes. These keys are fixed and are not in the config.
| Keys | Does |
|---|---|
| j k, arrows | Move by line. With the file list focused, move through the files |
| Space, PgDn, Ctrl+D / PgUp, Ctrl+U | Move a page |
| g G | First or last line |
| ] [ | Next or previous hunk, going on into the next or previous file |
| } { | Next or previous file |
| s | One column, or old and new side by side when the screen is wide enough |
| h l, ← → | Scroll the code sideways |
| Tab | Focus the file list or the diff |
| Enter | In the file list, open that file |
| c / C | A note on the line under the cursor, or on the whole hunk |
| e | Edit the note under the cursor |
| x | Resolve (remove) the note under the cursor |
| S | Send every unsent note to the agent as one message, typed when it is at rest |
| u | Switch between the changes since the base and only the uncommitted ones |
| b | Diff from another base |
| w | The compare view, for a pane in a fan |
| r | Read the diff again |
| Esc, q | Close |
The compare view lists the attempts of a fan. j/k move, Enter reviews an attempt, m marks one and d diffs the two marked attempts, V runs a command in every attempt, K keeps the attempt under the cursor and removes the others after a y, and Esc, q or w go back to the review.
Lists and the settings page
Every list moves the same way: the palette, the launcher, the settings page, the Inbox, the mailbox, the keybind manager, the pickers, the switchers, the menus and the tape manager.
| Keys | Does |
|---|---|
| ↑ ↓, Ctrl+P Ctrl+N | Move one row. Past either end, wrap round |
| Home End | First or last row |
| PgUp PgDn | A page, stopping at the ends |
| k j g G | Up, down, first and last, in a list with no filter to type into |
| Ctrl+U | Clear a typed filter |
Set appearance.wrap_lists = false to stop at the ends instead of wrapping.
The settings page (, in window mode, or Ctrl+B ,) reopens on the tab, row and search you left it on:
| Keys | Does |
|---|---|
| ← →, h l | Change the row's value |
| Enter, Space | Toggle, cycle, or open the row's picker or editor |
| Tab Shift+Tab, ] [ | Next or previous tab |
| 1 to 9 | Go to that tab |
| /, or a letter the page does not use | Search every tab |
| Backspace, Delete | Reset the row to its default |
| Ctrl+Z | Undo the last change made on the page |
| Esc, q | Close |
A row whose value differs from its default has a dot after its name, including the hand-drawn rows such as the theme and shared borders, which have no reset. See The in-app settings page for the search.
The key hints at the foot of a panel stay on one row. When they do not fit, they get shorter in steps. First, ctrl+ becomes ^, alt+ becomes M- and shift+ becomes S-. Then the least important hints go, one whole hint at a time. The way out, such as esc, stays. Only when the most important hints still do not fit do their labels go, from the last hint back. A hint is never cut in the middle of a word.
Mode keys in the dock
Copy mode, multi copy mode and hints mode show their keys at the right end of the dock while the mode is open. The keys follow the rule for panel footers, so a narrow screen shows fewer keys and never part of one. The main action and the way out always show. In hints mode, ? shows all of its keys in the help. A message that arrives while a mode is open shows in place of the keys until the message goes. The dock component is copy-help.
Messages
A message shows at the right end of the dock. A message that is too long for the dock stops after its last whole word, with … and more. A word with no space in it, such as a long path, is cut where the room ends.
- Put the pointer on a message to hold it. A key press, the terminal losing focus, or 60 seconds ends the hold.
- Put the pointer on a long message to see its first lines above the dock.
- Click a long message to read all of it in the message view. A click on a pane's request to set the clipboard allows it.
- Click a short message from a pane to go to that pane.
| Keys | Where | Does |
|---|---|---|
| Ctrl+B N | Anywhere | Show the last message from a pane, or the last message too long for the dock, also after it left the dock |
| Ctrl+B j | Anywhere | Go to the pane of the newest message |
| j k, ↑ ↓, wheel | Message view | Scroll one line |
| Ctrl+D Ctrl+U, Space, PgDn PgUp | Message view | Scroll half a page |
| g G, Home End | Message view | Go to the first or last line |
| y | Message view | Copy the message |
| Enter | Message view | Go to the pane the message came from |
| Esc, q | Message view | Close the message view |
The log viewer (Ctrl+B D l) lists every message the dock showed, and every warning and error. The entry under the cursor shows wrapped under the list. Press Enter, or click an entry, to read it in the message view. E copies the errors and A copies the whole log.
Spotlight
B in window mode turns the spotlight on and off. The spotlight dims the screen outside a circle around the pointer. Ctrl+B B turns it on and off in any mode. The key was b in earlier versions.
While the spotlight is on, the dock shows a Spotlight chip with the key that turns it off:
| Where | Turn off the spotlight |
|---|---|
| Window mode | Esc |
| Terminal mode | Ctrl+B B |
| Any mode | Click the Spotlight chip in the dock |
In terminal mode Esc goes to the program in the pane, so vim and other programs get it. An open dialog, menu or popup closes before Esc turns the spotlight off. The actions are toggle_spotlight and prefix_toggle_spotlight. [spotlight] sets the size and the dimming. See Themes.
Close every pane on a workspace
The close_workspace action closes every pane on the current workspace, like tmux kill-window. Use it to close the panes that tuios xpanes opened. It has no default key. The command palette has the entry Close workspace. This example binds it to Ctrl+B Alt+X, because Ctrl+B X closes the session:
[keybindings.prefix_mode]
close_workspace = ["alt+x"]The action asks first. The dialog shows how many panes close and how many agents are in them. Cancel is the default row. Scratch panes stay open. tuios close-workspace does the same from a shell.
Split into the same ssh
These actions open a pane on the machine that the focused pane is connected to with ssh:
| Action | What it does |
|---|---|
split_ssh_horizontal | Splits the pane top and bottom. |
split_ssh_vertical | Splits the pane left and right. |
new_window_ssh | Opens a new window. |
The new pane runs ssh again, to the same host as the same user. It keeps the connection options, such as the port, the identity file and the jump host. tuios does not run the remote command again. It also removes -N, -f, -T, port forwards and the other options that stop a shell. mosh works the same way. Eternal Terminal (et) is not followed.
When the focused pane does not run ssh, the action opens an ordinary pane. You can use the keys in every pane. Some ssh lines also get an ordinary pane. See Configuration.
The actions have no default key. The command palette has an entry for each one. To bind them, add them to a section. This example uses keys for window-management mode:
[keybindings.layout]
split_ssh_vertical = ["alt+v"]
split_ssh_horizontal = ["alt+s"]
new_window_ssh = ["alt+w"]To make the ordinary split and new-window keys do the same, set appearance.new_window_follow_ssh. To start the new pane in the remote folder, make the remote shell report its folder. See Configuration.
Copy mode
Press Ctrl+B [ to enter copy mode. It moves a cursor through the scrollback with vim keys. These keys are fixed and are not in the config, except Home and End. You can add keys that pipe a yank through a command. See Pipe a yank through a command. Put a count before a motion to repeat it: 10j, 5w.
The copy cursor starts on the terminal cursor, which is usually the prompt line. tmux does the same. To start on the middle row, set appearance.selection.copy_entry to center.
When the focused pane is in the multifocus set, Ctrl+B [ starts multi copy mode on every pane of the set.
| Keys | Does |
|---|---|
| h j k l, arrows | Move the cursor |
| w b e | Next word, previous word, end of word |
| W B E | The same, for space-separated words |
| 0 ^ $ | Line start, first non-blank, line end |
| Home End | Line start, line end. You can rebind these two. See Line start and line end |
| H M L | Top, middle and bottom of the screen |
| gg, G | Top of the scrollback, bottom (live output) |
{n}G | Go to line n |
| { } | Previous and next paragraph |
| % | Matching bracket |
| Ctrl+U / Ctrl+D | Half page up, down |
| Ctrl+B / Ctrl+F, PgUp / PgDn | Full page up, down |
| f F t T then a character | Find a character on the line |
| ; , | Repeat the character search, forward or back |
| / | Search forward, down to the newest output |
| ? | Search backward, up into the scrollback |
| n | Next match in the direction of the last search |
| N | Next match in the opposite direction |
| Esc in the search prompt | Cancel the search and move the cursor back |
| Ctrl+L | Clear search highlights |
| v V | Start a character or line selection |
| y, c | Copy the selection to the clipboard, through copy_command when it is set |
| i | Leave copy mode and go to terminal mode |
| q, Esc | Leave copy mode |
The scrollback browser (Ctrl+B s) is a different tool. It lists past commands by their prompt marks, for shells that emit OSC 133.
Line start and line end
Home moves the copy cursor to the start of the line, as 0 does. End moves it to the end of the line, as $ does. Both keys also move the end of a v or V selection. The help lists them next to 0 ^ $.
| Action | Default key |
|---|---|
copy_mode_line_start | Home |
copy_mode_line_end | End |
The keys are in the copy_mode section. They work only in copy mode. In the search prompt, they do not move the cursor. 0 and $ are fixed keys, and you cannot rebind them.
Do not bind a key here that copy mode already uses, such as y or v, or a key of a [[keybindings.copy_pipe]] entry. tuios keybinds doctor and the config check warn about such a key. A copy pipe key runs the pipe, and the binding does not run. A key that copy mode uses loses its copy mode action.
Ctrl+A and Ctrl+E are not defaults. Ctrl+A is a common leader key, and Ctrl+E scrolls one line in tmux copy mode. To use them, add them to the section:
[keybindings.copy_mode]
copy_mode_line_start = ["home", "ctrl+a"]
copy_mode_line_end = ["end", "ctrl+e"]Search
The prompt shows / or ? for the direction. The search starts at the copy cursor. When no match is found in that direction, the search continues from the other end of the buffer. n and N also start at the copy cursor. After you move the cursor, they find the nearest match. When a search finds more than 1000 matches, the prompt shows 1000+.
Two actions start copy mode and open the search prompt with one key. They have no default key.
| Action | Palette entry | Does |
|---|---|---|
copy_mode_search_forward | Copy mode: search forward | Start copy mode and open the / prompt |
copy_mode_search_backward | Copy mode: search backward | Start copy mode and open the ? prompt |
They do the same as tmux bind-key b copy-mode \; send-keys ?. Bind one in any section. This example puts the backward search on Ctrl+B /:
[keybindings.prefix_mode]
copy_mode_search_backward = ["/"]If the pane is already in copy mode, the action opens the prompt and does not move the cursor. In multi copy mode, the prompt opens in each pane of the mode.
In copy mode, only a key in the global, terminal_mode or window_management section starts the action. A key after the leader does not, because copy mode uses Ctrl+B for page up. In copy mode, / and ? open the same prompts.
TUIOS cannot put two actions on one key. tuios send-keys cannot do it either, because a key from send-keys does not go to copy mode.
Pipe a yank through a command
A yank can go through a command before it goes to the clipboard. tmux calls this copy-command and copy-pipe. TUIOS has two parts:
appearance.selection.copy_commandruns one command on every yank in copy mode.- A
[[keybindings.copy_pipe]]entry binds a key in copy mode to its own command.
[appearance.selection]
copy_command = "tmux-copy-it"
[[keybindings.copy_pipe]]
key = "p"
command = "tr '\n' ' '"
cancel = true
description = "flatten"The command runs with sh -c. It gets the selection on stdin. The clipboard gets what the command writes to stdout. When the selection does not end with a new line, TUIOS removes one new line from the end of the output.
The clipboard gets the selection itself in these cases:
- The command writes nothing. Use this for a command that sends the text to a socket or a file.
- The command stops with an exit code that is not 0. The dock shows the exit code and the first line of stderr.
- The command runs for more than 10 seconds. TUIOS stops the command and the processes that it started.
TUIOS waits until the command closes its stdout. xclip starts a process that stays open after xclip stops, and keeps stdout open. TUIOS then waits 1 second more. To prevent the wait, send the stdout of xclip to /dev/null. This example also puts each yank in the X primary selection:
[appearance.selection]
copy_command = "xclip -selection primary >/dev/null"| Field | Does |
|---|---|
key | The key in copy mode. Write it as in the other sections |
command | The command that gets the selection on stdin |
cancel | false, the default, keeps copy mode on and the cursor where it is. TUIOS clears the selection. This is tmux copy-pipe. true leaves copy mode, as q does. This is tmux copy-pipe-and-cancel |
description | The name of the entry in the dock messages. Optional |
The entry takes its key from copy mode. An entry on y replaces the plain yank. Copy mode does not use p or P. When an entry takes q, Esc, v, V, /, ? or a digit, TUIOS shows a warning when it loads the config. When no text is selected, the key shows a message and runs nothing. While you type a search, the key goes into the search.
Without copy_command, y copies the selection as it is. With copy_command, y and c pipe the selection through that command. A [[keybindings.copy_pipe]] key always uses its own command. A mouse selection that copies on release does not use copy_command.
In multi copy mode, the command gets the text that y copies: the selection of each pane, joined in the current format. It runs one time for all panes. Use the json format to process each pane separately, for example with jq. With cancel = true, multi copy mode stops in every pane.
The command runs on the machine that runs the TUIOS client, the same machine as for a shell command key. For the SSH and web clients, it is the server. The command starts in the folder of the focused pane and gets the variables of a command key: TUIOS_SESSION, TUIOS_SOCKET, TUIOS_ACTIVE_PANE_ID and TUIOS_ACTIVE_PANE_CWD. You can use TUIOS while the command runs.
Mouse
| Gesture | Does |
|---|---|
| Click a pane | Focus it |
| Double-click a pane | In window mode, also start typing in it. appearance.click_to_type makes it a single click, or turns it off |
| Drag a title bar | Move the window. In tiling, swap it with the pane you drop it on |
| Alt + drag | Move the window from anywhere inside it (appearance.alt_drag) |
| Right-drag | Resize the window |
| Right-click | In window mode, open the menu for the pane, the dock or the desktop |
| Shift or Ctrl + right-click | Open the pane menu even when the program in the pane uses the mouse |
| Title bar buttons | Minimize, zoom or close |
| Click a dock item | Restore a minimized window |
| Wheel up | Enter copy mode and scroll, when the program is not using the mouse |
| Drag the right border | Scroll with the scrollbar |
| Hover a link | Show where it goes. The label shows the real target, also when the text on the screen is different |
| Ctrl + click a link | Open it. Shift+click also opens it, but most terminals keep it for their own selection. See Links |
In floating mode, drop a window on a screen edge to snap it: the left or right edge for a half, a corner for a quarter, the top center for the full screen.
In copy mode, a click moves the cursor and a drag selects. Dragging past the top or bottom of the pane scrolls.
Ctrl+drag still moves the pane. A link opens only when the pointer does not move. appearance.link_click sets which click opens a link.
Command keys
A [[keybindings.command]] entry binds a key to a command that you write.
[[keybindings.command]]
key = "prefix+alt+g"
type = "scratch"
command = "lazygit"
description = "Lazygit"
width = "80%"
height = "80%"keyis the key that runs the command. A key that starts withprefix+works after the leader (Ctrl+B). Any other key works in window mode and in terminal mode.typeis one of these:scratch: a scratch terminal of its own. The key shows it and hides it, as Ctrl+B g does for the built-in one. Each entry has its own layout: you can split it. One scratch terminal is on the screen at a time. When the command exits, its pane closes. When no pane is left, the next press starts the command again. With nocommand, the first pane runs your shell.popup: a popup that closes when the command exits. This is the default.pane: a new pane in the layout, next to the focused pane. It closes when the command exits.shell: the command runs with no window. You do not see its output. When the command fails, the dock shows a message.
commandruns withsh -c, so you can write pipes and quotes. It starts in the folder of the focused pane.descriptionis the name in the command palette and intuios keybinds list. It is optional.namekeeps a scratch terminal under a fixed name. It is optional. Without it, tuios makes the name from the description or the command.widthandheightset the size of a scratch or popup entry, in cells (100) or percent (80%). The default is80%.
The command gets these variables:
| Variable | Value |
|---|---|
TUIOS_SESSION | The session in which you pressed the key |
TUIOS_SOCKET | The socket of the daemon |
TUIOS_ACTIVE_PANE_ID | The pane that had the focus |
TUIOS_ACTIVE_PANE_CWD | The folder in which the command starts |
A command key never takes a key from a tuios action or from the leader key.
When the key is taken, tuios keybinds doctor shows the entry as dead. When
two entries have the same key, the first entry in config.toml runs, and the
doctor shows the other as dead. To move an entry to a different key, edit its
key in config.toml. The command palette lists each entry, and
tuios keybinds list shows them under Commands.
A key with no modifier and no prefix+, for example g, works in terminal
mode too. It takes that letter from every pane, so tuios shows a warning. Use
prefix+g or a key with a modifier, for example alt+g.
When a scratch command stops in its first moments, for example because the program is not installed, the dock shows its exit code. The next press starts it again. tuios does not start it again by itself.
The command and the palette row of an entry change when you save
config.toml. A changed key works at the next key press, as for the other
keybindings. When you remove or rename an entry, or change the description of
an entry that has no name, the panes of its scratch terminal close at the
next reload. The
dock shows a message.
In a session on a different machine, a scratch or popup entry does not
run. The dock shows a message. A pane entry runs on the machine of the
session. A shell entry runs on the machine that runs the tuios client.
Only a key press or the command palette runs a command key. A change to
config.toml does not run a command. A pane that has the respond grant can
press keys as you through run-command. It can press a command key, also from
a session on a different machine, and a shell entry then runs on this
machine. Give the respond grant only to a pane that you trust.
Recipes
These are command keys for common tasks. Copy an entry into config.toml and
change the key to taste. Run tuios keybinds doctor after you add one, to
check the key is free.
Per-session notes. This scratch entry opens $EDITOR on a notes file
named after the session, and makes the notes folder first. It falls back to
vi when $EDITOR is not set.
[[keybindings.command]]
key = "prefix+alt+n"
type = "scratch"
command = "mkdir -p ~/notes && ${EDITOR:-vi} ~/notes/$TUIOS_SESSION.md"
description = "Session notes"Browser pane. This scratch entry opens a page in terminal-browser. It needs terminal-browser installed, and a terminal with kitty graphics.
[[keybindings.command]]
key = "prefix+alt+b"
type = "scratch"
command = "terminal-browser open https://example.com"
description = "Browser"lazygit. This is the example at the top of this section. It opens lazygit in the focused pane's folder.
[[keybindings.command]]
key = "prefix+alt+g"
type = "scratch"
command = "lazygit"
description = "Lazygit"
width = "80%"
height = "80%"Pick a file into the focused pane. This popup runs fzf and types the
pick into the pane you came from, with
tuios send-text and the pane id from
TUIOS_ACTIVE_PANE_ID.
[[keybindings.command]]
key = "prefix+alt+p"
type = "popup"
command = "tuios send-text -w \"$TUIOS_ACTIVE_PANE_ID\" \"$(fzf)\""
description = "Pick a file"Open a project. This popup runs fzf over the folders in ~/dev and
switches to the session of the folder you pick. When the session does not
exist, tuios switch-session makes it in
that folder. See Sessionizer.
[[keybindings.command]]
key = "prefix+alt+s"
type = "popup"
command = 'dir=$(find ~/dev -mindepth 1 -maxdepth 1 -type d | fzf) && tuios switch-session --create --cwd "$dir" "$(basename "$dir")"'
description = "Open a project"Copy the pane's folder. This shell entry copies the focused pane's folder
to the clipboard. It tries pbcopy, then wl-copy, then xclip, and uses the
first one it finds.
[[keybindings.command]]
key = "prefix+alt+y"
type = "shell"
command = "printf %s \"$TUIOS_ACTIVE_PANE_CWD\" | (pbcopy || wl-copy || xclip -selection clipboard)"
description = "Copy pane folder"Customizing
Bindings live in 23 sections under [keybindings] in config.toml. Each action takes a list of keys.
[keybindings]
leader_key = "ctrl+a"
[keybindings.window_management]
new_window = ["n", "ctrl+t"]
close_window = [] # unbind: the key goes back to the paneAn empty list and a missing line are different. A missing action gets its default back at the next load. An empty list stays empty. Key syntax and every section are on the Configuration page.
The [keybindings] sections can also be in a file that config.toml includes, or in a file in config.d. The tables merge key by key. A [[keybindings.command]] entry in a later file changes the earlier entry with the same name, or with the same key when one of them has no name. Add disabled = true to an entry to remove the earlier entry that it matches. The keybind manager and tuios keybinds unbind write a change to the file that sets the action. See Split the Config.
Modifier spellings
A key in config.toml can spell a modifier in more than one way. TUIOS reads each spelling as the same key.
| Write | TUIOS reads it as | Where |
|---|---|---|
opt+, option+ | alt+ | macOS only |
cmd+, command+ | super+ | All platforms |
control+ | ctrl+ | All platforms |
The order of the modifiers does not matter, so shift+ctrl+x is the same key as ctrl+shift+x. This applies to leader_key, to every binding table, and to tuios keybinds explain, free and unbind. tuios keybinds explain opt+f12 prints opt+f12 (tuios reads it as alt+f12). tuios keybinds doctor lists each key that TUIOS cannot read.
A super+ chord needs a terminal that sends the Super key. Most macOS terminals keep Command chords for their own menus. Ghostty and kitty send an unbound Command chord through the Kitty keyboard protocol. A super+ chord on F1 to F12, such as super+f12, works the same way. On a Mac keyboard, F12 can also be a media key, and then TUIOS does not get it.
Inspect and change bindings from the shell:
tuios keybinds list # the main tables
tuios keybinds browse # search every binding in an explorer
tuios keybinds doctor # conflicts, and keys taken from the pane
tuios keybinds explain alt+left # everything one key does
tuios keybinds unbind close_window w # take one key off one action
tuios keybinds free alt+left # take a key off every actiondoctor tags each finding with its evidence: certain comes from TUIOS routing, observed from the live pane, reference from a list of common program defaults. doctor and explain take --json and --guest <program>.
tuios keybinds browse opens the rows of tuios keybinds list --json in an explorer. Press / to search, and Tab or a click on a tab to show one scope. The detail pane shows the keys, the action, the scope and the description. q or Esc leaves it. Add a search to start with it: tuios keybinds browse spotlight. tuios keybinds list prints plain text, on a terminal too.
The keybind manager (Ctrl+B k) shows the same analysis in four tabs: Bindings, Conflicts, Guests and Record. Record captures the next key you press. On a binding, Ctrl+D removes it and Ctrl+X takes its key off every action.
Keybinding edits apply at once
A keybinding saved in config.toml works at the next key press in the running client. You do not need to restart TUIOS or attach again. Changes made with the keybind manager also apply at once.
keybinds list-custom does not report leader_key
tuios keybinds list-custom compares every keybinding section. It does not report leader_key. Use tuios keybinds doctor or read the file for that.
Other keyboard layouts
Bindings work with layouts for non-Latin scripts, such as Cyrillic, Greek, Hebrew or Arabic. When no binding matches the character that a key types, TUIOS uses the key at the same position on a US layout. On a Ukrainian layout, the key that types ш is the US i key. So Ctrl+B then that key opens the Inbox.
- A binding on the typed character wins. You can still bind
шyourself. - Text that you type into a pane, a rename or a search keeps the character that you typed.
- Ctrl on a non-Latin key sends the control code of the US key to the pane. Ctrl+с is Ctrl+C in the shell.
Latin layouts, such as AZERTY, QWERTZ or Dvorak, use the letters on their keys. A letter or a Ctrl chord means the key that it types, not the US key at its position. On Dvorak, Ctrl with the key that types b is Ctrl+B, the leader. The showkeys strip, the binding recorder and a tape show the chord the same way. tuios keybinds explain checks the key as you write it, so give it the Latin key.
This needs a terminal that sends the US-layout key through the Kitty keyboard protocol: Ghostty, kitty, WezTerm or foot. Other terminals send only the typed character. With those terminals, use a Latin layout for TUIOS commands.
Codes such as [97u in the shell
In window mode, TUIOS tells the terminal to send every key as a code. TUIOS resets this when it stops. After kill -9 or a dropped ssh connection, the terminal can stay in this mode. The shell then shows codes such as [97u when you type. To reset the terminal, run printf '\033[=0;1u', or close the tab.
Keys sent to a pane
In terminal mode, TUIOS sends these keys to the program in the pane:
- The keypad keys, with Num Lock on or off. Keypad Enter sends Enter.
- Begin, the center key of the keypad with Num Lock off.
- F13 and higher. A program that uses the legacy encoding gets them in the form that xterm sends.
- Insert, Delete, Page Up and Page Down with their modifiers. Ctrl+Delete stays Ctrl+Delete.
A program that uses the Kitty keyboard protocol gets each key with the number that the protocol gives it. Caps Lock, Num Lock and a modifier key pressed alone reach that program only when it asks for every key.
macOS
macOS treats Option as a compose key unless the terminal says otherwise. An Option chord then arrives as a character. TUIOS maps most of those characters back to the chord, which is why Option+1 to Option+9 work with no setup. Two kinds cannot be recovered:
- Dead keys. Option+e, i, n, u and ` send nothing until a second key. Alt+n (next window in terminal mode) takes two presses.
- Rewritten chords. Many terminals send Option+← and Option+→ as readline word motions, with no sign that an arrow was pressed.
To fix both, turn on your terminal's Option-as-Alt setting:
| Terminal | Setting |
|---|---|
| Ghostty | macos-option-as-alt = true |
| Terminal.app | Settings > Profiles > Keyboard > Use Option as Meta Key |
| iTerm2 | Settings > Profiles > Keys > Left Option key: Esc+ |
| kitty | macos_option_as_alt yes |
| WezTerm | send_composed_key_when_left_alt_is_pressed = false |
| Alacritty | option_as_alt = "Both" under [window] |
| VS Code | terminal.integrated.macOptionIsMeta |
Ghostty also needs keybind = alt+left=unbind and keybind = alt+right=unbind, because its own keybinds rewrite those arrows first.
The prefix works on every terminal with no setup. Ctrl+B then an arrow, n, p, (, ), a or a digit covers every navigation command.
Command chords never reach a terminal program. macOS sends them to the menu bar.