-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
go-term reads an optional INI-style config file at startup. The workspace
layer reads it, so it applies to every embedder that uses term/workspace,
including falcon. A bare term.Term embedder sets its options in code
through term.Cfg. See Embedding.
Everything in the file is optional. A missing file, an unknown section, or an unknown key is ignored. A malformed line is logged and skipped, and the rest of the file still applies. A broken config never prevents the terminal from starting.
The file is found in this order:
- The path the embedder passes as
workspace.Cfg.ConfigPath, if set $XDG_CONFIG_HOME/go-term/config~/.config/go-term/configos.UserConfigDir()/go-term/config
Falcon uses the default location. Cmd+, opens the file in your editor and
writes a commented stub first when the file does not exist.
# Comments start with '#'. Blank lines are ignored.
[section]
key = valueWhitespace around = is trimmed. Keys and values are capped at 128 bytes.
Cmd+Shift+, (Ctrl+Alt+, on Windows) re-reads the file and applies it to
every open pane without a restart. Font, theme, scrollback, bell,
scrollbar, and every keybinding change live. [env] applies to panes
created after the reload.
A setting deleted from the file reverts to the embedder's built-in default on the next reload. The file always applies to a pristine base, never on top of previously loaded values.
Reload leaves per-pane state alone, with one exception. The font zoom
resets, and only when the font actually changed. The zoom is an absolute
point size. Without the reset, it outranks the new configured size until
Cmd+0.
| Key | Type | Default | Meaning |
|---|---|---|---|
family |
string | embedder's default | Font family, as the font's own name table spells it |
size |
number | embedder's default | Point size, clamped to 4–72 |
[font]
family = JetBrainsMono NFM
size = 12The family must be the name the font reports, not its marketing name.
JetBrains Mono Nerd Font Mono reports as JetBrainsMono NFM.
| Key | Type | Default | Meaning |
|---|---|---|---|
theme |
string | embedder's first theme | Color theme, by display name, case-insensitive |
scrollback |
integer | 5000 |
Scrollback rows. 0 restores the default, negative disables |
bell |
enum | auto |
auto, audible, visual, both, none
|
scrollbar |
number | 4 |
Thumb width in px. Negative hides the scrollbar |
minimum-contrast |
number |
1 (off) |
WCAG ratio text is forced to reach against its cell background |
middle-click-paste |
boolean | on for Linux | Paste with the middle mouse button |
notify-after |
duration |
0 (off) |
Notify when a command this long finishes while you look away |
[general]
theme = Dracula
scrollback = 5000
bell = auto
scrollbar = 4
minimum-contrast = 1
middle-click-paste = trueBooleans accept true/false, yes/no, on/off, and 1/0.
theme matches by name against the themes the embedder registered. An
unknown name is logged and the default is kept. Nothing loads a theme from
disk.
Falcon registers the built-in Default plus the whole bundled corpus: 602
themes, 473 dark and 129 light. Press Cmd+Shift+T to browse them with a
live preview and a filter. That is the intended way to pick one.
Theme names that shipped before the corpus still resolve to their closest corpus equivalent, so existing config files keep working.
A light theme also switches falcon's window chrome to light, and tells any
child app subscribed to mode 2031 that the color scheme changed. A neovim
or delta that tracks the terminal re-themes itself. COLORFGBG is set at
spawn from the startup theme, which is how vim, less, and some prompts
decide the same question. A child started under a dark
theme still reports dark after a switch, because the variable cannot change
in a running process.
minimum-contrast fixes the one thing a theme cannot fix. A 24-bit color
sequence is not themeable. eza, starship, and most ls color schemes emit
colors chosen for a dark background, and on a light theme they arrive
exactly as sent.
Set a ratio, and any foreground below it is pushed toward white or black, whichever direction has room against that cell's background. The color blends rather than being replaced, so a red that fails by a little stays recognizably red.
| Value | Effect |
|---|---|
1 |
Off, the default. A color against itself is 1:1 |
3 |
Fixes the worst dark-tuned colors, leaves most palettes alone |
4.5 |
The WCAG floor for body text |
7 |
WCAG AAA. Expect most colors visibly adjusted |
The clamp is render-only. The grid keeps the color the app sent, so copy, search, and session recordings are unaffected. It costs about 11 ns per cell when on.
auto plays the system alert sound and falls back to a visual flash where
the platform has none. audible never flashes. visual never beeps.
both does both. none ignores BEL entirely.
Scrollback is clamped to at most 100000 rows.
Environment variables handed to every child process. The full child
environment is the parent's, with the host terminal identity scrubbed and
the pane's own TERM, COLORTERM, and COLORFGBG set. Entries here apply
last, so they win over all of it, including TERM_PROGRAM.
| Key | Type | Default | Meaning |
|---|---|---|---|
any NAME
|
string | inherited | Added to every child's environment. An empty value unsets it |
[env]
TERM_PROGRAM = Ghostty
PATH = /opt/homebrew/bin:/usr/bin:/binTERM_PROGRAM is what TUI file managers key their image protocol off.
yazi and superfile use the Kitty Graphics Protocol under a name they
recognize and fall back to sixel otherwise. go-term implements KGP, so
naming a known emulator here gets you its image quality. Falcon advertises
its own name by default.
Variables apply to panes created after the reload. A running child's environment is fixed at spawn.
Each entry rebinds one action. Keys are namespaced:
-
workspace.<command>— window-level commands: tabs, panes, overlays -
term.<action>— terminal-level actions: copy, find, scrollback, zoom
A key with no prefix means workspace., the form that predates the
term. namespace. New configs use the explicit form.
[keybindings]
workspace.splitVertical = Cmd+D
workspace.newTab = Cmd+T
term.copy = Cmd+Shift+C
term.find = Cmd+F
term.scroll-page-up = noneThe value none unbinds the action. That hands the key back to the child
process, which is the point. For example, freeing Ctrl+R lets the
shell's reverse search work instead of toggling regex search.
Modifiers first, then the key, joined with +:
Cmd (alias Super), Ctrl, Alt (alias Opt), Shift.
Key names: A–Z, 0–9, F1–F25, Space, Enter/Return,
Escape/Esc, Tab, Backspace, Delete/Del, Insert, Home, End,
PageUp, PageDown, Left, Right, Up, Down, and the punctuation
keys [ ] / ; , . - = `. Modifier and key names are
case-insensitive.
A chord already claimed by another binding is rejected, logged, and the losing entry keeps its default. The check runs across both namespaces. Rebinding both sides in the same file works fine. Collisions are judged against the final assignment, not the built-in defaults.
On Windows the Super key is OS-reserved, so the built-in Cmd-based
defaults are remapped: Cmd becomes Ctrl+Shift, Cmd+Shift becomes
Ctrl+Alt, and so on. Bindings you write in the config file are used
verbatim, no remapping, so write the chord you actually want to press.
The table lists the macOS and Linux default first, then the Windows chord.
| Command | Default (macOS / Linux) / Windows |
|---|---|
workspace.splitVertical |
Cmd+D / Ctrl+Shift+D
|
workspace.splitHorizontal |
Cmd+Shift+D / Ctrl+Alt+D
|
workspace.closePane |
Cmd+Shift+W / Ctrl+Alt+W
|
workspace.nextPane |
Cmd+] / Ctrl+Shift+]
|
workspace.prevPane |
Cmd+[ / Ctrl+Shift+[
|
workspace.resizeLeft |
Cmd+Ctrl+Left / Ctrl+Alt+Shift+Left
|
workspace.resizeRight |
Cmd+Ctrl+Right / Ctrl+Alt+Shift+Right
|
workspace.resizeUp |
Cmd+Ctrl+Up / Ctrl+Alt+Shift+Up
|
workspace.resizeDown |
Cmd+Ctrl+Down / Ctrl+Alt+Shift+Down
|
workspace.newTab |
Cmd+T / Ctrl+Shift+T
|
workspace.closeTab |
Cmd+Ctrl+W / Ctrl+Alt+Shift+W
|
workspace.moveTabLeft |
Cmd+Alt+[ / Alt+Shift+[
|
workspace.moveTabRight |
Cmd+Alt+] / Alt+Shift+]
|
workspace.nextTab |
Cmd+Shift+] / Ctrl+Alt+]
|
workspace.prevTab |
Cmd+Shift+[ / Ctrl+Alt+[
|
workspace.tab1 … workspace.tab9
|
Cmd+1 … Cmd+9 / Ctrl+Shift+1 … Ctrl+Shift+9
|
workspace.toggleRecording |
Cmd+Shift+R / Ctrl+Alt+R
|
workspace.save |
Cmd+S / Ctrl+Shift+S
|
workspace.toggleBroadcast |
Cmd+Shift+I / Ctrl+Alt+I
|
workspace.chooseTheme |
Cmd+Shift+T / Ctrl+Alt+T
|
workspace.reloadConfig |
Cmd+Shift+, / Ctrl+Alt+,
|
workspace.toggleHelp |
Cmd+/ / Ctrl+Shift+/
|
workspace.commandPalette |
Cmd+Shift+P / Ctrl+Alt+P
|
The overlay* commands are shared by every list overlay, and they route to
whichever one is open. They are one registration each on purpose: duplicate
shortcuts are rejected, and a rejection drops the rest of the batch.
| Action | Default |
|---|---|
term.copy |
Cmd+C / Ctrl+Shift+C
|
term.paste |
Cmd+V / Ctrl+Shift+V
|
term.find |
Cmd+F |
term.toggle-regex |
Ctrl+R, in Find |
term.next-match |
Enter, in Find |
term.prev-match |
Shift+Enter, in Find |
term.prev-prompt |
Cmd+Up |
term.next-prompt |
Cmd+Down |
term.jump-failure |
Cmd+Shift+E |
term.select-output |
Cmd+Shift+O |
term.scroll-page-up |
PageUp |
term.scroll-page-down |
PageDown |
term.scroll-top |
Shift+Home |
term.scroll-bottom |
Shift+End |
term.font-inc |
Cmd+= |
term.font-dec |
Cmd+- |
term.font-reset |
Cmd+0 |
term.copy-mode |
Cmd+Shift+Space / Ctrl+Shift+Space
|
term.hints |
Cmd+Shift+U / Ctrl+Shift+U
|
term.hints-copy |
Cmd+Shift+Y / Ctrl+Shift+Y
|
An override replaces the action's whole default chord list with the single
chord you give, and it inherits the action's Shift tolerance. Where Shift
is a keyboard artefact rather than meaningful, a stray Shift still matches:
rebinding term.find to Cmd+G also answers Cmd+Shift+G. Where Shift
picks a direction, like term.next-match versus term.prev-match, it
matches exactly.
Several actions only fire in context, and that gate is not part of the
binding. Ctrl+C still sends SIGINT when nothing is selected. The Find
keys apply only while the search bar is open. term.copy only copies when
there is a selection.
term.copy-mode enters a vim-keyed state for scrolling the buffer,
selecting text, and copying it without a mouse. While it is active, no key
reaches the shell, and incoming output freezes so the text you select
cannot scroll away. A status bar across the top shows the key hints.
A click anywhere in the pane leaves copy mode and hands selection back to the mouse.
The copy-mode actions are rebindable like any other. They are left out of
the Cmd+/ help overlay on purpose: twenty extra rows in a flat list helps
nobody. The full default table is in Usage.
[font]
family = JetBrainsMono NFM
size = 13
[general]
theme = TokyoNight
scrollback = 20000
bell = visual
scrollbar = 6
middle-click-paste = true
[env]
TERM_PROGRAM = Ghostty
[keybindings]
workspace.splitVertical = Cmd+D
workspace.splitHorizontal = Cmd+Shift+D
term.find = Cmd+G
term.toggle-regex = none