Keeper recommendations, draft board rankings, and strategic analysis for Yahoo Fantasy Football.
Most fantasy tools are dashboards: they show data, you decide. wuff is designed as an
agent — something that perceives league state, reasons about decisions using
league-specific learned patterns (not just generic expert consensus), and is working
toward eventually acting on those decisions itself. The core bet: a league's own multi-year
history is more predictive of this league's behavior than a national ranking site — see
app/qb_historical_adjustment.py for a concrete example (QB draft-slot targets computed
fresh from this league's own draft history each run, not hand-tuned).
Where it stands today: a strong "on-demand advisor" — ask it for a keeper board, a mock draft, or a QB-adjusted ranking, and it returns a scored recommendation with rationale, grounded in this league's own draft/keeper history. Read-only against Yahoo (write access requires manual API approval, currently pending).
What's next: closing the feedback loop. app/outcome_log.py (added 2026-07-31) logs
every keeper and QB-draft-slot forecast the app makes, tagged with which scoring method
produced it, then resolve-outcomes matches those forecasts against actual draft results
once a season's draft happens. Right now it records forecast accuracy; the next step is
having something read that log back and actually adjust scoring — that's what turns this
from a tool that makes recommendations into one that improves them over time. After that:
a lineup optimizer and trade evaluator (the two most common in-season decisions, neither
built yet), and a platform abstraction layer so the reasoning core stops being Yahoo-shaped.
# Install dependencies (creates .venv, installs Python packages)
make install
# Set up credentials (copy template and add OAuth tokens)
cp .env.example .env
# Run web dashboard
make web
# Opens at http://127.0.0.1:5001# Parse league rosters from Yahoo (copy-paste text when prompted)
python3 -m app parse-rosters
# Generate keeper recommendations for all teams
python3 -m app keepers-board-export
# View keeper board in web dashboard
make web# Combine multiple ranking sources
python3 -m app combine-rankings
# Pull fresh rankings from Yahoo
python3 -m app refresh-yahoo-rankings
# Import ADP (used to enrich keeper forecasts / mock draft)
python3 -m app import-adp data/raw/adp/fantasypros_adp.csv# Analyze historical draft data
python3 -m app draft-history 2025 --live-only
python3 -m app draft-order 2025Run make web or make web-debug for hot-reload during development.
Routes:
/— Dashboard with roster, rankings, and keeper insight/keepers-board— Team keeper picks + draft board (versioned by snapshot)/mock-draft— Full 15-round mock draft simulator (BPA + manager tendencies)/draft-history— Historical draft results by year/standings— League standings and performance
Requirements: Python 3.9+
Installation:
make install # Create venv + install dependencies
make install-dev # Create venv + install dependencies + pylint
make clean # Remove venvLinting:
make lint # Run pylint over app/ (config: .pylintrc)Yahoo OAuth:
Register callback at https://localhost:3000/oauth/callback in Yahoo app settings, then:
make auth-server # Start local HTTPS server for OAuth flowConfiguration: data/config/league_rules.json — keeper rules, file mappings, code ownership
Key data:
data/raw/rosters/— League roster snapshotsdata/raw/rankings/— Multi-source rankings (Yahoo, ESPN, FantasyPros, etc.)data/raw/draft_history/— Historical picks by seasondata/processed/keeper_exports/— Keeper board CSV exports (timestamped by method)data/processed/outcome_log.json— Forecast-vs-actual log (generated locally, gitignored); seeapp/outcome_log.py
Keeper logic: app/strategy.py — eligibility, scoring, and selection
Full command reference: python3 -m app --help
- Cost: 2 keepers per team, no round cost (occupy last 2 rounds)
- Eligibility: Round 1 or 2 pick from last draft ineligible
- Duration: Max 2 consecutive seasons as keeper
- Scoring: Rank-first, with positional scarcity + multi-year tenure as tiebreaks
Details: data/config/league_rules.json + CLAUDE.md