Skip to content

Repository files navigation

Agent Notifier

Give your AI coding agent a body. When Claude Code, Codex, or any tool finishes, needs your input, or fails, a lightweight animated companion — a painterly butterfly or a full-screen fireworks burst — appears over your workspace, then gets out of the way. No dock icon, no stolen focus, no network, no telemetry.

macOS 14+ Swift 6 Menu bar only License: MIT

It plugs into agents the same way a shell hook does: your agent fires a lifecycle event, a tiny CLI turns it into a local URL-scheme message, and the menu-bar app plays the animation. Drop it into any agent that can run a command on an event.


Why

Agents run long. You tab away. You miss the moment it finishes or stalls waiting for approval. A calm ambient signal on your own screen — no notification-center spam, no sound, no focus grab — tells you what happened at a glance and then disappears.

Companions

Companion Motion Look
Butterfly Airborne Blender-rendered painterly wings with a live shimmer trail; flies across and tours every display
Firecracker Burst Procedural SpriteKit fireworks — launches from the middle and bursts at random positions across every screen at once

Pick one from the menu-bar Companion submenu or Settings. Everything is drawn at runtime — no bundled videos, no proprietary assets.

Agent states

State Signal
completed Calm celebratory presentation, then exits on its own
input-needed Amber attention, re-pulses, and stays available in the menu bar
failed Crimson, sharper/sputtering motion, stays available in the menu bar
working Accepted but hidden unless you enable it in Settings

Reduce Motion, light/dark appearance, hover-to-pause, and multi-display are all handled. Input-needed and failed events never relaunch on a timer — a single presentation, then a quiet menu-bar entry until you acknowledge them.


Install

Requires macOS 14+, a Swift 6 toolchain, and Apple silicon for the packaging script. Full Xcode is not required to build.

git clone https://github.com/<you>/agent-notifier.git
cd agent-notifier
swift build
./Scripts/package-app.sh     # builds + ad-hoc signs the .app and CLI into ../../Artifacts
./Scripts/install-local.sh   # installs to ~/Applications, links the CLI, launches it

The app lands in ~/Applications, the helper CLI is linked at ~/.local/bin/butterfly-notify, and the menu-bar process starts.

Gatekeeper: local builds are ad-hoc signed, so macOS will warn the first time. Right-click the app → OpenOpen, or clear the quarantine flag: xattr -dr com.apple.quarantine "~/Applications/Agent Notifier.app". A public binary release still needs Developer ID signing and notarization.

Integrate with your agent

One command (Claude Code / Codex)

butterfly-notify integrations install claude   # or: codex, or: all
butterfly-notify integrations status all
butterfly-notify integrations remove all       # fully reversible

This writes a command hook into ~/.claude/settings.json (Stop, StopFailure, PermissionRequest, Elicitation, Notification) and/or ~/.codex/hooks.json (Stop, PermissionRequest). The write is structured, idempotent, and backs up the existing file first, and only ever touches its own marked hooks — your other hooks are left untouched. Codex surfaces newly installed command hooks through its normal trust flow.

Any other agent (generic CLI)

If your tool can run a command on an event, you don't need the installer — just call the CLI:

butterfly-notify send --state completed   --source my-agent
butterfly-notify send --state input-needed --source my-agent --title "Approval needed"
butterfly-notify send --state failed      --source my-agent --project "$PWD"

Or pipe a raw Claude/Codex hook JSON payload straight in:

echo '{"hook_event_name":"Stop"}' | butterfly-notify ingest --source claude

Manual hook (transparency)

The installer just adds an entry like this — you can write it yourself:

// ~/.claude/settings.json
{
  "hooks": {
    "Stop": [
      { "hooks": [{ "type": "command", "command": "/Users/you/.local/bin/butterfly-notify ingest --source claude", "timeout": 5 }] }
    ]
  }
}

How it works

agent lifecycle event
      │  (command hook)
      ▼
butterfly-notify  ──encode──▶  butterfly-agent-notifier://event?payload=…
      │                                   │  (local URL scheme, no network)
      ▼                                   ▼
  /usr/bin/open -g                 menu-bar app decodes + validates
                                          │
                                          ▼
                                 SpriteKit overlay per display

Three small pieces:

  • ButterflyCore — the event model, URL codec, agent adapters, hook installer, and motion math. Pure Swift, no UI, fully unit-tested.
  • ButterflyNotifyCLI (butterfly-notify) — turns events/hook payloads into a validated local URL and hands it to open.
  • ButterflyAgentNotifier — the LSUIElement menu-bar app that renders the companion with AppKit + SpriteKit, one borderless overlay panel per display.

Configuration

Menu bar → Settings: choose the companion, size, motion intensity, the completed-event duration, and whether working events show. Launch-at-login and per-agent hook install/remove/status live there too.

Security & privacy

Built to be safe to run and safe to publish:

  • No network. No telemetry. No event history. Nothing leaves your machine.
  • Events travel only through the registered butterfly-agent-notifier:// URL scheme, delivered with open — never a shell.
  • Payloads are size-bounded at both the base64 and decoded layers, JSON is parsed defensively, and every field is validated, whitespace-collapsed, control-character-stripped, and length-capped before it is shown.
  • Only bounded source / title / project / session metadata is accepted. Prompts, transcripts, tool input, and assistant output are never touched.
  • The hook installer quotes paths for the shell, edits only its own hooks, and backs up your config before writing.

Build & test

swift build
swift test --enable-swift-testing --disable-xctest   # requires full Xcode to run cases

Offline check without Xcode (compiles the core with its module and runs a smoke verifier):

swiftc Scripts/core-smoke.swift Sources/ButterflyCore/*.swift -o /tmp/cs && /tmp/cs

Extending: add a companion

Companions are a versioned catalog, so new ones don't touch event handling:

  1. Add a case to CompanionKind with a movementStyle (airborne, grounded, or burst) in Sources/ButterflyCore/Companion.swift.
  2. Build a CompanionNode renderer (procedural SpriteKit — see FireworkArtwork.swift for a self-contained example) and wire it into CompanionScene.prepare.
  3. Drop a manifest.json under Sources/ButterflyRenderer/Resources/Companions/<name>/.

See docs/companion-packs.md.

Roadmap / not yet included

Developer ID signing + notarization, a downloadable release, direct Cursor hooks, sounds, and community image / Blender companion packs.

License

MIT © Akshith Gojuru. Contributions welcome — open an issue or PR.

About

Animated menu-bar companions (butterfly + fireworks) that react to your AI coding agent's lifecycle events. Local-only, no telemetry.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages