Life Monitor
life-monitor is a cross-platform Rust activity tracker for Linux and Windows. It collects raw keyboard and mouse activity, tracks which window is focused over time, and stores the data in SQLite for later analysis.
- activity is written to a local SQLite database
- you can move or merge history between machines with snapshot export/import
- you can place the database on another disk or an already-mounted network share
There is no built-in dashboard yet. The output is a SQLite database plus a log file, so the current workflow is to inspect the data with SQL, scripts, or external tools.
Current Status
The main workflow is stable enough for local use:
- local SQLite storage is the supported default.
- import/export snapshots are the simplest built-in way to move history between machines
- remote samba/NFS shares are supported when already mounted by the OS
- optional multi-device sync is available behind the
multi-synccargo feature
Still missing:
- built-in charts or TUI
- deeper reporting and visualization on top of the stored data
Install
From crates.io
Then run:
From source
Binary location:
Build Requirements
Linux
You need:
- a recent Rust toolchain
clanglibclang- SQLite development libraries
- OpenSSL development libraries
pkg-config- Wayland/X11 development libraries
Examples:
Arch Linux
Debian / Ubuntu
Fedora
Nix
This repository ships a flake.nix with a development shell and build targets:
Notes:
nix build .#linuxproduces the native Linux package for the current host systemnix build .#windowscross-compiles the Windows GNU binary from the current host system; it is not a native Windows build
If you are building or testing from source, prefer the flake environment so the expected toolchain and native dependencies are available:
Inside the default dev shell:
- normal host Linux
cargo build,cargo test, andcargo runuse the host toolchain - Windows cross-builds are available by passing
--target x86_64-pc-windows-gnu - the shell does not switch the global default target for you
[!WARNING] On Linux,
life-monitorreads raw input events from/dev/input. Your user usually needs permission to access those devices, add yourself to input group usingsudo usermod -aG input $USERor run the program asroot
Usage
Basic form:
Useful examples:
Optional multi-device sync examples, when built with --features multi-sync:
Main CLI Options
| Flag | Purpose |
|---|---|
-i, --interval <SECS> |
Flush buffered activity to SQLite every N seconds |
-d, --debug |
Enable more verbose logs and a shorter default interval |
-p, --dpi <DPI> |
Set mouse DPI/CPI for distance estimation and remember it |
-c, --clear |
Delete the current database and start from an empty one |
--db-path <PATH> |
Use a custom SQLite path or directory and remember it |
--export-db <FILE> |
Export the current DB into a consistent SQLite snapshot |
--import-db <FILE> |
Import a previously exported snapshot |
--dry-run |
Preview the import without modifying the destination DB |
--import-notes <TEXT> |
Record notes alongside import metadata |
--enable-startup |
Enable automatic startup for the current user session |
--disable-startup |
Disable automatic startup for the current user session |
--startup-mode <MODE> |
Linux only: choose xdg or systemd startup mode |
-s, --no-systray |
Windows only: disable the tray icon |
When built with --features multi-sync, additional sync options and subcommands are available:
| Flag / Command | Purpose |
|---|---|
--sync-enable |
Enable background push/pull sync during normal collection |
--sync-remote-url <URL> |
Point the program at a remote sqld / libSQL endpoint |
--sync-auth-token <TOKEN> |
Provide an auth token for the remote endpoint |
--sync-interval <SECS> |
Change how often background sync runs |
sync push |
Send pending local device-owned rows to the remote |
sync pull |
Pull remote changes into the local SQLite database |
sync status |
Show the local sync state, pending work, and last known remote status |
Run life-monitor --help for the full generated help text.
Database Paths and Mounted Shares
By default the database lives in:
Linux
- database:
~/.local/share/life_monitor/data.db - log file:
~/.local/share/life_monitor/spy.log
Windows
- database:
%LOCALAPPDATA%\life_monitor\data.db - log file:
%LOCALAPPDATA%\life_monitor\spy.log
You can override that with --db-path.
Supported --db-path forms:
- a direct SQLite file path
- a directory, in which case
life-monitorusesdata.dbinside it - a mounted network share path such as Samba or NFS
Behavior:
- the path is remembered for future runs
- supplying
--db-pathagain overwrites the remembered path - if a remembered share is unavailable later, the program errors with a recovery message telling you to remount the share or provide a new DB path
SQLite note:
- Life Monitor bundles SQLite on both Linux and Windows
- you do not need a separate system SQLite installation just to run the program
Important limitation:
life-monitordoes not mount remote shares and does not prompt for share credentials- the OS must already have access to the path you provide
Snapshot Export and Import
To move or merge activity history between machines, use snapshot export/import:
Export behavior:
- creates a consistent SQLite snapshot
- does not copy the raw DB file blindly
Import behavior:
- validates source and destination integrity
- creates an automatic pre-import backup
- merges bucketed activity data
- records metadata so the same snapshot is not imported twice accidentally
Optional Multi-Device Sync
life-monitor now has an optional sync mode for people who want multiple devices to converge into the same dataset without manually exporting and importing snapshots all the time.
This mode is not enabled in the default build. Build from source with:
User-facing model:
- each device keeps collecting into its own local SQLite database
- the local database remains usable even if the remote is down
- sync push sends only rows authored by that device
- sync pull brings down rows from other devices
sync statusshows pending changes, last successful sync times, and the last known remote state
What you need:
- a reachable
sqld/ libSQL server - the remote URL
- an auth token if your deployment requires one
Typical setup:
- build
life-monitorwith--features multi-sync - run your
sqldserver somewhere you control - start
life-monitorwith--sync-enable --sync-remote-url <URL> - use
sync statusto confirm the local database is catching up
Important behavior:
- if the remote is unavailable,
life-monitorkeeps collecting locally - pending sync work stays queued and is retried later
- local-only mode remains the default if you do not enable sync
DPI and Mouse Distance
Mouse distance is estimated from raw input counts plus a configured DPI/CPI value.
Current behavior:
- if you provide
--dpi, the value is remembered - if you do not provide
--dpi,life-monitorreuses the remembered value - if no DPI is known yet, interactive runs ask once and persist it
Why this works this way:
- raw input avoids desktop pointer acceleration in the measurement path
- but raw counts still need DPI/CPI to estimate real-world distance in centimeters
- generic automatic CPI detection is not portable enough across Linux and Windows setups to be trusted as the main path
Startup
Linux
Linux has two startup modes:
xdgis the default and recommended modesystemdis an explicit advanced fallback
Use it from the graphical session where you normally run the program.
Recommended default:
Fallback mode:
What each mode does:
xdgwriteslife-monitor.desktopinto~/.config/autostartor$XDG_CONFIG_HOME/autostartsystemdwrites and enables a per-usersystemd --userunit tied tographical-session.target- the
systemdmode does not freeze volatile values such asWAYLAND_DISPLAYinto the unit file; it expects the graphical session to import them intosystemd --userat login
Best practice:
- enable startup from a stable installed binary such as
cargo install life-monitor - avoid enabling startup from
target/debugortarget/releaseinside a repo checkout, because moving or cleaning the repository will break the stored executable path - prefer
xdgunless you have already verified that your session imports graphical variables intosystemd --user
How to check whether XDG autostart is likely a good fit before enabling it:
Good signs:
- you are running inside a normal graphical session
- at least one of
XDG_CURRENT_DESKTOPorDESKTOP_SESSIONis set XDG_SESSION_TYPEis set towaylandorx11
If those values are missing, XDG autostart may still work, but your setup is probably more manual and you should verify it after logging in again.
How to check whether the systemd fallback is likely to inherit the graphical environment correctly:
|
|
Good signs:
- the same graphical-session variables appear in both
envandsystemctl --user show-environment graphical-session.targetexists and is part of the user session lifecycle
If the process environment has those variables but systemctl --user show-environment does not, prefer XDG startup. That means your session is not currently exporting the graphical environment into systemd --user.
After --enable-startup, Life Monitor does not try to launch a second copy immediately on Linux:
- XDG mode takes effect on the next graphical login
- systemd mode installs and enables the user unit, but does not start it right away
- this avoids racing the current process against Life Monitor's single-instance lock
If you want to test the systemd fallback immediately, first stop the current Life Monitor process and then run:
What life-monitor itself does not do:
- it does not try to detect every compositor or desktop environment individually
- it does not rewrite the wider
systemd --usermanager environment for you - it does not mount shares or recreate the whole desktop environment
Disable it with:
Windows
--enable-startup creates a shortcut in the current user's Startup folder.
Disable it with:
Notes and Limitations
- there is still no built-in dashboard or TUI
- mouse distance is still an estimate, not a physical measurement guarantee
- remote-share locking is best-effort and depends on filesystem/share semantics
- local-only mode is the supported default; multi-device sync is optional and requires a remote
sqld/ libSQL server - Wine can help with some Windows checks on Linux, but native Windows remains the reliable runtime validation environment
Contributing
Bug reports and PRs are welcome. Feel free to reach out to me if you have any questions :).
If you report a platform-specific issue, include:
- operating system
- desktop session type (
WaylandorX11) on Linux - how you launched the program
- relevant logs