Files
zed_time_tracker/README.md
T
fegger bfff093dc6 Add Zed Hours Tracker tooling
Introduces a local-first time tracker for Zed editor sessions, including
background activity tracking, automatic git commit logging, and markdown
report generation. Includes install script, systemd service template,
and setup instructions in README.
2026-09-11 10:27:56 +02:00

5.1 KiB

Zed Hours Tracker

A lightweight, local-first, background time tracker for Zed editor sessions, with automatic git commit logging. No cloud, no accounts, no manual timers.

Works on Arch Linux + Wayland and is designed to be portable to other projects.


What it does

  1. Detects when you are working in Zed on this project by monitoring the active window title (Wayland) and filesystem activity.
  2. Writes heartbeats to .zed-hours/heartbeats.jsonl:
    • timestamp
    • project path
    • focused file (if detectable)
    • idle status
  3. Logs git commits automatically via post-commit hook to .zed-hours/commits.jsonl.
  4. Generates markdown reports combining heartbeats + commits into daily summaries.

Files

File Purpose
install.py Install git hook and create .zed-hours/ data directory
log_commit.py Called by git hook; do not run directly usually
zed_tracker.py Background tracker for Zed activity
generate_report.py Generate a markdown hours report
README.md This file

Installation

Run from the project root:

python3 tools/time_tracking/install.py

This will:

  • create .zed-hours/ in the project root;
  • install a post-commit git hook that logs commits;
  • create a default config file.

Running the tracker

The tracker is intentionally a simple script you run in the background.

Option A: One-off test

python3 tools/time_tracking/zed_tracker.py --project-root $(pwd)

Press Ctrl+C to stop.

Option B: Zed tasks (run from the editor)

This project includes Zed tasks so you can trigger tracker actions with the task runner shortcut (alt+shift+t or ctrl+shift+t depending on your keymap). The default working directory for Zed tasks is the project root, so the commands use relative paths.

Task Action
Zed Hours: Install tracker Install git hook, config, and systemd service
Zed Hours: Start tracker (foreground) Start the tracker in a Zed terminal panel
Zed Hours: Generate report (today) Generate today's report
Zed Hours: Generate report (yesterday) Generate yesterday's report
Zed Hours: Generate report (last 14 days) Generate a 14-day report
Zed Hours: Open latest report Print path to latest report
Zed Hours: Status Show heartbeat/commit/report counts

A sample service file is generated by install.py at:

~/.config/systemd/user/zed-hours-gem360.service

Enable it:

systemctl --user daemon-reload
systemctl --user enable --now zed-hours-gem360.service
systemctl --user status zed-hours-gem360.service

Logs:

journalctl --user -u zed-hours-gem360.service -f

To stop:

systemctl --user stop zed-hours-gem360.service

Option C: tmux / screen

tmux new -s zed-hours -d 'python3 tools/time_tracking/zed_tracker.py --project-root $(pwd)'

Generating a report

python3 tools/time_tracking/generate_report.py --from 2026-08-03 --to yesterday

Output is written to .zed-hours/reports/YYYY-MM-DD_to_YYYY-MM-DD.md.

You can also run:

python3 tools/time_tracking/generate_report.py --today

How activity detection works on Wayland

Wayland does not expose a global active-window API for security reasons. The tracker tries several methods, in order:

  1. Hyprland: hyprctl activewindow
  2. Sway: swaymsg -t get_tree
  3. GNOME / Mutter: D-Bus GetActiveWindow via gdbus
  4. KDE / KWin: D-Bus via qdbus
  5. Fallback: monitor filesystem activity inside the project root using inotify or polling recent file access/modification times.

If all window-detection methods fail, the fallback still gives you a reliable signal that someone is actively editing files in this project.


Reusing in another project

Copy the tools/time_tracking/ directory to the new project and run:

python3 tools/time_tracking/install.py

The scripts detect the project root automatically from the current working directory.


Data format

.zed-hours/heartbeats.jsonl

{"timestamp": "2026-08-26T09:15:00", "project": "/home/fegger/Code/ixsol/gem360-git", "file": "README.md", "active": true, "source": "hyprctl"}

.zed-hours/commits.jsonl

{"type": "commit", "timestamp": "2026-08-26T09:20:00", "repo": "/home/fegger/Code/ixsol/gem360-git", "branch": "va_module", "sha": "abc12345", "message": "[ADD] feature X", "author": "Florian Egger"}

.zed-hours/config.json

{
  "project_root": "/home/fegger/Code/ixsol/gem360-git",
  "heartbeat_interval_seconds": 60,
  "idle_threshold_seconds": 300,
  "log_dir": ".zed-hours"
}

Notes

  • This tool is intentionally simple and local. It is not a replacement for a commercial time tracker, but it is a reliable fallback when you forget to log hours.
  • The tracker does not send data anywhere.
  • Heartbeat granularity is one minute by default. Tune it in config.json.
  • Because of Wayland security, window detection may not give the exact filename. The filesystem fallback compensates for this.