win4r/museai-skills/duffel

Claude Code and agent skill by win4r/museai-skills

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Use Duffel to search, book, pay for, or manage flights. Use Duffel to monitor an already booked flight's fare when the user directly asks for ongoing price monitoring.

Install

npx vskill@latest install win4r/museai-skills/duffel

SKILL.md

Duffel Flight Booking

For a user-facing flight search or booking, first read /opt/hatch/skills/booking/SKILL.md, /opt/hatch/skills/booking/references/flights.md, and /opt/hatch/skills/booking/references/presentation.md. Those files define the discovery, privacy, presentation, and commitment rules. Use this file for the Duffel CLI contract. Do not emit HTML, call create_options, or duplicate flight choices in another widget; the native flight widget owns flight selection and uses the action chosen for the current flow.

Use only this public CLI surface:

text
search
seat-options
validate-booking
book
booking-status
cancellation-quote
cancel-booking

Do not invent identifiers, call undocumented endpoints, or expose off_, ord_, or ore_ ids to users. Do not show a Duffel command. Keep sensitive values out of chat unless the booking JSON, validate-booking, or book accepts them for the active checkout. Never request payment-card data or account credentials. Run each search command directly into a distinct temporary JSON file; do not pipe the search through head or a parser, which can hide errors or required offer data. After the direct search succeeds, a read-only command may inspect the saved JSON to group and rank offers, but it must not overwrite the file. Reuse the unchanged file for presentation. If an earlier search was piped, truncated, reduced, or overwritten, do not repeat it in the same turn; explain that a complete result was not retained and ask the user to continue in a new turn. A hand-built summary is not sufficient input for the required structured flight list.

Booking flow

  1. Start by searching the complete itinerary and exact passenger mix together.
  2. Present the shortlist through

/opt/hatch/skills/booking/references/flights.md.

  1. If Travel Planning delegated the search in planning only posture, return

the selected itinerary to Travel Planning and stop. Do not continue into seats, traveler details, validation, or checkout until the posture changes to ready to book.

  1. Optionally show seat-options and collect bookable seats.
  2. Collect required passenger details and any loyalty account the user wants

attached.

  1. Let /opt/hatch/skills/booking/references/flights.md choose between the

native path and the airline website. When it chooses the airline website, follow /opt/hatch/skills/booking/references/browser-booking.md. Recheck the itinerary and terms. Do not require the user to complete the checkout.

  1. Otherwise continue through the supported native path without asking the

user to choose an implementation provider. Run validate-booking until ready_to_book: true, select an exact returned Stripe Link payment method, and call book once with the same offer, booking document, and seats.

  1. On success, report every carrier confirmation reference/PNR and ticket

status. Do not add the Duffel name to the message. Any required provider attribution belongs to the provider-controlled approval or receipt surface.

Do not skip validation or silently change the selected offer, route, passenger mix, fare, or seats before booking.

Search and compare

sh
duffel search --origin SFO --destination LAX --departure-date 2026-09-30 \
--limit 300
duffel search --origin SFO --destination LAX --departure-date 2026-09-30 \
--return-date 2026-10-04 --adults 2 --child-age 8 --lap-infants 1 --limit 300
duffel search --leg SFO:LAX:2026-09-30 --leg LAX:JFK:2026-10-03 --adults 2 \
--limit 300
duffel search --origin SFO --destination LAX --departure-date 2026-09-30 \
--max-connections 0 --sort duration --limit 300

Use --limit 300 for comparison searches so repeated fare variants from one carrier do not crowd plausible alternatives out of the inspected result set. If the CLI or provider returns a lower supported cap, use the complete result it returned and do not retry merely to reach 300. Present only the 3–6 most useful distinct offers. Start with every flight requested as one itinerary in the same search: use --return-date for a round trip and repeated --leg arguments for multi-city travel.

Treat each search as a live snapshot, not a price-monitoring loop. Do not refresh an identical search in a shell loop or launch duplicate searches in the background. The CLI suppresses completed and concurrent duplicate searches and bounds all provider attempts within one user turn. On duplicate_search, reuse the completed result. On search_in_progress, wait for the original invocation. On search_terminal, do not retry. On search_budget_exhausted, use any results already available and ask the user before expanding in a new turn.

For flexible dates or airports, choose the smallest useful set of distinct searches and run them sequentially. Show useful results as soon as they are available. If the requested comparison exceeds the CLI's turn budget, tell the user which combinations remain and ask them to continue in a new turn. Do not silently search the Cartesian product of every possible date and airport.

Use one search ordered by the user's stated priority; default to --sort duration when they give none. Do not automatically run separate duration, price, nonstop, and one-stop passes. Add or widen --max-connections only when the user requested that constraint or the first search produced no useful match. Run a targeted --airlines search when a requested, preferred, or credibly expected carrier is absent from the broad results, even when another carrier produced useful offers. A second sort is a separate live search, so run one only when the user's requested comparison genuinely requires it.

Before presenting, group the saved offers by complete itinerary signature: all segment airports, local timestamps, marketing and operating flight numbers, and segment order. Do not let repeated fare brands for one schedule consume the shortlist. Retain a distinct fare variant only when its cabin, baggage, refundability, changeability, or price creates a material user tradeoff.

Check carrier coverage after grouping. Use the user's preferences, the active travel-plan handoff, the response's carrier metadata when present, and verified route evidence to identify a materially relevant missing carrier. Search that carrier directly with --airlines before moving to Matrix or its website. If the targeted search still has no usable offer, follow the fallback in /opt/hatch/skills/booking/references/flights.md. Never conclude that Duffel does not support an airline, or that the airline does not fly the route, from its absence in one broad result set.

Use exact three-letter airport IATA codes, not metro codes such as NYC. Resolve unambiguous places, but confirm ambiguous dates or materially different airport choices. Do not guess an obscure or ambiguous code. Results are hard-filtered and nearby-airport inventory is excluded. When multiple airport pairs are acceptable, start with the preferred pair and expand to another pair only when requested or when the first search has no useful match; do not search every pair preemptively. An active travel-plan handoff that asks for the best option across named metro-area airports counts as an explicit request: search the smallest relevant set sequentially even if the first airport has a useful match. Zero results means only that the scanned Duffel inventory contained no match. For an exact-flight request, match the number in returned Duffel offers and do not substitute a different flight or use schedule data as proof it is bookable.

Passenger pricing is fixed at search:

  • --adults is the adult count.
  • Repeat --child-age for each seated traveler aged 2–17, using age on the

itinerary's final travel date.

  • --lap-infants counts travelers under two without a seat; each must have a

different accompanying adult.

Ask for missing ages once. Ask whether an infant is seated or on a lap. Do not infer it. This integration cannot reliably book an infant under two in their own seat, so do not validate or pay for that case; direct it to the airline. Do not search a known child as an adult or claim a child will be repriced at booking. Search again whenever the passenger mix changes.

Prefer one combined Duffel offer and booking for the complete itinerary. If no combined offer contains every requested leg, or the user explicitly asks for separate tickets, split only with their agreement before the first book. Explain that each booking has its own confirmation, fare conditions, approval, and payment; later offers are not held while an earlier one is purchased, so a later failure can leave earlier tickets booked. Compare the combined total. Compare useful alternatives such as cheapest, fastest, nonstop, and explicitly refundable, and identify all legs and total party price. Treat native-provider inventory as one live source, not exhaustive coverage across every airline channel.

Present the shortlist with native flight rows through widget.create, using kind: "list". Read the Flights section in /opt/hatch/skills/booking/references/flights.md for complete-trip rows and presentation. For list creation, redirect each search to a distinct temporary JSON file. Check the exit status and inspect the saved response for errors and available offers before creating the list. Keep the saved output unchanged:

sh
duffel search --origin SFO --destination JFK --departure-date 2026-10-14 \
--return-date 2026-10-18 --adults 1 --limit 300 > /tmp/sfo-jfk-flights.json

Create one row per selected complete offer. Set its type to "flight" and its data to the file path and that offer's JSON pointer, for example:

json
{
"flight_details_file": "/tmp/sfo-jfk-flights.json",
"json_pointer": "/offers/0"
}

Use the original offer's zero-based index in /offers/<index>. Keep the file until widget.create succeeds. Do not copy the offer JSON into the tool call, rewrite timestamps, remove fields, or generate a separate widget payload file. The runtime reads the selected object, maps timestamps, and stores the complete flight data. It does not retain the path or pointer. Keep all outbound, return and connecting segments in that one row. Show the whole offer price once. The server derives an identifying booking reply from those facts. For direct booking or a trip that is ready to book, omit the list-level flight_action and use the default booking CTA. For a Travel Planning handoff in planning only posture, set flight_action to {"cta_text":"Add to plan","response_message_prefix":"Add this flight to my trip plan:"} so selection returns the itinerary to the plan instead of implying checkout. Continue with the same complete offer id through validation and booking only after the flow advances to booking. Do not reinterpret a row tap as a request to buy only its first leg. Treat refundable and changeable as three-valued: yes, no, or not stated.

Fare brand, cabin, baggage, refundability, and changeability are optional provider facts. Preserve passenger/segment differences; render missing facts as “not stated.” Do not render missing facts as “none,” “not allowed,” or “non-refundable.” Airport-local times must not be timezone-converted without an explicit airport timezone. --refundable means refundable before departure with no stated positive penalty, not “cancel anytime.” Do not infer baggage or airline-standard fees.

After selection, use validate-booking's selected_offer as the canonical itinerary, price, baggage, and fare-condition snapshot.

Tracked fare monitoring

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
5

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/win4r/museai-skills/duffel/badge)](https://verified-skill.com/skills/win4r/museai-skills/duffel)

Something wrong with this skill or its page? Tell us.