Install
$ agentstack add skill-jaakla-openmapstack-openmapstack ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ● Dynamic code execution Used
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
OpenMapStack Toolkit
Production-grade geospatial workflows with an open-first stack and pragmatic hosted/SaaS choices when global scale, latency, SLA, or data quality makes local processing a poor fit. Cloud-native by default: STAC for discovery, GeoParquet + COG + PMTiles for storage, DuckDB and PostGIS for compute, MapLibre and Martin for delivery.
Reproducible project-first contract
> Core principle: reasoning may be exploratory; the delivered analysis must be deterministic, inspectable, and reproducible.
For any material multi-stage GIS analysis, do not optimize for reaching the final map, dashboard, or answer quickly. A one-off polished dashboard is not the deliverable — a reproducible technical GIS project is. First establish a reusable project artifact, then derive the map/dashboard/report from it.
Before treating an analysis as complete, you MUST compile (or maintain) a project like examples/tartu-development: a canonical project.yaml (openmapstack-project/v1), pipeline.py, and README.md; pinned sources with timestamps, selections and licensing; explicit assumptions; every manual addition or correction stored as real geodata; deterministic ordered steps with explicit CRS; machine-readable validation rules plus the report from the run; and output definitions with semantic presentation intent and provenance surfaced in the rendered view. references/project-spec.md is the full schema — read it before compiling a project.
Workflow (agent may retry/experiment internally, but the accepted analysis is recompiled deterministically):
USER QUESTION
↓
interpretation / exploration (internal, may be ad-hoc)
↓
COMPILE GIS PROJECT project.yaml + pipeline + manifest + overrides + validation
↓
EXECUTE PROJECT
↓
validated derived datasets
↓
QGIS project / standardized web view
↓
FINAL ANALYSIS / DASHBOARD / ANSWER
The polished map/dashboard is a view over the project, not the canonical definition of the analysis.
Hard rules for every material analysis — each is expanded in references/project-spec.md:
- Real source data mandatory; never hallucinate coordinates. Fabricating coordinates or synthesizing baseline geometry is forbidden without explicit, informed user consent. Hypothetical or planned features go in
data/overrides/with provenance, rationale, and evidence. - Never mutate source data. Immutable source + project override layer = effective input. Distinguish external facts, transformations, corrections, assumptions, and hypothetical data.
- Overrides must be executable and verified. Target a real source feature; for attribute changes the asserted prior value must match. Evidence must be non-placeholder. Validation reports each override
applied,rejected, ornot_testable— listing one is not applying it. Scenario features stay labeled hypothetical and visually distinct from authoritative layers. - Record, don't memoize on chat. Encode every manual fix as data or pipeline logic. A fresh environment with the documented sources must reproduce the project; the transcript is not part of the dependency graph.
- Prove semantic predicates from data. Ownership, active status, public access, legal designation: the source must expose an authoritative field or documented mapping. Preserve unknown as unknown; never default a missing value to the desired class.
- Bounded APIs must prove completeness. Record
numberMatched/equivalent and page until returned == matched. A response filled to the request limit is incomplete until proven otherwise. - Validation is a pipeline stage, not prose advice, with machine-readable results. Every declared check appears exactly once in the report;
warning/not_testablepropagate to run and project status; run IDs and hashes resolve to a realruns/*.jsonrecord. - Run the project CLI when available. Use
openmapstack validate project.yamlbefore delivery andopenmapstack run project.yamlfor the canonical execution path. The CLI audits the manifest, provenance, graph, artifacts, report, and run record; it does not replace domain GIS checks performed by the pipeline. - The manifest must resolve. Every step input is a source key or an earlier step's output, spelled as the producer declared it; every
generated_bynames a real step (manifest_graph_resolves). - One canonical implementation creates every declared output. Convenience/E2E entrypoints may wrap
pipeline.pybut must not duplicate its processing, QGIS, or report logic. - Build a layer- and style-perfect QGIS project (
project.qgz) mirroring the web view: matching layer-tree groups, identical categorized styles,./path.gpkg|layername=namedatasources, and a regional tiled basemap. Success means valid layers, not exit code 0 — pin the runtime, and when PyQGIS is available require every layerisValid(); otherwise recordnot_testable, never an implicit pass. - Separate analysis semantics from rendering. Declare semantic presentation roles; don't reinvent layout/colors/UX per run.
- Ship a reconfigurable view, and never let it misrepresent the run. Organise the sidebar into tabs of collapsible sections, give every layer group an on/off control, and expose the analysis parameters and scenario overrides as live controls. Each control opens at the value declared in
presentation.controlsand returning there must reproduce the published numbers; any other position labels itself exploratory and offers a reset. The browser re-applies published rules to values the pipeline measured — it never measures geometry, and a control that changes a shape switches between buffers the pipeline materialised. - Labels must match the operation. A Euclidean buffer is a "2 km straight-line proxy", not a walking catchment, and column names must say so too. State the measurement basis (nearest edge vs centroid) as an assumption — it changes which features qualify.
- Cheat-sheet:
references/project-spec.mddefines the full schema;templates/gives ready scaffolds;examples/tartu-developmentis a worked reference project matching the acceptance scenario.
Modules — read the relevant reference(s) before starting work
| If the task involves... | Read | |---|---| | Finding or sourcing data (OSM, Overture, Sentinel, Landsat, building footprints, regional portals, STAC catalogs, MCP-based discovery) | references/data-sources.md | | Choosing local processing vs online/hosted/SaaS services for global or continental scale; basemaps, elevation, routing, geocoding, place search, postcode lookup APIs | references/services-and-scale.md | | Choosing a format, converting between formats, or any CRS / projection / EPSG question | references/formats-and-crs.md | | Compiling a reproducible GIS project artifact (project.yaml, pipeline, overrides, validation, presentation) | references/project-spec.md + templates/ | | Running GDAL/OGR, GeoPandas, xarray, DuckDB, PostGIS, or PDAL — the actual processing | references/processing.md | | Writing or reviewing spatial SQL / GeoSQL in DuckDB Spatial, PostGIS, BigQuery GIS, Snowflake, or Sedona | references/spatial-sql.md | | Vector analytics, raster analytics, terrain/hydrology, network analysis, point cloud workflows | references/analytics.md | | Tile generation (PMTiles, MVT), tile servers (Martin, TiTiler), delivered rendering (MapLibre, deck.gl), or exploration rendering (kepler.gl, lonboard) | references/web-delivery.md | | QGIS desktop, QGIS plugin ecosystem, QGIS MCP, PyQGIS scripting, Processing toolbox | references/qgis.md | | Reproducibility, validation, license attribution, tile smoke tests, deployment checks | references/validation-and-ops.md |
For simple one-shot questions (single CRS conversion, one ogr2ogr invocation), the relevant reference alone is sufficient — a full project artifact is not needed. For multi-stage pipelines, read data-sources.md and processing.md together, and see project-spec.md + templates/ to compile analysis into a rerunnable project. For end-to-end "from raw data to web map" tasks, also read web-delivery.md.
Global defaults — apply unless the user specifies otherwise
- Storage formats: GeoParquet (vector analytics), COG (raster), PMTiles (tile delivery), GeoPackage (desktop interchange). Never produce Shapefile as new output.
- CRS: WGS84 (EPSG:4326) for storage; Web Mercator (EPSG:3857) for web rendering; local projected CRS for any metric computation (distance, area, buffer). For Estonia, EPSG:3301 (L-EST97).
- Compute placement: push spatial joins and aggregations to DuckDB or PostGIS — not Python loops. R-tree / GIST / spatial indexing is mandatory at scale.
- Discovery first: check STAC catalogs (Microsoft Planetary Computer, Earth Search, Overture STAC) before downloading anything. Lazy load with
odc-stacorstackstacand only materialize what's needed. - Cloud-native access: prefer querying remote GeoParquet/COG over downloading. DuckDB with
httpfsextension is the default pattern for Overture and similar S3-hosted datasets. - Scale first: local tools are fine for city/state work; at continental/global scale prefer cloud-native partitioned datasets, precomputed tiles, hosted APIs, or SaaS when they are more reliable than local batch processing.
- License hygiene: preserve license metadata through every transformation. OSM is ODbL (share-alike); Overture varies by source; Sentinel is free-with-attribution; national data varies.
- Runtime hygiene: prefer
conda-forgeenvironments or containers for GDAL/PROJ/GEOS/QGIS stacks. Avoid pip-only geospatial environments unless the project already proves they work.
Format decision matrix
| Use case | Format | |---|---| | Cloud analytics on vector | GeoParquet | | Streaming vector over HTTP | FlatGeobuf | | Desktop interchange | GeoPackage | | Web map vector tiles | PMTiles (containing MVT) | | Raster archive / serving | COG | | n-dimensional raster (time series, climate) | Zarr or NetCDF | | Point cloud archive | COPC (cloud-optimized LAZ) | | API response payload (small only) | GeoJSON | | Legacy compatibility (input only) | Shapefile |
Compute decision matrix
| Scale / context | Use | |---|---| | 100M features, distributed | Apache Sedona | | Continental/global lookup/search/routing/elevation | Hosted API or SaaS where coverage, SLA, terms, and price fit | | Planet-scale basemap delivery | Prebuilt PMTiles/vector tiles or managed basemap service | | n-dim raster, lazy/dask-backed | xarray + rioxarray (+ odc-stac for STAC ingest) | | CLI batch jobs on raster | GDAL utilities (gdalwarp, gdal_translate -of COG) | | Point clouds | PDAL pipelines | | Terrain & hydrology beyond gdaldem | WhiteboxTools or GRASS | | Desktop styling, cartography, ad-hoc exploration | QGIS (see qgis.md) |
Universal anti-patterns — flag and correct
- Hallucinating or fabricating mock coordinates and geometries instead of retrieving real source data (unless the user gave explicit, informed consent for a synthetic mock test)
- Generating a QGIS project that lacks the web dashboard's layers, omits basemaps, or uses broken OGR datasource syntax (
path.gpkg|layerwithoutlayername=), causing layers to load as non-spatial attribute tables - Producing Shapefile as new output (column truncation, 2GB limit, no UTF-8, multi-file)
- Calling
.distance(),.buffer(), or.areaon geographic CRS (EPSG:4326) — degrees are not meters; unless specific tool explicitly supports wgs84 based geodesic calculations - Web Mercator (EPSG:3857) for area or distance calculations — it is not equal-area, and the units are not in meters except at the equator
- Spatial joins in Python loops when DuckDB / PostGIS / R-tree-backed
sjoinis one line away - Using bbox containment for area queries when features can cross the boundary — use bbox overlap as the scan gate, then an exact spatial predicate
- Downloading entire datasets when STAC + cloud-native formats allow lazy/range-request access
- Running planet-scale local processing for lookup/search problems when reliable hosted services or precomputed global products already exist
- Treating MBTiles as the default for new web deployments — PMTiles is the modern default
- Using GeoTIFF when COG is one flag away (
-of COG) - Mixing CRS silently — every join must assert matching CRS
- Hand-rolling routing or geocoding when OSRM, Valhalla, or Nominatim are one Docker pull away
- Pinning data to "latest" in a reproducible pipeline — pin Overture release version and STAC item IDs, not just collections. For Overture, verify the pinned release is still available or mirror it.
Quick triage — recognize the request type
Before diving into a task, classify it:
- Discovery ("what data exists for…?", "is there a dataset of…?") → start with
data-sources.md. STAC search if raster; Overture or OSM if vector basemap. - Conversion / CRS ("convert this to…", "reproject to…", "the projection looks wrong") →
formats-and-crs.md. Usually oneogr2ogrorgdalwarpcall. - Analysis ("what's the average elevation in…", "how many buildings within 500m of…", "where are the hotspots?") →
analytics.mdand likelyprocessing.md. Push to DuckDB/PostGIS first. - Delivery ("publish this as a web map", "generate tiles for…") →
web-delivery.md. PMTiles + Martin + MapLibre is the default. - Desktop / cartography ("style this in QGIS", "make a print map", "automate this in QGIS") →
qgis.md. Consider QGIS MCP for agentic workflows.
Most real tasks span 2–3 of these — read the relevant references in order.
Reproducibility checklist for any pipeline you produce
- Pin dataset versions (Overture release, STAC item IDs, OSM extract dates) — never "latest"
- Document CRS at every stage; never assume
- Use
conda-forgeenvs or pinned container images (ghcr.io/osgeo/gdal:alpine-small-latestfor GDAL,qgis/qgis:for PyQGIS); pip-only geospatial envs break frequently - Validate outputs:
gpqfor GeoParquet,rio-cogeo validatefor COG,pmtiles showfor PMTiles,is_validfor geometries - Preserve license metadata in column or sidecar JSON and carry required attribution into maps/APIs
Command-level detail for each of these lives in references/validation-and-ops.md.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jaakla
- Source: jaakla/openmapstack
- License: MIT
- Homepage: https://github.com/jaakla/openmapstack#readme
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.