Privacy-first motion surveillance that runs on your laptop. Detects motion, captures snapshots, streams live — all local, no cloud.
Project description
RoomieWatch
Privacy-first motion surveillance that runs on your laptop. Detects motion, captures snapshots, streams live — all local, no cloud.
Built because I don't trust my roommate.
Why
You move to a new city. You get a room with strangers who are yet to become friends. Getting a good roommate is blissful — but what if you don't? You want to know what happens in your room when you're away at work.
Cloud cameras send your footage to someone else's server. Cheap IP cams have known vulnerabilities. Most "smart" security wants a subscription. RoomieWatch runs entirely on your machine — your webcam, your disk, your network. Nothing leaves your laptop unless you explicitly set up remote access via Tailscale.
I hope you never need this package. But if you do — it works.
Features
- Motion detection — OpenCV-based frame diffing with configurable sensitivity
- Live dashboard — MJPEG stream + stats + recent captures in a dark-themed web UI
- Privacy-first — no cloud, no third-party servers, all data stays on your machine
- Remote access — E2E encrypted via Tailscale (or self-hosted with Headscale)
- Runs locked — keeps working when your screen is locked (macOS
caffeinate) - Auto-restart — launcher script recovers from crashes automatically
- Zero config — works out of the box with your laptop webcam
Install
pipx install roomiewatch
Or from source:
git clone https://github.com/xghostient/roomiewatch.git
cd roomiewatch
pip install .
Quick Start
# Motion detection only — captures saved to ./roomiewatch_captures/
roomiewatch
# With live web dashboard
roomiewatch --stream
# Full setup — stream + prevent sleep
roomiewatch --stream --caffeinate
# Custom settings
roomiewatch --stream --port 9090 --sensitivity 5 --cooldown 10
Lock your screen (Ctrl+Cmd+Q) and leave. Do NOT close the lid.
Remote Access (Tailscale)
View your feed from anywhere on your phone — E2E encrypted, no middleman.
# On your machine
brew install tailscale
sudo brew services start tailscale
tailscale up
# Start roomiewatch (localhost only — not visible on your network)
roomiewatch --stream
# In another terminal, expose via Tailscale only
tailscale serve 8080
# Install Tailscale on your phone, sign in with the same account
# Open the Tailscale URL shown by `tailscale serve`
The stream never touches your local network — only devices signed into your Tailscale account can reach it.
Why Tailscale over Cloudflare Tunnel? Cloudflare terminates TLS at their edge — your images pass through their servers in plaintext. Tailscale is direct device-to-device WireGuard encryption. Nobody sees your footage.
For full self-hosted setup with zero third-party trust, use Headscale.
Launcher Script
For long-running sessions with auto-restart and sleep prevention:
chmod +x start_roomiewatch.sh
./start_roomiewatch.sh # stream + Tailscale
./start_roomiewatch.sh --no-stream # motion detection only
CLI Options
| Flag | Default | Description |
|---|---|---|
--stream |
off | Enable live web dashboard |
--port |
8080 | Web server port |
--expose |
off | Bind to all interfaces (0.0.0.0) instead of localhost |
--sensitivity |
3 | Motion threshold % (higher = less sensitive) |
--cooldown |
5 | Seconds between captures |
--duration |
unlimited | Auto-stop after N minutes |
--camera |
0 | Camera index |
--no-sound |
off | Disable alert beep |
--no-snapshots |
off | Stream only, don't save to disk |
--max-captures |
1000 | Max snapshots to keep; oldest auto-deleted (0=unlimited) |
--caffeinate |
off | Prevent system sleep (macOS + Linux) |
How It Works
- Captures frames from your webcam at ~15 FPS
- Converts to grayscale, applies Gaussian blur
- Computes absolute difference from previous frame
- If changed pixels exceed the sensitivity threshold — saves a timestamped JPEG and logs the event
- Flask serves a live MJPEG stream and a dashboard with stats and recent captures
Files Created
roomiewatch_captures/
├── motion_20260302_143022.jpg # snapshots with timestamp overlay
├── motion_log.txt # text log of all motion events
└── launcher.log # launcher/restart log
Troubleshooting
- Camera not opening — Grant Terminal camera access in System Settings > Privacy & Security > Camera
- Stream not loading — Check if port 8080 is in use:
lsof -i :8080 - Too many false alerts — Increase sensitivity:
roomiewatch --stream --sensitivity 5 - macOS sleeping — Don't close the lid. Use the launcher script which runs
caffeinate
Requirements
- Python 3.9+
- A webcam
- macOS or Linux (Windows: untested but should work)
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file roomiewatch-0.1.1.tar.gz.
File metadata
- Download URL: roomiewatch-0.1.1.tar.gz
- Upload date:
- Size: 13.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
846f5d9e7e04a0854333583f51e73e4a264f459a229517c72a60b460478d3ec9
|
|
| MD5 |
f4b1bd5505129b87207e4b79d02fcb59
|
|
| BLAKE2b-256 |
a76aaa3cb4291126263d4d18a74b1509c22a1eca1b6e0d70c392e162fa63e2d8
|
Provenance
The following attestation bundles were made for roomiewatch-0.1.1.tar.gz:
Publisher:
publish.yml on xghostient/roomiewatch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
roomiewatch-0.1.1.tar.gz -
Subject digest:
846f5d9e7e04a0854333583f51e73e4a264f459a229517c72a60b460478d3ec9 - Sigstore transparency entry: 1008365514
- Sigstore integration time:
-
Permalink:
xghostient/roomiewatch@158a1eae7a7d80f9503e7b5ed7081cddcd98c41a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/xghostient
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@158a1eae7a7d80f9503e7b5ed7081cddcd98c41a -
Trigger Event:
push
-
Statement type:
File details
Details for the file roomiewatch-0.1.1-py3-none-any.whl.
File metadata
- Download URL: roomiewatch-0.1.1-py3-none-any.whl
- Upload date:
- Size: 12.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f466c3653f8a7ac04189d44faaf3e1ca7fff6f8459ca70720d39884bf575f7e
|
|
| MD5 |
d44f6350fda355f98ceb1e3965084765
|
|
| BLAKE2b-256 |
fb2ffe538004eeda9bb4e6c97abcb0b8e94a763ba617a7ad44baa75d88768f83
|
Provenance
The following attestation bundles were made for roomiewatch-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on xghostient/roomiewatch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
roomiewatch-0.1.1-py3-none-any.whl -
Subject digest:
5f466c3653f8a7ac04189d44faaf3e1ca7fff6f8459ca70720d39884bf575f7e - Sigstore transparency entry: 1008365519
- Sigstore integration time:
-
Permalink:
xghostient/roomiewatch@158a1eae7a7d80f9503e7b5ed7081cddcd98c41a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/xghostient
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@158a1eae7a7d80f9503e7b5ed7081cddcd98c41a -
Trigger Event:
push
-
Statement type: