guru
██████╗ ██╗ ██╗██████╗ ██╗ ██╗ ██████╗ ██╗ ██╗
██╔════╝ ██║ ██║██╔══██╗██║ ██║ ██╔════╝ ██║ ██║
██║ ███╗██║ ██║██████╔╝██║ ██║ ███ ██║ ██║ ██║
██║ ██║██║ ██║██╔══██╗██║ ██║ ╚═╝ ██║ ██║ ██║
╚██████╔╝╚██████╔╝██║ ██║╚██████╔╝ ╚██████╗ ███████╗ ██║
╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚═╝
GURU-CLI · send it · right spot · thinking offloaded
kite bro who compiles · Wind + Guru energy, beach edition
Dr. Berend Gort · www.berendgort.dev
guru is the beach sibling of Windguru — named for the same idea: Wind + Guru (wind expert/guide). Václav Horník built Windguru as a Czech windsurfer who could code; this CLI is the kite bro / surfer dude who already blended the models and says SEND IT or SIT IT OUT. Less Tune tabs. More water time.
Windguru CLI + MCP + Python library for kiters and agents — free named spots, WINDGURU DEFAULT top models, gear advice. No HTML scraping. No PRO.
PyPI: https://pypi.org/project/windguru/
Free only — named spots + WINDGURU DEFAULT Tune top-3. No PRO lat/lon click-forecast.
Humans: paste this repo URL into Cursor, Claude, Codex, or ChatGPT and ask “set this up and tell me where I can kite.” The agent instructions below are written for that.
For AI agents (mandatory protocol)
If the user pasted https://github.com/berendgort/guru (or this README), you must follow this section exactly. Do not invent a Windguru scrape, browser walkthrough, or multi-question onboarding.
Goal
Onboard the rider on the first message, then answer kite questions with gear advice using the windguru package (guru CLI and/or guru-mcp tools). Speak like a kite bro who ships code (instruct → data.voice): SEND IT / SOFT CALL / SIT IT OUT — honest, lightly funny (programmer ∩ kiter jokes), never hype a long haul. Not a JSON dump. If asked about the name: data.voice.lore (Windguru = Wind + Guru).
Bootstrap (do this first)
- Prefer PyPI, and upgrade every session before briefing:
pipx upgrade windguru || pipx install 'windguru[mcp]' # or: pip install -U 'windguru[mcp]' (activate venv first)
- Run
guru doctor --json— checknetwork.reachableandupgrade.update_available. - Never tell the human “this sandbox can’t reach Windguru” before unlock. If
network.reachableis false: runguru unlock --jsonyourself, then showrider_facing.text/say_to_rideronce (user-visible UX copy — not a system prompt). Still blocked / no shell: onehuman_fixrecipe. Never ask for pipx/shell/MCP JSON. - Immediately check the profile. If
first_pass/ready=false/range_ready=false, your first rider-facing reply must be the intake prompt (include level). Do not run weekend/best yet. - One path for every app:
guru … --jsonon a host that reaches Windguru. Wire/tunnel only if shellguruis unavailable and a local MCP host needs it.
Optional MCP (only if the host already uses MCP):
{
"mcpServers": {
"guru": {
"command": "guru-mcp"
}
}
}
Operating loop (every kite question)
| Step | CLI | MCP |
|---|---|---|
| 0. Recipe / profile | guru instruct --json or guru profile --json |
instruct / get_profile |
| 1. First pass if needed | see below | see below |
| 2. “Where can I kite?” | guru where --json [--day Thu] |
where_spots — narrate data.schedule (~3 days) |
| 2b. “This weekend?” | guru weekend --json |
weekend_spots — Fri eve / Sat / Sun; respect uncertain |
| Local knowledge | guru note <id> "dirs=SW-W offshore=N-NE …" |
persists in profile |
| 3. Named / numeric spot | guru best <id> --advise --json |
best_forecast with advise=true |
| 4. Ambiguous name | use candidates → ask user or pass id / --pick |
same via resolve_spot |
First pass (mandatory on the first kite message when ready=false or range_ready=false / first_pass=true):
- Your first message to the human must show exactly
data.intake.prompt_to_user(or the template below). Collect sport, weight, level (required — changes GO wind and sizing), quiver, wetsuits, home range — one message. - Wait for one reply (key=value paste). Do not ask sport, then weight, then kites separately. Do not skip intake.
- Run:
guru setup --intake '<their paste>' --json
or MCPsetup_profilewith the same fields (includinglevel). - Only then continue with weekend / best.
Template to show if you cannot read prompt_to_user yet:
sport=kitefoil weight=78 level=intermediate kites=7,9,12 wetsuits=3/2,4/3 session=3 home=41.39,2.17 drive_km=200 range=Trabucador → Leucate
How to talk to the human
After tools return, narrate for a rider:
- Verdict: GO / MARGINAL / NO-GO
- Week plan from
schedule(Tue / Wed / Thu…) — do not wait for “what about Thursday?” - Best spot + rough drive distance
- Window in local-friendly terms if you can, else UTC
- Wind + gusts; model_agree; size for gusts
- Kite size from quiver; wetsuit for session hours
- Short checklist: watch beach 5 min, side-shore preference, don’t long-drive for marginal
Do not dump raw model tables unless they ask.
Hard rules
- Use preset WINDGURU_DEFAULT only (
guru best/best_forecast). Do not default to raw GFS. - Never scrape windguru.cz HTML, Tune UI, or MapLibre.
- Never require PRO or invent lat/lon click-forecasts.
- On
error_type: ambiguous, pick fromcandidates— never silent first-match. - Respect
retryableon errors; don’t hammer rate limits. - Windguru calls are spaced (
GURU_MIN_INTERVAL, default 0.85s), short-TTL cached (GURU_CACHE_TTL), and stop after IP Forbidden (circuit). - Profile lives at
~/.config/guru/profile.json(override withGURU_CONFIG_DIR).
MCP tool map
| Tool | Use for |
|---|---|
instruct |
Load this recipe into context |
get_profile / setup_profile |
Onboarding |
where_spots |
“Where can I kite?” (~3 days) |
weekend_spots |
Next Fri eve / Sat / Sun; check uncertain / coverage |
search_spots / resolve_spot / near_spots |
Find spot ids |
best_forecast (advise=true) |
Single spot + gear |
get_forecast / list_models |
Escape hatches only |
More: docs/mcp.md · skill copy: skills/guru/SKILL.md
Install
pipx install windguru # CLI: guru … ← canonical path for every app
pipx install 'windguru[mcp]' # + optional STDIO/HTTP adapters
guru doctor --json
Or with pip: pip install windguru / pip install 'windguru[mcp]'.
PyPI: windguru
Every app: guru … --json on a host that reaches Windguru. Optional guru-mcp is the same library for STDIO hosts. Cloud sandboxes that block Windguru are unsupported — move to a local agent; do not tunnel by default.
CLI
| Command | Role |
|---|---|
guru setup |
Rider + home range (sport / weight / level / quiver / drive_km) |
guru profile |
Show profile + missing fields |
guru where |
Where can I kite? ~3-day schedule + top-3 model agree (--day Thu) |
guru weekend |
Next kite weekend only: Fri evening / Sat / Sun; flags uncertain if high-% models short |
guru note |
Save local knowledge / wind sectors (dirs= offshore=) |
guru instruct |
Teach agents the workflow |
guru spots <q> |
Name search (resolve id) |
guru near --lat --lon |
Free map markers near a point |
guru best <spot> |
Spot call + gear advice (default; --no-advise for raw) |
guru forecast <spot> -m gfs |
Single model escape hatch |
guru models / schema / doctor / wire |
Discoverability + network probe + optional MCP adapters |
Ambiguous names fail with error_type: ambiguous + candidates (pass numeric id or --pick).
Library
from guru import get_best_forecast, search_spots
from guru.rider.advice import advise_forecast, drive_km_from_home
from guru.rider.profile_store import load_profile
spots = search_spots("castelldefels")
best = get_best_forecast(201, top=3, hours=24)
profile = load_profile()
advice = advise_forecast(
best.forecasts[0], profile, drive_km=drive_km_from_home(profile, best.spot)
)
print(advice.verdict, advice.summary)
Develop
git clone https://github.com/berendgort/guru.git
cd guru
pipx install -e ".[dev,mcp]"
# or: python -m venv .venv && source .venv/bin/activate && pip install -e ".[dev,mcp]"
pytest -q
ruff check .
| Layer | Path | Role |
|---|---|---|
| Core | guru/core/ |
Shared envelope, errors, instruct recipe |
| CLI | guru/cli/ |
Typer + Rich + --json (thin over core) |
| MCP | guru/mcp/ |
FastMCP over core (no CLI imports) |
| Rider | guru/rider/ |
Profile store + kite/wetsuit advice |
| Search | guru/search/ |
HTTP (curl_cffi), blend_math, near, forecast |
| Models | guru/models/ |
Pydantic + aliases only |
| Wire | docs/WIRE.md |
Captured iapi.php |
| MCP | docs/mcp.md |
guru-mcp setup + tools |
Read AGENTS.md before extending. Capture Network → fixtures → tests.
Engineering standards (kept in-repo):
docs/code_quality.md— Korotkevich / Tourist bardocs/data_engineering_standards.md— Gray / Stonebraker bar
Disclaimer
Unofficial. Not affiliated with Windguru. Personal / research use; respect ToS and rate limits.
License
MIT
Metadata
Release files for windguru 0.3.26
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| windguru-0.3.26.tar.gz | 429.9 kB | Without provenance | Details for windguru-0.3.26.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| windguru-0.3.26-py3-none-any.whl | Python 3 | none | any | Details for windguru-0.3.26-py3-none-any.whl |
Total release size: 532.0 kB
Release files / windguru-0.3.26.tar.gz
| Download URL | windguru-0.3.26.tar.gz |
|---|---|
| Size | 429.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c1c67763a47417b07240a97b38da4861357c08ce4f8f5ba698025702a5f4bbaf
|
|
BLAKE2b-256 checksum How to use checksums |
db702ed9145cf77bbf9c145c0072c1d0f7435cca335120a07481accbf589b681
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / windguru-0.3.26-py3-none-any.whl
| Download URL | windguru-0.3.26-py3-none-any.whl |
|---|---|
| Size | 102.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c915bd3b06844f85b57f35ed27d9b75e435419793ed19ce46b8d818831e6f3ac
|
|
BLAKE2b-256 checksum How to use checksums |
a12b804f2a9e660ad8ec4026f1785d8524515bba308b720e57385f632fc14479
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for windguru 0.3.26
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.