← all projects

sidewing

A xbar / bitbar compatible GTK4 desktop bar
repo bitbar elementaryos gtk4 menubar scripting wingpanel xbar MIT

Sidewing

Sidewing is a GTK4 desktop bar for elementary OS-style multi-monitor setups. It runs local executable plugins, parses xbar-style output, and renders the result in a slim bar window on a selected display.

Current target:

Sidewing discovers and runs plugins, schedules refreshes from xbar-style filenames, renders a translucent bar, and opens per-plugin popover menus with a built-in variables editor. See Current Limitations for scope boundaries.

image

What It Does

Current Limitations

The implementation is narrower than the long-term spec.

Install

Prebuilt artifacts are attached to each GitHub Release.

elementary OS / Ubuntu / Debian

Download the latest .deb and install it (apt resolves the runtime libs):

sudo apt install ./sidewing_*.deb

Other Linux (Flatpak)

Download sidewing.flatpak and run:

flatpak install --user sidewing.flatpak
flatpak run com.vandragt.sidewing

The Flatpak uses --filesystem=host and --share=network so plugin scripts can read host files and reach the network — Sidewing's plugin model is incompatible with a strict sandbox.

From source

See Build Requirements and Build below.

Build Requirements

You need:

On Debian/Ubuntu-based systems that usually means packages along these lines:

sudo apt install meson ninja-build valac libgtk-4-dev libgee-0.8-dev libx11-dev

If gtk4-x11 is packaged separately on your distro, install that too.

Build

meson setup build
meson compile -C build

Run

./build/src/sidewing

The app stores its state under:

On first launch, Sidewing copies the example plugins from examples/plugins into the user plugins directory if that directory is empty.

From the bar app menu you can:

Each plugin's own popover ends with a footer containing a Refresh button and, when the plugin declares variables, an Edit Variables… button that opens a generated form (see Plugin Variables).

On X11, Sidewing also detects whether the selected monitor currently has a maximized window. That state is checked when the bar appears and then polled periodically so the bar can switch between its translucent and opaque styles as window state changes.

Plugin Naming

Plugins must be executable files whose filenames encode the refresh interval:

name.10s.sh
name.5m.py
name.1h.rb
name.1d.sh

Supported interval suffixes:

If the filename does not match that pattern, the file is ignored.

Plugin Output

Sidewing follows the xbar text protocol loosely.

Basic structure:

Visible title
---
Menu item
Another item | href=https://example.com
Refresh now | refresh=true
Disabled item | disabled=true
--Indented child

Current behavior:

Currently recognized metadata:

Environment variables set for plugins:

This renamed the older STABA_* variables. Existing plugins that read those names need to be updated.

Plugins run with their own directory as the current working directory.

Plugin Variables

Sidewing supports xbar-style variable metadata in plugin comments:

# <xbar.var>string(VAR_NAME="Sidewing"): Display name.</xbar.var>
# <xbar.var>number(VAR_COUNT=3): Number of rows.</xbar.var>
# <xbar.var>boolean(VAR_VERBOSE=false): Show extra detail?</xbar.var>
# <xbar.var>select(VAR_STYLE="normal"): Style preset. [compact, normal, loud]</xbar.var>

When a plugin with variables is discovered, Sidewing creates a sidecar file next to it:

plugin.1m.sh.vars.json

That JSON file stores the current values and Sidewing exports them as environment variables before each plugin run.

Each plugin popover footer includes a Refresh button. Plugins that declare any <xbar.var> metadata also get an Edit Variables… button that opens a generated form: text fields for string and number, a switch for boolean, a dropdown for select. Variables whose name contains TOKEN, SECRET, PASSWORD, or API_KEY are masked. Saving writes the sidecar JSON and refreshes the plugin so the new values take effect immediately. The sidecar can still be edited by hand if preferred.

Examples

Bundled examples live in examples/plugins:

The GitHub example requires the gh CLI and an authenticated session.

Project Layout

src/
  application.vala
  bar-window.vala
  monitor-manager.vala
  plugin-manager.vala
  plugin-runner.vala
  xbar-parser.vala
  menu-builder.vala
  action-dispatcher.vala
examples/plugins/
docs/

Status

Related design and planning docs: