User-contributed article: enhanced and extensible i3bar with py3status

In the i3 documentation, the recommended tool for displaying a status line is to use i3status combined with i3bar.

While i3status is very efficient at what it does, it is, by design, fairly limited to a few modules and file output which does not give the flexibility to users to easily add anything they want to their bar.

This is said pretty clearly on the i3status man page:


    In i3status, we don’t want to implement process management again.
    Therefore, there is no module to run arbitrary scripts or commands.
    Instead, you should use your shell.

Introducing py3status

The goal of py3status is to fill this gap by allowing users to simply extend their i3bar while preserving their current i3status configuration. The main idea is to rely on i3status' strength without adding any configuration on the user's side. py3status is thus a wrapper script for i3status and its configuration as explained in the documentation below. This should be said that py3status is much more than just a wrapper script.


View the full documentation now or bookmark it for later viewing:

Using py3status

Using py3status has never been so easy. Update your i3 config with this and you're done:

bar {
    status_command py3status

In other words, just replace i3status in your current status_command by py3status.

Py3status will look for status config file in this order.

1    ~/.config/py3status/config
2    ~/.config/i3status/config
3    ~/.config/i3/i3status.conf
4    ~/.i3status.conf
5    ~/.i3/i3status.conf
6    /etc/xdg/i3status/config
7    /etc/i3status.conf

Alternatively, you can start from scratch with an empty status config.

bar {
    status_command py3status -c ~/.config/py3status/config

Learn more about how to configure py3status on the configuration documentation

Using py3status modules

Like i3status, py3status comes with modules (but a lot of them!).

Learn more about the modules provided by py3status on the modules documentation

Like i3status, we can add and configure the modules the same way... usually in the status config.

An excerpt from man 1 i3status.


    The basic idea of i3status is that you can specify which "modules" should be
    used (the order directive).
    You can then configure each module with its own section. For every module,
    you can specify the output format.

A skeleton reference.

order += "module_name"
module_name {
    config_name = "..."

An example of using imap module.

order += "battery 0"
order += "disk /"
order += "imap"    <----
order += "time"

# add imap settings and open xterm with mutt on left-click
imap {
    user = "alex"
    password = "ilovebugs"
    port = "993"
    server = ""

    on_click 1 = "exec xterm -e mutt"

Clicking the modules

Starting with version 2.0, py3status allows the mouse click events from the modules to be bound as options in the status config where the users can configure what to do when they received the click events.

It is possible to run commands, scripts, or programs with a click.

You can place the configuration parameter on_click [button number] = "[command]" in the module section. Py3status will run the command using i3-msg when the module's click event matches the configured module section's click event.

Quick reference:

on_click [button number] = "[command]"
on_click 1 = "exec firefox"    ---->    i3-msg "exec firefox"

Click events buttons reference:

1 left button
2 middle button
3 right button
4 up scroll
5 down scroll

Examples of using on_click config:

# reload i3 on left-click
# restart i3 on middle-click
time {
    on_click 1 = "reload"
    on_click 2 = "restart"

# open wicd-gtk on left-click
# kill wicd-gtk on right-click
ethernet eth0 {
    on_click 1 = "exec wicd-gtk"
    on_click 3 = "exec killall wicd-gtk"

# open thunar on left-click
disk {
    on_click 1 = "exec thunar"

# open firefox with an URL on left-click
weather_yahoo paris {
    on_click 1 = "exec firefox

Grouping the modules

The group module allows you to group several modules together to save space. Only one of the them will be displayed at a time.

The modules of a group can either be cycled through automatically or by user action (mouse scroll by default).

An example of using the group module with 3 different tztime modules:

order += "group tz"

# cycle through different timezone hours every 10s
group tz {
    cycle = 10
    format = "{output}"

    tztime la {
        format = "LA %H:%M"
        timezone = "America/Los_Angeles"

    tztime ny {
        format = "NY %H:%M"
        timezone = "America/New_York"

    tztime du {
        format = "DU %H:%M"
        timezone = "Asia/Dubai"

Writing new modules for py3status

Learn how to write (and contribute please!) your own modules!