# AGENTS.md ## Project Structure - `src/` — All application code (no subpackages) - `cli.py` — Entry point, argparse CLI with subcommands: add, remove, update, list, check, serve, daemon - `github.py` — GitHub REST API client (httpx), rate-limit aware, exponential backoff - `db.py` — SQLite layer with 0600 file permissions, upsert with UNIQUE(repo_id, tag_name) - `rss.py` — RSS 2.0 generation via xml.etree, markdown→plain text via markdown+bleach, 300-char truncation, 50-item cap - `server.py` — ThreadingHTTPServer with /feed.xml, /, /health endpoints - `config.py` — Centralized config (db_path, gh_token, defaults) - `tests/` — pytest test suite, 72 tests total ## Commands ```bash # Install for development pip install -e ".[test]" # Run all tests (use timeout to avoid server test hangs) timeout 30 python3 -m pytest tests/ -q # Run single test file python3 -m pytest tests/test_db.py -v # Run single test python3 -m pytest tests/test_db.py::TestCreateTables::test_tables_exist -v ``` ## Testing Quirks - `respx` is used to mock GitHub API calls in `test_github.py` - Integration tests in `test_integration.py` use `urllib` for localhost requests to avoid respx interception - Server tests spawn ThreadingHTTPServer — use `timeout 30` for full test suite to avoid hangs ## Key Gotchas - `--base-url` flag on `serve` command auto-appends port from `--port` (user only specifies hostname) - Tag date resolution uses commit SHA from tags API + `commits/{sha}` endpoint (works without auth for public repos) - Database uses `ON DELETE CASCADE` — removing a repo deletes its entries - `src` package requires `[tool.setuptools.packages.find]` in pyproject.toml for proper installation ## Environment - `GH_TOKEN` — GitHub token for API access (validate on startup if provided) - `GDB_REL_DB` — Override database path (default: `~/.local/share/ghrel/ghrel.db`)