Skip to content

Configuration

locainin edited this page Mar 16, 2026 · 10 revisions

Configuration

UnixNotis loads config.toml from the XDG config directory and hot-reloads it on change.

Config file

Locations:

  • $XDG_CONFIG_HOME/unixnotis/config.toml
  • fallback: $HOME/.config/unixnotis/config.toml

If the file is missing, built-in defaults are used. Unknown keys are ignored and logged. Runtime sanitization clamps out-of-range values to safe limits. Some layout values are also clamped at runtime. For example, the panel keeps a minimum usable width even if config.toml asks for something smaller.

Reload behavior

  • The daemon, panel, and popup UIs watch for config changes.
  • Updates are applied without restarting the service.
  • Reload failures keep the previous valid configuration.

Minimal example

[general]
log_level = "info"
dnd_default = false

[inhibit]
mode = "no_popups"

[panel]
anchor = "right"
width = 420
empty_text = "NO NOTIFICATIONS"
empty_offset_top = 120

[popups]
anchor = "top-right"
width = 360

[theme]
base_css = "base.css"
popup_css = "popup.css"
panel_css = "panel.css"
widgets_css = "widgets.css"
media_css = "media.css"

Defaults snapshot (widgets)

The default panel includes:

  • Sliders: Volume, Brightness
  • Toggles: Wi-Fi, Bluetooth, Airplane, Night
  • Stats: CPU, RAM, Battery
  • Cards: Calendar, Weather (static unless configured)

See Widgets for the full schema and default command backends.

Section reference

[general]

  • log_level: tracing filter syntax (RUST_LOG compatible).
  • dnd_default: default DND state when no persisted state exists.

[inhibit]

  • mode: no_popups (store notifications, suppress popups) or drop_all.

[panel]

  • anchor: top-right, top-left, bottom-right, bottom-left, top, bottom, left, right.
  • width: requested width in logical pixels. On smaller displays, runtime caps this to a monitor-aware maximum so the panel remains usable. This is not a hard ceiling. GTK may keep the live panel wider when child widgets need more horizontal space than the requested width.
  • height: 0 uses compositor-driven height. For side anchors (left/right), height uses monitor/work-area bounds with a dynamic bottom gap.
  • keyboard_interactivity: none, on-demand, exclusive.
  • output: optional Wayland output name.
  • close_on_blur: hide when the panel loses focus.
  • close_on_click_outside: hide on outside click (Hyprland only).
  • respect_work_area: respects compositor reserved area (Hyprland only).
  • empty_text: empty-state label text (supports \n for multi-line).
  • empty_offset_top: top offset when widgets are visible. When no widgets are visible, the empty state is centered in the list area.
  • [panel.margin]: margins in logical pixels.

Width behavior notes:

  • A smaller panel.width request does not force the panel narrower than its current natural width if widget content still needs more room
  • Fixed-column widget layouts are the most common cause: toggles render in 4 columns and stats/cards render in 2 columns
  • Theme CSS can also widen the live panel when controls use large min-width, padding, margins, or other horizontal sizing
  • noticenterctl css-check now warns when toggle/stat/card/media sizing looks likely to exceed the requested panel width
  • If a width change appears ignored, inspect widget CSS before assuming config reload is broken

Defaults:

  • empty_text = "NO NOTIFICATIONS"
  • empty_offset_top = 120

[popups]

  • anchor, width, spacing, max_visible.
  • width: requested width in logical pixels. On smaller displays, runtime caps this to a monitor-aware maximum so popup cards do not dominate the screen.
  • default_timeout_ms, critical_timeout_ms.
  • allow_click_through: disable input handling when true.
  • output: optional Wayland output name.
  • [popups.margin]: margins in logical pixels.

[history]

  • max_entries: history capacity.
  • max_active: active list capacity. Runtime clamps this to 12 so the panel and popup stack stay bounded under bursts.
  • transient_to_history: includes transient notifications in history.

Defaults:

  • max_entries = 200
  • max_active = 12
  • transient_to_history = false

[media]

  • enabled, include_browsers.
  • layout: structural media card preset.
    • carousel: nav buttons outside the card
    • inline: nav buttons folded into the card
    • stacked: vertical card with a lower control strip
    • showcase: wide card with a dedicated action rail
  • browser_tokens: case-insensitive tokens used to classify browser players.
  • title_char_limit: marquee starts after this length.
  • show_source: show the source badge row above the title.
  • show_position: show the 1/N player counter when more than one player is active.
  • allowlist / denylist: case-insensitive substrings for player identities.
  • remote_art_policy: controls which players may fetch remote album art.
    • disabled: never fetch remote art
    • native_only: allow remote https art only for non-browser players
    • browsers_too: also allow browser media sessions to fetch remote https art

Defaults:

  • browser_tokens includes common desktop browsers (Firefox, Chromium, Chrome, Brave, Vivaldi, Edge, Opera, Epiphany, Midori, Zen, Librewolf, Waterfox, Floorp).
  • layout = "carousel".
  • title_char_limit = 32.
  • show_source = true.
  • show_position = true.
  • remote_art_policy = "native_only".

Notes:

  • Layout presets change the real GTK shell, not just the CSS classes. showcase and stacked can use panel width very differently from carousel.
  • Local file artwork from native players such as mpv and smplayer is still allowed.
  • Remote art is limited to validated https URLs and bounded fetch sizes.
  • Browser remote art stays off by default because webpage-controlled metadata can choose the art URL.
  • The player counter only appears when show_position = true and there is more than one active player to cycle through.

Enable browser remote art only when that tradeoff is acceptable:

[media]
remote_art_policy = "browsers_too"

[sound]

  • enabled.
  • default_name: freedesktop sound theme name.
  • default_file: sound file path (relative to config dir when not absolute).
  • default_dir: directory containing sound files.

[theme]

Theme CSS file names resolve relative to the config directory. Alpha values are clamped to 0.0..=1.0 and dimensions are clamped to safe ranges.

  • base_css, panel_css, popup_css, widgets_css: theme file paths loaded by the live UI
  • media_css: media-widget-only theme layer loaded above widgets.css Relative paths resolve from the config directory. Absolute paths are also allowed
  • Active theme files do not have to end in .css, but using the standard names keeps output and troubleshooting easier to follow
  • border_width: card/control border thickness.
  • card_radius: card corner radius.
  • surface_alpha, surface_strong_alpha, card_alpha.
  • shadow_soft_alpha, shadow_strong_alpha.

Theme path notes:

  • noticenterctl css-check follows the active theme paths from config.toml instead of blindly scanning every .css file under the config tree
  • The active path list now includes [theme].media_css
  • It warns when a configured theme target is missing
  • It warns when multiple theme slots resolve to the same file
  • It prints the active resolved theme file list before validation so it is clear which files were actually checked

[widgets]

  • toggle_tooltips: enables GTK hover tooltips for toggle buttons. Default: false.
  • refresh_interval_ms: base refresh interval for widget polling.
  • refresh_interval_slow_ms: slower interval used during stable periods.
  • [[widgets.stats]].plugin: optional external plugin for stat values.
  • [[widgets.cards]].plugin: optional external plugin for card content.

Plugin block fields:

  • api_version: plugin contract version (currently 1).
  • command: simple executable command (no shell metacharacters).
  • timeout_ms: plugin runtime timeout in milliseconds.
  • max_output_bytes: maximum accepted plugin stdout payload size.

See Widgets for the widget schema and command examples.

Rules match notification fields and apply overrides. See Rules for details and examples.

Clone this wiki locally