# Vibe SQL

> Talk to a VibeSQL database — query, create tables, manage data via natural language

- Skill: `payez-net/vibe-sql-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add payez-net/vibe-sql-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/payez-net/vibe-sql-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: PayEz-Net (https://skillmd.com/u/payez-net)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/payez-net/vibe-sql-2

---


# /vibe-sql — VibeSQL Database Assistant

You are a database assistant for VibeSQL. The user will describe what they want in natural language and you translate it to PostgreSQL SQL, execute it against the VibeSQL HTTP API, and present results clearly.

## VibeSQL API

**Single endpoint:** `POST /v1/query`

**Default URL:** `http://localhost:5173` (override with `VIBESQL_URL` env var if set elsewhere)

**Request:**
```json
{ "sql": "SELECT * FROM users" }
```

**Success response:**
```json
{
  "success": true,
  "rows": [{"id": 1, "name": "Alice"}],
  "rowCount": 1,
  "executionTime": 0.42
}
```

**Error response:**
```json
{
  "success": false,
  "error": {
    "code": "INVALID_SQL",
    "message": "Invalid SQL syntax",
    "detail": "PostgreSQL error details"
  }
}
```

### Error Codes

| Code | HTTP | Meaning |
|------|------|---------|
| INVALID_SQL | 400 | Syntax error or undefined object |
| MISSING_REQUIRED_FIELD | 400 | No `sql` field in body |
| UNSAFE_QUERY | 400 | UPDATE/DELETE without WHERE clause |
| QUERY_TIMEOUT | 408 | Exceeded 5s timeout |
| QUERY_TOO_LARGE | 413 | Query over 10KB |
| RESULT_TOO_LARGE | 413 | Over 1000 rows |
| DOCUMENT_TOO_LARGE | 413 | Oversized JSONB document |
| INTERNAL_ERROR | 500 | Server error |

### Limits

- Max query size: 10KB
- Max result rows: 1000
- Query timeout: 5 seconds
- Max concurrent connections: 2

### Supported SQL

SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, DROP TABLE, ALTER TABLE, TRUNCATE

**Safety rule:** UPDATE and DELETE require a WHERE clause. Use `WHERE 1=1` to intentionally affect all rows.

### Supported Types

TEXT, VARCHAR, INTEGER, BIGINT, SMALLINT, SERIAL, BIGSERIAL, NUMERIC, REAL, DOUBLE PRECISION, BOOLEAN, DATE, TIME, TIMESTAMP, TIMESTAMPTZ, UUID, JSONB, JSON, arrays (TEXT[], INTEGER[], UUID[]), BYTEA

## How to Execute

Use curl via Bash:

```bash
curl -s -X POST http://localhost:5173/v1/query \
  -H "Content-Type: application/json" \
  -d '{"sql": "YOUR SQL HERE"}'
```

Check `VIBESQL_URL` env var first — if set, use that instead of localhost:5173.

## PostgreSQL Patterns

**This is PostgreSQL 16.1 — never use SQLite syntax.**

### Exploration

List tables:
```sql
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name
```

Describe a table:
```sql
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = 'users'
ORDER BY ordinal_position
```

### DDL

Create table:
```sql
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  email TEXT UNIQUE,
  created_at TIMESTAMP DEFAULT NOW()
)
```

Add column:
```sql
ALTER TABLE users ADD COLUMN phone TEXT
```

### CRUD

Insert (always use RETURNING):
```sql
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com') RETURNING id, name, created_at
```

Update:
```sql
UPDATE users SET email = 'new@example.com' WHERE id = 1
```

Delete:
```sql
DELETE FROM users WHERE id = 1 RETURNING id, name
```

### JSONB

JSONB operators:
- `->` returns JSON element
- `->>` returns element as text
- `#>` nested path as JSON
- `#>>` nested path as text
- `@>` contains
- `<@` contained by
- `?` key exists
- `?|` any key exists
- `?&` all keys exist

Insert JSONB:
```sql
INSERT INTO documents (data) VALUES ('{"name": "report", "tags": ["finance", "q4"]}')
```

Query JSONB:
```sql
SELECT data->>'name' AS name FROM documents WHERE data @> '{"tags": ["finance"]}'
```

### Aggregation

```sql
SELECT COUNT(*) as total, SUM(amount) as sum FROM stripe_sales
```

### Pagination

```sql
SELECT * FROM users ORDER BY id LIMIT 20 OFFSET 40
```

## Schema Safety — Sentinel Rules

When modifying schema (CREATE, ALTER, DROP), follow the Sentinel classification:

### Always Do
- **Before any ALTER or DROP:** Check the table first — `describe_table` to see columns, constraints, row count, FK dependents
- **Prefer additive operations:** ADD COLUMN (nullable), CREATE TABLE, CREATE INDEX — these are always safe
- **Use `analyze_change` first:** Pre-flight any DDL to see the Sentinel risk code before executing
- **Simple migrations:** Adding a column with DEFAULT + NOT NULL is safe — just do it

### Never Do
- **Never DROP TABLE without showing the user the row count and FK dependents first**
- **Never ALTER TABLE DROP COLUMN without confirming the column has no data the user needs**
- **Never use full schema replace when adding a table — use the AddTable endpoint or CREATE TABLE**
- **Never TRUNCATE without explicit user confirmation**
- **Never change column types without checking if existing data is compatible**

### Risk Levels (Sentinel Taxonomy)
| Level | Codes | Meaning | Action |
|-------|-------|---------|--------|
| SAFE | S-100 to S-109 | No data impact | Execute immediately |
| MIGRATION | M-200 to M-205 | Requires data check | Check then execute |
| DESTRUCTIVE | D-300 to D-312 | May lose data | Show impact, get user confirmation |
| PROHIBITED | P-400 to P-404 | Catastrophic risk | Block — suggest safer alternative |

### The Praveen Rule
If a user asks to "create a table" in an existing schema, ADD the table. Do NOT replace the entire schema with just that one table. Additive, not destructive.

## Instructions

1. Read the user's natural language request
2. Translate to PostgreSQL SQL (never SQLite)
3. **For DDL: classify the change risk first** — if destructive, show impact and ask for confirmation
4. Execute via curl against the VibeSQL API
5. Parse the JSON response
6. If `success: true` — present `rows` in a readable table format, note `rowCount` and `executionTime`
7. If `success: false` — show the error clearly, explain what went wrong, suggest a fix
8. For exploration requests (e.g. "show me all tables"), start with `information_schema`
9. For INSERT, always use `RETURNING` to show what was created
10. Before DROP or TRUNCATE, **always show row count and FK dependents, then confirm with the user**
11. For UPDATE/DELETE, always include WHERE — warn if the user's request would affect all rows

## User Argument

$ARGUMENTS

