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

@chessle/chess.js-extended

v0.1.0

Published

A powerful browser-only chess engine package that bundles Stockfish for position evaluation and analysis on top of chess.js

Downloads

53

Readme

chess.js-extended

A powerful browser-only chess engine package that extends chess.js with built-in Stockfish evaluation capabilities. This package bundles Stockfish for position evaluation and analysis directly in the browser using Web Workers and WebAssembly.

Features

  • 🚀 Built on chess.js: All standard chess.js functionality included
  • 🧠 Stockfish Integration: Bundled Stockfish engine for position evaluation
  • 🌐 Browser-Only: Designed specifically for browser environments with Web Worker support
  • WebAssembly Support: Automatically uses WASM when available for better performance
  • 🎯 Position Evaluation: Get numerical evaluations and mate scores
  • 📈 Multi-PV Analysis: Get multiple principal variations for deeper insight
  • 🔍 Suggested Lines: Get full suggested lines of play in SAN format
  • ⚙️ Flexible Options: Configure search depth, time limits, and more
  • 📦 Multiple Formats: CommonJS and ES Module builds included

Installation

pnpm install @chessle/chess.js-extended

Quick Start

import { ChessEngine } from "@chessle/chess.js-extended";

const engine = new ChessEngine();

// Make some moves
engine.move("e4");
engine.move("e5");
engine.move("Nf3");

// Evaluate the position
const lines = await engine.evaluatePosition();

if (lines.length > 0) {
  const bestLine = lines[0];
  console.log(`Evaluation: ${bestLine.evaluation}`);
  console.log(`Best move: ${bestLine.line[0]}`);
  console.log(`Suggested line: ${bestLine.line.join(" ")}`);
}

Dual-Mode API: Promise and Streaming

ChessEngine offers two distinct modes for analysis to suit different use cases: a simple Promise-based mode for one-shot evaluations and a powerful Streaming API for continuous analysis.

Important: A single ChessEngine instance can only perform one analysis at a time. Attempting to start a new evaluation or analysis while one is already in progress will result in an error.

1. Promise-Based Analysis (One-Shot)

The evaluatePosition() method is perfect for when you need a single, final evaluation of the current board state. It returns a promise that resolves once Stockfish has completed its analysis.

import { ChessEngine } from "@chessle/chess.js-extended";

const engine = new ChessEngine();
engine.load("rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2");

async function getEvaluation() {
  console.log("Evaluating position...");
  const lines = await engine.evaluatePosition({ depth: 18 });
  console.log("Evaluation complete.");

  if (lines.length > 0) {
    const bestLine = lines[0];
    console.log(`Evaluation: ${bestLine.evaluation}`);
    console.log(`Best move: ${bestLine.line[0]}`);
  }
}

getEvaluation();

2. Streaming Analysis (Continuous)

The streaming API is ideal for applications that need to display real-time engine analysis, such as a live chessboard UI.

  • startAnalysis(options): Begins an infinite analysis of the current position.
  • on('analysis', callback): Listens for analysis updates. The callback receives an array of the latest AnalysisLine objects as the engine deepens its search.
  • stopAnalysis(): Sends the stop command to Stockfish, which will then emit a final bestmove and terminate the analysis.
import { ChessEngine } from "@chessle/chess.js-extended";

const engine = new ChessEngine();
engine.load("r1bqkbnr/pp1ppppp/2n5/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3");

// 1. Listen for analysis updates
engine.on("analysis", (lines) => {
  console.clear();
  console.log("Current Analysis:");
  lines.forEach((line) => {
    console.log(`- ${line.line.join(" ")} (Eval: ${line.evaluation})`);
  });
});

// 2. Start the analysis
console.log("Starting continuous analysis...");
engine.startAnalysis({ multiPV: 3 });

// 3. Stop the analysis after a few seconds
setTimeout(() => {
  console.log("Stopping analysis...");
  engine.stopAnalysis();
  console.log("Analysis stopped.");
}, 5000);

API Reference

ChessEngine Class

The ChessEngine class extends the standard chess.js Chess class with evaluation capabilities.

Constructor

const engine = new ChessEngine();

Properties

  • lines: AnalysisLine[] - An array of the most recent final analysis lines from the last completed evaluatePosition call.

Methods

evaluatePosition(options?)

Evaluates the current position using Stockfish and returns a single result.

await engine.evaluatePosition(options?: StockfishOptions): Promise<AnalysisLine[]>;
startAnalysis(options?)

Starts a continuous, infinite analysis of the current position. Use the on('analysis', ...) method to receive updates.

engine.startAnalysis(options?: StockfishOptions): void;
stopAnalysis()

Stops a running analysis that was started with startAnalysis().

engine.stopAnalysis(): void;
on(event, listener)

Subscribes to engine events. Currently, only the analysis event is supported.

engine.on('analysis', (lines: AnalysisLine[]) => void): void;
off(event, listener)

Unsubscribes from engine events.

engine.off('analysis', (lines: AnalysisLine[]) => void): void;

StockfishOptions Interface

interface StockfishOptions {
  /** Search depth (default: 15) */
  depth?: number;
  /** Thinking time in milliseconds */
  time?: number;
  /** Exact time to think in milliseconds */
  movetime?: number;
  /** Number of nodes to search */
  nodes?: number;
  /** Number of principal variations to search for (default: 1) */
  multiPV?: number;
  /** Skill level of the engine (0-20) */
  skillLevel?: number;
  /** Contempt value for the engine (-100 to 100) */
  contempt?: number;
  /** Number of threads to use (1-512) */
  threads?: number;
  /** Hash table size in MB (1-32768) */
  hash?: number;
  /** Custom Stockfish worker URL (optional) */
  stockfishUrl?: string;
}

AnalysisLine Interface

interface AnalysisLine {
  /** The evaluation of the position (e.g., 0.5, -1.2, "M5", "M-3") */
  evaluation: number | string;
  /** The suggested sequence of moves in SAN format */
  line: string[];
}

Usage Examples

Basic Position Evaluation

import { ChessEngine } from "chess.js-extended";

const engine = new ChessEngine();
engine.load("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1");

const lines = await engine.evaluatePosition();
if (lines.length > 0) {
  console.log(`Position evaluation: ${lines[0].evaluation}`);
  // Output: Position evaluation: 0.15
}

Multi-PV Analysis

Get the top 3 best moves and their evaluations.

const lines = await engine.evaluatePosition({ multiPV: 3 });

lines.forEach((line, index) => {
  console.log(
    `Rank ${index + 1}: ${line.line.join(" ")} (Eval: ${line.evaluation})`,
  );
});
// Output:
// Rank 1: Nc6 ... (Eval: 0.15)
// Rank 2: c5 ... (Eval: 0.20)
// Rank 3: e6 ... (Eval: 0.22)

Time-Limited Analysis

// Analyze for exactly 5 seconds
const lines = await engine.evaluatePosition({ movetime: 5000 });
if (lines.length > 0) {
  console.log(`Timed evaluation: ${lines[0].evaluation}`);
}

Configuring Engine Parameters

You can fine-tune the engine's performance and playing style by providing additional options.

const lines = await engine.evaluatePosition({
  skillLevel: 10, // Set skill level to 10 (0-20)
  contempt: 20, // Set contempt to 20 (-100-100)
  threads: 4, // Use 4 threads
  hash: 128, // Use 128MB of hash memory
});

if (lines.length > 0) {
  console.log(`Evaluation with custom parameters: ${lines[0].evaluation}`);
}

Getting the Best Move and Line

const lines = await engine.evaluatePosition();

if (lines.length > 0) {
  const bestLine = lines[0];
  console.log(`Best move: ${bestLine.line[0]}`);
  engine.move(bestLine.line[0]);

  console.log(`Principal variation: ${bestLine.line.join(" ")}`);
  // Output: Principal variation: Nf3 Nc6 Bc4 Bc5
}

Handling Mate Scores

// Load a position with checkmate
engine.load("rnb1kbnr/pppp1ppp/4p3/8/6Pq/5P2/PPPPP2P/RNBQKBNR w KQkq - 1 3");

const lines = await engine.evaluatePosition();
if (lines.length > 0) {
  console.log(`Evaluation: ${lines[0].evaluation}`);
  // Output: Evaluation: M-1 (mate in 1 for black)
}

Using All chess.js Methods

Since ChessEngine extends Chess, you have access to all standard chess.js functionality:

const engine = new ChessEngine();

// Standard chess.js methods work as expected
console.log(engine.ascii());
console.log(engine.moves());
console.log(engine.inCheck());
console.log(engine.isGameOver());

// Make moves
engine.move("e4");
engine.move({ from: "e7", to: "e5" });

// Undo moves
engine.undo();

// Get FEN
console.log(engine.fen());

// And then evaluate
const lines = await engine.evaluatePosition();

Browser Compatibility

This package requires:

  • Web Worker support
  • WebAssembly support (recommended, falls back to JavaScript if unavailable)
  • Modern browser with ES6+ support

Performance Notes

  • WebAssembly: Automatically detected and used when available
  • Web Workers: Stockfish runs in a separate thread to avoid blocking the main thread
  • Memory Management: Worker instances are properly cleaned up after analysis
  • Timeout Protection: Analysis automatically times out after 30 seconds to prevent hanging

Error Handling

try {
  const lines = await engine.evaluatePosition();
  if (lines.length > 0) {
    console.log(lines[0].evaluation);
  }
} catch (error) {
  if (error.message.includes("browser environment")) {
    console.log("This package only works in browsers");
  } else if (error.message.includes("worker failed")) {
    console.log("Stockfish failed to load");
  }
}

Common Evaluation Values

  • Positive numbers: Advantage for White (e.g., +1.5 = White is ahead by 1.5 pawns)
  • Negative numbers: Advantage for Black (e.g., -0.8 = Black is ahead by 0.8 pawns)
  • Mate scores: M3 = mate in 3, M-2 = mate in 2 for opponent
  • Zero: Equal position

License

GPL-3.0 - See LICENSE file for details.

Contributing

This package is part of the Chessle project. Contributions welcome!

Related Packages

  • chess.js - The core chess library this extends
  • Stockfish - The powerful chess engine bundled within