On each restart, CUE pulls the latest code from origin before binding to the port, so deployments just require a service restart. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BLIGHT: CUE
A module in the BLIGHT ecosystem.
BLIGHT: CUE monitors Gitea repositories containing markdown files. When a push is received, it scans changed files for BLIGHT: trigger lines, sends the surrounding document to an AI model along with the instruction, and writes the result back to the file in-place — fully automated.
How It Works
- You write a
BLIGHT:trigger anywhere in a markdown file and push it to Gitea. - Gitea sends a webhook POST to this server.
- The server fetches the file, finds all
BLIGHT:triggers, and processes them one by one. - Each trigger is replaced with the AI's response at the exact position of the trigger line.
- The updated file is committed back to the repo automatically.
Trigger Syntax
BLIGHT: <your instruction here>
Examples:
This paragraph discusses は vs が in Japanese grammar.
BLIGHT: Explain the key differences between は and が based on the paragraph above.
## Next Section
BLIGHT: Spell check this entire document and list any errors found.
BLIGHT: Write a conclusion paragraph for this document.
Failure Behavior
If the AI call fails after 3 attempts, the trigger is replaced with:
<!-- BLIGHT_FAILED: your original instruction -->
You can re-trigger processing by editing the file to restore the original BLIGHT: line and pushing again.
Prerequisites
- Python 3.10+
- Access to your Gitea instance (via Tailscale or local network)
- A Google Gemini API key
- A Gitea personal access token with repository read/write permissions
Installation
# 1. Clone this repo onto the machine that will run the listener
git clone <this-repo-url>
cd Blight_Reader
# 2. Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activate
# 3. Install dependencies
pip install -r requirements.txt
# 4. Copy the example env file and fill in your values
cp .env.example .env
Configuration
Edit .env with your values:
| Variable | Description |
|---|---|
GITEA_URL |
Base URL of your Gitea instance, no trailing slash |
GITEA_TOKEN |
Personal access token from Gitea → Settings → Applications |
GEMINI_API_KEY |
API key from Google AI Studio |
WEBHOOK_SECRET |
A secret string you choose — must match what you set in Gitea |
WEBHOOK_PORT |
Port the listener binds to (default: 5010) |
Running
python app.py
The server binds to 0.0.0.0:5010 (or your configured port). Keep it running as a service or in a screen/tmux session.
For production use, consider running it with a process manager:
# With systemd (example unit file)
# /etc/systemd/system/blight-cue.service
[Unit]
Description=BLIGHT: CUE webhook listener
After=network.target
[Service]
WorkingDirectory=/path/to/Blight_Reader
ExecStart=/path/to/Blight_Reader/.venv/bin/python app.py
Restart=always
[Install]
WantedBy=multi-user.target
Replace
/path/to/Blight_Readerwith the actual path. The venv Python is at.venv/bin/pythonrelative to the project root — create it withpython3 -m venv .venv && .venv/bin/pip install -r requirements.txt.
Registering the Webhook in Gitea
Do this for each repository you want BLIGHT: CUE to watch.
- Open the repository in Gitea.
- Go to Settings → Webhooks → Add Webhook → Gitea.
- Set the fields:
- Target URL:
http://<your-machine-ip>:5010/webhook - HTTP Method: POST
- Content Type:
application/json - Secret: the same value as
WEBHOOK_SECRETin your.env - Trigger On: Push events only
- Target URL:
- Click Add Webhook, then use Test Delivery to verify connectivity.
AI Provider
BLIGHT: CUE currently uses Google Gemini 2.5 Flash-Lite — the most cost-effective stable Gemini model (~$0.10/$0.40 per million tokens input/output).
Adding a New Provider
All AI providers implement the AIProvider abstract base class in ai/base.py:
from abc import ABC, abstractmethod
class AIProvider(ABC):
def complete(self, document: str, instruction: str) -> str:
...
To add a new provider (e.g. OpenRouter):
- Create
ai/openrouter.pyand implementAIProvider. - In
processor.py, replaceGeminiProvider()with your new class.
Project Structure
Blight_Reader/
├── app.py # Flask webhook server
├── processor.py # Trigger scanning and replacement logic
├── gitea_client.py # Gitea REST API wrapper
├── config.py # Environment config loader
├── ai/
│ ├── base.py # AIProvider abstract base class
│ └── gemini.py # Gemini 2.5 Flash-Lite implementation
├── requirements.txt
├── .env.example
└── README.md
Part of the BLIGHT Ecosystem
BLIGHT: CUE is one module in a larger modular system called BLIGHT. Each module is independently deployable and communicates through Gitea repositories as the shared data layer.