Skip to content

rhsev/ticker

Repository files navigation

ticker

A LED dot-matrix ticker for the macOS menu bar, controlled from the command line. Also handles milan:// URL schemes for mi.lan.

Notifications can be overlooked. Motion catches the eye. ticker scrolls urgent messages through the menu bar, and the movement is what makes them register. The LED dot-matrix style amplifies this. There is no font pipeline: text is composed from a bitmap table, easy enough to scroll at 20 fps with negligible CPU load.

When a message arrives, the ticker appears in the menu bar and scrolls through all queued messages in sequence. Then it disappears or stays and waits for acknowledgment.

Quick example

ticker --send "HELLO WORLD!"

Transparent mode — adapts to your menu bar (default):

ticker transparent

LED mode with black background:

ticker demo

Each character is stored as six 8-bit glyph columns, five pixels wide plus one gap column, derived from the classic Adafruit GFX 5×7 bitmap font. Scrolling advances the canvas by exactly one column per tick, so the animation is pixel-smooth without any font rendering, which keeps CPU load very low. The same bitmap font drives the display and the custom glyph system. Like a real LED matrix display.

For a technical deep-dive see TECHNICAL.md.


Requirements

  • macOS 13 or later
  • Apple Silicon or Intel

Installation

Download Ticker.app from the latest release.

# Remove quarantine
xattr -dr com.apple.quarantine ~/Downloads/Ticker.app

# Move to a permanent location
mv ~/Downloads/Ticker.app ~/Applications/Ticker.app

# Open once — registers the app with macOS
open ~/Applications/Ticker.app

# Optional: symlink the CLI binary
ln -sf ~/Applications/Ticker.app/Contents/MacOS/ticker /usr/local/bin/ticker

The app runs as a menu bar accessory (no Dock icon). It creates a Unix domain socket at /tmp/menubar_ticker.sock and waits for commands.

Auto-start at login

Add Ticker.app under System Settings → General → Login Items.


Sending messages

ticker --send "HELLO WORLD"          # append to queue
ticker --urgent "IMPORTANT"          # jump to front; current message finishes
ticker --very-urgent "STOP PRESS"    # interrupt immediately; resumes after

Short aliases: -s, -u, -vu.

Standby text

Displayed instantly (no scroll), clipped to the visible width, for a fixed duration:

ticker --standby "OPEN 09:00-17:00" --duration 10
ticker --standby-urgent "CLOSING SOON" --duration 5
ticker --standby-very-urgent "EVACUATE NOW" --duration 30

Display width

ticker --width 30    # wider
ticker --width 10    # compact (minimum: 5)

Width persists until changed. Default is set in the config file.

Queue control

ticker --clear           # clear queue and stop current message
ticker --status          # query current state (JSON)
ticker --quit            # quit the app

--status returns:

{"phase":"scrolling","queue":2}

Possible phase values: idle, scrolling, sticky, standby.


Inline control codes

Control codes are embedded in the message text. They are not displayed.

Color

\c[amber]    orange-amber (default)
\c[green]    terminal green
\c[red]      red
\c[white]    white
\c[yellow]   yellow

Color applies to all following characters until the next \c[…].

ticker --send "STATUS \c[green]OK\c[amber] ALL CLEAR"
ticker --send "\c[red]ERROR \c[white]disk full on \c[yellow]backup-01"

Glyph

\g[name]     render a named custom glyph from config
ticker --send "SCORE \g[star] 9999"
ticker --send "I \g[heart] SWIFT"

Glyphs are defined in custom_chars in the config file (see below).

Pause

\p[N]          pause N seconds when this point reaches the left edge
\p[sticky]     pause until the user clicks the status item
\p[sticky:N]   pause with N blinks before waiting (e.g. \p[sticky:3])

The pause triggers when it scrolls into the leftmost visible column, so the preceding text is fully readable before the hold takes effect.

When \p[sticky:N] activates, the display blinks N times to draw attention, then holds the text until the user clicks.

Optional shell command on click

An optional shell command runs when the user clicks the sticky item:

ticker --send "BUILD FAILED \p[sticky:3]" --on-click "open -a Xcode"
ticker --send "DEPLOY DONE \p[3] RESTARTING..."

Priority rules

Flag Behaviour
--send / --standby Appended to queue
--urgent / --standby-urgent Inserted at front; current message finishes first
--very-urgent / --standby-very-urgent Interrupts immediately; interrupted message is re-queued and replayed

Context menu

Right-click the ticker to access:

  • Clear queue — discard all pending messages
  • Pause / Resume — freeze animation
  • Ticker — toggle the LED display on/off (the app keeps running)
  • Quit

Configuration

~/.config/ticker/config.json — created on first run with defaults:

{
  "tickerEnabled": true,
  "defaultColor": "amber",
  "defaultWidth": 20,
  "scrollSpeed": 0.05,
  "defaultPause": 3.0,
  "transparent": true,
  "milanPort": 8080,
  "customChars": {}
}
Key Description
tickerEnabled Show the LED display (default true). When false, messages are accepted but not displayed — the app keeps running
defaultColor LED color: amber green red white yellow
defaultWidth Visible character columns (default 20)
scrollSpeed Seconds per pixel column (default 0.05)
defaultPause Seconds to hold when the message is fully visible (default 3)
transparent true for transparent background with system text color (default true)
milanPort Milan HTTP port for milan:// URL forwarding (default 8080)
customChars Extra glyphs as 6-column bitmaps (see below)

Milan URL scheme

ticker registers the milan:// and ref:// URL schemes. When a link like milan://hello/World is opened from any app, ticker forwards it as a GET request to http://localhost:{milanPort}/hello/World on Milan. If Milan is not running, the request is silently dropped.

Custom glyphs

Glyphs are referenced by name via \g[name] in messages:

"customChars": {
  "star":  [4, 14, 31, 14, 4, 0],
  "heart": [6, 15, 30, 15, 6, 0]
}

Each value is an array of 6 column bytes (8 rows, bit 0 = top row). Column 6 is the trailing gap — use 0 for normal spacing, or non-zero to connect two glyphs seamlessly into a wider symbol: \g[left]\g[right].

To design a glyph, create a .led file — 8 rows × 6 columns, X for lit, . for dark:

..X...
.XXX..
XXXXX.
.XXX..
..X...
......
......
......

Then convert with the included tool:

bash tools/make_char.sh tools/glyphs/star.led star
# → "star": [4, 14, 31, 14, 4]

Example glyphs are in tools/glyphs/.


Building from source

# CLI binary
swift build -c release
# → .build/release/ticker

# App bundle (required for Login Items and URL scheme registration)
bash build-app.sh
# → Ticker.app

Requires Xcode Command Line Tools (xcode-select --install).

About

A LED dot-matrix ticker for the macOS menu bar, controlled from the command line, optional URL handler for mi.lan.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors