Human: Give this URL to your AI assistant and say "set up trvl":
https://raw.githubusercontent.com/MikkoParkkola/trvl/main/AGENTS.md
You are setting up trvl — a travel MCP server + CLI for flights, hotels, trains, cars, and ferries, with no API keys required. It reads real-time Google Flights and Google Hotels directly, ships as a single Go binary, and works with any MCP client. Run these steps in order:
brew install MikkoParkkola/tap/trvlPre-built binary, no toolchain needed, 1 second. If Homebrew is not available:
# Manual: detect OS/arch, download, extract
curl -fsSL https://github.com/MikkoParkkola/trvl/releases/latest/download/trvl_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz | tar xz -C /usr/local/bin trvlOne command auto-configures any of 10 MCP clients (Claude Desktop, Cursor, Claude Code, Windsurf, Codex, VS Code Copilot, Gemini CLI, Amazon Q, Zed, LM Studio) — no JSON hand-editing. Add --dry-run to preview the change first.
trvl mcp install # Claude Desktop (default)
trvl mcp install --client cursor # Cursor / Windsurf
trvl mcp install --client claude-code # Claude CodeThen restart your MCP client. No JSON editing needed.
For Claude Code, you can also run:
claude mcp add trvl --transport stdio -- trvl mcpmkdir -p ~/.claude/skills
for s in trvl providers; do
curl -fsSL "https://raw.githubusercontent.com/MikkoParkkola/trvl/main/.claude/skills/$s.md" -o "$HOME/.claude/skills/$s.md"
doneThe skills at .claude/skills/trvl.md and .claude/skills/providers.md teach you how to:
- Ask the right questions (From? To? When? Flex? Budget?)
- Run hack detectors automatically after every search
- Use the unified optimizer (
optimize_booking) for trip planning - Show the "Naive -> Optimized -> Saved" comparison after every plan
- Use all-in pricing with FF benefits (bag fees included, status benefits subtracted)
- Apply 36 travel hack detectors to find savings opportunities
- Configure optional hotel/restaurant/ground providers only after verified source-code research and user consent
trvl version
# Expected: trvl 1.18.0 (or later)
trvl flights HEL LHR 2026-07-01 --format json | head -5
# Expected: JSON with flight resultsTell the user: "trvl is installed with 1 smart MCP tool, 66 legacy-compatible capabilities, and 2 bundled Claude skills. It includes 36 travel hack detectors (including error fare and flash sale detection) that auto-fire on searches, a unified optimizer (optimize_booking) with 9 expansion strategies (alternative origins/destinations, rail+fly, date flex, hidden city, departure tax avoidance, rail competition alternatives, ferry cabin as hotel) that searches all combinations in parallel, all-in pricing with FF status (bag fees included, FF benefits subtracted), pre-priced candidate pipeline for ground alternatives, miles tracking and earning estimates, cross-program award sweet-spot scanning, and cross-provider hotel price comparison with cross-currency savings display. Use the primary travel tool for natural or structured requests; existing tool names such as search_flights, search_accommodations, search_hotels, and watch_price continue to work as legacy-compatible capabilities. I can search flights, accommodations, hotels, destinations, plan trips, find weekend getaways, find optimal travel windows, optimize multi-city routes, find nearby restaurants, check local events, search ground transport (buses, trains, ferries, night trains), detect travel hacks, check weather forecasts, look up airline baggage rules, find airport lounges, check visa requirements, calculate points-vs-cash redemptions, and configure additional data providers (Airbnb, Booking.com, Hostelworld). Just ask me anything about travel."
For accommodation decisions, use search_accommodations first. It starts from
the requested room/apartment need and returns only matched, room-level offers in
the ranked offers list. search_hotels is discovery only. Treat raw hotel
prices as lead-in search prices until you verify the shortlist. Before making a
public recommendation or ranking a final trip cost:
- Use
search_accommodationsfor traveller-facing stay recommendations. - Use
search_hotelsonly for broad candidate discovery or debugging. - Verify specific candidates with
search_hotels_with_details,hotel_rooms(passbooking_urlwhen available), ortrvl serpapiwhen the user hasSERPAPI_KEY. - Rank on
total_priceor tax-inclusive provider totals when present. - Surface taxes/fees, cancellation, board, and local tourist tax separately when known.
- Do not say a hotel rate is booked, held, locked, guaranteed, or checkout-final unless a provider checkout page confirms it.
Run the onboarding interview to learn how the user travels:
- Call
onboard_profilewithphase: 1— ask the basics (home, frequency, companions) - After user answers, call
onboard_profilewithphase: 2— travel style (accommodation, budget, transport) - Continue through phases 3 (favourite cities, properties), 4 (companion, wishlist), and 5 (reasoning and strategies)
- Each phase skips questions the profile already answers
- Save answers to
~/.trvl/profile.jsonviaadd_bookingorupdate_preferences
If the user has email access (Gmail), also offer to scan booking history:
Call build_profile with source: "email" to scan Gmail for past bookings
The profile powers personalized search — preferred neighbourhoods, price elasticity, booking strategies, and destination recommendations.
trvl works out of the box with Wikivoyage + OpenStreetMap (no keys needed). For richer data (events, restaurant ratings, attractions), the user can get free API keys:
| Service | What it adds | Signup |
|---|---|---|
| Ticketmaster | Events (concerts, sports, festivals) | https://developer.ticketmaster.com/ |
| Foursquare | Restaurant ratings, tips, price levels | https://developer.foursquare.com/ |
| Geoapify | Walking-distance POI search | https://myprojects.geoapify.com/ |
| OpenTripMap | Tourist attractions + Wikipedia | https://opentripmap.io/product |
All free, no credit card, 2 min signup each. Walk the user through each signup:
- Open the URL for them
- Tell them what to click (Sign up → Create project → Copy key)
- Have them paste the key
- Set it:
echo 'export TICKETMASTER_API_KEY="their-key"' >> ~/.zshrc && source ~/.zshrc - Verify:
trvl events "Barcelona" --from 2026-07-01 --to 2026-07-08
Use /setup-api-keys command for the guided wizard.
The profile lives at ~/.trvl/preferences.json. The best profile comes
from real booking history, not from asking questions. Try these approaches
in order — use the first one the user agrees to.
Tier 1 (best): Scan their email and calendar
Ask: "I can build your travel profile automatically by scanning your booking confirmation emails. I'll look for flight bookings, hotel reservations, loyalty programmes, and ground transport to understand your patterns. Want me to do that?"
If yes, search Gmail for:
from:(booking.com OR airbnb OR finnair OR klm OR ryanair OR norwegian OR sas OR easyjet OR wizzair OR flixbus OR regiojet OR eurostar) subject:(confirmed OR confirmation OR booking OR ticket OR itinerary)from:(flyingblue OR finnairplus) subject:(status OR tier OR gold OR silver)from:(marriott OR hilton OR accor) subject:(member OR status OR points)
From the results, extract:
- Airlines used and frequency →
loyalty_airlines, carrier preferences - Routes flown →
home_airports(most frequent origin) - Hotels booked →
min_hotel_stars(infer from actual bookings),preferred_districts(from hotel addresses), accommodation style - Loyalty status emails → exact programme and tier
- Ground transport → FlixBus/RegioJet/train patterns
- Booking patterns → books multiple and cancels? Airbnb vs hotels? Extended stays vs short trips?
Also check calendar for upcoming travel events.
Then run a quick trvl search to detect geoip currency → infer location.
Show the user what you found as a draft profile. Ask: "Here's what I see from your bookings. Anything wrong or missing?"
Fix what they correct. Save with update_preferences.
Tier 2 (good): Ask about a real trip
If they decline email access, ask about concrete experiences instead of abstract preferences:
"Tell me about your last trip — where did you go, how did you get there, and where did you stay?"
One real trip reveals airline choice, hotel quality, neighborhood, booking platform, trip length, and travel companions.
"What would you change about it?"
Reveals pain points: bad wifi → fast_wifi_needed, too far from center
→ neighborhood matters, 5am flight → flight_time_earliest.
"What's a trip that went perfectly?"
Reveals the gold standard: if they describe a 4-star boutique in Prague 1 with great coffee, you know more than 10 questions would give.
Then fill gaps with 2-3 targeted questions based on what you still
don't know. Save with update_preferences.
Tier 3 (fallback): Structured questions
If neither of the above works, ask these 4 questions:
Q1: Confirm home airport (infer from geoip first) Q2: Hotel dealbreakers (hostels? bathroom? stars? rating?) Q3: Carry-on only or checked bags? Q4: Direct flights or connections fine? Q5: Anything else about how you travel?
Save with update_preferences.
What each field actually does in the code:
| Field | Behavior |
|---|---|
home_airports |
Default origin for flight/trip/weekend/discover searches |
display_currency |
Price display across the smart router and all 66 legacy-compatible capabilities |
no_dormitories |
FilterHotels() drops hostels, capsules, guesthouse rooms by chain name + regex |
ensuite_only |
FilterHotels() drops shared-bathroom properties |
min_hotel_stars |
Passed to Google Hotels API as search filter |
min_hotel_rating |
Passed to search + activates 20-review minimum gate |
preferred_districts |
FilterHotels() strict-filters or prioritizes by neighborhood |
carry_on_only |
Travel hack detectors: hidden-city and throwaway require carry-on |
prefer_direct |
Flight search: nonstop filter |
default_companions |
0=solo, 1=couple, 2+=family/group — personalizes search defaults |
trip_types |
e.g. ["city_break","beach","adventure"] — destination suggestions |
seat_preference |
"window", "aisle", "no_preference" |
budget_per_night_min |
Filters too-cheap-to-trust hotels |
budget_per_night_max |
Max hotel price per night |
budget_flight_max |
Max one-way flight price |
deal_tolerance |
"price" (6am flight? yes), "comfort" (pay more), "balanced" |
flight_time_earliest |
e.g. "06:00" — no flights before this |
flight_time_latest |
e.g. "23:00" — no flights after this |
red_eye_ok |
Overnight flights acceptable? |
nationality |
ISO 3166-1 alpha-2 (e.g. "FI") — visa warnings |
languages |
Spoken languages, e.g. ["en","fi","sv"] |
previous_trips |
Cities/countries visited — avoids repeat suggestions |
bucket_list |
Dream destinations — prioritized in suggestions |
activity_preferences |
e.g. ["museums","food","nature"] — destination matching |
dietary_needs |
e.g. ["vegetarian","halal"] — restaurant filtering |
notes |
Free-text for anything else |
Frequent flyer and miles configuration:
Users with frequent flyer status get all-in pricing that accounts for free checked bags, lounge access, and miles earning. Here's an example FF configuration:
{
"frequent_flyer_programs": [
{"alliance": "skyteam", "tier": "gold", "airline_code": "KL", "program_name": "Flying Blue", "miles_balance": 45000},
{"alliance": "oneworld", "tier": "sapphire", "airline_code": "RJ", "program_name": "Royal Plus"}
],
"carry_on_only": false,
"nationality": "FI",
"home_airports": ["HEL"]
}When FF status is set:
- Flight results include all-in pricing (bag fees included, FF benefits like free checked bags subtracted)
- Miles earning estimates appear on each flight
- Airline preference within 15% price delta of the cheapest option for the FF's alliance
- Lounge access is annotated on
search_loungesresults calculate_points_valueuses the correct floor/ceiling valuations for the specific program
Continuous learning — the profile is never "done":
Track what the user searches for and how they respond to results. Every interaction is a signal. Update the profile when you see a pattern — always confirm before saving.
Within a conversation — watch reactions to results:
- Says "too expensive" to a €180 hotel → note their real budget ceiling
- Says "too far from center" → location matters, ask which neighborhood
- Ignores hostels in results →
no_dormitoriescandidate - Picks the 4-star over the 3-star every time →
min_hotel_stars: 4 - Asks for "something with character" → add to
notes - Rejects a 6am flight →
flight_time_earliest: "07:00" - Clicks the Booking.com link → note platform preference
Across conversations — detect evolving patterns:
- Searches from a new airport 3+ times → add to
home_airports - Visits a city repeatedly → add to
previous_trips, learn neighborhoods - Mentions a dream destination → add to
bucket_list - Booking patterns change → ask if preferences should update
- Mentions new loyalty status → update immediately
The key: don't ask abstract questions when you can observe behavior. "What's your budget?" is a bad question — watching them reject €180 hotels and pick €120 ones tells you more.
Always confirm before calling update_preferences. Show what changed.
CLI alternative: trvl prefs init
You now have one travel MCP tool available by default. Older clients that call legacy per-domain tool names still work — 66 of them remain legacy-compatible capabilities. Use travel for new clients and the legacy names when an older workflow names a specific tool:
{"origin": "HEL", "destination": "NRT", "departure_date": "2026-06-15"}Optional parameters:
return_date: "2026-06-22" (makes it round-trip)cabin_class: "economy" | "premium_economy" | "business" | "first"max_stops: "any" | "nonstop" | "one_stop" | "two_plus"sort_by: "cheapest" | "duration" | "departure" | "arrival"alliances: comma-separated alliance names: "STAR_ALLIANCE", "ONEWORLD", "SKYTEAM" — server-side filterdepart_after: earliest departure time "HH:MM" (e.g. "06:00") — server-sidedepart_before: latest departure time "HH:MM" (e.g. "22:00") — server-sideless_emissions: true/false — only show flights with below-average CO2 — server-sidecarry_on_bags: integer — require N carry-on bags included in price — server-side price recalculationchecked_bags: integer — hidden Google feature — require N checked bags in price. Google's UI only exposes carry-on; trvl also wires the checked-bag slot in the same filter array — server-siderequire_checked_bag: true/false — drop any flight without ≥1 free checked bag — client-side post-filtermax_price: integer — maximum price in whole currency units — server-sidemax_duration: integer — maximum total duration in minutes — server-sideexclude_basic: true/false — exclude basic economy fares — server-sideairlines: comma-separated IATA codes to restrict results (e.g. "AY,LH")provider: empty (default) merges Google Flights + Kiwi + Skiplagged into one sorted list;"skiplagged"queries Skiplagged solo for hidden-city / virtual-interlining cross-validationdeep: true/false — opt-in budget-gated counterfactual fan-out. Probes nearby departure airports, split-ticket options, and hidden-city routes via extra provider calls. Capped by a best-effort budget; never delays the primary result. When the budget is spent the tool returns what it has and notes the shortfall.
Response extras (single-airport, single-destination searches only):
price_position: where the current fare sits in the route's observed history (low / typical / high) with a buy-or-wait verdict. Omitted when there is not enough history or below the data floor.savings: call-free savings opportunities read from the persisted price calendar — same-day cheaper fares, vs-history comparison, shift-day options. Each entry carries anas_ofage when the data is not live.
{"origin": "HEL", "destination": "NRT", "start_date": "2026-06-01", "end_date": "2026-06-30"}Optional: trip_duration (days), is_round_trip (true/false)
{"origin": "BGY", "destination": "NAP", "earliest_depart": "2026-07-22", "latest_return": "2026-08-06", "min_nights": 5, "max_nights": 7}Use this when the trip length is a range, not a fixed date: it returns the cheapest
round-trip date combinations whose stay falls between min_nights (default 3) and
max_nights (default 7), ranked by price. This is the flexible-date duration-window
search — one tool call instead of scanning every date pair by hand. Adults is
honoured, so prices are for the real party size (not single-adult-only). For a
multi-airport city, call it once per airport code (e.g. BGY, MXP, LIN) and merge —
fli-style metro codes are not used; each airport is a separate round-trip.
{"location": "Tokyo", "check_in": "2026-06-15", "check_out": "2026-06-18", "adults": 2, "children_ages": [7], "accommodation_type": "entire_apartment", "must_have_kitchen": true, "refundable_required": true}Use this before recommending where to stay. It searches candidate properties,
checks room-level availability for the shortlist, and returns only
criteria-matched room/apartment offers in offers. Candidate lead-in prices stay
under candidates and must not be used for final trip-cost ranking.
{"location": "Tokyo", "check_in": "2026-06-15", "check_out": "2026-06-18"}Optional:
guests: number of guests (default: 2)stars: minimum star rating 1-5 — server-side?class=Nsort: "price" | "rating" | "distance" | "stars"currency: "EUR" | "USD" etc.free_cancellation: true/false — only hotels with free cancellation — server-side?fc=1property_type: "hotel" | "apartment" | "hostel" | "resort" | "bnb" | "villa" — server-side?ptype=Nbrand: hotel chain name substring (e.g. "hilton", "marriott", "ibis") — client-sidemin_rating: minimum guest rating e.g. 4.0 — server-side?rating=N+ client-side guardmax_distance: maximum km from city center — server-side?lrad=Namenities: comma-separated required amenities (e.g. "pool,wifi") — client-sidemin_price/max_price: price range per night — server-side?min_price/?max_price+ client-side guardenrich_amenities: true/false — fetch detail pages for top results (slower)eco_certified: true/false (default false) — only show eco-certified hotels with sustainability certifications — server-side?ecof=1
{"location": "Tokyo", "check_in": "2026-06-15", "check_out": "2026-06-18", "max_hotels": 3}Runs search_hotels, then fetches room-level availability and full amenity detail for the top hotels in one call. Room results include best-effort normalized cancellation_policy, refundable, free_cancellation, board, breakfast_included, nightly_price, total_price, taxes_and_fees, and taxes_fees_included fields when providers expose them. Partial detail failures stay localized to typed detail_errors objects instead of failing the whole hotel search. Optional:
- all
search_hotelsfilters max_hotels: top hotels to enrich (default 3, max 5)include_rooms: true/false (default true)include_amenities: true/false (default true)
{"hotel_id": "<from search_hotels>", "check_in": "2026-06-15", "check_out": "2026-06-18"}Use hotel_prices as a provider comparison when Google exposes booking partners,
not as a standalone guarantee. For final hotel recommendations, prefer
search_hotels_with_details or hotel_rooms totals because they can include
room-level cancellation, board, and tax/fee fields.
Response extras:
price_position: where the current rate sits in the property's observed price history (low / typical / high). Omitted when there is not enough data.booking_readiness: a verdict string —"ready","caution", or"unverified"— composed from verified price, stable link, confirmed property identity, and known refundability. Any unknown signal downgrades the verdict conservatively.booking_readiness_reasons: list of strings explaining what contributed to the verdict.
hotel_rooms returns the same booking_readiness and booking_readiness_reasons fields.
CLI re-book flow for existing refundable reservations:
trvl prices hold "<hotel_id>" --name "Hotel Name" --checkin 2026-06-15 --checkout 2026-06-18 --price 420 --currency EUR --refundable
trvl prices rebook <hold_id> --min-savings 25Stores active holds in ~/.trvl/active_holds.json, fetches current provider prices, and returns a hold-current vs. manual re-book decision. It never cancels or books automatically.
{"location": "Tokyo"}Optional: travel_dates ("2026-06-15,2026-06-18" — comma-separated check-in,check-out)
Returns: weather forecast, country info (capital, languages, currencies), public holidays during travel dates, safety advisory (1-5 scale), currency exchange rates vs EUR, timezone.
{"origin": "HEL", "destination": "BCN", "depart_date": "2026-07-01", "return_date": "2026-07-08"}Optional: guests (number, default 1), currency ("EUR" | "USD" etc.)
Returns: cheapest outbound flight + return flight + cheapest hotel per night, total cost, per-person cost, per-day cost.
{"origin": "HEL", "month": "july-2026"}Optional: max_budget (number in EUR, 0 = no limit), nights (default: 2)
Returns: top 10 cheapest weekend destinations ranked by total estimated cost (round-trip flight + estimated hotel).
{"origin": "HEL", "destination": "BCN", "target_date": "2026-07-15"}Optional: flex_days (default: 7), round_trip (boolean), duration (days for round-trip, default: 7)
Returns: 3 cheapest dates, weekday vs weekend analysis, savings insights, average price comparison.
{"home_airport": "HEL", "cities": "BCN,ROM,PAR", "depart_date": "2026-07-01"}Optional: return_date ("2026-07-21")
Returns: optimal visit order, per-segment prices, total cost, savings vs worst order. Tries all permutations (up to 6 cities).
{"min_hotel_stars": 4, "no_dormitories": true}Merges individual fields into ~/.trvl/preferences.json. Only send the
fields you want to change — other fields are preserved. Always confirm
with the user before calling this tool.
{"pickup_location": "HEL", "pickup_date": "2026-07-01", "dropoff_date": "2026-07-04", "currency": "EUR", "passengers": 3}Optional: dropoff_location, pickup_time, dropoff_time, driver_age, vehicle_class, max_price, provider.
Uses optional Skyscanner Car Hire access when SKYSCANNER_API_KEY is configured. Without credentials it returns a typed provider_statuses setup result instead of crashing or inventing prices.
{"airport": "HEL"}Returns: lounge name, terminal, type, accepted access cards (Priority Pass, Diners Club, LoungeKey, etc.), amenities, opening hours. Type indicates access network: "card" (Priority Pass/LoungeKey), "airline" (frequent flyer status), "bank" (credit card programme), "amex" (Centurion). If the user has lounge_cards or frequent flyer status set in preferences, results are annotated with accessible_with — the subset of their own cards or status that grant free entry to each lounge.
{"passport": "FI", "destination": "TH"}Returns: visa status (visa-free, visa-required, visa-on-arrival, e-visa, freedom-of-movement), max stay duration, and notes. Uses ISO 3166-1 alpha-2 country codes.
{"cash_price": 450, "points_required": 20000, "program": "finnair-plus"}Returns: effective cents-per-point, floor/ceiling valuation for the program, verdict (use points, pay cash, or borderline), and explanation.
CLI hotel points arbitrage can compare multiple offers:
trvl points-value --cash 300 --offer world-of-hyatt:12000 --offer hilton-honors:80000{"seats":[{"program":"VS","origin":"HEL","destination":"LHR","date":"2026-08-15","cabin":"business","miles_cost":50000,"cash_fees":35,"cash_equivalent":650,"bookable_segments":1}],"balances":[{"program":"MR","balance":80000},{"program":"VS","balance":20000}]}Returns: ranked award-seat redemption paths across native balances and transfer partners, including miles spent, cash fees, cents-per-point, affordability, and transfer route. Use when award availability is already known or supplied from another source.
{"origin": "HEL", "destination": "BCN", "departure_date": "2026-07-01", "return_date": "2026-07-08"}Optional:
flex_days: date flexibility +/-N days (default 3)guests: number of passengers (default 1)currency: display currency (default EUR)max_results: top N results to return (default 5)max_api_calls: API call budget (default 15)need_checked_bag: whether a checked bag is neededcarry_on_only: carry-on only trip
Returns: ranked booking strategies with all-in cost (baggage + FF status), savings vs naive direct booking. Searches alternative origins, destinations, rail+fly stations, hidden-city candidates, and date flexibility in a single call.
Use for the user painpoints that span multiple tabs: importing confirmations, saving booking candidates, exporting a trip, sanity-checking itinerary route time, and getting conservative fare intelligence.
{"action":"import_reservation","trip_id":"trip_abc123","subject":"Booking confirmation - KLM","body":"Flight HEL -> AMS... Booking reference ABC123","source":"email"}Actions:
get: return the full schema-versioned workspace.export_json/export_markdown: export the workspace for sharing or backup.import_json: merge a Trip Workspace JSON export into an existing trip, or create a new trip iftrip_idis omitted.import_reservation: parse user-approved booking text into confirmed legs and imported records.save_candidate: save a manually bookable option withtype,title,provider,price,currency,url,checked_at, and optionalexpires_at.optimize_itinerary: estimate route time from workspace place coordinates and warn on overpacked days.fare_intelligence: comparepriceagainsthistorypoints and return buy/watch/wait without claiming live availability.booking_ready: check whether a saved candidate has price, URL, and fresh enough evidence before the user books manually.
Important: this tool never purchases, cancels, or guarantees availability. Stale or missing evidence means re-check before the user acts.
{"origin": "HEL", "destination": "BCN", "from_date": "2026-07-01", "to_date": "2026-07-31", "trip_length": 7}Returns: cheapest departure dates across the entire range using a single CalendarGraph API call. Much faster than searching day by day.
{"origin": "HEL", "destination": "BKK", "depart_date": "2026-07-01", "return_date": "2026-07-14"}Optional: passport (ISO country code for visa check)
Returns: GO / WAIT / NO_GO verdict with parallel checks for flights, hotels, visa requirements, and weather. Use before detailed planning to quickly validate a trip idea.
{"name": "CORU House", "location": "Prague", "check_in": "2026-07-01", "check_out": "2026-07-05"}Searches all providers (Google Hotels, Trivago, Airbnb, Booking.com, Hostelworld, HomeToGo) using the property name as the search query, then fuzzy-matches results. Use when the user knows the exact hotel name.
{"from": "Amsterdam", "to": "Paris", "date": "2026-07-01"}Optional: type ("bus"|"train"|"ferry"), currency, max_price, provider
Searches 22+ providers in parallel including FlixBus, RegioJet, Eurostar, DB, NS, SNCF, Trainline, Trenitalia, Italo, and ferries. Eurostar Snap fares auto-searched for valid routes.
{"phase": 0}5-phase interview (0=LLM context confirmation, 1=basics, 2=style, 3=deep, 4=specifics, 5=reasoning). Builds a traveller personality model that drives search defaults.
{"type": "flight", "origin": "HEL", "destination": "BCN", "date": "2026-07-01", "target_price": 89, "currency": "EUR"}Stores watch in ~/.trvl/watches.json. Use check_watches to re-check prices, list_watches to see all active watches. Hotel watches can set last_minute: true and last_minute_drop_pct (default 25) to alert when sub-48h availability drops materially below the last seen price.
trvl nudges reads watches, price history, preferences, and trips from ~/.trvl and surfaces nudges when a real trigger fires. Triggers are: a watch crossing its target price, or a route sitting at a confident historic low. When nothing has triggered, the command outputs nothing. Each nudge cites its source record. No network calls are made.
trvl nudges # Show grounded nudges (silent when nothing triggered)
trvl nudges --format json # Machine-readableThis command has no MCP equivalent — use watch_price + check_watches for watch management and search_flights for on-demand price signals.
{}Shows per-provider success rate, average latency, result-count quality, freshness, last error class, circuit-break state, next retry time, and fix hint from the redacted ~/.trvl/health.jsonl log plus provider config state. Use to diagnose stale, sparse, blocked, or failing providers without exposing provider credentials.
{"origin": "HEL", "destination": "BCN", "date": "2026-07-01"}Runs 36 detectors in parallel: hidden-city, throwaway, positioning, back-to-back, rail competition, ferry cabin, error fare, date flex, and more. Optional: return_date, carry_on_only.
plan-trip— Full trip planning: flights + hotels + budget analysisfind-cheapest-dates— Month-wide price calendar for a routecompare-hotels— Side-by-side hotel comparison by user priorities
trvl covers the whole flight + accommodation budget search on its own — no separate flight tool, no separate price-verification server. The reliable pattern (sequential, not joint — LLMs lose track over hundreds of speculative calls):
- Flights window —
find_trip_windowper departure airport (min_nights/max_nights, realadultscount). Merge the per-airport results and keep the top 8–10 cheapest dates. - Accommodation, verified — for each kept flight date, call
search_accommodations(check-in = outbound, check-out = return, the realadults). It verifies room-level rates for the shortlist and returns only criteria-matched offers inoffers; rawcandidateslead-in prices are Google Hotels teasers and must not be ranked on. - Rank by total trip cost — flight (×party) + the verified accommodation total. Hotel nightly rates are far more stable than flight prices across small date shifts, so let flights be the variable part and rank on the combined total.
This is the same flights-then-accommodation flow people build with three separate tools, done with trvl alone.
- Results include
booking_url— share these with the user for direct Google links - Results include
suggestions— use these to offer follow-up searches - Prices reflect the user's IP geolocation currency
- For trip planning: search flights first, then hotels at the destination
- For budget trips: use
weekend_getawayorsuggest_datesto find the cheapest options - For multi-city: use
optimize_multi_cityto find the cheapest routing order - For full cost estimates: use
calculate_trip_costfor flights + hotel totals - For destination research: use
destination_infofor weather, safety, holidays - Common IATA codes: HEL (Helsinki), JFK (New York), LHR (London), NRT (Tokyo), CDG (Paris), BCN (Barcelona), BKK (Bangkok), SIN (Singapore), DXB (Dubai), LAX (Los Angeles), FRA (Frankfurt), AMS (Amsterdam), ICN (Seoul)
- "command not found":
which trvl— if empty, the binary isn't in PATH. Re-run Step 1. - No results: Google may rate-limit. Wait 60 seconds and retry.
- Wrong currency: Normal — currency follows IP geolocation.
- MCP tools not showing: Restart Claude Code / Claude Desktop after Step 2.
- HTTP / remote MCP:
trvl mcp --httpbinds to127.0.0.1by default and requires bearer auth. UseTRVL_MCP_TOKENfor read/write local gateway access,TRVL_MCP_READ_TOKEN/TRVL_MCP_WRITE_TOKENfor scoped static tokens, or OAuth introspection flags/env vars when an OAuth 2.1 gateway handles Authorization Code + PKCE. Remote exposure requires explicit--host.
- GitHub: https://github.com/MikkoParkkola/trvl
- License: PolyForm Noncommercial 1.0.0
- Inspired by fli by Punit Arani
This project is indexed by GitNexus as trvl (21933 symbols, 67842 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
If any GitNexus tool warns the index is stale, run
npx gitnexus analyzein terminal first.
- MUST run impact analysis before editing any symbol. Before modifying a function, class, or method, run
gitnexus_impact({target: "symbolName", direction: "upstream"})and report the blast radius (direct callers, affected processes, risk level) to the user. - MUST run
gitnexus_detect_changes()before committing to verify your changes only affect expected symbols and execution flows. - MUST warn the user if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
- When exploring unfamiliar code, use
gitnexus_query({query: "concept"})to find execution flows instead of grepping. It returns process-grouped results ranked by relevance. - When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use
gitnexus_context({name: "symbolName"}).
- NEVER edit a function, class, or method without first running
gitnexus_impacton it. - NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
- NEVER rename symbols with find-and-replace — use
gitnexus_renamewhich understands the call graph. - NEVER commit changes without running
gitnexus_detect_changes()to check affected scope.
| Resource | Use for |
|---|---|
gitnexus://repo/trvl/context |
Codebase overview, check index freshness |
gitnexus://repo/trvl/clusters |
All functional areas |
gitnexus://repo/trvl/processes |
All execution flows |
gitnexus://repo/trvl/process/{name} |
Step-by-step execution trace |
| Task | Read this skill file |
|---|---|
| Understand architecture / "How does X work?" | .claude/skills/gitnexus/gitnexus-exploring/SKILL.md |
| Blast radius / "What breaks if I change X?" | .claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md |
| Trace bugs / "Why is X failing?" | .claude/skills/gitnexus/gitnexus-debugging/SKILL.md |
| Rename / extract / split / refactor | .claude/skills/gitnexus/gitnexus-refactoring/SKILL.md |
| Tools, resources, schema reference | .claude/skills/gitnexus/gitnexus-guide/SKILL.md |
| Index, status, clean, wiki CLI commands | .claude/skills/gitnexus/gitnexus-cli/SKILL.md |