a bot that captures my face at the exact moment of reading slack messages.
demo.mp4
it watches slack's dock badge, and the instant the badge gets louder (a new dot, or the unread count going up) it snaps your webcam with the real time burned in. at the end of the day you get a grid of your emotional decline, a timelapse, and a neon terminal cut with a sentiment tracker.
macOS only. no slack app, no tokens, no admin: it reads the dock badge.
pip install opencv-python numpy pillow
you also need ffmpeg on your PATH for the video outputs.
python3 watch_slack.py
leave it running all day. every slack notification gets you:
- a frame in
frames/with the actual time burned in bottom-left - a line in
journal_log.jsonwith the time and (best effort) who it was from
the camera stays open the whole time so the capture is instant. that means the camera light is on all day. that is the price of art.
then build the outputs:
python3 stitch_journal.py # journal_grid.jpg (the grid) + journal.mp4 (timelapse)
python3 make_edit.py # journal_edit.mp4 (typewriter intro + sentiment tracker)
- camera: macOS will prompt the first time. required.
- full disk access (optional): grants the watcher read access to the macOS notification store so the "from:" line shows the real sender name from the slack notification. without it, senders log as "unknown" and everything else still works. System Settings > Privacy & Security > Full Disk Access > add your terminal app.
make_edit.py gives every capture a sentiment percentage and label in
neon green. by default it is a slow decline across the day, because that is
accurate. to override any shot, edit journal_log.json:
{
"file": "frames/2026-08-29_14-52-10.jpg",
"time": "2:52 PM",
"sender": "my boss",
"sentiment": 11,
"label": "suppressed rage"
}lsappinfo info -only StatusLabel Slack returns slack's dock badge: empty
(quiet), a dot (unread activity), or a number (mentions and DMs). the
watcher polls it twice a second and snaps when the badge escalates. reading
the message resets the badge, so the next message triggers again.
it will not fire once per message inside a burst that arrives before you look, and it cannot see messages while you have slack focused and read them instantly. it captures the moments that matter: the ones where slack interrupted you.