Files
Codeman/docs/wiki/Keyboard-Shortcuts.md
T
Michael GrundbergandClaude Opus 5 f9edb33d15 fix(terminal): trim the padding and shared indent out of a copied selection
xterm hands back whole screen rows and trims only the cells that were
never written to, so the real spaces a full-screen TUI paints across the
unused part of a row count as content and reach the clipboard. Measured
against Claude Code in a 282-column pane, single lines arrived carrying
138 trailing spaces, and every line carried the two-space transcript
indent as well. Windows Terminal, iTerm2 and GNOME Terminal all trim that
for you, decideAutoCopy already calls a wall of spaces "never what the
gesture meant", and _selectTouchSelectionLine already treats those cells
as padding — the mouse and keyboard paths never had the same rule.

CodemanCopySelection.clean lives in constants.js beside decideAutoCopy,
its pure sibling. It drops the trailing run from each line, and removes
the leading run only where every selected row shares one. A selection of
a single row keeps its run, because one row shares nothing with anything
and stripping it would silently reindent one line of `git log` body text
or one line out of `less`. A drag that began inside a row keeps its
partial first line untouched and out of the measurement, which otherwise
pins the shared run to zero and leaves every following row indented.

Every pass over a line is a scan rather than a regex. `/[ \t]+(\r?)$/` is
quadratic on a line whose spaces are followed by a non-space character,
which is what right-aligned or centred TUI content looks like: measured
over 50 000 rows with a 280-column run it took 2.9s, against 1.3ms for
the scan, and a 2 000-column run took 16s. The scan is also the faster of
the two on an ordinary padded row.

cleanedTerminalSelection in terminal-ui.js is the half that needs the
live terminal. It returns a COLUMN selection untouched: Alt+drag makes
one, and a rectangle's rows lining up is the point of the gesture, so
both halves of the clean would destroy it. xterm exposes the mode nowhere
public, so the check reads terminal._core._selectionService, the way this
file already reads terminal._core for cell dimensions, and cleans
normally if a future xterm renames the field. A test pins that assumption
against the library rather than against a stub repeating the literal.

The Ctrl+C chord decides on the cleaned selection, not the raw one. A
drag across the blank part of a row selects real padding spaces, so the
raw text is truthy, and testing it would spend that press on a copy of
nothing and make the user press again to interrupt. A padding-only
selection is now dropped and the press falls through to the PTY, while
Ctrl+Shift+C still never falls through. copyTerminalSelection gates on
trim() for the same reason, since a multi-row drag across padding cleans
to line breaks alone and a bare newline pasted into a chat composer
submits it.

All four of the main terminal's copy paths go through it: the Ctrl+C
chord, right-click, the phone selection button and Auto Copy. The
browser's own Edit menu copy, a disabled copy shortcut and the subagent
windows still copy raw rows, as they did before, and the invariants doc
now says so rather than claiming every copy is cleaned. Auto Copy
resolves its own toggle before it reads the selection, since it is off by
default and a selection can run to the 50 000-row scrollback ceiling.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 20:18:25 +02:00

4.6 KiB

Keyboard Shortcuts

Every binding, and how to change them. Ctrl also accepts Cmd on macOS.

Press Ctrl+? in the app for the same list in a floating overlay.

Sessions and tabs

Shortcut Action
Ctrl+K (also Cmd+K, Alt+K) Find an open session or start a new one.
Ctrl+W Kill the active session.
Ctrl+Tab Next session.
Alt+[ / Alt+] Previous / next tab.
Alt+1 to Alt+9 Switch to tab N. Physical keys, so macOS Option layouts work.
Ctrl+Shift+{ / Ctrl+Shift+} Move the active tab left / right.
Alt+B Collapse / expand the session sidebar, when that layout is on.

Terminal

Shortcut Action
Enter Send.
Shift+Enter Insert a newline without sending.
Ctrl+Enter Same.
Ctrl+C Copy the selection, or interrupt when nothing is selected.
Ctrl+Shift+C Copy the selection. Never interrupts.
Ctrl+V Paste. An image on the clipboard uploads and pastes its file path instead.
Ctrl+L Clear the terminal.
Ctrl+Shift+R Restore terminal size.
Ctrl + / Ctrl - Font size.
Shift+Wheel Scroll the local buffer, even where the wheel is forwarded to the CLI.
Shift+drag Start a selection in a pane whose mouse events go to the CLI.
Right-click Copy the selection. With nothing selected the native menu is left alone.
Ctrl+Z Swallowed in agent sessions so a running CLI cannot be suspended. Normal job control in a shell.

Anything you copy is cleaned on the way to the clipboard. Each line loses the padding spaces a full-screen program paints across the rest of the row, and a selection covering several rows also loses the indent every one of those rows shares, which is usually the program's own margin rather than your text. A one-row selection keeps its indent, and an Alt+drag rectangular selection is copied exactly as it looks, so its columns stay lined up.

Everything else

Shortcut Action
Ctrl+Shift+V Toggle voice input.
Ctrl+? Shortcut reference overlay.
Escape Close panels and modals.

Rebinding

App Settings → Shortcuts. Bindings live in a registry with per-user overrides, so a rebind is stored as an override on top of the default rather than replacing the table.

Two things are deliberately not rebindable:

  • Ctrl+C smart copy. The generic dispatch loop calls preventDefault() on every shortcut it handles, and doing that to Ctrl+C would swallow the interrupt when nothing is selected. It is handled separately for that reason.
  • Escape, which closes whatever is open.

Why some chords behave oddly

The terminal sees keystrokes before the app does. Any chord the app claims has to also be swallowed at the terminal layer, or xterm writes the control byte into the session as well as triggering the action. If you rebind something to a chord the terminal cares about (Ctrl+D, say), expect the CLI to see it too.

Alt+1 through Alt+9 are matched on physical key position rather than the character produced, so macOS Option layouts that produce ¡™£ still switch tabs.

On phones

There is no physical keyboard, so the equivalents live in the keyboard accessory bar: Esc, Ctrl as a one-shot modifier, Tab, arrows, and quick actions. See Mobile Guide.