swaync(5)
swaync(5) straight outta the File Formats Manual β part 1 of 5, and bestie we are going to read the whole config together, no skipping π
πΈ NAME πΈ
swaync β Configuration file. That's it, that's the whole name section, she's concise π
βοΈ CONFIGURATION βοΈ
Okay so real talk first: when you're editing the config file, please use a text editor that has a JSON language server, because that's literally how you catch config errors before they wreck your whole vibe. Do not rawdog this in notepad, I'm begging π«Ά
Every option below is written like it lives in your config, with its type, its default, its values (if it has any) and what it actually does. Let's go β¨
ignore-gtk-theme- type:
bool - default:
true - description: Unsets the
GTK_THEMEenvironment variable. This fixes a lot of issues where GTK themes were out here ruining the user's custom CSS themes. Iconic behaviour honestly π
- type:
positionX- type:
string - default:
right - values:
left,right,center - description: Horizontal position of the control center and the notification window. Same energy for both, no cap.
- type:
positionY- type:
string - default:
top - values:
top,center,bottom - description: Vertical position of the control center and the notification window. The vertical bestie to
positionX's horizontal.
- type:
layer- type:
string - default:
overlay - values:
background,bottom,top,overlay - description: Layer of the notification window relative to normal windows.
backgroundis below all windows,overlayis above all windows. Pick your fighter.
- type:
layer-shell- type:
bool - default:
true - description: Wether or not the windows should be opened as layer-shell surfaces.
- type:
β οΈ Heads up bestie: this one Requires a swaync restart to apply. No hot reload, she needs a nap and a comeback. π
cssPriority- type:
string - default:
application - values:
application,user - description: Which GTK priority to use when loading the default and user CSS files. Pick
"user"if you want to overrideXDG_CONFIG_HOME/gtk-3.0/gtk.css. Main character CSS energy, you love to see it π
- type:
control-center-positionX- type:
string - default:
right - values:
left,right,center - description: Optional: horizontal position of the control center. Supersedes
positionXif it's not set tonone.
- type:
control-center-positionY- type:
string - default:
top - values:
top,center,bottom - description: Optional: vertical position of the control center. Supersedes
positionYif it's not set tonone.
- type:
control-center-margin-top- type:
integer - default:
0 - description: The margin (in pixels) at the top of the notification center.
0to disable.
- type:
control-center-margin-bottom- type:
integer - default:
0 - description: The margin (in pixels) at the bottom of the notification center.
0to disable.
- type:
control-center-margin-right- type:
integer - default:
0 - description: The margin (in pixels) at the right of the notification center.
0to disable.
- type:
control-center-margin-left- type:
integer - default:
0 - description: The margin (in pixels) at the left of the notification center.
0to disable.
- type:
control-center-layer- type:
string - default:
top - values:
background,bottom,top,overlay - description: Layer of the control center window relative to normal windows.
backgroundis below all windows,overlayis above all windows. Same scale, different window π
- type:
control-center-exclusive-zone- type:
bool - default:
true - description: Whether or not the control center should follow the compositor's exclusive zones. A whole example: set it to
falseif you want it to cover your panel/dock. Rude but valid π«Ά
- type:
notification-2fa-action- type:
bool - default:
true - description: If each notification should display a
'COPY "1234"'action. Two-factor codes, we copy you, we love you π
- type:
timeout- type:
integer - default:
10 - description: The notification timeout for notifications with normal priority.
- type:
timeout-low- type:
integer - default:
5 - description: The notification timeout for notifications with low priority.
- type:
timeout-critical- type:
integer - default:
0 - description: The notification timeout for notifications with critical priority.
0to disable. Critical notifs get to stay, as they should π
- type:
notification-window-width- type:
integer - default:
500 - description: Width of the notification in pixels.
- type:
notification-window-height- type:
integer - default:
-1 - description: Max height of the notification in pixels.
-1to use the full amount of space given by the compositor. Let the compositor cook π
- type:
notification-window-preferred-output- type:
string - default:
"" - description: The preferred output to open the notification window (popup notifications) on. Can either be the monitor connector name (ex:
"DP-1"), or the full name, manufacturer model serial (ex:"Acer Technologies XV272U V 503023B314202"). If the output is not found, the currently focused one is picked. She'll find her way home π«
- type:
keyboard-shortcuts- type:
bool - default:
true - description: If the control center should use keyboard shortcuts.
- type:
notification-grouping- type:
bool - default:
true - description: If notifications should be grouped by app name. Organization is self care π§
- type:
image-visibility- type:
string - default:
always - values:
always,when-available,never - description: An explanation about the purpose of this instance. (Yes, that's literally what the docs say for this one. We keep it verbatim, bestie, that's the rule ππ)
- type:
transition-time- type:
integer - default:
200 - description: The notification animation duration.
0to disable. Motion is cute, but so is instant, you do you β¨
- type:
hide-on-clear- type:
bool - default:
false - description: Hides the control center after pressing
"Clear All". Bye bye panel π
- type:
hide-on-action- type:
bool - default:
true - description: Hides the control center when clicking on a notification action. Handled it, out of my sight π
- type:
text-empty- type:
string - default:
"No Notifications" - description: Text that appears when there are no notifications to show. The quiet era πΈ
- type:
fit-to-screen- type:
bool - default:
true - description: Whether the control center should expand vertically to fill the screen.
- type:
relative-timestamps- type:
bool - default:
true - description: Display notification timestamps relative to now, e.g.
"26 minutes ago". Iffalse, a local iso8601-formatted absolute timestamp is displayed. Choose your timeline aesthetic β°
- type:
control-center-height- type:
integer - default:
500 - description: Height of the control center in pixels.
- A value of
-1means that it will fit to the content. - Ignored when
'fit-to-screen'is set to'true'. - Also limited to the height of the monitor, unless
'layer-shell-cover-screen'is set tofalse.
- A value of
- type:
control-center-width- type:
integer - default:
500 - description: The control center width in pixels.
- type:
control-center-preferred-output- type:
string - default:
"" - description: The preferred output to open the control center on. Can either be the monitor connector name (ex:
"DP-1"), or the full name, manufacturer model serial (ex:"Acer Technologies XV272U V 503023B314202"). If the output is not found, the currently focused one is picked. Same rules as the notification one, different window π
- type:
notification-action-filter- type:
object - visibility object properties:
use-regex- type:
bool - optional: true
- default:
false - description: Indicates if all the below fields should use regex or not.
- type:
app-name- type:
string - optional: true
- description: The app-name.
- type:
desktop-entry- type:
string - optional: true
- description: The desktop-entry.
- type:
id-matcher- type:
string - optional: true (needs at least one matcher)
- description: Matches the action's identifier. Can be found by reading the output of swaync when run with the
G_MESSAGES_DEBUG=allenvironment variable.
- type:
text-matcher- type:
string - optional: true (needs at least one matcher)
- description: Matches the action's text visible in the notification.
- type:
- description: Hides matching action(s) of matching notifications. If the notification doesn't include one of the properties, that property will be ignored. If all properties match the given notification, the matching actions will be hidden.
- example:
- type:
{
"notification-action-filter": {
"hide-chromium-settings": {
"desktop-entry": "chromium-browser",
"use-regex": false,
"id-matcher": "settings",
"text-matcher": "Settings"
}
},
}
And that's a wrap on the config options, but bestie we are NOT done β this was only part 1 of 5. Stay tuned, there's more page to slay πβ¨
πΈ notification-visibility πΈ
ok so this one is type: object, and every key inside it is a visibility object with these properties bestie, listen up:
stateβ type: string, optional: false (so you literally have to give it), default:enabled, values:ignored,muted,transient,enabled. it's the notification visibility state πoverride-urgencyβ type: string, optional: true, default:unset, values:unset,low,normal,critical. this is the new urgency for the notification if it's set β¨app-nameβ type: string, optional: true. the app-name. uses Regex π§desktop-entryβ type: string, optional: true. the desktop-entry. uses Regex π§summaryβ type: string, optional: true. the summary of the notification. uses Regex π§bodyβ type: string, optional: true. the body of the notification. uses Regex π§urgencyβ type: string, optional: true, default:Normal, values:Low,Normal,Critical. the urgency of the notification π¨categoryβ type: string, optional: true. which category the notification belongs to. uses Regex π§
description: set the visibility or override the urgency of each incoming notification. if the notification doesn't include one of the properties, that property gets ignored (no hard feelings, it just skips it). all properties β except for state β use regex. if all the properties match the given notification, then the notification will follow the provided state. and bestie, pay attention: only the first matching object will be used. so order matters, periodt π
example:
{
"notification-visibility": {
"example-name": {
"state": "The notification state",
"app-name": "Notification app-name Regex",
"summary": "Notification summary Regex",
"body": "Notification body Regex",
"urgency": "Low or Normal or Critical",
"category": "Notification category Regex"
}
}
}
π widgets π
type: array. the default values are literally ["title", "dnd", "notifications"] and honestly, iconic lineup π
valid array values (peep widget-config for the whole tea):
notificationsβ required: true, optional: false (she is NOT optional, she is the moment π)titleβ optional: truedndβ optional: truelabelβ optional: truemprisβ optional: truemenubarβ optional: truebuttons-gridβ optional: truesliderβ optional: truevolumeβ optional: truebacklightβ optional: trueinhibitorsβ optional: true
description:
which order and which widgets to display. simple as that π¦
if the "notifications" widget isn't specified, it will be placed at the bottom. so like, she shows up anyway, she just shows up last β¨
multiple of same widget:
ok this is the part where it gets cute. append a # with any value to the end of the widget name. example: "title#TheMainTitle" π
and to address this widget specifically in the css file, use the css class .TheMainTitle π
example:
{
"widgets": [
"inhibitors",
"title",
"dnd",
"notifications"
]
}
π§ widget-config β the part where u make each widget yours
type: object
description: Configure specific widget properties.
Like. This is the section where u stop treating ur notification daemon as one big blob and start whispering to individual widgets about how u want them to behave. Very main character energy. π β¨
π got multiple of the same widget??
okay bestie this is the trick that unlocks everything:
- Append a
#with any value to the end of the widget name. - Example:
"title#TheMainTitle" - To address this widget specifically in the css file use the css class
.TheMainTitle
So u can have a title and a title#TheMainTitle and style them totally separately. iconic. π
π Widgets to customize
π notifications
type:object- css class:
widget-notifications - properties:
vexpandβ type:bool, optional:true, default:trueβ Whether or not the notifications widget should vertically expand or not
- description: The Notifications Widget.
π·οΈ title
type:object- css class:
widget-title - properties:
textβ type:string, optional:true, default:"Notifications"β The title of the widgetclear-all-buttonβ type:bool, optional:true, default:trueβ Whether to display a"Clear All"buttonbutton-textβ type:string, optional:true, default:"Clear All"β"Clear All"button text
- description: The notification visibility state.
π dnd
type:object- css class:
widget-dnd - properties:
textβ type:string, optional:true, default:"Do Not Disturb"β The title of the widget
- description: Control Center Do Not Disturb Widget.
π label
type:object- css class:
widget-label - properties:
textβ type:string, optional:true, default:"Label Text"β The text content of the widgetclear-all-buttonβ type:integer, optional:true, default:5β The maximum lines
yes bestie that one is anintegerand yes it's namedclear-all-button. we don't make the rules, we just report them faithfully. π«
- description: A generic widget that allows the user to add custom text.
π΅ mpris
type:object- css classes:
widget-mpriswidget-mpris-playerwidget-mpris-titlewidget-mpris-subtitle
- properties:
blacklistβ type:array, optional:true, default:[]β Audio sources for the mpris widget to ignore.- Valid array values:
type:stringdescription: Audio source/app name. Regex allowed. Hint$ qdbus | grep mpristo find source names.
- Valid array values:
autohideβ type:bool, optional:true, default:falseβ Whether to hide the widget when the player has no metadata.show-album-artβ type:string, optional:true, default:"always"β Whether or not the album art should be hidden, always visible, or only visible when a valid album art is provided.enum:["right", "left"]
loop-carouselβ type:bool, optional:true, default:falseβ Whether to loop through the mpris carousel.
- description: A widget that displays multiple music players.
not me staring at thatenum: ["right", "left"]undershow-album-artπ that's exactly what the page says, so that's exactly what u get. no notes. π
π menubar
type:object- css classes:
widget-menubar.widget-menubar>box>.menu-button-bar- name of element given after menu or buttons with
#
- patternProperties:
menu#<name>type:object- properties:
labelβ type:string, optional:true, default:"Menu"β Label of button to show/hide menu dropdownpositionβ type:string, optional:true, default:"right"β Horizontal position of the button in the barenum:["right", "left"]
animation-typeβ type:string, optional:true, default:"slide_down"β Animation type for menuenum:["slide_down", "slide_up", "none"]
animation-durationβ type:integer, optional:true, default:250β Duration of animation in millisecondsactionsβ type:array, Default values:[]β A list of actions containing a label and a command- Valid array values:
type:object- properties:
labelβ type:string, default:"label"β Text to be displayed in buttoncommandβ type:string, default:""β"Command to be executed on click"typeβ type:string, default:"normal"β Type of the button. Toggle buttons receive the'.active'css classenum:["normal", "toggle"]update-commandβ type:string, default:""β"Command to be executed on visibility change of cc to update the active state of the toggle button (should echo true or false)"activeβ type:bool, default:falseβ Wether the toggle button is active as default or not
- Valid array values:
- description: A button to reveal a dropdown with action-buttons
buttons#<name>type:object- properties:
positionβ type:string, optional:true, default:"right"β Horizontal position of the buttons in the barenum:["right", "left"]
actionsβ type:array, Default values:[]- Valid array values:
type:objectproperties:labelβ type:string, default:"label"β Text to be displayed in buttoncommandβ type:string, default:""β"Command to be executed on click"typeβ type:string, default:"normal"β Type of the button. Toggle buttons receive the'.active'css class and an env variable"SWAYNC_TOGGLE_STATE"is set. See example usage in the defaultconfig.jsonenum:["normal", "toggle"]update-commandβ
- Valid array values:
okay so continuing the widget tour, bestie π β the previous widget (you know the one) wraps up with these final properties:
typeβ type:string; default:""; description: "Command to be executed on visibility change of cc to update the active state of the toggle button (should echo true or false)" yes that's a whole sentence, slayactiveβ type:bool; default:false; description: Wether the toggle button is active as default or not (note: "Wether" is the original spelling, iykyk)- description: A list of actions containing a label and a command
- description: A list of buttons to be displayed in the menu-button-bar
β¨ buttons-grid β¨
this one is giving a grid of buttons that execute shell commands π₯
typeβ type:objectcss classβwidget-buttons(access buttons with>flowbox>flowboxchild>button)buttons-per-rowβ type:numberactionsβ type:array; Default values:[]; description: A list of actions containing a label and a command; Valid array values:- type:
object - properties:
labelβ type:string; default:"label"; description: Text to be displayed in buttoncommandβ type:string; default:""; description: "Command to be executed on click"typeβ type:string; default:"normal"; description: Type of the button Toggle buttons receive the '.active' css class and an env variable "SWAYNC_TOGGLE_STATE" is set. See example usage in the default config.json; enum:["normal", "toggle"]activeβ type:bool; default:false; description: Wether the toggle button is active as default or not
- type:
descriptionβ description: A grid of buttons that execute shell commands
ποΈ slider ποΈ
general slider control, periodt π
typeβ type:objectcss classβwidget-sliderlabelβ type:string; optional:true; default:"slider"; description: Text displayed in front of the slidercmd_setterβ type:string; optional:true; default:""; description: command to set the value. Use$valueto get the current value.cmd_getterβ type:string; optional:true; default:""; description: command to get the actual value. Use$valueto get the current value.minβ type:integer; optional:true; default:0; description: minimum value of the slider rangemaxβ type:integer; optional:true; default:100; description: maximum value of the slider rangemin_limitβ type:integer; optional:true; default:0; description: limit minimum value of the slidermax_limitβ type:integer; optional:true; default:100; description: limit maximum value of the slidervalue_scaleβ type:integer; optional:true; default:0; description: scale small value, slider round digitsdescriptionβ description: general slider control
π volume π
slider to control pulse volume, no cap πΆ
typeβ type:objectcss classβwidget-volume,per-app-volumelabelβ type:string; optional:true; default:"Volume"; description: Text displayed in front of the volume slidershow-per-appβ type:bool; optional:true; default:false; description: Show per app volume controlshow-per-app-iconβ type:bool; optional:true; default:false; description: Show application icon in per app controlshow-per-app-labelβ type:bool; optional:true; default:false; description: Show application name in per app controlexpand-per-appβ type:bool; optional:true; default:false; description: If the per app section should start expandedempty-list-labelβ type:string; optional:true; default:"No active sink input"; description: Text displayed when there are not active sink inputsexpand-button-labelβ type:string; optional:true; default:"β§"; description: Label displayed on button to show per app volume controlcollapse-button-labelβ type:string; optional:true; default:"β©"; description: Label displayed on button to hide per app volume controlanimation-typeβ type:string; optional:true; default:"slide_down"; description: Animation type for the per app volume control; enum:["slide_down", "slide_up", "none"]animation-durationβ type:integer; optional:true; default:250; description: Duration of animation in millisecondsdescriptionβ description: Slider to control pulse volume
π‘ backlight π‘
slider to control screen brightness, main character energy β¨
typeβ type:objectcss classβwidget-backlightlabelβ type:string; optional:true; default:"Brightness"; description: Text displayed in front of the backlight sliderdeviceβ type:string; optional:true; default:"intel_backlight"; description: Device in/sys/class/backlightor/sys/class/ledssubsystemβ type:string; optional:true; default:"backlight"; description: Kernel subsystem for brightness control; enum:["backlight", "leds"]minβ type:integer; optional:true; default:0; description: Lowest possible value for brightnessdescriptionβ description: Slider to control screen brightness
π« inhibitors π«
displayed if notifications are inhibited, iykyk π
typeβ type:objectcss classβwidget-inhibitorstextβ type:string; optional:true; default:"Inhibitors"; description: The title of the widgetclear-all-buttonβ type:bool; optional:true; default:true; description: Whether to display a "Clear All" buttonbutton-textβ type:string; optional:true; default:"Clear All"; description: "Clear All" button textdescriptionβ description: Displayed if notifications are inhibited.
{
"widget-config": {
"title": {
"text": "Notifications",
"clear-all-button": true,
"button-text": "Clear All"
},
"dnd": {
"text": "Do Not Disturb"
},
"label": {
"max-lines": 5,
"text": "Label Text"
},
"mpris": {
"blacklist": ["playerctld"],
"autohide": true,
"show-album-art": "always",
"loop-carousel": false
},
"menubar": {
"menu#power": {
"label": "Power",
"position": "right",
"actions": [
{
"label": "Shut down",
"command": "systemctl poweroff"
},
...
]
},
"buttons#screenshot": {
"position": "left",
"actions": [
{
"label": "Screenshot",
"command": "grim"
},
...
]
}
},
"buttons": {
"actions": [
{
"label": "wifi",
"command": "rofi-wifi-menu"
},
...
]
}
}
}
π Scripts π
Bestie. Okay. This part is literally my favorite, because it's how you make swaync do things when notifications roll in. It's giving automation queen energy. π
script-fail-notifyβ type:bool, default:true. If a script just... does not run? Yeah, you get a notification about it. Keeping you in the loop fr fr. πscriptsβ type:object. The properties of a script object, babes:execβ type:string, optional:false. The script to run. You can also run regular shell commands here, no cap.app-nameβ type:string, optional:true. The app-name. Uses Regex.desktop-entryβ type:string, optional:true. The desktop-entry. Uses Regex.summaryβ type:string, optional:true. The summary of the notification. Uses Regex.bodyβ type:string, optional:true. The body of the notification. Uses Regex.urgencyβ type:string, optional:true, default:Normal, values:Low,Normal,Critical. The urgency of the notification. π¨categoryβ type:string, optional:true. Which category the notification belongs to. Uses Regex.sound-fileβ type:string, optional:true. Which sound file the notification requested. Uses Regex.sound-nameβ type:string, optional:true. Which sound name the notification requested. Uses Regex.run-onβ type:string, optional:true, values:action,receive, default:receive. Whether to run this action when the notification is received, or when an action is taken on it.
- description: which scripts to check and potentially run for every notification. If the notification doesn't include one of the properties, that property will be ignored. All properties (except for
exec) use regex. If all properties match the given notification, the script will be run. Only the first matching script will be run. π - example:
{
"scripts": {
"example-script": {
"exec": "Your shell command or script here...",
"app-name": "Notification app-name Regex",
"summary": "Notification summary Regex",
"body": "Notification body Regex",
"urgency": "Low or Normal or Critical",
"category": "Notification category Regex"
}
}
}
You can also use these environment variables in your script, bestie β they're just handed to you, no setup required:
$SWAYNC_BODY="Notification body content"
$SWAYNC_DESKTOP_ENTRY="Desktop entry"
$SWAYNC_URGENCY="Notification urgency"
$SWAYNC_TIME="Notification time"
$SWAYNC_APP_NAME="Notification app name"
$SWAYNC_CATEGORY="SwayNC notification category"
$SWAYNC_REPLACES_ID="ID of notification to replace"
$SWAYNC_ID="SwayNC notification ID"
$SWAYNC_SUMMARY="Notification summary"
$SWAYNC_HINT_[NAME]="Value of the hint [NAME]"
$SWAYNC_SOUND_NAME="The name of the requested sound"
$SWAYNC_SOUND_FILE="The file path of the requested sound"
And that's a wrap on swaync(5)! π¦ This little icon of a page comes from the swaync source, dated 2026-05-19. Go forth and configure, you gorgeous genius β your notifications have never looked this good. β¨ππ
π¦ where this page comes from
- fedora 43: SwayNotificationCenter 0.12.6-1.fc43 Β· GPL-3.0-only
- fedora 44: SwayNotificationCenter 0.12.6-1.fc44 Β· GPL-3.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms