Provides direct query access to the GOAT PostgreSQL database for debugging and state inspection.

Install

mkdir -p .claude/skills/db-plan4better && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/17324" && unzip -o skill.zip -d .claude/skills/db-plan4better && rm skill.zip

Installs to .claude/skills/db-plan4better

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Use when inspecting, debugging, or understanding the GOAT PostgreSQL database — querying projects, layers, users, orgs, teams, roles, scenarios, jobs, or checking data state during local dev.
191 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • Connect to the GOAT PostgreSQL database via Docker
  • Execute one-off SQL queries against the database
  • Inspect database schemas and table relationships
  • Query specific tables like `customer.project`, `customer.layer`, `customer.job`, `customer.scenario_feature`
  • Retrieve common data patterns like projects with layer counts or job statuses
  • Understand how layer metadata and data are stored

How it works

The skill connects to the GOAT PostgreSQL database through its running Docker container, allowing execution of read-only SQL queries and inspection of schemas and table relationships to understand data state.

Inputs & outputs

You give it
An SQL query or a request to inspect database structure
You get back
Query results, schema information, or table details from the GOAT PostgreSQL database

When to use db

  • Debug database state
  • Run ad-hoc SQL queries
  • Inspect schema relationships

About this skill

Database Query

Query the GOAT PostgreSQL database to inspect data, debug issues, and understand state.

Connection

There is no host psql; go through the running Postgres container. The container name changes across setups (goat-db, goat-db18, …), so discover it rather than hardcoding:

source /home/p4b/goat/.env
DBC=$(docker ps --format '{{.Names}}' | grep -E '^goat-db' | head -1)
docker exec -e PGPASSWORD=$POSTGRES_PASSWORD "$DBC" psql -h 127.0.0.1 -U $POSTGRES_USER -d $POSTGRES_DB

One-off query:

source /home/p4b/goat/.env
DBC=$(docker ps --format '{{.Names}}' | grep -E '^goat-db' | head -1)
docker exec -e PGPASSWORD=$POSTGRES_PASSWORD "$DBC" psql -h 127.0.0.1 -U $POSTGRES_USER -d $POSTGRES_DB -c "YOUR SQL HERE"

Schemas

SchemaPurpose
customerEverything: users, orgs, teams, roles/permissions, projects, layers, scenarios, jobs, workflows
ducklakeDuckLake catalog (managed by geoapi, don't modify directly)

Key Tables & Relationships

The SQLModel definitions in apps/core are the source of truth — introspect when unsure:

SELECT table_name FROM information_schema.tables WHERE table_schema='customer' ORDER BY 1;
\d customer.layer

Identity & sharing (all in customer)

  • user (id uuid) — Keycloak-synced. firstname, lastname, avatar
  • organization (id uuid) — name, avatar; organization_domain, organization_analytics
  • team (id uuid) — belongs to org. name, avatar
  • role (id uuid) — permission roles; RBAC via permission, role_permission, user_role, resource, resource_grant, resource_permission
  • user_team — M2M user ↔ team; invitation — pending org/team invites
  • layer_organization / layer_team / layer_user — layer sharing with role
  • project_organization / project_team / project_user — project sharing with role

Projects, layers & scenarios (customer)

  • project (id uuid) — user_id, folder_id, active_scenario_id, layer_order[], basemap, tags[]
  • layer (id uuid) — user_id, folder_id, data_store_id. Key fields: name, type, data_type, tool_type, feature_layer_type, feature_layer_geometry_type, extent (geometry), properties (jsonb), url, size, attribute_mapping (jsonb), in_catalog, tags[]
  • layer_project (id int) — M2M layer ↔ project. name, properties (jsonb style config), other_properties, query (jsonb filters), charts, order, layer_project_group_id
  • layer_project_group (id int) — layer groups. project_id, parent_id (self-ref nesting), order
  • data_store (id uuid) — storage backends. type
  • folder (id uuid) — user_id, name
  • job (id uuid) — user_id. type, status, payload (jsonb)
  • scenario (id uuid) — project_id, user_id, name
  • scenario_feature (id uuid) — layer_project_id, feature_id (text), edit_type, geom, h3_3, h3_6. Generic typed columns: integer_attr1..25, float_attr1..25, text_attr1..25, plus bigint/jsonb/boolean/array/timestamp attrs
  • scenario_scenario_feature — M2M scenario ↔ scenario_feature
  • workflow (id uuid) — project_id, name, config (jsonb), is_default
  • report / report_layout (id uuid) — project_id, name, config (jsonb), is_default
  • project_public — public sharing config: password, config (jsonb snapshot)
  • user_project — user ↔ project with initial_view_state (jsonb)
  • system_setting — per-user: client_theme, preferred_language, unit
  • uploaded_asset — user uploads: s3_key, file_name, mime_type, file_size, asset_type, content_hash
  • cost / credit_usage — credit metering

Common Queries

-- Projects with layer counts
SELECT p.id, p.name, p.created_at, COUNT(lp.id) AS layer_count
FROM customer.project p
LEFT JOIN customer.layer_project lp ON lp.project_id = p.id
GROUP BY p.id ORDER BY p.created_at DESC;

-- Layers in a project with styles
SELECT lp.id, lp.name, lp.order, l.type, l.feature_layer_type, l.feature_layer_geometry_type
FROM customer.layer_project lp
JOIN customer.layer l ON l.id = lp.layer_id
WHERE lp.project_id = 'PROJECT_UUID'
ORDER BY lp.order;

-- Job status
SELECT id, type, status, created_at, payload->>'tool_type' AS tool
FROM customer.job ORDER BY created_at DESC LIMIT 10;

-- Scenario features for a scenario
SELECT sf.id, sf.feature_id, sf.edit_type, ST_AsText(sf.geom) AS geom
FROM customer.scenario_feature sf
JOIN customer.scenario_scenario_feature ssf ON ssf.scenario_feature_id = sf.id
WHERE ssf.scenario_id = 'SCENARIO_UUID';

Important Notes

  • Layer metadata lives in PostgreSQL (customer.layer), layer data lives in DuckLake (managed by geoapi)
  • layer_project.properties = style/rendering config (jsonb); layer_project.query = active filters (jsonb)
  • scenario_feature uses generic columns (integer_attr1..25 etc.) — check layer.attribute_mapping for which attr maps to which real column name
  • A public dashboard reads the project_public.config snapshot, not the live project — re-publish to reflect changes
  • Always use READ-ONLY queries. Never INSERT/UPDATE/DELETE unless explicitly asked
  • Use ST_AsText() or ST_AsGeoJSON() to read geometry columns

When not to use it

  • When performing INSERT, UPDATE, or DELETE operations unless explicitly asked
  • When the database is not GOAT PostgreSQL or not running in a Docker container
  • When the user needs to interact with the DuckLake catalog directly

Limitations

  • The skill only supports connecting to the GOAT PostgreSQL database via its Docker container
  • The skill is designed for READ-ONLY queries; INSERT/UPDATE/DELETE are not allowed unless explicitly asked
  • The skill does not directly modify DuckLake catalog data

How it compares

This skill provides a containerized and controlled method for database inspection and debugging, ensuring safe read-only access and consistent connection, unlike direct host `psql` access which might be unavailable or less secure.

Compared to similar skills

db side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
db (this skill)018dReviewIntermediate
data-sql03moNo flagsIntermediate
data-safety-auditor37moNo flagsAdvanced
supabase-incident-runbook110dReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry