[Gubar] Swaybar Generator, Written in Guile

Hi everyone,

Recently, I’ve set up a new Guix System on a Thinkpad and I decided to migrate over to Wayland and sway after being a longtime bspwm user on X11. For a top bar/status bar on X11, I use polybar, which is similar to waybar on Wayland.

I installed waybar and tinkered with it for a few minutes, but I wasn’t too keen on fiddling with CSS and trying to emulate my polybar configuration, all while wrangling and learning Guix to make it usable for me.

Once I remembered (from my i3 days) that there is a swaybar protocol (see i3blocks) I decided that I would take a more interesting approach and write my own version of a swaybar generator using Guile Scheme – Gubar (pronounced “goober” and named by @daviwil)

High-level design overview

After looking at the swaybar-protocol spec, I realized that I would need guile-json for serializing updated bar components (blocks), and also for deserializing click events that are captured by sway and dumped on stdin of the swaybar command (in this case, gubar).

The bare minimum bar usually sleeps for one second and then runs one or more shell command and parses the outputs into a nice long string, but that becomes quite inefficient if you have many blocks or a command that can take a bit longer to run. You could instead sleep for one minute, but then you don’t get instant updates on things like volume, cpu, battery, etc – IF those things are important to you.

I thought it would be more appropriate to use fibers and have one fiber per block. The fibers are kinda like greenthreads or goroutines, but based on “Concurrent ML”. Andy Wingo has a really nice write-up on it in the fibers manual.

With this design, I can sleep each block for different amounts of time, having them run asynchronously, and then message back to the main scheduler when they update so we know when to output the fresh set of blocks.

Configuration

Unlike i3blocks, I want gubar to be configured fully in Guile. Right now, it just calls load on the config.scm file, which I’m not entirely sure is correct, but it works well enough. This way made sense to me since it’s as if the config is just another module, that may or may not be present. If you have tips on this, I’d love to know!

I really like the ergonomics of the syntax that Guix uses for defining system or home configs. They have a custom record type that is, in my opinion, more robust than srfi-9 records. I don’t want to depend on Guix or copy paste out the definition, so right now the configuration is a bit clunky. If you have any ideas or would like to help make it more comfortable, I’m open to suggestions and collaboration.

Simple DateTime Block

As an example, here is a module for displaying the current time:

DateTime block code

link to src

(define-module (gubar blocks date-time)
  #:use-module (gubar gublock)
  #:use-module (gubar swaybar-protocol)
  #:use-module (ice-9 textual-ports)
  #:export (date-time))

(define* (date-time #:key (format "%c") (interval 1))
  "Creates a new date-time gublock."
  (gublock
   #:interval interval
   #:procedure
   (lambda (block)
     (scm->block
      `(("full_text" .
         ,(strftime format (localtime (current-time)))))))))

Due to guile-json not exposing modifiers on the generated srfi-9 record types, I opted to use an assoc-list and then convert it to the record type (scm->block). Eventually, I will have to implement the functional modifiers manually to avoid this.

Checkout the other modules for some (slightly) more interesting examples. I am slowly hacking on the ones that I will be using in my daily driver config.

Screenshot

It’s just the regular swaybar with some nerd font icons, but here’s a screenshot with the config:

Still needs a lot of work, but it’s getting there!

Happy Hacking!

9 Likes

This looks fantastic, huge potential! I’ll bump it on the stream this Friday.

1 Like

I agree with @daviwil @trev it does look fantastic. And it’s written in guile scheme. Great effort and excellent idea. I have forked your repo and hope I can contribute.

Just brilliant.

1 Like

That looks great, kudos for doing it in guile scheme! Went a different route myself by using my emacs modeline as a status_command for a STDIN-based status bar and writing a minor mode to keep it updated → theesm/modeline-statuscommand.el - Codeberg.org, but using guile to do so definitely is a lovely and cool thing!

Do you have any plans on using NetworkManagers dbus interface instead of nmcli to obtain network information? Am currently working on a minor mode in emacs displaying these things using elisps dbus functions (which is quite fiddly); and as guile has Gwen Weinholt / AC⚡D-Bus · GitLab that could be a good thing to dive into^^

1 Like

Seems cool! Definitely seems comfy to have everything on the emacs statusline.

I haven’t looked into NetworkManager and dbus yet. Was hoping to keep all the commands as simple as possible.

Hi SystemCrafters community!

Following up on @trev’s original gubar project, I wanted to share the progress we’ve made and invite the community to join in developing this excellent Guile-based status bar generator.

What is Gubar?

For those new to the project, gubar is a status bar generator for Sway written in Guile Scheme. It provides a hackable, scheme-based alternative to tools like i3blocks or waybar. What makes it special is its use of Guile’s powerful features:

  • Fiber-based concurrency for efficient block updates
  • Full Scheme configuration for ultimate customization
  • Native integration with system services
  • Real-time interactive blocks

Recent Improvements

Since the original release, we’ve added several enhancements:

  1. Robust Error Handling

    • Graceful recovery from block failures
    • Detailed error reporting for debugging
    • Better user feedback for configuration issues
  2. System Resource Monitoring

    • CPU usage and temperature
    • Memory utilization
    • Disk space monitoring
    • GPU temperature tracking
  3. Basic Audio Display

    • PipeWire volume display
    • Basic volume status monitoring
  4. Network Status

    • Basic network status display
    • WiFi connection indicator

Why Join the Project?

Gubar has been an incredible learning platform for:

  1. Guile Scheme Programming

    • Practical experience with Scheme in a real-world application
    • Understanding functional programming patterns
    • Working with Guile’s concurrency model (fibers)
  2. Systems Integration

    • Interfacing with system services
    • Real-time monitoring and reporting
    • Event handling and user interaction
  3. Linux Desktop Environment

    • Understanding Wayland/Sway architecture
    • Status bar protocol implementation
    • System resource management

Future Directions

We have several exciting areas for improvement:

  1. Configuration Ergonomics

    • Developing a more intuitive configuration DSL
    • Creating block templates for common use cases
    • Improving error feedback
  2. Feature Expansion

    • DBus integration for better service communication
    • Additional block types for various system metrics
    • Custom theming support
    • Interactive volume control with mute toggle
    • Advanced network management integration
    • Connection quality monitoring
    • WiFi network selection
  3. Documentation and Examples

    • Comprehensive user guide
    • Block creation tutorials
    • Configuration examples

Getting Started

The project is forked at: github.com/glenneth1/gubar

Requirements:

  • Guile 3.0+
  • guile-fibers
  • guile-json
  • Sway/i3bar compatible environment

Call to Action

If you’re interested in:

  • Learning Guile Scheme in a practical context
  • Contributing to a real-world system tool
  • Improving Linux desktop integration
  • Working with system monitoring and reporting

We’d love to have you join the project! Whether you’re new to Scheme or an experienced Guiler, there are plenty of ways to contribute:

  • Code contributions
  • Documentation improvements
  • Testing and bug reports
  • Feature suggestions
  • Configuration examples

Next Steps

  1. Check out the repository
  2. Join the discussion here
  3. Try gubar in your Sway setup
  4. Share your experience and ideas

Let’s make gubar a flagship SystemCrafters project and show what’s possible with Guile Scheme in system tooling!

Happy Hacking!


Note: Special thanks to @trev for creating the original gubar project and setting such solid foundations for this work.

1 Like

Let’s make gubar a flagship SystemCrafters project and show what’s possible with Guile Scheme in system tooling!

Please take it off my hands! With David’s permission we can transfer it into SystemCrafter’s org on Github (and mirror to Codeberg)

It would be nice to submit a patch to Guix as well, once some kinks are worked out. The package definition is already written in the repo.