Axol — a cheerful desktop companion

5 min read Original article ↗

A tiny axolotl who answers your alerts. She sits in the corner of your screen, pops a speech bubble when something needs you — a CI build, a Claude permission, a GitHub mention — and waves it off when you tap.

Install Axol View on GitHub

Alerts with a face.

Any tool that can curl can pop her speech bubble. Click to jump back to the terminal, URL, or file that needs you.

A little presence.

Drags anywhere on screen. Nudges you to breathe, hydrate, stretch. Fidgets and naps when things go quiet.

Nothing heavy.

One 350 KB Swift binary. No Electron, no helpers, no telemetry. Idles at 0 % CPU and ~40 MB RAM.

Three paths to a bubble

Anything worth your attention arrives as a speech bubble above Axol — urgent ones pin open, the rest fade on their own. Three paths in: a loopback listener on your Mac, a signed cloud bridge for webhook-capable services, and keychain-backed polling for services that can't push.

local tool curl · POST axol loopback :47329 ci-bot build passed

Local

A tiny loopback listener on 127.0.0.1:47329. Any script that can curl can pop a bubble. The envelope is title + body + priority + optional actions — focus a terminal, open a URL, reveal a file. Nothing ever leaves your Mac.

webhook signed POST neuromast signed intake lateral line local forwarder axol speech bubble main CI passed

Webhook

A signed cloud intake, deployable to Cloudflare, Railway, Fly, Render, or Webflow Cloud, paired with a 60-line bash forwarder on your Mac. Drop-in handlers for GitHub, Stripe, and Sentry signatures; a generic HMAC scheme for everything else.

axol bubble gill 30s sample + keychain github /notifications Roach/axol mention: Fix the widget

Polling

For services that don't webhook — GitHub mentions and review requests, Linear assignments, your own feeds. A gill is a ~20-line bash script that reads a keychain-backed PAT, queries its upstream on a 30-second schedule, and posts each new item straight to the loopback listener. No cloud round-trip; the credential never leaves your Mac.

Claude Code, answered

Two drop-in hook scripts turn Claude Code's in-terminal permission prompts into tappable bubbles above Axol — no more alt-tabbing back to the shell every few minutes. Purely local: the hooks POST straight to the loopback listener, the neuromast isn't involved.

claude code PreToolUse axol loopback :47329 Claude needs permission Allow Deny

Permission prompts, without context-switching

The PreToolUse hook intercepts CC's in-terminal ask and POSTs straight to Axol's loopback at 127.0.0.1:47329. She renders a tappable Allow/Deny; your choice is what CC waits on. A paired Stop hook posts a git-aware summary when CC finishes a turn — the file it touched, the branch it's on, whether tests still pass.

If Axol's closed the hook returns empty so CC falls back to its own in-terminal prompt. No cloud involvement, no lateral-line, no external round-trip — the bridge is two short scripts and a local port.

Also wired for remote callers: a GitHub Actions job or Slack slash command can ask for the same Allow/Deny bubble by posting to the cloud permission API, which routes through the neuromast and lateral-line instead.

Three sizes, on tap

⌘-click her to cycle through three sizes: full → mini → micro → full. The current mode persists across launches.

full

~300×360

Default. Bubble above her head; worry bubbles for unresolved alerts.

mini

62×56 → 290×80 with a bubble

Side bubble on her left; blue count badge on her gill.

micro

48×48

Static character + count badge.

Adapters and gills

Two drop-in extension points for adding new sources without touching Axol's binary. Adapters translate shapes you don't control; gills fetch from services that can't push.

Adapters

A JSON file in ~/Library/Application Support/Axol/adapters/ teaches Axol to read a new payload shape — match rules, a tiny {{field}} template language, and a closed action vocab. No code required. Five bundled: claude-code, github-actions, sentry, stripe, generic.

axol bubble gill 30s sample + keychain github /notifications Roach/axol mention: Fix the widget

Gills

A ~20-line bash script plus a launchd job. Reads a keychain-backed PAT, queries an upstream every 30 seconds, and POSTs each new item to Axol's loopback. Named for the axolotl's feathery external gills — same rhythmic sampling. One bundled (github-notifications); adding more is one file next to lib.sh.

Install & deploy

macOS 13+, with Xcode command-line tools (xcode-select --install).

git clone https://github.com/Roach/axol.git
cd axol/axol
./build.sh
./axol

Compiles to a single ~350 KB stripped binary — no Xcode project, no package manager, no code signing. To keep her around past reboot, drag the binary into System Settings → General → Login Items. Window position + alert history persist to ~/Library/Application Support/Axol/.

Deploy the remote bridge (optional)

Only needed if you want GitHub / Stripe / Sentry webhooks. Pick a target — Webflow Cloud is the shortest path since it doesn't need a separate Cloudflare account:

All five guides end at the same outcome — an HTTPS endpoint hosting /app/api/hooks/{source}. See the comparison table for tradeoffs.

View source on GitHub