A Raspberry Pi-first desk companion with a deterministic core, a small web cockpit, a living display face, and optional local AI wording.
JIRI is a small personal desk assistant designed for weak, practical hardware: a Raspberry Pi 3B/3B+, 1 GB RAM, SQLite storage, and a compact display. It manages todos, notes, weather, focus sessions, hydration, persona nudges, Telegram control, update checks, safe database backups, and a read-only database browser from a lightweight Flask admin dashboard.
The project is deliberately not a cloud chatbot, not a kiosk website, and not a heavyweight home server stack. It is a deterministic Python application that can optionally use local AI later for wording only.
AI-assisted, not AI-controlled.
Python owns truth, timing, state, safety rules, and actions.
Optional AI owns wording, summaries, and personality only.
Most “AI assistant” projects put the model in charge too early. JIRI does the opposite:
| Principle | What JIRI Does |
|---|---|
| Deterministic first | Todos, focus, weather, events, and persona rules work without AI. |
| Pi-first | Every feature is judged against Raspberry Pi 3B/3B+ constraints. |
| Local state | SQLite is the source of truth. No cloud database required. |
| Separate surfaces | Admin dashboard, screen preview, CLI, Telegram worker, and Pygame UI stay separate. |
| Safe AI boundary | AI cannot write SQLite, run commands, mark todos done, change due dates, or own state. |
| Area | Status | Notes |
|---|---|---|
| Core SQLite app | Working | Todos, notes, settings, events, focus sessions, weather cache. |
| Admin dashboard | Working | Password-protected Flask UI on port 5000. |
| Screen preview | Working | Separate web surface on port 5001. |
| CLI | Working | SSH-friendly control path. |
| Weather | Working | Open-Meteo primary, wttr.in fallback, SQLite cache fallback. |
| Focus Assist | Working | Start, pause, resume, complete, cancel, no per-second DB writes. |
| Persona engine | Working | Deterministic priority/cooldown rules and Telegram nudges. |
| Telegram | Working | Polling bot, allowlist, commands, DB-backed settings. |
| Themes | Working | Catppuccin Mocha default and Nothing UI alternative. |
| Water history | Working | Today, weekly, 30-day, and 12-month SQLite-backed views. |
| Safe updates | Documented + tools | GitHub update check, verified SQLite backup, restore script, rollback methodology. |
| DB browser | Working | Read-only raw SQLite inspection in admin. |
| Local AI | Scaffolded | llama-server integration is disabled by default and benchmark-gated. |
| Real Pi display | Hardware-gated | Needs final 3.5-inch display/touch confirmation. |
Browser / Phone
|
v
+---------------------------+
| Flask Admin :5000 |
| todos / notes / weather |
| focus / telegram / db |
+-------------+-------------+
|
v
+-------------+ +---------------------+ +------------------+
| Telegram | <----> | JIRI Runtime | <----> | Open-Meteo / |
| polling | | deterministic core | | wttr.in weather |
+-------------+ +----------+----------+ +------------------+
|
v
+----------------+
| SQLite |
| source of truth|
+-------+--------+
|
+-----------------+-----------------+
| |
v v
+--------------------+ +--------------------+
| Screen Web :5001 | | Pygame Display |
| display preview | | real Pi face UI |
+--------------------+ +--------------------+
Optional after benchmark:
JIRI Runtime -> local llama-server -> wording rewrite only -> deterministic fallback remains
Available at http://127.0.0.1:5000/admin during local development.
- Todos with due dates, priority, done/cancel/delete actions.
- Notes with tags.
- Weather location search, saved coordinates, refresh controls, current/hourly/daily forecast display.
- Focus sessions with pause/resume/complete/cancel controls.
- Water tracking with profile-based daily targets, weekly history, 30-day history, and 12-month aggregation.
- Telegram binding, bot status, chat allowlist, token management.
- Persona settings for quiet hours, category cooldowns, category toggles, and UI theme selection.
- AI status page with clean missing-binary handling for
llama-server. - Update checker button that compares local Git state with the configured upstream without applying changes.
- Read-only DB browser for inspecting raw SQLite tables.
Available at http://127.0.0.1:5001/screen during local development.
- Glanceable face and headline.
- Panel rotation for weather, focus, todos, notes, and system state.
- Intended to mirror the 3.5-inch Pi display without becoming the admin dashboard.
The CLI is designed for SSH and recovery work.
PYTHONPATH=src .venv/bin/python -m jiri.cli --help
PYTHONPATH=src .venv/bin/python -m jiri.cli todo add "Water the plants" --due "2026-05-16 18:00"
PYTHONPATH=src .venv/bin/python -m jiri.cli weather refresh
PYTHONPATH=src .venv/bin/python -m jiri.cli focus start --title "Deep work" --minutes 25
PYTHONPATH=src .venv/bin/python -m jiri.cli healthTelegram is an admin control surface, not the core system.
- Uses
getUpdatespolling. - No public IP, webhook, router port-forward, or TLS certificate required.
- Allowed chat IDs are enforced.
- Settings are stored in SQLite and managed from
/admin/telegram. - Commands include
/status,/todos,/todo add,/todo done,/notes,/note add,/weather,/focus, and/water.
JIRI has a deterministic personality layer. The display and Telegram worker can surface moments such as focus mode, overdue escalation, hydration reminders, weather tips, quiet hours, and ambient micro-expressions.
Priority order is intentionally explicit:
critical overdue > focus > normal overdue > weather > quiet hours > water > ambient
The persona can be tuned in /admin/persona without changing code.
The web dashboard has two lightweight themes:
| Theme | Notes |
|---|---|
| Catppuccin Mocha | Default, soft terminal-inspired palette. |
| Nothing UI | Black/white/red system using Nothing-style typography when available. |
Theme selection is stored in SQLite through persona settings. The navbar theme button toggles between the available themes.
JIRI includes an update checker and a safe update methodology, but it does not blindly auto-update by default.
/adminhas an Updates button that checks the configured Git upstream withgit ls-remote.- The checker does not run
git pull,git reset, or mutate the codebase. scripts/backup_db.shuses SQLite's online backup API and writes a manifest with SHA-256, schema version, table names, row counts, and integrity status.scripts/restore_db.sh <backup.db>verifies the backup before restore and backs up the current DB before replacement.- The full process is documented in
docs/SAFE_UPDATE_METHODOLOGY.md.
Backup manually:
scripts/backup_db.shRestore manually:
scripts/restore_db.sh backups/jiri-YYYYMMDD-HHMMSS.dbcd /root/Project/jiripython3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txtPYTHONPATH=src python -m pytest tests/ -qExpected current result:
145 passed
scripts/run_all.shOpen:
| Surface | URL | Purpose |
|---|---|---|
| Admin | http://127.0.0.1:5000/admin |
Full dashboard and CRUD controls. |
| Screen | http://127.0.0.1:5001/screen |
Display preview surface. |
Default development password:
test
Override it with:
export JIRI_ADMIN_PASSWORD='choose-a-real-password'scripts/run_admin.sh
scripts/run_screen.sh
scripts/run_telegram.sh
scripts/run_ui.shCopy the example config when you need persistent local settings:
cp config.example.toml config.tomlImportant environment overrides:
| Variable | Purpose |
|---|---|
JIRI_DB_PATH |
SQLite database path. |
JIRI_DISPLAY_DRIVER |
pygame or mock. |
JIRI_WEB_HOST |
Flask bind host. |
JIRI_WEB_PORT |
Flask port for the active surface. |
JIRI_WEATHER_FAKE |
Deterministic fake weather for tests. |
JIRI_TELEGRAM_BOT_TOKEN |
First-boot Telegram token seed. |
JIRI_TELEGRAM_ALLOWED_CHAT_IDS |
First-boot Telegram allowlist seed. |
JIRI_LLM_SERVER_BINARY |
Full path or command name for llama-server. |
JIRI_LLM_MODEL_PATH |
Local GGUF model path. |
JIRI_LOCAL_DEV |
Explicit opt-in for local AI preflight scripts. |
Local AI is optional and disabled by default. The admin AI page can show whether llama-server is available. If it is missing, JIRI now reports a clear setup message instead of exposing a raw [Errno 2] crash-style error.
To point JIRI at a custom llama.cpp server binary:
export JIRI_LLM_SERVER_BINARY=/path/to/llama-server
export JIRI_LLM_MODEL_PATH=/path/to/model.ggufProduction acceptance still requires a real Raspberry Pi benchmark. WSL/local runs are compatibility preflight only.
The read-only DB browser is available at:
http://127.0.0.1:5000/admin/db-browser
Use it to inspect what the app or previous agents stored in SQLite:
todosnotessettingsevents_logfocus_sessionsweather_cache
It does not write, delete, or mutate database rows.
.
├── config.example.toml # documented configuration defaults
├── data/ # local SQLite databases (ignored by git)
├── docs/ # handbook, gates, deployment and troubleshooting docs
├── jirie.png # README/project image
├── scripts/ # development, deployment, AI, and smoke scripts
├── src/jiri/ # application package
│ ├── cli.py # SSH-friendly command line interface
│ ├── db.py # SQLite schema and helpers
│ ├── events.py # idempotent event log
│ ├── focus.py # focus session state machine
│ ├── llama.py # optional llama-server control helpers
│ ├── persona.py # deterministic persona engine
│ ├── runtime.py # central orchestration object
│ ├── telegram.py # Telegram polling bot
│ ├── todos.py / notes.py # core personal data models
│ ├── weather.py / water.py # weather and hydration systems
│ ├── ui/ # Pygame display model and touch zones
│ └── web/ # Flask app, templates, static CSS
├── systemd/ # Raspberry Pi service files
└── tests/ # pytest coverage for core, web, CLI, Telegram, UI
| Script | Purpose |
|---|---|
scripts/test_wsl.sh |
Main WSL test gate. |
scripts/run_all.sh |
Start admin and screen surfaces together. |
scripts/run_admin.sh |
Start admin surface only. |
scripts/run_screen.sh |
Start screen preview only. |
scripts/run_telegram.sh |
Start Telegram polling worker. |
scripts/run_ui.sh |
Start Pygame UI. |
scripts/backup_db.sh |
Back up SQLite database. |
scripts/restore_db.sh |
Restore a verified SQLite backup after backing up the current DB. |
scripts/install_pi.sh |
Raspberry Pi installation helper. |
scripts/pi_smoke_test.sh |
Pi deployment smoke test. |
scripts/ai_*.sh |
Local AI benchmark and monitoring helpers. |
Run the full suite:
source .venv/bin/activate
PYTHONPATH=src python -m pytest tests/ -qRun the WSL gate:
scripts/test_wsl.shThe suite covers:
- Config/env loading.
- SQLite schema and migration behavior.
- Todos, notes, focus, water, weather.
- Monthly/yearly water history.
- Weather next-12-hour forecast slicing across midnight.
- Persona priority/cooldown rules.
- Event emission and deduplication.
- Telegram polling and command dispatch.
- Flask admin/screen/API surfaces.
- DB browser read-only inspection.
- Update checker logic.
- Pygame display model and touch zones.
- AI script guardrails.
Target hardware is a single Raspberry Pi 3B/3B+.
Raspberry Pi OS
-> Python virtualenv
-> SQLite database
-> Flask admin/screen services
-> optional Pygame display service
-> optional Telegram polling worker
-> optional local llama-server after benchmark acceptance
Real hardware acceptance still needs:
- Exact 3.5-inch display model confirmation.
- Touch/rotation/framebuffer behavior confirmation.
- RAM/CPU/temperature measurements on the target Pi.
- Local Gemma benchmark before production AI integration claims.
Set PYTHONPATH=src:
PYTHONPATH=src python -m jiri.cli healthDefault development password is test. Override with:
export JIRI_ADMIN_PASSWORD='your-password'Install llama.cpp or set the binary path:
export JIRI_LLM_SERVER_BINARY=/path/to/llama-serverJIRI will continue working without AI.
JIRI falls back in this order:
Open-Meteo -> wttr.in -> SQLite cache -> unavailable message
Use alternate ports:
JIRI_ADMIN_PORT=5100 JIRI_SCREEN_PORT=5101 scripts/run_all.shJIRI intentionally avoids:
- React / Node.js / Electron.
- Docker / Kubernetes.
- PostgreSQL / MongoDB / Redis / Celery.
- Browser kiosk as the Pi display UI.
- Cloud AI as a required dependency.
- AI-owned state or actions.
This keeps the project small enough to debug over SSH and realistic on Raspberry Pi 3B/3B+ hardware.
| Document | Purpose |
|---|---|
docs/ENGINEERING_HANDBOOK.md |
Source-of-truth engineering rules and gates. |
docs/ARCHITECTURE.md |
Layer overview and reliability rules. |
docs/MISSION_CONTROL.md |
Short operational status board. |
docs/STAGE_GATES.md |
Acceptance gates by stage. |
docs/ROADMAP.md |
Short progress tracker. |
docs/PI_DEPLOYMENT.md |
Raspberry Pi deployment notes. |
docs/SAFE_UPDATE_METHODOLOGY.md |
Safe GitHub update, backup, restore, and rollback rules. |
docs/TROUBLESHOOTING.md |
Common issues and fixes. |
docs/PERSONA_IMPLEMENTATION_PLAN.md |
Persona staged implementation plan. |
No license has been selected yet. Treat the code as private unless a license file is added.
