Kudosy automatically gives kudos on Strava to activities in your following feed β based on configurable distance and duration rules, with human-like random timing so it doesn't look like a bot.
β οΈ Strava Terms of Service notice: Kudosy authenticates using your personal_strava4_sessionbrowser cookie (web session), not the official Strava API/OAuth. This is a personal/educational tool β use it responsibly. Keep the scheduler interval generous and rely on the built-in delays and jitter to stay under the radar. You are solely responsible for compliance with Strava's ToS.
- π€ β π§ Human-like timing β randomised interval jitter and per-kudos delays between requests
- βοΈ Web UI β German-language interface with four tabs (Config, Defaults, Settings, Status & Log)
- π§© Flexible rules β catch-all + per-sport-type distance/duration thresholds, activity-name regex overrides
- π Scheduler β configurable interval, enable/disable, dry-run mode
- π³ Docker-first β single
docker compose upto run - π§ͺ Test-driven β β₯85% test coverage, pure functions tested in isolation
# Clone the repo
git clone https://github.com/bin101/kudosy.git
cd kudosy
# Copy the example config and fill in your cookie + athlete ID
cp data/config.example.yaml data/config.yaml
$EDITOR data/config.yaml
# Start
docker compose up -d
# Open http://localhost:8080python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
KUDOSY_DATA_DIR=./data KUDOSY_PORT=8080 python -m kudosy- Log in to strava.com in your browser.
- Open DevTools β Application β Cookies β
https://www.strava.com. - Copy the value of
_strava4_session. - Paste it into
data/config.yamlasstravaSessionCookie, or enter it in the web UI.
The cookie expires β if Kudosy suddenly stops finding activities, refresh it here.
All config lives in ./data/ (mounted as /data in Docker):
| File | Purpose |
|---|---|
config.yaml |
Your session cookie, athlete ID, ignore list, per-sport rules |
defaults.yaml |
Catch-all and default per-sport thresholds |
settings.json |
Scheduler interval, jitter, per-kudos delays, dry-run flag |
athlete-labels.json |
Cached athlete ID β name lookups |
last-run.log |
Output of the most recent run |
See data/config.example.yaml for a fully annotated example.
Kudosy has two layers of randomness to avoid a detectable machine pattern:
- Interval jitter: each scheduled run fires after
intervalMinutes Β± jitterMinutes(uniform random). Default: 60 Β± 15 minutes. - Per-kudos delay: between each individual kudo POST, Kudosy waits a random duration in
[minKudosDelaySeconds, maxKudosDelaySeconds]. Default: 3β25 seconds. - Shuffle order: the list of activities to kudo can be shuffled randomly before sending.
All timing parameters are configurable in the web UI under Einstellungen.
Pre-built multi-arch images (amd64 + arm64) are published to GitHub Container Registry:
docker pull ghcr.io/bin101/kudosy:latestTags: latest (from main), vX.Y.Z (releases), X.Y (minor), commit SHA.
# Install
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# TDD cycle: write tests first, then implementation
pytest tests/unit/ # pure functions (fast)
pytest --cov=kudosy --cov-report=term-missing
# Lint & type-check
ruff check src tests
ruff format --check src tests
mypy srcSee CLAUDE.md for the full architecture guide.
Semantic Versioning via pyproject.toml. Releases are driven by
Conventional Commits and automated with
release-please.
See CHANGELOG.md for release history.
MIT β see LICENSE.