From room-genie
Use this skill BEFORE calling `cruise_search_sailings`, `cruise_list_categories`, or `create_alert` (kind:"cruise") for any Disney Cruise Line trip — Disney Wish, Disney Fantasy, Disney Treasure, Disney Dream, Disney Magic, Disney Wonder, Disney Destiny, Disney Adventure — or any DCL itinerary (Bahamian, Caribbean, Alaskan, Mediterranean, Transatlantic, Castaway Cay, Lookout Cay, Port Canaveral). Cruise flow is STRUCTURALLY DIFFERENT from hotels: no ticket days, no dining plan toggle, no Memory Maker — the cruise fare already bundles those. Contains the two-step DCL flow (cruise_search_sailings → cruise_list_categories), the questionnaire (months array for search, party, optional ship/nights; then sailingId + placeholder yes/no), stateroom category structure (Inside/Oceanview/Verandah/Concierge), ship codes (WW=Wish, WD=Destiny, DF=Fantasy, DA=Adventure, DD=Dream, DT=Treasure, DM=Magic, DW=Wonder), and kid-pricing nuances.
How this skill is triggered — by the user, by Claude, or both
Slash command
/room-genie:disney-cruise-plannerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Layer this on top of `room-genie-core`. DCL is structurally different from hotels: you book a *sailing* (a specific ship + departure date) and pick a *stateroom category* (a room type code like "O9C").
Layer this on top of room-genie-core. DCL is structurally different from hotels: you book a sailing (a specific ship + departure date) and pick a stateroom category (a room type code like "O9C").
| Step | Tool | Cost | Use it for |
|---|---|---|---|
| 1 | cruise_search_sailings | cheap (~20–60s) | Find sailings by month/ship. Returns sailing ID, ship, itinerary name, dates, nights, ports of call, lowest fare, available y/n. |
| 2 | cruise_list_categories | full quote (~15–30s) | After the user picks ONE sailing AND you've asked the placeholder question, render the FULL pricing view: cruise title, itinerary + ports + sea days, payment schedule (deposit-due rule per tier, final-payment date), sectioned tables (Interior / Oceanview / Oceanview with Verandah / Concierge) with deck/location/total/deposit/gratuities/grand-total, gratuities footer, and price-drop alert guidance. When placeholder: true, the tables show discounted Total / Savings / placeholder Deposit. This is the only DCL pricing tool — there is no separate "quote" step. |
Cruise pricing has moved fully to the two tools above. explore_rates is hotel-only — do not pass sailingId to it. The previous list_cruise_sailings, list_stateroom_categories, and cruise_get_quote tools have been removed (their functionality is now folded into cruise_list_categories).
Before calling any cruise tool — cruise_search_sailings or cruise_list_categories — you MUST ask the user three things explicitly:
Ask these BEFORE cruise_search_sailings. Search results show per-category lowest pricing, which depends on the party composition; asking once at the start means you never have to re-ask at the categories step. The same party flows through to every subsequent cruise call.
Then pass adults, children, childAges, AND partyConfirmed: true on every cruise tool. The server REFUSES the call when partyConfirmed is missing or false; it returns a message listing the exact three questions you forgot.
Never set partyConfirmed: true without having asked. That defeats the whole guard — it exists specifically to prevent you from silently defaulting to "2 adults, 0 children, no childAges". The default is wrong half the time and the user is annoyed when you re-quote after they correct it.
cruise_list_categoriesBefore calling cruise_list_categories, you MUST ask the user whether they're booking with a DCL placeholder (Booking a Future Cruise Onboard). The placeholder discount is 10% off the voyage fare and a $250-reduced deposit; standard pricing has neither. Disney never returns placeholder pricing in its APIs — the math happens in the tool, but only when you pass placeholder: true.
Ask the placeholder question right after the user picks a sailing — BEFORE cruise_list_categories. The category list itself renders prices, so showing the user standard pricing when they have a placeholder means they see the wrong numbers and you have to re-quote afterwards. Asking once upfront avoids that.
Phrase it like:
"Are you booking this with a Disney Cruise Line placeholder (also called Booking a Future Cruise Onboard)? It gets you 10% off the voyage fare and a $250 reduced deposit. Or is this your first DCL cruise / no placeholder?"
Then pass BOTH:
placeholder: true (yes, has placeholder) or placeholder: false (no placeholder) — required, no default.placeholderConfirmed: true — REQUIRED attestation flag.The server REFUSES the call when placeholderConfirmed is missing or false; it returns a message naming exactly what to ask. Never set placeholderConfirmed: true without having asked.
cruise_list_categories placeholder mode renders the same sectioned tables, plus a Savings column. When placeholder: true:
Total column shows the adjusted total (10% off voyage fare).Savings column shows the per-category dollar discount vs Disney's standard pricing (positive dollar value, e.g. $220.00).Deposit column shows the placeholder deposit (standard deposit minus $250 prepaid onboard).Render the table verbatim (Rule B applies). Don't summarize the savings; let the user see each row's discount.
When cruise_list_categories returns 27 categories, render all 27. The output is a complete markdown table — paste it verbatim into your reply to the user. The tool appends a ⚠ **RENDER THIS RESPONSE TO THE USER VERBATIM** directive at the bottom of its text response; that directive is binding.
Forbidden patterns (Claude has been caught doing all of these — DO NOT):
The correct pattern:
### Section H3 headers with their tables underneath. Do NOT collapse to one combined table.room-genie-core (cruise variant): "What next? I can (a) set a price-drop alert on a category, (b) set an availability alert on a sold-out category — only offer this if any category showed as sold out, or (c) build you a branded PDF quote for the client (calls generate_quote_pdf)." Skip option (b) when no category is sold out. Skip (c) on Free / Watcher plans (Explorer-only).Do NOT ask any of these — cruise_list_categories already has the answer:
The only time cruise_list_categories runs after cruise_list_categories is when the user explicitly wants the placeholder math (Booking a Future Cruise Onboard — 10% off + $250 reduced deposit). At that point, ask the placeholder yes/no question, then call cruise_list_categories with the user's picks. Otherwise the natural next step from the tables is the alert offer.
That's it. No prose summary. No highlights. No tier "entry points". The user is making a real comparison decision — even rows that look obviously too expensive or obviously too cheap inform the decision. Render every priced row.
After the user picks a subset: they might say "just give me the cheapest Verandah" or "skip Concierge". Then you re-render a filtered view from the data you already have — no new tool call needed. But the FIRST render is always the full list.
| Code | Ship | Typical routes |
|---|---|---|
WD | Disney Destiny | (New 2025) — Caribbean, Bahamas |
WW | Disney Wish | Bahamas, Caribbean |
DF | Disney Fantasy | 7-night Caribbean |
DA | Disney Adventure | (New) — Asia-Pacific |
DD | Disney Dream | Europe |
DT | Disney Treasure | Caribbean |
DM | Disney Magic | Europe, transatlantic |
DW | Disney Wonder | Alaska, Mexico, Pacific |
Pass the 2-letter code as the ships filter on cruise_search_sailings when the user wants a specific ship.
| Type | Letter prefix | Examples | Typical vibe |
|---|---|---|---|
| Inside | I, 11 | 11C, 11B, 11A | No window, cheapest |
| Oceanview | O, 8, 9 | O9C, 8D, 9B | Porthole or window, no verandah |
| Verandah | V, 4, 5, 6, 7 | V7A, 5C, 4A | Private balcony |
| Concierge | T, V1, V2, V3 | V3B, T, R | Concierge lounge access, top decks, pricier |
The exact category codes come from cruise_list_categories — never guess; always call the tool to get the current list for a specific sailing.
DCL questionnaire is different from hotels. Ask BEFORE calling the relevant tool:
cruise_search_sailings)partyConfirmed: true. Ask this BEFORE picking month/ship/nights.YYYY-MM format, at least one. Ask "what month(s) are you flexible on?".nights: ["5"] → server maps to "5-6" bucket → returns 5 AND 6 night sailings.nights: ["5-6"] → server adds the suffix → same result.nights: ["5-6;filterType=night"] → passes through.
There is NO exact "5 nights only" filter on Disney's side. If the user said "5 nights", warn that 6-night sailings will also appear in results — let them filter visually.["BAHAMAS"], ["CARIBBEAN"], ["ALASKA"], ["EUROPE"], ["MEXICAN RIVIERA"]).["WW"], ["WD"], ["DF"]). No suffix needed.Search performance note: cruise_search_sailings scrapes DCL live. Scope drives latency:
When the user asks for a specific target date (e.g. "closest to April 8"): the tool returns every matching sailing for the month filters, which can be 30–50 rows for a popular ship. Don't dump all of them. Instead:
|departureDate - targetDate| and show only the 3–5 closest sailings — nearest match first, then nearest alternatives on either side.cruise_list_categories)Required: sailingId, party (adults, children, childAges) + partyConfirmed: true, AND placeholder: true | false + placeholderConfirmed: true. Both Rule A and Rule C apply — ask both questions before this call. The category list itself shows pricing, so the placeholder answer must be in hand before the first render.
cruise_list_categories)Sailing ID — from search results.
Party confirmed — adults, children, childAges (one age per child) + partyConfirmed: true. Required — see Rule A above. The server refuses the call without this.
Placeholder confirmed — placeholder: true | false + placeholderConfirmed: true. Required — see Rule C above. The server refuses the call without this. Ask: "Are you booking with a DCL placeholder (10% off + $250 reduced deposit), or first/no placeholder?"
Categories the user is interested in — pass categoryCodes: ["04A","08A"] to limit the deposit fan-out. Strongly preferred — call cruise_list_categories FIRST, show the user every category, let them pick, then quote their picks. Only omit categoryCodes when the user explicitly said "show me everything". Phrase it like:
"Are you booking this with a Disney Cruise Line placeholder (also called Booking a Future Cruise Onboard)? It gets you 10% off the voyage fare and a $250-reduced deposit since you prepaid that on your prior cruise. Or is this your first DCL cruise / no placeholder?"
cruise_list_categories({ ..., placeholder: true }). The placeholder flag triggers the legacy detailed format that shows the adjusted prices.placeholder (or placeholder: false) so the user sees Disney's standard pricing in the new compact format.cruise_list_categories. Don't speculatively fetch.Claude's instinct is to be helpful by saying "while you answer, I'll start fetching" and immediately calling the tool. Don't. The placeholder flag is part of the tool input — calling without it means the prices are wrong for placeholder users, and you'll have to recall the tool (each call is 15–30s with categoryCodes, longer without). That's a worse experience than waiting 5 seconds for the user's reply.
What IS safe to do in parallel with the placeholder question:
cruise_search_sailings (only if you don't already have the sailingId).cruise_list_categories — listing categories doesn't take a placeholder param.get_my_profile — for notification setup later.What is NOT safe to do until the user answers:
cruise_list_categories({ sailingId, ... }) — placeholder is part of the input.Do NOT ask: ticket days, dining plan, Memory Maker, travel protection — DCL doesn't offer these as toggles. The cruise fare already includes onboard dining (rotational dining + Cabanas + QSRs). Gratuities are extra but NOT configurable through the tool.
The standard format puts the final-payment date in the Final Payment Due column of the table. The placeholder format emits a callout line above the per-group blocks like:
📅 Final payment due Jan 5, 2027 for all priced categories on this sailing.
In either format, you MUST keep the final-payment date visible in your reply. It's the single most important piece of payment-timing info for the user. Do not drop, summarize, or paraphrase as "due before sailing" — the user wants the exact date.
Disney's APIs do NOT return placeholder pricing. Disney has no idea which user holds a placeholder; they always return standard fare/tax/total. The placeholder math is computed inside the tool using Disney's exact pricing as the input. The formula is:
netFare = total - tax
discount = netFare × 0.10
adjustedTotal = total - discount
adjustedFare = adjustedTotal - tax
standardDep = adjustedFare × 0.10
placeholderDep = max(0, standardDep - 250)
When you call cruise_list_categories({ ..., placeholder: true }), the tool's text output already contains the adjusted values. The summary table headers swap to Total (10% off) and Placeholder Deposit, and each detail block adds 10% off fare, Adjusted total, Adjusted fare, Standard deposit, and Placeholder deposit rows. Render those rows as-is.
These are wrong. Disney never returns placeholder pricing, by design. The math happens in the tool. If the placeholder rows aren't in your output, it's because you forgot to pass placeholder: true — re-call the tool with the flag set. Don't write an excuse.
0. ASK PARTY FIRST. "How many adults? How many children? Each child's age?"
Wait for the answer before any tool call.
1. cruise_search_sailings({
months: ["2026-09"],
ships: ["WW"], // narrow if user has a preference
nights: ["5"], // optional — server normalizes 5 → 5-6 bucket
adults: 2, children: 0, childAges: [],
partyConfirmed: true, // REQUIRED — only after asking
})
--- After user picks a sailing, ASK THE PLACEHOLDER QUESTION before
cruise_list_categories. The category list shows pricing; asking
afterwards means the user saw the wrong numbers.
2. Render the sailing list verbatim (the tool returns a markdown table with
sailing ID, ship, itinerary, dates, nights, PORTS OF CALL, available).
3. Ask: "Which sailing looks interesting?"
4. cruise_list_categories({
sailingId: "WW0509",
adults: 2, children: 0, childAges: [],
partyConfirmed: true, // REQUIRED — only after asking party
placeholder: true | false, // REQUIRED — pass user's actual answer
placeholderConfirmed: true, // REQUIRED — only after asking placeholder
})
- Renders itinerary line + per-port bullets at the top
- Then the category list (no deposits, no due dates — fast view)
5. Ask: "Which categories should I quote? Pick 1–3 and I'll pull the full
pricing with deposit and due dates." Also ask the placeholder question
here if you haven't already.
6. cruise_list_categories({
sailingId: "WW0509",
adults: 2, children: 0, childAges: [],
partyConfirmed: true, // REQUIRED — only after asking party
placeholder: true | false, // REQUIRED — pass user's actual answer
placeholderConfirmed: true, // REQUIRED — only after asking placeholder
categoryCodes: ["08A", "11C"], // ALWAYS pass — set to user's picks
})
7. Render the quote output verbatim.
cruise_list_categories calls Disney's stateroom-availability endpoint and returns categories + base prices in one shot (~10s). cruise_list_categories does the same, then ALSO fans out to Disney's payment-calculator endpoint once per category to get the deposit and final-payment date (~1–2s per category). When the user only cares about 2 categories, categoryCodes: ["08A","11C"] saves you ~20+ seconds of unnecessary API calls.
When the user explicitly says "show me every category with full pricing", omit categoryCodes and accept the slower call.
cruise_search_sailings.cruise_list_categories → get category, stateroomType.create_alert({ alert: { kind: "cruise", sailingId, stateroomCategory: "O9C", stateroomType: "OUTSIDE-DELUXE", shipName: "Disney Wish", sailingName: "4-Night Bahamian Cruise", checkIn: "2026-09-07", checkOut: "2026-09-11", adults: 2, children: 0, childAges: [], alertType: "price_drop", currentPrice: 3200, notificationMethod: "email", clientNote: "" } })Total column, NEVER Total + GratuitiesThe Room Genie worker watches Disney's voyage fare on every re-check (fare + tax, gratuities excluded). When you propose a price-drop alert, the threshold MUST come from the Total column of the cruise_list_categories output, not the Total + Gratuities column. Mistakes:
Total + Gratuities ($4,472.64 fare + $160.00 gratuities). The worker compares against $4,472.64, which is already below $4,632.64 → alert fires on the next check. Useless alert.When recapping the alert in chat, say something like "price-drop alert fires when Disney's voyage fare drops under $X (gratuities excluded — those are auto-charged at end of cruise)" so the user knows what's being watched and isn't surprised when their gratuities bill is on top.
WW0509 (Wish, sailing 0509). Don't invent them — always pull from cruise_search_sailings.roomCount is often 2–5 for Concierge categories. Sellout risk is real; an availability alert is valuable.cruise_search_sailings response when applicable. Surface them when present.cruise_list_categories outputRender the tool's content[0].text verbatim. Do NOT re-format, summarize, or drop sections. The new compact format produces this exact structure (when placeholder is false or omitted):
## {Cruise Title}
{Ship Name} · {departureDate} → {returnDate} · {numberOfNights} nights
Party: {N} adults{, M children (ages …)}
**Itinerary:** {nights} · {N} ports · {seaDays} sea days
- **{Port 1}** — {description}
- **{Port 2}** — {description}
- …
| Category | Type | Total | Deposit | Final Payment | Deposit Due | Final Payment Due |
|---|---|---|---|---|---|---|
| 04A | Concierge 1-Bedroom Suite | $9,432.18 | $1,500.00 | $7,932.18 | At booking | 2026-06-04 |
| 08A | Deluxe Verandah | $5,210.44 | $250.00 | $4,960.44 | At booking | 2026-06-04 |
| … |
**Gratuities** (auto-charged at end of cruise, not in totals above):
- Standard categories: $14.50/guest/night × 7 × 4 = $406.00
- Concierge categories: $16.50/guest/night × 7 × 4 = $462.00
Rules for the new format:
categoryCodes was passed. That tells the user there are more categories on the sailing they could explore via cruise_list_categories — keep that footer.placeholder: true is passedThe legacy detailed format is used (it has the placeholder math). Render it verbatim — the table has different headers (Total (10% off), Placeholder Deposit (due now)), and there's a fenced detail block per category with Adjusted total, Adjusted fare, Standard deposit, Placeholder deposit, etc. The placeholder format also emits the 📅 **Final payment due …** callout line above the blocks. Keep the callout. Keep every row.
~.gratuitiesRate and conciergeGratuitiesRate are Disney's actual per-sailing rates, not rounded averages.~$X,XXX or approximately $X,XXX or about $X,XXX when rendering a number from the tool. They are exact figures for this sailing + party + category combination.not returned by Disney — never invent a tilde.Those numbers come from Disney's own payment-calculator API via the tool and are already in the text output (and in structuredContent.categories[].deposit / .price.tax / the gratuitiesRate field). Disney's deposit, gratuity, and final-payment formulas vary per sailing, per category, and per concierge tier — there is no single percentage you can apply. Pass through whatever the tool emitted. Full stop.
Do NOT write intro text like "Gratuities auto-apply at Disney's default rate: $80/guest standard, $136.25/guest concierge (sailing total, ~$16/night and ~$27.25/night)" before the table. The Gratuities block already carries that information with the EXACT rate and trip total for the sailing. Inventing a summary preamble introduces:
If the user asks specifically for the gratuity rate, cite the value from the tool's structuredContent (gratuitiesRate or conciergeGratuitiesRate) — never a computed average.
After cruise_search_sailings returns multiple sailings:
After cruise_list_categories returns categories for a sailing:
After cruise_list_categories:
After the user seems stuck between two ships:
When the party includes young kids (under 3):
After create_alert for a cruise:
When the user mentions they're flexible on dates:
npx claudepluginhub tombandini-7/room-genie-skills --plugin room-genieProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.