rstatus feeds the i3bar protocol on stdout, so it works as status_command for i3, sway
and anything else speaking that protocol.
cargo build --release- builds with the default pipewire backend
Sound backends are selected by cargo features. Exactly one is not required - every enabled backend is compiled in, and the first one that connects at runtime is used (pipewire, then pulse, then alsa).
cargo build --release --features alsa- pipewire + alsacargo build --release --no-default-features --features pulse- pulseaudio onlycargo build --release --no-default-features- no sound support, the volume block always renders itsinvalidvalue
- pipewire (default)
- alsa (optional)
- pulseaudio (optional)
- copy one of the sample configs to the actual config, e.g. mkdir -p ~/.config/rstatus cp samples/simple.yaml ~/.config/rstatus/config.yaml ./rstatus
- if everything goes ok you could paste rstatus command to config of your tiling wm
The config path is fixed: $HOME/.config/rstatus/config.yaml. There are no command line options.
The config is a YAML sequence of blocks. Each entry is tagged with the block type and carries its options; blocks are rendered left to right in the order they are listed:
- !temperature
sensor: 'x86_pkg*'
suffix: ' °C'
interval: 3
- !time
format: '%H:%M'
interval: 1Available block types: !battery, !cpuload, !custom, !filesystem, !memory, !mpris, !network, !temperature, !time, !volume.
Unknown options are silently ignored, so a typo in an option name costs you the option without any warning.
- interval - update period in seconds.
0(the default) means the block is never updated by the timer, only by a signal. - signal - offset from
SIGRTMIN(34).0(the default) disables signal updates. Withsignal: 3the block is refreshed bypkill -RTMIN+3 rstatus.
At least one block must have a non-zero interval, otherwise rstatus prints nothing at
all and exits immediately. The timer resolution is the greatest common divisor of all
non-zero intervals.
Every block accepts these:
- interval - update interval in seconds (see above)
- signal - signal for updating the block (see above)
- separator_width - width in pixels of the separator drawn after the block
- custom_separator - custom symbol(s) drawn before the block instead of the
regular separator, used for powerline style bars. It is only rendered when bgcolor
is also set: the symbol is painted in this block's
bgcoloron top of the previous block's background. Setting it also suppressesseparator_widthfor this block. - color - foreground color of the value, '#RRGGBB' or 'RRGGBB' (default '#FFFFFF')
- bgcolor - background color of the whole block (default: none)
- prefix - text placed before the value
- prefix_color - color of the prefix (defaults to the current value color)
- suffix - text placed after the value
- suffix_color - color of the suffix (defaults to the current value color)
- invalid - string displayed when the value is invalid (default 'invalid'). While it is displayed, prefix and suffix are not rendered.
- invalid_color - color of the invalid string (default '#FF0000')
- threshold_fix - if true, prefix and suffix follow the threshold color instead of
prefix_color/suffix_color, but only while that threshold color actually differs fromcolor - thresholds - map of
lower bound: color. The color of the highest bound that is less than or equal to the value wins; below the lowest boundcoloris used. Only numeric values have thresholds - blocks producing text ignore them.
Note that the block name reported in the i3bar protocol is the block type
(temperature, volume, ...) and cannot be configured.
Some blocks inject their own prefix/suffix (battery statuses, network, volume jack
icons). Those are rendered between your prefix/suffix and the value, so both are
visible at once.
- sensor (required) - power supply directory, e.g. '/sys/class/power_supply/BAT0'.
statusandcapacityare read from it. - statuses - per-state decoration, each with its own
prefixandsuffix:- online - charging
- offline - discharging
- full - any other state reported by the kernel
- warning_level - capacity percentage below which
warning_actionfires (default 0, i.e. never) - warning_action - shell command executed while discharging and below
warning_level. It runs on every update, synchronously, so keep it short.
The value is the battery capacity in percent; a missing or unreadable sensor renders
invalid.
No options besides the common ones. The value is the busy CPU percentage since the
previous update, so the very first update always renders invalid.
- path (required) - any path on the filesystem you want to measure, e.g. '/home'
The value is used space in percent, rounded up.
No options besides the common ones. The value is used memory in percent, computed as
100 - MemAvailable / MemTotal from /proc/meminfo.
Shows what is playing, taken from any MPRIS2 player on the session bus
(org.mpris.MediaPlayer2.*). The block refreshes itself on player events, so it needs no
interval - unless you display the playing position, see format below.
-
players - preferred players, named by the part of the bus name after
org.mpris.MediaPlayer2., e.g.['pmcp', 'chromium']. An instance suffix is matched too, so 'chromium' also matcheschromium.instance123. When the list is not empty it doubles as a whitelist and players outside it are ignored entirely. Empty by default, meaning every player is considered. -
format - layout of the value. Omit it and you get
artist - title, falling back to whichever of the two the player reports. Set it and these placeholders are substituted:- {artist}, {title}, {album} - as reported by the player
- {player} - the player name, the same one players matches on
- {position}, {length} - times, as
mm:ss, widening toh:mm:sspast an hour
Text in
[ ]is an optional group: it is printed with its brackets when every placeholder inside it resolves, and dropped entirely when any of them does not, which is how'{title} [{position}/{length}]'degrades to just the title on a stream reporting no length. Outside a group an unresolved placeholder renders as nothing, leaving whatever literal text you put around it, so prefer a group when a field may be missing. An unknown placeholder is left as written, to make a typo visible. -
max_length - maximum length in characters of the text the block shows, an overlong value is cut and gets '…' appended.
0(the default) means unlimited. With format it is a budget shared by{artist},{title},{album}and{player}, spent in the order they appear;{position}and{length}never count against it and are never truncated, so the clock survives however long the title is. -
statuses - per-state decoration, each with its own
prefixandsuffix, exactly like !battery:- playing
- paused
- stopped
When several players are alive the playing one wins, then the paused one; ties are broken
by the order of players and then by whoever started playing last. With no player at
all - or a player reporting no track - the block renders invalid, so invalid: '' hides
it while nothing is playing.
Showing the position needs interval: 1. MPRIS deliberately does not announce the
playing position - it would be a signal per second per player - so the block samples it on
the events players do send and counts on from there. Without an interval nothing
re-renders between those events and the clock appears stuck. The interval costs no D-Bus
traffic, it only redraws:
- !mpris
interval: 1
format: '{title} [{position}/{length}]'
max_length: 40Reports on the interface holding the default route with the lowest metric.
- wifi - prefix used when that interface is wireless (default 'wifi'). The value is then the signal strength in percent, with '%' appended automatically.
- ethernet - text displayed as the value when the interface is not wireless (default 'eth')
Without a default route the block renders invalid.
- sensor (required) - sensor name or name mask, e.g. 'x86_pkg_temp' or 'x86_pkg*'.
Masks support
*(any sequence of characters) and?(exactly one character); a mask without wildcards is an exact name match.
Names are matched against /sys/class/thermal/*/type, /sys/class/hwmon/*/name and the hwmon temp*_label files, so chips exposing no thermal zone (coretemp, k10temp, nvme, amdgpu) are covered too. When a mask matches several sensors, the highest temperature among them is displayed - 'coretemp*' therefore shows the hottest core. The value is in degrees Celsius. Sysfs paths are not accepted, use names instead.
- format - chrono/strftime format string (default '%d.%m.%Y %H:%M')
The backend is chosen at runtime: pipewire, then pulseaudio, then alsa, limited to the
features the binary was built with. The block refreshes itself on backend events, so it
does not need an interval.
- mixer - alsa simple mixer element name (default 'PCM'). If a 'Master' element
exists, muting Master renders
invalidand the displayed level is taken from mixer. Pipewire and pulseaudio always report the default sink volume and ignore this option. - card - alsa card name (default 'default'). Ignored by pipewire and pulseaudio.
- jack_icons - list of two strings,
[plugged, unplugged], used as an icon in front of the value. Lists shorter than two entries are ignored. - jack_only - list of sink names that are always treated as "jack plugged", useful
for outputs with no jack detection. The sink name is
node.nickon pipewire, the default sink name on pulseaudio, and the card name on alsa. - alsa_jack_switch_outputs - alsa only. On plug mute 'Speaker' and unmute 'Headphone', on unplug do the opposite (default false).
- alsa_jack_mute_on_unplug - alsa only. Mute 'Master' when the jack is unplugged (default false).
- alsa_jack_unmute_on_plug - alsa only. Unmute 'Master' when the jack is plugged (default false).
A muted output renders invalid, which is how the samples display a "muted" indicator.
- command (required) - shell command executed via
sh -c
The first line of stdout is the value: it becomes a number if it parses as one
(thresholds then apply), otherwise it is used as text. The optional second line sets the
value color ('#RRGGBB' or 'RRGGBB'); once set it replaces color for good. Empty output
renders invalid.
See one of samples for syntax. It asks from your binary/shell scripts for output. First line is for value, second is for color(optional) Please also note, custom block executes command in the main thread. That means you shoud not make network requests here. This could be implemented in async way, but it also means you have to detect network activity, failure handlers and so on. Instead please check systemd timers, you always could send unix signal(kill/pkill) to rstatus from process triggered by systemd.


