# Patina: local-first Windows time tracking built with Tauri and React

> Patina records foreground app usage into a local SQLite database on Windows 10 and 11, with idle, lock and sleep boundaries handled in Rust. Here is what it does, how to build it, and where it stops.

**Ceceliaee/patina** — A beautiful Windows desktop time tracking app built with Tauri & React.

- Repository: https://github.com/Ceceliaee/patina
- Stars: 533 · Forks: 26
- Language: TypeScript
- License: MIT
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/ceceliaee-patina

## The problem Patina solves for Windows desktop workers

Manual timers fail for a simple reason: the work you want to measure is the work you forget to start a timer for. Patina's answer is to remove the start and stop decision entirely. The README describes it as recording "foreground app usage as local, quiet, and trustworthy personal desktop time records." There is no account, no cloud sync and no server dependency in that description, and the Current Scope section repeats the boundary: personal local data storage, automatic tracking, review, classification, backup and restore.

The audience is narrow on purpose. Patina targets Windows 10 and 11 desktop use by one person on one machine. The README explicitly says it is not aimed at team collaboration, account systems, cloud sync, multi-platform sync or heavy AI insights. If you are shopping for a tool that produces a shared dashboard for a five-person team, this is the wrong category of software and no amount of configuration will change that.

The interesting part is the word "trustworthy." Anyone can log the window title that has focus every second. The hard part is deciding which of those seconds count as effective activity. Patina's feature list is mostly a list of boundary cases: idle, lock, sleep, resume, long-away periods and abnormal exits. That framing is the project's actual thesis.

## How Patina turns foreground windows into effective-duration records

The stack is visible from the README and the repository layout. The desktop shell is Tauri v2, the backend is Rust, the frontend is React with Vite and TypeScript, styling is Tailwind CSS, animation is Framer Motion, charts are Recharts, and the database is SQLite accessed through `@tauri-apps/plugin-sql`. Windows integration comes from the `windows` crate. That last detail matters: the foreground-window detection is not a portable abstraction, it is Windows API work in Rust.

The data flow implied by that stack runs one way. The Rust side watches the foreground window and produces activity events. Those events are written into SQLite. The React frontend reads them back and renders the overview, timeline, trends, heatmaps and app curves. The `tests/` directory contains files named `trackingLifecycle.test.ts`, `trackingReplay.test.ts` and `historyReadModel.test.ts`, which suggests the tracking logic is separated from the UI and can be replayed against recorded event sequences. That is a reasonable design for a program whose correctness depends on edge cases rather than on rendering.

The reliability section names the boundaries directly: idle time does not continue counting as effective activity; lock, sleep, resume, long-away and abnormal exits each get boundary handling; rankings, distributions and totals use effective activity time rather than open spans. Window title capture can be disabled per app, which the README frames as reducing retention of sensitive information. Separately, Patina Web Sync is a browser extension published for Chrome, Firefox and Edge that "adds specific webpage details to browser activity." It is optional and lives in its own repository.

## Installing Patina and building it from source

For most users the README points at the releases page rather than a source build. The Download section links to `https://github.com/Ceceliaee/patina/releases/latest`, and the current release listed is v1.9.4 from 2026-08-13. The README does not document a package manager install, so there is no `winget` or `scoop` command to quote here.

If you want to run or modify the source, the README gives three steps. First clone and install dependencies with npm:

```bash
git clone https://github.com/Ceceliaee/patina.git
cd patina
npm install
```

Then start the development build. This launches the Tauri shell with the Vite frontend attached:

```bash
npm run tauri dev
```

To produce an installer, run the build command. The README states the output lands under `src-tauri/target/release/bundle/`:

```bash
npm run tauri build
```

There is a discrepancy worth knowing before you start. The README's Requirements section lists Rust and Node.js 18+, but `package.json` pins `engines.node` to `24.21.0` and `engines.pnpm` to `12.3.4`, and the repository ships a `pnpm-lock.yaml` and `pnpm-workspace.yaml` rather than a `package-lock.json`. The README's install step uses `npm install` while the lockfile is pnpm's. Expect to reconcile those two before a clean build, and check `CONTRIBUTING.md`, which the README says to read first for product direction and architecture boundaries.

## Where Patina's scope ends: platform, privacy and title capture

The most concrete limitation is platform. Patina is Windows 10 and 11 only, and the Windows integration is a Rust crate dependency rather than a plugin boundary. There is no macOS or Linux build described anywhere in the README, and the Current Scope section lists Windows desktop use as the first bullet. If your team is mixed-platform, Patina covers part of it.

The second limitation is structural rather than a bug. Automatic foreground tracking means Patina sees the title of whatever window you are in, and window titles are frequently the most sensitive string on your screen: document names, patient records, customer names, private repository paths. The README offers a per-app switch to disable title capture, and describes the default as keeping data local. Local is not the same as invisible. Anything running as your user on that machine, including backup software and malware, can read the SQLite file. The README does not describe encryption at rest, and it does not describe what happens to the database if you uninstall the app.

The third is the boundary handling itself. The README claims idle, lock, sleep and abnormal-exit handling reduce invalid time and accidentally merged records. Those claims are the kind that only hold for the specific edge cases the author tested. A laptop that sleeps mid-video, a remote desktop session, or a virtual machine window will each exercise different paths, and the README does not publish a compatibility list. The `tests/` directory names suggest lifecycle and replay coverage exists, but the README does not state what those tests assert.

## Patina compared with self-hosted time trackers like ActivityWatch

The obvious alternative in the same category is ActivityWatch, which is also open source, also local-first, and also records foreground window activity without manual timers. The difference is in the approach to platforms and extensibility. ActivityWatch is built around a watcher and bucket model with a Python core and a documented local API, and it has watchers for multiple operating systems. Patina is a single Tauri binary with a Rust backend and a React frontend, and it is Windows only.

That difference cuts both ways. If you want one tool across a Windows laptop and a Linux desktop, or you want to write your own watcher against a documented HTTP API, ActivityWatch is the better fit and Patina cannot substitute for it. If you want a self-contained Windows installer with no Python runtime, a fixed set of views, and no plugin surface to maintain, Patina's shape is simpler. There is no plugin API documented in the README, which means less to configure and also less to extend.

A second, less obvious comparison is with browser-only trackers. Patina Web Sync covers browser activity detail, but it is an add-on to the desktop app rather than a standalone product, and the README treats it as optional. If all your work happens in a browser, a browser extension may be enough on its own; Patina's value is in the desktop apps that a browser extension cannot see.

## Maintenance, releases and the MIT licence

The repository is not archived and the last push was on 2026-08-13, which is the same day as the v1.9.4 release. The release cadence in the listed history is tight: v1.9.2 on 2026-08-05, v1.9.3 on 2026-08-10, v1.9.4 on 2026-08-13. Three releases in eight days is a burst, not a long-run average, so treat it as evidence of current activity rather than a forecast. `package.json` shows version 1.9.6, which is ahead of the latest listed release tag; if you build from `main` you are building code that has not been tagged.

Upgrade cost is the part the README is silent on. It documents exporting local backups, restoring backups, and cleaning up historical records, and it documents building installers, but it does not describe a migration path between releases or a schema version for the SQLite database. The practical consequence: export a backup before installing a new version, because the README does not promise that an older database opens in a newer build. There is also no documented rollback procedure.

The licence is MIT, which is permissive and places few conditions on reuse or redistribution beyond preserving the notice. That is a statement about the licence text, not legal advice, and it says nothing about the separate Patina Web Sync extension, whose repository and licence are not described in the README. The README also accepts sponsorship through Ko-fi and a WeChat reward, and states that sponsorship does not affect feature priority, issue handling, the roadmap or the product direction.

## Conclusion

Adopt Patina if you work on a single Windows 10 or 11 machine and want foreground app records that stay in a local SQLite file you can back up yourself. Do not adopt it if you need macOS or Linux coverage, team dashboards, or cloud sync, because the README states the project is not aimed at those. Before installing, check CONTRIBUTING.md for the architecture boundaries and confirm the v1.9.4 release asset matches your Windows architecture. The one thing to verify on your own hardware is how Patina classifies your specific video, meeting and livestream apps, since the README claims low-interaction scenarios are handled but does not list which apps it has validated.

## FAQ

### Is Patina available for macOS or Linux?

No. The README lists Windows 10 and 11 desktop use as the first item under Current Scope, and the Windows integration is handled through the `windows` crate in the Rust backend. No macOS or Linux build is described.

### Does Patina send my time tracking data to a server?

The README describes Patina as local-first with no account, cloud sync or server dependency, and says core data stays local with backups, restores and history cleanup initiated by the user. The database is SQLite accessed through `@tauri-apps/plugin-sql`, which is a local file.

### What do I need to build Patina from source?

The README lists Rust and Node.js 18 or later, then `npm install`, `npm run tauri dev` to run in development, and `npm run tauri build` to produce an installer under `src-tauri/target/release/bundle/`. Note that `package.json` pins Node to 24.21.0 and pnpm to 12.3.4, while the README's install step uses npm.

### Can Patina track browser activity in detail?

Not by itself. The README describes Patina Web Sync as a separate extension for Chrome, Firefox and Edge that adds specific webpage details to browser activity, and says to install it as needed. The desktop app records foreground apps.

## Sources

- [Official README](https://github.com/Ceceliaee/patina#readme)
- [Project repository](https://github.com/Ceceliaee/patina)
- [Release notes](https://github.com/Ceceliaee/patina/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ceceliaee-patina
