syntaqlite

syntaqlite provides a CLI and language server for parsing, formatting, and statically analyzing SQLite SQL. libsyntaqlite contains the parser, formatter, and analyzer used by those tools, with APIs for Rust, Python, JavaScript/WASM, and C.

Both are built from SQLite's own grammar and tokenizer and can target specific SQLite versions and compile-time flags.

Note: syntaqlite and libsyntaqlite are at 0.x. Their APIs and command-line interface may change before 1.0.

What it does

Format

Line width, keyword casing, and indentation are configurable, while the same input always produces the same deterministic output.

Input
select u.id,u.name, p.title from
  users u join posts p on u.id
  =p.user_id where u.active
  =1 and p.published=true
  order by p.created_at
  desc limit 10
Output
SELECT u.id, u.name, p.title
FROM users u
  JOIN posts p ON u.id = p.user_id
WHERE u.active = 1
  AND p.published = true
ORDER BY p.created_at DESC
LIMIT 10;

Validate

The analyzer checks tables, columns, and functions against your schema without opening a database. These are the same errors that sqlite3_prepare catches, but syntaqlite can report multiple errors from one analysis and include a source location for each:

CREATE TABLE orders (id, status, total, created_at);

WITH
  monthly_stats(month, revenue, order_count) AS (
    SELECT strftime('%Y-%m', o.created_at), SUM(o.total)
    FROM orders o WHERE o.status = 'completed'
    GROUP BY strftime('%Y-%m', o.created_at)
  )
SELECT ms.month, ms.revenue, ms.order_count,
  ROUDN(ms.revenue / ms.order_count, 2) AS avg_order
FROM monthly_stats ms;

Two errors: CTE declares 3 columns but the SELECT produces 2, and ROUDN is a typo for ROUND.

sqlite3
Error: in prepare, table monthly_stats
has 2 values for 3 columns

Stops after the first error and therefore does not report the ROUDN typo.

syntaqlite
error: table 'monthly_stats' has 2
      values for 3 columns
  |
2 | monthly_stats(month, revenue,
  | ^~~~~~~~~~~~~

warning: unknown function 'ROUDN'
   |
14 | ROUDN(ms.revenue / ms.order_count,
   | ^~~~~
   = help: did you mean 'round'?

Version and compile-flag aware

SQLite syntax changes between releases, and compile-time flags enable optional features. syntaqlite accounts for both across the parser, formatter, validator, and LSP.

# RETURNING was added in SQLite 3.35.0
# Check for incompatibility with Android 13's SQLite 3.32.2:
syntaqlite --sqlite-version 3.32.0 analyze \
  -e "DELETE FROM users WHERE id = 1 RETURNING *;"
error: syntax error near 'RETURNING'
 --> <stdin>:1:32
  |
1 | DELETE FROM users WHERE id = 1 RETURNING *;
  |                                ^~~~~~~~~

Validate SQL inside other languages experimental

SQL lives inside Python and TypeScript strings in most real codebases. syntaqlite extracts and validates these strings while preserving interpolation holes and suggesting corrections for misspelled names.

app.py
def get_user_stats(user_id: int):
    return conn.execute(
        f"SELECT nme, ROUDN(score, 2) FROM users WHERE id = {user_id}"
    )
syntaqlite analyze --experimental-lang python app.py
warning: unknown function 'ROUDN'
 --> app.py:3:23
  |
3 |         f"SELECT nme, ROUDN(score, 2) FROM users WHERE id = {user_id}"
  |                       ^~~~~
  = help: did you mean 'round'?

Parse

The parser returns an abstract syntax tree with side tables for tokens, comments, and whitespace boundaries.

SelectStmt
  columns:
    ResultColumn
      expr:
        ColumnRef
          column: "id"
    ResultColumn
      expr:
        ColumnRef
          column: "name"
  from_clause:
    TableRef
      table_name: "users"
  where_clause:
    BinaryExpr
      op: EQ
      left:
        ColumnRef
          column: "active"
      right:
        Literal "1"

Editor integration

The language server provides diagnostics, format on save, completions for keywords, functions, tables, and columns, and semantic highlighting without requiring a database connection.

# Install the VS Code extension from the marketplace
ext install syntaqlite.syntaqlite

# Or point any LSP client at this command:
syntaqlite lsp

Design principles

  • Reliability: syntaqlite uses SQLite's own tokenizer and grammar rules, verified by running the full SQLite test suite through the parser.
  • Speed: in the comparison benchmark, syntaqlite parses 3,500 lines of SQL in 2.6ms, formats them in 4.9ms, and validates them in 7.3ms. The tokenizer avoids copying, the parser uses an arena, and the formatter reuses allocations across inputs.
  • Portability: the runtime has no dependencies beyond the C and Rust standard libraries, and runs natively, in WASM, or as a shared library.
  • Extensibility: the grammar system supports database engines that extend SQLite's syntax. Define custom grammar rules, AST nodes, and formatting recipes, then load your dialect as a shared library at runtime.

syntaqlite grew out of 8+ years of maintaining PerfettoSQL and scaling it to 100K+ line SQL codebases. See the comparison for how it stacks up against other tools.

What it does not do

  • It does not support other SQL engines. syntaqlite is SQLite-only by design, which allows it to use the real grammar rather than a lowest-common-denominator subset.
  • It does not do runtime type checking. It catches what sqlite3_prepare catches (syntax errors, unknown names), not data-dependent errors like division by zero or type mismatches.

Get started

Pick your starting point:

Try it without installing Open the playground to format, validate, and parse SQL in your browser. VS Code Install the extension for diagnostics, formatting, and completions. Claude Code Plugin and MCP server for Claude Code, Claude Desktop, Cursor, Windsurf. Command line Install the CLI for formatting, validation, CI, and scripting. Other editors Neovim, Helix, or any editor with LSP support. libsyntaqlite for Rust Embed the parser, formatter, and static analyzer in a Rust project. libsyntaqlite for Python Parse, format, and statically analyze SQLite SQL from Python. libsyntaqlite for C Use the C API or compile the dependency-free parser amalgamation. libsyntaqlite for JavaScript Use the parser, formatter, and static analyzer in JavaScript or WebAssembly.

Further reading

Guides CI integration, validation, embedding via Rust and C APIs. Concepts The rationale behind the parser, formatter, and analyzer designs. Reference CLI flags, config options, and API reference. Contributing Architecture, testing, how the project works.