- JavaScript 38.9%
- Python 27.8%
- HTML 19.6%
- CSS 13.2%
- Dockerfile 0.4%
- Other 0.1%
|
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
Reviewed-on: #6 |
||
|---|---|---|
| .forgejo/workflows | ||
| static | ||
| templates | ||
| .dockerignore | ||
| Dockerfile | ||
| entrypoint.sh | ||
| jailarr.py | ||
| README.md | ||
| web.py | ||
Jailarr
A Python-based monitoring system that tracks and stores MyOCV-based jail inmate rosters, and displays them in a simple web interface. It also sends real-time notifications via Apprise (supporting 80+ notification services).
| Main Screen | Analytics |
|---|---|
![]() |
![]() |
| Awards | Detective Mode |
![]() |
![]() |
Core Features
- Multi-Agency Support — Monitor multiple MyOCV-based jail rosters simultaneously
- Real-time Monitoring — Customizable check interval (default: 1 hour)
- Flexible Notifications — Supports Telegram, Discord, Slack, email, Pushover, and 80+ other services via Apprise
- Modern Web Interface — Simple and intuitive web interface
- Booking Alerts — Sends notifications with mugshot photos for new arrests
- Release Tracking — Automatically detects and logs when inmates are released
- Change Detection — Tracks updates to charges, mugshots, and other inmate details
- Mugshot Versioning — Detects mugshot changes via image hashing and preserves old versions
- Image Archiving — Downloads and stores inmate mugshots locally
- Change History — Full audit log of all record modifications
Web Interface Features
- Inmate Awards — Optionally shows a small badge for inmates that excel in certain areas (enable it to find out more)
- Analytics — View statistics and trends over time
- Detective Mode — A mini game where you can practice your detective skills. In the game, you will be presented with three random mugshots and their associated lists of charges. Your goal is to correctly match the charges to the mugshots.
Configuration
The monitor is configured through environment variables:
| Variable | Description | Required | Default |
|---|---|---|---|
JSON_URLS |
Agency JSON endpoint(s), comma or newline separated | ✅ Yes | empty |
APPRISE_URLS |
Notification service URL(s), comma-separated | ❌ No | empty |
DB_PATH |
Path to SQLite database file | ❌ No | /data/inmates.db |
CHECK_INTERVAL |
Time between scans in seconds | ❌ No | 3600 |
WEB_PORT |
Port for web server | ❌ No | 5000 |
ENABLE_AWARDS |
Enable inmate awards | ❌ No | false |
NOTIFY_NEW |
New inmate bookings | ❌ No | true |
NOTIFY_MUGSHOT |
Mugshot updates | ❌ No | true |
NOTIFY_CHARGES |
Charges updates | ❌ No | false |
NOTIFY_UPDATES |
Other field updates | ❌ No | false |
NOTIFY_STARTUP |
Send a message when the service starts | ❌ No | true |
PLACEHOLDER_MUGSHOT_HASHES |
Comma-separated MD5 hashes of placeholder mugshots | ❌ No | a859a5e7da5999c932a52430e95bbe78 |
NOTIFY_PLACEHOLDER_CHANGES |
Enable notifications for all placeholder transitions | ❌ No | false |
Note: If
APPRISE_URLSis not set, all notifications are disabled and the monitor runs in silent/archive mode.
JSON Endpoints
This app ONLY works with jail rosters that use the MyOCV platform. You must provide the JSON URL(s) for the roster(s) you want to monitor. The URLs are not public, and may require a bit of work to obtain. Read the wiki page to find out how to find the endpoint URLs.
Known JSON Endpoints
| Municipality | Agency ID | JSON URL |
|---|---|---|
| Chippewa County, MI | a20449768 |
https://cdn.myocv.com/ocvapps/a20449768/Chippewainmates.json |
| Dickinson County, MI | a135649801 |
https://cdn.myocv.com/ocvapps/a135649801/Dickinsoninmates.json |
| Houghton County, MI | a134149931 |
https://cdn.myocv.com/ocvapps/a134149931/Houghtoninmates.json |
| Mackinac County, MI | a109249781 |
https://cdn.myocv.com/ocvapps/a109249781/Mackinacinmates.json |
| Marquette County, MI | a39949855 |
https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json |
Notifications
Notification Services (Apprise)
Jailarr uses Apprise for notifications. Configure one or more services via URL:
Multiple services: Comma-separate URLs to notify multiple services simultaneously:
APPRISE_URLS=tgram://bot/chat,discord://id/token,ntfy://mytopic
See the full list of supported services.
Notification Types
| Event | Title | Includes Photo |
|---|---|---|
| New booking | 🚨 New Inmate Booking | ✅ Yes |
| Mugshot updated | 📷 Mugshot Updated | ✅ Yes |
| Charges updated | ⚖️ Charges Updated | ❌ No |
| Record updated | 📝 Inmate Record Updated | ❌ No |
First Run Behavior
On the first run (empty database), all inmates are added silently without sending notifications. This prevents a flood of alerts when initially populating the database. A startup message is still sent to confirm the monitor is online.
Example Notification
🚨 New Inmate Booking
Name: Smith, John
Age: 35
Gender: M
Booking Date: 2026-01-15 10:30:00
Charges:
OWI - OPERATING WHILE INTOXICATED - 1000.00
DRIVING WHILE LICENSE SUSPENDED - 500.00
Installation
Local
Prerequisites
- Python 3.11+
- pip
-
Clone the repository:
git clone https://github.com/yourusername/jailarr.git cd jailarr -
Install dependencies:
pip install requests apprise python-dateutil flask -
Set environment variables:
# Single agency export JSON_URLS="https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json" # Or multiple agencies (comma-separated) export JSON_URLS="https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json,https://cdn.myocv.com/ocvapps/a135649801/Dickinsoninmates.json" export APPRISE_URLS="tgram://your_bot_token/your_chat_id" export DB_PATH="./data/inmates.db" -
Run the monitor:
python jailarr.py
Docker
Option 1: Using Pre-built Image (placeholder. images coming soon)
services:
jailarr:
image: placeholder-registry/jailarr:latest
container_name: jailarr
restart: unless-stopped
environment:
- JSON_URLS=https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json
- APPRISE_URLS=tgram://bot_token/chat_id
- CHECK_INTERVAL=3600
ports:
- "5000:5000"
volumes:
- ./data:/data
Option 2: Building the Image
# Build locally
docker build -t jailarr .
# Or with docker compose
docker compose build
Option 3: Mount Source Files (No Build)
If you prefer to mount the source files directly without building an image:
services:
jailarr:
image: python:3.11-slim
container_name: jailarr
restart: unless-stopped
command: >
sh -c "pip install requests apprise python-dateutil flask && sh /app/entrypoint.sh"
environment:
- PYTHONUNBUFFERED=1
- JSON_URLS=https://cdn.myocv.com/ocvapps/a39949855/Marquetteinmates.json
- APPRISE_URLS=tgram://bot_token/chat_id
- DB_PATH=/app/data/inmates.db
- CHECK_INTERVAL=3600
ports:
- "5000:5000"
volumes:
- ./jailarr:/app
Data Storage
The monitor stores data in two locations:
Database (/data/inmates.db)
inmates table:
| Column | Description |
|---|---|
record_id |
Composite key: {agency}_{inmate_id} |
agency |
Source roster (e.g., Marquette, Dickinson) |
inmate_id |
Original ID from the source roster |
name |
Inmate name |
age, gender, race |
Demographics |
height, weight |
Physical description (if available) |
booking_date |
Date/time of booking |
charges |
List of charges |
arresting_agency |
Agency that made the arrest (if available) |
image_url |
Original mugshot URL |
image_hash |
MD5 hash for change detection |
first_seen |
Unix timestamp when first detected |
last_seen |
Unix timestamp of last scan |
status |
active or released |
change_history table:
| Column | Description |
|---|---|
record_id |
Links to inmate |
field_name |
Which field changed |
old_value |
Previous value |
new_value |
Updated value |
changed_at |
Unix timestamp |
Images (/data/images/)
- Current mugshots:
{arrest_no}.jpg - Previous versions:
{arrest_no}_v1.jpg,{arrest_no}_v2.jpg, etc.



