{"id":44085255,"url":"https://github.com/vinsidious/holywell","last_synced_at":"2026-02-13T05:01:27.150Z","repository":{"id":336906800,"uuid":"1151402875","full_name":"vinsidious/holywell","owner":"vinsidious","description":"Opinionated SQL formatter that implements Simon Holywell's sqlstyle.guide. Zero dependencies.","archived":false,"fork":false,"pushed_at":"2026-02-11T08:44:27.000Z","size":1619,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-12T11:52:07.528Z","etag":null,"topics":["cli","code-formatter","developer-tools","formatter","postgresql","sql","sql-formatter","sql-style-guide","typescript"],"latest_commit_sha":null,"homepage":"https://holywell.sh","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vinsidious.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-06T12:26:05.000Z","updated_at":"2026-02-11T08:44:32.000Z","dependencies_parsed_at":"2026-02-08T15:05:29.382Z","dependency_job_id":null,"html_url":"https://github.com/vinsidious/holywell","commit_stats":null,"previous_names":["vinsidious/sqlfmt","vinsidious/holywell"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/vinsidious/holywell","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinsidious%2Fholywell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinsidious%2Fholywell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinsidious%2Fholywell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinsidious%2Fholywell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vinsidious","download_url":"https://codeload.github.com/vinsidious/holywell/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vinsidious%2Fholywell/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29367815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T08:51:36.827Z","status":"ssl_error","status_checked_at":"2026-02-12T08:51:26.849Z","response_time":55,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","code-formatter","developer-tools","formatter","postgresql","sql","sql-formatter","sql-style-guide","typescript"],"created_at":"2026-02-08T10:01:37.054Z","updated_at":"2026-02-13T05:01:27.144Z","avatar_url":"https://github.com/vinsidious.png","language":"TypeScript","readme":"# holywell\n\n[![npm version](https://img.shields.io/npm/v/holywell)](https://www.npmjs.com/package/holywell)\n[![npm downloads](https://img.shields.io/npm/dm/holywell)](https://www.npmjs.com/package/holywell)\n[![license](https://img.shields.io/npm/l/holywell)](https://github.com/vinsidious/holywell/blob/main/LICENSE)\n[![CI](https://img.shields.io/github/actions/workflow/status/vinsidious/holywell/ci.yml?branch=main\u0026label=CI)](https://github.com/vinsidious/holywell/actions)\n[![coverage](https://img.shields.io/badge/coverage-regression%20suite-brightgreen)](https://github.com/vinsidious/holywell/tree/main/tests)\n\nAn opinionated SQL formatter that implements [Simon Holywell's SQL Style Guide](https://www.sqlstyle.guide/). It faithfully applies the guide's formatting rules -- including river alignment, keyword uppercasing, and consistent indentation -- to produce deterministic, readable SQL with minimal configuration.\n\n**[Try it live in your browser at holywell.sh](https://holywell.sh)**\n\n## Why?\n\nThe [SQL Style Guide](https://www.sqlstyle.guide/) is an excellent resource for writing readable, maintainable SQL, but no formatter existed to enforce it automatically. holywell was created to fill that gap -- a zero-dependency TypeScript formatter that faithfully implements the guide's river alignment and formatting conventions with minimal configuration.\n\n```sql\nSELECT e.name,\n       e.salary,\n       d.department_name,\n       RANK() OVER (PARTITION BY d.department_name\n                        ORDER BY e.salary DESC) AS dept_rank\n  FROM employees AS e\n       INNER JOIN departments AS d\n       ON e.department_id = d.id\n WHERE e.start_date \u003e= '2024-01-01'\n   AND d.active = TRUE\n ORDER BY d.department_name, dept_rank;\n```\n\n\u003e **Disclaimer:** This project is not officially associated with or endorsed by Simon Holywell or sqlstyle.guide. It is an independent, faithful implementation of the SQL formatting rules described in that style guide.\n\n## Quick Start\n\n### Install\n\n```bash\nnpm install holywell\n```\n\n### CLI Usage\n\n```bash\n# Format a file\nnpx holywell query.sql\n\n# Format all SQL files\nnpx holywell \"**/*.sql\"\n\n# Check formatting (CI mode)\nnpx holywell --check \"**/*.sql\"\n\n# Format in place\nnpx holywell --write \"**/*.sql\"\n```\n\n### Programmatic Usage\n\n```typescript\nimport { formatSQL } from 'holywell';\n\nconst formatted = formatSQL('select id, name from users where active = true;');\n// Output:\n// SELECT id, name\n//   FROM users\n//  WHERE active = TRUE;\n```\n\n## Table of Contents\n\n- [What it does](#what-it-does)\n- [When NOT to use holywell](#when-not-to-use-holywell)\n- [SQL Dialect Support](#sql-dialect-support)\n- [CLI Reference](#cli-reference)\n- [API Guide](#api-guide)\n- [How the formatter works](#how-the-formatter-works)\n- [Edge Cases \u0026 Behavior](#edge-cases--behavior)\n- [FAQ](#faq)\n- [Documentation](#documentation)\n- [Development](#development)\n- [Performance](#performance)\n- [Limitations](#limitations)\n- [License](#license)\n\n## What it does\n\nTakes messy SQL and formats it according to the [Simon Holywell SQL Style Guide](https://www.sqlstyle.guide/). A key technique from the guide is **river alignment** -- right-aligning keywords so content flows along a consistent vertical column:\n\n```sql\n-- Input\nselect e.name, e.salary, d.department_name from employees as e inner join departments as d on e.department_id = d.department_id where e.salary \u003e 50000 and d.department_name in ('Sales', 'Engineering') order by e.salary desc;\n\n-- Output\nSELECT e.name, e.salary, d.department_name\n  FROM employees AS e\n       INNER JOIN departments AS d\n       ON e.department_id = d.department_id\n WHERE e.salary \u003e 50000\n   AND d.department_name IN ('Sales', 'Engineering')\n ORDER BY e.salary DESC;\n```\n\n### More examples\n\n**Multi-table JOINs:**\n\n```sql\n-- Input\nselect o.id, c.name, p.title, o.total from orders o join customers c on o.customer_id = c.id left join products p on o.product_id = p.id left join shipping s on o.id = s.order_id where o.created_at \u003e '2024-01-01' and s.status = 'delivered' order by o.created_at desc;\n\n-- Output\nSELECT o.id, c.name, p.title, o.total\n  FROM orders AS o\n  JOIN customers AS c\n    ON o.customer_id = c.id\n\n       LEFT JOIN products AS p\n       ON o.product_id = p.id\n\n       LEFT JOIN shipping AS s\n       ON o.id = s.order_id\n WHERE o.created_at \u003e '2024-01-01'\n   AND s.status = 'delivered'\n ORDER BY o.created_at DESC;\n```\n\n**CTEs (Common Table Expressions):**\n\n```sql\n-- Input\nwith monthly_totals as (select date_trunc('month', created_at) as month, sum(amount) as total from payments group by 1), running as (select month, total, sum(total) over (order by month) as cumulative from monthly_totals) select * from running where cumulative \u003e 10000;\n\n-- Output\n  WITH monthly_totals AS (\n           SELECT DATE_TRUNC('month', created_at) AS month,\n                  SUM(amount) AS total\n             FROM payments\n            GROUP BY 1\n       ),\n       running AS (\n           SELECT month, total, SUM(total) OVER (ORDER BY month) AS cumulative\n             FROM monthly_totals\n       )\nSELECT *\n  FROM running\n WHERE cumulative \u003e 10000;\n```\n\n**Window functions:**\n\n```sql\n-- Input\nselect department, employee, salary, rank() over (partition by department order by salary desc) as dept_rank, salary - avg(salary) over (partition by department) as diff_from_avg from employees;\n\n-- Output\nSELECT department,\n       employee,\n       salary,\n       RANK() OVER (PARTITION BY department\n                        ORDER BY salary DESC) AS dept_rank,\n       salary - AVG(salary) OVER (PARTITION BY department) AS diff_from_avg\n  FROM employees;\n```\n\n**CASE expressions:**\n\n```sql\n-- Input\nselect name, case status when 'A' then 'Active' when 'I' then 'Inactive' when 'P' then 'Pending' else 'Unknown' end as status_label, case when balance \u003e 10000 then 'high' when balance \u003e 1000 then 'medium' else 'low' end as tier from accounts;\n\n-- Output\nSELECT name,\n       CASE status\n       WHEN 'A' THEN 'Active'\n       WHEN 'I' THEN 'Inactive'\n       WHEN 'P' THEN 'Pending'\n       ELSE 'Unknown'\n       END AS status_label,\n       CASE\n       WHEN balance \u003e 10000 THEN 'high'\n       WHEN balance \u003e 1000 THEN 'medium'\n       ELSE 'low'\n       END AS tier\n  FROM accounts;\n```\n\n## When NOT to use holywell\n\n- **You need highly configurable style output** -- holywell intentionally does not expose style knobs for indentation strategy, keyword casing, or alignment mode. If you need full style customization, use [sql-formatter](https://github.com/sql-formatter-org/sql-formatter) or [prettier-plugin-sql](https://github.com/JounQin/prettier-plugin-sql).\n- **You need full procedural-language AST rewriting** -- holywell formats SQL and supports many procedural/script syntaxes, but it does not build full PL/pgSQL / PL/SQL / T-SQL procedural ASTs for semantic rewrites.\n- **You need a language server** -- holywell is a formatter, not a linter or LSP. It does not provide diagnostics, completions, or semantic analysis.\n\n## SQL Dialect Support\n\nCoverage is PostgreSQL-first, but materially broader than ANSI + PostgreSQL alone. The list below reflects current implementation and regression tests.\n\n| Dialect / Syntax Family | Coverage | Notes |\n|---|---|---|\n| ANSI SQL core | First-class | Structured parsing/formatting for SELECT/CTE/DML/MERGE, joins, windows, and common DDL |\n| PostgreSQL | First-class / continuously tested | Casts, arrays, JSON operators, FILTER/WITHIN GROUP, ON CONFLICT, RETURNING, COPY stdin handling |\n| MySQL / MariaDB | Substantial / continuously tested | Backticks, LIMIT offset normalization, STRAIGHT_JOIN, RLIKE, INTERVAL, ALTER key actions, FULLTEXT, DELIMITER scripts |\n| SQL Server (T-SQL) | Substantial / continuously tested | GO batches, IF/BEGIN/END chains, CROSS APPLY, PIVOT, bracket identifiers, BACKUP/BULK, PRINT, compound assignments |\n| Oracle / PL/SQL surface syntax | Substantial / continuously tested | START WITH/CONNECT BY, q-quoted strings, slash terminators, RETURNING INTO, type declarations, nested table storage |\n| SQLite | Targeted | Numbered positional parameters (`?1`, `?2`, ...) plus ANSI-compatible statements |\n| Snowflake | Targeted | CREATE STAGE, CREATE FILE FORMAT, CREATE VIEW COMMENT, COPY INTO handling |\n| ClickHouse | Targeted | CREATE MATERIALIZED VIEW ... TO ... AS and CREATE TABLE option clauses |\n| BigQuery / Exasol / DB2 / H2 | Targeted | Backtick multipart identifiers + SAFE_CAST/TRY_CAST, Lua bracket strings, slash delimiters, MERGE ... VALUES shorthand |\n| Client/meta command syntax | First-class passthrough | psql `\\` commands/variables, SQL*Plus slash run terminators, MySQL DELIMITER blocks, T-SQL GO separators |\n\nIf you rely heavily on vendor extensions, run `--check` in CI and use `--strict` where parse failures should block merges.\n\nYou can extend keyword/clause recognition without forking:\n\n```typescript\nimport { formatSQL } from 'holywell';\n\nconst formatted = formatSQL(sql, {\n  dialect: {\n    additionalKeywords: ['QUALIFY', 'TOP'],\n    clauseKeywords: ['QUALIFY'],\n  },\n});\n```\n\n### PostgreSQL + ANSI (First-class)\n\n- Type casts (`::integer`), JSON operators (`-\u003e`, `-\u003e\u003e`), dollar-quoting (`$$...$$`)\n- Array constructors, window functions, CTEs, LATERAL joins\n- ON CONFLICT (UPSERT), RETURNING clauses\n- COPY stdin blocks and psql interpolation forms are preserved and formatted safely\n- **Note:** procedural bodies are block-aware, but not modeled as full procedural ASTs\n\n### MySQL / MariaDB (Substantial)\n\n- STRAIGHT_JOIN, RLIKE, INSERT ... VALUE, UPDATE multi-target/join forms\n- CREATE/ALTER TABLE options including ENGINE/CHARSET and FULLTEXT/KEY constraints\n- DELIMITER script boundaries and conditional comments are preserved\n\n### SQL Server (T-SQL) + Oracle (Substantial)\n\n- SQL Server: GO separators, IF/BEGIN/END and ELSE IF chains, CROSS APPLY, PIVOT, BACKUP/BULK statements\n- Oracle: hierarchical queries, q-quoted strings, slash run terminators, DELETE shorthand normalization, RETURNING ... INTO\n\n### Pass-Through Model and Strict Mode\n\nholywell supports statements through a mix of:\n\n- Structured AST parsing (deep formatting)\n- Keyword-normalized pass-through for unmodeled statement families\n- Verbatim pass-through for client/script commands\n\nIn default mode, unparseable statements are preserved where possible. Use `--strict` to fail on true parse errors instead of recovering.\n\n## Style Guide\n\nThis formatter implements the [Simon Holywell SQL Style Guide](https://www.sqlstyle.guide/). Key principles from the guide that holywell enforces:\n\n- **River alignment** -- Clause/logical keywords are right-aligned to a per-statement river width derived from the longest top-level aligned keyword\n- **Keyword uppercasing** -- Reserved words like `SELECT`, `FROM`, `WHERE` are uppercased\n- **Identifier normalization** -- Most unquoted identifiers are lowercased; quoted identifiers are preserved\n- **Right-aligned clause/logical keywords** -- `SELECT`, `FROM`, `WHERE`, `AND`, `OR`, `JOIN`, `ON`, `ORDER BY`, `GROUP BY`, etc. align within each formatted block\n- **Consistent indentation** -- Continuation lines and subexpressions are indented predictably\n\nFor the full style guide, see [sqlstyle.guide](https://www.sqlstyle.guide/) or the [source on GitHub](https://github.com/treffynnon/sqlstyle.guide).\n\n## Why holywell?\n\n| | **holywell** | sql-formatter | prettier-plugin-sql | pgFormatter | sqlfluff |\n|---|---|---|---|---|---|\n| **Formatting style** | River alignment ([sqlstyle.guide](https://www.sqlstyle.guide/)) | Indentation-based | Indentation-based | Indentation-based | Indentation-based |\n| **Language** | TypeScript/JavaScript | TypeScript/JavaScript | TypeScript/JavaScript | Perl | Python |\n| **Configuration** | Opinionated defaults + small operational config (`.holywellrc.json`) | Configurable | Configurable via Prettier | Highly configurable | Highly configurable |\n| **PostgreSQL support** | First-class (casts, JSON ops, dollar-quoting, arrays) | Partial | Partial | First-class | Broad dialect support |\n| **Runtime dependencies** | Zero | 8 deps | Prettier + parser | Perl runtime | Python + deps |\n| **Idempotent** | Yes | Yes | Yes | Yes | Yes |\n| **Keyword casing** | Uppercase (enforced) | Configurable | Configurable | Configurable | Configurable |\n| **Identifier casing** | Lowercase (enforced) | Not modified | Not modified | Configurable | Not modified |\n| **Output** | Deterministic, single style | Depends on config | Depends on config | Depends on config | Depends on config |\n| **Editor extensions** | In development | Available | Prettier-compatible | VS Code extension | VS Code extension |\n\nholywell is the right choice when you want consistent, readable SQL with minimal setup and deterministic style.\n\n### Configuration philosophy\n\nholywell keeps style deterministic by design: no indentation/casing style matrix, no formatter presets.\nIt does support a focused optional config file (`.holywellrc.json`) for operational settings:\n\n- `maxLineLength`\n- `maxDepth`\n- `maxInputSize`\n- `strict`\n- `recover`\n\nCLI flags still override config values.\n\nA starter config is available at `.holywellrc.json.example`.\n\n## CLI Reference\n\n```bash\n# Format a file (prints to stdout by default)\nnpx holywell query.sql\n\n# Format a file in place\nnpx holywell --write query.sql\n\n# Format from stdin\ncat query.sql | npx holywell\n\n# Check if a file is already formatted (exits non-zero if not)\nnpx holywell --check query.sql\n\n# List files that would change (useful in CI)\nnpx holywell --list-different \"src/**/*.sql\"\nnpx holywell -l \"migrations/*.sql\"\n\n# Strict mode: fail on unparseable SQL instead of passing through\nnpx holywell --strict --check \"**/*.sql\"\n\n# Tune output width\nnpx holywell --max-line-length 100 query.sql\n\n# Use project config\nnpx holywell --config .holywellrc.json --check \"**/*.sql\"\n\n# Ignore files (can repeat --ignore)\nnpx holywell --check --ignore \"migrations/**\" \"**/*.sql\"\n\n# Or store ignore patterns in .holywellignore (one pattern per line)\nnpx holywell --check \"**/*.sql\"\n\n# Control color in CI/logs\nnpx holywell --color=always --check query.sql\n\n# Generate shell completion\nnpx holywell --completion bash\nnpx holywell --completion zsh\nnpx holywell --completion fish\n\n# Pipe patterns\npbpaste | npx holywell | pbcopy          # Format clipboard (macOS)\npg_dump mydb --schema-only | npx holywell \u003e schema.sql\necho \"select 1\" | npx holywell\n```\n\nBy default, `npx holywell query.sql` prints formatted output to **stdout**. Use `--write` to modify the file in place.\n\nWhen present, `.holywellignore` is read from the current working directory and combined with any `--ignore` flags.\n\n**CLI exit codes:**\n\n| Code | Meaning |\n|------|---------|\n| `0` | Success (or all files already formatted with `--check`) |\n| `1` | Check failure |\n| `2` | Parse or tokenize error |\n| `3` | Usage or I/O error |\n\n## API Guide\n\n### Basic Usage\n\n```typescript\nimport { formatSQL } from 'holywell';\n\nconst formatted = formatSQL('SELECT * FROM users;');\n```\n\n### Synchronous API by design\n\n`formatSQL`, `parse`, and `tokenize` are intentionally synchronous.\nThis keeps editor/CLI integration predictable and avoids hidden async overhead.\n\n### Error Recovery\n\nBy default, unparseable SQL is passed through unchanged:\n\n```typescript\nconst warnings: string[] = [];\nconst formatted = formatSQL(sql, {\n  onRecover: (error, raw) =\u003e {\n    warnings.push(`Line ${error.token.line}: ${error.message}`);\n  }\n});\n```\n\n### Strict Mode (throw on parse errors)\n\n```typescript\nimport { formatSQL, ParseError } from 'holywell';\n\ntry {\n  formatSQL(sql, { recover: false });\n} catch (err) {\n  if (err instanceof ParseError) {\n    console.error(`Parse error: ${err.message}`);\n  }\n}\n```\n\n### Depth Limits\n\n```typescript\nformatSQL(sql, { maxDepth: 300 }); // Increase for deeply nested CTEs\n```\n\n### Input Size Limits\n\n```typescript\nformatSQL(sql, { maxInputSize: 5_000_000 }); // 5MB limit (default: 10MB)\n```\n\n### Low-Level Access\n\n```typescript\nimport { tokenize, parse, formatStatements, visitAst } from 'holywell';\n\n// Tokenize SQL into a token stream\nconst tokens = tokenize(sql);\n\n// Parse SQL into an AST\nconst ast = parse(sql);\n\n// Format AST nodes back to SQL\nconst output = formatStatements(ast);\n\n// Visit AST nodes (for custom linting/analysis)\nvisitAst(ast, {\n  byType: {\n    select(node) {\n      console.log('SELECT node:', node);\n    },\n  },\n});\n```\n\n### Error Types\n\n```typescript\nimport { formatSQL, TokenizeError, ParseError, MaxDepthError } from 'holywell';\n\ntry {\n  const result = formatSQL(input);\n} catch (err) {\n  if (err instanceof TokenizeError) {\n    // Invalid token encountered during lexing (e.g., unterminated string)\n    console.error(`Tokenize error at position ${err.position}: ${err.message}`);\n  } else if (err instanceof MaxDepthError) {\n    // Parser nesting exceeded configured maxDepth\n    console.error(`Parse depth exceeded: ${err.message}`);\n  } else if (err instanceof ParseError) {\n    // Structural error in the SQL (e.g., unmatched parentheses)\n    console.error(`Parse error: ${err.message}`);\n  } else if (err instanceof Error \u0026\u0026 err.message.includes('Input exceeds maximum size')) {\n    // Input exceeded maxInputSize\n    console.error(`Input too large: ${err.message}`);\n  } else {\n    throw err;\n  }\n}\n```\n\n## How the formatter works\n\n```\nSQL Text → Tokenizer → Parser → AST → Formatter → Formatted SQL\n```\n\n1. **Tokenizer** (`src/tokenizer.ts`) -- Splits SQL text into tokens (keywords, identifiers, literals, operators, comments)\n2. **Parser** (`src/parser.ts`) -- Builds an AST from the token stream\n3. **Formatter** (`src/formatter.ts`) -- Walks the AST and produces formatted output\n\nThe key formatting concept is the **river**. For each statement, holywell derives a river width from the longest top-level aligned keyword in that statement (for example, `RETURNING` can widen DML alignment). Clause/logical keywords are then right-aligned to that width so content starts in a consistent column. Nested blocks may use their own derived widths. This approach comes directly from the [Simon Holywell SQL Style Guide](https://www.sqlstyle.guide/).\n\n## Edge Cases \u0026 Behavior\n\n### Long Lines\n\nholywell targets 80-column output by default and supports `maxLineLength` (CLI flag or config file). It does not break individual tokens (identifiers, string literals), so single-token lines can still exceed the configured width.\n\n### Comment Preservation\n\nLine comments and block comments are preserved. Comments attached to specific expressions maintain their association.\n\n### Keyword Casing\n\nAll SQL keywords are uppercased. Identifiers are preserved as-is (quoted identifiers keep their case and quotes). Unquoted identifiers are lowercased.\n\n### Idempotency\n\nFormatting is idempotent: `formatSQL(formatSQL(x)) === formatSQL(x)` for all valid inputs.\n\n## FAQ\n\n**Q: Can I change the indentation style or keyword casing?**\n\nNo. Style output is intentionally fixed. holywell provides operational configuration (line length, strictness/safety), not style customization.\n\n**Q: What happens with SQL syntax holywell doesn't understand?**\n\nIn default (recovery) mode, unrecognized statements are passed through unchanged. Use `--strict` to fail instead.\n\n**Q: How fast is holywell?**\n\n~23,000 statements/second on modern hardware. A typical migration file formats in \u003c10ms.\n\n**Q: Does holywell modify SQL semantics?**\n\nNo. holywell changes whitespace, uppercases SQL keywords, lowercases unquoted identifiers, and normalizes alias syntax (e.g., inserting AS). Quoted identifiers and string literals are preserved exactly. The semantic meaning is preserved.\n\n**Q: Does holywell respect `.editorconfig`?**\n\nNo. holywell does not read `.editorconfig`. It does read `.holywellrc.json` (or `--config`) for operational settings, but style output remains deterministic.\n\n**Q: Can I customize the river width?**\n\nNot directly. River width is derived automatically from statement structure. You can influence wrapping via `maxLineLength`, but keyword alignment behavior itself is fixed.\n\n**Q: Does formatting change SQL semantics?**\n\nholywell only changes whitespace and casing. Specifically: SQL keywords are uppercased (`select` becomes `SELECT`), unquoted identifiers are lowercased (`MyTable` becomes `mytable`), and quoted identifiers are preserved exactly (`\"MyTable\"` stays `\"MyTable\"`). If your database is case-sensitive for unquoted identifiers (rare, but possible), see the [Migration Guide](docs/migration-guide.md) for details.\n\n**Q: Does holywell work with MySQL / SQL Server / SQLite / Oracle?**\n\nYes. holywell is PostgreSQL-first, but it has substantial tested coverage for MySQL, SQL Server, and Oracle surface syntax, plus targeted support for SQLite/Snowflake/ClickHouse and client scripting commands (`GO`, `DELIMITER`, `\\gset`, slash terminators). See [SQL Dialect Support](#sql-dialect-support) for the current matrix.\n\n## Documentation\n\n- [Integrations](docs/integrations.md) -- Pre-commit hooks, CI pipelines, and editor setup recipes\n- [Architecture](docs/architecture.md) -- Internal pipeline and design decisions\n- [Style Guide Mapping](docs/style-guide.md) -- How holywell maps to each rule in the Simon Holywell SQL Style Guide\n- [Migration Guide](docs/migration-guide.md) -- Rolling out holywell in existing codebases with minimal churn\n- [Contributing](CONTRIBUTING.md) -- Development setup, running tests, and submitting changes\n- [Changelog](CHANGELOG.md) -- Release history\n\n## Development\n\nRequires [Bun](https://bun.sh/).\n\n```bash\n# Install dependencies\nbun install\n\n# Run tests\nbun test\n\n# Type check\nbun run check\n\n# Build dist (for npm publishing)\nbun run build\n```\n\n## Performance\n\nholywell has zero runtime dependencies and formats SQL through a single tokenize-parse-format pass. Typical throughput is ~23,000 statements per second on modern hardware. Input is bounded by default size limits to prevent excessive memory use on untrusted input.\n\n## Limitations\n\n- Dialect coverage is broad but intentionally pragmatic, with strongest support for PostgreSQL-style syntax.\n- Procedural SQL bodies and vendor scripting commands are mostly handled via block-aware pass-through, not full procedural AST rewriting.\n- Unknown/unmodeled constructs may still fall back to raw statement preservation.\n- Formatting style is opinionated and focused on faithfully implementing the [Simon Holywell SQL Style Guide](https://www.sqlstyle.guide/) rather than per-project style configurability.\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvinsidious%2Fholywell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvinsidious%2Fholywell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvinsidious%2Fholywell/lists"}