No description
  • Python 99.4%
  • Nix 0.4%
  • Shell 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-18 10:32:43 +01:00
tests feat: add report output controls 2026-07-18 10:32:43 +01:00
.envrc Move report publishing to BookStack 2026-07-14 23:45:01 +01:00
.gitignore Move report publishing to BookStack 2026-07-14 23:45:01 +01:00
config.json.example feat: send repository reports as MP3 audio 2026-07-18 09:29:26 +01:00
extract_diffs.py Add Claude Code CLI fallback, manual pipeline scripts, and #model attribute 2026-04-14 22:26:48 +01:00
flake.lock Move report publishing to BookStack 2026-07-14 23:45:01 +01:00
flake.nix feat: send repository reports as MP3 audio 2026-07-18 09:29:26 +01:00
forgejo-daily-report.py feat: add report output controls 2026-07-18 10:32:43 +01:00
forgejo_daily_report.py Move report publishing to BookStack 2026-07-14 23:45:01 +01:00
post_note.py Index reports under Trilium repositories 2026-07-14 23:56:14 +01:00
pyrightconfig.json Add setup.sh, pyrightconfig.json, and fix type/style warnings 2026-03-06 20:36:58 +00:00
README.md feat: add report output controls 2026-07-18 10:32:43 +01:00
requirements.txt Extract dependencies into requirements.txt 2026-04-14 22:28:52 +01:00
setup.sh Move report publishing to BookStack 2026-07-14 23:45:01 +01:00

forgejo-daily-report

Generates a daily summary of Forgejo repository activity and posts it to both TriliumNext and BookStack.

For each repo with commit or issue activity on the target day, it:

  1. Fetches commits via the Forgejo API
  2. Fetches issues and milestones opened, updated, or closed that day
  3. Fetches the diff for each commit
  4. Syncs the matching Engram project and extracts memories created that UTC day
  5. Sends the diffs, commit messages, issue and milestone context, and memories to Ollama for an HTML summary
  6. Posts the summary, commits, compact issue/milestone activity lists, and verbatim memories as a child note under that day's Trilium date note and as a page in the BookStack Project Logs shelf
  7. Generates a separate conversational voice summary from the same source material, renders it as a Fern Brady-voiced MP3, and posts it to the forgejo-reports ntfy topic

Engram is optional. A missing binary, failed cloud sync, or invalid export produces a warning and the normal Forgejo-only report continues.

Requirements

  • Python 3.11+
  • An Ollama instance with a model loaded
  • A TriliumNext instance with ETAPI enabled
  • A BookStack instance reachable by the scheduled job
  • A Forgejo instance with an API token
  • Optional: an Engram v1.17-compatible binary and access to an Engram cloud server
  • Optional: Pocket TTS and a Hugging Face token for repository audio notifications

Setup

cp config.json.example config.json
# Edit config.json with your details
direnv allow

The included .envrc loads a Nix development shell with Python, requests, and Pyright. Once allowed, run the scripts directly; no virtual environment is needed.

Usage

# Report yesterday's UTC activity.
python forgejo_daily_report.py

# Report one specific UTC day.
python forgejo_daily_report.py 2026-07-13

# Backfill from the given UTC day through yesterday.
python forgejo_daily_report.py --backfill 2026-07-01

# Rebuild existing successful reports with current Forgejo context.
python forgejo_daily_report.py 2026-07-13 --refresh

# Single-date run with text and voice reports explicitly enabled.
python forgejo_daily_report.py 2026-07-13 --voice --text

# Backfill text reports only (the backfill default).
python forgejo_daily_report.py --backfill 2026-07-01

# Backfill with voice reports enabled, but no text reports.
python forgejo_daily_report.py --backfill 2026-07-01 --voice --no-text

--backfill fetches the repository list and each repository's Forgejo activity once for the full date range, buckets it by UTC day, then applies the normal report flow to each day. It continues if an individual day fails and exits non-zero after the range if any dates failed. Voice reports default to on for a single-date run and off for backfills; use --voice or --no-voice to override that default. Text reports default to on for all runs; use --no-text to intentionally disable Trilium and BookStack report generation/delivery, or --text to state the default explicitly. Add --test to generate summaries without publishing. --refresh checks existing successful text reports against current Forgejo activity, validation results, API states, and the selected model. It only replaces both text reports when those inputs or the model changed; voice-only runs are not suppressed by existing text reports.

Configuration

All settings can be provided via config.json (takes precedence) or environment variables.

Key Description Default
FORGEJO_URL Base URL of your Forgejo instance https://git.nimmog.uk
FORGEJO_TOKEN API token with read:repository, read:issue, and read:user scopes (required)
FORGEJO_USER Forgejo username whose repos to report on nimmo
OLLAMA_URL Ollama API base URL http://nova.mesh:11434
OLLAMA_MODEL Model to use for summarisation qwen3.6:35b-a3b-q8_0
OLLAMA_NUM_CTX Ollama context-window allocation 262144
OLLAMA_TIMEOUT Ollama request timeout in seconds 3600
CODEX_MODEL Model to use for the Codex fallback gpt-5.5
TRILIUM_URL TriliumNext base URL https://notes.nimmog.uk
TRILIUM_TOKEN ETAPI token (required)
TRILIUM_REPOSITORIES_NOTE_ID Parent note for repository report indexes QUadK9c6ibZA
HF_TOKEN Hugging Face token used to download Pocket TTS weights (optional; required for first model download)
POCKET_TTS_BIN Pocket TTS executable pocket-tts
POCKET_TTS_VOICE Voice sample WAV ../daily-briefing/voice_samples/fern_brady.wav
POCKET_TTS_FALLBACK_VOICE Built-in voice if sample cloning fails anna
POCKET_TTS_TIMEOUT TTS timeout in seconds 600
FFMPEG_BIN ffmpeg executable used to convert Pocket TTS WAV output to MP3 ffmpeg
MP3_BITRATE MP3 encoding bitrate 96k
NTFY_BASE_URL ntfy server base URL (optional; disables audio when absent)
NTFY_API_KEY ntfy bearer token (optional; disables audio when absent)
NTFY_TOPIC ntfy topic for repository audio forgejo-reports
BOOKSTACK_URL BookStack base URL https://wiki.nimmog.uk
BOOKSTACK_ID BookStack API token ID (required)
BOOKSTACK_SECRET BookStack API token secret (required)
ENGRAM_ENABLED Enable same-day Engram memory collection true
ENGRAM_BINARY Engram executable; falls back to ./engram, then PATH (auto-detect)
ENGRAM_CLOUD_SERVER Engram cloud endpoint used for project sync http://10.10.0.2:18080
ENGRAM_CLOUD_TOKEN Bearer token for Engram cloud (optional for unauthenticated servers)
ENGRAM_DATA_DIR Persistent local Engram database directory Engram default (~/.engram)
MAX_DIFF_BYTES Max bytes of diff to send per repo 100000
DIFF_EXCLUDE_PATTERNS Extra filename patterns to exclude from diffs (config.json only, as a list) []

Engram on media1

Place the engram binary beside forgejo-daily-report.py, make it executable, and configure the Vega cloud endpoint and token in the private config.json. Keep ENGRAM_DATA_DIR on persistent storage writable by the cron user.

chmod +x ./engram
./engram version

For each repository with commits, the report runs a project-scoped cloud sync using the repository name. If the local project has not been enrolled, it enrolls it and retries once. Engram failures never mark or block the Forgejo report.

Usage

# Report on yesterday (default)
venv/bin/python3 forgejo-daily-report.py

# Report on a specific date
venv/bin/python3 forgejo-daily-report.py 2026-03-05

Cron

0 1 * * * /home/nimmo/scripts/forgejo-daily-report/venv/bin/python3 /home/nimmo/scripts/forgejo-daily-report/forgejo-daily-report.py

Trilium notes

Each generated note is tagged with:

  • git-report — allows searching across all reports
  • iconClass=bx bxl-git — git icon in the note tree
  • <repo-name>=<date> — e.g. nixos-config=2026-03-05, for per-repo history searches

When matching Engram memories exist, the note also contains a chronological Memories section with escaped verbatim content. Those memories are supplied to the summary model as additional context. Issue activity and Milestone activity sections list each item opened, updated, or closed that UTC day. Updated issues include bounded same-day comment and timeline context when available. To keep reports readable, descriptions are not copied into the note; the first 1,500 characters of newly opened issues and milestones are supplied only to the summary model as context.

Reports also show Forgejo Actions and commit-status signals for the reported commits. These are validation signals, not proof that a deployment completed. Report metadata records the status of issue, milestone, Actions, and commit-status API sources; repositories with issue tracking disabled are skipped quietly.

When TRILIUM_REPOSITORIES_NOTE_ID is configured, the script also creates a repository note beneath that parent and adds every report as an additional Trilium parent. Reports therefore remain under their daily date note while also appearing in their repository's report history.

BookStack pages

Reports are stored on a Project Logs shelf. Each repository has one book on that shelf, each repository book has YYYY-MM chapters, and each daily report is a dated page within its month chapter. Shelves, books, and chapters are created automatically when first needed.

Repository books are refreshed from Forgejo metadata: their description records the repository URL and default branch, while tags record repository name, Forgejo URL, visibility, default branch, reported languages, and any available license, topics, or archived status.

Each report page is tagged with git-report=true, repository=<repo>, report-date=<YYYY-MM-DD>, model=<summary model>, and a forgejo-report-inputs fingerprint. The fingerprint includes activity and validation outcomes (including successes and failures), so refresh can avoid an unchanged regeneration. A report that could not be summarised also receives forgejo-failed=true.

Trilium and BookStack are independent delivery targets: a lookup or posting failure in one is logged but does not prevent delivery to the other. Create a BookStack API token with access to the Project Logs shelf and ensure the configured API URL is reachable from the cron host.