waybar(5)

🌸 NAME 🌸

waybar β€” the configuration file, bestie πŸ’–

(Yeah, this is waybar(5) from the File Formats Manual β€” the glow-up guide for your bar's config.)


✨ DESCRIPTION ✨

So the config is in JSONC format (JSON with comments, yes we love a bit of extra), and it's named either config or config.jsonc. πŸŽ€

The valid places you can put it are, literally:

  • $XDG_CONFIG_HOME/waybar/
  • ~/.config/waybar/
  • ~/waybar/
  • /etc/xdg/waybar/
  • /etc/xdg/waybar/
Not me pointing out that /etc/xdg/waybar/ shows up twice up there β€” that's what the man page says, so I'm keeping it fr fr. πŸ’€

If you're looking for a starting point that actually slays, the default configuration lives at https://github.com/Alexays/Waybar/blob/master/resources/config.jsonc β€” iconic. And there's a minimal example config at the bottom of this man page too, so keep reading. πŸ‘‘

Also important: the visual display bits of waybar use a CSS stylesheet, so go check waybar-styles(5) for all of that. πŸ¦‹


πŸ’… BAR CONFIGURATION πŸ’…

  • expand-center β€” typeof: bool, default: false. Lets the modules-center eat up all the leftover space dynamically. Feeding the center block, basically. πŸ“
  • expand-left β€” typeof: bool, default: false. Same deal, but for modules-left β€” it consumes all the left over space dynamically.
  • expand-right β€” typeof: bool, default: false. And this one... enables modules-left to consume all the left over space dynamically. Yes, it says modules-left. That's what the man page says, no cap, I'm not editing it. πŸ™ˆ
  • layer β€” typeof: string, default: bottom. Decides whether the bar is out in front of your windows (top) or hiding behind them (bottom).
  • output β€” typeof: string|array. Tells waybar which screen this bar shows up on. You can slap an exclamation mark ! on it to exclude a specific output.
    • The output spec follows sway's, so it can be either the output port like HDMI-A-1, or a string made of make, model, and serial like Some Company ABC123 0x00000000. Peep sway-output(5) for the deets.
    • In an array, a star '*' can go at the end to accept all outputs β€” that's for when all the previous entries are exclusions.
  • position β€” typeof: string, default: top. Where the bar sits. Options: top, bottom, left, right.
  • height β€” typeof: integer. Height for the bar if it's possible to give it one. Leave it blank and you get a dynamic value instead. ✨
  • width β€” typeof: integer. Width for the bar if possible. Leave blank for dynamic. Same energy, other axis. 🌈
  • modules-left β€” typeof: array. The modules that get displayed on the left.
  • modules-center β€” typeof: array. The modules that get displayed in the center β€” main character spot, obviously.
  • modules-right β€” typeof: array. The modules that get displayed on the right.
  • margin β€” typeof: string. Margin value using CSS format, without units.
  • margin-<top|left|bottom|right> β€” typeof: integer. Margin value, no units.
  • no-center β€” typeof: bool, default: false. Fully disables the center modules β€” super useful when you're pairing it with expand-*.
  • spacing β€” typeof: integer. How big the gaps between the different modules are.
  • name β€” typeof: string. An optional name that gets added as a CSS class, for when you wanna style multiple waybars differently. πŸŽ€
  • mode β€” typeof: string. Picks one of the preconfigured display modes. It's the equivalent of the sway-bar(5) mode command and supports the same values: dock, hide, invisible, overlay.
Heads up: hide and invisible modes might not be as useful without Sway IPC. πŸ‘€
  • start_hidden β€” typeof: bool, default: false. Makes the bar start out hidden. Shy bar behavior. πŸ™ˆ
  • modifier-reset β€” typeof: string, default: press. Sets the timing of the modifier key that resets the bar's visibility. Wanna reset visibility the moment the modifier key is pressed? Use press. Use release to reset visibility when the modifier key is released, and only if nothing else happened while it was held down. This is the one that stops your bar from vanishing when you use the modifier to switch a workspace, change binding mode, or start a keybinding. πŸ’…
  • exclusive β€” typeof: bool, default: true. Requests an exclusive zone from the compositor. Turn it off if you want application windows to be able to draw underneath or on top of the bar.
  • fixed-center β€” typeof: bool, default: true. Prefers a fixed center position for the modules-center block, so the center block stays in the middle of the bar whenever it possibly can. It can still get pushed around if the other blocks need more space. Set it to false and the center block gets centered in the space between the left and right blocks instead.
  • passthrough β€” typeof: bool, default: false. Passes any pointer events straight to the window under the bar. It's meant to be used with either the top or overlay layers, and with no exclusive zone.
  • ipc β€” typeof: bool, default: false. Subscribes to the Sway IPC bar configuration and visibility events, so you can control waybar with swaymsg bar commands. It requires a bar_id value from the sway configuration, which has to be either passed with the -b command line argument or set with the id option.
  • id β€” typeof: string. The bar_id for the Sway IPC. Use this when you need to override the value passed with the -b bar_id command line argument for this specific bar instance.
  • include β€” typeof: string|array. Paths to additional configuration files.
    • Each file can hold a single object with any of the bar configuration options. If options get duplicated, the first defined value wins, i.e. the including file β†’ the first included file β†’ and so on. Nested includes are allowed, just make sure you don't create circular imports. πŸ™… For a multi-bar config, the include directive only affects the current bar configuration object.
  • reload_style_on_change β€” typeof: bool, default: false. Enables reloading the CSS style whenever a modification is detected on the style sheet file, or on any imported CSS files. πŸ”₯
  • on-sigusr1 β€” typeof: string, default: toggle. The action performed when it receives the SIGUSR1 kill signal. Possible values: show, hide, toggle, reload, noop. Default value: toggle.
  • on-sigusr2 β€” typeof: string, default: reload. The action performed when it receives the SIGUSR2 kill signal. Possible values: show, hide, toggle, reload, noop. Default value: reload.

πŸŽ€ MODULE FORMAT πŸŽ€

You can use PangoMarkupFormat here β€” go peek at https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat for the whole menu of options.

e.g.

"format": "<span style="italic">{}</span>"

πŸ‘― MULTIPLE INSTANCES OF A MODULE πŸ‘―

Wanna run a second instance of a module? Just suffix it with a '#' and a custom name. So if you want a second battery module, drop "battery#bat2" into your modules. Then, to configure that brand new module, you also add a module configuration with the exact same name. Two batteries, double the drama. πŸ“

It could look something like this (heads up, this is an incomplete example):

"modules-right": ["battery", "battery#bat2"],
"battery": {
     "bat": "BAT1"
},
"battery#bat2": {
     "bat": "BAT2"
}

⭐ MINIMAL CONFIGURATION ⭐

A minimal config file could look like this:

{
     "layer": "top",
     "modules-left": ["sway/workspaces", "sway/mode"],
     "modules-center": ["sway/window"],
     "modules-right": ["battery", "clock"],
     "sway/window": {
          "max-length": 50
     },
     "battery": {
          "format": "{capacity}% {icon}",
          "format-icons": ["", "", "", "", ""]
     },
     "clock": {
          "format-alt": "{:%a, %d. %b  %H:%M}"
     }
}

🚨 SIGNALS 🚨

Waybar accepts the following signals, bestie:

  • SIGUSR1 β€” by default, this toggles the bar visibility (hides it if it's shown, shows it if it's hidden).
  • SIGUSR2 β€” by default, this reloads (resets) the bar.
  • SIGINT β€” this quits the bar. πŸ’€

So for example, to toggle the bar programmatically, you can invoke killall -SIGUSR1 waybar.

🌈 User signal configuration 🌈

The config parameters on-sigusr1 and on-sigusr2 change what happens when bars receive SIGUSR1 and SIGUSR2 signals.

Which means the commands killall -SIGUSR1 waybar and killall -SIGUSR2 waybar can perform a user-configured action.

It also means that if an external script has the PID of the bar, it can perform more complex show/hide/reload logic for each instance of Waybar. You can find the PID by doing something like pgrep -a waybar, which could then be matched by config name or other parameters. πŸ•΅οΈ

πŸ’… Kill parameter meanings πŸ’…

  • show β€” switches state to visible (per bar).
  • hide β€” switches state to hidden (per bar).
  • toggle β€” switches state between visible and hidden (per bar).
  • reload β€” reloads all waybars of the current waybar process (basically equivalent to restarting with updated config, which sets initial visibility values).
  • noop β€” does absolutely nothing when the kill signal is received. Iconic laziness. 😌

🌈 MULTI OUTPUT CONFIGURATION 🌈

Limit a configuration to some outputs

ok so if you want a bar setup that only lives on one (or a few) specific screens, you just hit it with the output key. like:

{
     "layer": "top",
     "output": "eDP-1",
     "modules-left": ["sway/workspaces", "sway/mode"],
     ...

}

and yeah bestie, she takes a list too if you wanna spread the love:

{
     "layer": "top",
     "output": ["eDP-1", "VGA"],
     "modules-left": ["sway/workspaces", "sway/mode"],
     ...
}

Configuration of multiple outputs

not me needing bars on every monitor πŸ’€ here's the trick: if you want multiple bars riding around on the same screen, you just don't specify an output. wild, right? then you hand it a whole array of configs:

[{
     "layer": "top",
     "output": "eDP-1",
     "modules-left": ["sway/workspaces", "sway/mode"],
     ...
}, {
     "layer": "top",
     "output": "VGA",
     "modules-right": ["clock"],
     ...
}]

Rotating modules πŸ”„

so when you've parked Waybar on the left or right edge of your screen, sometimes the text should be running vertically instead of chillin' horizontally. that's the rotate property on a module, and it eats it up:

{
     "clock": {
          "rotate": 90
     }
}

valid options for that rotate property are exactly: 0, 90, 180, and 270. don't get creative, that's the list πŸ’…


Swapping icon and label

if a module is serving both a label and an icon, sometimes you wanna flip the order (super handy for panels on the left or right of the screen, or if you're a right-to-left script user ✨). that's the swap-icon-label property, and it takes a boolean:

{
     "sway/window": {
          "swap-icon-label": true
     }
}

slay, order swapped, no cap.


Grouping modules 🫢

module groups let you stack modules in any direction, which is honestly iconic. by default: bar on top or bottom β†’ the group's modules stack vertically. bar on the left or right β†’ they stack horizontally. wanna change that up? the orientation property is your girl.

you make a group by defining a module named group/some-group-name. the group also has to get a list of the modules it's holding. like so:

{
     "modules-right": ["group/hardware", "clock"],

     "group/hardware": {
          "orientation": "vertical",
          "modules": [
               "cpu",
               "memory",
               "battery"
          ]
     },

     ...
}

and the valid options for that optional orientation property are: "horizontal", "vertical", "inherit", and "orthogonal" β€” and heads up, orthogonal is the default.


Group Drawers πŸŽ€

here's the cute part: a group can hide everything except one element, and only pop the rest out on mouse hover. that's the drawer property, and it's an object with all these little settings inside it:

  • transition-duration β€” typeof: integer, default: 500. this is how long the transition animation runs, in milliseconds.
  • children-class β€” typeof: string, default: "hidden". the CSS class that gets slapped onto the hidden elements.
  • click-to-reveal β€” typeof: bool, default: false. whether a left click should reveal the content instead of a mouse over. πŸ’€ careful tho, grouped modules may still process their own on-click events, so don't be surprised.
  • transition-left-to-right β€” typeof: bool, default: true. the direction of the transition animation. if true, the hidden elements slide left β†’ right. if false, right β†’ left.
when the bar is vertical, just read that as top-to-bottom, okay? πŸ™ˆ

and here's the whole vibe in one go:

"group/power": {
    "orientation": "inherit",
    "drawer": {
        "transition-duration": 500,
        "children-class": "not-power",
        "transition-left-to-right": false,
    },
    "modules": [
        "custom/power", // First element is the "group leader" and won't ever be hidden
        "custom/quit",
        "custom/lock",
        "custom/reboot",
    ]
},

not the little comment explaining that the first element is the "group leader" and legit never gets hidden πŸ‘‘ put respect on the leader's name fr fr.


πŸ“š SUPPORTED MODULES πŸ“š

okay bestie, here's the full roster of modules Waybar comes with. each one has its own man page, so go read up:

that's the whole lineup, no gatekeeping ✨


πŸ‘€ SEE ALSO πŸ‘€

go read those two if you wanna keep leveling up, iykyk 🌸


aaand that's a wrap bestie πŸ’– this page is from the 2026-02-08 edition of the Waybar manual, covering version waybar(5) β€” so if your copy is older, some of these options might not be giving what mine's giving. go style something iconic, you got this πŸ‘‘πŸ’…βœ¨

πŸ“¦ where this page comes from