Fetch, score, and browse CTF writeups in a terminal UI.
Pulls writeups from CTFtime's RSS feed, enriches them with event quality data from the CTFtime API, computes a composite quality score, stores everything in a local SQLite database (deduplicated), and presents it all in a Textual TUI.
python3 -m venv .venv
source .venv/bin/activate
pip install -e .# Fetch + launch TUI (default)
writeups-fetcher
# Fetch only (stores to SQLite, no TUI)
writeups-fetcher fetch
writeups-fetcher fetch --pages 5 # scrape 5 pages (~150 writeups)
writeups-fetcher fetch --pages 3 --days 60 # 3 pages, wider event window
writeups-fetcher fetch --min-score 50 # only keep high-quality
# TUI only (browse existing data)
writeups-fetcher tui
# Database stats
writeups-fetcher statsOr run as a module:
python -m writeups_fetcher fetch
python -m writeups_fetcher tui| Key | Action |
|---|---|
f |
Fetch new writeups from CTFtime |
o |
Open original writeup URL in browser |
c |
Open CTFtime page in browser |
r |
Refresh table |
/ |
Focus search bar |
q |
Quit |
Use the dropdowns to filter by tag or minimum quality score.
Each writeup gets a composite score (0-100) computed from:
| Signal | Weight | Source |
|---|---|---|
| CTFtime writeup rating | 40% | RSS feed (0-5 scale) |
| CTF event weight | 35% | /api/v1/events/ (0-100) |
| Has original writeup link | 10% | RSS <original_url> |
| Has tags/topics | 10% | RSS description |
| Top-50 team authorship | 5% | /api/v1/top/ |
Unrated writeups receive a neutral 2.5/5 for the rating component.
- CTFtime RSS (
https://ctftime.org/writeups/rss/) -- primary writeup feed with ratings, tags, and original URLs - CTFtime Events API (
/api/v1/events/) -- event weights reflecting CTF quality (0-100 scale; 90+ = elite, 50-89 = advanced) - CTFtime Top Teams API (
/api/v1/top/) -- current year's top 50 teams for reputation scoring
SQLite database stored at ~/.local/share/writeups_fetcher/writeups.db by default. Override with --db /path/to/db.
Re-running fetch upserts (inserts or updates) by CTFtime writeup ID -- no duplicates.
src/writeups_fetcher/
__main__.py # CLI entry point
fetcher.py # RSS + API fetching
scorer.py # quality scoring
db.py # SQLite operations
tui.py # Textual TUI
models.py # dataclasses