Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

✈️ flypi

Live flight price search + route watching from the command line, using live Google Flights data. Four small verbs, plain text or JSON out — no chat code, no account, no API key.

Ships as a pi coding agent skill but is a pure CLI: any agent, cron job, or script can drive it.

  • (a) flypi search FROM TO DATE [--return] [filters] — live fares, cheapest first
  • (b) flypi watch add|list|rm|history ... — remember a trip and track its price
  • (c) flypi check — re-search every watch, print/notify on drops
  • (d) flypi notify off|cmd|agent — where alerts go: printed, piped to a command (ntfy/Telegram/anything), or delivered by your agent over chat

Search engine: fli (pip install flights), the same reverse-engineered Google Flights API used by flightclaw.

Requirements

  • Python ≥ 3.10

No accounts, API keys, or services needed. For push alerts, the only extra is the free ntfy phone app.

Install

With pi (recommended)

flypi is a pi package:

pi install git:github.com/sarguru/flypi          # or pin a release: ...@v0.5.0
cd ~/.pi/agent/git/github.com/sarguru/flypi
./scripts/setup.sh                               # one-time: venv + flight engine

The skill is then available to pi automatically (install with pi install; update with pi update; remove with pi remove git:github.com/sarguru/flypi). If a pi update replaces the checkout, re-run ./scripts/setup.sh once.

Manually (any agent or plain cron)

git clone https://github.com/sarguru/flypi.git
cd flypi
./scripts/setup.sh        # creates .venv, installs the flight engine
./scripts/flypi --version

As a pi skill, clone or symlink the repo into a skill directory such as ~/.pi/agent/skills/flypi, then run ./scripts/setup.sh.

Quick start

./scripts/flypi search LHR CTA 2026-12-21                 # one-way, cheapest first
./scripts/flypi search JFK LHR 2026-12-01 --return 2026-12-08 --stops nonstop
./scripts/flypi search LGW "CTA,PMO" 2026-12-21 --max-price 300
./scripts/flypi search LHR JFK 2026-12-01 --seat business --airlines BA,AA --json

Output: one line per option — airline flight(s) | dep -> arr | price | stops | duration.

Filters

flag meaning
--return YYYY-MM-DD round trip
--until YYYY-MM-DD cheapest fare per day across a date range
--stops nonstop direct only (any default)
--seat business cabin: economy / premium_economy / business / first
--airlines BA,AA / --exclude-airlines FR include / exclude carriers
--max-price 300 only fares under the cap
--adults 2 passenger count
--currency EUR currency (default USD)
--top N how many results (default 8)
--json structured output

Airports: IATA codes, comma-separated for several at once (LHR,LGW, JFK,EWR,LGA). Dates are always YYYY-MM-DD.

Watching a route

./scripts/flypi watch add LHR,LGW "CTA,PMO" 2026-12-21 --return 2027-01-03 \
    --target 400 --label "sicily xmas"
./scripts/flypi watch list
./scripts/flypi watch rm 3

watch add immediately fetches today's cheapest fare and stores it as the baseline. --target is an optional price goal.

./scripts/flypi watch history 1     # full price history of watch #1

Checking

./scripts/flypi check            # re-search everything
./scripts/flypi check --quiet    # only print changes/errors (cron-friendly)

check stores each result in history and prints a line per watch:

watch #2 (LHR,LGW -> CTA,PMO 2026-12-21 -> 2027-01-03): 367 (unchanged)
PRICE DROP watch #1 (LHR -> CTA 2026-12-21): 448 -> 367 (-81)
TARGET HIT watch #1: 367 <= target 400

Exit code is 1 when anything changed (drop or target hit) so cron can act on it. Watches are polled sequentially with a pause between queries (FLYPI_DELAY, default 3s — keep it; Google rate-limits). On HTTP 429 flypi waits FLYPI_RETRY_SEC (default 90s) and retries once before failing cleanly.

Notifications

flypi never sends anything on its own. When check sees a drop or target hit, the event digest is printed — and handed to whatever notifier you configured (default: printed only):

./scripts/flypi notify status                                        # current config
./scripts/flypi notify cmd 'curl -d @- https://ntfy.sh/your-topic'   # pipe to anything
./scripts/flypi notify agent [--jid <address>]                      # your agent alerts you
./scripts/flypi notify off

Only price drops and target hits are ever sent — "unchanged" checks stay silent.

Recommended: ntfy (push notification, zero setup)

  1. Install the ntfy app on your phone
  2. Pick a topic name and point flypi at it:
./scripts/flypi notify cmd 'curl -d @- https://ntfy.sh/your-topic'

That's it — no account, no server, no pairing. A price drop on any watch pings your phone. (Your topic is public on the default server unless you protect it; anything secret goes in the message, not the topic.)

notify cmd pipes each event digest to the command's stdin, so the same hook works for any destination you prefer — Telegram, a Slack webhook, an email API, or your own script:

./scripts/flypi notify cmd 'curl -s -F chat_id=YOUR_ID -F text=@- https://api.telegram.org/botTOKEN/sendMessage'

Alerts over chat: notify agent

When flypi runs inside an agent with a chat channel (e.g. whatsapp-pi), you don't need any pairing, topic, or push app — alerts ride the same channel you already talk to the agent on:

./scripts/flypi notify agent --jid 130476962508942@s.whatsapp.net

The jid is stored as an opaque recipient address; flypi itself contains no chat code. On a drop/target hit the operator agent sends you one concise WhatsApp message (see the "Agent behavior" section in SKILL.md).

Scheduling checks (no cron needed)

flypi check runs when something invokes it — you, a cron job, or pi itself. If you keep a pi session running (e.g. the launchd + tmux setup used by whatsapp-pi), this package ships an extension that turns that long-lived session into the scheduler:

  1. Set the interval in the always-on pi's environment: export FLYPI_CHECK_HOURS=6 (or FLYPI_CHECK_MINUTES=360)
  2. Restart that pi session.

From then on, the extension runs flypi check --quiet every 6h while pi is alive; results are appended to ~/.flypi/checks.log, and any price drop/target hit flows to your notifier — through your notify cmd destination, or, when you subscribed with flypi notify agent --jid <addr> and whatsapp-pi is online, by waking the agent to push you a WhatsApp message (set FLYPI_CHECK_WAKE=0 to disable the wake-up). A /flypi-check command in pi runs a check on demand. No timer starts unless the env var is set, and a lock file prevents two pi sessions from checking doubly. (Classic cron — flypi check --quiet every few hours, exit code 1 on changes — remains a fine alternative when pi is not always on.)

Storage

State lives in ~/.flypi/ (flypi.db = watches + history, config.json = notifier). Override the location with FLYPI_HOME.

Tests

./scripts/setup.sh            # once
.venv/bin/python -m unittest discover -s tests -v

All offline — nothing in the test suite queries Google Flights.

Notes

  • Uses an unofficial Google Flights access path via fli; it can break upstream. Keep the flights pip package updated (./scripts/setup.sh).
  • Be gentle: personal checks every few hours are fine. On sustained HTTP 429 back off ~10–15 minutes; flypi already waits FLYPI_RETRY_SEC once.
  • Prices are indicative fare engine quotes, not bookings.

License

MIT — see LICENSE. Not affiliated with Google or any airline.

About

Live flight price search + route watches from the CLI. A pi coding agent skill: search fares, watch routes, check for price drops, alert via command or WhatsApp. Data: Google Flights via fli.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages