Focusd

July 17, 2026 · View on GitHub

Version Build Status Downloads
License Go Platform

focusd icon

Privacy-First Digital Wellbeing for Windows

Track your screen time. Own your data. No cloud required.
focusd.0xarchit.is-a.dev


Overview

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 — a ~9 MB installer with a ~12 MB CLI binary and a ~8 MB daemon, no runtime dependencies. If you're looking for a local, no-account alternative to RescueTime, StayFree, or Toggl Track, focusd is built for that.

Nothing leaves your machine. The only network traffic is the optional update check against the GitHub Releases API.

AppDistributionSync modelAccount required
StayFree (Windows)Microsoft Store (UWP) + Electron desktopCross-device syncYes
Toggl TrackNative C++/.NET desktop client (source)Cloud sync (Toggl account)Yes
RescueTimeNative Windows client + web dashboardCloud sync (RescueTime account)Yes
FocusdStandalone binary (~9 MB installer)None — local SQLite onlyNo

Competitor distribution details come from each vendor's own product pages and repos. RAM figures were dropped from this table because they cannot be reproducibly sourced — measure on your own machine if you need them.


Why focusd?

ProblemHow focusd solves it
Screen time trackers that send your data to the cloudAll data stays in a local SQLite database — no accounts, no telemetry
Trackers that ship a bundled browser or heavy runtimeTwo small native Go binaries (~12 MB CLI, ~8 MB daemon); ~9 MB installer
No visibility into browser tab usageTracks time per tab via window title, grouped under 74 hard-coded categories
No way to limit distracting appsSet daily per-app time limits with notifications
Hard to stay focusedBuilt-in Pomodoro timer with break reminders

Quick Start

PowerShell (recommended):

iwr "https://github.com/0xarchit/focusd/releases/latest/download/focusd_setup.exe" -OutFile focusd_setup.exe; ./focusd_setup.exe

Command Prompt:

curl -L -o focusd_setup.exe "https://github.com/0xarchit/focusd/releases/latest/download/focusd_setup.exe" && focusd_setup.exe

The 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.


Features

Interactive 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.

Background daemon

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.

Per-app and per-browser tracking

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.

Smart browser-tab grouping

Tab titles are matched against 74 hard-coded categories (91 pattern strings) in coreapi/app_groups.go and grouped under a parent (YouTube, GitHub, LeetCode, ChatGPT, Claude, Notion, Figma, AWS, Coursera, Discord, Gmail, Reddit, and so on). Sub-entries are listed under each category in stats output.

Default browser detection

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.

Pomodoro timer

File-backed timer at %APPDATA%\focusd\pomodoro.json so state survives across processes. Default 25 minutes; configurable. Completion is announced through a Windows Toast (Windows.UI.Notifications.ToastNotification, invoked from core/notifications.go via a short PowerShell command). A 10-second cooldown suppresses duplicate toasts.

Break reminders

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).

Daily app time limits

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.

Whitelist

Whitelisted executables are skipped entirely by the tracker (never recorded).

Data export

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.

Auto-update

focusd update queries api.github.com/repos/0xarchit/focusd/releases/latest, downloads focusd_setup.exe for that tag, then invokes the installer silently (/S) with a UAC elevation prompt via ShellExecute("runas"). The daemon is stopped before install and restarted afterwards.

Verification is up to you. The auto-updater does not verify the downloaded installer's SHA-256 at runtime. Each release also publishes a checksums.txt file (SHA-256 of focusd_setup.exe, generated by the release workflow) so you can verify manually before installing.


Commands

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

Subcommands

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.


Architecture

┌─────────────────┐   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                            │
└────────────────────────────────────────────────────────────────────┘
PackagePurpose
cmd/focusdEntry point for the CLI/TUI binary. Calls system.AttachParentConsole, system.CleanupOldBinary, then cli.Run.
cmd/focusd_daemonEntry point for the silent daemon. Calls cli.RunDaemon.
cmd/release_notesBuild-time helper that generates release_notes.md from git log via the GitHub Models API.
cliCommand parsing, interactive menu, update flow, status / stats / export commands.
coreTracker loop, IPC client helpers, app classification, title cleaner, notifications (Windows Toast).
coreapiShared cross-package data: IPC address/constants, browser-tab group definitions, Pomodoro state on disk, aggregation.
storageSQLite schema and queries, retention enforcement, browser registry, durable config.
systemAll 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).
tuiBubble Tea / Lipgloss model, splash, tabs, dashboard, stats, focus, limits, settings panels.
uiANSI colours, table renderer, duration formatter for the classic CLI commands.

IPC

The daemon listens on 127.0.0.1:48321 and accepts two text commands:

CommandEffect
stopAcknowledge with ok, flush state, exit.
flushClose 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.

Tickers inside the tracker loop

TickerIntervalWhat it does
pollTicker5s (configurable)Sample the foreground window
batchTicker5 minWrite batched sessions to SQLite
persistTicker5 minSnapshot the active session for crash recovery
retentionTicker1 hourDelete rows older than retention window
focusTicker5sPomodoro completion, break reminders, app-limit notifications

Data & Configuration

Everything lives under %APPDATA%\focusd\.

FileContents
focusd.dbSQLite database (WAL mode, incremental autovacuum, NORMAL synchronous)
config.jsonUser config: whitelist, app limits, Pomodoro minutes, break reminder, snooze duration, custom browsers
pomodoro.jsonCurrent Pomodoro state (active flag, start time, duration, notified flag)

Database schema

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.

Defaults & ranges (from storage/config.go and system/userconfig.go)

SettingDefaultRange
Retention (days)71 – 30
Tracking poll interval (s)51 – 60
Pomodoro (min)25> 0
Break reminder (min)60> 0
Snooze (min)60> 0

Registry keys written

  • HKCU\Software\Microsoft\Windows\CurrentVersion\Run\focusd — autostart entry (full quoted path to focusd_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.

Privacy

focusd is built for privacy by design:

  • No telemetry. The only network call is GET https://api.github.com/repos/0xarchit/focusd/releases/latest when you run focusd update (and the subsequent download from github.com if you confirm). Grep for http. 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.

Building from Source

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.nsi

Replace dev-build with the release version. The -X 'focusd/system.Version=...' ldflag is read at runtime by focusd version and the update checker.

CI

WorkflowTriggerOutput
.github/workflows/release.ymlPush of a vX.Y.Z tagBuilds 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.ymlPush to test branchBuilds an unsigned dev installer, uploads as a 5-day artifact.
.github/workflows/deploy-site.ymlPush to main/master touching website/**Deploys the static site under website/ to GitHub Pages (focusd.0xarchit.is-a.dev).

Uninstalling

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.


Contributing

Contributions welcome. See CONTRIBUTING.md and CODE_OF_CONDUCT.md. Security issues: see SECURITY.md.

License

MIT License — see LICENSE.


Built by @0xarchit