No description
  • Python 99.5%
  • Nix 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-18 22:45:11 +01:00
tests Migrate reports to OpenAI-compatible API 2026-09-18 22:45:11 +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 Migrate reports to OpenAI-compatible API 2026-09-18 22:45:11 +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 Migrate reports to OpenAI-compatible API 2026-09-18 22:45:11 +01:00
forgejo_daily_report.py Move report publishing to BookStack 2026-07-14 23:45:01 +01:00
LICENSE Adopt EUPL 1.2 license 2026-09-06 16:39:37 +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 Migrate reports to OpenAI-compatible API 2026-09-18 22:45:11 +01:00
requirements.txt Extract dependencies into requirements.txt 2026-04-14 22:28:52 +01:00
setup.sh Replace Engram report memories with KiwiFS 2026-09-17 21:01:52 +01:00

forgejo-daily-report

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

License

This project is licensed under the European Union Public Licence v1.2 (EUPL-1.2). See LICENSE for the complete text.

The project’s source code is licensed separately from its dependencies and external services, which retain their own terms and licenses.

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. Reads same-day KiwiFS memory revisions for the matching project
  5. Sends the diffs, commit messages, issue and milestone context, and memories to an OpenAI-compatible model API 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

KiwiFS memory context is optional. A missing token or failed KiwiFS request produces a warning and the normal Forgejo-only report continues.

Requirements

  • Python 3.11+
  • An OpenAI-compatible model API
  • A TriliumNext instance with ETAPI enabled
  • A BookStack instance reachable by the scheduled job
  • A Forgejo instance with an API token
  • Optional: access to the shared KiwiFS HTTP/MCP service
  • 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

# Report only one repository (NAME or OWNER/NAME).
python forgejo_daily_report.py --repo nixos-config
python forgejo_daily_report.py 2026-07-13 --repo nimmo/nixos-config

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

# Backfill only one repository.
python forgejo_daily_report.py --backfill 2026-07-01 --repo nimmo/nixos-config

# 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.

Use --repo NAME (or --repo OWNER/NAME) with the default run, a specific date, or --backfill to limit repository discovery and activity collection to that repository.

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
OPENAI_URL OpenAI-compatible API base URL for the main (Nova) host https://ollama-nova.nimmog.uk
OPENAI_API_KEY Shared bearer token for the hosted model APIs (required)
OPENAI_MODEL Model to use on Nova qwen3.8
OPENAI_TIMEOUT Main-host request timeout in seconds 3600
OPENAI_SMALL_URL API URL for smaller diffs (Desktop) (optional)
OPENAI_SMALL_MODEL Model used on Desktop OPENAI_MODEL
OPENAI_SMALL_TIMEOUT Desktop request timeout in seconds 600
OPENAI_SMALL_THRESHOLD Approximate maximum diff size routed to Desktop (~100k tokens) 400000 bytes
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)
KIWIFS_ENABLED Enable same-day KiwiFS memory collection true
KIWIFS_MCP_URL KiwiFS streamable-MCP endpoint; its sibling HTTP API is used for historical reads http://10.10.0.2:18081/mcp
KIWIFS_MCP_TOKEN Bearer token for the KiwiFS HTTP/MCP service (optional; disables memory collection when absent)
KIWIFS_TIMEOUT KiwiFS request timeout in seconds 30
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) []

KiwiFS on media1

KiwiFS runs on Vega at http://10.10.0.2:18081/mcp. Add the shared bearer token to media1's private config.json as KIWIFS_MCP_TOKEN (or provide it through that service's environment). Do not add it to this repository or to config.json.example.

For each repository with activity, the report reads same-day writes under pages/projects/<repository>/ plus scoped episodic entries under episodes/. It retrieves the historical file revision from KiwiFS, so backfills retain the memory content that existed on the reported day. KiwiFS failures never 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 KiwiFS memory revisions 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.