Metadata-Version: 2.4
Name: opensky-cli
Version: 0.1.0
Summary: The first agentic flight search engine. Searches hundreds of routes in minutes, not hours.
Project-URL: Homepage, https://github.com/federicodeponte/opensky
Project-URL: Repository, https://github.com/federicodeponte/opensky
Author: Federico De Ponte
License-Expression: MIT
License-File: LICENSE
Keywords: cli,flight-search,flights,google-flights,price-comparison,travel
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet
Requires-Python: >=3.11
Requires-Dist: airportsdata>=20240101
Requires-Dist: curl-cffi>=0.7
Requires-Dist: diskcache>=5.6
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.10
Requires-Dist: ratelimit>=2.2
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.15
Description-Content-Type: text/markdown

# opensky

The first agentic flight search engine. Define your origins, destinations, and dates, and opensky searches every combination for you, in minutes instead of hours.

```
$ opensky scan --config scan.toml

Scanning 6 origins x 6 destinations x 10 dates = 360 combos via google

Best per Destination
Destination   Price   Date         Duration   Route
Amsterdam     €289    Tue Mar 17   11h 20m    Bangkok → Amsterdam
Berlin        €312    Thu Mar 12   12h 45m    Kuala Lumpur → Berlin
Frankfurt     €298    Wed Mar 11   11h 50m    Bangkok → Frankfurt
Hamburg       €357    Tue Mar 10   13h 10m    Bangalore → Dubai → Hamburg
Munich        €315    Fri Mar 13   12h 30m    Delhi → Munich
Copenhagen    €345    Mon Mar 16   13h 10m    Singapore → Copenhagen
```

Doing this manually on Google Flights would take 360 individual searches. opensky does it in one command.

## How it works

1. You define a search space: origins, destinations, date range
2. opensky searches every combination across up to three providers (Google Flights, Duffel, Amadeus)
3. Results are deduplicated, scored, and presented as a price matrix with the cheapest options highlighted

It also works for single route searches:

```bash
opensky search bangalore hamburg tomorrow
opensky search BLR HAM next monday
opensky search BLR HAM mar 15
```

## Install

Requires Python 3.11+.

```bash
pip install opensky
```

Or from source:

```bash
git clone https://github.com/federicodeponte/opensky.git
cd opensky
python -m venv .venv && source .venv/bin/activate
pip install -e .
```

Copy `.env.example` to `.env` and fill in any API keys you have (optional, Google Flights works without any keys).

## Quick demo

See what opensky does without any API keys or network calls:

```bash
opensky demo
```

![opensky demo](demo.gif)

## Usage

### Multi-route scan (the power feature)

Search every combination of origins, destinations, and dates at once.

#### Interactive setup

```bash
opensky config init
```

```
opensky config init

Where are you flying from? (comma-separated cities or codes): bangalore, delhi, bangkok
  → BLR (Bangalore), DEL (Delhi), BKK (Bangkok)
Where to? (comma-separated cities or codes): hamburg, frankfurt, amsterdam
  → HAM (Hamburg), FRA (Frankfurt), AMS (Amsterdam)
Start date (YYYY-MM-DD): mar 15
End date (YYYY-MM-DD): mar 25
Currency [EUR]:

Created scan.toml. Next: opensky scan --config scan.toml
```

Then run:

```bash
opensky scan --config scan.toml
```

#### Quick template

```bash
opensky config init --quick    # dumps template, no prompts
# edit scan.toml with your routes and dates
opensky scan --config scan.toml
```

6 origins x 6 destinations x 10 dates = 360 searches, one command. You get:
- **Best per destination**: cheapest flight to each city, with date and route
- **Price matrix**: prices across all dates, cheapest highlighted
- **Stats**: total flights found, price range

```bash
opensky scan --config scan.toml --all-flights    # show every flight, not just summary
opensky scan --config scan.toml --workers 5      # parallel workers (default: 3)
opensky scan --config scan.toml --json -o results.json
```

Scans are cached. If interrupted, re-run the same command to resume where it left off.

#### Scan config

```toml
[search]
origins = ["BLR", "DEL", "BOM", "KUL", "BKK", "SIN"]
destinations = ["HAM", "FRA", "MUC", "BER", "AMS", "CPH"]
cabin = "economy"
currency = "EUR"
stops = "any"

[search.date_range]
start = "2026-03-10"
end = "2026-03-20"

[scoring]
price_weight = 1.0
duration_weight = 0.5

# Optional: add ground transit time for scoring
[connections]
final_destination = "Hamburg"

[connections.transit_hours]
HAM = 0
BER = 2
FRA = 4

[safety]
risk_threshold = "high_risk"
```

### Single route search

Use city names, IATA codes, or friendly dates:

```bash
opensky search bangalore hamburg tomorrow
opensky search BLR HAM next monday
opensky search BLR HAM mar 15 --class business
opensky search BLR HAM 2026-03-10 --source duffel
opensky search BLR HAM 2026-03-10 --json
opensky search BLR HAM 2026-03-10 --fresh
```

Options:
- `--class` / `--cabin`: Travel class (economy, premium, business, first)
- `--stops`: Max stops (nonstop, 1, 2, or any)
- `--max-price`: Maximum price (0 = no limit)
- `--fresh` / `--no-cache`: Skip cached results
- `--source` / `--provider`: Flight data source (google, duffel, amadeus)
- `--include-risky`: Include flights through conflict zones
- `--json` / `--csv`: Machine-readable output
- `--output` / `-o`: Save results to file
- `--currency` / `-c`: Currency code (EUR, USD, GBP, etc.)

## Providers

opensky aggregates results from up to three flight data sources. When multiple providers are configured, results are deduplicated (same flight from two sources keeps the cheapest price).

| Provider | Env vars | Notes |
|----------|----------|-------|
| Google Flights | none (default) | Scrapes Google Flights. Needs residential IP. |
| [Duffel](https://duffel.com) | `OPENSKY_DUFFEL_TOKEN` | Free unlimited searches. |
| [Amadeus](https://developers.amadeus.com) | `OPENSKY_AMADEUS_KEY` + `OPENSKY_AMADEUS_SECRET` | Free tier: 2,000 calls/month. |

## Conflict zones

opensky ships with a conflict zone database. By default, flights through high-risk airspace are filtered out. Use `--include-risky` to see all options.

```bash
opensky zones              # list active conflict zones
opensky zones --update     # fetch latest data
```

## Limitations

- **Residential IP required**: Google Flights blocks datacenter IPs. Use `--proxy` on servers. Duffel and Amadeus work from any IP.
- **Rate limits**: All providers rate-limited to 10 req/sec. Default scan settings (3 workers, 1s delay) are conservative.
- **Price accuracy**: Prices may differ from airline websites. Always verify before booking.

## Credits

Flight data API based on [fli](https://github.com/punitarani/fli) by Punit Arani (MIT license). Airport metadata from [airportsdata](https://github.com/mborsetti/airportsdata).

## License

MIT
