Metadata-Version: 2.4
Name: cli-surf
Version: 2.2.1
Summary: Command-line surf report tool
License: MIT
License-File: LICENSE
Keywords: surf,surfing,weather,ocean,cli,terminal
Author: ryansurf
Author-email: your@email.com
Requires-Python: >=3.10
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Utilities
Requires-Dist: cachetools (>=7.0.5,<8.0.0)
Requires-Dist: curl-cffi (>=0.7.1,<0.8.0)
Requires-Dist: debugpy (>=1.8.20,<2.0.0)
Requires-Dist: email-validator (==2.1.1)
Requires-Dist: fastapi (>=0.135.2,<0.136.0)
Requires-Dist: flask (==3.0.3)
Requires-Dist: flask-cors (==5.0.0)
Requires-Dist: g4f (==0.3.2.2)
Requires-Dist: geopy (==2.4.1)
Requires-Dist: httpx (>=0.28.1,<0.29.0)
Requires-Dist: matplotlib (>=3.9.0)
Requires-Dist: numpy (>=1.26.4,<2.0.0)
Requires-Dist: openai (>=1.30.5,<2.0.0)
Requires-Dist: openmeteo-requests (==1.2.0)
Requires-Dist: pandas (==2.2.2)
Requires-Dist: pydantic (>=2.12.5,<3.0.0)
Requires-Dist: pydantic-settings (==2.2.1)
Requires-Dist: pymongo[gssapi,snappy,srv,tls] (>=4.15.4,<5.0.0)
Requires-Dist: python-dotenv (==1.0.1)
Requires-Dist: requests (==2.32.4)
Requires-Dist: requests-cache (==1.2.0)
Requires-Dist: retry-requests (==2.0.0)
Requires-Dist: seaborn (>=0.13.2,<0.14.0)
Requires-Dist: streamlit (>=1.35.0,<2.0.0)
Requires-Dist: streamlit-folium (>=0.22.0,<0.23.0)
Requires-Dist: uvicorn (>=0.42.0,<0.43.0)
Project-URL: Homepage, https://github.com/ryansurf/cli-surf
Project-URL: Repository, https://github.com/ryansurf/cli-surf
Description-Content-Type: text/markdown

![pytest](https://github.com/ryansurf/cli-surf/actions/workflows/pytest.yml/badge.svg)
![linter](https://github.com/ryansurf/cli-surf/actions/workflows/linter.yml/badge.svg)
[![codecov](https://codecov.io/github/ryansurf/cli-surf/graph/badge.svg?token=N8CAIUXMJG)](https://codecov.io/github/ryansurf/cli-surf)
![GitHub last commit](https://img.shields.io/github/last-commit/ryansurf/cli-surf)

**cli-surf** is a real-time ocean data and surf forecasting tool for the command line.

- Live wave height, swell direction, period, UV index, wind, and more
- Forecasts up to 7 days out
- Use as a CLI tool (`surf`) or query via HTTP API / browser
- Optional GPT-powered surf reports
- Supports metric and imperial units, custom colors, and JSON output

Inspired by [wttr.in](https://github.com/chubin/wttr.in) · [Documentation](https://ryansurf.github.io/cli-surf/) · [Discord](https://discord.gg/He2UpxRuJP)

    cli-surf gif

---

## Table of Contents

- [Usage](#-usage)
- [Setup](#️-setup)
  - [Poetry](#how-to-start-locally-with-poetry)
  - [Docker](#how-to-start-with-docker)
  - [Environment Variables](#variables)
  - [Email Server](#email-server)
  - [MongoDB](#mongodb)
- [GPT Surf Report](#-gpt-surf-report)
- [Tech Stack](#-tech-stack)
- [Contributing](#-contributing)
- [Contributors](#-contributors)

---

## 💻 Usage

There are two ways to use cli-surf: install it as a CLI tool via pipx, or run the server and access it via API/browser.

### Installing via [pipx](https://pipx.pypa.io/stable/) ([pypi](https://pypi.org/project/cli-surf/))

```bash
brew install pipx
pipx install cli-surf
```

```bash
surf --help
surf --location scripps_pier --forecast 4
```

### Running the server and using via API

Start the server locally (see [Setup](#️-setup) below), then query it from your browser or CLI:

```
$ curl localhost:8000

Location:  San Diego

      .-``'.
    .`   .`
_.-'     '._ 

UV index:  6.4
Wave Height:  3.9
Wave Direction:  238.0
Wave Period:  9.8

```

**API Examples**
> Arguments are separated by commas.

```bash
curl localhost:8000
curl localhost:8000?location=new_york,hide_height,hide_wave,show_large_wave
curl localhost:8000?fc=3,hdate,loc=trestles,c=light_blue
curl localhost:8000?show_past_uv,show_height_history,show_direction_history,show_period_history
curl localhost:8000?loc=malibu,gpt,color=yellow
curl localhost:8000?loc=nazare,json
```

For the full argument reference, see below or run:
```bash
curl localhost:8000/help
```

**API Arguments**

*Display*

| Argument | Shorthand | Description |
|---|---|---|
| `location` | `loc` | Location for the forecast. Ex: `loc=new_york_city` or `loc=nyc` |
| `hide_wave` | `hw` | Hide the default wave art |
| `show_large_wave` | `slw` | Show the large wave art |
| `color` | `c` | Color of wave art. Ex: `color=light_blue` |
| `hide_location` | `hl` | Hide location name |
| `hide_date` | `hdate` | Hide date in forecast |
| `metric` | `m` | Use metric units (default: imperial) |
| `decimal` | `dec` | Specify decimal places in output |
| `json` | `j` | Output data as JSON. Must be the only argument |

*Surf Conditions*

| Argument | Shorthand | Description |
|---|---|---|
| `hide_height` | `hh` | Hide wave height |
| `hide_direction` | `hdir` | Hide swell direction |
| `hide_period` | `hp` | Hide swell period |
| `hide_uv` | `huv` | Hide UV index |
| `show_air_temp` | `sat` | Show air temperature |
| `show_wind_speed` | `sws` | Show wind speed |
| `show_wind_direction` | `swd` | Show wind direction |
| `show_rain_sum` | `srs` | Show rain sum |
| `show_precipitation_prob` | `spp` | Show max precipitation chance |
| `show_cloud_cover` | `scc` | Show hourly cloud cover |
| `show_visibility` | `sv` | Show hourly visibility |

*Historical Data*

| Argument | Shorthand | Description |
|---|---|---|
| `show_past_uv` | `spuv` | Show past UV index |
| `hide_past_uv` | — | Hide past UV index |
| `show_height_history` | `shh` | Show past wave height |
| `hide_height_history` | — | Hide past wave height |
| `show_direction_history` | `sdh` | Show past wave direction |
| `hide_direction_history` | — | Hide past wave direction |
| `show_period_history` | `sph` | Show past wave period |
| `hide_period_history` | — | Hide past wave period |

*GPT*

| Argument | Shorthand | Description |
|---|---|---|
| `gpt` | `g` | Activate GPT surf report. Customize via `GPT_PROMPT` in `.env`. Default: off |

---

## 🛠️ Setup

### How to Start Locally with `Poetry`

1. Install [Poetry](https://python-poetry.org/docs/#installation).

2. Clone the repository.
    ```bash
    git clone https://github.com/ryansurf/cli-surf.git
    cd cli-surf
    ```

3. Install dependencies and activate the virtual environment.
    ```bash
    make install
    ```

4. Start the server.
    ```bash
    poetry run python src/server.py

    # Or via Makefile
    make run
    ```

### How to Start with `Docker`

1. Install [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/).

2. Clone the repository.
    ```bash
    git clone https://github.com/ryansurf/cli-surf.git
    cd cli-surf
    ```

3. Start the container.
    ```bash
    docker compose up -d

    # Or via Makefile
    make run_docker
    ```

### Variables

When running locally with Poetry, create a `.env` file from the example:
```bash
cp .env.example .env
```

When starting with Docker, the `.env` file is created automatically from `.env.example` during the image build.

**General**

| Variable | Description |
|---|---|
| `PORT` | Port to run the application on. Default: `8000` |
| `IP_ADDRESS` | IP address the server runs on. Default: `localhost` |

**Email** *(optional — see [Email Server](#email-server))*

| Variable | Description |
|---|---|
| `SMTP_SERVER` | Email server. Default: `smtp.gmail.com` |
| `SMTP_PORT` | Email server port. Default: `587` |
| `EMAIL` | Address to send the report from |
| `EMAIL_PW` | Sending email's password |
| `EMAIL_RECEIVER` | Address to receive the report |
| `COMMAND` | Command shown in the email. Default: `localhost:8000` |
| `SUBJECT` | Email subject line. Default: `Surf Report` |

**GPT** *(optional — see [GPT Surf Report](#-gpt-surf-report))*

| Variable | Description |
|---|---|
| `GPT_PROMPT` | Prompt sent to the model along with surf data. Ex: `With this data, recommend what size board I should ride.` |
| `API_KEY` | OpenAI API key. Create one [here](https://platform.openai.com/api-keys) |
| `GPT_MODEL` | OpenAI model to use. Default: `gpt-3.5-turbo` (recommended: `gpt-4o`). See all models [here](https://platform.openai.com/docs/overview) |

**Database** *(optional — see [MongoDB](#mongodb))*

| Variable | Description |
|---|---|
| `DB_URI` | MongoDB connection URI |

### Email Server

Optional — sends a surf report to a specified email on a schedule.

You'll need an email account with SMTP access. Gmail works; follow Method #1 [here](https://www.cubebackup.com/blog/how-to-use-google-smtp-service-to-send-emails-for-free/), then update the email variables in `.env`.

> Note: The FastAPI server must be running to send emails.

```bash
# Send email locally (Poetry)
make send_email

# Send email via Docker
make send_email_docker
```

### MongoDB

Optional — stores all request output in a MongoDB database.

See the [MongoDB get started guide](https://www.mongodb.com/docs/get-started/?language=python) for setup, then set `DB_URI` in your `.env`.

### Frontend

Note: The frontend is no longer maintained

    cli-surf_website gif

Although this application was made with the CLI in mind, a frontend exists.

**Streamlit Frontend**

```bash
streamlit run src/dev_streamlit.py
# Available at http://localhost:8502
```

**HTML/JS/CSS Frontend** *(legacy, no longer actively developed)*

Available at `http://localhost:8000/home` or `<ip_of_host>:<port>/home`.

You may need to set `IP_ADDRESS` in `.env` to match the host's IP.

---

## 🧠 GPT Surf Report

cli-surf can generate personalized surf reports using OpenAI's GPT models.

**Setup**

1. Get an OpenAI API key at [platform.openai.com](https://platform.openai.com/api-keys). Make sure a payment method is added.

2. Update `.env`:
   ```bash
   API_KEY=your_openai_api_key_here
   GPT_MODEL=gpt-3.5-turbo   # gpt-4o recommended for better results
   GPT_PROMPT=With this data, recommend what size board I should ride and nearby surf spots that may be better with the given conditions.
   ```

3. Use the `gpt` argument:
   ```bash
   curl localhost:8000?location=Malibu,gpt
   ```

**Customizing the prompt**

Change `GPT_PROMPT` in `.env` to get different types of reports:
```bash
GPT_PROMPT="Analyze the surf conditions and suggest the best time of day to surf."
GPT_PROMPT="What are some good places to eat around this surf spot?"
```

**Notes**
- A payment method is required — OpenAI will reject requests from free accounts.
- GPT responses consume tokens based on prompt and response size.
- Response time may be slower than standard output, especially during OpenAI outages.
- `gpt-4o` gives better results than `gpt-3.5-turbo` but costs more.

---

## 🔧 Tech Stack

| Layer | Technology |
|---|---|
| Language | Python 3.10+ |
| Web framework | FastAPI + Uvicorn |
| CLI | Click |
| Weather data | [Open-Meteo API](https://open-meteo.com/) |
| Optional AI | OpenAI GPT API |
| Optional database | MongoDB (pymongo) |
| Optional frontend | Streamlit |
| Packaging | Poetry, pipx |
| Containerization | Docker / Docker Compose |

---

## 📈 Contributing

Thank you for considering contributing to cli-surf!

See [CONTRIBUTING.md](https://github.com/ryansurf/cli-surf/blob/main/CONTRIBUTING.md) to get started.

Questions? Comments?

* [Discord](https://discord.gg/He2UpxRuJP)
* [Discussions](https://github.com/ryansurf/cli-surf/discussions)
* [GitHub](https://github.com/ryansurf)

---

## ✨ Contributors

[![All Contributors](https://img.shields.io/github/all-contributors/ryansurf/cli-surf?color=ee8449&style=flat-square)](#contributors)

       Ryan Frederich
Ryan Frederich (https://ryansurf.github.io/)
💻 📖 ⚠️ 🤔 💬
       𝕂' 
𝕂'  (https://github.com/K-dash)
💻 📖 ⚠️ 🤔 💬
       Corey L.
Corey L. (https://github.com/death12239)
💻
       Shaiful Azhar
Shaiful Azhar (https://github.com/shaifulazh)
💻
       Hummus-Ful
Hummus-Ful (https://github.com/Hummus-Ful)
🚇
       Rajiv-Rago
Rajiv-Rago (https://github.com/Rajiv-Rago)
💻
       Ulises-Sanch3z
Ulises-Sanch3z (https://github.com/Ulises-Sanch3z)
💻

       Andrew Koller
Andrew Koller (https://github.com/avkoll)
💻
       Michael McGrain
Michael McGrain (https://github.com/mrmcgrain)
💻
       SeanAverS
SeanAverS (https://github.com/SeanAverS)
💻
       Rabel Mervin 
Rabel Mervin  (https://github.com/rabelmervin)
💻
       Vaibhav Chouhan
Vaibhav Chouhan (https://github.com/vaibhav-2703)
💻
       Nandani Thakur 
Nandani Thakur  (https://github.com/NandaniThakur)
💻
       Brandon
Brandon (https://github.com/hotpocket)
🚇

       ChristianToro
ChristianToro (https://github.com/ChristianToro)
💻 🐛
       Myles B.
Myles B. (https://github.com/MylesPerHour201)
💻
       Balaji Ganapathy
Balaji Ganapathy (https://github.com/balugans)
🐛
       chengjackjelly
chengjackjelly (https://github.com/chengjackjelly)
🚇
       Varun Singh
Varun Singh (https://github.com/vsingk)
📖 🐛
       macnult
macnult (https://github.com/macnult)
💻
       AITMAR-TAFE
AITMAR-TAFE (https://github.com/AITMAR-TAFE)
💻

       Latif Fetahaj
Latif Fetahaj (https://github.com/latiffetahaj)
💻 ⚠️
       Kim
Kim (http://www.kimcodes.lol)
⚠️ 💻
       Devon Hebenton
Devon Hebenton (https://github.com/hebentod)
💻
       AristosKass
AristosKass (https://github.com/AristosKass)
⚠️
       Raza Khan
Raza Khan (https://github.com/raza-khan0108)
💻

## License
[![License](https://img.shields.io/:license-mit-blue.svg?style=flat-square)](https://badges.mit-license.org)

