One charged AirPod is zero AirPods.

A bud doesn't seat, only one charges, and you find out in the car. Oddpod notices in two minutes and tells you.

$ git clone && ./scripts/install.sh
Read the whole install →
LEFT
RIGHT
Chris’s AirPods Pro
Right AirPod is NOT charging (40%) — left went 40%→86%
now

How it works

01

Reads what macOS already knows

Every two minutes, the same left and right percentages your battery widget shows. No pairing, no driver, no admin rights.

02

Watches for divergence

Twenty minutes of history. One bud climbs 3%, the other hasn't moved — that's not a slow charge, that's a bud that isn't seated.

03

Tells you while it still matters

A native notification, once an hour at most. At the desk, not in the car.

Why not just look

The failure is silent, and the moment you'd catch it is the moment you stopped paying attention.

The case clicks the same either way. Nothing distinguishes "both charging" from "one charging" unless you go looking — and you only look after it's cost you.

Install

macOS with AirPods already paired. Python 3 ships with the system — there's nothing else to install.

One thing to check: notifications come from Script Editor, so enable it under System Settings → Notifications.

./scripts/install.sh --uninstall removes everything.

$ git clone https://github.com/chrisdeweese/oddpod
$ cd oddpod
$ ./scripts/install.sh
Oddpod is watching. Checks every 2 minutes.

# confirm it's running
$ launchctl list | grep oddpod
-	0	com.oddpod.watch

What it doesn't do

It runs forever, so the limits matter more than the features. Under 100 lines of Python in one file — reading it takes less time than this page.

  • No network access. It never opens a socket.
  • No telemetry, no analytics, no account.
  • No admin privileges. No helper tool, no kernel extension. It runs as you.
  • Writes one file. ~/.oddpod.json — twenty minutes of percentages.
  • No menu bar icon, no window, no dock item. Silent until it has something to say.
  • It infers charging from rising percentages. macOS exposes no charging flag for AirPods, so it needs ten minutes of history before calling a bud stuck. It errs toward silence.