Track time like you mean it. A personal productivity tracker that replaces spreadsheets with real-time timers, hierarchical organization, and an AI assistant that can answer questions about your own time.
What it is
log(ger) is for people who care enough about their time to track it — students, researchers, makers — but who never want to feel like they’re doing data entry. You hit start, you do the work, you hit stop. Everything else — the dashboards, the streaks, the project-progression view, the natural-language Q&A — flows from the same simple act.
The previous version of this idea lived in Chatable-Study-Database — three years of CSV files, a Jupyter notebook, and a homemade RAG pipeline. It worked, but every quarter cost an hour of column-formatting and asking simple questions cost a pandas query. log(ger) closes that loop into a single web app.
See it in two minutes
Watch a full workflow: starting a session, logging time with timers, adding entries by hand, browsing analytics, and asking the chat about your own data.
The clip above is an in-page mockup, not a real screen recording. The actual app looks the same — clone the repo and run it locally to see your own data flowing through these screens.
The daily workflow
Three things, in order. Everything else is on top.
Start a session
A session is a window of time you care about together — usually an academic quarter or a work cycle. You pick the year and the season, the app figures out the date range, and that’s the bucket all your data lands in. Returning users can import a CSV instead of starting fresh.
Log time as it happens
Hit play on a category and the timer runs. Pause for breaks, resume when you’re back, stop when you’re done — you get prompted for a description and location at the end. Forgot to start a timer earlier today? Drop in a Manual Entry with a date and minutes. Both produce the same kind of data.
Get answers, not data
The Analytics page lets you slice your time at every scale — today, this week, this session, all-time, by category or by family. The Chat page lets you skip charts entirely and just ask. The Projects page tells you what each of your ongoing projects looked like quarter-by-quarter.
What you can do
Real-time timers
Start, pause, stop. Run several at once if you need to (a meeting and a recording session in parallel). All timestamps auto-round to the nearest minute so your data stays honest.
Manual entry
The escape hatch for the time you didn’t time. Pick a date, a category, the minutes, and a note. Treated identically to timer data downstream.
Analytics that adapt
Stacked area charts, category breakdowns, weekly heatmaps, side-by-side session comparisons. One control changes the time scale (overall / year / month / week) and every chart re-fits.
Ask your own data
An AI chat tied to Claude that has read-only access to your sessions. Ask “what did I work on most in Spring 2025?” or “summarize my year.” Every API call surfaces a tiny approval card — nothing leaves the app silently.
Projects over time
A bubble visualization where the biggest circles are Groups, the next layer is Families, and the leaves are individual sessions. You can see — literally see — what you actually spent your year on.
Bring your history
If you’ve been tracking time in CSVs already, drag both files (the numbers and the notes) onto the Import page. Column variations across years, BOM bytes, inconsistent header casing — all handled.
How log(ger) organizes time
Most time trackers give you one flat list of tags. That’s fine for a week and catastrophic for a year. log(ger) uses a three-level hierarchy that maps cleanly onto how most people actually think about their work.
A Group is the kind of thing
Research, courses, personal work, training. Four buckets by default; you can add more. This is the level you reason at when you ask “was that a good week?”
A Family is the thread that runs through
Your Salk family is the same project whether you’re in Spring 2025 or Fall 2026. Department codes like CSE are families that catch every course in that department automatically.
A Category is one session’s slice
The actual line item you log against, scoped to one session. The same family lives in many sessions as different categories. Auto-matching means new categories find their family on import.
From a stopwatch to insight
Every feature in log(ger) is downstream of the same simple act: a category accumulating minutes during a session. Here’s what gets built on top.
Timer or manual entry
You log time against a category. Minutes accumulate.
Observations & daily totals
The DB rolls up entries into per-day-per-category numbers.
Group · Family · Category
Same numbers, indexed three ways. Same data, three lenses.
Dashboards · Charts · Chat
Every view is a different cross-section of that same shape.
That’s why adding a new chart or a new question to the chat doesn’t require new logging behavior on your side. The data is the same; the questions are just different cuts of it.
Run it locally
log(ger) runs in two flavors — pick whichever fits. Both use the same code and
the same on-disk database; the only differences are how the UI is served and
whether you get a real .app in your Dock.
🖥️ Mac app
Native window via WKWebView, no terminals after the build, DB at
~/Library/Application Support/Logger/. Double-click to launch.
- Best for using the tool day-to-day.
- One-time build (~30s), then
open dist/Logger.app. - FastAPI + SvelteKit bundled together on one ephemeral port.
🌐 Browser dev mode
Two terminals with hot-reload — backend on :8000, Vite on
:5173. DB at ./logger.db in the repo (separate from the app's data).
- Best for tweaking the code (HMR on Svelte + Python).
- Open http://localhost:5173 in your browser, not the backend port.
- No PyInstaller build needed.
Build the Mac app
Recommended path. Builds from source on your own machine, no external download.
1. One-time prerequisites
brew install uv pnpm node@22
brew unlink node 2>/dev/null
brew link --overwrite --force node@22
uv (Python), pnpm (Node), Node 22.13+ — older Node will fail with
ERR_UNKNOWN_BUILTIN_MODULE: node:sqlite on pnpm install.
The brew link step ensures node --version resolves to 22.
2. Clone & install deps
git clone https://github.com/KevinBian107/logger.git
cd logger
uv sync --project backend --extra macapp
pnpm --dir frontend install
The macapp extra adds pywebview + PyInstaller. The --project backend flag tells uv where pyproject.toml lives.
3. Build the app bundle
pnpm --dir frontend build
uv run --project backend python scripts/build_macapp.py
Output: dist/Logger.app (~65 MB, includes the FastAPI backend + static SvelteKit frontend + a WKWebView shell).
4. Launch
open dist/Logger.app
If Gatekeeper objects on first launch:
xattr -dr com.apple.quarantine dist/Logger.app
Drag the app to /Applications if you'd like it permanent.
First-launch flow. DB is empty on first run. On the Data tab, create a new session (pick a year + season). Add a few categories. Hit play on the dashboard's Quick Start to begin logging. Optional: paste an Anthropic API key in Settings to unlock the AI chat assistant. Have old CSV data? Drop the pair onto the Data tab's Import dropzone.
Or: run in the browser (dev mode)
Pick this path if you're hacking on the code. You skip the PyInstaller build entirely — the backend runs in uvicorn's reload mode and Vite serves the SvelteKit frontend with HMR. Two terminals, both with live-reload.
Terminal 1 — backend on :8000
cd backend
uv sync
uv run uvicorn logger.main:app --reload --port 8000
Terminal 2 — frontend on :5173
cd frontend
pnpm install
pnpm dev
Open the UI
open http://localhost:5173
Open :5173 (the frontend), not :8000 (the backend — that one
returns 404 on / because it only serves /api/*). The Vite dev server
proxies API calls to the backend automatically.
Two databases. Dev mode reads/writes ./logger.db in your
repo checkout; the packaged Mac app reads/writes
~/Library/Application Support/Logger/logger.db. They're independent.
Use Settings → Database → Download current in one mode and
Choose .db file in the other to copy data between them.
Built with SvelteKit, FastAPI, SQLite, D3, PyWebView, and the Claude API. Development was driven by Propel — a structured workflow for AI-assisted coding.
Credits
- Chatable-Study-Database — The Python/Jupyter ancestor. Same goal, less polish.
- Propel — The workflow framework used to build this with Claude Code.
- Code Manual — Methodology notes for AI-assisted development.