Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/terralabai-qgis
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: agent-building
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Python package
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/qgis
What's inside
- Skill name
qgis- Description
- Works in QGIS step by step and checks each result. Inspects the project and layers first (CRS, geometry type, fields, extent, feature count), finds and runs Processing algorithms with processing.run, processing.algorithmHelp and qgis_process (headless, from a terminal, Codex or Claude Code), writes PyQGIS for QGIS 3 and QGIS 4 (Qt6), edits layers, saves projects, runs Processing chains, installs and writes plugins, and fixes common errors. Use when the user mentions QGIS, PyQGIS, qgis_process, Processing, a .qgz or .qgs project, the Python console, a QGIS plugin, a model or batch run, migrating to QGIS 4 or Qt6, or errors such as "iface is not defined", "Couldn't load PyQGIS", "type object 'Qt' has no attribute", "no attribute exec_", an invalid layer. Which analysis to run (buffers, joins, terrain, suitability) is in spatial-analysis.
- License
- MIT
- Metadata
- author: TerraLab · version: 1.1.0 · homepage: https://terra-lab.ai
- Instructions
- 133 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Files (6)
- SKILL.md
- evals.json · evals/
- geoprocessing.md · references/
- pyqgis.md · references/
- troubleshooting.md · references/
- layer_report.py · scripts/
SKILL.md (first lines)
# QGIS
Agents fail in QGIS mostly by skipping a step or running steps in the wrong order, not by calling the wrong function. Follow the workflow for the task, and check each step before the next. A run without errors is not a correct run.
## Core rules
1. Inspect before acting: every input's CRS, geometry type, fields, feature count and extent. Write the numbers down.
2. Never guess an algorithm id or parameter name. Read it (`processing.algorithmHelp`, `qgis_process help`).
3. Measure only in a projected CRS in meters, never EPSG:4326 (degrees) or EPSG:3857.
4. Check after each step: count, extent, validity, and one number cross-checked another way.
5. Ask when the task is ambiguous (which layer, which boundary, which units, which year). Say so when the data cannot answer.
6. Return the code or command that was run, so the user can rerun it.
## Workflow index
| Task | Workflow |
| --- | --- |
| Look at a project or layer | A. Inspect |
| Run one or a chain of tools | B. Processing (console or headless) |
| Buffer, clip, overlay, join, areas | C. Vector chain ([references/geoprocessing.md](references/geoprocessing.md)) |
| Write PyQGIS, a plugin, migrate to QGIS 4 | [references/pyqgis.md](references/pyqgis.md) |
| Edit features or attributes | D. Edit |
| Save, share or package | E. Save |
| Something fails | [references/troubleshooting.md](references/troubleshooting.md) |
## A. Inspect
In the QGIS Python console:
```python
from qgis.core import QgsProject, QgsVectorLayer, QgsRasterLayer, QgsWkbTypes
p = QgsProject.instance()
print("project CRS:", p.crs().authid(), "file:", p.fileName())
for lyr in p.mapLayers().values():
print(lyr.name(), lyr.crs().authid() or "NO CRS", "valid" if lyr.isValid() else "INVALID",
lyr.extent().toString(2))
if isinstance(lyr, QgsVectorLayer):
print(" ", QgsWkbTypes.displayString(lyr.wkbType()), lyr.featureCount(), "features",
[f.name() for f in lyr.fields()])
elif isinstance(lyr, QgsRasterLayer):
dp = lyr.dataProvider()
print(" ", lyr.width(), "x", lyr.height(), "px, size", lyr.rasterUnitsPerPixelX(),
"bands", lyr.bandCount(), "nodata", dp.sourceNoDataValue(1) if dp.sourceHasNoDataValue(1) else None)
```
Headless, without QGIS open: `python3 scripts/layer_report.py data.gpkg --layer name` (feature count, CRS, extent, invalid and null geometries, total area or length in meters; exit code 1 on invalid or null geometries), or `ogrinfo -so -al data.gpkg` and `gdalinfo raster.tif`.
Check: the CRS is known (not empty), the extent is where the data should be (not near 0,0, not lat/lon swapped), units are meters before any distance or area work.
## B. Processing
Find an algorithm and its parameters:
```python
import processing
from qgis.core import QgsApplication
for alg in QgsApplication.processingRegistry().algorithms():
if "buffer" in alg.id():
print(alg.id(), "-", alg.displayName())
processing.algorithmHelp("native:buffer")
```
```bash
qgis_process list | grep -i buffer
qgis_process help native:buffer
```
Run in the console:
```python
res = processing.run("native:buffer", {"INPUT": layer, "DISTANCE": 50, "SEGMENTS": 8,
"DISSOLVE": False, "OUTPUT": "TEMPORARY_OUTPUT"})
out = res["OUTPUT"] # a layer object for TEMPORARY_OUTPUT, else the path
print(out.featureCount(), out.extent().toString(2))
```
`processing.runAndLoadResults(...)` also adds the output to the map (GUI only). Enum parameters take the integer index listed by `algorithmHelp`.
Run headless (terminal, CI, Codex, Claude Code):
```bash
qgis_process run native:reprojectlayer -- INPUT=pts.geojson TARGET_CRS=EPSG:2154 OUTPUT=pts_2154.gpkg
qgis_process run native:buffer --json -- INPUT=pts_2154.gpkg DISTANCE=100 SEGMENTS=8 DISSOLVE=false OUTPUT=buf.gpkg
```
`--json` prints machine-readable results. Parameters go after `--` as `NAME=value`. On macOS the binary is `/Applications/QGIS.app/Contents/MacOS/qgis_process`; on Windows `qgis_process-qgis.bat` in the OSGeo4W `bin` folder. Without a display, set `QT_QPA_PLATFORM=offscreen`. To keep a run away from the user's own profile and plugins, set `QGIS_CUSTOM_CONFIG_PATH` to an empty folder.
Batch: loop in Python over files and call `processing.run` per file, or save a Graphical Modeler model (`.model3`) and run it with `qgis_process run path/to/model.model3 -- ...`.
## C. Vector chain
Order: inspect, reproject to one projected CRS, fix geometries, clip or filter early, buffer, dissolve, overlay, spatial join, compute areas and lengths last. Skip steps you do not need, never reorder them. Algorithm ids, checks per step and raster alignment: [references/geoprocessing.md](references/geoprocessing.md).
## D. Edit
```python
from qgis.core import edit, QgsFeature, QgsGeometry
with edit(layer): # commits, or rolls back on error
f = QgsFeature(layer.fields())
f.setGeometry(QgsGeometry.fromWkt("POINT(652301 6861302)"))
f["name"] = "new"
layer.addFeature(f)
layer.updateExtents(); layer.triggerRepaint()
```
Bulk attribute updates: `native:fieldcalculator` (new output layer) or, in place, `layer.changeAttributeValues(...)` inside `edit(layer)`. Check: feature count before and after, `layer.commitErrors()` if a commit returns False. Never edit the user's source file without saying so; write to a new file when unsure.
## E. Save and share
- Save: `QgsProject.instance().write("/path/project.qgz")` returns True on success. Memory layers ("TEMPORARY_OUTPUT", scratch layers) are lost on close: save them first with `native:savefeatures` or `QgsVectorFileWriter`.
- Share data and styles together: `native:package` writes layers (and optionally styles) into one GeoPackage.
- Relative paths: Project Properties > General > Save paths: Relative, so the project opens on another machine.
- Output format: GeoPackage. Shapefile cuts field names to 10 characters and is limited to 2 GB per file.
## Plugins
- Install from Plugins > Manage and Install Plugins. Experimental plugins need "Show also experimental plugins" in Settings.
- From Python: plugin folders live in the profile's `python/plugins/`. `qgis.utils.plugins` lists loaded ones.
- Writing or migrating a plugin to QGIS 4: [references/pyqgis.md](references/pyqgis.md).From TerraLabAI/geoai-skills, MIT.
More from TerraLabAI/geoai-skills
- 0.570score
remote-sensing
TerraLab
Picks satellite imagery and processes it correctly as ordered workflows with checks.
SkillAFreshness: AClaude Code +9 - 0.570score
gis-data
TerraLab
Finds, downloads, loads, converts, reprojects, cleans and cites geospatial data, and checks it before use.
SkillAFreshness: AClaude Code +9 - 0.570score
spatial-analysis
TerraLab
Runs vector and raster spatial analysis as ordered workflows with a check after each step, in QGIS Processing, qgis_process, PyQGIS, GeoPandas, Shapely or GDAL.
SkillAFreshness: AClaude Code +9 - 0.570score
object-detection
TerraLab
Detects, segments and counts objects such as buildings, trees, cars, solar panels, swimming pools and ships in aerial, drone or satellite imagery, then cleans…
SkillAFreshness: AClaude Code +9 - 0.570score
spatial-sql
TerraLab
Writes and checks spatial SQL in PostGIS and DuckDB spatial.
SkillAFreshness: AClaude Code +9 - 0.570score
cartography
TerraLab
Makes a map end to end, from purpose and audience to a checked export.
SkillAFreshness: AClaude Code +9 - 0.565score
geoprocessing-checklist
TerraLab
Legacy entry point kept so existing links keep working.
SkillAFreshness: AClaude Code +9 - 0.565score
open-map-data
TerraLab
Legacy entry point kept so existing links keep working.
SkillAFreshness: AClaude Code +9 - 0.565score
sentinel2-indices
TerraLab
Legacy entry point kept so existing links keep working.
SkillAFreshness: AClaude Code +9 - 0.565score
crs-and-measurements
TerraLab
Legacy entry point kept so existing links keep working.
SkillAFreshness: AClaude Code +9 - 0.559score
pyqgis-qgis4
TerraLab
Legacy entry point kept so existing links keep working.
SkillAFreshness: AClaude Code +9 - 0.559score
imagery-for-object-detection
TerraLab
Legacy entry point kept so existing links keep working.
SkillAFreshness: AClaude Code +9
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 11, 2026 (17 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- Version
- 1.1.0
- License
- MIT
- Repository
- github.com/TerraLabAI/geoai-skills
- Website
- terra-lab.ai
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from TerraLab
- 0.570score
remote-sensing
TerraLab
Picks satellite imagery and processes it correctly as ordered workflows with checks.
SkillAFreshness: AClaude Code +9 - 0.570score
spatial-analysis
TerraLab
Runs vector and raster spatial analysis as ordered workflows with a check after each step, in QGIS Processing, qgis_process, PyQGIS, GeoPandas, Shapely or GDAL.
SkillAFreshness: AClaude Code +9 - 0.570score
object-detection
TerraLab
Detects, segments and counts objects such as buildings, trees, cars, solar panels, swimming pools and ships in aerial, drone or satellite imagery, then cleans…
SkillAFreshness: AClaude Code +9 - 0.570score
cartography
TerraLab
Makes a map end to end, from purpose and audience to a checked export.
SkillAFreshness: AClaude Code +9 - 0.570score
gis-data
TerraLab
Finds, downloads, loads, converts, reprojects, cleans and cites geospatial data, and checks it before use.
SkillAFreshness: AClaude Code +9 - 0.570score
spatial-sql
TerraLab
Writes and checks spatial SQL in PostGIS and DuckDB spatial.
SkillAFreshness: AClaude Code +9
Cite this page
qgis skill. Agent Mart. https://agentmart.dev/skills/terralabai-qgis (last updated 2026-10-24)