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, 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 (customer)

  • project (id uuid) — user_id, folder_id, layer_order[], basemap, tags[]
  • layer (id uuid) — user_id, folder_id. Key fields: name, type, data_type, tool_type, job_id, feature_layer_type, feature_layer_geometry_type, extent (geometry), properties (jsonb), other_properties (jsonb — holds catalog_item / catalog_materialize for promoted catalog layers), field_config (jsonb, per-column metadata), url, size, in_catalog, tags[], catalog_external_uid, catalog_version
  • 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
  • folder (id uuid) — user_id, name
  • job (id uuid) — user_id. type, status, payload (jsonb)
  • 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;

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)
  • Scenarios are gone (2026-08-27): the feature, the three tables and project.active_scenario_id were all removed. scenario_feature was the last table using generic columns (integer_attr1..25); nothing in GOAT uses that scheme any more
  • A catalog layer has no owner: layer.user_id and layer.folder_id are NULL for promoted catalog layers. Joins from layer to user must be LEFT joins or those rows vanish
  • 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)02moReviewIntermediate
data-sql04moNo flagsIntermediate
data-safety-auditor38moNo flagsAdvanced
supabase-incident-runbook11moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry