Skip to the content
Jess. All projects

Stack · Free menu bar app for macOS

Sit like you meant to. Stack remembers what that looked like.

Physios have a phrase for it: stack your spine. Ears over shoulders over hips. It is easy to do for about four minutes, and then there is a deadline and the screen gets closer.

Stack lives in your menu bar. You record a baseline once, by sitting the way you actually want to sit. After that it takes a webcam frame every thirty seconds, measures where your head sits relative to your shoulders, and compares it against that baseline. When you have been out of position for a sustained stretch, a small popup appears. It never takes keyboard focus, so it cannot interrupt a sentence you are in the middle of typing.

Download Stack

Free macOS about 276 KB

  • It measures, it does not guess Actual geometry: where your ear sits relative to your shoulder, read off the frame 2,880 times a day.
  • It learns your posture, not an ideal one You calibrate once by sitting how you want to sit. That becomes the line.
  • It only speaks when it matters Sustained drift, not one frame. Reaching for coffee is not a slouch.

Everything above happens on your Mac. Stack can optionally send a cropped frame to Google’s Gemini for a second opinion and better-worded coaching; that needs your own API key, and it is a setting you turn on.

Ears over shoulders over hips. Stack measures how far the first has drifted from the other two, and compares that against how you sat on the day you calibrated it.

What it does

Three things, on a loop.

  1. It looks, every thirty seconds.

    One webcam frame goes into Google’s MediaPipe pose model, which runs on your machine. Nothing is uploaded, and nothing waits on a server to come back with an answer.

  2. It compares you against you.

    You calibrate once, sitting the way you want to sit. That becomes the reference. The score is drift from your own baseline, not a verdict handed down from a table of ideal humans.

  3. It waits before it says anything.

    One bad frame is a stretch or a reach for the coffee. The popup only arrives after you have been out of position for a sustained stretch, and it is deliberately non-activating: it will not steal your cursor or your keystrokes.

Every check is written to a local SQLite file. When you want to look at it, Stack builds an HTML dashboard that opens straight from disk, with no connection involved.

Why a camera

You cannot see yourself work.

That is the whole reason posture advice fails. Every bit of it assumes you will notice, and noticing is exactly the thing that stops happening the moment the work gets interesting. A mirror works for five seconds. A reminder every hour is right by accident. Meanwhile the camera on your laptop has been pointed at you all day, doing nothing.

It sees the thing you cannot.
A pose model finds your ear, your shoulder and your hip in the frame, and the angle between them is a real measurement. Not a timer, not a guess about how long you have been sitting: where your head actually is, right now.
Your baseline, not a diagram.
Sit the way you want to sit and Stack records it. Everything after that is drift from your own line. Backs differ, chairs differ, desks differ, and an ideal posture from a poster does not know anything about yours.
It stays quiet until it should not be.
Checking every thirty seconds means it can afford to wait. It only speaks after you have been out of position for a sustained stretch, and the popup never takes keyboard focus, so it cannot land in the middle of a sentence you are typing.
It remembers, so you can stop guessing.
Every check goes into a local file. When you want to know whether this week was better than last, there is a real answer instead of a feeling.

The camera was already there. This is the first thing that put it to work while you are not on a call.

Requirements and setup

Getting it running.

  • macOS
  • A webcam, built-in is fine
  • Homebrew and uv
  • Python 3.12, which uv installs for you

Download the zip, unpack it, then run these from the project folder:

uv sync
./scripts/fetch_model.sh
uv run python scripts/identify_cameras.py
uv run python scripts/calibrate.py
./run.sh

If identify_cameras.py says No cameras found the first time, run it again. That first camera access is what triggers the macOS permission prompt, and OpenCV does not wait around for your answer.

calibrate.py is the step that matters. Sit the way you want to be sitting for the rest of the day, and let it take the frame. Everything the app says afterwards is measured against it. The download is small, 276 KB, because the 9.4 MB pose model is fetched by fetch_model.sh rather than shipped inside the zip.

Limitations

What it cannot do.

  • It sees what a desk webcam sees, which is roughly your head and shoulders. Your lower back is not in the frame, and Stack has no opinion about it.
  • Move your chair, your desk or your camera and the baseline stops describing you. Recalibrate, and expect the trend to blank itself when you do.
  • Lighting is part of the measurement. A dark room or a bright window behind you gives the pose model less to work with, and the history will show the gaps rather than paper over them.
  • It is not a medical device and it diagnoses nothing. It measures one angle and tells you when that angle has drifted from where you put it.