Sandbox
@skywain/trip-planner-skill

Trip planning skill for SKILL.md agents

This skill takes a travel request and produces a verified itinerary with route options, hour-by-hour days, booking links, and map exports. It uses `SKILL.md` plus Python scripts and themed renderers to keep the plan, maps, and page output in sync.

38 stars0 forksPythonUpdated 12d ago
Who it's for

Builders who want their agent to plan trips with verified hours, prices, and booking links.

What it delivers

You can turn a rough travel idea into a bookable itinerary and a polished page without redoing the planning by hand.

What it does

Verified itinerary planning

Checks opening hours, holidays, flight prices, and route choices with tools instead of guessing.

Hour-by-hour day plans

Builds daily schedules with dwell times, buffers, and map links for each stop.

Theme-based page output

Renders the plan into one of eight HTML themes, including a default illustrated layout.

Offline map exports

Generates `plan.geo.json` and KML so the trip can be opened in map tools like Organic Maps or Google My Maps.

Booking checklist and calendar gates

Produces deadline-sorted tasks and `.ics` reminders for ticket releases and re-checks.

How to get it

  1. 11. Install — agents that support Agent Skills discover them by directory, so clone…
    git clone https://github.com/skywain/trip-planner-skill.git ~/.claude/skills/trip-planner
    pip3 install --user fast-flights Pillow   # optional: flight price scanner · asset pipeline
  2. 2Try it in 30 s — no key, no agent needed, from the repo root
    python3 scripts/render_plan.py examples/kyoto-sample.plan.geo.json -o kyoto.html          # the plain page (Chinese-language sample)
    python3 themes/render_clay2.py examples/china-2026/china.geo.json -o china-clay.html \
      && python3 themes/qc.py china-clay.html                                                 # an English themed page + its QC (exit 0)
  3. 32. Plan a trip — in your agent, one sentence. The skill triggers on its own for trip /…
    /trip-planner Japan, 12-15 days in October from London, mid budget, history and food, dates ±3 days
  4. 4One key — no native generation: create themes/.auth_header containing one line —…
    python3 themes/gen.py <trip>/jobs.json --outdir <trip> --manifest <trip>/manifest.<trip>.json      # gpt-image-2; --dry-run first
    python3 themes/genvideo.py jobs.json --outdir <trip>/portal --manifest <trip>/manifest.<trip>.json  # veo-3.1-lite by default; --models for prices
  5. 5No image generator? Still a designed page. Two commands, and the plan comes out in a…
    python3 themes/stock_art.py plan.geo.json --theme illustrated -o plan.art.json
    python3 themes/render_theme2.py plan.geo.json --art plan.art.json \
            --assets themes/assets/stock -o trip-illustrated.html   # --assets is required here

README

English | 简体中文

Trip Planner Skill

One sentence in, a verified, hour-by-hour, bookable trip plan out — delivered as a designed page in one of eight visual themes. An open-format Agent Skill (SKILL.md) that runs inside whichever coding agent you already use — Claude Code, Codex, Gemini CLI, Cursor, GitHub Copilot, OpenCode, Qwen Code, Deep Code, Goose, Kiro, Roo Code, or any other harness that loads Agent Skills: it checks opening hours, prices and holidays with tools instead of guessing, hands you a link for every booking, and never books or pays for you.

Agent Skills: open format Agents: Claude Code · Codex · Gemini CLI · Cursor · GitHub Copilot · OpenCode · Qwen Code · Deep Code · Goose · Kiro · Roo Code

Live demos Verified in: Claude Code (others untested) Models: any Python 3.9+ License: MIT

The eight themes, one cover each: illustrated, clay, noir, glass, journal, zine, splash, portal

Showcase

Eight themes across four real trips (two themes per trip). Every trip below was planned end-to-end by a fresh agent session using this skill, then rendered from its plan.geo.json

  • art.json; the three frames per row are the cover, one day module (what the share buttons export on the seven still themes) and the end of the scroll — the checklist and closing spread. Four of the eight pages ship verbatim under examples/; three of the other four render from the same example folders with one command (each example's art.json carries both of its trip's themes); portal additionally needs footage (see below).

Every page below is live: open the demo site or click a theme's Live page link.

illustrated — Japan · London → Tokyo → Hakone → Kyoto → Osaka (open-jaw) → London, 21–28 Nov 2026 · a painted picture-book on paper: the cover is the menu, each day a tinted riso plate with a ghost numeral, the whole scroll exports as one long image · examples/japan-2026 · Live page ↗

covera daythe end

clay — China · New York → Beijing → Xi'an → Beijing → New York, 11–18 Nov 2026 · one continuous claymation landscape with a road threading the milestone stones · render it: python3 themes/render_clay2.py examples/china-2026/china.geo.json -o china-clay.html · Live page ↗ (Chinese-language clay example: examples/turkey-2026 · live ↗)

covera daythe end

noir — Mexico · Berlin → Mexico City → Oaxaca → Berlin, 28 Oct – 6 Nov 2026 (Día de Muertos) · one night-negative tracking shot, monospace body, days dissolving into each other · render it: python3 themes/render_noir2.py examples/mexico-2026/mexico.geo.json -o mexico-noir.html · Live page ↗ (Chinese-language noir example: examples/nordic-2026 · live ↗)

covera daythe end

glass — Morocco · Toronto → Marrakech → Aït Benhaddou → Merzouga → Fes → Chefchaouen → Casablanca → Toronto, 6–15 Nov 2026 · liquid-glass panes floating over a fixed world of cross-fading photographs, one pane per world · examples/morocco-2026 · Live page ↗

covera daythe end

journal — Mexico · Berlin → Mexico City → Oaxaca → Berlin, 28 Oct – 6 Nov 2026 · a vintage travel journal on a dark desk: tape, stamps, postmarks, polaroids, and a Day of the Dead week planned around the crowd · examples/mexico-2026 · Live page ↗

covera daythe end

zine — Japan · London → Tokyo → Hakone → Kyoto → Osaka (open-jaw) → London, 21–28 Nov 2026 · torn riso-poster collage with giant vertical two-colour glyphs, built like a photocopied fan zine · render it: python3 themes/render_zine.py examples/japan-2026/japan.geo.json -o japan-zine.html · Live page ↗ (Chinese-language zine example: examples/vietnam-2026 · live ↗)

covera daythe end

splash — China · New York → Beijing → Xi'an → Beijing → New York, 11–18 Nov 2026 · a game splash screen stretched into a scroll: floating day-islands under a chained sky, routed Xi'an-first so the Wall and the Forbidden City both land on weekdays · examples/china-2026 · Live page ↗

covera daythe end

portal — Morocco · Toronto → Marrakech → Aït Benhaddou → Merzouga → Fes → Chefchaouen → Casablanca → Toronto, 6–15 Nov 2026 · scrolling is flying: five 3D worlds in one unbroken take, dive → frame-chained link → dive, with the day's plan laid over the footage; let go and it holds, scroll back and it flies in reverse. The only theme that needs video (nine clips here, rendered on a local GPU; an agent with native video generation or themes/genvideo.py produces the same chain). Footage is not shipped with the example, so the page in the repo is screenshots only; the demo site serves the nine clips from a release asset, which makes the live link below the real thing — the motion capture is recorded from it · examples/morocco-2026 · Live page ↗ (16 MB of video)

Portal theme in motion: dive into a world, link to the next, day overlay on top (animated)

covera daythe end

Every render command, cost and file for the seven trips is listed in examples/README.md. The plain, un-themed page — the printable extra, never the default deliverable — looks like examples/kyoto-sample.html (a Chinese-language sample; the same renderer produces the English UI from a "lang": "en" plan); themes/render_picker.py builds a style-chooser page linking every rendered edition of a trip as <prefix>-<theme>.html.

What you get

Say "Japan, 12–15 days in October, mid budget, history and food." The skill returns:

  • A route across cities — 2–3 skeletons to pick from, then real flight prices for a grid of dates and a train-vs-fly call for every intercity leg.
  • An hour-level plan for every day — opening hours and closure days checked with tools, dwell times and buffers from a written scheduling method, a holiday and festival collision scan, and a tappable map link on every hop.
  • A designed page as the deliverable, not a wall of text — the plan is rendered through one of the eight themed renderers above (default illustrated) into one self-contained, phone-friendly file: trip-<theme>.html. The seven still themes carry offline share-image buttons (Save this day / Save appendix / One long image; whole-page export on five of the eight — noir and glass export day modules only), and portal (video) has no share buttons — screenshot it. The plain printable page is an extra you can ask for.
  • plan.geo.json, the single source of truth — the themed page, the map links and an offline KML for Organic Maps / Google My Maps all come out of that one file.
  • A hotel shortlist by neighbourhood (dated deep links, not invented nightly rates), a budget rollup in your home currency, a travel-insurance line calibrated to the destination, and a booking checklist sorted by deadline — with date-locked gates (ticket-release instants, decision deadlines, on-trip re-checks) also delivered as a .ics calendar file: dual alarms per gate, the full action list in the event body, and floating local times so an on-trip reminder rings wherever you are.
  • Pictures, whatever your agent can do — three rungs, checked silently before the page style ever comes up: your agent's native image generation → your own OpenRouter key → the built-in stock kit. The last rung still ships a themed page, and says so in plain words (see No image generator? below).

What it will not do: book, pay, hold, or enter personal data. You click the links.

Quick start

1. Install — agents that support Agent Skills discover them by directory, so clone straight into your skills folder (Claude Code's path is shown; other agents: see Compatibility):

git clone https://github.com/skywain/trip-planner-skill.git ~/.claude/skills/trip-planner
pip3 install --user fast-flights Pillow   # optional: flight price scanner · asset pipeline

Everything else is Python 3.9+ standard library. Without fast-flights the scanner degrades to a Google Flights link; without Pillow you can still render every theme from the shipped picture library. If pip3 install --user is refused with externally-managed-environment (PEP 668: Homebrew / Debian Python 3.11+), install into a python3 -m venv instead, or add --break-system-packages.

Try it in 30 s — no key, no agent needed, from the repo root:

python3 scripts/render_plan.py examples/kyoto-sample.plan.geo.json -o kyoto.html          # the plain page (Chinese-language sample)
python3 themes/render_clay2.py examples/china-2026/china.geo.json -o china-clay.html \
  && python3 themes/qc.py china-clay.html                                                 # an English themed page + its QC (exit 0)

(For a Chinese-language themed page swap in examples/turkey-2026/turkey.geo.json; the other six trips and their commands are in examples/README.md.)

2. Plan a trip — in your agent, one sentence. The skill triggers on its own for trip / flight / itinerary requests, or explicitly:

/trip-planner Japan, 12-15 days in October from London, mid budget, history and food, dates ±3 days

The plan's UI language follows the language you ask in ("lang": "zh"|"en" in the plan; --lang overrides on every renderer). Four modes are picked from what you ask:

ModeTriggerWhat runs
Full trip"plan me 12 days in Japan"All phases: intake → country brief → route skeleton → flights → day plans → hotels → assemble + self-check
Single day"we have one day in Rome"Holiday/festival check + that day + self-check; flights and hotels skipped
Gap filler"I'm near X with 2 free hours"2–3 options within a 15-min radius, each with walk time, map link, turn-back deadline
Live replan"missed the train / it's pouring"Rebuilds only the affected day from its degradation tags

3. The designed page — this is the deliverable the skill hands over, in the theme you picked (default illustrated = render_theme2.py), never a plain text page. Three commands, from the repo root (full manual: themes/README.md, references/themes.md):

# optional: a <plan>.art.json beside the plan is picked up automatically — cover title, per-day titles, which pictures go where
python3 themes/render_<theme>.py plan.geo.json -o trip-<theme>.html   # theme2 clay2 noir2 glass2 journal zine splash portal
python3 themes/qc.py trip-<theme>.html                                # exit 0 = clean; exit code = FAIL count
themes/xprobe.sh trip-<theme>.html module '#d5' out.png              # click the real share button headlessly, look at out.png (macOS + Chrome only)

The art contract is themes/ART-SCHEMA.md; every field is optional and an empty art file must still render. Pictures resolve --assets → art dir → plan dir → themes/assets/.

4. Pictures and video: three rungs, best first. The skill walks this ladder itself, silently, before it ever mentions a page style:

  1. Native — the agent running the skill can already generate images or video, so it uses that: art drawn for this trip, no key to set up (same specs and prompts, same split_sheet.pycutout.pytowebp.py → trip-manifest steps; the contract is the generator-choice section of themes/ART-SCHEMA.md).

  2. One key — no native generation: create themes/.auth_header containing one line — Authorization: Bearer <your OpenRouter key> — (gitignored, read only from that directory; both scripts pass it to curl as a header file, so it must be the full header line, not the bare key). --dry-run prints the credential path it would read:

    python3 themes/gen.py <trip>/jobs.json --outdir <trip> --manifest <trip>/manifest.<trip>.json      # gpt-image-2; --dry-run first
    python3 themes/genvideo.py jobs.json --outdir <trip>/portal --manifest <trip>/manifest.<trip>.json  # veo-3.1-lite by default; --models for prices
    
  3. Stock kit — neither of the above: the pictures come from the kit bundled in this repo, and the page is still a themed page (next block).

On every rung the shipped library comes first — themes/assets/IMAGE-LIBRARY.md indexes 355 stems (515 webp, 30 MB) by subject, and its rules draw the line: generic props are reusable, while anything destination-specific (covers, hero plates, title stickers, terrain bands, splash islands, journal photos) must belong to the trip it is on. Real costs from the shipped examples: $0.25–0.46 of image generation per trip (7–11 gpt-image-2 calls). The portal theme is the one that needs footage: either genvideo.py in the cloud (google/veo-3.1-lite, 720p, ≈ $0.03/s → roughly $3 for a ten-world chain; smoke-tested on one 4 s clip, $0.12) or a local GPU (the author's regression footage comes from ComfyUI on an RTX 5090 via themes/build_portal_jobs.py). The US chain that drove the design (19 clips, ~35 MB) is the style reference and a release asset, not part of the tree — one curl + unzip restores it into themes/assets/portal/ (how). The shipped portal case is Morocco, live on the demo site; another trip needs its own chain.

No image generator? Still a designed page. Two commands, and the plan comes out in a real theme instead of degrading to plain text:

python3 themes/stock_art.py plan.geo.json --theme illustrated -o plan.art.json
python3 themes/render_theme2.py plan.geo.json --art plan.art.json \
        --assets themes/assets/stock -o trip-illustrated.html   # --assets is required here

The kit (themes/assets/stock/, 80 stems / 161 webp / 5.2 MB, all in the illustrated gouache style) holds 14 region cover paintings, 30 generic scene cut-outs and 36 world-landmark cut-outs; stock_art.py picks the cover from the destination country and one hero per day by keyword score, leaves the words (cover title, day titles, captions) to the agent, and writes the notice — "Pictures: built-in stock kit — no image generator or key was available; provide one and the art is generated for this trip." — into the page's fine print, where it must stay, and into the chat summary. Coverage: complete for illustrated, works for clay; the other six themes need generated pictures. Details: themes/assets/stock/README.md.

How it works

Pipeline. SKILL.md is the playbook the agent follows: Phase 0 intake (one message, only for what is missing) → Phase 1 country brief (visa from official sources, holiday API + a budgeted festival search, weather, money, safety) → Phase 2 route skeletons → checkpoint → Phase 3 flights and intercity legs (scripts/flight_scan.py) → Phase 4 city day-plans (parallel city subagents with an explicit search budget) → Phase 5 hotels → Phase 6 assemble, adversarial self-check, deliver. Three moments with the user at most, usually two: an intake message only when a core fact is missing and cannot be inferred, the route-skeleton pick, and delivery.

Intake: no questions when the request already carries the facts. "Plan my Germany trip, 1–7 Oct this year" has the destination and the dates, so nothing is asked — the origin and the rest are inferred and listed as assumptions at the first checkpoint. Only a genuinely missing core fact (destination, when / how long, an origin that cannot be inferred) triggers a single intake message, and the optional preferences ride along in that same message, each one marked skip = default: travel style (public transport · self-drive · group tour), lodging habit and band, scenery taste (nature / city / beach / forest / lake / mountain), pace, party size, budget, ranked interests, date flexibility. Whatever you answer or the skill assumes is written into the plan's prefs block (assets/plan.example.json) so a later replan does not re-ask. Say "just plan it, don't ask" and both the intake and the route checkpoint are skipped, with every assumption stated at the top of the result.

One file, one truth. plan.geo.json is written once and read by everything: scripts/route_tools.py (geocode · check · links --write · kml · sun) produces the map links and the KML from its stops; scripts/render_plan.py produces the plain HTML; every themed renderer reads the same file plus its art.json. That is what stops the written plan, the map links and the pretty version from drifting apart. Schema template: assets/plan.example.json — copy it, fill the PLACEHOLDERs, then render (render_plan.py refuses an unfilled copy unless --force).

Hard rules (distilled from SKILL.md and references/):

  1. Never books, pays, holds, or enters personal data — links and a checklist only.
  2. Prices and hours come from tools, never from memory; a missing price is "—, check link".
  3. Cheap before expensive: bundled scripts and keyless APIs first, browser second; never curl OTA or airline sites.
  4. Search budgets are explicit and written into every subagent prompt.
  5. Estimates stay estimates: transit durations ship as (est.) ranges unless verified.
  6. Beyond ~3 months out nobody publishes that day's hours — verify the seasonal pattern, stamp "as of {date}", put a re-confirm task on the checklist.
  7. The plan must survive the self-check before delivery: closure scans, chain arithmetic, last-entry times, walking totals, open-jaw consistency.

Data sources — all keyless and free; prices are comparison-grade and the deep links in the plan are the source of truth (references/data-sources.md):

SourceUsed forNotes
Google Flights (via fast-flights)flight price gridsoutbound legs listed; return times back-computed
Nominatim / OpenStreetMapvenue coordinates1 req/s + User-Agent enforced in-script; weak on non-Latin names
Nager.Datepublic holidaysno religious / lunar holidays — a budgeted festival search covers the gap
Open-Meteoweather and climate for the datesfirst call can take ~10 s
sunrise-sunset.orggolden-hour schedulingrequires visible attribution in the plan footer
frankfurter.dev → open.er-api.comFXECB daily, ~30 majors; minor / closed currencies fall back to open.er-api.com
Google Maps / Booking / operator siteshotel bands, transit detail, ticketsbrowser, deep links only

Hotels have no usable keyless API, so the skill recommends neighbourhoods and produces dated deep links rather than quoting a nightly price it cannot verify.

Compatibility

  • Format, not a product integration. This is an Agent Skill — an open format: a SKILL.md playbook plus references/, scripts/ and themes/. Any harness that loads Agent Skills can load this one; nothing here is tied to one vendor's agent.
  • The agents. Claude Code, Codex, Gemini CLI, Cursor, GitHub Copilot, OpenCode, Qwen Code, Deep Code (DeepSeek), Goose, Kiro and Roo Code all declare support for SKILL.md skills, and the scripts here are stdlib-only Python 3.9+. The only difference between them, from this repo's point of view, is where they expect skills to live — so the git clone target in Quick start is the one line you adapt.
  • Verified in Claude Code; the rest are untested. Every trip, render and export in this repository was produced in Claude Code, and the install path above is its skills directory. We have not run the other harnesses one by one — reports welcome, including the skills directory each one expects.
  • What the harness needs. A shell that can run Python 3.9+ (the scripts), and web search / fetch tools (the country brief, day plans and hotel phases verify hours, prices and holidays online). Nice-to-have: subagents (Phase 4 fans out one agent per city — a harness without them plans the cities in sequence), a browser tool (the flight and hotel price fallbacks when the keyless scripts fail), and native

Files in the repo

Repository payload13 top-level entries
  • .github
  • assets
  • docs
  • examples
  • references
  • scripts
  • themes
  • .gitignore
  • LICENSE
  • README.md
  • README.zh-CN.md
  • SKILL.md
  • THIRD-PARTY-NOTICES.md

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More skills

Turn any codebase, with its docs, SQL schemas, configs, and PDFs, into a queryable knowledge graph. A /graphify skill for Claude Code, Cursor, Codex, and Gemini CLI: local deterministic AST parsing, every edge explained, no vector store.

117k
1 add

Open-source AI job search: scan job portals, evaluate listings into a structured A-H report with a global 1-5 score, tailor your CV, track applications — runs locally in your AI coding CLI (Claude Code, Codex, OpenCode, Antigravity…)

71k
ayghri/
i-have-adhd

A skill to stop your coding agent from burying the answer. ADHD-friendly output.

38k
mvanhorn/
last30days-skill

AI agent skill that researches any topic across Reddit, X, YouTube, HN, Polymarket, and the web - then synthesizes a grounded summary

62k
Nanako0129/
sepia

De-AI writing skill for any Agent Skills-compatible agent (77+ via the Skills CLI), with native plugins for Claude Code, Codex, Grok Build, and Antigravity. Narrative-architecture repair for fiction, venue-matched rules for professional prose. Based on StoryScope (arXiv:2604.03136).

2.5k
Imbad0202/
academic-research-skills

Academic Research Skills for Claude Code: research → write → review → revise → finalize

48k