About BooTheSchedule
Turn your notifications into calendar events automatically and intelligently. Heck, maybe even fast too.
What is BooTheSchedule?
BooTheSchedule is an end-to-end pipeline that captures notifications from your Android phone, runs them through an AI engine to detect scheduling intent, and adds the extracted events directly to your Google Calendar. No more manually typing "Team standup tomorrow at 10am" into your calendar. Your phone already told you about it! BooTheSchedule does the rest.
Built by BooTheMeg Group as a passion project to solve a problem we all felt: our phones buzz with plans, deadlines, and reminders all day, but none of that ever makes it into our actual calendars without manual effort.
The Team
Our team consist of 5 people:
Afdhal, Adib, Welsom, Amir and Iqram
We came into this project with different levels of programming experience. Afdhall, who had the deepest technical knowledge, took the lead on architecture and the trickiest integrations. The dynamic worked because we complemented each other. Some could dive deep into ADB internals and Google OAuth flows while the rest of the team focused on the Flask API, frontend, and testing.
We spent countless hours brainstorming the core idea. We knew we wanted to build something that actually solved a problem and not just another todo app. The moment we landed on "what if your phone notifications could schedule themselves?" everything clicked.
The Pipeline
get_notif.py— Connects to an Android phone via ADB (Android Debug Bridge), dumps the notification tray usingdumpsys notification, parses the raw output with regex to extract app names, senders, messages, and timestamps. Implements two-layer deduplication (ADB notification ID + content fingerprint) so the same notification is never processed twice.processing.py— Takes the raw notification JSON and sends each message to OpenRouter AI (using thepoolside/laguna-m.1model) with a carefully crafted system prompt. The AI extracts structured calendar event data: title, date, time, duration, location, attendees, and recurrence rules. Output is validated against a strict schema before proceeding. Why laguna-m.1 you might ask? We dont have any clear reason other than because its free on openrouter.calendar_api.py— Takes the validated event objects and inserts them into Google Calendar via the Google Calendar API (OAuth 2.0). Handles token refresh, timezone conversion, and builds proper Google Calendar event resources with optional fields like attendees and recurrence rules.api.py(Flask REST API) — Wraps the entire pipeline into HTTP endpoints so the mobile app can trigger processing and calendar insertion over the network. Includes rate limiting, CORS support, and input validation.Expo App (React Native) — A cross-platform mobile app (Android, iOS, web) with four tabs: Home (server status), Notifications (process with AI), Pipeline (end-to-end demo), and Settings (API configuration). Built with Expo Router, a Cal.com-inspired design system, and typed API client with timeout handling.
Tech Stack
| Layer | Technology |
|---|---|
| Notification Fetching | Python + adbutils + Android ADB |
| AI Processing | OpenRouter API (poolside/laguna-m.1) |
| Calendar Integration | Google Calendar API (OAuth 2.0) |
| Backend API | Flask + flask-cors + flask-limiter |
| Frontend | Expo SDK 56 + React Native + TypeScript |
| Package Management | uv (Python) + npm (TypeScript) |
| Optional Speedups | Cython (compiled .so extensions) |
What We Learned
ADB & Android Internals
None of us had ever interacted with an Android device at the system level before. Learning to use adb shell dumpsys notification to extract the raw notification dump and then parsing it with regex was completely new territory. We learned about Android's notification record format, package naming conventions, and how different OEM skins (Samsung, Xiaomi) format their dumpsys output differently. The deduplication system (tracking seen notification IDs in a persistent file) was a direct result of discovering that dumpsys returns the same notifications across multiple polls.
Google APIs & OAuth
Integrating with Google Calendar meant diving into the Google API Python client, understanding OAuth 2.0 flows (installed app vs. web server), and handling token refresh. We learned the hard way that credentials.json must be kept out of version control, and that the first run requires an interactive browser-based OAuth consent screen which doesn't work on headless servers.
AI Prompt Engineering
Getting an LLM to return structured, validated JSON from freeform notification text was harder than expected. We iterated on the system prompt dozens of times, teaching the model to resolve relative dates ("tomorrow", "next Monday"), distinguish between schedulable and non-schedulable messages, and always include the is_schedulable boolean. The model occasionally wraps output in markdown fences (`json) or hallucinates fields, so we built a validation layer that catches and rejects malformed responses.
Unix Pipeline Philosophy
Designing each module to read from stdin and write to stdout composable with the pipe operator (|) was one of the best decisions we made. It meant we could test each stage independently, swap out components, and reuse the same code in both CLI and HTTP contexts without duplication.
Cython & Performance
We explored compiling CPU-bound utility functions (fingerprinting, schema validation) to C extensions using Cython. The learning: not every project benefits from compilation. When your bottleneck is I/O (ADB USB latency, HTTP API calls), Cython's CPU acceleration makes a negligible difference. We kept the infrastructure in place as an optional optimization, but the real lesson was to profile before optimizing.
Challenges We Faced
Lack of Information
This was our biggest obstacle. Android's dumpsys notification output is not documented as a public API. it's an internal debugging tool whose format varies wildly across Android versions and manufacturers. We spent hours trial-and-erroring regex patterns against raw dumpsys output, only to discover they broke on a friend's Samsung phone. In the end, we decided to ask our 'friend' AI. The Google Calendar API documentation, while extensive, assumes familiarity with OAuth 2.0 and the Google API client library patterns. There's a steep learning curve for first-timers especially our group.
The OpenRouter/OpenAI API was more straightforward, but prompt engineering for structured output required reading through community discussions and experimenting with different model personalities.
Miscommunication
Working as a small team with different experience levels meant that assumptions didn't always align. Some would architect a solution assuming a certain data format, and the frontend would be built against a slightly different expectation. We learned to:
- Agree on JSON schemas before writing code — we now define the exact shape of every API request and response upfront
- Write tests that serve as living documentation —
test.pynot only validates the pipeline but also demonstrates the expected data shapes - Use TypeScript interfaces that mirror the backend schemas — the frontend types in
services/api.tsare a direct reflection of what the Flask API returns
Debugging Across Layers
A bug could be in any of four layers: ADB extraction → AI processing → Calendar API → Frontend rendering. Tracing an issue through the full stack meant checking ADB connectivity, OpenRouter API quotas, Google OAuth token expiry, and React state management but sometimes all at once. We addressed this by adding structured logging at every layer and building the test suite to isolate each stage.
Real Device Testing
The ADB notification extraction only works with a physical Android phone connected via USB. This meant we couldn't test in CI/CD. Every change to get_notif.py required plugging in a phone and manually triggering notifications. We built the --mock flag in test.py and the seed messages in the Expo pipeline screen specifically to enable development without a phone attached. Yeah, it HAS flaws. But we dont hide it, instead we are planning to find an alternative if we were given the chance.
What's Next?
- Background service — Run the notification polling as a daemon instead of on-demand
- Multi-calendar support — Let users choose which Google Calendar to add events to
- Notification filtering — Allow users to whitelist/blacklist specific apps
- Push to phone — Instead of pulling via ADB, build an Android app that pushes notifications directly
- Web dashboard — A proper web UI for viewing and managing scheduled events
- Kotlin migration — Maybe even change to kotlin for android apk if possible
Built with ☕, late nights, and a lot of adb logcat by **BooTheMeg Group.
Log in or sign up for Devpost to join the conversation.