Files
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

130 lines
4.4 KiB
Python

#!/usr/bin/env python3
"""Install the Zed Hours Tracker git hook and config for the current project."""
import json
import os
import stat
import subprocess
from pathlib import Path
def get_project_root() -> Path:
"""Return the git project root, falling back to the script's project directory."""
try:
root = subprocess.check_output(
["git", "rev-parse", "--show-toplevel"],
text=True,
stderr=subprocess.DEVNULL,
).strip()
return Path(root).resolve()
except (subprocess.CalledProcessError, FileNotFoundError):
pass
# Fallback 1: directory containing this script's grandparent (<project>/tools/time_tracking/install.py)
script_project = Path(__file__).resolve().parents[2]
if (script_project / ".git").exists() or (script_project / ".zed-hours").exists():
return script_project
# Fallback 2: current working directory
return Path.cwd().resolve()
def ensure_log_dir(project_root: Path) -> Path:
log_dir = project_root / ".zed-hours"
log_dir.mkdir(parents=True, exist_ok=True)
return log_dir
def write_config(log_dir: Path, project_root: Path) -> Path:
config = {
"project_root": str(project_root),
"log_dir": str(log_dir.relative_to(project_root)),
"heartbeat_interval_seconds": 60,
"idle_threshold_seconds": 300,
"max_inactive_gap_seconds": 600,
}
config_path = log_dir / "config.json"
if not config_path.exists():
config_path.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8")
print(f"Created config: {config_path}")
else:
print(f"Config already exists: {config_path}")
return config_path
def install_git_hook(project_root: Path) -> None:
hook_path = project_root / ".git" / "hooks" / "post-commit"
if not hook_path.parent.exists():
print("No .git directory found; skipping git hook install.")
return
script_dir = project_root / "tools" / "time_tracking"
log_commit_script = script_dir / "log_commit.py"
hook_content = f"""#!/bin/sh
# Zed Hours Tracker - post-commit hook
python3 "{log_commit_script}" "$@"
"""
if hook_path.exists():
existing = hook_path.read_text(encoding="utf-8")
if "Zed Hours Tracker" in existing:
print(f"Hook already installed: {hook_path}")
return
# Append to existing hook
hook_path.write_text(existing.rstrip("\n") + "\n\n" + hook_content, encoding="utf-8")
else:
hook_path.write_text(hook_content, encoding="utf-8")
# Make executable
hook_path.chmod(hook_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
print(f"Installed git hook: {hook_path}")
def write_systemd_service(project_root: Path, script_dir: Path) -> None:
"""Write a sample systemd user service file for background tracking."""
systemd_dir = Path.home() / ".config" / "systemd" / "user"
service_name = f"zed-hours-{project_root.name}.service"
service_path = systemd_dir / service_name
tracker_script = script_dir / "zed_tracker.py"
service_content = f"""[Unit]
Description=Zed Hours Tracker for {project_root.name}
After=graphical-session.target
[Service]
Type=simple
WorkingDirectory={project_root}
ExecStart=/usr/bin/python3 {tracker_script} --project-root {project_root}
Restart=on-failure
RestartSec=10
Environment="PYTHONUNBUFFERED=1"
[Install]
WantedBy=default.target
"""
systemd_dir.mkdir(parents=True, exist_ok=True)
service_path.write_text(service_content, encoding="utf-8")
print(f"Wrote systemd user service: {service_path}")
print(f"Enable with: systemctl --user daemon-reload && systemctl --user enable --now {service_name}")
def main() -> None:
project_root = get_project_root()
script_dir = Path(__file__).resolve().parent
log_dir = ensure_log_dir(project_root)
write_config(log_dir, project_root)
install_git_hook(project_root)
write_systemd_service(project_root, script_dir)
print(f"\nZed Hours Tracker installed for project: {project_root}")
print(f"Data directory: {log_dir}")
print("\nNext steps:")
print(" 1. Start the tracker: python3 tools/time_tracking/zed_tracker.py")
print(" 2. Or enable the systemd service shown above.")
print(" 3. Make a commit to test the git hook.")
print(" 4. Generate a report: python3 tools/time_tracking/generate_report.py --today")
if __name__ == "__main__":
main()