Skip to content
phunguyen1006Public

About

Automatic study-time tracker. Don't start a timer, just study - a local-first desktop web app that reads ActivityWatch activity, classifies it into subjects and turns it into learning analytics.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

25 Commits

Folders and files

Repository files navigation

StudyOS

Don't start a timer. Just study.

StudyOS is an automatic study-time tracker for students. Instead of requiring you to manually start and stop timers, it reads computer activity from your existing ActivityWatch installation, figures out which activity is actually studying, classifies it into subjects, merges it into meaningful study sessions, and turns the result into useful learning analytics.

ActivityWatch            StudyOS
   (sensor)        →     (brain)              →        UI
         raw activity        classification        dashboard / timeline

StudyOS is local-first and private: everything runs on your machine, the raw data stays in a local SQLite database, nothing ever leaves your computer.

Status: Phases 1–5 mostly done. The full pipeline works end-to-end with tests: ActivityWatch → classification → sessions → SQLite → local web UI (dashboard, timeline, manual timer, subjects, rules, analytics, settings, weekly review). The UI is a PWA installable on iPhone/desktop, and a Tauri desktop shell is included for Windows. Statistics auto-sync in the background and you get a notification when a goal is reached. An optional AI learning mode (Phase 5) lets Google Gemini propose new classification rules for activity that is still unclassified.

Dashboard (dark)


Quick start

.\run.bat

That starts the backend and the web UI, then opens http://localhost:4173 in your browser. On Windows you can also run the Tauri desktop app instead (see below). To auto-start StudyOS every time you log in, place a shortcut to run.bat in your Startup folder (shell:startup), or install with the desktop bundle which registers an app you can launch anytime.

Requirements

  • Windows / macOS / Linux with Python 3.12+
  • ActivityWatch running locally (default API at http://127.0.0.1:5600) with at least the window and afk watchers

Setup (development)

python -m venv .venv
.venv\Scripts\pip install -r backend/requirements.txt

Run

cd backend
..\.venv\Scripts\python.exe -m uvicorn studyos.api.main:app --port 8765

Then visit http://127.0.0.1:8765 (OpenAPI docs at /docs).

Hot reload during development:

..\.venv\Scripts\python.exe -m uvicorn studyos.api.main:app --port 8765 --reload

Frontend (development)

cd web
npm install
npm run dev

Then visit http://localhost:5173. The Vite dev server proxies /api to the backend at http://127.0.0.1:8765, so keep the backend running (see above).

Production build:

cd web
npm run build

Desktop app (Tauri)

# one-time prerequisites: Rust (rustup) + Visual Studio Build Tools (VC++ workload)
# 1. build the standalone backend binary (bundles the API + a Python runtime):
.\.venv\Scripts\pyinstaller.exe --onefile --name studyos-backend --paths backend --distpath desktop\src-tauri\resources --workpath "$env:TEMP\studyos-pyi" --specpath "$env:TEMP\studyos-pyi" backend\launcher_desktop.py
# 2. build the installer (embeds the web UI + the backend binary):
cd desktop
npx @tauri-apps/cli@latest build   # produces StudyOS_<version>_x64-setup.exe (+ .msi)
# 3. copy the installer to the release folder (outside the repo):
Copy-Item src-tauri\target\release\bundle\nsis\StudyOS_*_x64-setup.exe C:\Users\nguye\Documents\GitHub\studyos-release\

The installed app is fully standalone: it embeds the web UI and starts the backend itself, so it needs no Python, Node or the repository. Data lives in %APPDATA%\com.studyos.desktop\studyos.db (existing dev data is migrated on first run). A "StudyOS" shortcut in the Startup folder starts it automatically at login.

Run tests

.\.venv\Scripts\python.exe -m pytest backend

Windows note: if your %TEMP% directory is locked (e.g. leftover pytest-of-* folder with broken ACLs), pass an explicit temp dir:

.\.venv\Scripts\python.exe -m pytest backend --basetemp=backend/.pytest_tmp

Architecture

Activity data flow (Phase 1):

 ActivityWatch REST API
        │  GET /api/0/buckets/.../events
        ▼
 ActivityWatchClient (studyos/aw)          graceful if AW is stopped
        ▼
 normalize (studyos/normalize)             app / title / domain extraction,
                                           overlap clipping, AFK subtraction
        ▼
 Classification engine (studyos/classification)
        │  deterministic rules only (no AI), user rules beat system rules
        ▼
 Session builder (studyos/sessions)        merge events per subject,
        │  short gaps, distraction accounting, AFK excluded
        ▼
 SQLite (studyos/models + studyos/db)      subjects, rules, events, sessions

Backend layout:

Module Responsibility
studyos/aw/client.py thin ActiveWatch REST client (never crashes when AW is down, reports aw_connected instead)
studyos/normalize.py ActivityWatch event → normalized event; domain extraction; overlap clipping; AFK interval math
studyos/classification/ deterministic rule engine + built-in (system) rules
studyos/sessions/builder.py merges classified events into study sessions
studyos/services/ingest.py the sync pipeline: fetch → normalize → classify → rebuild sessions
studyos/api/ FastAPI app with health / sync / events / sessions / subjects / rules / unknown-classification endpoints

Core endpoints

Method Path Purpose
GET /api/health server + ActivityWatch connection state
POST /api/sync run the ActivityWatch → sessions pipeline
GET /api/sessions study sessions (filterable by time / subject)
GET /api/sessions/{id} session detail with its activity breakdown
GET /api/events raw normalized events
GET /api/unknown unknown activity, grouped for review
POST /api/events/{id}/classify manually classify + optional "remember" rule
CRUD /api/subjects, /api/rules manage subjects and classification rules
GET /api/ai/status AI learning state (enabled, model, key hint, last run)
POST /api/ai/classify run the AI learning pass on demand

Classification model

Every normalized event is classified as exactly one of:

  • study — belongs to a subject (builds sessions),
  • non-study — e.g. entertainment (never enters a session),
  • distraction — counted inside a session but not as study time,
  • ignore — invisible to StudyOS,
  • unknown — awaiting a manual decision (see /api/unknown).

Rules are (app / title / domain) → outcome conditions with an explicit priority. Lower priority number wins. Built-in system rules start at priority 10000, so any user rule overrides the defaults.

"Remember this classification" teaches StudyOS: it stores a user rule from your manual choice and the next sync applies it to matching historical events as well.

AI learning (optional, Phase 5). When enabled with a Gemini API key, StudyOS collects window activity that still matches no rule, asks the model which subject it belongs to (or whether it is a distraction etc.), and stores new rules automatically — named ai: … — once a suggestion clears the confidence threshold. Runs in the background at most once an hour plus on demand from Settings, and only after a successful sync.


Privacy model

  • StudyOS never collects keystrokes, passwords, clipboard, screenshots, microphone, or camera data.
  • All data is stored locally (SQLite file in backend/data/).
  • ActivityWatch itself is the only activity sensor, also fully local.
  • Blacklist controls for apps/domains, plus raw-activity retention limits (both configurable in the Settings page).
  • AI learning is off by default: nothing is sent anywhere until you paste your own Gemini API key. Then only the app/title strings of still unclassified windows leave your machine (to Google's API, only as long as needed), and yours — not StudyOS's — is the account behind that call. The key is kept in your local database, write-only: it is never shown in the UI, never returned by the API, and never pinged to any other service.

Roadmap

  • Phase 1 — done: ActivityWatch integration, classification, session builder, SQLite, API, tests.
  • Phase 2 — done: web UI (dashboard, timeline, manual timer, session editing, subject and rule management).
  • Phase 3 — done: analytics (daily/weekly/monthly/yearly stats, goals, weekly review, streaks, study heatmap, focus & distraction metrics).
  • Phase 4 — done: PWA install, privacy controls (per-app/domain blacklists, raw-activity retention), background auto-sync with goal notifications, Tauri desktop shell for Windows.
  • Phase 5 — done: optional AI learning (Gemini) that proposes new classification rules from still-unclassified activity, with a confidence threshold, on-demand runs, and write-only key storage.

Out of scope: calendars, cloud sync, accounts, social features, TODOs, notes, flashcards.

About

Automatic study-time tracker. Don't start a timer, just study - a local-first desktop web app that reads ActivityWatch activity, classifies it into subjects and turns it into learning analytics.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages