Taffybar: a GTK status bar for XMonad that you compile like a window manager
A gtk based status bar for tiling window managers such as XMonad
At a glance
- What is it?
- Taffybar is a desktop information bar for tiling window managers, written in Haskell on top of GTK 3, that you configure by compiling your own executable rather than by editing a config file, with a growing set of widgets and a partial Wayland story through gtk-layer-shell. It suits a Haskell user who wants a bar with GTK polish, and it is a library in the window manager sense, not a program you install and configure.
- Who is it for?
- Taffybar fits a Haskell user on X11 who wants a status bar with GTK widgets rather than the leaner text output of xmobar, and it does not fit someone who wants a bar they can configure by editing a file or a UI, because the configuration is a Haskell program you compile.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Haskell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A bar you compile, not a bar you configure
Taffybar is a desktop information bar, intended primarily for use with XMonad, though it can also function alongside other EWMH compliant window managers. The README places it in relation to xmobar directly: it is similar in spirit, but it differs in that it gives up some simplicity for a reasonable helping of GTK 3 eye candy.
That trade is the whole design. xmobar is a small program you install and configure from a text file. Taffybar is a Haskell library, and the README draws the analogy explicitly: as with window managers like XMonad and dwm, Taffybar is most appropriately described as a library that allows you to build an executable that is customized to your tastes. Like xmobar and XMonad, Taffybar is configured in Haskell.
The practical consequence is stated without ambiguity. Taffybar has a reasonably useful default configuration built in. To use a different configuration, however, you must install a Haskell compiler that can compile your taffybar.hs source file.
So there are two usage modes and they are quite different in effort. The default configuration is a ready-made executable you can install from packages and run. Anything beyond it means you write Haskell, compile it with GHC, and deal with the Haskell toolchain as part of maintaining your desktop configuration. That is a real cost, and it is the price of the GTK widgets.
The project is BSD-3-Clause licensed, the default branch is master, and the last push was on 2026-10-20 with the release v7.4.4 published the same day, after v7.4.3 on 2026-10-17 and v7.4.2 on 2026-10-09.
Wayland support that is real but partial
Taffybar also supports running under Wayland via gtk-layer-shell, and the README is careful about the limits of that support. Wayland support is currently compositor-specific for some widgets, with Hyprland workspaces, windows and layout widgets available. Many widgets still rely on X11/EWMH, so the guidance is to check the widget docs and examples, including example/taffybar-wayland.hs, for what works on your setup.
That is an unusually honest paragraph, and it describes the actual state of any X11 project moving to Wayland. A status bar is a special case because it is a shell surface that has to reserve space, and the mechanism for that differs between compositors. The widgets that report window titles, workspaces and layout state are the ones that depend on the EWMH protocol, which is an X11 protocol, and under Wayland they depend on a compositor-specific equivalent instead.
The repository contents support the claim. There is a nix directory and a flake.nix with a flake.lock, and a nix.yml build workflow badge in the README, so the Nix path is the one the project itself exercises. The example directory holds example/taffybar-wayland.hs alongside example/taffybar.hs, example/xmonad.hs, a default.nix, a my-taffybar.cabal and a stack.yaml, which is a set of starting points for the different ways someone might run it rather than a single canonical configuration.
The top level also has a cabal.project and a cabal.project.dev, a stack.yaml with a stack.yaml.lock, an hie.yaml, a taffybar.cabal and a taffybar.css. The build metadata and the stylesheet sit side by side, and the stylesheet is worth noting because it is where the GTK 3 look that distinguishes Taffybar from xmobar is actually adjusted, rather than being themed in the configuration language.
Nine packages, and a widget list that is the real API
The README carries a package release status table, and it is the clearest picture of how the project is organised.
The root taffybar package is one of nine. The others are dbus-hslogger, dbus-menu, gi-wireplumber, gtk-scaling-image, gtk-sni-tray, gtk-strut, status-notifier-item and xdg-desktop-entry. Every one of them is published on Hackage with its own badge and its own unreleased commits count.
The split is not arbitrary and each name tells you what the package is for. dbus-hslogger and dbus-menu are the D-Bus plumbing, the logging and the menu protocol. gi-wireplumber is the PipeWire integration, which is what makes the system tray work under modern desktops. gtk-sni-tray and status-notifier-item are the StatusNotifierItem protocol implementation, the freedesktop standard for tray icons, and they are separate packages so other programs can use them without pulling in the whole bar. gtk-scaling-image handles images that need to scale, gtk-strut handles the reserved screen edge that a panel requires so that maximised windows do not overlap it, and xdg-desktop-entry generates the desktop entry file.
The status table also documents a detail that would otherwise be confusing. The unreleased commit badges are path-scoped to each package directory, and the root taffybar badge counts non-packages/ changes. So the repository is a monorepo with several independently published libraries, and the badge table exists so a user can tell whether the component they depend on has moved since its last Hackage release.
The functional interface is the widget list rather than a command line, and the README points to it: you select from the list of available widgets for functionality to add to your Taffybar. If the widget you need doesn't exist, then you create your own with GTK.
The example directory is the documentation
For a project whose configuration is code, the examples are where a new user should start, and the repository is built around that.
The example directory contains taffybar.hs, which is the configuration file the README tells you to compile, plus xmonad.hs, which is a variant intended to be run alongside XMonad rather than as a standalone bar, and taffybar-wayland.hs for the Wayland case. There is also a default.nix, a my-taffybar.cabal and a stack.yaml, so the examples are wired for both Nix and Stack workflows and include a package file for someone who wants to build their configuration as its own executable.
The my-taffybar.cabal file is the interesting one for anyone planning to use Taffybar seriously. It is the pattern for treating your bar configuration as a separate package with its own dependency set, so that rebuilding the bar does not force a rebuild of the rest of your Haskell tooling, and so that a broken change to the bar does not take the whole desktop down with it. The README's framing of Taffybar as a library rather than an application is what makes that pattern natural.
The example/taffybar.hs file is the one to copy. The list of available widgets is published in the Haddock documentation under System-Taffybar-Widget, which is the API reference for everything the bar can display, and it is where you find out what exists before writing any configuration at all.
The repository also carries a doc directory with a screenshot, a CHANGELOG.md, an INSTALL file, a CONTRIBUTING file, a CODE_OF_CONDUCT.md, an AGENTS.md, a .envrc for direnv, a .stan.toml, a weeder.toml, a dbus-xml directory, an icons directory, an app directory, src, packages and test. The weeder.toml is a Haskell-specific tool for finding unused code, which is a small sign of how seriously the project treats its own hygiene.
Installing it, and what the INSTALL file is for
The installation documentation is not reproduced in the README, which lists Installation as a documentation link and states that Taffybar can be installed from Linux distribution packages, or compiled f. The README truncates there, so the details live in the INSTALL file at the top of the repository and on the documentation site, and that is the place to look rather than inferring a build recipe from this page.
The distribution package route is the one that suits the default configuration, and the badges in the README show the three channels the project supports beyond that: Hackage for the library itself, a Stackage LTS badge and a Stackage Nightly badge, and a Nix build workflow badge. The Nix path is the one the project develops against, with flake.nix and flake.lock in the repository root, and there is an .envrc so that direnv enters the development environment automatically.
For the compile-your-own route, the requirements in the README are explicit and minimal: a Haskell compiler, GHC, that can compile your taffybar.hs source file. The example directory supplies the cabal file and the stack.yaml so you have a build definition to start from, and the nix directory plus flake.nix give you the fully pinned alternative.
One thing the documentation does not spell out in the README is the GTK 3 dependency and what it means at runtime. Taffybar links against GTK 3, and a status bar is a GTK application, so the bar and the desktop need compatible GTK libraries present. That is a normal consequence of choosing eye candy over simplicity, and it is the main operational difference from a bar written directly against X11 drawing.
Against xmobar, and against the bar your window manager already provides
The comparison the project itself invites is with xmobar, and the README frames it in terms of what each side gives up.
xmobar gives up simplicity for nothing in return, in the sense that it stays a text bar and a configuration file. Taffybar gives up some simplicity for a reasonable helping of GTK 3 eye candy, which means real GTK widgets, themed through a stylesheet, and the ability to write your own widget when the list does not contain what you need.
That is a coherent position for a specific user. A Haskell user running XMonad who wants a clock, a system tray, a workspace indicator and a window list, and who wants them to look like the rest of a GTK desktop rather than like a text console, gets something here that xmobar will not give. The cost is the Haskell toolchain, the compile step, and the fact that a mistake in your bar configuration is a compile error rather than a runtime one.
The third option, which the README does not discuss, is the bar your window manager already provides. XMonad has its own layouts including a status bar, and dwm has its own tag bar. Those are the fastest route to something working, they are configured in the same Haskell you already maintain for the window manager, and they are one fewer separate process to manage. What they do not give you is the widget ecosystem, which is the entire point of Taffybar.
So the choice is not really bar against bar. It is whether you want a single static bar tied to your window manager, a text bar with a config file, or a GTK application you compile. Taffybar wins the third category, loses the first on simplicity, and loses the second on effort. The Wayland story is the deciding factor for anyone on a modern compositor, and on that score the README is candid that the port is partial and that Hyprland is the compositor with workspace, window and layout widgets available.
Editorial conclusion
Taffybar fits a Haskell user on X11 who wants a status bar with GTK widgets rather than the leaner text output of xmobar, and it does not fit someone who wants a bar they can configure by editing a file or a UI, because the configuration is a Haskell program you compile. Before adopting it, check the widget documentation and the example files, including example/taffybar-wayland.hs, against the compositor you run, since the README states that Wayland support is currently compositor-specific for some widgets and that many widgets still rely on X11 and EWMH.
Frequently asked questions
How do I install Taffybar?
The README states that Taffybar can be installed from Linux distribution packages or compiled, with the details in the INSTALL file at the repository root and on the documentation site. The project publishes to Hackage and Stackage, and develops against Nix, with a flake.nix and an .envrc in the repository.
Do I need Haskell to configure Taffybar?
Not for the built-in default configuration, which the README describes as reasonably useful. To use a different configuration you must install a Haskell compiler that can compile your taffybar.hs source file, and then you select from the list of available widgets.
Does Taffybar work on Wayland?
It supports running under Wayland via gtk-layer-shell, but the README says Wayland support is currently compositor-specific for some widgets, with Hyprland workspaces, windows and layout widgets available, and that many widgets still rely on X11 and EWMH. It points at the widget docs and the example/taffybar-wayland.hs file to check what works on a given setup.
What packages does the Taffybar repository publish?
The release status table lists nine: taffybar, dbus-hslogger, dbus-menu, gi-wireplumber, gtk-scaling-image, gtk-sni-tray, gtk-strut, status-notifier-item and xdg-desktop-entry, each published separately on Hackage with its own unreleased commit count.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/taffybar-taffybar)Was this useful?