npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pgn-chess

v1.0.2

Published

Python-chess compatible game tree API for PGN parsing - built on top of @mliebelt/pgn-parser

Readme

pgn-chess

Python-chess compatible game tree API for PGN parsing. Built on top of @mliebelt/pgn-parser.

Features

  • Python-chess compatible API: Uses the same tree structure and methods as python-chess
  • Full move validation: Includes a complete chess Board class with legal move generation
  • Variation support: Properly handles nested variations matching python-chess behavior
  • FEN tracking: Each node tracks the board position after that move
  • Annotations: Supports NAGs, comments, arrows, shapes, clock times, and eval

Installation

npm install pgn-chess

Quick Start

import { readGame, readGames } from 'pgn-chess';

// Read a single game
const game = readGame(`
  [Event "Example"]
  [White "Player1"]
  [Black "Player2"]

  1. e4 e5 (1... c5 2. Nf3) 2. Nf3 Nc6 3. Bb5 *
`);

// Access headers (like python-chess game.headers)
console.log(game.headers.get("Event"));  // "Example"
console.log(game.headers.get("White"));  // "Player1"

// Iterate mainline moves (like python-chess game.mainline())
for (const node of game.mainline()) {
  console.log(node.san());   // "e4", "e5", "Nf3", "Nc6", "Bb5"
  console.log(node.uci());   // "e2e4", "e7e5", etc.
  console.log(node.fen());   // FEN after this move
}

// Access variations (like python-chess)
const e4 = game.variations[0];
console.log(e4.variations.length);         // 2 (e5 and c5)
console.log(e4.variations[0].san());       // "e5" (mainline)
console.log(e4.variations[1].san());       // "c5" (variation)

// Tree navigation
const lastNode = game.end();               // Follow mainline to end
const root = lastNode.root();              // Get game root
console.log(lastNode.isEnd());             // true
console.log(lastNode.isMainline());        // true

// Board state at any node
const board = lastNode.board();
console.log(board.fen());
console.log(board.turn);                   // false (black to move)
console.log([...board.legalMoves()]);      // All legal moves

API Reference

Reading Games

// Read a single game (returns null if empty/invalid)
const game = readGame(pgnString);

// Read multiple games
const games = readGames(pgnString);

// Iterator for large files
for (const game of iterGames(pgnString)) {
  console.log(game.headers.get("White"));
}

Game Class

The root node of a game tree. Extends GameNode.

// Headers
game.headers.get("Event")
game.headers.set("Event", "My Tournament")

// Root-level comment
game.comment                // Comment before first move

// First move(s)
game.variations             // Array of first moves
game.variations[0]          // First move of mainline

// Errors during parsing
game.errors                 // Array of parse errors

GameNode Class

Represents a node in the game tree.

// Move information
node.move          // Move object (null for root)
node.san()         // SAN notation: "e4", "Nf3", "O-O"
node.uci()         // UCI notation: "e2e4", "g1f3"

// Board state
node.board()       // Board object after this move
node.fen()         // FEN string after this move

// Annotations
node.comment       // Comment after move
node.startingComment  // Comment before move
node.nags          // Set<number> of NAGs ($1, $2, etc.)
node.clock         // Clock time in seconds
node.eval          // Engine eval
node.arrows        // Arrow annotations
node.shapes        // Shape/highlight annotations

// Tree navigation
node.parent        // Parent node (null for root)
node.variations    // Child nodes
node.isEnd()       // No more moves?
node.isMainline()  // Is this node in the mainline?
node.next()        // First child (mainline continuation)
node.root()        // Get the Game object
node.end()         // Follow mainline to terminal node

// Iteration
node.mainline()    // Iterate mainline nodes
node.mainlineMoves()  // Iterate mainline Move objects
node.countNodes()  // Count nodes in subtree

// Modification
node.addVariation(move)      // Add a variation
node.addMainVariation(move)  // Add as new mainline
node.addLine(moves)          // Add sequence of moves
node.removeVariation(child)  // Remove a variation
node.promote()               // Move up in variation order
node.promoteToMain()         // Make this the mainline

Board Class

Full chess board with move generation and validation.

import { Board, Move } from 'pgn-chess';

const board = new Board();           // Starting position
const board2 = new Board(fenString); // From FEN

// Make moves
board.push(Move.fromUci("e2e4"));
board.pushSan("Nf3");
board.pushUci("e7e5");

// Undo moves
const move = board.pop();

// Position queries
board.fen()                     // Current FEN
board.turn                      // true=white, false=black
board.pieceAt(square)           // Piece at square
board.isCheck()                 // Is current player in check?
board.isCheckmate()             // Is it checkmate?
board.legalMoves()              // Iterator of legal moves

// Move conversion
board.san(move)                 // Get SAN for a move
board.parseSan("Nf3")           // Parse SAN to Move

Move Class

import { Move } from 'pgn-chess';

// Create moves
const move = Move.fromUci("e2e4");
const promo = Move.fromUci("e7e8q");

// Properties
move.fromSquare     // 12 (e2)
move.toSquare       // 28 (e4)
move.promotion      // null or piece type (2-5)
move.uci()          // "e2e4"
move.equals(other)  // Compare moves

Comparison with python-chess

This library provides an API that closely matches python-chess:

| python-chess | pgn-chess | |-------------|----------------| | chess.pgn.read_game(file) | readGame(string) | | game.headers["White"] | game.headers.get("White") | | game.mainline() | game.mainline() | | node.board() | node.board() | | node.san() | node.san() | | node.variations | node.variations | | node.is_mainline() | node.isMainline() | | board.push(move) | board.push(move) | | board.fen() | board.fen() |

License

MIT