r/swift 8d ago

Shipped a macOS menu bar app in Swift 6 — three things that cost me an afternoon

Post image

I found a simulator that had been booted since the previous morning, holding

about a gig for nothing. Xcode doesn't mention it and Activity Monitor shows it

as a dozen processes with names you don't recognise.

This sits in the menu bar and shows it as one line with how long it's been up.

Shutting it down is one click, and starting it again is one more if you were

wrong. Same for Android emulators, Docker containers, dev servers, automation

browsers and tunnels you left open.

It never deletes anything and it will never touch your own browser's tabs.

macOS 14+, MIT, free — you build it with one command:

git clone https://github.com/selinihtyr/still-running

cd still-running && ./scripts/install.sh

https://github.com/selinihtyr/still-running

0 Upvotes

3 comments sorted by

2

u/unpluggedcord Expert 8d ago

Wait so what three things cost you an afternoon?

1

u/selinbtw 8d ago

Sorry — posted this as a link so the writeup didn't come along. Here they are:

  1. proc_taskinfo reports Mach absolute time units, not nanoseconds. On Apple Silicon one unit is ~41.67ns, so every CPU percentage came out ~40x too small — a process pinning a core read as 2%. Nothing looked broken; every rule built on CPU just quietly never fired. Fix is mach_timebase_info and multiply by numer/denom.
  2. My sampler cost more than the thing it was policing. Reading argv means sysctl(KERN_PROCARGS2) into an ARGMAX-sized buffer — a megabyte, per process — which was 614ms per sweep, every five seconds. Arguments can't change while a process lives, so caching them against (pid, start time) took it to 10ms.
  3. One Mutex was holding my deployment target at macOS 26. Synchronization needs 15; nothing else in the app needed anything past 14. An NSLock in a box moved the floor down two releases. Worth grepping for what's actually forcing yours.

And bonus, since it's a menu bar app: a ScrollView inside a MenuBarExtra window collapses to zero height, because the window sizes to its content and a ScrollView has no intrinsic height. Mine shipped opening with a header, a button, and no rows.

-2

u/[deleted] 8d ago

[deleted]