Locks your Mac with a full-screen overlay at intervals. The overlay is only dismissable by walking — it tracks your real step count (iPhone + Health Auto Export, via Home Assistant/MQTT) and unlocks once you've taken enough new steps since the lock started.
Built for people who sit too long. If you have a Home Assistant instance already ingesting iPhone step data, this closes the loop: no steps, no Mac.
iPhone Companion app ─┐
├─► HA sensor.* ──► MQTT discovery/state ──► steplock/steps
Health Auto Export ─┘ (or REST fallback poll) │
▼
Mac daemon (enforcer.py)
│
every N minutes (adaptive)
▼
Overlay (overlay.py)
unlocks when
steps_now ≥ baseline + goal
Two ways to feed step data in:
- MQTT (recommended) —
ha_setup.pypublishes MQTT-discovery configs so Home Assistant creates a device with sensors/controls automatically, and the enforcer subscribes for live updates. - REST fallback — polls two HA entities directly (e.g. an iPhone Companion sensor and a Health Auto Export sensor) and picks whichever is freshest.
- Full-screen overlay across all displays, dismissable only by steps
- Adaptive lock interval based on daily step pace (behind pace → locks more often)
- Optional "compute budget": earn seconds of unlocked time per step, lock when it runs out
- Optional calendar-aware skip (don't lock during meetings)
- MQTT remote control: pause, skip, trigger-now, resume — controllable from Home Assistant
- Idle-aware timer (won't burn your interval while you're away)
- Terminal dashboard (
cli.py, built with Textual) to watch status/logs and control the service - Home Assistant dashboard auto-provisioned via
ha_setup.py
- macOS (uses PyObjC/AppKit/Quartz for the overlay and idle detection)
- Python 3.11+, uv
- A Home Assistant instance with an MQTT broker (e.g. the Mosquitto add-on)
- A step-count entity in HA — from the iOS Home Assistant Companion app, Health Auto Export, or similar
git clone https://github.com/Rahulsharma0810/steplock.git ~/.config/steplock
cd ~/.config/steplock
uv venv
uv pip install -e .
cp config.example.toml config.toml
cp .env.example .env # fill in MQTT_PASSWORD and (optionally) HA_TOKEN
chmod 600 .envEdit config.toml — set your HA host, MQTT username, and step-sensor
entity IDs (see the [mqtt] and [fallback] sections).
Run the provisioning script once to create the MQTT-discovered device, entities, and a dashboard view in HA:
.venv/bin/python src/ha_setup.pyMake sure MQTT auth is set up (a dedicated broker login is recommended)
and the password matches .env.
# foreground smoke test
.venv/bin/python src/enforcer.py
# terminal dashboard
.venv/bin/python src/cli.pyInstall as a background service:
cp launchd/com.steplock.enforcer.plist ~/Library/LaunchAgents/
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.steplock.enforcer.plistLogs land in logs/ (rotating, 1MB x 3).
See config.example.toml for all options and inline comments:
[timer], [goal], [daily], [mqtt], [fallback], [overlay],
[compute_throttle], [calendar].
.env holds secrets only: MQTT_PASSWORD and optional HA_TOKEN
(long-lived access token, used for REST fallback polling and by
ha_setup.py).
launchctl bootout gui/$(id -u)/com.steplock.enforcer
rm ~/Library/LaunchAgents/com.steplock.enforcer.plistThen remove the MQTT-discovered device/entities and dashboard view from Home Assistant if you provisioned them.
MIT