Need help developing a watcher for Zettlr

Hi everyone,

I’d like to develop a simple watcher for https://www.zettlr.com/, which seems based on chromium.

Currently, AW only logs the window title “Zettlr”, and similar to Chrome/Firefox I’d like to track the title of the active tab as well.

I’ve read the description on how to write a custom watcher, but coming from PHP I’m not sure what to do.

Can anyone help me how to run setup a test system (or test plugin) so I can develop/debug the code to see where I can access the value of the tab title from Zettlr?

I asked gemini to create a demo script about this, it came up with

import time
from datetime import datetime, timezone
import pygetwindow as gw
from aw_client import ActivityWatchClient
from aw_core.models import Event

# Configuration
CLIENT_NAME = "aw-watcher-zettlr"
BUCKET_ID = f"{CLIENT_NAME}_local"
POLL_TIME = 1.0  # Check every second

def get_zettlr_info():
    """
    Finds the active Zettlr window and parses its title.
    Zettlr titles usually look like: 'My Note.md - Zettlr'
    """
    try:
        active_win = gw.getActiveWindow()
        if active_win and "Zettlr" in active_win.title:
            title = active_win.title
            # Strip the suffix to get the filename
            filename = title.replace(" - Zettlr", "").strip()
            return {"file": filename, "app": "Zettlr"}
    except Exception:
        pass
    return None

def main():
    # 1. Connect to ActivityWatch
    client = ActivityWatchClient(CLIENT_NAME, testing=False)
    
    # 2. Create the bucket (it won't overwrite if it exists)
    client.create_bucket(BUCKET_ID, event_type="app.zettlr.activity")

    print(f"Watcher started. Tracking Zettlr activity to bucket: {BUCKET_ID}")

    while True:
        try:
            data = get_zettlr_info()
            
            if data:
                # 3. Create an event
                # The 'heartbeat' function merges consecutive identical events
                event = Event(timestamp=datetime.now(timezone.utc), data=data)
                
                # 'pulsetime' is the max gap (in seconds) to merge events
                client.heartbeat(BUCKET_ID, event, pulsetime=POLL_TIME + 1.0)
            
            time.sleep(POLL_TIME)
        except KeyboardInterrupt:
            print("Watcher stopped.")
            break

if __name__ == "__main__":
    main()

I’d recommend using a LLMs for this. They can guide you through setting up python, installing the packages, testing and debugging. If you get stuck let me know :slight_smile: I might be able to help.

Okay got so far as to run the script, but running into an error:

ModuleNotFoundError: No module named ‘aw_client’

Steps to get there:

  • save script to %CONFIG_FOLDER%/aw-watcher-zettlr/aw-watcher-zettlr.py
  • via terminal: chmod +x ./aw-watcher-zettlr.py
  • python3 ./aw-watcher-zettlr.py
  • python3 -m pip install pygetwindow and python3 -m pip install pyobjc-framework-Quartz to get around the “ModuleNotFoundError” errors

aw_client seems to be the ActivityWatch client, so how do I run the client so that aw_client is available for the script?

(Thanks for helping. I’m getting there. Coming from an Apache/PHP world, I have yet to get acquainted with Python).

I created an easy to install project repo for this, but it seems that Zettlr does not surface document information. The application title will always be Zettlr. If you want more info, you will need to submit an issue in the Zettlr repo to have an option to surface this in the application title. There is currently an issue to add an api to the software that might be useful for this, but it seems to be fairly old and stale. It might also be easier to just add the this info into the title rather than wait for the API and implement calls to the API in the watcher code.

Actually, it was a pretty easy change to the Zettlr code base. The changes are here: GitHub - RTnhN/Zettlr: Your One-Stop Publication Workbench · GitHub. I might try to make a PR to merge this into the main Zettlr codebase in a day or so.

Best man! :+1:

Thanks alot :folded_hands:

PR is here: [Feat] Add active tab name to window title by RTnhN · Pull Request #6283 · Zettlr/Zettlr · GitHub
Feel free to comment on it to give it support. It might be useful to have someone who is really interested in the feature support it.