swaybar-protocol(7)
π NAME π
swaybar-protocol β the JSON status line protocol for swaybar, bestie. Yes, that status line. The one chilling on the right side of your bar. We're gonna speak fluent JSON together, iykyk.
(Also hello, this is from the Miscellaneous Information Manual section of the swaybar-protocol(7) page, in case you were wondering where we're at π«Ά)
β¨ SUMMARY β¨
Okay so here's the whole vibe: swaybar defines the following JSON protocol to specify what information is displayed in the status line on the right side of swaybar.
The protocol is literally just two things, babes:
- A header β that's a JSON object, followed by a newline (
0x0A) - Then an infinite JSON array that represents the information to display
That's it. That's the whole protocol. And all communication is done by writing the status line to standard output and reading events from standard input. Very demure, very stdio π
πΈ HEADER πΈ
The header is a JSON object with support for the following properties β and heads up, only version is required. Everything else is optional, no pressure bestie π
versionβ data type:integer, default:-. This is the protocol version to use. Currently, this must be1. (Like, it literally has to be 1. Don't try to be cute with it.)click_eventsβ data type:boolean, default:false. Whether to receive click event information to standard input. Set it totrueand your clicks come home to you πcont_signalβ data type:integer, default:SIGCONT. The signal thatswaybarshould send to continue processing. Go off, signal, resume the timeline βstop_signalβ data type:integer, default:SIGSTOP. The signal thatswaybarshould send to stop processing. Pause. Breathe. Drama. π
π MINIMAL HEADER
The bare minimum. The "I woke up like this" of headers. Lowkey iconic:
{
"version": 1
}
π¦ FULL HEADER
And here's the full send β every property showing up to the function, main character energy:
{
"version": 1,
"click_events": true,
"cont_signal": 18,
"stop_signal": 19
}
π₯ BODY π₯
The body is an infinite array, where each element of the array is a representation of the status line at the time that the element was written. So like, every time you write an element, that's a fresh snapshot of your bar. Time-stamped vibes, fr fr β
Each element of the array is itself an array of JSON objects, where each object represents a block in the status line. So it's arrays within arrays β nesting era, we love to see it πͺ
Each block can have the following properties β and yes, only full_text is required, everything else is a garnish:
Okay so here's the property table, but make it a glow-up list because tables are lowkey not it. Every property, every type, every default β all of it, bestie π
full_textβ string β the actual text that gets displayed. If it's missing, the whole block gets skipped. Periodt, no text no block πshort_textβ string β if you give this AND the text needs to be shortened because of space, this gets displayed instead offull_text. It's giving backup outfit energy β¨colorβ string β the text color to use, in#RRGGBBAAor#RRGGBBnotation π¨backgroundβ string β the background color for the block, in#RRGGBBAAor#RRGGBBnotationborderβ string β the border color for the block, in#RRGGBBAAor#RRGGBBnotationborder_topβ integer β the height in pixels of the top border. The default is1border_bottomβ integer β the height in pixels of the bottom border. The default is1border_leftβ integer β the width in pixels of the left border. The default is1border_rightβ integer β the width in pixels of the right border. The default is1min_widthβ integer or string β the minimum width to use for the block. This can either be given in pixels, or a string can be given to allow for it to be calculated based on the width of the string. Flexible queen behavior πalignβ string β if the text does not span the full width of the block, this specifies how the text should be aligned inside of the block. This can beleft(default),right, orcenternameβ string β a name for the block. This is only used to identify the block for click events. If set, each block should have a unique name and instance pair. Don't be out here duplicating, it's not cute πinstanceβ string β the instance of the name for the block. This is only used to identify the block for click events. If set, each block should have a unique name and instance pair. Same rule, bestie, uniqueness is the vibe check π¦urgentβ boolean β whether the block should be displayed as urgent. Currently swaybar utilizes the colors set in the sway config for urgent workspace buttons. Seesway-bar(5)for more information on bar color configuration π₯separatorβ boolean β whether the bar separator should be drawn after the block. Seesway-bar(5)for more information on how to set the separator textseparator_block_widthβ integer β the amount of pixels to leave blank after the block. The separator text will be displayed centered in this gap. The default is9pixels πΈ
okay so the last block-property row is this one, bestie:
markup(string) β The type of markup to use when parsing the text for the block. This can either bepangoornone(default).
Other properties may be given and swaybar will ignore any property that it does not know. It is recommended to prefix any custom properties with an underscore to make it easier to distinguish them from protocol properties.
πΈ BODY EXAMPLE πΈ
[
[
{
"full_text": "25%",
"min_width": "100%",
"urgent": false
},
{
"full_text": "Thu 30 May 2019 02:15:15"
}
],
[
{
"full_text": "20%",
"min_width": "100%",
"urgent": false
},
{
"full_text": "Thu 30 May 2019 02:20:52"
}
],
[
{
"full_text": "15%",
"min_width": "100%",
"urgent": true
},
{
"full_text": "Thu 30 May 2019 02:25:41"
}
],
...
π FULL BLOCK EXAMPLE π
{
"full_text": "Thu 30 May 2019 02:09:15",
"short_text": "02:09",
"color": "#ccccccff",
"background": "#111111ff",
"border": "#222222ff",
"border_top": 1,
"border_bottom": 1,
"border_left": 1,
"border_right": 1,
"min_width": 100,
"align": "center",
"name": "clock",
"instance": "edt",
"urgent": false,
"separator": true,
"separator_block_width": 5,
"markup": "none"
}
π₯ CLICK EVENTS π₯
If requested in the header, swaybar will write a JSON object, that can be read from standard in, when the user clicks on a block. The event object will have the following properties:
name(string) β The name of the block, if setinstance(string) β The instance of the block, if setx(integer) β The x location that the click occurred aty(integer) β The y location that the click occurred atbutton(integer) β The x11 button number for the click. If the button does not have an x11 button mapping, this will be0.event(integer) β The event code that corresponds to the button for the clickrelative_x(integer) β The x location of the click relative to the top-left of the blockrelative_y(integer) β The y location of the click relative to the top-left of the blockwidth(integer) β The width of the block in pixelsheight(integer) β The height of the block in pixels
Differences from i3bar's protocol:
buttonmay be0for buttons that do not have x11 button mappingseventhas been introduced to allow for non-x11 buttons to be represented- The
modifiersproperty is not currently added by swaybar
π EXAMPLE π
{
"name": "clock",
"instance": "edt",
"x": 1900,
"y": 10,
"button": 1,
"event": 274,
"relative_x": 100,
"relative_y": 8,
"width": 120,
"height": 18
}
π SEE ALSO π
sway-bar(5)β go peek at that one too, bestie π«Ά
okay thatβs the whole swaybar-protocol(7) page, dated 2026-04-26 β footer served, no cap π
β¨
π¦ where this page comes from
- alpine 3.24: sway-doc 1.12_rc3-r0 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms