Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -69,6 +70,21 @@ If you prefer headless / paste-token login:
mna login --paste-token <key> # 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.
Expand Down Expand Up @@ -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 <id> --json` to confirm — and check the request body shape against the OpenAPI schema for that endpoint.

## Configuration

Expand Down
153 changes: 109 additions & 44 deletions skills/mna/SKILL.md
Original file line number Diff line number Diff line change
@@ -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 <key>` 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>` (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 <tripId> --json` — full detail for one trip.
- `mna trips show <tripId> --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 <id> --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 <tripId> --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 <trip> <variant> --place "<City, Country>"
--start-date <YYYY-MM-DD> --end-date <YYYY-MM-DD> --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 <file>` 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 <trip> <variant>`; 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 <file>`). 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.
109 changes: 109 additions & 0 deletions skills/mna/references/cli-and-schemas.md
Original file line number Diff line number Diff line change
@@ -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 <id> [--all-options] | create --name | edit <id> | delete <id> | share | unshare
variants add <trip> --name | duplicate <trip> <var> | edit <trip> <var> | select <trip> <var> | delete
destinations add <trip> <var> --place [--start-date --end-date --notes --return-to-home]
edit <trip> <var> <destKey> [--place --notes --start-date --end-date --return-to-home/--no-…]
reorder <trip> <var> --order=k1,k2,k3 | delete <trip> <var> <destKey>
options add <trip> <var> <destKey> <kind> --from-json <file> [--free-cancellation-until <date>]
edit <trip> <var> <destKey> <kind> <optKey> [--from-json <file>] [--free-cancellation-until <date>]
select <trip> <var> <destKey> <kind> <optKey> | deselect <trip> <var> <destKey> <kind>
delete <trip> <var> <destKey> <kind> <optKey>
events add <trip> <var> --from-json <file> | edit <trip> <var> <eventKey> --from-json
toggle <trip> <var> <eventKey> | delete <trip> <var> <eventKey>
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
```

`<kind>` 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 <date>` (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": "<full address>, <City>, <Country>",
"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 <tripId> --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.
Loading
Loading