Track your screen time. Own your data. No cloud required.
focusd.0xarchit.is-a.dev
Focusd is a native Windows screen time tracker and digital wellbeing tool written in Go. A lightweight background daemon (focusd_daemon.exe) polls the foreground window via Win32 syscalls and records per-app and per-browser-tab usage into a local SQLite database. A separate CLI/TUI binary (focusd.exe) renders dashboards, manages limits, and controls the daemon over a local TCP IPC channel.
It functions as an app usage monitor, browser time tracker, Pomodoro focus timer, and productivity dashboard — all in one under-12 MB binary with no runtime dependencies. If you're looking for a free alternative to RescueTime, StayFree, or Toggl Track that keeps your data local, focusd is built for that.
Nothing leaves your machine. The only network traffic is the optional update check against the GitHub Releases API.
| App | Installer / Disk Size | RAM Usage (Idle) | Tech Stack |
|---|---|---|---|
| StayFree (Windows) | ~164 MB | 150 – 400 MB | likely Electron / UWP |
| Toggl Track | ~100 MB | 200 – 500 MB | Electron (Chromium bundled) |
| RescueTime (Classic) | ~25 MB | 20 – 50 MB | Native C++ / Qt |
| Focusd | < 12 MB | ~10 – 25 MB | Go (Native Win32 syscalls) |
| Problem | How focusd solves it |
|---|---|
| Screen time trackers that send your data to the cloud | All data stays in a local SQLite database — no accounts, no telemetry |
| Heavy Electron-based trackers (100-400 MB RAM) | Under 12 MB installer, 10-25 MB RAM idle, native Win32 syscalls |
| No visibility into browser tab usage | Tracks time per tab via window title, groups 70+ sites automatically |
| No way to limit distracting apps | Set daily per-app time limits with notifications |
| Hard to stay focused | Built-in Pomodoro timer with break reminders |
PowerShell (recommended):
iwr "https://github.com/0xarchit/focusd/releases/latest/download/focusd_setup.exe" -OutFile focusd_setup.exe; ./focusd_setup.exeCommand Prompt:
curl -L -o focusd_setup.exe "https://github.com/0xarchit/focusd/releases/latest/download/focusd_setup.exe" && focusd_setup.exeThe NSIS installer (installer.nsi) installs both binaries to %APPDATA%\focusd, adds the install directory to your user PATH, registers focusd_daemon.exe under the HKCU\...\Run autostart key, registers an entry in Add/Remove Programs, and immediately launches the daemon.
Open a new terminal and type focusd to launch the TUI.
Launching focusd with no arguments opens a Bubble Tea / Lipgloss terminal UI with five tabs: Dashboard, Stats, Focus, Limits, Settings. Mouse and alt-screen are enabled; minimum terminal size is 80×24. Press ? for the full key-binding overlay.
focusd_daemon.exe is built with the -H=windowsgui linker flag so it runs with no console window. It polls the active window every 5 seconds (configurable 1–60s), batches sessions to SQLite every 5 minutes, persists the active session every 5 minutes (so a crash recovers cleanly), enforces retention every hour, and checks Pomodoro / break / app-limit conditions every 5 seconds.
The daemon reads the foreground window's title and process executable using GetForegroundWindow, GetWindowTextW, and GetModuleBaseNameW. App sessions are written to the sessions table; daily totals are upserted into apps_daily. When the foreground process is a recognised browser, the cleaned window title (not URL) is upserted into browsing_daily.
Tab titles are matched against ~74 hard-coded URL/title patterns in core/app_groups.go and grouped under a parent category (YouTube, GitHub, LeetCode, ChatGPT, Claude, Notion, Figma, AWS, Coursera, Discord, Gmail, Reddit, etc.). Sub-entries are listed under each category in stats output.
chrome, firefox, msedge, brave, opera, vivaldi, waterfox, arc, iexplore, safari, whale, yandex, thorium, librewolf, chromium, floorp, zen. Add others with focusd browser add <name>.exe.
File-backed timer at %APPDATA%\focusd\pomodoro.json so state survives across processes. Default 25 minutes; configurable. Completion is announced through a Win32 MessageBoxW notification with a 10-second cooldown.
When enabled, the daemon notifies after a configurable number of minutes of continuous use (default 60). The reminder can be snoozed for the global snooze duration (default 60 min).
Set per-executable limits (focusd limit chrome.exe 60). The daemon notifies once when the day's usage exceeds the limit; the snooze button suppresses repeats for the snooze window. Limits reset at local midnight.
Whitelisted executables are skipped entirely by the tracker (never recorded).
Export tracking data to CSV or JSON from the TUI Settings tab. Files are saved to %USERPROFILE%\Desktop. You can also open the SQLite database directly at %APPDATA%\focusd\focusd.db.
focusd update queries api.github.com/repos/0xarchit/focusd/releases/latest, downloads focusd_setup.exe for that tag, verifies its SHA-256 against checksums.txt, then invokes the installer silently (/S) with a UAC elevation prompt via ShellExecute("runas"). The daemon is stopped before install and restarted afterwards.
focusd Launch interactive TUI (default)
focusd start Start the background daemon
focusd stop Stop the daemon (graceful via IPC, falls back to kill)
focusd status (s) Daemon + tracking status with today's top 5 apps
focusd stats (st) Full daily breakdown: top apps + grouped browsing
focusd pause (p) Pause tracking (daemon keeps running, drops samples)
focusd resume (r) Resume tracking
focusd focus [min] Start a Pomodoro timer (default 25 min)
focusd stop-timer Stop the running Pomodoro
focusd limit <app> <min> Set a daily time limit (omit args to list)
focusd update Check for and install updates
focusd help (h) Show built-in help
focusd version (-v) Print version
focusd retention status Show current retention window
focusd retention set <days> Set retention (1–30, default 7)
focusd retention reset Reset retention to default
focusd autostart status Show autostart state
focusd autostart enable Add daemon to HKCU\...\Run
focusd autostart disable Remove daemon from HKCU\...\Run
focusd path status Show whether install dir is on PATH
focusd path enable Append install dir to user PATH
focusd path disable Remove install dir from user PATH
focusd browser list Show user-defined browsers
focusd browser add <exe> Add a custom browser executable
focusd browser remove <exe> Remove a custom browser
focusd --daemon is the entry the daemon binary uses to enter its tracker loop; you should not invoke it directly.
┌─────────────────┐ TCP 127.0.0.1:48321 ┌──────────────────────┐
│ focusd.exe │ ────── "stop" / ──────► │ focusd_daemon.exe │
│ (CLI + TUI) │ ◄──── "flush" / "ok" ── │ (windowsgui, no UI) │
└────────┬────────┘ └──────────┬───────────┘
│ │
│ reads / writes │ reads / writes
▼ ▼
┌────────────────────────────────────────────────────────────────────┐
│ %APPDATA%\focusd\ │
│ focusd.db (SQLite WAL) config.json browsers.json │
│ pomodoro.json │
└────────────────────────────────────────────────────────────────────┘
| Package | Purpose |
|---|---|
cmd/focusd |
Entry point for the CLI/TUI binary. Calls system.AttachParentConsole, system.CleanupOldBinary, then cli.Run. |
cmd/focusd_daemon |
Entry point for the silent daemon. Calls cli.RunDaemon. |
cmd/release_notes |
Build-time helper that generates release_notes.md from git log via the GitHub Models API. |
cli |
Command parsing, interactive menu, update flow, status / stats / export commands. |
core |
Tracker loop, IPC server/client, app classification, browser-tab grouping, title cleaner, Pomodoro state, notifications. |
storage |
SQLite schema and queries, retention enforcement, browser registry, durable config. |
system |
All Windows-specific code: Win32 syscalls (user32, kernel32, psapi), process enumeration, registry (autostart + PATH), user-config file, daemon process spawn. Stubs exist for non-Windows builds so go build still passes on other OSes (the daemon refuses to run). |
tui |
Bubble Tea / Lipgloss model, splash, tabs, dashboard, stats, focus, limits, settings panels. |
ui |
ANSI colours, table renderer, duration formatter for the classic CLI commands. |
The daemon listens on 127.0.0.1:48321 and accepts two text commands:
| Command | Effect |
|---|---|
stop |
Acknowledge with ok, flush state, exit. |
flush |
Close the current session, write batched sessions, persist active-session checkpoint, reply ok. |
The CLI calls flush before reading stats so reports never miss the in-flight session.
| Ticker | Interval | What it does |
|---|---|---|
pollTicker |
5s (configurable) | Sample the foreground window |
batchTicker |
5 min | Write batched sessions to SQLite |
persistTicker |
5 min | Snapshot the active session for crash recovery |
retentionTicker |
1 hour | Delete rows older than retention window |
focusTicker |
5s | Pomodoro completion, break reminders, app-limit notifications |
Everything lives under %APPDATA%\focusd\.
| File | Contents |
|---|---|
focusd.db |
SQLite database (WAL mode, incremental autovacuum, NORMAL synchronous) |
config.json |
User config: whitelist, app limits, Pomodoro minutes, break reminder, snooze duration, custom browsers |
pomodoro.json |
Current Pomodoro state (active flag, start time, duration, notified flag) |
config (key, value, updated_at)
sessions (id, app_name, exe_name, window_title, start_time, end_time, duration_secs, date)
apps_daily (id, date, app_name, exe_name, total_duration_secs, open_count) -- UNIQUE(date, exe_name)
browsing_daily (id, date, domain_or_title, total_duration_secs, open_count) -- UNIQUE(date, domain_or_title)
active_session (id=1, app_name, exe_name, window_title, start_time, last_seen, date)Indexes: idx_sessions_date, idx_sessions_start, idx_apps_daily_date.
| Setting | Default | Range |
|---|---|---|
| Retention (days) | 7 | 1 – 30 |
| Tracking poll interval (s) | 5 | 1 – 60 |
| Pomodoro (min) | 25 | > 0 |
| Break reminder (min) | 60 | > 0 |
| Snooze (min) | 60 | > 0 |
HKCU\Software\Microsoft\Windows\CurrentVersion\Run\focusd— autostart entry (full quoted path tofocusd_daemon.exe).HKCU\Environment\Path— append-only modification of user PATH.HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\Focusd— written by the NSIS installer for Add/Remove Programs.
focusd is built for privacy by design:
- No telemetry. The only network call is
GET https://api.github.com/repos/0xarchit/focusd/releases/latestwhen you runfocusd update(and the subsequent download fromgithub.comif you confirm). Grep forhttp.if you don't believe it. - Local-only storage. All data lives in
%APPDATA%\focusd\focusd.db. The SQLite file is standard; query it with any SQL tool. - Titles, not URLs. Browser tracking records the window title only. There is no browser extension, no HTTP interception, no DNS sniffing.
- Whitelist & pause give you full control. Whitelisted executables are never recorded.
- No background privilege. Both binaries run under your user account. The only elevation request is for the auto-updater (NSIS installer needs admin to write to
%APPDATA%files held by the running daemon). - Open source. Full source code available. Audit it yourself.
Requirements: Go 1.26+, Windows (the daemon only runs on Windows). NSIS is required to build the installer.
git clone https://github.com/0xarchit/focusd.git
cd focusd
# CLI / TUI binary
$env:CGO_ENABLED = "0"
go build -ldflags="-s -w -X 'focusd/system.Version=dev-build'" -trimpath -o focusd.exe ./cmd/focusd
# Silent background daemon
go build -ldflags="-s -w -H=windowsgui -X 'focusd/system.Version=dev-build'" -trimpath -o focusd_daemon.exe ./cmd/focusd_daemon
# NSIS installer (optional)
makensis /DVERSION=dev-build installer.nsiReplace dev-build with the release version. The -X 'focusd/system.Version=...' ldflag is read at runtime by focusd version and the update checker.
| Workflow | Trigger | Output |
|---|---|---|
.github/workflows/release.yml |
Push of a vX.Y.Z tag |
Builds both binaries, NSIS installer, SHA-256 checksums.txt, AI-generated release notes via GitHub Models (gpt-4o-mini), publishes a GitHub Release. |
.github/workflows/test_build.yml |
Push to test branch |
Builds an unsigned dev installer, uploads as a 5-day artifact. |
.github/workflows/deploy-site.yml |
Push to main/master touching website/** |
Deploys the static site under website/ to GitHub Pages (focusd.0xarchit.is-a.dev). |
Use Settings → Apps → Installed apps → Focusd → Uninstall, which invokes the NSIS uninstaller. It stops the daemon, removes the binaries, deletes the autostart registry entry, and removes the install directory from your user PATH.
To delete your usage history as well, remove %APPDATA%\focusd\ manually after uninstalling.
Contributions welcome. See CONTRIBUTING.md and CODE_OF_CONDUCT.md. Security issues: see SECURITY.md.
MIT License — see LICENSE.
Built by @0xarchit