Kwybars
Configuration

General

A practical reference for Kwybars config.toml.

Kwybars can run without a config file. If no file exists, it uses the built-in defaults.

The config file is split into four main sections:

SectionWhat it controls
[overlay]Where the visualizer window appears, which monitor it uses, and which layer it sits on
[visualizer]Layout, bar shape, colors, themes, animation, and audio backend behavior
[image_overlay]Optional transparent image layer drawn above the visualizer
[daemon]Automatic start/stop behavior when audio becomes active or silent

If you only want something that works quickly, start with Preset Configs. Use this page when you want to understand each option.

Config Path

Kwybars looks for config files in this order:

  1. --config /path/to/config.toml
  2. KWYBARS_CONFIG
  3. $XDG_CONFIG_HOME/kwybars/config.toml
  4. ~/.config/kwybars/config.toml
  5. ./kwybars.toml

The packaged example config is installed at:

/usr/share/doc/kwybars/examples/config.toml

To run with a specific config:

kwybars-daemon --config ~/.config/kwybars/custom/my_config.toml

Valid config changes are hot reloaded while Kwybars is running. If a reload fails, Kwybars keeps the current active config and logs the error.

Default Config

This is the built-in default shape. You do not need to copy all of it; copy only the keys you want to change.

[overlay]
monitor_mode = "primary"
layer = "background"
position = "bottom"
full_length = true
width = 800
height = 500
anchor_margin = 20
margin_left = 20
margin_right = 20
margin_top = 0
margin_bottom = 0
fade_in_ms = 180
fade_out_ms = 350
horizontal_alignment = "center"
vertical_alignment = "center"

[visualizer]
backend = "cava"
layout = "line"
line_mode = "continuous"
line_split_gap = 200
mirror_orientation = "horizontal"
mirror_gap = 0
wave_stroke_width = 10
wave_fill = true
wave_glow = false
wave_smoothing = 1.0
wave_motion_smoothing = 0.22
wave_amplitude = 0.8
frame_edges = ["top", "bottom"]
frame_mirror_mode = "pairs"
bars = 50
bar_width = 8
bar_corner_radius = 20
segmented_bars = false
segment_length = 14
segment_gap = 6
radial_inner_radius = 180
radial_start_angle = -90
radial_arc_degrees = 360
radial_rotation_speed = 0
center_offset_x = 0
center_offset_y = 0
polygon_sides = 3
polygon_radius = 220
polygon_bar_length = 0
polygon_rotation = -90
polygon_rotation_speed = 0
gap = 20
framerate = 60
color_mode = "gradient"
color_rgba = "rgba(175, 198, 255, 0.7)"
color2_rgba = "rgba(191, 198, 220, 0.7)"
theme_opacity = 1.0
pipewire_attack = 0.14
pipewire_decay = 0.975
pipewire_gain = 1.20
pipewire_curve = 0.95
pipewire_neighbor_mix = 0.24

[image_overlay]
enabled = false
path = ""
opacity = 1.0
fit = "contain"
width = 0
height = 0
offset_x = 0
offset_y = 0

[daemon]
enabled = true
poll_interval_ms = 90
activity_threshold = 0.035
activate_delay_ms = 180
deactivate_delay_ms = 2200
stop_on_silence = true
notify_on_error = true
notify_cooldown_seconds = 45
overlay_command = "kwybars-overlay"
overlay_args = []

[overlay]

Use [overlay] to decide where Kwybars appears.

[overlay]
monitor_mode = "primary"
layer = "background"
position = "bottom"
full_length = true
height = 500
anchor_margin = 20
margin_left = 20
margin_right = 20
fade_in_ms = 180
fade_out_ms = 350
KeyDescriptionDefaultAccepted values
positionScreen edge used by normal edge-based layouts."bottom""bottom", "top", "left", "right"
layerLayer-shell stacking layer."background""background", "bottom", "top"
anchor_marginMargin on the active anchored edge.20integer pixels
margin_leftExplicit left margin.20integer pixels
margin_rightExplicit right margin.20integer pixels
margin_topExplicit top margin.0integer pixels
margin_bottomExplicit bottom margin.0integer pixels
fade_in_msFade duration when the overlay appears or audio becomes active again.180integer milliseconds
fade_out_msFade duration after audio has stayed silent for deactivate_delay_ms.350integer milliseconds
full_lengthStretch along the full selected edge.truetrue, false
widthFixed width for horizontal overlays, or thickness for left/right overlays.800integer pixels
heightFixed height for vertical overlays, or thickness for top/bottom overlays.500integer pixels
horizontal_alignmentAlignment for top/bottom overlays when full_length = false."center""left", "center", "right"
vertical_alignmentAlignment for left/right overlays when full_length = false."center""top", "center", "bottom"
monitor_modeWhich monitor gets an overlay."primary""primary", "all", "list"
monitorsConnector names or 1-based monitor indices used when monitor_mode = "list".[]array of strings

Per-Monitor Outputs

Use [[overlay.outputs]] when different monitors need different overlay geometry. If at least one output entry exists, Kwybars uses those entries instead of monitor_mode and monitors

[overlay]
height = 220
position = "bottom"

[[overlay.outputs]]
monitor = "DP-1"
height = 180
margin_left = 40
margin_right = 40

[overlay.outputs.visualizer]
layout = "wave"
wave_glow = true
color_mode = "solid"
color_rgba = "rgba(175, 198, 255, 0.75)"

[[overlay.outputs]]
monitor = "HDMI-A-1"
position = "top"
height = 120

[overlay.outputs.visualizer]
layout = "particle"
bar_width = 6
gap = 14

[[overlay.outputs]]
monitor = "index:3"
enabled = false

Each output starts from the main [overlay] values, then applies any keys in that output entry. monitor accepts connector names such as "DP-1", "primary", or 1-based indices such as "1" / "index:1". enabled = false skips that output entry; it does not subtract from monitor_mode because output entries replace monitor_mode selection. Supported per-output override keys are enabled, position, layer, anchor_margin, edge margins, fade_in_ms, fade_out_ms, full_length, width, height, horizontal_alignment, and vertical_alignment.

Add [overlay.outputs.visualizer] after an output entry to override render-only visualizer settings for that monitor. It supports layout, line, mirror, wave, frame, radial, polygon, bar shape, gap, segmentation, and direct color keys. Direct color overrides opt that monitor out of the global theme palette so the configured colors are visible. It intentionally does not support audio-source keys such as backend, bars, framerate, PipeWire tuning, or theme; all outputs share one audio frame stream.

Monitor Targeting

Use all monitors:

[overlay]
monitor_mode = "all"

Use specific monitors:

[overlay]
monitor_mode = "list"
monitors = ["DP-1", "HDMI-A-1"]

When monitor_mode = "list", unknown monitor entries are ignored. If the list has no valid entries, Kwybars falls back to the first monitor.

Layer Behavior

LayerBehavior
"background"Behind normal app windows. This is the default and usually the least intrusive option
"bottom"Above wallpaper but below normal windows, compositor dependent
"top"Above normal windows

[visualizer] Basics

[visualizer] controls how the bars look and how audio frames are read.

[visualizer]
layout = "line"
bars = 50
bar_width = 8
gap = 20
framerate = 60
color_mode = "gradient"
gradient_direction = "vertical"
color_rgba = "rgba(166, 227, 161, 0.82)"
color2_rgba = "rgba(137, 180, 250, 0.82)"
KeyDescriptionDefaultAccepted values
backendAudio frame backend."cava""auto", "cava", "pipewire", "dummy"
layoutVisualizer layout mode."line""line", "mirror", "wave", "frame", "radial", "polygon", "particle", "floating"
barsNumber of bars or samples used by the layout.50integer
bar_widthBase bar thickness.8integer pixels
bar_corner_radiusRounded corner radius. Effective value is clamped by bar size.20number, 0 for square bars
gapSpace between bars.20integer pixels
framerateRender update target.60integer
color_modeHow colors are applied."gradient""solid", "gradient"
gradient_directionGradient direction for bar layouts. vertical follows the bar growth axis. horizontal follows bar order across the layout."vertical""vertical", "horizontal"
color_rgbaPrimary bar color."rgba(175, 198, 255, 0.7)"RGBA string
color2_rgbaSecondary color used by gradient mode."rgba(191, 198, 220, 0.7)"RGBA string
themeOptional theme name.nonestring
theme_opacityAlpha multiplier for theme colors.1.00.0..1.0

Color Formats

gradient_direction = "horizontal" gives line, mirror, and frame layouts a smooth layout-wide gradient. With themes, this switches from discrete palette blocks to a continuous multi-stop gradient similar to the wave layout. For radial and polygon layouts, it smooths theme colors between palette stops around bar order instead of snapping bars into six hard color blocks.

color_rgba and color2_rgba accept CSS-like and comma-separated values:

color_rgba = "rgba(31, 224, 173, 0.90)"
color_rgba = "31,224,173,0.90"
color_rgba = "0.12,0.88,0.68,0.90"

RGB values can be 0..255 or normalized 0..1. Alpha is always 0..1.

For colors.toml overrides and Matugen integration, see Colors and Matugen.

Layout Options

Each layout uses the shared keys above, then adds a few layout-specific keys.

Line

Use line for the standard edge-aligned bar layout.

If you want a ready-to-copy setup, see the Line preset config.

[visualizer]
layout = "line"
line_mode = "continuous"
KeyDescriptionDefaultAccepted values
line_modeNormal continuous line or split line with a center gap."continuous""continuous", "split"
line_split_gapCenter gap when line_mode = "split".200integer pixels

Split example:

[visualizer]
layout = "line"
line_mode = "split"
line_split_gap = 220

Mirror

Use mirror for centered mirrored bars. horizontal mirrors bars above and below a center axis; vertical mirrors them left and right.

If you want a ready-to-copy setup, see the Mirror preset config.

[visualizer]
layout = "mirror"
mirror_orientation = "horizontal"
mirror_gap = 24
KeyDescriptionDefaultAccepted values
mirror_orientationMirror axis direction."horizontal""horizontal", "vertical"
mirror_gapEmpty space between mirrored halves.0integer pixels
line_modeCan also split the mirrored distribution."continuous""continuous", "split"
line_split_gapCenter split gap when line_mode = "split".200integer pixels
center_offset_xHorizontal offset from monitor center.0pixels, positive moves right
center_offset_yVertical offset from monitor center.0pixels, positive moves down

Wave

Use wave for a continuous smoothed line. It follows the normal edge overlay geometry from [overlay].position.

If you want a ready-to-copy setup, see the Wave preset config.

[visualizer]
layout = "wave"
wave_stroke_width = 10
wave_fill = true
wave_glow = false
wave_smoothing = 1.0
wave_motion_smoothing = 0.22
wave_amplitude = 0.8
KeyDescriptionDefaultAccepted values
wave_stroke_widthWave line thickness.10integer pixels, minimum 1
wave_fillDraws a low-opacity fill under the wave.truetrue, false
wave_glowDraws a soft glow behind the wave line.falsetrue, false
wave_smoothingCurve smoothing factor.1.0number, 0 is sharper
wave_motion_smoothingTemporal smoothing for movement.0.22number, higher feels softer/slower
wave_amplitudeOverall wave height multiplier.0.8number, higher is taller

Frame

Use frame to draw bars on multiple edges in one monitor-sized overlay.

If you want a ready-to-copy setup, see the Frame preset config.

[visualizer]
layout = "frame"
frame_edges = ["top", "bottom", "left", "right"]
frame_mirror_mode = "pairs"
KeyDescriptionDefaultAccepted values
frame_edgesEdges to render on.["top", "bottom"]array using "top", "bottom", "left", "right"
frame_mirror_modeHow bars are distributed across active edges."pairs""off", "all", "pairs"

frame_mirror_mode = "off" distributes bars across selected edges. "all" mirrors the full bar set on every selected edge. "pairs" mirrors top+bottom together and left+right together.

Radial

Use radial for a circular or arc-shaped visualizer centered in a monitor-sized overlay.

If you want a ready-to-copy setup, see the Radial preset config.

[visualizer]
layout = "radial"
radial_inner_radius = 180
radial_start_angle = -90
radial_arc_degrees = 360
radial_rotation_speed = 0
KeyDescriptionDefaultAccepted values
radial_inner_radiusWhere radial bars start before growing outward.180integer pixels, minimum 1
radial_start_angleStart angle in degrees.-90number
radial_arc_degreesArc span. 360 is a full ring, 180 is a half circle.360number
radial_rotation_speedRotation speed in degrees per second.0number, negative reverses direction
center_offset_xHorizontal offset from monitor center.0pixels, positive moves right
center_offset_yVertical offset from monitor center.0pixels, positive moves down

Half-circle example:

[visualizer]
layout = "radial"
radial_inner_radius = 160
radial_start_angle = -180
radial_arc_degrees = 180

Polygon

Use polygon to place bars around a regular polygon such as a triangle, square, or hexagon.

If you want a ready-to-copy setup, see the Polygon preset config.

[visualizer]
layout = "polygon"
polygon_sides = 3
polygon_radius = 220
polygon_bar_length = 0
polygon_rotation = -90
polygon_rotation_speed = 0
KeyDescriptionDefaultAccepted values
polygon_sidesNumber of polygon sides.3integer, minimum 3
polygon_radiusOuter polygon radius.220integer pixels, minimum 1
polygon_bar_lengthMaximum outward bar length. 0 keeps automatic sizing.0integer pixels
polygon_rotationStatic polygon rotation in degrees.-90number
polygon_rotation_speedRotation speed in degrees per second.0number, negative reverses direction
center_offset_xHorizontal offset from monitor center.0pixels, positive moves right
center_offset_yVertical offset from monitor center.0pixels, positive moves down

Triangle example:

[visualizer]
layout = "polygon"
polygon_sides = 3
polygon_radius = 220
polygon_rotation = -90
polygon_rotation_speed = 18

Particle and Floating

particle and floating use the normal edge overlay geometry and follow [overlay].position. They are not centered monitor-sized layouts.

If you want ready-to-copy setups, see the Particle preset config and Floating preset config.

[visualizer]
layout = "particle"
bars = 10
bar_width = 40
gap = 10
[visualizer]
layout = "floating"
bars = 10
bar_width = 40
gap = 10

Segmented Bars

Segmented bars split each bar into repeated blocks.

[visualizer]
segmented_bars = true
segment_length = 14
segment_gap = 6
KeyDescriptionDefaultAccepted values
segmented_barsEnables repeated block rendering.falsetrue, false
segment_lengthLength of each segment along the growth direction.14integer pixels, minimum 1
segment_gapGap between segments.6integer pixels

Audio Backend and PipeWire Tuning

KeyDescriptionDefaultAccepted values
backendAudio frame backend."cava""auto", "cava", "pipewire", "dummy"
pipewire_attackHow quickly PipeWire levels rise.0.14number
pipewire_decayHow slowly PipeWire levels fall.0.975number
pipewire_gainPipeWire level gain.1.20number
pipewire_curveCurve applied to PipeWire levels.0.95number
pipewire_neighbor_mixSmoothing between neighboring bars.0.24number

Backend fallback order:

backendFallback order
"auto"cava -> pipewire -> dummy
"cava"cava -> pipewire -> dummy
"pipewire"pipewire -> cava -> dummy
"dummy"synthetic animation only

Tuning guidance:

  • slower or softer motion: lower pipewire_attack, for example 0.08..0.14
  • slower falloff: raise pipewire_decay, for example 0.975..0.99
  • less low-level noise: lower pipewire_gain or raise pipewire_curve
  • smoother neighboring bars: increase pipewire_neighbor_mix, for example 0.24..0.35

[image_overlay]

[image_overlay] draws one optional image above the visualizer in the same transparent overlay window. This is useful for Rainmeter-style compositions where transparent PNG artwork sits in front of bars, waves, or particles.

[image_overlay]
enabled = true
path = "~/.config/kwybars/overlays/mountain.png"
opacity = 1.0
fit = "contain"
width = 0
height = 0
offset_x = 0
offset_y = 0
KeyDescriptionDefaultAccepted values
enabledEnable image overlay drawing.falsetrue, false
pathImage file path. Absolute paths, ~/..., and paths relative to the active config file directory are supported.""string
opacityImage alpha multiplier.1.00.0..1.0
fitHow the image fits inside the target box."contain""contain", "cover", "stretch"
widthTarget image box width. 0 uses the current overlay width.0integer pixels
heightTarget image box height. 0 uses the current overlay height.0integer pixels
offset_xHorizontal offset from centered placement.0number pixels
offset_yVertical offset from centered placement.0number pixels

Notes:

  • Use transparent PNG artwork if you want the visualizer to remain visible around or behind the image.
  • The source image is decoded on config reload, and the scaled image is cached per overlay size so normal frames only repaint the cached pixbuf.
  • Replacing the image file triggers hot reload just like config, colors, and themes.
  • kwybarsctl validate-config and kwybarsctl doctor report missing image paths.

Match Overlays to Wallpapers

kwybarsctl image-overlay match updates [image_overlay] by matching a wallpaper filename stem against an overlay directory.

kwybarsctl image-overlay match --overlay-dir ~/.config/kwybars/wallpaper-overlays ~/Pictures/wallpapers/forest.jpg

This looks for forest.png, forest.webp, forest.jpg, then forest.jpeg in the overlay directory. On success it sets image_overlay.enabled = true and image_overlay.path to the matched image. If the selected config path is a symlink, the command edits the resolved target file so preset symlinks stay intact.

Use --config when the daemon or overlay is watching a non-default config path:

kwybarsctl image-overlay match --config ~/.config/kwybars/current.toml --overlay-dir ~/.config/kwybars/wallpaper-overlays ~/Pictures/wallpapers/forest.jpg

[daemon]

The daemon watches audio activity and starts or stops the overlay automatically. When it launches kwybars-overlay, it passes a private frame socket so the overlay reuses the daemon audio stream instead of starting a second Cava or PipeWire helper.

The overlay fades itself based on the same audio threshold and silence delay. When stop_on_silence = true, the daemon waits overlay.fade_out_ms before terminating the overlay process so the fade can finish. Overlay exits during this managed silence shutdown are logged but do not trigger desktop error notifications.

[daemon]
enabled = true
poll_interval_ms = 90
activity_threshold = 0.035
activate_delay_ms = 180
deactivate_delay_ms = 2200
stop_on_silence = true
notify_on_error = true
notify_cooldown_seconds = 45
overlay_command = "kwybars-overlay"
overlay_args = []
KeyDescriptionDefaultAccepted values
enabledEnables daemon runtime behavior.truetrue, false
poll_interval_msDaemon activity check interval.90integer milliseconds
activity_thresholdPeak level threshold for active audio.0.0350.0..1.0
activate_delay_msAudio must stay active this long before overlay starts.180integer milliseconds
deactivate_delay_msAudio must stay silent this long before overlay stops.2200integer milliseconds
stop_on_silenceStops overlay after sustained silence.truetrue, false
notify_on_errorEnables desktop notifications for daemon/config errors through notify-send. Managed overlay stops during silence are not notified.truetrue, false
notify_cooldown_secondsMinimum time between repeated notifications for the same error.45integer seconds
overlay_commandCommand used to launch the overlay."kwybars-overlay"command string
overlay_argsExtra arguments for overlay_command.[]array of strings

kwybars-overlay defaults to GSK_RENDERER=cairo when the variable is not already set. If you prefer GTK's GPU renderer, set the environment before starting the daemon, for example GSK_RENDERER=ngl kwybars-daemon.

For local development without installed binaries:

[daemon]
overlay_command = "cargo"
overlay_args = ["run", "-p", "kwybars-overlay"]

Validate Config

kwybarsctl validate-config checks the active config file, adjacent colors.toml, and configured theme resolution.

kwybarsctl doctor reports the active config summary and, when an overlay is running, whether it is using the daemon frame socket or a direct backend stream.

kwybarsctl validate-config
kwybarsctl validate-config ~/.config/kwybars/custom/my_config.toml
kwybarsctl validate-config --config ~/.config/kwybars/current.toml
kwybarsctl doctor
kwybarsctl doctor ~/.config/kwybars/custom/my_config.toml
kwybarsctl doctor --config ~/.config/kwybars/current.toml

kwybarsctl list-themes shows available user and built-in themes with their source paths.

kwybarsctl list-themes
kwybarsctl list-themes --config ~/.config/kwybars/current.toml

On this page