Talk to your database in plain language. No SQL required.
speakql is an AI-powered CLI agent that translates natural language into SQL queries and returns human-readable answers. It connects to any PostgreSQL database and uses Claude (Anthropic) to understand your questions and format results.
> quantos pacientes ativos temos?
Voces tem 280 pacientes ativos no sistema.
A maioria (182) esta vinculada a tratamentos em andamento.
> quais profissionais tem mais consultas este mes?
┌──────────────────────┬────────────┐
│ Profissional │ Consultas │
├──────────────────────┼────────────┤
│ Dra. Maria Silva │ 47 │
│ Dr. Joao Santos │ 38 │
│ Dra. Ana Oliveira │ 31 │
└──────────────────────┴────────────┘
> /sql
SELECT u.name, COUNT(a.id) as consultas
FROM appointments a
JOIN users u ON u.id = a.professional_id
WHERE a.start_time >= '2026-04-01'
GROUP BY u.name
ORDER BY consultas DESC
┌──────────────┐ tRPC/SSE ┌──────────────────────────┐ SQL ┌──────────┐
│ CLI REPL │ ──────────────▶ │ Server │ ──────────▶ │ Postgres │
│ (speakql) │ ◀────────────── │ Claude AI + Validator │ ◀────────── │ (read-only)
└──────────────┘ streaming └──────────────────────────┘ results └──────────┘
- You type a question in natural language
- Server sends it to Claude, which generates a SQL query
- Server validates the SQL (SELECT only, no sensitive columns)
- Server executes the query on your database
- Claude formats the results as a human-readable answer
- Response streams back to the CLI in real-time
- Monorepo with Turborepo + npm workspaces
- Server: Hono + tRPC subscriptions (SSE streaming)
- CLI: Interactive REPL with Claude Code-inspired UI
- AI: Claude (Anthropic) with prompt caching for cost efficiency
- Database: PostgreSQL via postgres.js (read-only connection)
- Type safety: tRPC end-to-end between CLI and server
Three layers of protection ensure your database is safe:
| Layer | What it does |
|---|---|
| Prompt | Claude is instructed to generate only SELECT queries |
| Validator | Server-side code rejects INSERT, UPDATE, DELETE, DROP and sensitive columns |
| Database | Dedicated read-only PostgreSQL role — even malicious SQL gets "permission denied" |
- Node.js 20+
- A PostgreSQL database (Supabase, local, or any Postgres)
- An Anthropic API key
git clone https://github.com/joaodadas/speakql.git
cd speakql
npm installRun this SQL in your database (e.g., Supabase SQL Editor):
CREATE ROLE speakql_reader WITH LOGIN PASSWORD 'your_secure_password';
GRANT CONNECT ON DATABASE postgres TO speakql_reader;
GRANT USAGE ON SCHEMA public TO speakql_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO speakql_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO speakql_reader;cp .env.example .envEdit .env:
ANTHROPIC_API_KEY=sk-ant-...
DATABASE_URL=postgresql://speakql_reader:password@your-host:6543/postgres
PORT=3001
CLYNEA_SERVER_URL=http://localhost:3001This creates a snapshot of your database schema for the AI to understand:
npm run generate-ddlnpm run devThis starts both the server and CLI. Start asking questions!
| Command | Description |
|---|---|
/sql |
Show the last generated SQL query |
/schema |
List all available tables |
/limpar |
Clear conversation history |
/sair |
Exit |
speakql/
├── packages/
│ ├── server/ # Hono + tRPC + Claude + PostgreSQL
│ │ └── src/
│ │ ├── agent/ # AI modules (prompt, generate-sql, validate, format)
│ │ ├── db/ # Database client
│ │ └── router.ts # tRPC router (ask subscription + schema query)
│ └── cli/ # Interactive REPL
│ └── src/
│ ├── ui/ # Banner, spinner
│ └── commands/ # /sql, /schema, /limpar
├── scripts/
│ └── generate-ddl.ts # Schema DDL generator
└── turbo.json # Turborepo config
| Component | Technology |
|---|---|
| Runtime | Node.js 20+ / TypeScript |
| Monorepo | Turborepo + npm workspaces |
| Server | Hono |
| API | tRPC 11 (subscriptions via SSE) |
| AI | Claude (Anthropic SDK) with prompt caching |
| Database | PostgreSQL via postgres.js |
| Validation | Zod |
| Testing | Vitest |
MIT