Good SQL Formatting
Optimize your queries for readability. A fast, opinionated formatter with a Monaco-grade editor and CLI-friendly workflows.
GoogleSQLPostgreSQLMySQLSnowflake+10 dialects
14 dialectsmonaco editorzero installcurl ready
~/query.sql
BigQuery (GoogleSQL)•1 lines•0 charsReady
Format from anywhere
Integrate formatting into your workflow — as simple as piping a file through curl. No install, no config.
BigQuery · sensible defaults
cat query.sql | curl -X POST --data-binary @- https://api.nidoran.work/format-sql
live · matches the options above
cat query.sql | curl -X POST \ --data-binary @- \ "https://api.nidoran.work/format-sql?dialect=bigquery&max_length=120&keyword_handling=upper_case&builtin_function_handling=lower_case&indent_cte_definitions=true&always_break_select=false&always_break_query=true&always_break_pipe=true"
Agent skill — format-sql/SKILL.md
Drop into .agents/skills/ to let agents format SQL automatically.
--- name: format-sql description: Format a SQL script using the silos formatting API. Pipe SQL text via curl to format with dialect, line length, and casing options. argument-hint: 'path to .sql file, e.g. query.sql' --- # Format SQL Use this skill when the user asks to format, beautify, or prettify a SQL query. ## Command ```bash cat query.sql | curl -X POST --data-binary @- "https://api.nidoran.work/format-sql?dialect=bigquery&max_length=120&keyword_handling=upper_case" ``` Pipe the SQL file contents to the API. The response is returned as plain text. ## Important Caveats ### Comments may be dropped The API does not always retain SQL comments. When formatting a query that contains comments (single-line `--` or block `/* */`), compare the original SQL with the formatted output. If comments were dropped, you must re-wire them back into the formatted SQL at the appropriate locations. Preserve the original comment text and place it logically near the code it was annotating. ### Error responses The API returns `text/plain` for both success and error cases. Check the response content: - If it starts with `Error:` or `error code:`, formatting failed — report the error reason to the user rather than treating it as formatted SQL. - A successful response is raw formatted SQL with no prefix. ### Minor syntax fixes If the API returns a syntax error, you may make **minimal, non-semantic fixes** to the SQL and retry formatting. Allowed fixes: - Add or adjust `AS` aliases (e.g. `unnest(...) x` → `unnest(...) AS x`) - Fix missing or trailing commas in SELECT, GROUP BY, etc. - Fix trivial keyword casing inconsistencies - Balance unmatched parentheses or quotes - Fix keyword typos (e.g. `SELEC` → `SELECT`) Do **not** make changes that alter the query's semantics, logic, or results. When in doubt, show the user the error and ask how they'd like to fix it. ## Available Options (query parameters) | Parameter | Type | Default | Description | | --------------------------- | ------------------------------- | -------------- | --------------------------------------------------------------------------------------------------------- | | `dialect` | string | `"bigquery"` | SQL dialect. GooglesQL dialects: `"bigquery"`, `"googlesql"`. Any other value falls through to sqlfusion. | | `max_length` | int | `120` | Maximum line length before the formatter wraps | | `keyword_handling` | `"upper_case"` / `"lower_case"` | `"upper_case"` | Case for SQL keywords (SELECT, FROM, WHERE, etc.) | | `builtin_function_handling` | `"upper_case"` / `"lower_case"` | `"upper_case"` | Case for builtin functions (COUNT, SUM, etc.) | | `indent_cte_definitions` | bool | `true` | Indent CTE definitions | | `always_break_select` | bool | `false` | Always put each select item on its own line | | `always_break_query` | bool | `false` | Always put each query clause on its own line | | `always_break_pipe` | bool | `false` | Always break pipe operators to separate lines | ### Notes - **GooglesQL dialects** (`"bigquery"`, `"googlesql"`): all options above are supported. - **Other dialects** (sqlfusion fallback): only `dialect` and `max_length` apply. The dialect value is passed directly to sqlfusion (e.g. `"postgresql"`, `"mysql"`, `"sqlite"`, `"duckdb"`, `"databricks"`, etc.). ### Bool parameter values Accepted truthy values: `"true"`, `"1"`, `"yes"`, `"on"` (case-insensitive). Anything else is falsy. ### Default request (no options) ```bash cat query.sql | curl -X POST --data-binary @- "https://api.nidoran.work/format-sql" ``` This formats as GooglesQL/BigQuery with `max_length=120` and `keyword_handling=upper_case`. ### Examples Format with lower-case keywords and 80-char line length: ```bash cat query.sql | curl -X POST --data-binary @- "https://api.nidoran.work/format-sql?keyword_handling=lower_case&max_length=80" ``` Format as Postgres: ```bash cat query.sql | curl -X POST --data-binary @- "https://api.nidoran.work/format-sql?dialect=postgresql&max_length=100" ```
Under the hood
Two parsers, full AST formatting, broad dialect coverage.
most complete
GoogleSQL (BigQuery) ↗
Parsed with Google’s own GoogleSQL engine into an abstract syntax tree before formatting rules are applied — including scripts and pipe syntax.
everything else
DataFusion SqlParser ↗
All other dialects use the DataFusion SQL parser. It covers most dialects well; a few unusual dialect-specific features may not parse.
Supported dialects
ANSI SQLBigQuery (GoogleSQL)ClickHouseDatabricksDuckDBGeneric SQLHiveMS SQLMySQLOraclePostgreSQLRedshiftSQLiteSnowflake