Chronicle v0.1.0: Telemetry harvester and context engine for Wayland and AI agents

Hello everyone,

I’ve tagged the initial v0.1.0 release of Chronicle, a local, privacy-first telemetry daemon and context correlation engine written in Crystal.

The Problem

When pair programming with AI agents or conducting weekly engineering retrospectives, human engineers and autonomous agents often lose high-resolution context regarding what was worked on across disparate repositories, terminal tabs, and editor windows. Existing commercial solutions either exfiltrate activity to third-party clouds or lack the correlation depth required by LLMs to reconstruct technical progress.

What Chronicle Does

Chronicle runs as a non-blocking local daemon (via systemd user service) and collects lightweight, local-only telemetry:

  1. Compositor Window Focus: Subscribes directly to Wayland IPC streams. Native drivers currently exist for Niri (niri msg -j event-stream), Sway (i3 IPC), and KWin (via qdbus), along with Wayland idle state detection.
  2. Shell History Harvester: Ingests commands executed across Bash, Zsh, and Fish, mapping them to current working directories.
  3. Git Churn & Conventional Commits: Scans local git repositories in a single-pass git log run, extracting files changed, insertions, deletions (--shortstat), and classifying commits via Conventional Commits metadata.
  4. Project Attribution Engine: Correlates window focus duration, shell commands, and git churn into discrete project workspaces.
  5. Deep-Work Session Clustering: Groups contiguous focus intervals into discrete work sessions based on a configurable idle threshold (default 15 minutes).
  6. Multi-Format Exporters:
    • chronicle report --today: Human-readable terminal dashboard.
    • chronicle export -f md --compact: Token-efficient Markdown summary optimized for LLM context injection.
    • chronicle export -f json: Structured machine telemetry.
    • Scoping via --project <name> (-p).

Why Crystal?

Chronicle relies on Crystal’s concurrency model (Execution Contexts and lightweight fibers) to process IPC event streams concurrently with local SQLite3 writes without perceptible latency or CPU overhead. A single stripped native binary runs rootless with zero JVM/Node dependencies.

Links

Feedback and patches are welcome.

So, in plain English, this thingamabob can answer the question “what the hell did I do today”?

Exactly. Or this past week. It’s always hard to know. ;D

I thought I was the only one into both Crystal and using Podman quadlets!

I have one conceptual question, and one more technical.

  1. Sometimes, I ask opencode to parse some journalctl logs for certain things, and it generally can find it with enough digging. Besides using an external LLM, how would Chronicle differ from that approach?

  2. Again, pretty cool that I see quadlets being used outside of system-admin circles, so kudos to you. It looks like port 8080 is hardcoded in a few files. Have you tried defining that port in a regular .env file, and referencing it a [Service] section in your .containerfile. Something like:

[Container]
Image=localhost/chronicle:latest
ContainerName=chronicle
PublishPort=${PORT}:${PORT}
Environment=APP_ENV=production
Environment=LOG_LEVEL=INFO
Exec=--host 0.0.0.0 --port 8080
AutoUpdate=registry
Network=host.network

[Service]
EnvironmentFile=%h/.config/containers/systemd/chronicle/.env 

You’d have to symlink that entire dir over to wherever systemd looks for your quadlet files, and put that .env in that symlinked directory too. So it isn’t without its downsides.

The only reason I ask is port 8080 seems really popular, and I could see someone wanting to switch that port to prevent conflicts. I’m not sure how this would jive with the Makefile though, maybe it makes more sense to parameterize it there.

Hey, hello! I like to think of myself as a systems engineer. I do sysadmin work (call it what you want, [A-Za-z0-9]+ops, platform engineer, etc.) and appreciate podman/quadlets as a useful technology—happy to use it when required, but not as a blunt hammer. Containers aren’t for everything.

I also do some programming here and there.

Happy to meet a kindred spirit! :slight_smile:

IMHO, the journal doesn’t have it all. Systemd journals have zero awareness of desktop Wayland GUI focus (window titles, app_id, workspace transitions, idle/lock states) or granular interactive shell metrics (command duration, working directory, git branch, exit codes).

Besides, pointing an LLM directly at raw journal dumps burns serious token context and invites hallucinations when asking it to find signals that simply aren’t in syslog.

Chronicle is a deterministic telemetry harvester and correlation engine. It calculates active dwell intervals, associates window focus with shell interaction, scans git commits, and correlates PJP records. At the very least, Chronicle saves massive time and token overhead for the supporting agent by feeding it an exact, pre-digested timeline.

Ah, good eye, but here is the funny part: Chronicle doesn’t actually expose a network port at all!

It’s purely a local UNIX domain socket (~/.local/share/chronicle/chronicle.sock) writing to a local SQLite database. That port 8080 in the Containerfile and Quadlet was vestigial scaffolding boilerplate from when the repo was initialized from a generic service template.

In v0.2.0 (which I just tagged), that dead port config was completely stripped out. The Quadlet now just runs daemon and volume-mounts %h/.local/share/chronicle so the containerized process writes directly to the user’s local database without exposing any TCP ports.


I thought of building this because it’s super useful to me when I want last week’s summary of my work. Also, I just joined contra.com and they require posting what one does, hence, Chronicle. ;D

As a self-reporting tool you can audit, it helps you discover what you did before a stand-up meeting. Maybe it’s also useful for auditing AI agents or workstations if you’re into that kind of old-school UNIX visibility.

IMHO, the journal doesn’t have it all. Systemd journals have zero awareness of desktop Wayland GUI focus (window titles, app_id, workspace transitions, idle/lock states) or granular interactive shell metrics (command duration, working directory, git branch, exit codes).

Oh, I did not know that, TIL. I assumed most Window managers logged stuff, but I guess not.

And regarding the logging, ok that does make sense. So by having everything there with a specific structure, you dramatically cut down on how many tokens you use to parse logs.

As a self-reporting tool you can audit, it helps you discover what you did before a stand-up meeting. Maybe it’s also useful for auditing AI agents or workstations if you’re into that kind of old-school UNIX visibility.

Actually that last sentence is a really neat idea. Provide a summary of what other agents were up to.