A command-line application for importing chess games from PGN files or Chess.com/Lichess APIs, analyzing them with Stockfish, and storing them in a SQLite database.
- Import games from PGN files or directories
- Fetch games from Chess.com API with date filtering
- Fetch games from Lichess API with date filtering
- Deep Stockfish analysis (depth 20) for each position
- Multi-PV analysis (top 3 continuations)
- Duplicate detection based on exact PGN match
- SQLite database with full game and position data
- Colored terminal output for progress tracking
- Comprehensive error logging to console and file
- TypeScript v5.x
- Node.js v18+ (required for WASM support)
- better-sqlite3 - SQLite database operations
- kokopu - PGN parsing and chess logic
- stockfish - WASM-based Stockfish engine
- chalk - Terminal colors
- date-fns - Flexible date parsing
- commander - CLI argument parsing
- Node.js v18 or higher
- npm or yarn
npm installnpm run buildImport a single PGN file:
chess-game-importer pgn /path/to/game.pgnImport all PGN files from a directory (recursive):
chess-game-importer pgn /path/to/pgns/Import all games for a user (last 30 days by default):
chess-game-importer chesscom usernameImport games with a date range:
chess-game-importer chesscom username 2025-01-01 2025-01-31Supported date formats:
2025-01-01(ISO format)01/01/2025(MM/DD/YYYY)Jan 1, 2025January 1, 20251 Jan 20251 January 2025
Import games from Lichess (same syntax as Chess.com):
chess-game-importer lichess username
chess-game-importer lichess username 2025-01-01 2025-01-31-h, --help- Display help message-v, --version- Display version number
The CLI provides colored terminal output showing:
- ℹ Information messages (blue)
- ✓ Success messages (green)
- ⚠ Warning messages (yellow) - e.g., duplicate games
- ✗ Error messages (red)
During import, you'll see:
- File being processed
- Games found and parsed
- Positions being analyzed with Stockfish
- Summary of imported/skipped/errored games
Games are stored in games.db with:
- games table: Game metadata (players, winner, tournament, PGN)
- positions table: Each position with FEN, evaluation, best move, continuations, and board state
Duplicate detection prevents importing the same game twice (based on exact PGN match).
Run with automatic reloading on file changes:
npm run devCompile TypeScript to JavaScript:
npm run buildRun all tests:
npm testRun tests in watch mode:
npm run test:watchRun tests with coverage:
npm test -- --coverageCheck code for issues:
npm run lintFormat code with Prettier:
npm run formatCheck formatting without changing:
npm run format:checkchess-game-importer/
├── src/
│ ├── cli/ # CLI command handlers
│ ├── config/ # Configuration files
│ ├── constants/ # SQL and UCI constants
│ ├── errors/ # Custom error classes
│ ├── models/ # TypeScript interfaces
│ ├── services/ # Core business logic
│ └── utils/ # Utility functions
├── tests/
│ ├── unit/ # Unit tests
│ ├── integration/ # Integration tests
│ └── e2e/ # End-to-end tests
├── dist/ # Compiled JavaScript (generated)
└── games.db # SQLite database (generated)
Each position is analyzed to depth 20 with the following configuration:
- MultiPV: 3 (top 3 continuations)
- Hash: 128 MB
- Threads: 1 (for stability)
Analysis results include:
- Evaluation in pawns (or "M3" for mate in 3)
- Best move in UCI notation
- Top 3 principal variations with moves and evaluations
All errors are logged to:
- Console (with colors)
error.logfile (with timestamps and stack traces)
The application continues processing after errors, logging them and moving to the next game/file.
- Stockfish analysis is sequential (one position at a time) for stability
- Expected speed: ~1-3 seconds per position
- Large PGN files (100+ games) may take several minutes
- Duplicate detection is instant (UNIQUE constraint on PGN)
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting:
npm test && npm run lint - Commit your changes
- Push to the branch
- Create a Pull Request
- Use TypeScript with strict mode
- Follow ESLint rules
- Format with Prettier (2 spaces, single quotes)
- Add JSDoc comments for functions
- Use private methods with underscore prefix
- Aim for >80% code coverage
- Write unit tests for utilities and services
- Write integration tests for workflows
- Write E2E tests for CLI commands
MIT
Nathan Loding