PGN Merger
Merge multiple chess PGN files into one database with this fast F# CLI. Zero dependencies, streaming I/O, preserves all game metadata.
PGN Merger: Merge Chess PGN Files from the Command Line
A fast, standalone command-line tool to merge multiple PGN (Portable Game Notation) chess files into a single database. Written in F# with streaming I/O, it handles thousands of files with ~64 KB of memory.
When I needed to aggregate Lichess Elite PGN files for opening preparation, existing tools either required Python dependencies, discarded game metadata, or forced games into variation trees. I wanted something simpler: a zero-dependency CLI that takes a folder of .pgn files and produces one clean merge.pgn.
Quick Start
# Install from NuGet (requires .NET 10.0 SDK)dotnet tool install --global PgnMerger
# Merge all PGN files in a folderpgn-merger ./lichess_gamesThe tool creates merge.pgn in the target folder. Done.
What Is a PGN File?
PGN (Portable Game Notation) is the standard text format for recording chess games. Every game includes headers (player names, event, date, result) and the move list. When you download games from Lichess or Chess.com, you get .pgn files, often hundreds or thousands of them. Merging PGN files into one database makes analysis and opening preparation far easier — load a single file into Scid vs PC, ChessBase, or your engine of choice.
Features
- Merge entire directories — point at a folder, get a single
merge.pgn - Preserves all metadata — headers, comments, NAGs, and variations stay intact
- Zero dependencies — standalone binary, no Python or runtime required
- Cross-platform — runs on Windows, macOS, and Linux via .NET
- Memory-efficient — streaming I/O with fixed 64 KB buffers, regardless of file size
- Recursive mode — include subdirectories with
--recursive - Progress feedback — optional verbose mode shows throughput per file
- Safe by default — handles missing directories, permission errors, and excludes the output file from input
Installation
From NuGet (Recommended)
Install as a .NET global tool:
dotnet tool install --global PgnMergerOr add the NuGet package to your project.
From Source
Requires .NET 10.0 SDK:
git clone https://github.com/CorentinGS/pgn-merger.gitcd pgn-mergerdotnet buildUsage
# Basic: merge all PGN files in a folderpgn-merger ./lichess_games
# With verbose outputpgn-merger ./lichess_games --verbose
# Custom output filenamepgn-merger ./lichess_games --output my_database.pgn
# Include subdirectories recursivelypgn-merger ./lichess_games --recursiveThe tool creates merge.pgn (or your chosen filename) in the target folder. Exit code 0 means success, 1 means complete failure, 2 means partial success (some files failed).
How PGN Merger Compares to Alternatives
| Tool | Language | Standalone | Preserves Headers | Preserves Comments | Merge Type |
|---|---|---|---|---|---|
| PGN Merger | F# / .NET | Yes | Yes | Yes | Clean concatenation |
| merge-pgn | Python | No (requires python-chess) | No | No | Variation tree |
| pgn-tools | Python | No (requires python-chess) | Yes | Yes | Variation tree |
PGN Merger is the only tool that does just concatenation: no parsing, no transformation, no dependencies. This makes it faster and safer for simple aggregation tasks.
FAQ
How do I merge Lichess PGN files?
Download your games from Lichess (Settings → Export games), place all .pgn files in one folder, then run pgn-merger ./your_folder. The tool preserves all Lichess metadata including ratings, timestamps, and opening codes (ECO).
Can I merge PGN files from Chess.com?
Yes. Export your games from Chess.com in PGN format and use the same process. The tool handles any valid PGN file regardless of source — Lichess, Chess.com, ICC, or custom databases.
Does PGN Merger modify game data?
No. PGN Merger performs a byte-for-byte append operation. It does not parse, validate, or transform the games in any way. What goes in is exactly what comes out.
How do I merge PGN files recursively (with subdirectories)?
Use the --recursive flag:
pgn-merger ./chess_database --recursiveThis walks all subdirectories and merges every .pgn file found.
How much memory does PGN Merger use?
Approximately 64 KB per file. The tool streams data through fixed-size buffers and never loads entire files into memory. You can merge a 50 GB PGN archive on a machine with 512 MB of RAM.
What is the difference between merging and combining PGN files?
“Merging” in chess software often means building a variation tree or database with deduplication. PGN Merger does concatenation: it appends files sequentially, preserving each game as-is. This is ideal for building raw databases for analysis engines.
Technical Details
- Language: F# 7.0
- Runtime: .NET 10.0
- Input: Any valid PGN files (UTF-8)
- Output: Single concatenated PGN file
- Memory usage: ~64 KB per file (fixed buffer)
- Exit codes:
0(success),1(complete failure),2(partial success)
Want to understand the implementation? I wrote a detailed technical walkthrough covering the streaming I/O, functional patterns, and performance optimizations behind PGN Merger.
Looking for a Go-based chess library? Check out my corentings/chess project — move generation, PGN encoding, and UCI interop, all in Go.
Get the Source
PGN Merger is open source under the MIT license.