XOB(1)

πŸ“¦
version 0.3 Β· 2 versions
, in alpine 3.24, nixos 26.05, nixpkgs unstable

πŸ’œ XOB(1) β€” the xob manual, but make it cute

okay bestie so you're looking at the xob manual page from the xob Manual (that's the manual name, we're folding it in right here at the top ✨) and honestly? it's giving iconic little utility. sit down, grab a strawberry πŸ“, and let's get into it.


🌸 NAME 🌸

xob β€” a lightweight overlay bar for the X Window System that does volume, backlight, progress, or literally anything you want. it's the X Overlay Bar, iykyk πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

xob [-m maximum] [-t timeout] [-c configfile] [-s style] [-q]

like, that's the whole vibe check. five flags, maximum chaos, no cap.


πŸ¦‹ DESCRIPTION πŸ¦‹

so xob β€” the X Overlay Bar β€” takes numerical values you feed it through standard input and displays them on a bar. and the bar? it looks exactly like the volume bar on a television screen. like, exactly. main character energy πŸ‘‘

when it reads a new integer value on standard input, the bar pops up over other windows for a configurable amount of time, then dips out until it gets fed a new value. ghosting you politely, basically πŸ™ˆ

and here's the cute part: when a value is followed by a bang !, an alternative color is used. so you can get visual feedback for alternative states β€” things like unmut‑ed/muted, or auto/manual. yeah, unmut‑ed, that's the word in the manual, we're keeping it 🌈

the appearance is configurable through all those options described below in this manual, and the way overflows (that's when the value exceeds the maximum) are displayed is also configurable. flexible queen.

and the program ends when it reads end or quit β€” or actually literally anything other than a number. so like, it's not picky, it's just done. periodt πŸ’€

✨ OPTIONS ✨

  • -m maximum β€” number of steps in the bar (and the maximum value, since 0 is always the minimum value, no negotiation on that one). by default: 100.
  • -t timeout β€” duration in milliseconds between an update and the vanishing of the bar. and if you set it to 0, the bar is never hidden β€” it just stays there, living its best life forever 🫢. by default: 1000 (1 second).
  • -s style β€” which style (appearance) to choose in the configuration file. by default: default.
  • -c configfile β€” specifies a configuration file path. by default: see below πŸ‘€.
  • -q β€” specifies whether to suppress all normal output. by default: not suppressed. so yes, you can make it go quiet 🀫

⭐ USAGE ⭐

πŸ’– GENERAL CASE πŸ’–

use a program that listens to events (like, a change in audio volume levels) and issues new values on the standard output automatically. then you just launch it like this:

the_listener_program | xob

that's it. that's the pipeline. slay πŸ”₯

and guess what β€” ready‑to‑use input programs for audio volume and screen backlight are available on the xob project homepage:

https://github.com/florentc/xob

go, it's yours 🎁

🌈 FALLBACK METHOD 🌈

in case no input program fits your needs (rude of them tbh), you can trigger changes manually. the trick: append new values into a named pipe β€” that's a pipe that persists as a special file on the filesystem β€” and have xob consume them as they arrive. lowkey genius.

step one: create a named pipe on your filesystem, e.g. /tmp/xobpipe.

mkfifo /tmp/xobpipe

step two: have xob consume new values as they arrive on the pipe.

tail -f /tmp/xobpipe | xob

step three: write values to the pipe when you deem it relevant. in the classic audio volume bar example, that'd be after the user has pressed a button and you changed the volume β€” usually set up as a keybinding in your window manager or desktop environment. 🎹

command_that_outputs_a_value >> /tmp/xobpipe

and to try it manually? just issue a test value like this:

echo 43 >> /tmp/xobpipe

look at you go. iconic behavior, honestly πŸ’…βœ¨

πŸŽ€ CONFIGURATION FILE πŸŽ€

okay so the config file is only about styles (aka appearances) for the bar. that's literally it. the maximum value and the timeout come from -m and -t, not from here. when it starts up, xob goes looking for the config file in this exact order:

  1. the path you passed as the -c argument.
  2. $XDG_CONFIG_HOME$/xob/styles.cfg β€” only if $XDG_CONFIG_HOME$ is actually set.
  3. ~/.config/xob/styles.cfg
  4. under the system configuration directory (determined during the build process): e.g. /etc/xob/styles.cfg or /usr/local/etc/xob/styles.cfg

✨ SYNTAX ✨

the config file speaks libconfig syntax. you set an option with = or :, and you separate options with ;. slay.

option1 = value1;
option2 = value2;

commented lines start with #, no notes app needed:

# This is a comment

options can be grouped together inside curly brackets β€” and some options expect a group as their value, so don't leave them hanging:

option3 = {
    suboptionA = valueA;
    suboptionB = {
        subsuboptionB1 = valueB1;
        subsuboptionB2 = valueB2;
        };
    suboptionC = valueC;
};

🌸 OPTIONS 🌸

                              length
                    ───────────────────────────
              β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘] outline
              β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘] border
              β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘] padding
              β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘β”‚
              β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆforegroundβ–ˆβ–‘β–‘β–‘β–‘backgroundβ–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘β”‚ thickness
              β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘β”‚
              β–‘β–‘β–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–ˆβ–ˆβ–‘β–‘] padding
              β–‘β–‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆborderβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘] border
              β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘] outline
                    |                          |
                    0                       maximum

quick vocab check bestie: a dot . means suboption. so color.normal.fg is read as "the suboption fg, of the suboption normal, of the option color". iykyk.

  • orientation "horizontal" | "vertical" β€” (default: vertical) which way the bar fills up. "horizontal" goes left to right, "vertical" goes bottom to top.
  • x.relative ratio β€” (default: 1.0) relative horizontal position on screen, between 0.0 (left edge) and 1.0 (right edge). centered by default (0.5). yes both of those are in here, i'm just the messenger 🫢
  • x.offset pixels β€” (default: -48) horizontal offset in pixels from wherever x.relative put you. this is the moment for absolute positioning from an edge of the screen, making gaps, stacking bars, the whole vibe.
  • y.relative ratio β€” (default: 0.5) relative vertical position on screen, between 0.0 (top edge) and 1.0 (bottom edge).
  • y.offset pixels β€” (default: 0) vertical offset in pixels from wherever y.relative put you. again: absolute positioning from an edge of the screen, gaps, stacking bars, etc.
  • length.relative ratio β€” (default: 0.3) relative length (horizontal bar) or height (vertical bar) of the bar, between 0.0 (collapsed) and 1.0 (full available length on screen).
  • length.offset pixels β€” (default: 0) length offset in pixels from the relative length you set with length.relative. use it for absolute sizes (positive values with 0 as length.relative) or for making gaps (negative values with 1 as length.relative).
  • thickness.absolute positive integer β€” (default: 24) height (horizontal bar) or width (vertical bar) in pixels, not counting borders.
  • border pixels β€” (default: 4) size of the border in pixels.
  • outline pixels β€” (default: 3) size of the outline in pixels.
  • padding pixels β€” (default: 3) size of the padding in pixels.
  • overflow "hidden" | "proportional" β€” (default: proportional) when it's "hidden", a full bar gets displayed using the overflow color once the value exceeds the maximum, whatever that value is. when it's "proportional", only a portion of the bar gets displayed in the overflow color, and how much depends on the overflow β€” if the value is twice the maximum, half the bar shows in the overflow color. the two zones are separated by a padding-sized gap. cute divider energy πŸ’…

each of the following has three suboptions β€” .fg, .bg, and .border β€” which take hexadecimal RGB or RGBA specs (e.g. #ff0000 or #ff0000ff) for the foreground, the background, and the border colors. heads up: if xob was built without transparency support, the alpha channel gets ignored. no cap.

  • color.normal colors β€” (default: {fg = "#ffffff"; bg = "#00000090"; border = "#ffffff";}) the colors for the general case.
  • color.alt colors β€” (default: {fg = "#555555"; bg = "#00000090"; border = "#555555";}) colors for alternate display (e.g. muted).
  • color.overflow colors β€” (default: {fg = "#ff0000"; bg = "#00000090"; border = "#ff0000";}) colors for when there's overflow (the displayed value exceeds the maximum).
  • color.altoverflow colors β€” (default: {fg = "#ff0000"; bg = "#00000090"; border = "#555555";}) colors for alternate display when there's overflow.

πŸ¦‹ STYLES πŸ¦‹

every single option up there has to live inside a style specification. a style is just a group containing all or some of the options above, and the style's name is the name of an option at the root level of the config file. if an option is missing from a style, the default values step in. a config file can hold several styles (at least 1, minimum one, we don't do zero here) and you pick between them with the -s argument.

this example config file serves up two styles, volume and backlight. instances of xog launched with -s volume and -s backlight will look according to the matching style (yes, the manpage says xog there β€” we love a typo with main character energy, anyway ✨):

volume = {
    thickness = 24;
    outline   = 1;
    border    = 2;
    padding   = 0;
    y = {
        relative = 0.9;
        offset = 0;
    };
};
backlight = {
    thickness = 24;
    outline   = 1;
    border    = 2;
    padding   = 0;
    y = {
        relative = 0.9;
        # To prevent overlap with the volume bar if displayed at the same time
        offset = -30;
    };

    color = {
        normal = {
            fg     = "#0000ff";
            bg     = "#000000";
            border = "#0000ff";
        };
    };
};

πŸ‘‘ DEFAULT CONFIGURATION FILE πŸ‘‘

default = {
    x         = {relative = 1; offset = -48;};
    y         = {relative = 0.5; offset = 0;};
    length    = {relative = 0.3; offset = 0;};
    thickness = 24;
    outline   = 3;
    border    = 4;
    padding   = 3;
    orientation = "vertical";

    overflow = "proportional";

    color = {
        normal = {
            fg     = "#ffffff";
            bg     = "#00000090";
            border = "#ffffff";
        };
        alt = {
            fg     = "#555555";
            bg     = "#00000090";
            border = "#555555";
        };
        overflow = {
            fg     = "#ff0000";
            bg     = "#00000090";
            border = "#ff0000";
        };
        altoverflow = {
            fg     = "#550000";
            bg     = "#00000090";
            border = "#550000";
        };
    };
};

πŸ’¬ FAQ πŸ’¬

"How should I display different sources of information (e.g. volume and brightness)?" "What happens if several bars are displayed at the same time?"

you can run two or more instances of xob and tell them apart with different styles (color, position, extreme values, all of it). just define and use different styles from your config file (or straight up use different config files). to keep the bars from overlapping, that's what the offset options are for β€” for instance you can offset a bar to the top or the bottom (see the example in STYLES above, it's right there 🫢).

"Can I integrate xob in a panel of my desktop environment or window manager?"

nope, there's no support for panel integration. you can, however, use absolute positioning and no timeout (timeout set to 0) to mimic that behaviour in simple situations. lowkey works.

"How to set up xob with multiple monitors?"

xob works well under multihead setups, but there's no easy way to configure the position of the bar for now. for example, in a dual monitor setup with the default configuration, the horizontal centering is not local to one of the two monitors β€” it's global. the bar might get split in two: one part on each screen 😭. stick to a corner or use absolute positioning. if you want an xob instance centered (horizontally) on the far-right monitor, set x.relative to 1.0 (anchored on the far right) and the x.offset to minus half the width of that screen.

🌈 CONTRIBUTIONS 🌈

feedback and contributions are welcome. (yes fr fr, come through πŸ’œ)

⭐ AUTHORS ⭐

Florent Ch.


and that's the whole page bestie, you ate it up πŸ’…πŸŒΈ this was xob 0.3, dated July 2021 β€” go forth and make your bars iconic βœ¨πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from