Quick Start
What you need
- CQLi binary for your platform (Windows, macOS, or Linux)
- A PGN chess game database (see PGN Databases for free sources)
- A terminal / command prompt
CQLi searches chess games stored in PGN files using the Chess Query Language (CQL). This page walks you through running one query from start to finish and then lists short examples you can adapt.
Your first query
The command below finds decisive games that lasted more than 100 moves. Replace input.pgn
with your PGN file, output.pgn with the file to write, and cqli with the
executable for your platform: cqli on Linux, cqli-arm64 (Apple Silicon) or
cqli-x86_64 (Intel) on macOS, and cqli.exe on Windows.
cqli -i input.pgn -o output.pgn -cql'terminal result 1-0 or result 0-1 movenumber > 100'
CQLi checks every position of every game against the query and writes each game with a matching position to
output.pgn. A position matches when all of the query's filters match it: here
terminal matches only the final position of a game, result 1-0 or result 0-1
requires a decisive result, and movenumber > 100 requires more than 100 moves. In a sample of
one million games from lichess.org, 356 games match; the links below open ten of them at the matching move.
Viewing the results
The output file is an ordinary PGN file that can be opened in any chess program that reads PGN, such as
ChessBase, Scid, or the Lichess analysis board. CQLi marks the matching position in each game with the
comment {CQL}, so you can step straight to it.
Games downloaded from Lichess have a Site tag containing the address of the game on lichess.org,
so a matching game can also be opened there and replayed with engine analysis. The sample match links on this
page were produced that way.
Useful options
The -i option specifies the input PGN file and the -o option specifies the output file.
The -cql option provides the query on the command line; a longer query can instead be saved in a
file with a .cql extension, which is named on the command line in place of the -cql option.
On Windows, Windows PowerShell 5.1 (the version included with Windows) removes double quotes from inside a quoted
argument before CQLi sees them. If a query contains double quotes, type each one as \", for example
-cql 'zobristkey == \"9f2e3a461655ff6b\"', save the query in a .cql file instead, or use
PowerShell 7.3 or later, which passes the quotes through unchanged.
The -matchstring option changes the CQL comment added to matching positions, and the
-silent option stops CQLi from adding comments at all. By default, CQLi keeps all matching games in
memory until processing finishes; if a query matches a very large number of games, the -nosort
option writes each game out as soon as it is found instead.
When trying queries on a large PGN file (millions of games), the -g option limits processing to a
range of games so you do not have to wait for the whole file. For example, -g 1 100000 processes
only the first 100,000 games.
Short Examples
Make the same substitutions for input.pgn, output.pgn, and
cqli as above. Most examples show how many of the same one million lichess.org games match,
along with links to ten sample matches.
Remove all comments from a PGN file
cqli -i input.pgn -o output.pgn -silent -nosort -cql'removecomment'
Failed conversion of KBBvK ending
cqli -i input.pgn -o output.pgn -cql'terminal result 1/2-1/2 flipcolor { A == K a == [kb] == 3 }'
Mate in KNBvK ending
cqli -i input.pgn -o output.pgn -cql'terminal mate flipcolor { A == K a == 3 n == 1 b == 1 }'
Win by player 400+ Elo lower
cqli -i input.pgn -o output.pgn -cql'initial flipcolor { result 1-0 elo white + 400 <= elo black }'
Castling opposite sides
cqli -i input.pgn -o output.pgn -cql'initial find move o-o find move o-o-o'
Bishop pins rook to queen
cqli -i input.pgn -o output.pgn -cql'flipcolor pin from B through r to q'
Positions that match a specific Zobrist key
cqli -i input.pgn -o output.pgn -cql'zobristkey == "9f2e3a461655ff6b"'
Populate a tag named EndFEN with the FEN of the ending position
cqli -i input.pgn -o output.pgn -silent -nosort -cql'terminal settag("EndFEN" currentfen)'
Promotion(s) by both sides
cqli -i input.pgn -o output.pgn -cql'initial find { wtm move promote A } find { btm move promote A }'
Both sides have promoted queens on the board
cqli -i input.pgn -o output.pgn -cql'promotedpieces & Q promotedpieces & q'
2+ consecutive promotions
cqli -i input.pgn -o output.pgn -cql'line --> move promote A {2,}'
Underpromotions
cqli -i input.pgn -o output.pgn -cql'move promote [BNR]'
When you're ready for more, the Examples page works through longer queries in detail, and the HTML Reference Manual documents every filter and option used here.