century-arcade/xd

a futureproof crossword corpus toolset

Python

265

539 commits

updated Jun 12, 2026

See the code

README

xd

The xd project includes a text format for crossword puzzles and a pipeline for downloading, parsing, analyzing puzzles, and producing the website and released data at xd.saul.pw.

Validating .xd files

xdlint.py is the authoritative validator for the .xd format. It enforces the spec plus a set of structural and quality rules grounded in real-world fix patterns. Stdlib-only, no dependencies.

xdlint.py path [path ...]              # lint files or directories
xdlint.py --base BASE [--head HEAD]    # lint files changed in a git diff
xdlint.py --list-rules                 # print the rule catalog
xdlint.py --no-experimental ...        # skip rules interpreting unspec'd extensions

See doc/rebus-conventions.md for the rebus / quantum / Schrödinger conventions the linter recognizes (these are extensions to the spec, not yet formalized).

Requirements

  • python 3.7+
  • git
  • pandoc (to build website)
  • sqlite (for grid comparison)
  • gcc (to build sqlite plugin)

Running the pipeline

  1. Checkout the gxd repo (private; join #crosswords on the Discord to discuss getting access).

    make setup

  2. Download new puzzles from known sources, convert to .xd, shelve, and commit to gxd repo.

    make import

Raw puz/etc files saved to .zip in /tmp, and .xd files saved to gxd directory.

  1. Analyze puzzles

    make analyze

Output in pub directory.

  1. Build website

    make website

Output in wwwroot directory.

  1. Generate gxd.sqlite database (400MB)

    make gxd.sqlite

  2. Find similar grids (takes ~12 hours)

    make gridmatches

Similarity scores saved to gridmatches table in gxd.sqlite.

Contributors

andjelx

204 commits

saulpw

197 commits

alexdej

52 commits

anjakefala

32 commits

century-arcade/xd

a futureproof crossword corpus toolset

Python

265

539 commits

updated Jun 12, 2026

See the code

README

xd

The xd project includes a text format for crossword puzzles and a pipeline for downloading, parsing, analyzing puzzles, and producing the website and released data at xd.saul.pw.

Validating .xd files

xdlint.py is the authoritative validator for the .xd format. It enforces the spec plus a set of structural and quality rules grounded in real-world fix patterns. Stdlib-only, no dependencies.

xdlint.py path [path ...]              # lint files or directories
xdlint.py --base BASE [--head HEAD]    # lint files changed in a git diff
xdlint.py --list-rules                 # print the rule catalog
xdlint.py --no-experimental ...        # skip rules interpreting unspec'd extensions

See doc/rebus-conventions.md for the rebus / quantum / Schrödinger conventions the linter recognizes (these are extensions to the spec, not yet formalized).

Requirements

  • python 3.7+
  • git
  • pandoc (to build website)
  • sqlite (for grid comparison)
  • gcc (to build sqlite plugin)

Running the pipeline

  1. Checkout the gxd repo (private; join #crosswords on the Discord to discuss getting access).

    make setup

  2. Download new puzzles from known sources, convert to .xd, shelve, and commit to gxd repo.

    make import

Raw puz/etc files saved to .zip in /tmp, and .xd files saved to gxd directory.

  1. Analyze puzzles

    make analyze

Output in pub directory.

  1. Build website

    make website

Output in wwwroot directory.

  1. Generate gxd.sqlite database (400MB)

    make gxd.sqlite

  2. Find similar grids (takes ~12 hours)

    make gridmatches

Similarity scores saved to gridmatches table in gxd.sqlite.

Contributors

andjelx

204 commits

saulpw

197 commits

alexdej

52 commits

anjakefala

32 commits

Languages

Python

92.2%

Shell

3.8%

CSS

2.0%

C

1.2%