# tmuxrdr roadmap: what only patching herdr can do What is left of tmux's default prefix table, and of this machine's tmux.conf, after `tmuxrdr/config/config.toml` and the tmux-mode plugin (`tmuxrdr/plugin`). Each gap: what tmux does, why neither config nor plugin reaches it, and the patch -- with touch points checked against the herdr v0.9.3 source, the base this branch sits on. Each becomes one commit on the `tmuxrdr` branch, kept small for rebasing (README.md, "Maintaining"). Applied so far: tmuxrdr's own directories -- `app_dir_name()` in `src/config/io.rs` returns `tmuxrdr` -- so it runs beside stock herdr; and tmux's status line as the tab row (`ui.tab_style = "tmux"`, `src/client/shell/tabs_tmux.rs`). None of the patches below is applied yet. ## Coverage tmux 3.7c's default prefix table has 88 bindings (`tmux -L x -f /dev/null start-server \; list-keys -T prefix`). With this machine's tmux.conf on top: - **67 bound** in config or plugin, each pressed in a tmuxrdr client (run in a throwaway tmux on its own socket) and its effect checked through the herdr CLI -- except `M-n`/`M-p`, seen only to do no harm with no agents running, and of `1`..`9` only 1 and 3. Approximate rather than exact: `w` `f` `q` (herdr's navigator), `/` (help, filtered), `C` (settings), `M-n` `M-p` (agents, not alerts), `E` (evens the whole tab, not just the current pane's neighbours), the C-/M-arrow step sizes (fractions of the area, not cells), and window indexes (positions -- see "Stable window indexes"). - **5 moot**: `S-Up` `S-Down` `S-Left` `S-Right` and `DC` pan or reset the view of a client smaller than its window. Herdr always sizes a tab to its client. - **16 need a fork**: `Space`, `M-1`..`M-7`, `<`, `>`, `#`, `=`, `-`, `D`, `C-z`, `PPage` -- below, with the behaviours a binding cannot carry. ## Where patches go Building, installing and rebasing are in README.md. For the patches below: the keybinding layer is compact -- adding an action touches four files: `src/config/keybinds.rs` (config field, parser), `src/input/keybindings.rs` (`KeybindAction`, resolver table), `src/client/shell/input.rs` (mode dispatch), `src/client/shell/actions.rs` (what it does). Put the logic in new files where it can live apart, so the lines that touch upstream's stay few. ## Patches, smallest first ### 1. PageUp/PageDown/Home/End/Delete/Insert key names -- tmux `PPage` - tmux: `prefix+PPage` is `copy-mode -u`, copy mode scrolled up a page. - Gap: `parse_key_combo` (`src/config/keybinds.rs`, the `match lower.as_str()` near line 1303) knows no `pageup`, so nothing can bind it -- upstream issue #4892, "Keybinding will not accept PageUp", opened 2026-10-04. Copy mode is client-side and not in the CLI, so no plugin can enter it either. - Patch: six arms in that match (`"pageup" | "ppage" => KeyCode::PageUp`, ...); a `copy_mode_page_up` action that enters copy mode and applies the page-up path `src/client/shell/copy_mode.rs` already has (`KeyCode::PageUp`, line 161). Bind `prefix+pageup`. Small; the key names alone are a likely-accepted upstream PR. ### 2. Repeatable bindings -- tmux `-r`, repeat-time 500 ms - tmux: arrows (select-pane), C-arrows and M-arrows (resize) repeat -- prefix once, then the arrow as often as wanted within 500 ms of the last. - Gap: `src/client/shell/input.rs`, the `ClientShellMode::Prefix` arm, sets `self.mode = return_mode` before running any binding: prefix mode is one key, always. herdr's resize mode (`prefix+ctrl+r` here) is the nearest. - Patch: a `repeat` flag on bindings (config: a `keys.repeatable` list of action names, plus `repeat = true` on `[[keys.command]]` for the C-arrow commands) and `keys.repeat_time` (ms, default 500). After a repeatable binding, stay in Prefix with `prefix_repeat_deadline = now + repeat_time`; on the next key past the deadline, drop to terminal mode and route the key as typed -- tmux checks on the key too, so no timer is needed. Small to medium. ### 3. synchronize-panes -- tmux.conf's ``bind ` setw synchronize-panes`` - tmux: every pane of the window gets the keys typed into one. - Gap: no API takes input once for many panes, and input routing is in the client. Upstream discussion "Hotkey / Toogle to Synchronize Input to All Panes in a Workspace" asks for exactly this. - Patch: a per-tab `synchronized` flag and a `toggle_synchronize_panes` action; in `input.rs`'s Terminal arm, where keys go to `self.focused_pane_id().map(ClientInputTarget::Pane)` (line 577), fan out to every pane of the tab while the flag is set; mark it in the tab bar. Small to medium. ### 4. C-z suspend-client - tmux: stops the client (SIGTSTP) and returns to the shell that started it; `fg` brings it back. - Gap: client-only; nothing in the client handles it (no SIGTSTP in `src/client`). - Patch: an action that leaves the alternate screen and raw mode, raises SIGTSTP, and on SIGCONT re-enters them and forces a full redraw. Small. (Under `exec herdr` from a terminal emulator there is no shell to return to -- tmux has the same problem -- so this matters only for herdr started by hand.) ### 5. Stable window indexes -- tmux's renumber-windows off - tmux: closing window 2 of 3 leaves 1 and 3; prefix+3 still reaches the third. - Gap: herdr shows an unnamed tab's place (`tab_display_name`, `src/workspace.rs` line 442: `tab_idx + 1`) and switch_tab counts places (`src/client/shell/actions.rs` line 955), so tabs renumber on every close -- tmux with renumber-windows on. - Patch: a `ui.stable_tab_numbers` option showing each tab's public number (already kept: `next_public_tab_number`) and making switch_tab, `0` and `'` select by it. Small. Optional -- many tmux users set renumber-windows on. ### 6. `<` `>` window and pane menus - tmux: prefix+< and prefix+> open the window and pane menus. - Gap: herdr's menus are right-click only (`src/client/shell/context_menu.rs`); no action opens one from the keyboard. - Patch: `open_tab_menu` and `open_pane_menu` actions opening the existing menus anchored on the focused tab and pane. Small to medium. ### 7. Marked-pane border - tmux: the marked pane's border is highlighted. - Gap: plugins cannot style borders; tmux-mode toasts "pane N marked" instead. - Patch: a `marked` pane flag settable over the socket, drawn by the border rendering in `src/ui/panes.rs`; the plugin then sets it. Small. ### 8. Layouts -- `Space`, `M-1`..`M-7` - tmux: next-layout and select-layout even-horizontal, even-vertical, main-horizontal, main-vertical, tiled, and the two mirrored mains, with main-pane-width 80 and main-pane-height 24. - Gap: a tab is a BSP tree (`Node`, `src/layout.rs` line 73). The socket can set split ratios (`layout.set_split_ratio`, which tmux-mode's `E` uses) but not move a pane within its tab (`pane move` to the same tab reports `changed: false`), and `layout.apply` replaces the tab and kills its processes. A plugin could round-trip every pane through temporary tabs (`pane move` keeps a pane's process) and rebuild the tree -- it works on paper, flickers through tab creation in practice, and is not done here. - Patch: `Layout::apply_preset(preset, ordered_panes)` in `src/layout.rs` rebuilding the tree from the pane order -- panes are ids in the tree, so their processes are untouched -- with the seven presets and tmux's main-pane sizes; `select_layout_*` and `next_layout` actions (per-tab index for the cycle). Medium. ### 9. display-panes -- `q` - tmux: numbers on every pane for display-panes-time (1 s); a digit picks one. - Gap: needs an overlay over the panes and a timed input mode. herdr's navigator stands in on `q`. - Patch: a `DisplayPanes` client mode with a deadline, the numbers drawn by `src/client/shell/render.rs`, digits focusing the pane. Medium. ### 10. Paste buffers -- `#` `=` `-` - tmux: a stack of copied buffers (buffer-limit 50); list-buffers, choose-buffer, delete-buffer. - Gap: herdr writes copies straight to the system clipboard (`write_clipboard`, `src/platform/macos.rs` line 631), and plugins see no copy event, so nothing can keep a history. tmux-mode's `]` pastes the clipboard, which is tmux's newest buffer. - Patch: push each copy onto a capped buffer list as it is written; a buffer view for `#`, a picker for `=` that pastes through the bracketed-paste path `pane send-text` already uses (`encode_api_text`, `src/app/api_helpers.rs`), delete for `-`. Medium. ### 11. A mouse drag enters copy mode - tmux: a drag enters copy mode (`MouseDrag1Pane` -> `copy-mode -M`); this machine's tmux.conf unbinds `copy-mode-vi MouseDragEnd1Pane`, so the selection stays there for `y` (its copy-pipe binding), `Enter`, or more vi movement; double- and triple-click do the same with a word or a line. - Gap: herdr's mouse selection is separate from copy mode (`mouse.rs`): kept (copy_on_select = false) it copies only on Ctrl+C, and `y` goes to the pane. tmuxrdr's config copies on release meanwhile. - Patch: on drag release (and double/triple click), enter copy mode for that pane with the selection carried over -- copy mode's selection is an anchor and a cursor (`ClientCopySelection::Character`), in the same absolute pane coordinates as the mouse selection (`sync_copy_selection`). Logic in a tmuxrdr file, hooked from `mouse.rs` and `word_selection.rs`. Small to medium. ### 12. `D` choose-client - tmux: lists attached clients; pick one to detach. - Gap: no client list in the CLI or UI. - Patch: a client registry query on the server and a picker. Medium; low value on a single-user machine.