-
Notifications
You must be signed in to change notification settings - Fork 2k
feat: Add SKILL.md for keplergl python package #3429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Copilot
wants to merge
18
commits into
master
Choose a base branch
from
copilot/xli-kepler-jupyter-skill-add-skill-md
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
0538412
Add SKILL.md and map type reference files for keplergl-jupyter
Copilot 84804a4
Add AI coding assistant guide section to bindings/python README.md
Copilot b576f58
Rename SKILL.md to CLAUDE.md following Claude Code standard protocol …
Copilot d41befd
Plan: rewrite SKILL.md with YAML frontmatter per official Claude Code…
Copilot fc7a268
Rewrite SKILL.md with YAML frontmatter per Claude Code skills protoco…
Copilot 0a2da21
Make skill-references always installed alongside SKILL.md, remove opt…
Copilot 0b8b479
Document default quantile+vibrant color guidance and custom-break wor…
Copilot df6f5d8
Address PR review thread feedback for Python skill docs
Copilot 476f834
docs(python): add Codex skill setup and packaging guidance
Copilot f7579b2
docs(python): document Codex skill setup and distribution in README
Copilot 2a14fc7
fix: add name to SKILL.md frontmatter, complete add_data/save_to_html…
Copilot 756ee4a
docs(python): update SKILL.md with kepler.gl-jupyter requirements and…
lixun910 ff37492
Merge branch 'copilot/xli-kepler-jupyter-skill-add-skill-md' of https…
lixun910 789a192
Add keplergl-map skill files for Python integration
lixun910 ede9f37
Update README.md and SKILL.md for keplergl-map skill
lixun910 90c91ab
Remove deprecated keplergl-map skill files and assets
lixun910 35a8d3f
Update publish workflow and plugin version
lixun910 f8af855
Update README.md to include direct download links for kepler.gl skill
lixun910 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| name: Publish kepler.gl Skill | ||
|
|
||
| on: | ||
| push: | ||
| paths: | ||
| - 'skill/SKILL.md' | ||
| - 'skill/skill-references/**' | ||
| - 'skill/agents/**' | ||
| - 'skill/plugin.json' | ||
| tags: | ||
| - 'skill-v*' | ||
| workflow_dispatch: | ||
|
|
||
| jobs: | ||
| build-skills: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Read skill version | ||
| id: version | ||
| run: | | ||
| VERSION=$(python3 -c "import json; print(json.load(open('skill/plugin.json'))['version'])") | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Build Claude skill package | ||
| run: | | ||
| STAGING=$(mktemp -d) | ||
| SKILL_DIR="$STAGING/kepler.gl" | ||
| mkdir -p "$SKILL_DIR" | ||
|
|
||
| cp skill/SKILL.md "$SKILL_DIR/SKILL.md" | ||
| cp -r skill/skill-references "$SKILL_DIR/skill-references" | ||
|
|
||
| (cd "$STAGING" && zip -r "$OLDPWD/kepler.gl-claude.zip" kepler.gl) | ||
| rm -rf "$STAGING" | ||
|
|
||
| - name: Build Codex skill package | ||
| run: | | ||
| STAGING=$(mktemp -d) | ||
| SKILL_DIR="$STAGING/kepler.gl" | ||
| mkdir -p "$SKILL_DIR" | ||
|
|
||
| cp skill/SKILL.md "$SKILL_DIR/SKILL.md" | ||
| cp -r skill/skill-references "$SKILL_DIR/skill-references" | ||
| cp -r skill/agents "$SKILL_DIR/agents" | ||
|
|
||
| (cd "$STAGING" && zip -r "$OLDPWD/kepler.gl-codex.zip" kepler.gl) | ||
| rm -rf "$STAGING" | ||
|
|
||
| - name: Upload Claude skill artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: kepler.gl-claude-v${{ steps.version.outputs.version }} | ||
| path: kepler.gl-claude.zip | ||
|
|
||
| - name: Upload Codex skill artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: kepler.gl-codex-v${{ steps.version.outputs.version }} | ||
| path: kepler.gl-codex.zip | ||
|
|
||
| - name: Build source package | ||
| run: | | ||
| zip -r kepler.gl-skill-source.zip skill/ | ||
|
|
||
| - name: Attach packages to release | ||
| if: startsWith(github.ref, 'refs/tags/skill-v') | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| files: | | ||
| kepler.gl-claude.zip | ||
| kepler.gl-codex.zip | ||
| kepler.gl-skill-source.zip |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # kepler.gl Skill for AI Coding Assistants | ||
|
|
||
| This directory contains the **kepler.gl** agent skill — a set of instructions and references that help AI coding assistants (Claude Code, Codex, Cursor, etc.) generate `keplergl` map scripts and exports consistently. | ||
|
|
||
| ## Skill References | ||
|
|
||
| | Reference | Description | | ||
| |-----------|-------------| | ||
| | [point-map.md](skill-references/point-map.md) | Scatter plot from lat/lng | | ||
| | [geojson-polygon-map.md](skill-references/geojson-polygon-map.md) | Polygons & lines from GeoJSON / GeoDataFrame | | ||
| | [h3-hexagon-map.md](skill-references/h3-hexagon-map.md) | H3 spatial index hexagons | | ||
| | [arc-line-map.md](skill-references/arc-line-map.md) | Origin–destination arcs & lines | | ||
| | [heatmap.md](skill-references/heatmap.md) | Density heatmap from points | | ||
| | [hexbin-aggregation-map.md](skill-references/hexbin-aggregation-map.md) | Spatial binning into hexagons | | ||
| | [trip-animation-map.md](skill-references/trip-animation-map.md) | Animated trips along paths | | ||
| | [summary-panel.md](skill-references/summary-panel.md) | SampleMapPanel-style info overlay in exported HTML | | ||
|
|
||
| ## Quick Setup via AI Agent | ||
|
|
||
| The easiest way to get started is to prompt your AI agent: | ||
|
|
||
| > Help me install the kepler.gl skill from | ||
|
|
||
| - claude: https://github.com/keplergl/kepler.gl/releases/download/skill-v0.0.1/kepler.gl-claude.zip | ||
| - codex: https://github.com/keplergl/kepler.gl/releases/download/skill-v0.0.1/kepler.gl-codex.zip | ||
| - source: https://github.com/keplergl/kepler.gl/releases/download/skill-v0.0.1/kepler.gl-skill-source.zip | ||
|
|
||
| or just "kepler.gl github repo" | ||
|
|
||
| The agent will locate the skill file and set it up for you automatically. | ||
|
|
||
| ## Example Prompt | ||
|
|
||
| > Create a map showing distribution of HR60 from natregimes.geojson. | ||
| > Color the polygons by population, use a light theme. | ||
|
|
||
| The agent will generate a Python script and run it, producing a standalone HTML map file you can open in any browser. | ||
|
|
||
| ## Versioning | ||
|
|
||
| The skill version is tracked in [`plugin.json`](plugin.json). Releases use the tag pattern `skill-v*` (e.g. `skill-v1.0.0`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,209 @@ | ||
| --- | ||
| name: kepler.gl | ||
| description: Create interactive map visualizations and export to standalone HTML using the keplergl Python package. Use when the user wants to create maps, visualize geospatial data, plot locations on a map, or generate HTML map files from DataFrames, GeoDataFrames, GeoJSON, or CSV data with coordinates. | ||
| --- | ||
|
|
||
| # Create Maps with keplergl | ||
|
|
||
| Use the `keplergl` Python package to create standalone, interactive HTML map files from geospatial data. The exported HTML loads kepler.gl from CDN — no JavaScript build or server is needed. The resulting `.html` file can be opened directly in any browser. | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| pip install keplergl | ||
| ``` | ||
|
|
||
| Requires `kepler.gl-jupyter >= 0.4.0`. Earlier versions use a different widget/serialization API and the examples in this skill will not work. Requirements: Python >= 3.9. Dependencies (`pandas`, `geopandas`, `shapely`) are installed automatically. | ||
|
|
||
| ## Instructions | ||
|
|
||
| 1. Import `KeplerGl` from `keplergl` | ||
| 2. Load data as a DataFrame, GeoDataFrame, GeoJSON dict, or CSV string | ||
| 3. Create a map with `KeplerGl(data={'name': data_object})` | ||
| 4. Optionally configure layers, colors, and map state via a `config` dict (default to quantile color scale and a vibrant palette for quantitative color encoding when the user does not specify) | ||
| 5. Export with `map.save_to_html(file_name='output.html', center_map=True)` | ||
| 6. The output HTML is fully standalone — open it in any browser | ||
|
|
||
| ## API Reference | ||
|
|
||
| ### `KeplerGl(data=None, config=None, height=400, mapbox_token="", use_arrow=False, show_docs=False, theme="", app_name="kepler.gl", **kwargs)` | ||
|
|
||
| | Parameter | Type | Default | Description | | ||
| |-----------|------|---------|-------------| | ||
| | `height` | int | 400 | Map height in pixels | | ||
| | `data` | dict | None | `{"dataset_name": data_object}` | | ||
| | `config` | dict | None | Map configuration (layers, filters, map state) | | ||
| | `mapbox_token` | str | "" | Mapbox token (only for Mapbox basemap styles) | | ||
| | `use_arrow` | bool | False | Serialize DataFrames as Arrow IPC (more compact, preserves types) | | ||
| | `show_docs` | bool | False | Deprecated (kept for compatibility) | | ||
| | `theme` | str | "" | `"light"`, `"dark"`, `"base"`, or `""` (default dark) | | ||
| | `app_name` | str | "kepler.gl" | App name in header and HTML title | | ||
|
|
||
| ### `.add_data(data, name)` | ||
|
|
||
| - `data`: DataFrame, GeoDataFrame, CSV string, GeoJSON dict, or GeoJSON string | ||
| - `name`: Dataset identifier — must match `dataId` in config if using a config | ||
|
|
||
| ### `.save_to_html(file_name="keplergl_map.html", data=None, config=None, read_only=False, center_map=True, mapbox_token="", json_encoder=str, app_name=None, theme=None)` | ||
|
|
||
| | Parameter | Type | Default | Description | | ||
| |-----------|------|---------|-------------| | ||
| | `file_name` | str | required | Output file path | | ||
| | `data` | dict | None | Data override for export (uses current widget data when None) | | ||
| | `config` | dict | None | Config override for export (uses current widget config when None) | | ||
| | `read_only` | bool | True | True = hide side panel | | ||
| | `center_map` | bool | True | True = auto-fit map to data bounds | | ||
| | `mapbox_token` | str | "" | Mapbox token override for export | | ||
| | `json_encoder` | callable | str | Fallback encoder for non-JSON-native values in GeoDataFrames | | ||
| | `app_name` | str | None | App name override for export title/header | | ||
| | `theme` | str | None | Theme override for export (`"light"`, `"dark"`, `"base"`, or `""`) | | ||
|
|
||
| ### `.config` | ||
|
|
||
| Read or set the map configuration dict. Use `map.config` after customizing in Jupyter UI, then save and reuse. | ||
|
|
||
| ## Key Rules | ||
|
|
||
| - **`dataId` must match the dataset `name`** — every layer and filter references a dataset by `dataId`; this must match the key in the `data` dict or the `name` passed to `add_data()`. | ||
| - **GeoJSON columns use `_geojson`** — when data is loaded as GeoJSON, the geometry column is internally named `_geojson` in configs. | ||
| - **`colorField` / `colorScale` / `sizeField` / `heightField` etc. belong under `visualChannels`, NOT under `config`.** Putting them under `config` is silently ignored — the layer will render but the "Color Based On (field)" input shows empty. The layer object must have two siblings: `config` (for `dataId`, `columns`, `visConfig`, …) and `visualChannels` (for all field-to-channel mappings). | ||
| - Columns named `latitude`/`lat`/`lng`/`longitude` are auto-detected as coordinates. | ||
| - H3 hex IDs are auto-detected if a column contains valid H3 strings. | ||
| - Use `center_map=True` to auto-fit map bounds. Use `read_only=True` to hide the side panel. | ||
| - For numeric color encoding, if the user does not specify a color scale, use `visualChannels.colorScale: 'quantile'`. | ||
| - For numeric color encoding, if the user does not specify a palette, use a vibrant sequential/diverging palette (for example, `colorRange.name: 'Global Warming'`). | ||
| - If the user asks for custom class breaks, compute breakpoints in Python first (for example with `pygeoda`), add a derived classified/bin column to the dataset, and map colors using that derived field. | ||
| - **No `SampleMapPanel` in standalone exports.** The `SampleMapPanel` React component lives in the kepler.gl demo app, not in the UMD bundle used by `save_to_html()`. To show a summary/legend overlay, inject an HTML+CSS `<div>` into the exported file (position it at `right: 56px` or `left: 66px` so it doesn't block map controls). See [Summary Panel Overlay](skill-references/summary-panel.md). | ||
|
|
||
| ## Supported Data Formats | ||
|
|
||
| | Format | How to Load | | ||
| |--------|-------------| | ||
| | pandas DataFrame | Columns with `lat`/`lng` (or similar) for point data | | ||
| | geopandas GeoDataFrame | Geometry column auto-detected. Interactive widget serialization uses GeoArrow (no CRS reprojection); HTML export path re-projects to EPSG:4326 when needed. | | ||
| | CSV string | Raw CSV text with lat/lng or geometry columns | | ||
| | GeoJSON dict | `Feature` or `FeatureCollection` as Python dict | | ||
| | GeoJSON string | JSON string of GeoJSON | | ||
| | WKT in DataFrame | DataFrame column containing WKT geometry strings | | ||
|
|
||
| ## Layer Types | ||
|
|
||
| | Layer Type | Config `type` | Typical Data | | ||
| |------------|---------------|--------------| | ||
| | Point | `"point"` | DataFrame with lat/lng columns | | ||
| | Arc | `"arc"` | DataFrame with origin/destination lat/lng | | ||
| | Line | `"line"` | DataFrame with origin/destination lat/lng | | ||
| | Hexbin | `"hexagon"` | DataFrame with lat/lng (aggregated spatially) | | ||
| | Heatmap | `"heatmap"` | DataFrame with lat/lng | | ||
| | H3 Hexagon | `"hexagonId"` | DataFrame with H3 hex ID column | | ||
| | GeoJSON / Polygon | `"geojson"` | GeoJSON or GeoDataFrame with polygon/line geometries | | ||
| | Cluster | `"cluster"` | DataFrame with lat/lng | | ||
| | Icon | `"icon"` | DataFrame with lat/lng | | ||
| | Trip | `"trip"` | GeoJSON with LineString + timestamps | | ||
| | S2 | `"s2"` | DataFrame with S2 token column | | ||
|
|
||
| ## Config Structure | ||
|
|
||
| ```python | ||
| config = { | ||
| 'version': 'v1', | ||
| 'config': { | ||
| 'visState': { | ||
| 'layers': [...], # Layer definitions | ||
| 'filters': [...], # Data filters | ||
| 'interactionConfig': {}, # Tooltips, brush, geocoder | ||
| 'splitMaps': [], # Split map views | ||
| 'layerBlending': 'normal' # 'normal', 'additive', 'subtractive' | ||
| }, | ||
| 'mapState': { | ||
| 'latitude': 37.76, | ||
| 'longitude': -122.4, | ||
| 'zoom': 11, | ||
| 'bearing': 0, | ||
| 'pitch': 0, | ||
| 'dragRotate': False, | ||
| 'isSplit': False | ||
| }, | ||
| 'mapStyle': { | ||
| 'styleType': 'dark-matter' | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Basemap Styles | ||
|
|
||
| Free (no token needed): `dark-matter`, `positron`, `voyager`, `dark-matter-nolabels`, `positron-nolabels`, `voyager-nolabels` | ||
|
lixun910 marked this conversation as resolved.
|
||
|
|
||
| Mapbox (require `mapbox_token`): `dark`, `light`, `muted`, `muted_night` | ||
|
|
||
| ## Additional Resources | ||
|
|
||
| For detailed per-layer-type examples with full config, see supporting files: | ||
|
|
||
| - [Point Map](skill-references/point-map.md) — Scatter plot from lat/lng | ||
| - [GeoJSON / Polygon Map](skill-references/geojson-polygon-map.md) — Polygons, lines from GeoJSON or GeoDataFrame | ||
| - [H3 Hexagon Map](skill-references/h3-hexagon-map.md) — H3 spatial index hexagons | ||
| - [Arc / Line Map](skill-references/arc-line-map.md) — Origin-destination connections | ||
| - [Heatmap](skill-references/heatmap.md) — Density heatmap from points | ||
| - [Hexbin Aggregation Map](skill-references/hexbin-aggregation-map.md) — Spatial binning into hexagons | ||
| - [Trip Animation Map](skill-references/trip-animation-map.md) — Animated trips along paths | ||
| - [Summary Panel Overlay](skill-references/summary-panel.md) — Inject a SampleMapPanel-style info overlay into the exported HTML (for LISA/cluster counts, model summaries, custom legends) | ||
|
|
||
| ## Examples | ||
|
|
||
| For full config examples per layer type, see: | ||
| - [Point Map](skill-references/point-map.md) — includes quantile color + vibrant palette config | ||
| - [GeoJSON / Polygon Map](skill-references/geojson-polygon-map.md) — includes choropleth config with `visualChannels` | ||
|
|
||
| ### Quick start (auto-detected layers, no config needed) | ||
|
|
||
| ```python | ||
| from keplergl import KeplerGl | ||
| import pandas as pd | ||
|
|
||
| df = pd.DataFrame({ | ||
| 'lat': [37.7749, 34.0522, 40.7128], | ||
| 'lng': [-122.4194, -118.2437, -74.0060], | ||
| 'name': ['San Francisco', 'Los Angeles', 'New York'], | ||
| 'value': [15, 42, 27] | ||
| }) | ||
|
|
||
| map_1 = KeplerGl(data={'cities': df}) | ||
| map_1.save_to_html(file_name='cities_map.html', center_map=True) | ||
| ``` | ||
|
|
||
| ### GeoDataFrame from shapefile | ||
|
|
||
| ```python | ||
| from keplergl import KeplerGl | ||
| import geopandas as gpd | ||
|
|
||
| gdf = gpd.read_file('shapefile.shp') | ||
| map_1 = KeplerGl(data={'regions': gdf}) | ||
| map_1.save_to_html(file_name='regions_map.html', read_only=True, center_map=True) | ||
| ``` | ||
|
|
||
| ### Multiple datasets | ||
|
|
||
| ```python | ||
| map_1 = KeplerGl(data={ | ||
| 'locations': points_df, | ||
| 'routes': routes_df | ||
| }) | ||
| map_1.save_to_html(file_name='combined_map.html', center_map=True) | ||
| ``` | ||
|
|
||
| ### Save and reuse config | ||
|
|
||
| ```python | ||
| import json | ||
| # Save | ||
| with open('my_config.json', 'w') as f: | ||
| json.dump(map_1.config, f) | ||
| # Load | ||
| with open('my_config.json', 'r') as f: | ||
| config = json.load(f) | ||
| map_2 = KeplerGl(data={'data_1': df}, config=config) | ||
| map_2.save_to_html(file_name='map.html') | ||
| ``` | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| interface: | ||
| display_name: "kepler.gl Map" | ||
| short_description: "Create interactive map visualizations with kepler.gl" | ||
| icon_small: "./assets/icon-small.svg" | ||
| icon_large: "./assets/icon-large.svg" | ||
| brand_color: "#1FBAD6" | ||
| default_prompt: "Create an interactive map visualization" | ||
|
|
||
| policy: | ||
| allow_implicit_invocation: true | ||
|
|
||
| dependencies: | ||
| tools: [] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.