Configuration reference
This reference comes from config.example.toml. Active values are defaults.
Commented settings are optional examples. All settings are optional.
See Configuration for the file path and reload steps.
# Thurm example configuration.# Copy this file to ~/.config/thurm/config.toml, or use `thurm config-path`# to find the active path. Run `thurm reload` after you make changes.# All settings are optional. Active values below match the defaults.# Optional overrides and custom entries are commented out. Remove the leading# "# " from an example setting to use it.
# The updates Thurm has made to this file: it turns on features that came after the file was# written, then raises this. Leave it as it is.config_version = 9
[font]# Use a font family or face name. Sizes and spacing are in points.family = "JetBrains Mono"# A face of the family for regular text; bold and italic follow its width.# style = "Semi-Condensed"size = 16.0# These faces are selected from the font family when not set.# family_bold = "JetBrains Mono Bold"# family_italic = "JetBrains Mono Italic"# family_bold_italic = "JetBrains Mono Bold Italic"ligatures = true# OpenType features, for example ["ss01", "zero", "-dlig"].# A leading minus sign disables a feature.features = []# Multiply the font line height by this value.line_height = 1.0letter_spacing = 0.0# Use CoreText font smoothing. Strength: 0 to 255.thicken = truethicken_strength = 255fallback = ["SF Mono", "Menlo"]# Use the included Symbols Nerd Font Mono for missing icons.nerd_font_symbols = true
[window]# Padding and sidebar width are in points.padding_x = 8.0padding_y = 6.0# Opacity: 0.0 to 1.0. Blur needs opacity below 1.0.opacity = 1.0# Any value above 0 enables blur.blur = 0# Backdrop of the chrome when opacity is below 1: "theme", "system", "blend" or "modern".material = "theme"# Treat the Option key as Alt: "none", "left", "right", or "both".option_as_alt = "none"# Initial window size in terminal cells.columns = 110rows = 32confirm_close = truequit_after_last_window = false# Dim panes without focus: 0.0 disables dimming; 1.0 gives full dimming.unfocused_split_dim = 0.25# Draw an accent-colored border around the focused pane while a tab shows several.active_pane_border = false# Even out a tab's splits when a pane opens or closes. A dragged divider holds until then.auto_balance = truepane_headers = true# Space between split panes (and around them) when pane headers show, in points.pane_gap = 6.0# Animation speed for panes and the chrome: "normal", "slow" or "slower".animation_speed = "normal"# Tab location: "native" or "sidebar".tab_style = "sidebar"sidebar_width = 240.0# Group the sidebar's tabs by repository; or list every workspace's tabs; or only what is# going on: every agent that isn't idle, by status, and the tabs with progress.sidebar_group_by_repo = truesidebar_all_workspaces = falsesidebar_active_only = false# What is left of the Claude Code / Codex subscription limits, at the bottom of the sidebar.sidebar_usage_claude = falsesidebar_usage_codex = false# The mouse's back and forward buttons go back and forward through the tabs visited# (Window > Back / Forward). Off, they reach the program as mouse buttons.mouse_navigation_buttons = true
[cursor]# Shape: "block", "beam", or "underline".style = "block"blink = false# Beam and underline thickness in points.thickness = 2.0
[colors]# Use a theme name or a path to a theme file. `thurm theme` lists names.# To follow system appearance, use "light:NAME,dark:NAME".# theme = "light:catppuccin-latte,dark:catppuccin-mocha"# Colors use hexadecimal RGB values. Unset colors come from the theme.# foreground = "#d8dee9"# background = "#0e1116"# cursor = "#d8dee9"# cursor_text = "#0e1116"# selection_foreground = "#ffffff"# selection_background = "#434c5e"# Override up to 16 ANSI colors, starting at index 0.# For example: palette = ["#1b2029", "#e06c75"].palette = []bold_is_bright = falseimprove_contrast = falsetheme_palette = falseblend_backgrounds = falsedisplay_p3 = false
[terminal]# Scrollback lines kept in memory per pane.scrollback = 10000# Use the login shell when no shell command is set.# shell = ["/bin/zsh", "-l"]term = "xterm-256color"# Add prompt marks and working directory tracking for zsh, bash, and fish.shell_integration = true# Clipboard access through OSC 52: "disabled", "copy", "paste", or "copy-paste".osc52 = "copy"kitty_keyboard = truekitty_graphics = true# Maximum memory for kitty graphics per pane, in MiB.image_memory_mib = 320# Characters that end a word during selection with a double click.word_separators = ",│`|:\"' ()[]{}<>\t"copy_on_select = false# Lines moved per line of wheel or trackpad input.scroll_multiplier = 3.0smooth_scroll = true# Show completion choices at a shell prompt. Requires shell integration.tab_completion = true
[terminal.env]# Set environment variables for shell processes.# EDITOR = "nvim"
[session]# Save the layout, working directories, and agents to disk. Scrollback stays in memory.persist = truesnapshot_interval_secs = 15# "detach" keeps shells running when the app quits.# "terminate" stops shells when the app quits.quit = "detach"# Run configured agent resume commands when a saved session is restored.resume_agents = true# Exit the daemon this many seconds after the last pane closes. 0 disables this.daemon_idle_exit_secs = 0
[security]# Enable Secure Keyboard Entry when a password prompt is detected.auto_secure_input = truesecure_input_indicator = true# Ask before a paste with multiple lines outside bracketed paste mode.confirm_multiline_paste = true
[notifications]enabled = true# Notify when a command takes at least this many seconds and ends without focus.# Set to 0 to disable these command notifications.command_finished_secs = 15# Allow OSC 9, OSC 99, and OSC 777 notifications from programs.program_notifications = truebell_badge = true# What an agent does in each state: a tab indicator, a desktop notification (in a pane without# focus), a Dock badge (until seen) and a sound ("default", "none", or a sound file's name).# States: working, waiting (needs input), blocked (asks for a permission), finished (ended a# turn; needs agent hooks), failed, idle.working = { tab_indicator = true, notify = false, badge = false, sound = "none" }waiting = { tab_indicator = true, notify = true, badge = true, sound = "default" }blocked = { tab_indicator = true, notify = true, badge = true, sound = "default" }finished = { tab_indicator = true, notify = true, badge = true, sound = "default" }failed = { tab_indicator = true, notify = true, badge = true, sound = "default" }idle = { tab_indicator = true, notify = false, badge = false, sound = "none" }
[agents]detect = true# Mark a working agent as idle after this many milliseconds without output.idle_after_ms = 1500# Use agent session titles for tabs. Requires agent hooks.session_titles = true# Install the agent hooks (see `thurm hooks install`) when an agent launches without them.install_hooks = true# Empty presets use the installed built-in agents.# Replace [] with entries that each contain a name and command, for example:# [{ name = "My Bot", command = ["mybot"] }]presets = []
# Add an agent definition, or use an existing kind to override it.# Remove the comment prefix from the full block to enable this example.# Replace the commands and matching text with values for your agent.# The default list of custom definitions is empty.# [[agents.define]]# kind = "mybot"# name = "My Bot"# processes = ["mybot"]# argv = ["mybot/cli"]# working = ["Working"]# attention = ["Approve?"]# launch = ["mybot"]# resume = ["mybot", "--continue"]# resume_session = ["mybot", "--resume", "{session}"]# fork_session = ["mybot", "--fork", "{session}"]# processes matches executable names; argv matches parts of process arguments.# working and attention match text on the screen.# launch, resume, resume_session, and fork_session are optional commands.# {session} is replaced with the session ID reported by agent hooks.
[programs]# Show known programs (Neovim, Node, htop) with an icon for their kind in headers and the sidebar.detect = true# Show the program's name in place of its process name in titles ("Neovim" for "nvim").names = true# Add a program definition, or use an existing id to override it.# Remove the comment prefix from the full block to enable this example.# The default list of custom definitions is empty.# [[programs.define]]# id = "mytool"# name = "My Tool"# processes = ["mytool"]# argv = ["mytool/cli.js"]# icon = "build"# color = "#3776ab"# ink = "#ffffff"# processes matches executable names, and a trailing * matches any suffix.# argv matches parts of an interpreter's arguments.# icon is a kind of program (editor, runtime, git, build, container, cluster, database,# monitor, multiplexer, remote, files, docs), a mark (neovim, vim, sofka), or an SF Symbol# name on macOS. color and ink are optional.
[ai]# Use the on-device Apple Intelligence model. Requires macOS 26 or later, Apple silicon,# and Apple Intelligence turned on in System Settings. Text never leaves the Mac.# The features below take effect only when enabled is true.enabled = false# Name agent tabs after the task when the agent does not provide a session title.titles = true# Detect agents waiting for an answer when no attention pattern matches.# Applies to agents without hooks.status = true# Describe agent requests and summarize finished turns in notifications# and the agent switcher.notifications = true# Allow Edit > Explain Last Command and `thurm explain`.explain = true
[plugins]# Run plugins: init.lua next to this file, and the plugins in plugins/.enabled = true# Plugins not to start, by name.disabled = []# Settings for one plugin, passed to it as they are.# [plugins.settings]# git-tools = { remote = "origin" }
[updates]# "auto" follows the installed build's channel: "release" or "tip".# Use "release" or "tip" to select a fixed channel.channel = "auto"# Check for updates in the background.check_automatically = true# Download updates in the background and install them when Thurm quits.download_automatically = false
[quick_terminal]# A terminal that slides in from a screen edge on a global shortcut, from# any app or Space. Its shell keeps running while it is hidden. You can also# use Window > Quick Terminal.# Modifiers are cmd, ctrl, alt and shift. An empty value sets no shortcut.hotkey = ""# hotkey = "ctrl+grave"# "top", "bottom", "left", "right" or "center".position = "top"# The fraction of the screen that it takes.size = 0.4# Hide it when another app or another Thurm window takes focus.autohide = true# "mouse" uses the screen with the pointer. "main" uses the menu bar screen.screen = "mouse"# The slide animation length in seconds. Use 0 for no animation.animation_duration = 0.2# Background opacity from 0 to 1. When not set, window.opacity is used.# opacity = 0.9
[keybindings]# Map a key combination to an action name.# "cmd+shift+d" = "split_down"# "cmd+d" = "split_right"
# A command of your own, in the command palette and on an optional key. The daemon# runs it through your login shell in the focused pane's directory, with# THURM_PANE_ID and THURM_SOCKET set.# [[commands]]# name = "Dev layout"# exec = ["~/bin/dev-layout", "--branch", "main"]# key = "cmd+shift+l"
# For more than running a command, use init.lua next to this file, or a# plugin in plugins/.
# A command the daemon runs on an event, with the event as JSON on stdin.# Events: agent_working, agent_waiting, agent_blocked, agent_finished,# agent_failed, agent_idle, command_finished and pane_exited.# [[on]]# event = "agent_finished"# exec = ["~/bin/agent-done"]# min_secs = 0 # command_finished only
[tailscale]# Serve the daemon over Tailscale as a device of its own, so your phone and other# devices reach it at wss://HOSTNAME.YOUR-TAILNET.ts.net/v1/connect without ssh.# The first time, sign in with the link in Settings or `thurm tailscale status`.enabled = false# The device's name on the tailnet: one DNS label.hostname = "thurm"# Admit every tailnet member, not only the account that signed the device in.allow_tailnet_members = false# ACL tags to enroll with, such as ["tag:thurm"]. Needs allow_tailnet_members.advertise_tags = []# A file with a Tailscale auth key, to enroll without a browser.auth_key_file = ""# Also listen on this machine's tailnet addresses through its own Tailscale.host_listen = ""# host_listen = ":7297"# A coordination server other than Tailscale's, such as a headscale.# control_url = "https://headscale.example.com"# Without HTTPS (no MagicDNS or certificates, as on headscale), listen on a tailnet address# without TLS.# plain_listen = ":7297"# With host_listen: admit every identified caller, not only this machine's owner.host_allow_identified = false# A socket for `tailscale serve` to proxy to.serve_socket = false# Serve the browser client on the node's HTTPS address, at https://HOSTNAME.YOUR-TAILNET.ts.net/.# Needs enabled.web = false
# Remote workspaces: thurmd on another machine, reached with the system ssh, or over# Tailscale when `tailnet` is set (ssh still installs, checks and hands off).# `thurm remote add devbox devbox` checks the connection and writes an entry.# [[remote]]# name = "devbox"# host = "devbox" # an ssh Host alias, user@host, or ssh://user@host:port# socket = "/run/user/1000/thurm-1000/thurmd.sock" # discovered when unset# enabled = true# clipboard_read = "ask" # "ask", "always" or "never"# tailnet = "wss://devbox.YOUR-TAILNET.ts.net/v1/connect" # over Tailscale instead of ssh