From 450e70e0e90925458dbd7e796b265b055912ccf8 Mon Sep 17 00:00:00 2001 From: Akos Orban Date: Sun, 14 Jun 2026 00:25:37 +0200 Subject: [PATCH] docs(skill): whole-trip-planning mna skill + Claude Code install The old SKILL.md described a read-only Phase-0 CLI; the CLI now does full trip mutation. Replace it with a general, reusable planning method: - SKILL.md: data model, collaboration principles (app as source of truth, recommend-don't-enumerate, verify real availability, cost with looked-up numbers, honor user edits, verify-after-write) and a step-by-step playbook. - references/cli-and-schemas.md: command map, option/event JSON body shapes, enums, the nested-coordinates location requirement, dates, verify-after-write. - references/research-and-costing.md: hotel-connector research + exact-date availability verification, and own-car fuel costing. - README: one-command Claude Code skill install; writes are live; link the skill; drop the stale roadmap note. Generic and connector-agnostic (any hotel connector or web search). Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 22 ++- skills/mna/SKILL.md | 153 +++++++++++++----- skills/mna/references/cli-and-schemas.md | 109 +++++++++++++ skills/mna/references/research-and-costing.md | 65 ++++++++ 4 files changed, 302 insertions(+), 47 deletions(-) create mode 100644 skills/mna/references/cli-and-schemas.md create mode 100644 skills/mna/references/research-and-costing.md diff --git a/README.md b/README.md index 9b35460..a083ce1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ `mna` is an open-source CLI for managing your trips on My Next Adventure. It also ships as a [Claude Code](https://claude.com/claude-code) skill so Claude -can plan, view, and (in later phases) modify trips on your behalf. +can plan, research, build, cost, and manage whole trips on your behalf — see +[`skills/mna/SKILL.md`](./skills/mna/SKILL.md). Status: **pre-1.0, alpha.** Tagged releases publish binaries to GitHub Releases. npm and Homebrew distribution land with the first tag. @@ -69,6 +70,21 @@ If you prefer headless / paste-token login: mna login --paste-token # generate the key from the user menu on mynextadventure.cloud ``` +## Use it as a Claude Code skill + +`mna` doubles as a [Claude Code](https://claude.com/claude-code) skill — install it and Claude +can plan, research, cost, and manage whole trips for you. **One command:** + +```bash +git clone --depth 1 https://github.com/akoso/mna-cli /tmp/mna-cli && mkdir -p ~/.claude/skills && cp -r /tmp/mna-cli/skills/mna ~/.claude/skills/ +``` + +This drops the skill at `~/.claude/skills/mna/`. Start (or `/reload`) Claude Code and just ask +it to plan a trip — the skill triggers on its own. (Already have the repo cloned? Just +`cp -r skills/mna ~/.claude/skills/`.) + +The skill drives the `mna` CLI, so install the CLI (above) and run `mna login` first. + ## Commands Every command supports `--json` for piping into `jq` or Claude. @@ -180,9 +196,9 @@ Every command supports `--json` for piping into `jq` or Claude. ## Status -All command groups (auth/keys/config, trips, variants, destinations, options, events, access, vote/votes, goals, collections) are wired and CI-tested. Pre-1.0 means the public API contract is still allowed to break under `/v1/`. Once `1.0.0` ships, `/v1/` becomes stable; breaking changes require `/v2/`. +All command groups (auth/keys/config, trips, variants, destinations, options, events, access, vote/votes, goals, collections) are wired, CI-tested, and backed by live `/v1/` endpoints in production. Pre-1.0 means the public API contract is still allowed to break under `/v1/`. Once `1.0.0` ships, `/v1/` becomes stable; breaking changes require `/v2/`. -The matching server-side public API endpoints land progressively in the `akoso/travel-plans` repo. If a command returns a 404 against production, the corresponding server PR likely hasn't deployed yet — try `mna whoami --verify` to confirm your base URL. +The contract of record is `https://api.mynextadventure.cloud/v1/openapi.json`. If a write seems to "succeed" but a field doesn't stick, re-fetch with `mna trips show --json` to confirm — and check the request body shape against the OpenAPI schema for that endpoint. ## Configuration diff --git a/skills/mna/SKILL.md b/skills/mna/SKILL.md index a4813e2..5b02c41 100644 --- a/skills/mna/SKILL.md +++ b/skills/mna/SKILL.md @@ -1,55 +1,120 @@ --- name: mna -description: Use when the user wants to view, create, or manage their trips, - variants, destinations, accommodation/transport/activity options, events, - shares, travel goals, or collections on My Next Adventure. +description: >- + Plan and manage trips end-to-end on My Next Adventure via the `mna` CLI — create trips, + compare variants, build destinations and travel legs, research and book real accommodation, + cost transport, set dates and cancellation deadlines, and keep it all in sync. Use this + whenever the user wants to plan, research, price, build, or manage a trip / vacation / + itinerary on My Next Adventure (or mentions `mna`), even if they don't name the app — e.g. + "help me plan our summer trip", "find a lakefront place near X", "add a stopover on the way", + "compare these two hotels", "set up a few options to compare", "what's this trip costing". + Also covers travel goals, collections, trip sharing, and group voting. --- -# Managing trips with My Next Adventure +# Planning trips with My Next Adventure (`mna`) -You have access to the `mna` CLI for the user's trips on app.mynextadventure.cloud. +`mna` is a CLI over the My Next Adventure API (`app.mynextadventure.cloud`). The app is the +**source of truth** for a trip. Your job is to drive it as a thoughtful travel-planning +partner: do the research and the arithmetic, keep the plan organized, and let the user make +the real calls. ## Bootstrap -Run `mna whoami` first. If it fails with "Not logged in", ask the user to run -`mna login --paste-token ` themselves — they generate the key by signing -in at https://app.mynextadventure.cloud, opening the user menu, and clicking -"API Keys". +Run `mna whoami` first. If it reports "Not logged in", ask the user to run `mna login` +themselves (browser consent) or `mna login --paste-token ` (key from the user menu → +API Keys on the site). **Always pass `--json`** so output is parseable. -Always pass `--json` so output is parseable. +## The data model (hold this in your head) -## Phase 0 capabilities (read-only) - -- `mna trips list --json` — overview of all trips. -- `mna trips show --json` — full detail for one trip. -- `mna trips show --json --all-options` — include unselected options. -- `mna whoami --json` — current credentials (no server call). -- `mna config get apiBaseUrl --json` — current base URL. - -## Not yet available - -Write operations, goals/collections, share/invite, voting, browser login, -`whoami --verify`. These land in Phases 1–7 of the server roadmap. Until then, -respond to write requests by explaining that this CLI is read-only today and -suggesting the web UI for mutations. - -## Common workflows - -### "What trips do I have?" - -```bash -mna trips list --json ``` - -Filter by status: append `--status=planning`, `--status=booked`, or `--status=completed`. - -### "Show me details for trip X" - -If the user gives a name or ambiguous reference, first run `mna trips list --json` -to find the matching ID, then `mna trips show --json`. - -## Output expectations - -`--json` returns the raw server response. Schemas track -https://api.mynextadventure.cloud/v1/openapi.json — when in doubt, fetch that and -read the schema definitions for the endpoint you're about to call. +trip +└── variant ← a whole-trip STRATEGY you compare (one is "selected") + ├── destination ← a place/leg, in travel order; one can be return-to-home + │ ├── accommodation options (one selected) ← where you sleep + │ ├── transport options (one selected) ← how you get TO this leg + │ └── getting-around options (one selected) ← local mobility + └── event ← an activity/booking (optional) +``` +Most things support multiple **options** so the user (and collaborators) can compare and vote; +exactly one per kind is **selected** and counts toward the plan. After any write, the response +is thin — **re-fetch `mna trips show --json` to confirm it actually persisted.** + +## How to work — the method + +The *way of working* matters more than the commands. Internalize these principles, then follow +the playbook below. + +1. **The app holds the plan; keep a local mirror.** Treat the trip in `mna` as source of truth, + and also keep a lightweight `PLAN.md` in the working directory — IDs, decisions made, open + questions, running totals. It's what lets you resume cleanly in a later session. +2. **Anchor on what exists.** Before creating anything, check `mna trips list --json` and/or ask + — the user may already have the trip going. Don't spawn a duplicate. +3. **Brainstorm before building.** Nail who's going, exact dates, origin/return, the vibe, the + budget band, and the non-negotiables — and let the *user* define the variant strategy. Don't + invent structure they didn't ask for. +4. **Variants are comparable whole-trip strategies**, not tweaks — e.g. "single base the whole + time" vs "stopover + base" vs "stopover + base + a different return stop". Fork a baseline + with `variants duplicate`, then diverge. +5. **Recommend, don't enumerate.** Present 2–4 candidates with the *one trade-off that matters* + and a clear pick — not an exhaustive menu. Reserve a hard question (or `AskUserQuestion`) for + genuine forks: which stopover, which place, splurge vs value. +6. **Research real, bookable data.** Use a hotel connector for accommodation and **verify + availability for the exact dates before recommending** (see + `references/research-and-costing.md`). Never invent prices or "it's available". +7. **Cost with looked-up numbers, show the math.** Fuel prices, distances, nightly rates — look + them up, compute, and state what's excluded (food, tolls, activities). No hand-waved figures. +8. **Be geography-aware.** Order legs to avoid backtracking, mark the return-home leg, and keep + far-flung sights as day-trips rather than extra bases. Break long drives with a stopover. +9. **The user's edits are authoritative.** Manual price changes (e.g. a loyalty discount applied + by hand), geocoded location fixes, spelling corrections — keep them, never "correct" them + back to the scraped value. When you add an option, note that the real price may differ. +10. **Iterate as the brief sharpens.** Accommodation priorities shift mid-search ("actually, + lakefront, calmer, with restaurants nearby"). Re-run the search against the new criteria + rather than defending the old shortlist. +11. **Set precise, real data.** Exact coordinates, per-destination dates, free-cancellation + deadlines — so the plan maps correctly and is genuinely actionable. + +## The playbook + +0. **Bootstrap** — `mna whoami`; everything `--json`. +1. **Frame & anchor** — confirm participants, exact dates, origin/return, vibe, budget, the main + goal. Anchor on an existing trip (`trips list`) or `mna trips create --name "…"`. +2. **Shape variants with the user** — agree on 2–3 comparable strategies. `mna variants add`, or + `mna variants duplicate` to fork a baseline and then `variants edit` the notes. +3. **Lay out destinations** — add in travel order with dates: + `mna destinations add --place "" + --start-date --end-date --notes "…"`. Mark the home leg with + `--return-to-home`. Fix ordering with `mna destinations reorder … --order=k1,k2,k3`. + For stopovers, research candidates, present with a recommendation, let the user pick. +4. **Transport per leg** — usually how you arrive at each destination (own car, train, flight). + Cost it (look up fuel/fares; see the reference). Add via + `mna options add … transport --from-json ` and `mna options select …`. Put the + home-return drive on the return-to-home destination so totals stay clean. +5. **Accommodation per destination** — research with a hotel connector, present a curated spread + (price tiers + location trade-offs + ratings) with a recommendation, **verify availability**, + then add the shortlist (`options add … accommodation --from-json`), set the chosen one + `options select …`, and set its exact location, `--free-cancellation-until`, and check-in/out + dates. Replace stale placeholder options rather than piling new ones on top. +6. **Events** — only if the user wants them. The app is not a day-by-day itinerary planner and + many users explicitly don't want that — ask, don't assume. +7. **Choose & total** — `mna variants select `; sum selected accommodation + + transport; present the variant comparison with subtotals and what's excluded. +8. **Sync & verify** — update `PLAN.md`, and confirm every change with `mna trips show --json`. + +## Writing options and events + +Options and events are created from a JSON body (`--from-json `). The exact field shapes, +the enums, the **nested-coordinates location requirement**, and the date/cancellation fields are +in **`references/cli-and-schemas.md`** — read it before building option/event bodies. + +## Research and costing + +How to drive a hotel connector (search → verify availability → map into an option), run +area/beachfront searches, and compute own-car fuel costs from looked-up prices live in +**`references/research-and-costing.md`**. + +## Full command reference + +The complete command map (auth, trips, variants, destinations, options, events, access/voting, +goals, collections) is in the repo `README.md`. When a body shape is unclear, fetch and read +`https://api.mynextadventure.cloud/v1/openapi.json` — it's the contract of record. diff --git a/skills/mna/references/cli-and-schemas.md b/skills/mna/references/cli-and-schemas.md new file mode 100644 index 0000000..aa67244 --- /dev/null +++ b/skills/mna/references/cli-and-schemas.md @@ -0,0 +1,109 @@ +# CLI map, JSON body shapes, and gotchas + +Read this when you're building option/event bodies or need the exact command for a mutation. +The repo `README.md` has the exhaustive table; this file is the planning-focused subset plus +the field shapes you can't guess. Examples below use neutral placeholders. + +## Command quick-map (all support `--json`) + +``` +trips list | show [--all-options] | create --name | edit | delete | share | unshare +variants add --name | duplicate | edit | select | delete +destinations add --place [--start-date --end-date --notes --return-to-home] + edit [--place --notes --start-date --end-date --return-to-home/--no-…] + reorder --order=k1,k2,k3 | delete +options add --from-json [--free-cancellation-until ] + edit [--from-json ] [--free-cancellation-until ] + select | deselect + delete +events add --from-json | edit --from-json + toggle | delete +access/vote access list|invite|set-role|revoke|*-invite-link ; vote option|event ; votes list +goals list|show|add|quick-add|edit|delete|link-trip|unlink-trip|mark-visited|mark-dreaming +collections list|show|create|edit|delete|add-goal|remove-goal|share|open-shared +``` + +`` is one of `accommodation | transport | getting-around`. + +## Option JSON bodies (`--from-json`) + +### accommodation +```json +{ + "name": "Seaside Apartment", + "type": "apartment", // hotel|hostel|apartment|house|camping|other + "totalCost": 1200, "currency": "EUR", + "location": { ...see "Location shape" below... }, + "roomDetails": { "numberOfRooms": 1 }, // optional: sizeInM2 + "sourceUrl": "https://…", + "notes": "9.7 (240 reviews). Beachfront, kitchen, free parking.", + "checkIn": "2026-07-07T12:00:00.000Z", // ISO date-time + "checkOut": "2026-07-15T12:00:00.000Z", + "freeCancellationUntil": "2026-07-02T12:00:00.000Z" +} +``` +`checkIn`/`checkOut`/`checkInTime`/`checkOutTime`/`freeCancellationUntil` can also be set with +`options edit … --free-cancellation-until ` (accommodation only) without a JSON file. + +### transport +```json +{ + "transportType": "car", // car|plane|train|bus|ship|motorbike|bike|other + "roundTrip": false, + "totalCost": 120, "currency": "EUR", + "from": { ...location... }, "to": { ...location... }, + "departAt": "2026-07-05T08:00", "arriveAt": "2026-07-05T11:00", + "durationHours": 3, "durationMinutes": 0, + "notes": "Own car, ~250 km. Fuel only." +} +``` +Model each leg as the trip *into* a destination; attach it to that destination. Put the final +home-return drive on the `--return-to-home` destination so the per-variant total is clean. + +### getting-around +```json +{ "type": "ownCar", "totalCost": 0, "currency": "EUR", "notes": "Own car throughout." } +``` +`type`: walk|publicTransport|rideShare|ownCar|rentalCar|ownMotor|rentalMotor|bike|rentalBike|other. + +### event (variant-level, `events add`) +```json +{ "name": "City walking tour", "start": "2026-07-06T10:00", "end": "2026-07-06T13:00", + "totalCost": 0, "currency": "EUR", "link": "…", "notes": "…", + "location": { "name": "Old Town", "formattedAddress": "…", "coordinates": { "latitude": 0.0, "longitude": 0.0 } } } +``` + +## Location shape — a non-obvious gotcha + +For accommodation/transport `location`, the OpenAPI advertises flat `address` / `latitude` / +`longitude` — **but the API drops those silently.** Only `name` persists from the flat form. +Coordinates persist **only** when sent nested: + +```json +"location": { + "name": "Seaside Apartment", + "formattedAddress": ", , ", + "coordinates": { "lat": 0.000000, "lng": 0.000000 } +} +``` +(Option locations use `coordinates.lat`/`.lng`; **event** locations use +`coordinates.latitude`/`.longitude`.) Get exact coordinates from the search result, or geocode +the address (e.g. OpenStreetMap Nominatim). After setting, **verify with `trips show`** — never +trust the 2xx alone. + +## Dates + +`destinations --start-date/--end-date`, accommodation `checkIn/checkOut/freeCancellationUntil`, +and event `start/end` are all ISO date-time. Accept `YYYY-MM-DD` from the user and normalize. +Using `T12:00:00.000Z` (noon UTC) avoids timezone off-by-one on the displayed calendar date. + +## Verify-after-write + +Mutation responses are intentionally thin (often just the new key). Confirm the state with +`mna trips show --json` and parse the field you changed. This is the reliable way to +catch a silently-dropped field or an accidental duplicate create. + +## Auth / config + +Header is `X-API-Key` (handled by the CLI). Creds live at `~/.config/mna/credentials` +(`XDG_CONFIG_HOME` overrides). `MNA_API_KEY` / `MNA_API_BASE_URL` env vars override for CI/dev. diff --git a/skills/mna/references/research-and-costing.md b/skills/mna/references/research-and-costing.md new file mode 100644 index 0000000..0b37ceb --- /dev/null +++ b/skills/mna/references/research-and-costing.md @@ -0,0 +1,65 @@ +# Research & costing: real accommodation and honest numbers + +The plans that land are the ones built on real, bookable data and looked-up costs. + +## Accommodation research + +If a hotel-search connector is available, use it — a Booking.com MCP tool +(`accommodations_search`) is a good option when present, and Expedia / Tripadvisor connectors +work too. If none is available, fall back to web search and the property's own page. Whatever +the source, the workflow is the same: + +1. **Search each destination with the real constraints:** + - check-in / check-out = that destination's exact nights *for that variant* — a short base and + a long base return different prices and availability. + - adults + **children ages** — kids' ages change room eligibility and price. + - currency = the user's home currency so totals are comparable. + - require a kitchen when needed (filter to apartments / holiday homes). + - hard requirements as filters (free parking, beachfront). + - a price ceiling and type/photo filters to shape the spread. +2. **For "on the water / at the nice beaches" type asks**, search the specific area by name or by + coordinates (lat/lng + radius) with a beachfront filter. A generic city search buries them. +3. **Present a curated spread, not the raw list** — typically a value pick, a proven/most-reviewed + pick, and a splurge/location pick. For each: nightly + total, rating *and review count*, and + the one location trade-off (central vs waterfront, walkable vs needs-the-car). Give a clear + recommendation tied to the user's stated priorities. +4. **Verify availability for the exact dates before recommending or adding.** Re-query the + specific properties by name for the real check-in/out. Search ranking can hide an available + place, and a place that showed up for a long stay may be unavailable for a shorter window. If a + by-name availability check returns nothing, it's genuinely gone — drop it. This distinguishes + "ranked out of the list" from "actually unavailable". +5. **Map the chosen places into accommodation options** (`options add … accommodation --from-json`) + with the quoted total, exact `coordinates`, `sourceUrl`, rating in `notes`, then + `options select` the pick and set `--free-cancellation-until` + check-in/out. + +Reviews: weight **review count**, not just score — a 10/10 from 4 reviews is far less proven than +a 9.7 from 240. Flag thin-review places as such. + +## Costing own-car transport (fuel) + +The user usually just wants the fuel number. Do it honestly: + +1. **Look up current fuel prices** for the *countries the route passes through*, for the right + grade. Don't assume. +2. **Route-weight** them — most of a long drive may be in one country; weight by rough km share. +3. **Convert to the user's currency** (look up the FX rate). +4. **Fuel = distance_km × (L/100km ÷ 100) × price_per_L.** Use the consumption the user gives. + Compute per leg; attach each leg's fuel to its destination's transport option; fold the + home-return drive into the return-to-home leg. +5. **State what's excluded** — tolls, vignettes, parking — unless asked to include them. + +For other modes (train, flights), price the actual fares from a connector or the carrier, not a +guess, and note the class/conditions. + +## Honoring the user's own numbers + +If the user hand-edits a price (a loyalty discount such as a booking-site membership often makes +their real rate lower than the public quote) or fixes a location/spelling, that value is +authoritative — don't revert it on the next sync. When you add a freshly-searched option, note +that the public price may be higher than what they'll actually pay. + +## Keep a local PLAN.md + +Mirror the app into a `PLAN.md` in the working dir: the trip/variant/destination IDs, the chosen +options with prices, running totals, decisions made, and open questions. It's cheap and it's what +makes a multi-session plan resumable.