log(ger)

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.

Kaiwen Bian · Yuer Tang · Jiaying Chen

Local-first · Mac native. Runs as a real .app on your machine — your database stays in ~/Library/Application Support/Logger/. No cloud, no accounts. Build & launch instructions ↓

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.

log(ger) — Spring 2026
Good afternoon
Monday · May 25
Spring 2026 · active
Today's Total
0m
Entries Today
0
Current Streak
0d
Quick Start
Salk Research
Salk Research 00:14:32
Analytics · this quarter
Salk COGS PP Training
Group → Family → Category
Research
Salk
MPI
SWL
Courses
COGS
DSC
Training
Training
Ask your own data
How much research time this quarter?
In Spring 2026 you've logged 52h 15m of research — 41% on Salk lab work and 32% on TopoMIMIC. Peak day: April 22 with 6h 40m.
Dashboard Analytics Hierarchy Chat

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.

1

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.

2

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.

3

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.

Group
Research Training Personal Courses
Family
Salk MPI SWL FMP PP COGS CSE DSC
Category
Salk · Spring 2026 COGS 118C · Winter 2026 Training · Fall 2024 PP · Summer 2024 + many more

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.

SOURCE

Timer or manual entry

You log time against a category. Minutes accumulate.

AGGREGATE

Observations & daily totals

The DB rolls up entries into per-day-per-category numbers.

SHAPE

Group · Family · Category

Same numbers, indexed three ways. Same data, three lenses.

SURFACE

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.

Recommended

🖥️ 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.
For hackers

🌐 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