OdyTTY Feature Reference
September 5, 2026 · View on GitHub
Use this guide to understand OdyTTY's terminal behavior, configure the native app, and work with tabs, panes, workspaces, remote hosts, and shell integration. For installation and a shorter overview, start with the README.
Contents
- Configuring OdyTTY
- Terminal Compatibility
- Text, Emoji, And Graphics
- Tab And Pane Workflow
- Shell Integration
- Settings And Themes
Configuring OdyTTY
Most customization happens inside OdyTTY. Hand-editing a config file is optional: the settings panel, pickers, and command palette provide the primary in-app paths. For a shorter tour of what ships enabled and which opt-ins fit particular workflows, start with the settings guide.
| Task | Where to do it | What happens |
|---|---|---|
| Browse and edit settings | Ctrl+Shift+, | Changes apply live in the terminal behind the panel |
| Find a setting | Press / inside Settings | Filters by name, config key, description, or group |
| Save changes | Ctrl+S inside Settings | Writes only changed rows to odytty.conf |
| Choose a theme | Ctrl+Shift+H or Settings → Themes | Opens the theme picker |
| Choose a font | Open a font row in Settings → Fonts | Opens the bundled and system font picker |
| Run an action | Ctrl+Shift+P | Opens the command palette |
| Configure tabs and panes | Settings → Layout | Groups Tabs, Workspace rail, Panel, and Panes |
The settings panel is keyboard- and pointer-driven. Arrow keys move through
sections and rows, Enter activates a choice, and Esc clears a search or
closes the panel. Clicking a numeric row starts text entry; the first keystroke
replaces the prefilled value so a new number can be typed directly.
Ctrl+Shift+, and Settings from the terminal content menu open the section
list. Settings from the empty tab strip, a workspace slot, or the empty
workspace rail opens Layout directly.
Edits apply live, but the config file is not changed until you press Ctrl+S.
Saving uses a preservation-first writeback: comments, blank lines, key order,
and unknown or future keys stay in place, while changed keys are rewritten and
missing changed keys are appended. OdyTTY saves through a same-directory
temporary file and rename instead of truncating the file in place.
odytty.conf and hosts.conf share a single-writer, temporary-file, sync, and
atomic-rename path. On Unix, a new file is created with mode 0644; a stricter
existing mode is preserved, while group/other-write and execute bits are
clamped back to that 0644 ceiling. Windows preserves inherited ACLs.
Settings resolve in this order:
| Priority | Source | Intended use |
|---|---|---|
| 1 | Built-in defaults | A complete usable setup |
| 2 | odytty.conf | Durable preferences |
| 3 | ODYTTY_* environment variables | Session-scoped overrides |
On Unix, the config path is $XDG_CONFIG_HOME/odytty/odytty.conf, falling back
to ~/.config/odytty/odytty.conf. On Windows it is
%APPDATA%\odytty\odytty.conf. OdyTTY polls the resolved file about once per
second and applies valid external edits live; environment-pinned values remain
pinned for that session.
The optional file format is dependency-free key = value text with #
comments:
theme = odyssey-default
font_family = Victor Mono
font_size = 20.0
render_quality = high
See Runtime Knobs for every config key, environment variable, range, default, and reload rule. The annotated config is a starting point for readers who prefer to edit the file.
Terminal Compatibility
OdyTTY owns its parser and terminal model. The supported surface covers common shells and full-screen terminal applications:
| Area | Supported behavior |
|---|---|
| Text and attributes | Printing, UTF-8 chunking, SGR attributes including legacy SGR 21 double underline, 256-color, and truecolor |
| Cursor and editing | Cursor movement including CNL/CPL line-relative redraw controls, erase, insert/delete character and line, insert/replace mode (IRM), repeat, and reverse index |
| Screen state | Scroll regions, origin mode, tab stops, bracketed paste, focus reporting, and alternate-screen modes 47/1047/1048/1049 |
| Character sets | G0/G1 designation, SO/SI selection, and DEC Special Graphics mapping for ncurses ACS line drawing |
| OSC sequences | OSC 0/2 titles, OSC 7 working directories, OSC 8 hyperlinks, bounded OSC 9/777 notifications, OSC 9;4 progress, OSC 52 clipboard write plus opt-in read, OSC 133 prompt marks, and OSC 4/10/11/12 dynamic colors |
| Queries and controls | DECRQM/DECRPM, XTWINOPS, XTGETTCAP, DECRQSS, rectangle operations, selective erase, and synchronized output mode 2026 |
| Pointer input | Broad mouse reporting, including X10, normal, button-event, any-event, focus events, UTF-8, SGR, urxvt, legacy encodings, and SGR-pixel mode 1016 |
| Keyboard input | Mode-aware legacy encoding, negotiated Kitty keyboard protocol, and IME composition |
SGR-pixel mode reports true physical pixel coordinates from the native window.
Alternate scroll mode 1007 is on by default and translates the wheel into
cursor-key presses on the alternate screen. Full-screen applications that do
not track the mouse therefore scroll at the configured scroll_wheel_lines
rows per notch.
The Kitty keyboard protocol is a negotiated overlay. With no Kitty flags
active, legacy bytes are preserved. Under the disambiguate flag, modified
Enter/Tab/Backspace (for example Ctrl+Enter, Shift+Enter,
Ctrl+Backspace) become distinct CSI-u sequences while the unmodified keys
stay on their legacy bytes.
xterm's modifyOtherKeys (XTMODKEYS, levels 1 and 2) is supported as a
compatibility layer for applications that select it by TERM — Vim's default
keyprotocol and emacs both do under xterm-256color, and tmux negotiates
extended keys through it. Modified keys encode as
CSI 27 ; modifier ; codepoint ~, the level is per-screen with the same
reset behavior as the Kitty flags, and XTQMODKEYS reports it. When an
application enables both protocols (fish does), non-zero Kitty flags win.
On Windows, a console application can request ConPTY Win32 input with DEC
private mode 9001. While that mode is active, OdyTTY sends complete Win32 key
records, including key-up state, virtual-key and scan codes, Unicode text,
modifier flags, and repeat counts. This preserves input such as
Ctrl+Backspace word deletion in PowerShell and distinct Shift+Enter.
The application requests the mode; there is no OdyTTY setting, and the mode is
inert on Unix. When it is inactive, Kitty, modifyOtherKeys, and legacy input
continue through their normal selection rules.
On Linux display stacks, editing keys are normalized before shortcut and PTY
dispatch whether the compositor reports a named key or its translated control
character. Backspace, Tab, Shift+Tab, Enter, Escape, and forward Delete retain
their ordinary behavior; at an enhanced Bash or Zsh prompt,
Ctrl+Backspace remains distinct and word-deletes. Fish continues to manage
its own keyboard protocol.
Paste Safety
OdyTTY's risky-paste confirmation is a structural safeguard for text entering a child that has not enabled terminal bracketed-paste mode. It does not try to understand shell syntax or decide whether a command is safe. The child application controls bracketed-paste mode; interactive shells and editors such as Fish commonly enable it while their input editor is active. In that normal case OdyTTY preserves the existing bracketed transaction without adding a second confirmation dialog.
With warn_on_risky_paste = on (the default), the dialog opens only when all
of these conditions are true:
- A native text paste is requested for the active pane.
- The destination child currently reports bracketed-paste mode as disabled.
- The original text contains a CR or LF line break, or a Unicode control character other than Tab.
| Original text and destination state | Result |
|---|---|
| Single line with ordinary text, Unicode, or tabs; bracketed paste off | Paste directly |
| CR, LF, CRLF, empty lines, or another control character; bracketed paste off | Show the risky-paste dialog |
| Any text while the child has bracketed paste on | Preserve the existing bracketed-paste path; no dialog |
Any text with warn_on_risky_paste = off | Use the historical encoder; no dialog |
Classification examines the complete original transaction before any line ending normalization. The dialog escapes controls for display, caps the rendered preview at 512 UTF-8 bytes, and reports exact original line and byte counts even when the preview is truncated. Raw clipboard text stays in transient application state: it is not logged, persisted in a workspace, placed in diagnostics, or copied into notification text.
The choices have explicit behavior:
- Paste sends the held original text through the existing encoder. It does not append Enter or split the confirmation into implicit commands.
- Paste as One Line is offered only for multiline text without another
disallowed control and when the reversible result is at most 32 MiB. It
displays CR/LF as visible
\\r/\\ntext and doubles existing backslashes; it does not silently discard or merge source bytes. - Cancel writes nothing. Focus loss, a destination-pane ownership change, pane exit, window close, preview setup failure, or a stale bracketed-paste state also cancels the held paste.
Shortcut, command-palette/menu, context-menu, Linux PRIMARY, external text
drop, and authorized automation paste routes use the same policy. PRIMARY has
no platform surface on macOS or Windows. The setting can be changed through
Settings, warn_on_risky_paste in odytty.conf, or
ODYTTY_WARN_ON_RISKY_PASTE; disabling it is an advanced global opt-out.
A bracketed paste is queued as one transaction containing the opening marker,
sanitized text, and closing marker, so unrelated input cannot split the frame.
A bracketed paste whose complete framed payload exceeds
MAX_BRACKETED_PASTE_BYTES = 32 MiB is refused whole. Plain, non-bracketed
paste has no comparable whole-payload rejection and remains deliberately
chunked. With child bracketed-paste mode off, original multiline or
control-bearing text is held behind a bounded escaped preview before PTY
writing. The dialog reports original line and byte counts and offers Paste,
reversible Paste as One Line when available, or Cancel. Safe single-line and
child-enabled bracketed paste retain their existing byte behavior.
IME pre-edit appears inline at the cursor and committed text is sent to the shell. This supports CJK input methods and compose-key or dead-key accents.
The terminal bell (BEL) has no audible mode:
bell value | Behavior |
|---|---|
urgent | Requests window attention when unfocused; this is the default |
visual | Shows a brief, readability-safe screen flash |
all | Requests attention and shows the flash |
off | Disables bell feedback |
Text, Emoji, And Graphics
Render Text And Symbols
Victor Mono is bundled and selected by default at 20 logical pixels with line
height 1.0. JetBrains Mono is also bundled and selectable through
font_family.
The font picker separates always-available Bundled Fonts from host System Fonts. Its bundled symbol fallback is a chain of Nerd Fonts v3 and v2 faces, so PUA prompt icons work without a host-installed Nerd font and remain compatible with configs from either Nerd Font era.
Bundled and discovered system families both resolve without hand-written configuration.
With wheel_zoom enabled, Ctrl+wheel changes the live font size when the
running application has not claimed mouse reporting. Each effective step shows
a compact centered font-size HUD, replaces the previous value during a gesture,
and clears after one bounded delay without animation.
| Text control | Support |
|---|---|
| Font sources | Bundled families, system families, and direct font files |
| Styling | Font-weight variants, synthetic styles, and subpixel antialiasing |
| Programming ligatures | Default-on calt+liga for ASCII plus a curated non-ASCII operator allowlist; optional off-by-default ss01/ss02; Arabic joining forms in logical LTR cell order; grid-aligned source cells |
| Fallback | Per-range symbol maps and bundled Nerd Font v3/v2 faces |
| Readability | Linear-light color composition, glyph coverage gamma, stem darkening, and minimum-contrast enforcement |
Fresh profiles enable contextual programming ligatures from the selected text
font. Shaping runs cover eligible ASCII graphics, a curated allowlist of
common non-ASCII operators and arrows, and Arabic joining bases, and change
only presentation: the terminal model keeps one logical character per cell, so
copying, selection, search, cursor placement, and wide-cell behavior retain
their ordinary semantics. Latin/operator runs enable OpenType calt and
liga together; optional stylistic sets ss01 and ss02 are off by default
(ss01 = on / ODYTTY_LIGATURE_SS01=on, and likewise for ss02). Arabic
joining is shaped in logical left-to-right cell order - not bidi
reordering; RTL visual layout remains deferred. Unsupported fonts and runs
render through the normal per-cell path. Set ligatures = off in Settings or
configuration, or ODYTTY_LIGATURES=off for one launch, to restore scalar
rendering; the setting reloads live.
The support boundary is explicit:
| Surface | Current support | Standing position |
|---|---|---|
| Latin and programming operators | ASCII calt+liga, a curated non-ASCII operator allowlist, and opt-in ss01/ss02 overlays | More curated operators and bounded, explicit font-feature settings are candidates within the current overlay model |
| Arabic | Contextual joining forms in logical left-to-right cell order; combining-marked cells stay on the monochrome path | More joining-script coverage that requires no visual reordering is a candidate; this is not bidirectional layout |
| Full Unicode bidirectional layout | Not supported | Outside the current overlay model. Correct support first requires line-level logical-to-visual mapping shared by rendering, hit testing, cursor movement, selection, damage tracking, and copy semantics |
| Complex Indic/Brahmic shaping | Not supported | Outside the current one-character-per-cell overlay model. Correct support requires grapheme-cluster ownership plus reordered glyph placement that remains reversible to logical cells |
| Emoji cluster rendering | VS15/VS16 presentation, flags, keycaps, skin tones, and common ZWJ clusters are reconstructed for the color-glyph renderer | Rendering support does not yet make grid width cluster-aware; sequence-aware width is tractable follow-up work |
| SVG-in-OpenType | Not supported; SVG-only glyphs use monochrome fallback | Deferred implementation work, not a cell-model conflict. It requires a bounded, non-networked SVG raster path and portable fixtures before enablement |
A partial BiDi or complex-script approximation is not planned: visual order that disagrees with cursor, selection, search, or copy behavior would weaken terminal correctness. The detailed prerequisites, acceptance boundaries, and measurement are in the text shaping roadmap.
The independent 2026-08-16 review's ucs-detect run covered 85 languages and
recorded an aggregate 81.2% check pass rate. Failures appeared in 22 language
cases, all Brahmic or derived from Southeast Asian Brahmic scripts; the run
reported none in its Latin, Cyrillic, Greek, CJK, Hebrew, or non-conjunct Arabic
cases. This is a result for that corpus, not a percentage of languages OdyTTY
claims to support.
Decomposed combining marks stay attached to their base glyph in the monochrome text path. Wrapped and rectangular selection copy the base followed by its marks in stored order. If the active font lacks a combining mark, OdyTTY omits that mark instead of drawing a tofu box over the base glyph.
Supported box-drawing, block and shade elements, Braille, Powerline separators,
and Symbols for Legacy Computing sextants and octants use OdyTTY's procedural
cell coverage instead of font outlines. The coverage meets its cell edges
exactly, keeping TUI borders, graphs, and prompt separators crisp and seamless
at every font size. geometric_boxdraw is on by default; box_thickness tunes
line weight when a different visual density is preferred.
Text colors are composed in linear light, with an sRGB surface preferred for
correct antialiased edges. text_gamma controls coverage weight independently,
and optional subpixel antialiasing uses dual-source blending on capable GPUs.
Render Color Emoji
Color emoji uses swash, Fontations, and a dedicated premultiplied-RGBA atlas.
It supports bitmap strikes through Noto Color Emoji (CBDT/CBLC) and Apple Color
Emoji (sbix), static COLR/CPAL v0 layers, and COLR v1 Paint graphs including
solid fills, linear/radial/sweep gradients, affine transforms, clipping, and
the standard composite modes. Directory discovery recognizes stock Windows
Segoe UI Emoji and other parseable COLR/CPAL faces. The shared raster and atlas
logic is platform-neutral.
Variation selectors, flags, keycaps, skin tones, and common ZWJ clusters are supported by the color-glyph renderer. This is presentation support, not a claim that the terminal grid computes sequence width: grid occupancy is still assigned per codepoint, so VS15, VS16, and ZWJ sequences can occupy the wrong number of columns even when they draw as one color glyph. Text-default symbols stay on the monochrome fallback path, missing color glyphs fall back there instead of becoming tofu, and emoji pixels are not SGR-tinted. Cluster coverage is bounded by the host font: stock Windows Segoe UI Emoji ships no regional-indicator flag glyphs, so flag clusters on a stock Windows install render as the visible letter fallback - the same behavior as native Windows applications - rather than a color flag.
Regional-indicator pairs currently total two columns by independent scalar
arithmetic, not because the grid recognizes a flag cluster. The separate
unicode-width versus Python wcwidth disagreement for a standalone regional
indicator is an ecosystem compatibility decision, not an OdyTTY defect.
Source preference is bitmap strike, then COLR v0, then COLR v1. The first two paths retain their established byte output; v1 is attempted only when they do not cover the glyph. The Windows CI assertion records how many glyphs in the installed Segoe build expose v0, v1, and v1-only coverage instead of assuming a specific system-font revision. The synthetic v1-only fixture is the portable correctness evidence when no stock v1-only glyph is observed. SVG-in-OpenType remains deferred; an SVG-only glyph falls back to the monochrome path.
Display Inline Graphics
| Protocol | Supported surface |
|---|---|
| Kitty graphics | Still-image actions t, T, p, d, and q, plus animation frame/control/composition actions f, a, and c; raw RGB, raw RGBA, and PNG data; direct and chunked-inline transports; opt-in file, temporary-file, and Unix POSIX shared-memory transports; image and placement ids; z-index; crop; cell scaling; pixel offsets; and Unicode placeholders (U=1 virtual placements resolved from U+10EEEE placeholder cells) |
| Sixel | DEC/xterm data language, RGB/HLS color introducers, repeat, raster attributes, transparency, VT340 palette, and DECSDM |
| iTerm2 inline images | OSC 1337 ; File= with inline, size, width, height (cell / px / % / auto units), and preserveAspectRatio; PNG, JPEG, and WebP containers; cursor advances below the image. Payloads are bounded by the 128 KiB OSC cap (~96 KiB of encoded file bytes) and an over-cap command is rejected whole. inline=0 downloads are never honored — no escape sequence writes files. |
Animation is supported: frame transmission (a=f), playback control (a=a),
frame composition (a=c), and single-frame deletion (d=f/d=F, requiring
an image id). Frames share the image store's byte budget, visible placements in
every active split pane advance, and a session with no animated image schedules
no extra work. Animated container formats (APNG, GIF) are still decoded as a
single still frame - animation comes from the protocol's frame commands.
Tab And Pane Workflow
OdyTTY can run many shells in one window. Tabs hold one or more panes, while workspaces group complete sets of tabs.
Open, Close, And Switch Tabs
| Task | Shortcut |
|---|---|
| Open a new tab | Ctrl+Shift+T |
| Close the active tab | Ctrl+Shift+W |
| Switch to the next tab | Ctrl+PageDown or Ctrl+Shift+' |
| Switch to the previous tab | Ctrl+PageUp or Ctrl+Shift+; |
Closing a tab closes the whole tab, including every pane it holds. Closing a single pane is a separate action, and closing the last tab in the last workspace quits OdyTTY.
The punctuation alternatives use the physical ; and ' keys for keyboards
without PageUp/PageDown. They are unavailable on layouts where those positions
produce letters, such as German O-umlaut/A-umlaut layouts; use the command
palette in that case.
Rename a tab from its right-click menu or with Rename Tab in the command palette. The custom name overrides shell title updates until an empty name clears it, and names are session-local rather than saved across restarts.
When more than one workspace exists, a tab's right-click menu adds Move to Workspace…. The picker lists the other workspaces by name and moves the clicked tab to the selected destination.
Duplicate Tab in the tab menu, or Ctrl+Shift+D, opens a fresh shell at the
active pane's working directory. It does not copy scrollback or the running
program, and a pane without a tracked directory opens in the default one.
Adjust The Tab Bar
The bar appears when two or more sessions exist. A single unnamed shell keeps the full-grid view, while a renamed single tab always shows the bar so its workflow name remains visible.
| Tab-bar control | Behavior |
|---|---|
| Always show tab bar | Keeps the bar visible with one unnamed tab; always_show_tab_bar is off by default |
| Drag the bottom edge | Sets tab_bar_height from one to five text rows |
| Double-click the bottom edge | Resets tab_bar_height to auto, the default one-row height |
The bar and a pinned workspace rail form one continuous, pixel-snapped chrome surface with no exposed background gutter. Their shared junction has one intentional resize seam, while the rail-to-content gap remains content padding. The band stays opaque enough for labels to remain legible over images and effects. Inactive tabs are dimmed; the active tab is marked by a selection-role fill and a bright, bold label. A static dot marks unseen bell activity on a background tab and clears through the existing view/switch semantics.
Labels stay centered vertically when the bar grows. Inline image placements use the same reserved rows as text, so inline graphics remain aligned with the visible grid.
Split A Tab Into Panes
| Task | Direct path |
|---|---|
| Split into columns, with the new pane on the right | Ctrl+Shift+E or Split Right |
| Split into rows, with the new pane below | Ctrl+Shift+O or Split Down |
| Close only the focused pane | Close Pane, labeled with Ctrl+b x, in a multi-pane content menu |
| Resize adjacent panes | Drag their divider |
The direct split chords follow common Linux terminal conventions and work in both single-pane and multi-pane tabs. Close Pane is hidden for a single-pane tab, where closing the tab is the only close action.
Once a tab has multiple panes, a tmux-style prefix enters a transient pane
command mode. The prefix is Ctrl+b by default and is configurable through
pane_prefix.
| Key after the prefix | Action |
|---|---|
% | Split the focused pane into columns |
" | Split the focused pane into rows |
← / → / ↑ / ↓ | Move focus to the neighboring pane |
o | Cycle focus to the next pane |
x | Close the focused pane |
z | Zoom or unzoom the focused pane while preserving its layout |
Space / = | Equalize split sizes |
Ctrl+b | Send a literal prefix to the focused pane for a nested multiplexer |
The prefix is captured only in a multi-pane tab. A single-pane shell receives
Ctrl+b unchanged, and pane_prefix=off frees it in multi-pane tabs as well.
Each pane owns an independent PTY, terminal model, scrollback, viewport, selection, search, and cursor. Selection and search highlights render in their own pane, while the search query bar stays on the focused pane.
window_padding applies at divider-facing edges as well as the outside window
and chrome edges. After a window resize or divider drag settles, every affected
pane is reconciled to the final whole-cell geometry. A pane narrowed below one
drawable cell keeps a valid one-cell PTY backing model but clips terminal
rendering and rejects cell input until it expands again.
During interactive window resize, a centered transient HUD reports the final
debounced terminal geometry as columns × rows. The initial nonzero configure
is silent, minimize events are ignored, and later updates clear 750 ms after the
last applied resize. The same static treatment works in single- and multi-pane,
plain-theme, effects, and reduced-motion paths without changing PTY state.
Inline image placements are also per-pane and clipped to the pane's
sub-rectangle. Optional inactive-pane dimming uses inactive_pane_dim, defaults
to 0.0, and is disabled by render_quality=plain; the no-dim frame remains
byte-identical.
The terminal content menu includes Settings plus Keyboard Shortcuts, Connection Manager, Command Palette, Session Replay, Manage Sessions, and Detach & switch in a launcher section. Items with a bound chord show it right-aligned. A tab's own menu provides New Tab, optional New Local Tab for a host-bound workspace, Duplicate Tab, Rename Tab, Close Tab, Close Other Tabs, Connect to Host…, Replace with Host…, optional Move to Workspace…, and New Window.
Connect to Host… opens a saved host in a new tab immediately after the clicked tab without changing the clicked shell. Replace with Host… replaces the clicked tab and asks for confirmation when that tab still has a program running.
Right-clicking the empty tab strip offers New Tab, New Workspace, Open Layout, Command Palette, and Settings.
Organize Workspaces And The Rail
Every workspace keeps its own tabs and remembers which tab was active. Switching workspaces swaps the complete tab strip, while a one-workspace session adds no extra chrome.
| Task | Shortcut or control |
|---|---|
| Create a workspace | Ctrl+Shift+Enter or the rail's + slot |
| Open the workspace picker | Ctrl+Shift+G |
| Switch to the next workspace | Ctrl+Shift+PageDown |
| Switch to the previous workspace | Ctrl+Shift+PageUp |
| Duplicate a workspace | Ctrl+Shift+Alt+D or Duplicate Workspace |
The vertical workspace rail appears when a second workspace exists. Its +
slot rests at a visible brightness, and a dead gap row above it prevents clicks
past the last workspace from opening one accidentally. A static edge dot rolls
up unseen activity from that workspace's tabs; it coexists with the independent
remote-binding marker and uses no motion effect.
An always-visible chevron at the rail's bottom edge toggles auto-hide and saves the choice. The same control remains available while an auto-hidden rail is temporarily revealed, so it can be pinned again without opening Settings.
Drag the rail's inner edge to adjust its width.
workspace_rail value | Rail placement |
|---|---|
auto | Reveals the rail after a second workspace exists; this is the default |
always | Pins the rail even with one workspace |
left | Pins the rail on the left |
right | Pins the rail on the right |
Drag a rail slot to reorder workspaces. A bright rule marks the destination;
release drops the slot, while Esc cancels without changing the order.
A short press that stays below the drag threshold remains a normal workspace switch. Auto-hide keeps the rail revealed throughout a drag, and the shared pointer path behaves the same on Linux, Windows, and macOS.
The workspace menu offers Move Up and Move Down as a non-drag reorder path with no bindable chord. It also offers New, Duplicate, Rename, Close Workspace, Bind to Host…, Unbind from Host, and Settings.
Either reorder path follows the active workspace by identity, so focus does not change, and the order persists across restart. Rename edits the label in place.
Binding a workspace routes its future tabs to the chosen saved host without changing existing tabs. The terminal content menu exposes the same New, Rename, Close Workspace, and Bind or Unbind actions for the active workspace.
Duplicating a workspace starts a fresh workspace whose first shell uses the active pane's working directory. Like Duplicate Tab, it creates a new shell rather than cloning scrollback or the running program.
The working-directory path is shared by New Tab, Duplicate Tab, and Duplicate Workspace. It behaves consistently on Linux, macOS, and Windows, where ConPTY honors the selected directory.
Close Workspaces And Handle Shell Exit
Closing the last tab in a workspace closes that workspace. Closing the last workspace quits the app.
Typing exit or pressing Ctrl+D follows shell_exit_closes:
| Value | Behavior |
|---|---|
workspace | Follows the normal tab-to-workspace-to-app cascade; this is the default |
app | Quits OdyTTY whenever the exit would close a workspace |
The app value pairs with Restore workspaces when the entire saved shape
should reopen on the next launch.
For a short-lived initial local command, launch with --hold,
--hold=true, or --hold=false. Hold is off by default. When enabled, the
exited pane reports its numeric exit status, or an explicit unknown/
possible-signal result, and remains until the next keypress. Dismissal follows
the same pane-to-tab-to-workspace-to-app cascade above. Later sessions do not
inherit hold, and a dropped remote session still shows its reconnect prompt
first.
Restore Workspaces And Open Layouts
Turn on restore_workspaces in Settings → Sessions or with
ODYTTY_RESTORE_WORKSPACES to reopen the previous window shape. It is off by
default.
Launching odytty with no arguments restores the primary instance's
workspaces, tabs, pane splits, and each pane's recorded working directory. Any
command-line argument suppresses restore.
On Unix, OdyTTY validates its final state-directory leaves as owner-private, non-symlink directories and uses owner-private regular files for layouts, snapshots, and diagnostics. State JSON is written through a private temporary sibling and atomic rename. Existing direct layout JSON files are the only entries migrated; unknown children are left untouched. A failed validation disables the affected disk sink instead of following or repairing an unexpected object. macOS preserves inherited ACL entries while tightening mode bits; Windows retains its inherited-ACL behavior.
A second window leaves restore ownership with the first and shows this notice:
Another OdyTTY window owns session restore — this window won't restore or autosave workspaces.
The snapshot records structure only. It never saves terminal output, scrollback, environment, or the commands that were running. A plain local pane therefore restores as a fresh shell at its captured directory; the live-host and remote reconnect paths below do not re-execute captured commands.
A restored remote pane reconnects through the same ssh path and opens a fresh
remote login shell at the host's default directory. It does not re-enter the
recorded remote directory or restart anything that was running.
If a remote host no longer resolves, OdyTTY opens a local shell instead. If a local directory has vanished or denies access, OdyTTY retries at the home directory; snapshots from before remote restore support also reopen those panes locally.
On Unix, a restored or instantiated pane reattaches when its detached session host is still alive. A dead host silently opens a fresh shell and OdyTTY shows a compact "N of M sessions reattached" notice.
Restore and named layouts use %LOCALAPPDATA% on Windows. Session-host
reattachment is Unix-only, so Windows restores always open fresh shells.
Save And Reopen Named Layouts
A named layout can capture either the whole app or one workspace:
| Scope | Save paths |
|---|---|
| Every workspace, tab, split, directory, and host binding | Save as Layout… in the content, rail-slot, or empty-rail menu; Save All Workspaces as Layout in the command palette |
| One clicked or active workspace | Save Workspace as Layout… in a rail-slot or content menu; Save Workspace as Layout in the command palette |
Reusing a layout name prompts to replace the existing layout, choose another name, or cancel.
Open Open Layout from the command palette, or Open Layout… from the empty rail, empty tab strip, or content menu. When the current window already contains real state, choose how to apply it:
| Choice | Result |
|---|---|
| Replace | Tears down the current workspaces and installs the saved set |
| Add | Appends the saved workspaces beside the current ones |
| Cancel | Leaves the window untouched |
A fresh window with one untouched default workspace skips this prompt and replaces that placeholder. When no layouts exist, the picker explains how to create one.
Open Local Tools
| Shortcut | Action |
|---|---|
Ctrl+Shift+F | Search scrollback |
Ctrl+Shift+, | Open Settings |
Ctrl+Shift+H | Open the theme picker |
Ctrl+Shift+B | Open the theme builder |
Ctrl+Shift+P | Open the command palette |
Ctrl+Shift+S | Open the connection manager |
Ctrl+Shift+R | Open session replay |
Ctrl+Shift+A | Open the Session Navigator (detached sessions Unix-only) |
Ctrl+Shift+C / Ctrl+Shift+V | Copy or paste |
Shift+PageUp / Shift+PageDown | Scroll the local viewport |
Ctrl+Shift+L | Open keyboard quick-select hints |
Ctrl+Shift+Space | Enter keyboard copy mode |
Ctrl+Shift+Up / Ctrl+Shift+Down | Jump to the previous or next prompt mark |
Ctrl+Shift+K | Clear the current shell input line (sends readline Ctrl+A, Ctrl+K; no shell integration required) |
Delete / Backspace | Delete selected editable prompt input when shell integration allows it |
The command palette, connection manager, session replay, theme builder, and
Manage Sessions each have a discoverable menu entry and a default
Ctrl+Shift+<letter> shortcut. A TUI cannot receive those chords, so PTY input
is unchanged.
Launcher actions appear in the content menu, while Settings → Themes includes
an Open Theme Builder entry. The command palette also carries Create
Theme From Current Colors, which captures the focused pane's live
dynamic-color state into a theme draft and opens the builder on it; inside the
builder, C does the same for the draft already being edited. See
themes.md for what is captured
versus derived.
Prompt navigation uses Ctrl+Shift+Up and Ctrl+Shift+Down. Rebind any local
action through Settings → Input, in the Key bindings row, or keybinds:
keybinds = ctrl+alt+p=command-palette
Shell Integration
Enable Prompt-Aware Actions
OSC 133 prompt marks enable prompt jumps, deleting selected editable prompt input, command-status gutters, click-to-position support when the shell advertises it, and verified command-output actions.
Shell integration is on by default. Newly spawned local bash, zsh, and
fish shells load OdyTTY's wrapper after their normal shell config; the
wrapper only adds prompt-mark hooks and never edits your rc files. Set
shell_integration = off in Settings or odytty.conf to disable it, in which
case OdyTTY still parses marks a shell emits on its own but injects no hooks.
Existing shells do not change until restarted. Bash uses an interactive
--rcfile, so login-shell-only startup files remain the shell's responsibility.
| Windows shell | Integration behavior |
|---|---|
powershell / pwsh | Loads an OdyTTY PowerShell profile through -NoExit -Command; PSReadLine drives the command-start mark |
cmd.exe | Unsupported because it has no OSC 133 hook surface |
The single switch means different things per shell, so the Settings section lists what each one delivers rather than implying a uniform capability:
| Shell | What the switch delivers |
|---|---|
bash | Prompt marks, cwd, click-to-position, button emitters; optional prompt key enhancement |
zsh | The bash set plus per-keystroke edit-region reports; optional prompt key enhancement |
fish | Prompt marks, cwd, edit region, click-to-position, button emitters; fish 4+ drives the keyboard protocol itself |
powershell / pwsh | Windows only: prompt marks, cwd, click-to-position, button emitters; key bindings use the PSReadLine/Console API, not a VT protocol |
nushell | Configure natively: set $env.config.shell_integration.osc133/osc7/osc2 and use_kitty_protocol in your nushell config; OdyTTY injects nothing |
Command-Output Actions
The command palette and terminal context menu expose these actions when the current selection is wholly inside a complete OSC 133 command range, or for the latest complete command when no selection exists:
| Action | Result |
|---|---|
| Select Command Output | Select visible output only |
| Select Command With Prompt | Select the prompt, command line, and visible output |
| Copy Command Output | Copy visible output only |
| Copy Command With Prompt | Copy the prompt, command line, and visible output |
| Search Command Output | Open search restricted to that output range |
| Jump To Previous/Next Failed Command | Navigate only explicit nonzero OSC 133 exit statuses |
| Export Command Output | Choose a native save destination and write bounded plain text |
Each range-targeting action revalidates an opaque, generation-bound handle against the live grid; failed-command navigation derives only from the current verified range set. Missing, partial, malformed, evicted, reset, reflowed, or otherwise stale marks disable the action instead of deriving a range from terminal text. Alternate-screen content has no command-output actions.
Export has a 32 MiB UTF-8 cap and never exports control sequences, OSC metadata, hyperlink targets, inline-image payloads, or private cwd metadata. The native dialog uses an application-owned neutral filename; terminal output cannot choose a path. Cancellation writes nothing. The writer leaves the selected parent directory untouched, refuses final symlinks or Windows reparse points, and uses private atomic replacement. Linux uses the XDG portal on both Wayland and X11; macOS and Windows use their native dialog implementations.
Notifications And Pane Monitors
OSC 9 and OSC 777 requests produce bounded, pane-owned attention state. OSC
9;4 produces typed progress with a bounded lifetime. Terminal-authored text is
never copied into trusted OdyTTY or desktop-notification chrome; generic
application wording is used instead. The command palette provides one-shot
command-finish, activity, silence, bell, process-finish, and command-failure
monitors plus an explicit clear action. See
notifications.md for exact sequences, caps, policy, and
independent platform behavior.
Integration applies only to shells OdyTTY launches. Nested shells, sudo, and
exec-swaps are not covered; fish survives a plain nested launch through
XDG_DATA_DIRS, and SSH tabs keep the bash bootstrap.
All four injected shell snippets percent-encode OSC 7 working-directory paths, including non-ASCII names. The Bash encoder and prompt hooks are compatible with the Bash 3.2 that ships on older macOS systems.
Prompt Key Enhancement (bash/zsh)
Set shell_key_enhancement = on (with shell_integration on) to make modified
keys reachable at the bash and zsh prompt. While the prompt is active the
shell enables the Kitty keyboard protocol in disambiguate mode, then turns it off
before each command runs so the programs the shell launches see the terminal's
default keyboard mode. Modified keys such as
Ctrl+Enter, Shift+Enter, and Ctrl+Backspace then arrive as distinct
escape sequences you can bind:
# bash (~/.inputrc)
"\e[13;5u": "run-this-command\n" # Ctrl+Enter
# zsh (~/.zshrc)
bindkey '^[[13;5u' accept-line # Ctrl+Enter
When the knob is on, the integration also ships default bindings so the keys do
something out of the box: Ctrl+Backspace deletes the previous word,
Shift+Enter inserts a literal newline for multi-line edits, and Ctrl+Enter
submits the line. Each default is skipped when you have already bound the
sequence — your ~/.bashrc/~/.inputrc and ~/.zshrc are read before the
integration, so a personal rebind always wins. To override afterwards, rebind
the sequence with bind/bindkey (for example
bind '"\e[127;5u": kill-whole-line').
fish manages the protocol itself (use bind ctrl-enter ...), and PowerShell
key bindings use Set-PSReadLineKeyHandler through the Console API, so neither
needs this knob.
Off by default, and the reason is a correctness boundary rather than taste.
Kitty keyboard flag 0x1 is defined to re-encode every Ctrl+key as a CSI-u
sequence — the protocol specification states that with disambiguation on,
Ctrl+C no longer generates SIGINT and is delivered as an escape code instead.
OdyTTY implements that faithfully, so for as long as the flag is set the terminal
emits no 0x03, the tty line discipline never sees an INTR byte, and no
interrupt is raised. Ctrl+D (0x04, EOF) and Ctrl+Z (0x1a, SIGTSTP) go the
same way.
That is survivable only for a line editor that speaks CSI-u, and neither
readline nor ZLE does out of the box — unbound CSI-u arrives at the prompt as
literal text. Zsh can at least be taught to recover, because send-break is
bindable:
bindkey '^[[99;5u' send-break # Ctrl+C
Readline has no equivalent: it exposes no function that raises SIGINT, so Bash
has no route back to a working Ctrl+C while the flag is set. Turning this on is
a deliberate trade — three enhanced binds in exchange for hand-binding every
Ctrl+key your prompt still needs.
Bash 4.4 and newer remove the prompt-only disambiguation flag through PS0
after readline accepts a command and before it runs. Bash 3.2 and other older
versions do not expand PS0, so the wrapper uses a prompt-guarded first-real-
command DEBUG boundary instead. Both paths remove the flag before child
programs run and preserve existing scalar or array-valued PROMPT_COMMAND
hooks.
The command-status gutter is on by default. Each visible pane derives its own
thin green or red bar from completed OSC 133 command marks, its own scrollback
viewport, and its pane origin. Bash status capture spans existing
PROMPT_COMMAND helpers, while PowerShell preserves native exit codes and maps
a failed cmdlet with no nonzero $LASTEXITCODE to failure. Turning
command_status_gutter off leaves the margin untouched without disabling the
underlying prompt marks.
For manual setup, SSH or login shells, or explicit rc management, print and source the integration:
eval "$(odytty shell-integration bash)"
eval "$(odytty shell-integration zsh)"
odytty shell-integration fish | source
Until prompt input marks are active, the content menu disables Cut and Delete
for prompt input and shows an Enable shell integration in Settings hint.
A plain Delete or Backspace with no selection still reaches the shell.
With a selection but no known prompt boundary, OdyTTY does not send blind edit bytes. It clears the stale selection and shows the same hint instead of risking a corrupted command line.
Search Actions, History, And Directories
The command palette fuzzy-filters local actions, bounded read-only shell history, and recent OSC 7 directories. A history or directory choice types its text into the active pane without pressing Enter; an action runs after the overlay closes.
Use an environment override for one session:
ODYTTY_KEYBINDS="ctrl+alt+p=command-palette" odytty
Environment values win for that session.
Replay Recent Output
Session replay is the session-replay action, bound to Ctrl+Shift+R. Recording
is off by default, so enable session_replay before opening the scrub overlay:
session_replay = on
keybinds = ctrl+alt+r=session-replay
For a one-session override:
ODYTTY_SESSION_REPLAY=on ODYTTY_KEYBINDS="ctrl+alt+r=session-replay" odytty
The local-only ring never touches disk or the network. It is capped at 600 frames or 24 MiB, whichever limit is reached first.
The overlay is presentation-only while the live session continues underneath.
Use ← or → to step, PgUp or PgDn to jump ten frames, and Home or End
to move to either end.
Connect To Saved Or Ad-Hoc Hosts
The connection-manager action opens a type-to-filter host list with
Ctrl+Shift+S. Rebind it if desired:
keybinds = ctrl+alt+h=connection-manager
For a one-session override:
ODYTTY_KEYBINDS="ctrl+alt+h=connection-manager" odytty
Hosts come from OdyTTY's hosts.conf. When ssh_config_hosts = on, the manager
also shows name-only entries from the OpenSSH config; while it is off, OdyTTY
does not reference ~/.ssh.
The manager is presentation-only. Selecting a host starts the system ssh
client in a new session.
Connect without saving. Type a valid [user@]host[:port] that matches no
saved host. The Connect to: … row connects with Enter, while
Shift+Enter or Ctrl+S connects and atomically appends a matching Host
block to hosts.conf.
Existing contents are preserved. If the alias already exists, OdyTTY connects
and reports "already saved"; embedded spaces, a leading -, and out-of-range
ports are rejected to prevent option injection.
Add or edit a host. Press Tab for a blank form, or the right arrow to edit
the selected OdyTTY-owned host. OpenSSH-imported rows are read-only.
| Form area | Fields and behavior |
|---|---|
| Connection | Alias, host, user, and port |
| Identity | IdentityFile path, passed to ssh with -i; it is a path, never a stored secret |
| Overrides | Integration, Reuse, and Tmux, each set to inherit, on, or off |
| Appearance | Theme, font, and title |
Saving appends a new block or edits the existing block in place while
preserving every other block, comment, and unknown field byte-for-byte.
ssh-copy-id remains the once-only path away from password prompts.
Test a host. The form runs a non-interactive background probe and reports one of four honest results: reachable with key-based authentication, reachable but requiring interactive authentication, host-key mismatch, or unreachable. OdyTTY never handles a password, and normal connection still works for an interactive-auth host.
Connection-launch and probe-start failures are shown in the pane or form rather than leaving a selection with no visible result.
Use the host-row menu. Right-click a row for Open in New Tab, Open in New Workspace, or Bind Current Workspace. A new host workspace is pre-bound so its later tabs use that host too.
OdyTTY-owned rows also offer Edit… and confirmed Remove… actions. Imported OpenSSH rows hide both actions, and dismissing the menu preserves the manager's selection.
Control Remote Sessions
Saved hosts support these connection behaviors:
| Setting | Default | Behavior |
|---|---|---|
remote_integration | on | Sends a temporary bash-only integration wrapper and opens an interactive shell against it |
remote_reuse | on | Reuses a shared ControlMaster connection for later tabs to the same effective SSH endpoint |
remote_persist | 10 minutes | Keeps the master socket alive after the last tab closes |
remote_tmux | off | Wraps the remote shell in a persistent tmux session named odytty |
The integration wrapper writes a temporary remote rcfile and persists nothing
on the host. A non-bash shell or any bootstrap failure falls back to plain
ssh, and the tab title becomes user@host.
The tmux behavior is equivalent to:
tmux new-session -A -s odytty
Each saved host can override Integration, Reuse, and Tmux in hosts.conf.
Connection reuse is available on Unix clients; Windows clients authenticate
each connection independently through ssh.exe. Unix socket names use
OpenSSH's %C hash of the effective host, port, and user, keeping different
endpoints isolated while preserving a fixed-width path.
When a remote connection drops, the tab stays open with a reconnect prompt.
Enter reconnects in place, while Esc or Ctrl+D closes the tab.
Paste Images Into Remote Sessions
Pasting a clipboard image into an integrated remote tab follows
remote_image_paste, which defaults to ask. OdyTTY first shows this
confirmation in the pane:
upload image
to user@host? Enter: upload · Esc: cancel
Only Enter starts the transfer. The image streams over the authenticated
ssh connection, reusing ControlMaster when available, into an unguessable
0600 file under /tmp.
Nothing executes remotely, and files above 10 MiB are refused. After a
successful upload, OdyTTY shows
image uploaded <path> · copied to clipboard, copies the remote path to the
local clipboard, and does not type it into the shell.
Paste the copied path with Ctrl+Shift+V where it belongs as a command
argument. Uploaded files are cleaned up best-effort when the tab closes, and
the path works for reconnected and restored remote tabs.
Manage Detached Sessions
On Unix, detached sessions can be managed inside the window as well as from the
CLI.
The session-attach action, Ctrl+Shift+A, and Manage Sessions all open the
Session Navigator, whose rows include the live detached-session registry
alongside workspaces, tabs, and panes (see
v0.14.0-session-navigator.md). Choosing an
already-open session switches to its tab; another session prompts for New
tab or Replace. Stale or errored registry entries show
session unavailable and cannot be attached.
Press X on a detached session to kill it after confirmation. Detach &
switch gives the focused pane's working directory to a fresh managed session.
Attaching reconnects the live PTY and terminal model. The session host keeps both alive through detach and attach cycles until the child exits or the idle timeout reaps it.
Snapshot format v3 preserves G0/G1 character-set designation and SO/SI selection, so an ACS box-drawing run survives reattach. Older v1 and v2 snapshots remain readable and restore the power-on ASCII character-set state.
On Windows, the Session Navigator lists live local and integrated SSH panes only; detached sessions and attach stay unavailable until a Windows detached session-host surface exists.
Open Interactive Paths
Interactive paths are off by default through interactive_paths. When enabled,
Ctrl+click on Linux/Windows or Cmd+click on macOS opens a detected path: text
files open in the configured editor with line:col positioning, while png, jpg,
jpeg, and webp files open in an in-app lightbox.
Dismiss the lightbox with Esc or a click outside. A click hint and the path
menu expose Open, Open With…, Copy Path, Copy File, and Reveal in File
Manager.
Path detection currently recognizes POSIX path shapes (/, ~/, ./, ../).
Windows drive-absolute (C:\, C:/), UNC (\\server\share), and
backslash-relative paths are also recognized. Drive-relative forms such as
C:folder are deliberately not detected because their meaning depends on
per-drive process state.
Opening uses xdg-open on Linux, open on macOS, or explorer on Windows,
each with a scheme allowlist. OdyTTY passes the target as a single argument and
never interpolates a path into a shell command line.
Rebind Local Actions
The keybinds setting and ODYTTY_KEYBINDS override local actions:
| Scope | Actions |
|---|---|
| Global | search, settings, theme-picker, theme-builder, copy, paste, scroll-up, scroll-down, jump-prompt-prev, jump-prompt-next, select-command-output, select-command-with-prompt, copy-command-output, copy-command-with-prompt, search-command-output, jump-failed-command-prev, jump-failed-command-next, export-command-output, copy-mode, hints, clear-input, command-palette, session-replay, connection-manager, session-attach, new-tab, new-window, next-tab, prev-tab, close-tab, and duplicate-tab |
| Workspace | new-workspace, duplicate-workspace, close-workspace, rename-workspace, next-workspace, prev-workspace, and workspace-picker |
| Pane | split-columns, split-rows, focus-pane-left, focus-pane-right, focus-pane-up, focus-pane-down, focus-pane-next, close-pane, zoom-pane, and equalize-panes |
For pane actions, the binding is the key pressed after the prefix:
keybinds = ctrl+f=zoom-pane
See Keybindings for every default chord, the pane prefix, copy mode, hints, overlay navigation, and rebinding.
Settings And Themes
Use Configuring OdyTTY for the in-app settings workflow. This section covers theme selection, background images, and transparency.
Cursor Presentation
Fresh profiles use a blinking Block cursor with cursor slide, trail, blink
fade, and the restrained shape-aware glow enabled. Nearby eligible moves glide
while the logical cursor and input remain immediate. Stable jumps beyond the
six-cell glide range use the selected cursor_trail_strength presentation
profile (balanced by default): one cursor-shaped follower stretches into the
destination without delaying terminal state or input.
Keyboard and IME activity keep a requested blinking cursor visible; blinking resumes after a short quiet period and parks visibly on after prolonged idle. In an unfocused window, a Block cursor becomes a hollow outline while Bar and Underline keep their normal forms. Cursor motion, trail, glow, easing, and follower presentation advance only in the focused pane of a split, where they stay clipped and do not wake idle panes.
The aura follows the active Block, Bar, or Underline geometry without changing
terminal state or input behavior. Its strength is adjustable through
cursor_glow_intensity on a 0.0..=1.0 scale, independent of the whole-scene
bloom: 0.0 removes the aura while leaving the glow toggle on, the default is a
restrained peak, and higher values stay bounded so text remains readable. Each
presentation control remains independently configurable in Settings or
Runtime Knobs; reduced_motion = on makes slide, trail, glow, easing, and new-output fade static or instant
while preserving their saved choices.
Follow The Desktop Theme
Set theme = system or ODYTTY_THEME=system to follow the desktop dark or
light preference. The default mapping uses odyssey-classic for dark mode and
odyssey-light for light mode.
Use follow_os_theme, os_theme_dark, and os_theme_light to choose custom
mappings.
Change Or Disable The Background Image
Since v0.6.0, OdyTTY ships its OdysseyOS visual identity enabled by default. The
odyssey-default theme is a deep forest-green palette and is also available
through the odyssey-jungle alias.
The original "Dark Waves" image is bundled into the binary and shown behind the grid. It works without an external file in source builds, AppImages, and distro packages, and carries the repository license described in assets/backgrounds/LICENSE.
Draw only the theme background:
background_treatment = color
Alternatively, keep image treatment available without selecting an image:
background_image = none
Choose a custom image instead:
background_treatment = image
background_image = /path/to/your/wallpaper.png
background_image_scrim = 0.5
PNG, JPEG, and WebP images are supported. background_image_scrim ranges from
0 for no scrim to 1 for an opaque scrim, while auto selects a
floor-safe value. Any image, bundled or custom, is resampled to the window
before it reaches the GPU, so a large wallpaper costs what the window displays
rather than what the file contains.
background_image = default, including the unset state, selects the bundled
image again.
Make The Window Transparent
Window transparency lets the desktop show through the terminal background.
Text, the cursor, menus, pickers, and the settings panel remain fully opaque, so
only the background fades. The selection is fully opaque by default
(selection_opacity = 1.0), tuned by its own strength control
(selection_opacity, below) independent of the window opacity.
Transparency is on by default at window_opacity = 80, so the desktop shows
through the background a little out of the box. Where the display server offers
no alpha compositing the window simply presents opaque. Turn it off, or set a
fully-opaque look, from Settings → Rendering or in odytty.conf:
window_transparency = off
# or keep it on and go fully opaque, which matches the opaque render path:
window_opacity = 100
selection_opacity tunes the text-selection highlight strength on its own axis,
from 0.0 (invisible) through 1.5 (strongest), independent of
window_opacity, the theme colours, and min_contrast. The default 1.0 is
the authored fully opaque selection. Below 1.0 is a translucent tint that
reads as a highlight rather than a solid block yet stays clearly visible over a
transparent or busy backdrop, because a selected cell's surface alpha is lifted
toward opaque as the knob rises so the selection never falls weaker than the
surrounding content. Above 1.0 the surface stays fully opaque and the
highlight colour is pushed stronger along the backdrop-to-selection vector,
bounded and in gamut. Text under the selection stays legible through the
minimum-contrast floor.
window_opacity is a percentage from 20 through 100 in steps of 5, with 100
fully opaque.
Two controls keep content readable as the window grows more transparent.
colored_bg_opacity (default 0.9) holds a minimum background strength for
cells whose colour differs from the theme default, so colored blocks — prompt
powerline segments, button chips, and highlighted status runs — stay solid
while the plain background still lets the desktop through; 1.0 removes the
window-opacity attenuation from those cells so they keep their full configured
background opacity (literally opaque only where the cell background already is),
0.0 disables the floor, and it has no effect at window_opacity = 100. text_brightness (default 1.0) lifts glyph ink
toward white so text stays legible over busy backdrops, applied after the
minimum-contrast floor and leaving colour emoji unchanged. Both live in
Settings → Rendering.
Wayland and macOS support compositing natively, X11 requires a compositor, and Windows uses DWM. In an environment without alpha compositing, the setting has no visible effect.
An open menu, picker, or settings panel remains the same themed, opaque surface in one-pane and split-pane tabs without making the whole window opaque. The terminal behind it continues to show the desktop.
A configured background image is part of the background layer. With transparency enabled, it also becomes translucent and composes over the desktop.
Further reference:
-
Named profiles documents the complete profile editor: launch, appearance, cursor, effects, layout, switching, and platform fields, including bounded add/edit/remove list rows.
-
Runtime Knobs lists every config key, environment variable, range, default, and reload behavior.
-
Annotated Config is a complete commented example.
-
Themes documents the theme format and built-in roster.
-
Effects covers bloom, CRT, retro, background, and motion effects.
-
Keybindings is the complete keyboard and rebinding reference.
-
Accessibility covers minimum contrast, color-vision modes, dimming, and the bell.