Keybindings
The complete built-in keymap, and how to change it. Bindings are
grouped by context: the terminal deliberately steals nothing, so
every bare key reaches your shell. The third column is the action
id you use in [keymap].
Keys are listed for both platforms wherever they differ. The ctrl-w chords, and every bare key in the file tree, the workspaces panel, the overlays, and copy mode, are identical on macOS and Linux. Where macOS uses cmd, Linux uses ctrl-shift — the usual terminal convention, so plain ctrl-c stays the shell's — and alt-1 … alt-9 for tabs, because Super belongs to the window manager: nothing is bound to it. A row tagged mac only has no Linux binding at all; that job is the window manager's.
Can't remember a key? cmd-shift-p on macOS, ctrl-shift-p on Linux, opens the command palette: every action, fuzzy-searchable, with its current binding shown alongside.
How contexts work
Everything terminal-scoped is either modifier-prefixed
(cmd-… on macOS, ctrl-shift-… on Linux) or
sequence-led (ctrl-w then a key),
and bound at the root, so no bare keystroke is taken away from the
shell. The file tree, the workspaces panel, and the theme picker are
modeless lists with no text input, so bare letters are free there.
The command palette has a text input, so only arrows and
ctrl-n / ctrl-p move its selection.
Copy mode is the one place in
the terminal where bare keys are legal: nothing typed there reaches
the shell, so it has its own context, terminal_vi.
Configuring
Add a [keymap] table to
config.toml:
keystroke on the left, action id on the right. Anything you don't
mention keeps its default. Changes apply live when you save.
[keymap] # on Linux, write ctrl-shift-… where a Mac uses cmd-… "cmd-shift-p" = "app::palette" "ctrl-w e" = "pane::equalize" "cmd-shift-]" = "tab::next" # Unbind by assigning nothing. "cmd-d" = "" [keymap.file_tree] # context-scoped tables "y" = "tree::refresh" [keymap.terminal] "cmd-shift-c" = "terminal::copy"
-
Keystrokes are
modifier-…-key, withcmd,ctrl,alt,shift, andfnas modifiers, in any order. Separate the steps of a chord with a space:"ctrl-w z". Named keys:up,down,left,right,enter,escape,tab,space,backspace,f1… On Linux,cmdmeans Super: it parses and binds, but under Hyprland, GNOME, or KDE the compositor usually takes Super combos before OmniPTY sees them, which is why none of the defaults use it. Preferctrl-shiftoralt. -
Contexts. Pairs directly under
[keymap]bind at the root and work everywhere. Subtables scope a binding:[keymap.terminal],[keymap.terminal_vi](copy mode, where bare keys are allowed),[keymap.file_tree],[keymap.workspaces], and[keymap.overlay](the theme picker and command palette). A binding in a deeper context wins over the same key at the root. -
The shell comes first. A bare key — no
cmd,ctrl, oralt— at the root or in[keymap.terminal]would hide that key from whatever you're running, so OmniPTY refuses it and tells you why. Use a modifier, or a ctrl-w chord. - Mistakes are reported, not ignored. An unknown action id (with a "did you mean" suggestion), a keystroke that doesn't parse, or a bare key in the terminal each produce a line in the error toast in the bottom-right corner. Everything else in the table still binds.
-
Starting from scratch.
replace_defaults = trueunder[keymap]drops the built-in map entirely. Every action OmniPTY ships after that is unreachable until you bind it, so prefer overriding.
Application
| cmd-, mac ctrl-, linux | open the config file in $EDITOR | app::settings |
| cmd-shift-p mac ctrl-shift-p linux | command palette | app::palette |
| cmd-alt-t mac ctrl-w shift-t linux | theme picker | app::select_theme |
| cmd-q mac ctrl-shift-q linux | quit | app::quit |
| cmd-h / alt-cmd-h mac only | hide OmniPTY / hide others — the window manager's job on Linux | app::hide / app::hide_others |
| cmd-m mac only | minimize | window::minimize |
| ctrl-cmd-f mac only | toggle full screen | window::toggle_fullscreen |
Terminal
| cmd-c / cmd-v mac ctrl-shift-c / ctrl-shift-v linux | copy / paste (bracketed); on Linux, selecting also sets the primary selection and middle-click pastes it | terminal::copy / terminal::paste |
| cmd-a mac ctrl-shift-a linux | select all | terminal::select_all |
| cmd-f mac ctrl-shift-f linux | search scrollback — ⏎ older, ⇧⏎ newer, esc closes | terminal::search |
| cmd-alt-r cmd-alt-c cmd-alt-w mac ctrl-alt-r ctrl-alt-c ctrl-alt-w linux | search toggles: regex / case-sensitive / whole word (also chips in the bar) | terminal::search_regex / …search_case / …search_word |
| ctrl-w [ / cmd-shift-v mac | copy mode — vim keys in the scrollback | terminal::copy_mode |
| cmd-k mac ctrl-shift-k linux | clear scrollback | terminal::clear_scrollback |
| cmd-↑ / cmd-↓ mac ctrl-shift-↑ / ctrl-shift-↓ linux | jump to previous / next prompt | terminal::prompt_up / terminal::prompt_down |
| cmd-r mac ctrl-shift-r linux | command history — ⏎ inserts, ⌘⏎ (ctrl-⏎ on Linux) runs | terminal::history |
| cmd-shift-c mac ctrl-shift-alt-c linux | copy the last command's output | terminal::copy_last_output |
| click a gutter tick | scroll to that command | |
| cmd-+ cmd-- cmd-0 mac ctrl-+ ctrl-- ctrl-0 linux | font size up / down / reset (ctrl-= also steps up on Linux) | terminal::font_increase / …decrease / …reset |
| cmd-click mac ctrl-click linux | open the URL, or the path:line in your editor, under the pointer | |
| cmd-p mac ctrl-shift-o linux | fuzzy file finder — ⏎ open, ⌘⏎ / ctrl-⏎ insert path, ⌥⏎ reveal | app::file_finder |
| shift + drag | select text even while a program grabs the mouse |
Tabs & windows
| cmd-t mac ctrl-shift-t linux | new tab | tab::new |
| cmd-shift-t mac ctrl-shift-alt-t linux | reopen the last closed tab (the last ten are remembered) | tab::reopen |
| ctrl-w , / double-click a tab | rename the tab; an empty name restores the automatic title | tab::rename |
| drag a tab | reorder — drop it on the tab whose place it should take | tab::move_left / tab::move_right (unbound) |
| cmd-n mac ctrl-shift-n linux | new window | window::new |
| cmd-1 … cmd-9 mac alt-1 … alt-9 linux | select tab 1–9 | tab::select_1 … tab::select_9 |
| ⌃tab / ⌃⇧tab | next / previous tab | tab::next / tab::previous |
| ⇧⌘] / ⇧⌘[ mac ctrl-pagedown / ctrl-pageup linux | next / previous tab | tab::next / tab::previous |
| cmd-w mac ctrl-shift-w linux | close the pane; the window with the last one | window::close |
Splits & focus
| ctrl-w v / cmd-d mac | split right | pane::split_right |
| ctrl-w s / cmd-shift-d mac | split down | pane::split_down |
| ctrl-w V / ctrl-w S | split left / up | pane::split_left / pane::split_up |
| ctrl-w h j k l | focus the pane in that direction | pane::focus_left / …down / …up / …right |
| cmd-opt-←↓↑→ mac only | focus the pane in that direction | pane::focus_left / …down / …up / …right |
| ctrl-w q | close the focused pane | pane::close |
| ctrl-w < / ctrl-w > | shrink / grow the pane horizontally (4 columns) | pane::narrower / pane::wider |
| ctrl-w - / ctrl-w + | shrink / grow the pane vertically (2 rows) | pane::shorter / pane::taller |
| ctrl-w = | equalise every split in the tab | pane::equalize |
| ctrl-w z | zoom the pane to the full tab; again to restore | pane::zoom |
| ctrl-w b | broadcast typing and pastes to every pane in the tab | pane::broadcast |
| ctrl-w o | close every other pane in the tab (asks when more than one would go) | pane::only |
| ctrl-w x | swap the pane with its neighbour in the split | pane::swap |
| ctrl-w r | set the pane's startup command — run when its pinned workspace is restored | pane::set_startup_command |
| drag a divider | resize the two panes either side of it | |
| ctrl-w w | toggle focus: drawer ↔ terminal | drawer::focus_toggle |
The drawer
| cmd-b mac ctrl-shift-b linux | show / hide the drawer | drawer::toggle |
| ctrl-w t / cmd-shift-e mac ctrl-shift-e linux | focus the file tree | drawer::focus_tree |
| cmd-alt-1 … cmd-alt-9 mac ctrl-alt-1 … ctrl-alt-9 linux | switch to workspace 1–9 | workspace::select_1 … workspace::select_9 |
| ctrl-w p | focus the workspaces panel | drawer::focus_workspaces |
| cmd-shift-r mac ctrl-shift-alt-r linux | reveal the shell's directory in the tree | drawer::reveal |
| tab | switch between the two panels | drawer::focus_workspaces / drawer::focus_tree |
In the file tree
| j k / ↓ ↑ | move | tree::down / tree::up |
| gg / G | top / bottom | tree::top / tree::bottom |
| ctrl-d / ctrl-u | half page down / up | tree::half_page_down / tree::half_page_up |
| l / h | expand & descend / collapse & ascend | tree::expand / tree::collapse |
| p | select the parent directory | tree::parent |
| enter / o | open a directory, or a file in $EDITOR | tree::open |
| y / Y | insert the path at the prompt, relative / absolute | tree::yank_path / tree::yank_path_absolute |
| cmd-c mac ctrl-shift-c linux | copy the path | tree::copy_path |
| cmd-shift-o mac ctrl-shift-o linux | reveal in Finder / the file manager | tree::reveal_in_finder |
| P | preview the selected markdown file | tree::preview |
| right-click | open, preview markdown (.md files), set as root, new file or folder (directories), insert path, copy path, rename, move, reveal in Finder / the file manager, delete | |
| right-click the root's name, or under the last row | new file or folder in the root, copy its path, reveal it | |
| — | cd the shell to the selection without re-rooting (only differs with follow_cwd = false) | tree::cd |
| drag a row onto a pane | insert the path at the prompt | |
| drag a row onto another | move it into that directory (or beside that file); below the last row moves it to the root. The tree scrolls when the drag nears its top or bottom | |
| drag the drawer's right edge | resize the drawer; double-click it to go back to tree.width | |
| c / - | re-root at the selection / one level up | tree::set_root / tree::root_up |
| / | filter | tree::filter |
| a r m d | add / rename / move / delete to Trash | tree::add / tree::rename / tree::move / tree::delete |
| I / R | toggle hidden files / refresh | tree::toggle_hidden / tree::refresh |
| esc | dismiss input → clear filter → back to the terminal | tree::escape |
In the workspaces panel
| j k / ↓ ↑ | move | workspace::down / workspace::up |
| enter / o | switch to the workspace | workspace::open |
| a r d | add / rename / delete (y confirms); a row's × deletes without asking | workspace::add / workspace::rename / workspace::delete |
| p | pin — persist across restarts | workspace::toggle_persist |
| e | edit every pane's startup command | workspace::edit_startup_commands |
| drag a workspace | reorder — drop it on the workspace whose place it should take | |
| esc | dismiss input → back to the terminal | workspace::escape |
In the palette, history, file finder, and theme picker
| ↓ ↑ / ctrl-n ctrl-p | move (the theme picker previews as you go) | overlay::next / overlay::prev |
| j k | move — theme picker only; the palette is typing | overlay::next / overlay::prev |
| enter | run the command / apply the theme / insert the history entry | overlay::confirm |
| cmd-enter mac ctrl-enter linux | in history: run the entry; in the file finder: insert the path | overlay::confirm_alt |
| alt-enter | in the file finder: reveal in the tree | overlay::confirm_reveal |
| esc | close, restoring focus (and the previous theme) | overlay::cancel |
| opt-← opt-→ mac ctrl-← ctrl-→ linux | in any text field: move by word | |
| opt-delete mac ctrl-backspace linux | in any text field: delete the word before the cursor | |
| cmd-← cmd-→ / ctrl-a ctrl-e | in any text field: jump to the start / end |
In copy mode
ctrl-w [ turns the scrollback into a vim buffer. These
keys are fixed — they're vim's — but anything else can be bound in
[keymap.terminal_vi], bare keys included, since
nothing typed here reaches the shell.
| h j k l / arrows | move; a count prefix repeats (5j) | |
| w b e / W B E | word motions — punctuation-aware / whitespace-delimited | |
| 0 ^ $ | line start / first non-blank / line end | |
| gg G / H M L | top / bottom of the buffer; top / middle / bottom of the screen | |
| ctrl-d ctrl-u / ctrl-f ctrl-b | half page / full page down and up | |
| % / { } | matching bracket / paragraph | |
| / ? then n N | search forward / backward from the cursor, repeat — the same bar and toggles as cmd-f / ctrl-shift-f; ⏎ parks the cursor on the match | |
| v V ctrl-v | character / line / block selection; motions extend it | |
| y / yy / ⏎ | yank the selection (or the line) to the clipboard and leave | |
| esc / q | clear the selection, then leave; ctrl-w [ also toggles out | terminal::copy_mode |
Commands without a default binding
These have no default key. They live in the menus at the path
shown — the macOS menu bar, or the ☰ button in the top-left
corner of a Linux window. Every one is also in the command
palette (cmd-shift-p / ctrl-shift-p) and
can be bound in [keymap]:
| Window → Move Tab Left / Right | reorder without the mouse | tab::move_left / tab::move_right |
| Edit → Copy Last Command | the last command line | terminal::copy_last_command |
| Edit → Copy Last Command and Output | both together, for an issue | terminal::copy_last_block |
| View → Toggle Status Bar | show or hide the bar for this window | app::toggle_status_bar |
| View → Toggle Tab Bar | show or hide the tab bar for this window | app::toggle_tab_bar |
| ☰ (Linux) | open the app menu from the keyboard — handy with every bar hidden | app::menu |
| File → New Workspace | create an unnamed workspace | workspace::new |
| OmniPTY → Check for Updates… | check GitHub for a newer release | app::check_for_updates |
| OmniPTY → About OmniPTY | the app icon, version, and a link to the site | app::about |
| Window → Zoom | zoom the window | window::zoom |
| Help → OmniPTY Help / Report an Issue | open the docs / a new issue | app::help / app::report_issue |
| Help → What's New | open the changelog in a new tab | app::changelog |