← Search

map-3d
Video 📌 Pinned version: commit 65ab781
🔎 Install prompt analysis · 2026-10-19 : runs commands · makes network calls · writes files · uses API keys or tokens
⚙ Needs: Before you start: read this whole install prompt…

map-3d

Turn one JSON spec into a vertical 3D terrain map video: real relief (AWS Terrain Tiles elevation draped with Esri satellite imagery, MapLibre GL) — a dive from orbit, a full-route 3D overview

At a glance
What
Turn one JSON spec into a vertical 3D terrain map video: real relief (AWS Terrain Tiles elevation draped with Esri satellite imagery, MapLibre GL) — a dive from orbit, a full-route 3D overview
Cost
Free
Needs
Before you start: read this whole install prompt, tell me in a few lines what this skill does and what installing it involves, and wait for my go-ahead before you do anything else.
Install
Copy the installer prompt below into your Muse — your agent does the rest.

Version:

⌁

Install

Copy the install package below, then paste it into Muse📌 Pinned version: commit 65ab781
Wanna be extra careful?

The install prompt below already includes the vetting steps: your agent follows the community checklist before installing anything with executable code. Want more?

How to check a build before installing →

🧭 What this touches
  • It can run commands on your Muse’s computer.
  • It can contact outside services over the network.
  • It can create or modify files.
  • It works with an API key or a token that you provide.
Install prompt analysis · 2026-10-19
🔒 Security and provenance
📌 Pinned version: commit 65ab781 · 2026-10-19
🔎 Install prompt analysis · 2026-10-19 : runs commands · makes network calls · writes files · uses API keys or tokens
What the scan found — excerpts from the install prompt
  • runs commands — Prerequisites: none for the install itself — no account, no API key, no paid service, and nothing is run or do · (e) Package and browser downloads at first use (never during this install): each m3d run executes uv run -q -- · (e) Téléchargements de paquets et de navigateur au premier usage (jamais pendant cette installation) : chaque
  • makes network calls — (a) AMap / Gaode — scripts/amap.py → https://restapi.amap.com — ONLY if the spec contains place-name strings o · (b) OpenStreetMap Overpass — scripts/osm.py → POST to the first working mirror of https://overpass-api.de/api/ · (f) Present in the installed files but NOT called by map-3d's own modes — know they are there: scripts/elev.py
  • writes files — Prerequisites: none for the install itself — no account, no API key, no paid service, and nothing is run or do · - The layout is two parts, and both are needed. (a) The skill folder map-3d/ holds 8 files only: SKILL.md (10, · Prérequis : aucun pour l'installation elle-même — aucun compte, aucune clé API, aucun service payant, et rien
  • uses API keys or tokens — Prerequisites: none for the install itself — no account, no API key, no paid service, and nothing is run or do · Prérequis : aucun pour l'installation elle-même — aucun compte, aucune clé API, aucun service payant, et rien
Skill Harbor never reviews the code of a listed skill. These are dated facts about the install prompt and our install test, not a safety certification. Review a skill yourself before you install it. How we verify

Before you start: read this whole install prompt, tell me in a few lines what this skill does and what installing it involves, and wait for my go-ahead before you do anything else. Prerequisites: none for the install itself — no account, no API key, no paid service, and nothing is run or downloaded beyond the skill files from GitHub at the pinned commit. For using the skill afterwards, read this first, because the tooling is heavy: you need Python 3, uv, ffmpeg, and zsh (the entry wrapper map-3d/scripts/m3d.sh is a zsh script; on a machine without zsh, the same commands can be run as python3 map-3d/scripts/m3d.py …). The first actual use downloads more, on its own — disclosed here, never during this install: uv fetches the Python packages certifi, pillow and playwright from PyPI on every m3d run (uv run --with …), Playwright needs its Chromium browser (uv run --with playwright playwright install chromium, a large download, done by me separately, later), render.py downloads MapLibre GL 5.24.0 from unpkg.com once and caches it, and a first render downloads thousands of satellite and elevation tiles and caches them under ~/.cache/map-motion/. One key is conditional: a free AMap (Gaode) "Web Service" API key is needed ONLY when a spec uses place-name strings or AMap route planning (driving/walking/bicycling from/to) — specs written with numeric coordinates, a GPX/GeoJSON track file, or OSM trail waypoints do not need it. The key is read from the environment variable AMAP_KEY or from the file ~/.config/map-motion/amap_key, never from the spec; I set it myself, later, if I need it — do not ask for it and do not set it during this install. Renders are slow (software WebGL: roughly 1 frame per second, a 30-second clip takes about 15–25 minutes and runs in the background) and the output is a vertical (portrait) MP4 plus a 270px preview GIF. Install "map-3d" for me. It makes 3D terrain map videos from one JSON spec: real relief (AWS Terrain Tiles elevation + Esri satellite imagery, rendered with MapLibre GL) with a satellite-earth dive, a full-route 3D overview, then a camera that follows the track (walked line turning yellow, live mileage, elevation, cumulative climb, a mini-map, a bottom elevation profile, and photos from the spec popping up along the way), ending pulled back with totals — for hiking/mountaineering (GPX file or OpenStreetMap trail linking), driving, cycling and walking routes; or a single place dived to and orbited (place name, coordinates, elevation); or a sunlight forecast ("sun" mode: for a given date, when sunrise/sunset light hits a peak and when a chosen viewpoint first sees light, computed from the real solar position plus terrain shadowing, about ±3 minutes). It is a sub-skill of the map-motion engine in the same repository: the map-3d folder alone does nothing — its scripts/m3d.py drives the shared engine at the repository root (scripts/compile.py dispatches "3d" specs to scripts/terrain3d.py and "sun" specs to scripts/sunlight.py, scripts/render.py renders), so this install places the skill and the strictly required engine files side by side, in the layout m3d.py itself looks for. Repository: https://github.com/SpaceZephyr/map-motion (the skill is the map-3d/ folder, 8 files, plus the engine subset listed in step 1: 13 Python modules in scripts/, 4 files in scripts/runtime/, and the 4 font files in assets/fonts/ that the 3D runtime loads — 29 files in total) Pinned version: install the code at commit 65ab781832cace6e0f28d4c00452410a99f3a02c exactly. Do not substitute a newer version. If this commit is unreachable, stop and tell me. 1. Clone https://github.com/SpaceZephyr/map-motion into a temporary folder, check out commit 65ab781832cace6e0f28d4c00452410a99f3a02c, and from that checkout take exactly these 29 files (repository paths): the whole map-3d/ folder (8 files), scripts/amap.py, scripts/audio.py, scripts/compile.py, scripts/dem.py, scripts/elev.py, scripts/geo.py, scripts/osm.py, scripts/qa.py, scripts/render.py, scripts/status.py, scripts/sun.py, scripts/sunlight.py, scripts/terrain3d.py, scripts/runtime/hud.js, scripts/runtime/qa.js, scripts/runtime/t3d.js, scripts/runtime/terrain.html, and assets/fonts/Anton-400.woff, assets/fonts/LXGWWenKai-500.woff, assets/fonts/NotoSansSC-700.woff, assets/fonts/NotoSansSC-900.woff. Compare every one of them with the fingerprints recorded for this listing on 2026-10-19: [FINGERPRINTS] - map-3d/SKILL.md: SHA-256 c8cd678bfc9a2d2b45be7e3e0c05fe57e5809b4d4592f31035ca041572702b52 - map-3d/examples/drive_amap_shangrila.json: SHA-256 7d97cee99fcfe122d81fcff4d762bcff12df882a4b8da8852f1193361f37640f - map-3d/examples/hike_osm_yubeng.json: SHA-256 bdd3e8129391ab4d9579a4778755426eb8369a32feaed367e817507e38a7fe6a - map-3d/examples/place_orbit_meili.json: SHA-256 a1ac1c749ccdc0e6615888bc009fd484ca7fd1d671bcf6e233108a9f01b83312 - map-3d/examples/sun_meili_sunrise.json: SHA-256 f302f78c6d69a783d9b18a45dacf5a453ffc6e3f81d79064c0eaff192283fc87 - map-3d/examples/walk_amap_taishan.json: SHA-256 b2854dd5f1ed348bd79b068fcfa67430ff1978931a3fe7d9f57321737efcc397 - map-3d/scripts/m3d.py: SHA-256 eeb3bfc0e96247c70ead88aa0cadcc479fa80b0495b2b9428056b225b0bca47d - map-3d/scripts/m3d.sh: SHA-256 705ad779aae7e1b4f92ab8eb6df3eb2ec82b397746e4c4ed2e96b067bab8c243 - scripts/amap.py: SHA-256 7db7efbaf5b63362ca8078d88da9f0606e5c38a92410c3643e0f19072486b92d - scripts/audio.py: SHA-256 4785e478cea1ff36158f3db471214706465fa7cd8946e516c5f4faad6d52770e - scripts/compile.py: SHA-256 32420d87aa526d5bf86ea526dfb61e63d4ba2b31666c5828bbb4d5bbd3a5879e - scripts/dem.py: SHA-256 c193482183aa1e0bb54e8b7661d77e6dde0a6e56339c2e3c229439013d588a9c - scripts/elev.py: SHA-256 ec41a716692742c58a80596b1df804db02d8f7017108ad2d0797b2b1b5b588a7 - scripts/geo.py: SHA-256 9a7b1f555e7a54c0b5f15504a9aa213d4dc99b3f11c410404d6ab57cf30e7b63 - scripts/osm.py: SHA-256 3e30d7b0d8288f5a62de626f428899cddf9c7ca5b3e94623ebf7892a307421e2 - scripts/qa.py: SHA-256 9b87b89c690d22aeecf0441685f2d7489a2379cf9a8c9514045e2438eeb19baa - scripts/render.py: SHA-256 fd5eb323b0207c9b9920aa6dc24982113a04020b582fe67266f8359a57db5ecd - scripts/status.py: SHA-256 eca7060ddc17aef9262d5b0c7536449de7f6856afe4184411be43351f3c5f0d5 - scripts/sun.py: SHA-256 2c6ce15ccc443a6fa0935d31ca76fdca1cea4d2d82c6119598757f91269db2bc - scripts/sunlight.py: SHA-256 577c7613504d84a14c5813a7ace7534c81dc0dee8bb0c295fcb7a7f58819dadc - scripts/terrain3d.py: SHA-256 cd2741899a619a477c917e6107a04033157a3e92bf29b1662c94ff65c6602cc2 - scripts/runtime/hud.js: SHA-256 143017794af92ca455a6caa8ec3c1811171ee80b99c0d875442ce10a9983f4db - scripts/runtime/qa.js: SHA-256 8c761421f289a378b8341fac965a1f516567899eda9cb5786ac1fc8f792e801a - scripts/runtime/t3d.js: SHA-256 a891d9343f8471407c1b39bd6d5fe2d2a796d0a81e479aa6c61663e97fb7a306 - scripts/runtime/terrain.html: SHA-256 61cc9712c9323e2ba22ea1d5bb7d9e19bf5bfe52b518a1edb717528c80e7954c - assets/fonts/Anton-400.woff: SHA-256 791375bdbed00de4a3aad4811291220ead0e1405d6f8b5bdbf109798c8359ac5 - assets/fonts/LXGWWenKai-500.woff: SHA-256 734bd187392579417ac83effe31d37b9de43c7b290bcb400800456511ed79e8f - assets/fonts/NotoSansSC-700.woff: SHA-256 dd0d39a9780eb995c499af0c20cca93b1dfdda865da70871a20890b3e406b968 - assets/fonts/NotoSansSC-900.woff: SHA-256 d2d8a42438b18b65b6577434df4e41bb08c6b5051281757849af00ab743bb58f If a file does not match, it changed since the listing was prepared: do not install it yet, tell me what you found and let me decide. 2. Read map-3d/SKILL.md in full, read map-3d/scripts/m3d.py and m3d.sh, and read the engine files listed above (compile.py at least for its "3d"/"sun" dispatch, terrain3d.py, sunlight.py, sun.py, dem.py, elev.py, osm.py, amap.py, geo.py, render.py, and the runtime files terrain.html, t3d.js, hud.js, qa.js), and tell me in plain words: what the skill does when used, which services it connects to, whether it reads or sends any personal information or keys, and anything that seems unusual. Stop on any red flag and tell me before going further. Confirm these points from the files: - The layout is two parts, and both are needed. (a) The skill folder map-3d/ holds 8 files only: SKILL.md (10,000 bytes), five example specs in examples/, and scripts/m3d.py + scripts/m3d.sh. (b) The engine subset is 21 files: 13 Python modules at the repository root scripts/ and 4 runtime files in scripts/runtime/, plus the 4 fonts in assets/fonts/. m3d.py finds the engine first at <parent of the map-3d folder>/scripts/ and otherwise falls back to ~/.claude/skills/map-motion/scripts — step 3 uses that fallback layout. The rest of the repository is NOT part of this install and is not needed by map-3d: the root SKILL.md and scripts/make.sh (the main 2D skill's entry), scripts/runtime/mm.js and scripts/runtime/index.html (the 2D runtime; 3D timelines declare "runtime": "terrain" and never load them), assets/land.json and assets/china.json (loaded only by mm.js), the documentation in references/ and README.md, the root assets/examples/, docs/media/, and the two sibling skills photo-spot/ and travel-vlog/ — separate listings that share the same engine but that map-3d never imports or calls (no cross-reference exists in either direction; each sibling has its own wrapper around the engine). - Nothing is sent anywhere during installation itself; the only download at install time is the repository from GitHub at the pinned commit. No script is run, no package is installed, no browser is downloaded, and no key is asked for during installation. There is no telemetry in the perimeter. - What leaves this machine at use time, disclosed here before it ever happens — using the skill is a separate step that only starts when I give it a spec, and every send below happens then, at compile or render time, through plain HTTPS GET/POST calls in the listed files (no hidden calls: every network call in the perimeter goes through amap.py, osm.py, dem.py, or the local proxy in render.py): (a) AMap / Gaode — scripts/amap.py → https://restapi.amap.com — ONLY if the spec contains place-name strings or an AMap-planned track ({"mode": "driving"|"walking"|"bicycling", "from": …, "to": …}): geocoding sends the place-name/address strings I wrote (GET /v3/geocode/geo, falling back to POI keyword search GET /v3/place/text) and route planning sends the origin, destination and waypoint coordinates (GET /v3/direction/driving, /v3/direction/walking or /v4/direction/bicycling); my AMAP_KEY goes with every one of these requests as the "key" query parameter, to AMap only. Responses are cached under ~/.cache/map-motion/api/ so repeats do not re-send. Coordinates I write numerically are never sent to AMap (only converted locally between WGS-84 and GCJ-02). (b) OpenStreetMap Overpass — scripts/osm.py → POST to the first working mirror of https://overpass-api.de/api/interpreter, https://maps.mail.ru/osm/tools/overpass/api/interpreter, https://overpass.kumi.systems/api/interpreter — ONLY for a trail spec ({"via": [waypoints…]} with no GPX): the request body is an Overpass query containing the bounding box computed from my waypoints (plus the spec's margin, 0.02° by default), i.e. the area my route crosses is disclosed to the mirror that answers. Cached under ~/.cache/map-motion/osm/. A GPX/GeoJSON track file is parsed locally and is never uploaded. (c) AWS Terrain Tiles — scripts/dem.py → GET https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png — on EVERY 3D/sun compile: elevation is sampled for each point of my track/place (and, in sun mode, along sight lines up to 80 km around the peak and viewpoint), so the tile coordinates requested reveal the area of my route; no key. Cached under ~/.cache/map-motion/tiles/dem/. The same tiles are fetched again at render time through the render proxy (same host, same cache). (d) Render-time tiles and library, through the local proxy in scripts/render.py (a temporary HTTP server bound to 127.0.0.1 on a random port, serving only the runtime files, the fonts, the tiles below, and the photo files named in my spec — to the local headless Chromium only): Esri World Imagery satellite tiles GET https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x} (tile coordinates of the filmed area; sent with a "Referer: https://www.amap.com/" header the proxy adds to tile requests), the AWS elevation tiles of (c), and, once, MapLibre GL 5.24.0 from https://unpkg.com/[email protected]/dist/maplibre-gl.js, cached under ~/.cache/map-motion/vendor/. The browser page itself (scripts/runtime/t3d.js) only ever talks to that localhost proxy (/tile/…, /asset/fonts/…, /file/…); it calls no outside host directly. My spec's photos are read from local files and served by that proxy to the local browser only — they are not uploaded anywhere — but they end up visible in the finished video, which is mine to publish or not (SKILL.md warns about photos showing people). (e) Package and browser downloads at first use (never during this install): each m3d run executes uv run -q --with certifi --with pillow --with playwright python …, so uv downloads those three packages from PyPI if they are not already in its cache; the Playwright Chromium browser is a separate one-time download I trigger myself. ffmpeg is a system tool the scripts call locally; it makes no network calls. (f) Present in the installed files but NOT called by map-3d's own modes — know they are there: scripts/elev.py contains a lookup to https://api.opentopodata.org/v1/srtm30m that sends coordinates in batches of 100, but the 3D/sun code paths only use elev.py's local GCJ↔WGS conversion and never call that lookup (it serves the main 2D skill); scripts/amap.py also contains a district() boundary function and scripts/osm.py an area() boundary function that map-3d never calls; scripts/render.py's proxy table also contains AMap tile URLs (wprd0*.is.autonavi.com, webst0*.is.autonavi.com) that only the 2D runtime requests — the 3D runtime requests Esri and AWS tiles only. scripts/render.py launches headless Chromium with --disable-web-security (plus SwiftShader software-WebGL flags for terrain); that browser only loads the localhost page above, but the flag is real — do not reuse that launch configuration for anything else. - The local-only parts at use time: the sun position math (scripts/sun.py, NOAA algorithm), all camera/geometry math (geo.py, terrain3d.py, sunlight.py), the automatic QA (qa.py/qa.js), audio synthesis (audio.py, imported by render.py; 3D timelines carry no sound events, so it stays idle), title/HUD drawing, and the ffmpeg encodes. AMap responses, OSM responses and tiles are cached under ~/.cache/map-motion/ (api/, osm/, tiles/, vendor/), so re-rendering the same spec re-sends little or nothing. Mileage and climb are computed from AWS elevation data and can differ 5–15% from a watch; a trail built from OSM ways is a shortest-path guess between waypoints, not a track I actually walked — the delivery must say which source a route came from. - Terms caution from the repository itself: AMap tiles/API and Esri imagery are fine for personal, non-commercial videos with the on-screen attribution kept; commercial use needs an AMap / Esri licence. Do not remove the attribution line the engine burns into the frame. - Do not install uv, ffmpeg, Python packages or Chromium during this install, do not set or ask for AMAP_KEY, do not run m3d.py/m3d.sh, compile.py or render.py, and do not render any video: tool setup and the key are my decisions, later, when I actually ask for a 3D map video. 3. When I say "yes, install", install it as two sibling folders, copying only the verified files from the pinned checkout: (a) the map-3d folder into the agent's skills directory as "map-3d", keeping all 8 files (SKILL.md at its root, examples/, scripts/m3d.py and scripts/m3d.sh); (b) the engine into a folder named "map-motion" next to it: the 13 scripts/*.py modules into map-motion/scripts/, the 4 runtime files into map-motion/scripts/runtime/, and the 4 fonts into map-motion/assets/fonts/ — exactly the fallback path ~/.claude/skills/map-motion/scripts that m3d.py looks for. Do not copy any other repository file (no root SKILL.md, no make.sh, no mm.js/index.html, no land.json/china.json, no photo-spot/, no travel-vlog/). Any other layout is fine only as long as every installed file matches its fingerprint and m3d.py can find terrain3d.py in one of its two documented engine locations. 4. Verify with no network calls: frontmatter of the installed map-3d/SKILL.md valid (name: map-3d), all 29 files in place across the two folders with matching fingerprints. Do not run any script, do not invoke uv, and do not open the runtime pages to verify. 5. Report what was installed, where, and what I still need to do myself (for example: install uv and ffmpeg myself if they are missing; on first use, let uv fetch certifi/pillow/playwright from PyPI and install Playwright's Chromium myself — both are downloads that happen at use time, not install time; create a free AMap Web Service key and set AMAP_KEY or ~/.config/map-motion/amap_key myself ONLY if I want place names or AMap-planned routes — coordinate, GPX and OSM-trail specs work without it; expect the first render of an area to download thousands of Esri/AWS tiles into ~/.cache/map-motion/ and a 30-second clip to take roughly 15–25 minutes in the background; keep the use commercial/non-commercial boundary and the attribution line in mind; using the skill is a separate step that only starts when I give it a spec, and the use-time sends disclosed in point 2 happen only then). GitHub is optional: if I have a GitHub account or the gh CLI, you may use it; otherwise public access is fine. Never require it unless it's in the prerequisites above. Rules: don't touch anything outside the temp folder and the install targets. If anything looks off, stop and ask me.

?

Questions

How do I install a build?

Every product page includes a copy-paste install prompt. Paste it into your Muse and it sets the build up for you — no manual configuration.

Where does my money go?

Straight to the seller. Skill Harbor never processes payments: checkout happens on the seller’s own page, usually Stripe.

What does the ✓ next to a creator’s name mean?

It means we confirmed the identity of the person behind the listing. It says nothing about the code itself — always check a build before installing it.