config.json
Every key Nermalreads, its type, and its default.
| macOS / Linux | ~/.config/Nermal/config.json |
| Windows | %APPDATA%\Nermal\config.json |
| Override the whole directory | Nermal_CONFIG_DIR |
Every key is optional — a missing one means its default, so you only write what you change. Out-of-range numbers are clamped rather than rejected, and an unrecognised enum value falls back to the default with a log line instead of failing the file.
{
"font_family": "JetBrains Mono",
"font_size": 14,
"theme_follow_system": true,
"theme_preset_light": "one_light",
"theme_preset_dark": "dracula",
"macos_option_as_alt": true,
"scrollback_limit": 50000
}Typography
| Key | Type | Default | |
|---|---|---|---|
font_family | string | "Hack" | Primary face. Hack is bundled. |
font_fallbacks | string[] | platform list | Ordered fallbacks. Stock platform faces are appended to whatever you write. |
font_family_bold | string | — | A distinct bold face. |
font_family_italic | string | — | A distinct italic face. |
font_features | object | — | OpenType tags, e.g. {"calt": true, "liga": 1}. Four alphanumeric characters per tag. |
font_size | number | 15 | Terminal text size in px (4–256). |
line_height | number | 1.4 | Multiple of the font size (0.5–4). |
ui_font_size | number | 16 | The interface's root size in px (12–24). |
ui_font_family | string | — | The face for everything outside the grid. Unset means the system UI font. |
Theme and window
| Key | Type | Default | |
|---|---|---|---|
theme_preset | string | "light" | Active theme id. |
theme_follow_system | bool | false | Follow the OS appearance. |
theme_preset_light | string | "light" | Used when following the system. |
theme_preset_dark | string | "dark" | Used when following the system. |
theme_legible_palette | bool | true | Brighten or darken bright ANSI colours that would be unreadable on the background. |
window_opacity | number | — | 0.2–1.0. Unset means "follow the theme". |
window_blur | bool | — | Blur behind a translucent window (macOS). Unset means "follow the theme". |
window_backdrop | enum | "auto" | Windows only: auto, blur, mica, mica-alt, acrylic, off. |
dim_inactive_panes | bool | true | Dim panes that are not focused. |
startup_mode | enum | "normal" | normal, maximized, fullscreen. |
remember_window_size | bool | true | Reopen at the last size and position. |
restore_session | bool | true | Reopen the last window's tabs, splits, and directories. |
gui_language | enum | "en" | en, zh-CN, ja-JP. Anything else falls back to en. |
Built-in theme ids: light, one_light, catppuccin_latte, rose_pine_dawn,
dark, dracula, harbor, one_dark_pro, rose_pine. Your own themes take
their id from the file name. More about themes →
Tabs, sidebar, panels
| Key | Type | Default | |
|---|---|---|---|
tab_bar_position | enum | "left" | left (sidebar) or top (strip). |
new_tab_position | enum | "after-current" | Or end. |
sidebar_grouping | enum | "repo" | Or repo-or-directory to group non-repo tabs by their folder, or none for a flat list. |
sidebar_diff_preview | bool | true | Clicking a row's +N −M opens the diff overlay. |
sidebar_width | number | 220 | Pixels (100–2000). |
sidebar_collapsed | bool | false | |
right_panel_visible | bool | false | |
right_panel_width | number | 260 | Pixels (100–2000). |
right_panel_tab | enum | "info" | info, changes, files. |
diff_view | enum | "split" | Or unified. Global, not per file. |
document_layout | enum | "dock" | Where an open file or diff is drawn: dock beside the terminal, or fill over the workspace. What a fresh tab starts as — each tab keeps its own from there. |
document_ratio | number | 0.5 | The docked column’s share of the terminal column (0.2–0.8). Named widths are 0.333, 0.5, 0.667. |
scm_graph_expanded | bool | false | Whether the history section starts open. |
show_tray_icon | bool | true | The tray / menu bar status item. |
Terminal
| Key | Type | Default | |
|---|---|---|---|
shell | object | — | {"program": "fish", "args": ["-l"]}. Unset uses the platform default. args you write are launched verbatim, which also turns off shell integration for that shell — leave them out to keep it. |
custom_shells | array | [] | Extra entries for the new-tab menu: [{"label": "Ubuntu", "program": "wsl.exe", "args": ["-d", "Ubuntu"]}]. Launched exactly as written, listed after the detected shells. Give an entry arguments and Nermalalso skips shell integration for it, so it has no prompt marks, working-directory tracking, or command-finished notifications; an entry with no arguments, on a shell Nermalrecognizes, is integrated like the detected row beside it. An entry with no program is skipped; with no label it is named after its program. |
working_directory | object | {"strategy":"inherit"} | strategy is inherit, home, or custom; path is used when custom. |
env | object | {} | Extra environment variables for every pane. |
scrollback_limit | number | 10000 | Lines per pane (100–100,000). New panes only. |
cursor_style | enum | "block" | block, bar, underline. |
cursor_blink | bool | true | |
bell | enum | "visual" | none, visual, audible, both. |
per_pane_history | bool | false | Give each pane its own shell history file. |
Mouse and scrolling
| Key | Type | Default | |
|---|---|---|---|
mouse_scroll_multiplier | number | 1.0 | 0.1–10. |
smooth_scroll | bool | true | Ease each wheel notch. Trackpads unaffected. |
mouse_reporting | bool | true | Let full-screen apps handle clicks and scrolling. |
mouse_zoom_modifier | enum | "platform" | Modifier that makes the wheel resize the font: platform (⌘ on macOS, Ctrl elsewhere), ctrl, alt, none. |
mouse_hide_while_typing | bool | true | |
focus_follows_mouse | bool | false |
Input and clipboard
| Key | Type | Default | |
|---|---|---|---|
prompt_editor | bool | true | Nermaledits the shell prompt. Off sends every key at the prompt to the shell, so its own line editor (ZLE, readline) owns editing. Shell integration stays on. |
tab_completion | bool | true | Nermal's completion menu on ⇥. Off hands the key to the shell. Needs prompt_editor. |
history_search | bool | true | Nermal's fuzzy history on ⌃ R. Off hands the key to the shell. Needs prompt_editor. |
smart_select | bool | true | Double-click grabs URLs, paths, bracket pairs, CJK words. |
word_separators | string | see below | Characters that end a word. Used when smart selection is off. |
copy_on_select | bool | false | |
clipboard_trim_trailing_spaces | bool | false | |
macos_option_as_alt | bool | false | ⌥+key sends the escape chord instead of typing a special character. |
keybindings | object | {} | {"SplitRight": "cmd-d"}. Syntax → |
keybinding_preset | string | "default" | Or "tmux". |
prefix | string | "ctrl-b" | The tmux preset's prefix. |
The default word_separators are a comma, a box-drawing bar, a backtick, a
pipe, a colon, both quote characters, a space, the six bracket characters, the
angle brackets, and a tab:
{ "word_separators": ",│`|:\"' ()[]{}<>\t" }Links
| Key | Type | Default | |
|---|---|---|---|
link_url | bool | true | Underline and open URLs on ⌘/Ctrl-click. |
link_file_open | string | internal | What a file link opens: internal (Nermal's editor, at the line), system (the OS file association), command. A file on another machine always uses internal. |
link_file_command | string | — | Command for file links under link_file_open: command. {path}, {line}, {column} are substituted; a flag whose value is missing is dropped. |
ssh_loopback_forward | bool | true | Forward the ports a remote pane starts serving, and open its localhost:PORT links through those forwards. |
Notifications
| Key | Type | Default | |
|---|---|---|---|
notify_on_command_finish | enum | "unfocused" | never, unfocused, always. |
notify_threshold_secs | number | 10 | How long a command must run to qualify (1–3600). |
Agents
| Key | Type | Default | |
|---|---|---|---|
agent_commands | object | {} | Map a wrapper command to an agent slug: {"cc": "claude"}. |
restore_agent_sessions | bool | true | Relaunch an agent conversation when a lost pane is restored. |
install_cli_on_path | bool | true | Put the bundled Nermal command on PATH at launch. |
SSH
| Key | Type | Default | |
|---|---|---|---|
ssh_profiles | array | [] | Managed from Settings → SSH. Secrets live in the OS keychain, never here. |
verify_host_keys | bool | true | |
ssh_warn_on_close | bool | false | Confirm before closing a live connection. |
Each object in ssh_profiles can also set:
| Key | Type | Default | |
|---|---|---|---|
remote_clipboard_write | bool | false | Allow programs on that SSH host to write PNG, JPEG, GIF, or WebP images to this machine's clipboard with OSC 5522. |
Updates and network
| Key | Type | Default | |
|---|---|---|---|
check_for_updates | bool | true | |
update_channel | enum | "stable" | Or nightly. |
auto_download_updates | bool | true | Fetch and verify in the background so installing is a restart. Packages are ~25–30 MB and a check happens every six hours. |
http_proxy | string | — | For Nermal's own traffic only — update checks, downloads, remote-server installs. http://… or socks5://…. Programs in a pane are unaffected. |
Keys Nermalmanages itself
ssh_profile_frecency and command_frecency record how often and how recently
you use a profile or command, so the pickers can rank them. They are written by
the app; there is no reason to edit them.
If the file cannot be parsed, Nermalstarts on defaults, keeps your original at
config.json.corrupt, and logs the reason. It never silently overwrites what
you wrote.