guru
Windguru CLI + MCP + Python library for kiters and agents — free named spots, WINDGURU DEFAULT top models, gear advice. No HTML scraping. No PRO.
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 to the human like a kiter, not like a JSON dump.
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)
Checkguru doctor --json→upgrade.update_available, orguru instruct --json→data.upgrade. - Confirm:
guru doctorandguru instruct --json. - Immediately check the profile. If
first_pass/ready=false/range_ready=false, your first reply to the human must be the intake prompt (include level). Do not run weekend/best yet. - Wire tools for the host you are in:
- Cursor / Claude Desktop / local Codex with MCP → ensure MCP server
gururunsguru-mcp(full path fromwhich guru-mcpif needed). Then prefer MCP tools over shell. - Shell-capable agent (Cursor Agent, Codex, Claude with bash) → run
guru … --jsonif MCP is not configured yet. - Claude Cowork / claude.ai → local STDIO MCP will not work. Either run CLI in a local terminal the user controls, or start
guru-mcp-httpand help them add a public HTTPS URL under Customize → Connectors. Do not pretend localhost is reachable from Anthropic’s cloud. - ChatGPT cloud → same as Cowork for MCP (needs public HTTP), otherwise guide install + have the user paste
guru … --jsonoutput, or use whatever shell/Code Interpreter the product gives you.
- Cursor / Claude Desktop / local Codex with MCP → ensure MCP server
MCP config (Cursor / Claude Desktop):
{
"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 weekend --json |
weekend_spots — narrate data.schedule (whole horizon) |
| 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. - 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 |
weekend_spots |
“Where can I kite?” |
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 …
pipx install 'windguru[mcp]' # + MCP: guru-mcp / guru-mcp-http
guru --help
Or with pip: pip install windguru / pip install 'windguru[mcp]'.
PyPI: windguru · commands: guru, guru-mcp, guru-mcp-http
Host cheat sheet
| Host | Wire |
|---|---|
| Cursor | MCP guru-mcp and/or shell guru … --json + optional skills/guru/SKILL.md |
| Claude Desktop | Local STDIO in claude_desktop_config.json |
| Claude Cowork / claude.ai | Remote custom connector → public HTTPS to guru-mcp-http (docs) |
| Codex / shell agents | pipx install windguru then guru … --json |
| ChatGPT cloud | Public HTTP MCP/Action you host, or user runs CLI and pastes JSON |
guru-mcp-http listens at http://127.0.0.1:8000/mcp/ — Cowork/claude.ai need that URL exposed publicly; there is no hosted Windguru MCP in this repo.
CLI
| Command | Role |
|---|---|
guru setup |
Rider + home range (sport / weight / level / quiver / drive_km) |
guru profile |
Show profile + missing fields |
guru weekend |
Where can I kite? ~4-day schedule + top-3 model agree |
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 |
Discoverability |
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.5
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.5.tar.gz | 382.5 kB | Without provenance | Details for windguru-0.3.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| windguru-0.3.5-py3-none-any.whl | Python 3 | none | any | Details for windguru-0.3.5-py3-none-any.whl |
Total release size: 431.7 kB
Release files / windguru-0.3.5.tar.gz
| Download URL | windguru-0.3.5.tar.gz |
|---|---|
| Size | 382.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6151f10360d4458d9071c504d02dea6ffa836beb847251c79d3303455e4f3a10
|
|
BLAKE2b-256 checksum How to use checksums |
f8a9a8ee41effcea2f44c66b543cb52c8f039ba9401071be605986482755e089
|
| 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.5-py3-none-any.whl
| Download URL | windguru-0.3.5-py3-none-any.whl |
|---|---|
| Size | 49.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
431750e12db6da7a414b1a05c25eb37a286e2a6ac925f37e3d5065772921475a
|
|
BLAKE2b-256 checksum How to use checksums |
f5a535beeefcce0c1827302b3e30b9b215c97f0605dc02d1aac0dd9ce4f247e4
|
| 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.5
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.