Skip to content

wtbates99/batesposture

Repository files navigation

BatesPosture

Real-time desktop posture monitor. Webcam in, posture score out. 100% local.

License GitHub stars Last commit Python Made with MediaPipe Site

Website · Install · How it works · Privacy · FAQ


🟢 excellent — streak running 12m 🟡 fair — corrections needed 🔴 poor posture — alert fired

A tiny tray app that watches your webcam, scores your posture every second on a 0–100 scale, and pings you when you start slouching. No cloud. No accounts. No telemetry. Just a webcam and uv run.

Why

Most posture apps are either subscription SaaS or a Pomodoro timer that yells "stand up!" every 30 minutes. BatesPosture actually looks at you with MediaPipe, computes seven weighted geometric metrics (head tilt, neck angle, shoulder balance, spine alignment, …), and only nudges you when your score drops — calibrated to your posture, not a generic threshold.

It's free, open source, and the entire pipeline runs on-device. Nothing leaves your computer.

Features

🎯 Live 0–100 score Color-coded tray icon updated every second
📊 Session dashboard Sparkline history, average, min/max, best streak, duration
🔔 Smart alerts Native OS notifications with threshold + cooldown + focus mode
⏱️ Scheduling Continuous or interval tracking, plus 50-min break reminders
💾 Local logging Optional SQLite + CSV export, all on your machine
Adaptive perf Auto-downscales on slow hardware, optional GPU mode
👤 Auto-pause Stops counting away-from-desk time after ~2s no-detection
🔒 100% local No cloud, no accounts, no telemetry, ever

Install

Requires Python 3.10+ and uv.

git clone https://github.com/wtbates99/batesposture.git
cd batesposture
uv sync --all-groups
uv run batesposture

That's it. Grant camera permission, complete the 6-second calibration, and the tray icon takes over.

Linux: extra system libraries (Debian/Ubuntu)
sudo apt-get update
sudo apt-get install -y \
  libgl1 libglib2.0-0 \
  libxcb-xinerama0 libxcb-cursor0 libxcb-icccm4 libxcb-image0 \
  libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 \
  libxcb-xfixes0 libxkbcommon-x11-0 libegl1

GNOME users may need the AppIndicator extension.

How it works

  1. Calibrate — a 6-second baseline of your natural posture so alerts are tuned to you.
  2. Track — MediaPipe extracts pose landmarks → seven weighted metrics → one 0–100 score → tray color.
  3. Alert — score drops below your threshold → native desktop notification (with cooldown to prevent fatigue).
  4. Review — open the dashboard for the live frame, score sparkline, session stats, and streaks.

Shortcuts: Ctrl+Shift+T start/stop · Ctrl+Shift+D dashboard · Ctrl+, settings · Ctrl+Q quit

Configuration

Settings cover camera, notifications, tracking schedule, and advanced scoring controls. Anything in the UI can also be set via POSTURE_<SECTION>_<FIELD> env vars at launch:

POSTURE_RUNTIME_DEFAULT_CAMERA_ID=1 uv run batesposture     # use a different camera
POSTURE_RUNTIME_DEFAULT_FPS=15 uv run batesposture          # reduce camera load
POSTURE_RUNTIME_POOR_POSTURE_THRESHOLD=55 uv run batesposture
POSTURE_ML_ENABLE_GPU=true uv run batesposture              # GPU mode

Full mapping: KEY_TO_SECTION_FIELD in batesposture/services/settings_service.py.

Default tuning values
Constant Default Description
POOR_POSTURE_THRESHOLD_DEFAULT 60 Score below which an alert can fire
SCORE_THRESHOLD_DEFAULT 65 Threshold for good-posture streak tracking
DEFAULT_POSTURE_WEIGHTS (0.2, 0.2, 0.15, 0.15, 0.15, 0.1, 0.05) Per-metric contribution to score
BREAK_REMINDER_MINUTES 50 Continuous sitting time before a break reminder
CALIBRATION_DURATION_SECONDS 6 Baseline capture time during onboarding

Data locations

Database / lock Linux ~/.local/share/BatesPosture/ · macOS ~/Library/Application Support/BatesPosture/ · Windows %APPDATA%
Logs macOS ~/Library/Logs/BatesPosture/app.log · other ~/.batesposture_logs/app.log (5 MB rotation, 3 backups)
CSV exports ~/posture_export_YYYYMMDD_HHMMSS.csv
Settings QSettings (platform-specific backing store)

Privacy

  • No video frames are uploaded. MediaPipe runs locally.
  • No posture data leaves your machine. Period.
  • No accounts, no telemetry, no analytics.
  • SQLite logging is opt-in and disabled by default.

FAQ

Does it work on macOS / Windows / Linux? Yes — all three. Requires a webcam and Python 3.10+.

Does it slow down my computer? Adaptive resolution + optional GPU mode keep it light. Drop POSTURE_RUNTIME_DEFAULT_FPS=15 for older hardware.

Will it nag me constantly? No. Notifications have a configurable cooldown, focus mode silences them entirely, and the score only fires alerts below your threshold.

Can I export my data? Yes — local SQLite + CSV export when logging is enabled.

Why not a packaged installer? Source is the only distribution. uv sync && uv run batesposture is faster than installing a .dmg/.msi anyway.

Development

uv sync --all-groups
QT_QPA_PLATFORM=offscreen uv run python -m pytest
uv run pre-commit run --all-files

Marketing site source is in web/. Preview locally:

docker build -t batesposture-site .
docker run --rm -p 8080:80 batesposture-site

Troubleshooting

Camera does not open
  • Try another camera index: POSTURE_RUNTIME_DEFAULT_CAMERA_ID=1 uv run batesposture
  • Make sure another app is not already using the camera
  • Check that only one BatesPosture instance is running
Tracking keeps pausing

If no person is detected for ~2 seconds, BatesPosture pauses the session on purpose so away-from-desk time doesn't pollute your stats. Make sure your head and shoulders are well lit and visible.

Performance is poor
  • POSTURE_RUNTIME_ADAPTIVE_RESOLUTION=true
  • POSTURE_RUNTIME_DEFAULT_FPS=15
  • Reduce frame size in settings
  • Lower model complexity in the Advanced section
Export is empty

Database logging must be enabled before data can be exported. Export writes saved score rows, not unsaved live state.

Contributing

Issues and PRs welcome. If you change runtime behavior, update tests and keep the README in sync.


posture.palanbates.com · MIT-style license · Built by @wtbates99

If BatesPosture saves your neck, ⭐ the repo — that's how more people find it.

Releases

No releases published

Packages

 
 
 

Contributors