I’ve been doing more (a lot more) with Claude Code lately. With its subagents and skills features, it’s become more customizable and powerful. I can really dial it into doing things the way I want them done, which accelerates my development and quickly gets me to where I am focused on important behaviors, rather than rote scaffolding.
I recently wanted to trying expanding beyond code generation to analytic tasks, so I set about building a Claude Code Skill to do point-in-polygon analysis between two PostGIS tables. Truth in advertising: I used AI to help me with this experiment.
First, what is a skill? A skill is a modular package that extends Claude’s capabilities by providing specialized knowledge, workflows, scripts, and reference materials for specific domains or tasks. It is essentially an “onboarding guide” that gives Claude additional domain expertise. It generally consists of a few pieces, laid out in a file structure like this:

Starting with SKILL.md, a markdown file that describes the skill and provides details instructions on how to perform its related work. Here is the description section of my file:
name: postgis-spatial-analysis
description: Perform point-in-polygon spatial analysis on PostGIS databases to determine which points fall within which polygons and generate summary reports. Use when working with PostGIS databases for spatial queries that assign points to polygons, analyze geographic relationships between point and polygon tables, or generate summaries of spatial distributions. Handles SRID transformations, spatial index checks, and optimized query generation.
The scripts folder contains executable code for operations that are repeatedly rewritten or require deterministic reliability. In my case, that’s a Python script that handles the PostgreSQL connection, transformations, query execution, and results. The references folder contains detailed documentation that Claude loads as needed. If SKILL.md provides the essential workflow, references provide comprehensive details and specifications.
All of these files are arranged in the file structure depicted above. The skill is deployed by copying that entire file structure to your Claude skills folder. I use MacOS, so that’s ~/.claude/skills/ for me. For this skill, I said I would provide the connection details in the prompt. That sentence probably just made a few dozen cybersecurity professionals faint, but it was easy for this demo. Here was my prompt:
I need to count the number of records in the metro_bus_stops table that are inside Maryland.
The database is at localhost:5432, database name is “dev”,
user “postgres” with password “postgres”.Points table: public.metro_bus_stops (geometry column: geom, id column: id)
Polygons table: public.maryland_boundary (geometry column: geom, name column: name)
(Yes, my dev instance of Postgres that is full of data I don’t care about running in an environment that you can’t get access to uses default user names and passwords. Guilty as charged.)
I simply issued the prompt in Claude Code. It figured out that the skill was there and that it should use it.

It determined that, using the data I told it to, there are 4,563 Metro bus stops in Maryland. Hallucination?

According to the most basic way to answer that same question in QGIS, it is not a hallucination.
This was an encouraging first step. Note that it had to first hit an error to figure out it needed to transform coordinates, so there is some optimization to be done. I’ll try to do some more advance queries in the near future to see if I can find the limits, but skills seem to be a powerful feature that I will look to integrate more into my workflows as I gain proficiency.
The files for this skill can be found here: https://gist.github.com/geobabbler/1c66dff4dceb5af07631a2497aa74d15