pgcheck — Agent Reference
Project
One-shot PostgreSQL executor for LLM agents. Takes SQL, returns structured JSON to stdout, exits. No interactive shell, no ANSI decoration — clean output agents can parse directly.
Implemented as a single JBang-runnable Java file (pgcheck.java). JBang handles compilation and dependency download on first run — no build step required.
Tech stack
- Java 17+ · JBang (bundled wrappers:
jbang,jbang.cmd,jbang.ps1) - picocli · Jackson · PostgreSQL JDBC · tinylog
- Docker Compose for local dev database
Key files
| Path | Purpose |
|---|---|
pgcheck.java | Entire implementation — one file, all classes |
.pgcheck.properties.example | Connection config template → copy to ~/.pgcheck.properties |
support/docker-compose.yml | Local PostgreSQL 16 instance |
support/initdb/ | Schema + seed SQL applied on container start |
.claude/skills/pgcheck.md | pgcheck skill (Claude Code auto-discovers) |
jbang-catalog.json | Local alias: ./jbang pgcheck |
Local database
bash support/scripts/up.sh # start (waits for healthcheck)
bash support/scripts/down.sh # stop and remove volumes
Connection defaults (match Docker Compose): localhost:5432, db pgcheck_demo, user/password pgcheck.
Schema: store
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_id INTEGER NOT NULL REFERENCES customers(id),
status VARCHAR(20) NOT NULL DEFAULT 'pending'
CHECK (status IN ('pending', 'shipped', 'delivered', 'cancelled')),
total_cents INTEGER NOT NULL CHECK (total_cents >= 0),
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
Running pgcheck
# Unix
./jbang pgcheck.java --sql "SELECT count(*) FROM store.customers"
# Windows
jbang.cmd pgcheck.java --sql "SELECT count(*) FROM store.customers"
Output is always JSON on stdout. Exit code signals result category: 0 ok · 1 sql_error · 2 policy_violation · 3 input_error · 4 connection_error.
Architecture
Everything lives in pgcheck.java. JBang single-file mode requires all types in one file — this is intentional, not a shortcut. The file contains: pgcheck (main command), ExitCode, DatabaseConfig, QueryOptions, SqlInputGroup, StatementType, PolicyGuard, QueryExecutor, ResponseWriter, and supporting types.
Code principles
- Stay in one file. JBang single-file mode is a hard constraint — never split into multiple files.
- One responsibility per type. Each class/record has a single clear purpose.
- Names reveal intent. Honest, intention-revealing names. No type suffixes, no abbreviations, no clever tricks.
- No silent failures. All error paths produce a valid JSON error envelope. Exceptions are handled close to origin or propagated intentionally — never swallowed.
- Comments explain why, never what. Comment only non-obvious constraints or workarounds. Well-named code is self-documenting.
- Don't abstract early. Wait for the third occurrence before extracting a helper.
- Prefer real collaborators. Mock only at system boundaries (JDBC, filesystem).
Skills
Agent-executable skills live in .claude/skills/. Each file has YAML frontmatter (name, description) followed by instructions.
| Skill | Description |
|---|---|
| pgcheck | Run a SQL query against PostgreSQL and return structured JSON |