Install the daemon
The daemon ships with the openusage binary. There is no separate package — the same binary is the dashboard, the hook receiver, and the daemon itself.
:::warning CGO required
The daemon links mattn/go-sqlite3, which requires CGO. Use the official release binaries or build with CGO_ENABLED=1. A go run build is rejected at install time because the path points at a transient temp file.
:::
Prerequisites
- macOS (launchd) or Linux with
systemd --user - A persistent install of
openusageon$PATH(e.g./usr/local/bin/openusage) - Write access to
~/Library/LaunchAgents/(macOS) or~/.config/systemd/user/(Linux)
Install
openusage telemetry daemon install
What it does:
- macOS — writes
~/Library/LaunchAgents/com.openusage.telemetryd.plistwithKeepAlive=trueandRunAtLoad=true, then bootstraps and kickstarts it via the modernlaunchctl bootstrap/launchctl kickstartAPI. - Linux — writes
~/.config/systemd/user/openusage-telemetry.service(Type=simple,Restart=always,RestartSec=2), runssystemctl --user daemon-reload, andsystemctl --user enable --now openusage-telemetry.service.
After install the daemon is running and will restart automatically on logout/login or reboot (provided your platform's user services are active).
Status
openusage telemetry daemon status
openusage telemetry daemon status --details
--details prints:
- Service state from launchd or systemctl
- Socket path and whether
/healthzanswers - DB and spool paths
- Recent log file sizes
You can also query the platform tools directly:
# macOS
launchctl print gui/$(id -u)/com.openusage.telemetryd
# Linux
systemctl --user status openusage-telemetry.service
Uninstall
openusage telemetry daemon uninstall
This stops the service and removes the plist or unit file. It does not delete:
~/.local/state/openusage/telemetry.db- The spool directory
- The log files
Remove those manually if you want a clean slate. See Storage.
Run in the foreground
For development or debugging:
openusage telemetry daemon run --verbose
Useful flags:
| Flag | Default | Purpose |
|---|---|---|
--socket-path PATH | ~/.local/state/openusage/telemetry.sock | Where to bind the Unix socket. Also honors OPENUSAGE_TELEMETRY_SOCKET. |
--db-path PATH | ~/.local/state/openusage/telemetry.db | SQLite file. |
--spool-dir PATH | ~/.local/state/openusage/telemetry-spool/ | Disk queue for unreachable hooks. |
--interval DURATION | 30s | Default poll/collect interval. |
--collect-interval DURATION | (inherits --interval) | Override only for collectors. |
--poll-interval DURATION | (inherits --interval) | Override only for provider polling. |
--verbose | off | Verbose log output to stderr. |
Logs
When run as a service:
~/.local/state/openusage/daemon.stdout.log~/.local/state/openusage/daemon.stderr.log
On Linux, systemd-journal also captures everything:
journalctl --user-unit openusage-telemetry.service -f
Set OPENUSAGE_DEBUG=1 in the launchd plist or systemd unit's environment to get verbose output without restarting with --verbose.
Verifying it works
After install:
# Liveness probe
curl --unix-socket ~/.local/state/openusage/telemetry.sock http://localhost/healthz
# Connect the TUI — it auto-detects a running daemon
openusage
If the dashboard shows "telemetry: connected" in the Telemetry settings tab (, then 6), the daemon is reachable and the TUI is reading from it.
Common pitfalls
go runinstall rejected. Build withmake buildand put the binary on$PATHbefore runningdaemon install.- Multiple binaries on
$PATH. The plist or service unit pins the absolute path captured at install time. Reinstall (uninstalltheninstall) after moving the binary. - Linux without lingering. If
systemctl --userservices do not survive logout, enable lingering once:loginctl enable-linger $USER.