Nermal
Reference

config.json

Every key Nermalreads, its type, and its default.

macOS / Linux~/.config/Nermal/config.json
Windows%APPDATA%\Nermal\config.json
Override the whole directoryNermal_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

KeyTypeDefault
font_familystring"Hack"Primary face. Hack is bundled.
font_fallbacksstring[]platform listOrdered fallbacks. Stock platform faces are appended to whatever you write.
font_family_boldstring—A distinct bold face.
font_family_italicstring—A distinct italic face.
font_featuresobject—OpenType tags, e.g. {"calt": true, "liga": 1}. Four alphanumeric characters per tag.
font_sizenumber15Terminal text size in px (4–256).
line_heightnumber1.4Multiple of the font size (0.5–4).
ui_font_sizenumber16The interface's root size in px (12–24).
ui_font_familystring—The face for everything outside the grid. Unset means the system UI font.

More about fonts →

Theme and window

KeyTypeDefault
theme_presetstring"light"Active theme id.
theme_follow_systemboolfalseFollow the OS appearance.
theme_preset_lightstring"light"Used when following the system.
theme_preset_darkstring"dark"Used when following the system.
theme_legible_palettebooltrueBrighten or darken bright ANSI colours that would be unreadable on the background.
window_opacitynumber—0.2–1.0. Unset means "follow the theme".
window_blurbool—Blur behind a translucent window (macOS). Unset means "follow the theme".
window_backdropenum"auto"Windows only: auto, blur, mica, mica-alt, acrylic, off.
dim_inactive_panesbooltrueDim panes that are not focused.
startup_modeenum"normal"normal, maximized, fullscreen.
remember_window_sizebooltrueReopen at the last size and position.
restore_sessionbooltrueReopen the last window's tabs, splits, and directories.
gui_languageenum"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

KeyTypeDefault
tab_bar_positionenum"left"left (sidebar) or top (strip).
new_tab_positionenum"after-current"Or end.
sidebar_groupingenum"repo"Or repo-or-directory to group non-repo tabs by their folder, or none for a flat list.
sidebar_diff_previewbooltrueClicking a row's +N −M opens the diff overlay.
sidebar_widthnumber220Pixels (100–2000).
sidebar_collapsedboolfalse
right_panel_visibleboolfalse
right_panel_widthnumber260Pixels (100–2000).
right_panel_tabenum"info"info, changes, files.
diff_viewenum"split"Or unified. Global, not per file.
document_layoutenum"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_rationumber0.5The docked column’s share of the terminal column (0.2–0.8). Named widths are 0.333, 0.5, 0.667.
scm_graph_expandedboolfalseWhether the history section starts open.
show_tray_iconbooltrueThe tray / menu bar status item.

Terminal

KeyTypeDefault
shellobject—{"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_shellsarray[]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_directoryobject{"strategy":"inherit"}strategy is inherit, home, or custom; path is used when custom.
envobject{}Extra environment variables for every pane.
scrollback_limitnumber10000Lines per pane (100–100,000). New panes only.
cursor_styleenum"block"block, bar, underline.
cursor_blinkbooltrue
bellenum"visual"none, visual, audible, both.
per_pane_historyboolfalseGive each pane its own shell history file.

Mouse and scrolling

KeyTypeDefault
mouse_scroll_multipliernumber1.00.1–10.
smooth_scrollbooltrueEase each wheel notch. Trackpads unaffected.
mouse_reportingbooltrueLet full-screen apps handle clicks and scrolling.
mouse_zoom_modifierenum"platform"Modifier that makes the wheel resize the font: platform (⌘ on macOS, Ctrl elsewhere), ctrl, alt, none.
mouse_hide_while_typingbooltrue
focus_follows_mouseboolfalse

Input and clipboard

KeyTypeDefault
prompt_editorbooltrueNermaledits 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_completionbooltrueNermal's completion menu on ⇥. Off hands the key to the shell. Needs prompt_editor.
history_searchbooltrueNermal's fuzzy history on ⌃ R. Off hands the key to the shell. Needs prompt_editor.
smart_selectbooltrueDouble-click grabs URLs, paths, bracket pairs, CJK words.
word_separatorsstringsee belowCharacters that end a word. Used when smart selection is off.
copy_on_selectboolfalse
clipboard_trim_trailing_spacesboolfalse
macos_option_as_altboolfalse⌥+key sends the escape chord instead of typing a special character.
keybindingsobject{}{"SplitRight": "cmd-d"}. Syntax →
keybinding_presetstring"default"Or "tmux".
prefixstring"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" }
KeyTypeDefault
link_urlbooltrueUnderline and open URLs on ⌘/Ctrl-click.
link_file_openstringinternalWhat 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_commandstring—Command for file links under link_file_open: command. {path}, {line}, {column} are substituted; a flag whose value is missing is dropped.
ssh_loopback_forwardbooltrueForward the ports a remote pane starts serving, and open its localhost:PORT links through those forwards.

Notifications

KeyTypeDefault
notify_on_command_finishenum"unfocused"never, unfocused, always.
notify_threshold_secsnumber10How long a command must run to qualify (1–3600).

Agents

KeyTypeDefault
agent_commandsobject{}Map a wrapper command to an agent slug: {"cc": "claude"}.
restore_agent_sessionsbooltrueRelaunch an agent conversation when a lost pane is restored.
install_cli_on_pathbooltruePut the bundled Nermal command on PATH at launch.

Agent slugs →

SSH

KeyTypeDefault
ssh_profilesarray[]Managed from Settings → SSH. Secrets live in the OS keychain, never here.
verify_host_keysbooltrue
ssh_warn_on_closeboolfalseConfirm before closing a live connection.

Each object in ssh_profiles can also set:

KeyTypeDefault
remote_clipboard_writeboolfalseAllow programs on that SSH host to write PNG, JPEG, GIF, or WebP images to this machine's clipboard with OSC 5522.

Updates and network

KeyTypeDefault
check_for_updatesbooltrue
update_channelenum"stable"Or nightly.
auto_download_updatesbooltrueFetch and verify in the background so installing is a restart. Packages are ~25–30 MB and a check happens every six hours.
http_proxystring—For Nermal's own traffic only — update checks, downloads, remote-server installs. http://… or socks5://…. Programs in a pane are unaffected.

Updates →

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.

Sponsor