Custom widgets

Description #

Custom widgets let you run any executable script and display its output in the bar. The output format is derived from and inspired by the xbar plugin API. Any script that produces valid xbar-compatible output will work in a-bar without modification.

A script runs periodically, writes to standard output, and a-bar parses the result into bar text and an optional dropdown menu. This means you can write plugins in any language: bash, Python, Ruby, Node.js, Swift, or anything else that can print to stdout.

How the output is parsed #

The output of your script is split into two sections by the first --- line.

  • Lines before --- are called header lines. They cycle in the bar one at a time, rotating according to the widget's Cycle Duration setting.
  • Lines after --- appear in a native dropdown menu when the widget is clicked.
  • If there is no --- line, all output lines cycle as header lines and no dropdown is shown.

Any line that consists of exactly --- and nothing else acts as a separator:

  • The first --- in the output marks the boundary between header lines and menu items.
  • Any subsequent --- line inside the menu section inserts a visual separator between menu items.

Empty lines are ignored.

Parameters #

Each line can carry optional parameters by appending a pipe character | followed by key=value pairs, separated by additional pipes.

Text to display | param1=value1 | param2=value2

Parameter names and values are trimmed of surrounding whitespace. Values may be wrapped in single or double quotes. The pipe-splitting respects quoted strings, so a value containing a pipe character can be quoted safely.

The following parameters are supported.

Visual parameters #

Parameter Type Default Description
color string inherited Text color. Accepts named colors (red, blue, green, orange, purple, cyan, cadetblue, etc.), hex values (#RGB, #RRGGBB, #RRGGBBAA), and rgb() / rgba() functions.
font string bar font Font name to use for this item's text.
size number bar font size Font size in points.
length integer none Truncate the title to this many characters and append .... The full text is shown in a tooltip.
trim true/false true Whether to strip leading and trailing whitespace from the title.
image base64 string none Attach an image to the menu item. The value must be the image data encoded as a base64 string. Displayed at 16x16 points.
templateImage base64 string none Same as image but the image is treated as a template, meaning macOS renders it in the appropriate color for the current menu appearance. Recommended for icons that should respect dark/light mode.

Interaction parameters #

Parameter Type Default Description
href URL string none Open this URL in the default browser when the item is clicked. Accepts https://, http://, and custom URL schemes.
shell path string none Path to an executable to run when the item is clicked, e.g. /bin/bash.
param1 ... paramN string none Arguments passed to the shell executable in order. Use param1, param2, param3, etc.
terminal true/false true When shell is set, controls whether the script runs inside a visible terminal window. Set to false to run silently in the background.
refresh true/false false Re-run the widget script after the action (shell command or href) completes.
disabled true/false false Grey out the item and make it non-interactive. Useful for section labels or static information.
alternate true/false false Mark this item as an alternate to the previous one. While the Option key is held, this item replaces the previous one in the dropdown.
key shortcut string none Assign a keyboard shortcut to the menu item. See the Key shortcuts section below.
dropdown true/false true When set to false, this header line is excluded from the dropdown entirely and only cycles in the bar.

Key shortcuts #

The key parameter accepts a combination of modifier names and a key character joined by +.

Supported modifier names: CmdOrCtrl, OptionOrAlt, shift, ctrl, super.

Supported special key names: return, escape, tab, space, plus, up, down, f1 through f12.

Examples:

Open settings | key=CmdOrCtrl+,
Quit | key=CmdOrCtrl+q
Submit | key=shift+return

Inside the dropdown menu section, lines that start with -- (two dashes) are placed one level deeper as submenu items. Each additional pair of dashes adds one more level of nesting.

Top-level item
--First submenu item
--Second submenu item
----Nested inside second submenu

Submenu nesting only applies to lines in the menu section (after ---). Dashes at the start of a header line are treated as literal text.

Submenus support all the same parameters as top-level items.

Widget settings #

Custom widget options are configured in the Custom tab in Settings.

  • Name: Display name. Must be unique because it is used as the target for AppleScript commands.
  • Command: The shell command or script path to run. The output is interpreted as xbar-compatible markup.
  • Refresh interval: How often to re-run the script in seconds. Default is 60.
  • Cycle duration: How long each header line is shown before rotating to the next one, in seconds. Only relevant when the script produces more than one header line. Default is 4.
  • Background color: Optional background color for the widget pill. Accepts theme color names (main, mainAlt, minor, accent, red, green, yellow, orange, blue, magenta, cyan) or any CSS color string.
  • Active: Whether the widget is currently visible in the bar.
  • Hide when empty: Hide the widget entirely if the script produces no output.

Writing a script #

Any executable that prints to standard output will work. The recommended approach is to use a shebang line so the script is self-contained.

#!/usr/bin/env bash
echo "Hello"

Set the Command field to the full path of the script:

/Users/you/scripts/hello.sh

Or invoke the interpreter directly if the script is not executable:

bash /Users/you/scripts/hello.sh

If your script depends on tools installed by Homebrew or other package managers, add their directories to PATH explicitly, because a-bar does not source your shell profile:

#!/usr/bin/env bash
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
brew services list | grep running | wc -l | xargs echo "Homebrew services:"

a-bar passes the following environment variable to every script:

Variable Value
PATH Inherits the app PATH, prepended with /usr/local/bin and /opt/homebrew/bin.

Interactions #

  • Click a widget that has a dropdown to open the native menu.
  • Click a menu item that has href= to open the URL.
  • Click a menu item that has shell= to run the command.
  • Items with refresh=true will re-run the script after the action completes.
  • Widgets can be refreshed, toggled, hidden, or shown via AppleScript. See the Automation page.

AppleScript #

Custom widgets respond to the same AppleScript commands as other widgets. Use the widget's Name as the target.

Refresh a specific widget:

tell application "a-bar" to refresh "My Widget"

Toggle a widget:

tell application "a-bar" to toggle "My Widget"

Show or hide a widget:

tell application "a-bar" to show "My Widget"
tell application "a-bar" to hide "My Widget"

Example: World Clock #

The following script demonstrates header line cycling, color-coded items, submenus, a clipboard action, and a manual refresh item.

#!/usr/bin/env bash

ZONES=(
  "America/New_York:New York"
  "Europe/London:London"
  "Europe/Paris:Paris"
  "Asia/Tokyo:Tokyo"
  "Australia/Sydney:Sydney"
)

# Header lines -- one per timezone, cycled in the bar
for entry in "${ZONES[@]}"; do
  tz="${entry%%:*}"
  city="${entry##*:}"
  time=$(TZ="$tz" date "+%H:%M")
  echo "$city $time"
done

echo "---"

echo "World Clock | disabled=true color=#888888"
echo "---"

for entry in "${ZONES[@]}"; do
  tz="${entry%%:*}"
  city="${entry##*:}"
  time=$(TZ="$tz" date "+%H:%M")
  day=$(TZ="$tz" date "+%a %d %b")
  offset=$(TZ="$tz" date "+%Z (UTC%z)")
  hour=$(TZ="$tz" date "+%H")

  if [ "$hour" -ge 9 ] && [ "$hour" -lt 18 ]; then
    color="#4CAF50"
  elif [ "$hour" -ge 18 ] && [ "$hour" -lt 22 ]; then
    color="#FF9800"
  else
    color="#5C6BC0"
  fi

  echo "$city $time | color=$color"
  echo "--$day | disabled=true"
  echo "--$offset | disabled=true"
  echo "--Copy to clipboard | shell=/bin/bash param1=-c param2=\"echo -n '${city}: ${time}' | pbcopy\" terminal=false refresh=false"

  echo "---"
done

echo "---"
echo "Refresh | key=CmdOrCtrl+R | refresh=true"

Settings for this widget: Refresh interval 60, Cycle duration 4.

Something is wrong in this documentation? Please open an issue on GitHub in a-bar repo.
Toggle documentation menu