Chess Server for AI Agents
A Rust-powered chess server and CLI with REST, WebSocket, and deep analysis APIs — following FIDE 2023 rules.
- Full FIDE 2023 Rules — Move generation and validation with castling, en passant, promotion, check/checkmate/stalemate, and all draw conditions (50-move rule, threefold repetition, insufficient material)
- Deep Game Analysis — Asynchronous engine with 30+ ply depth, PVS/Negascout, transposition table, null-move pruning, LMR, SEE, futility pruning, killer/history heuristics, and quiescence search
- PeSTO Evaluation — Midgame/endgame piece-square tables with king safety, pawn shield analysis, piece mobility, and phase interpolation
- Opening Book — Polyglot
.binformat with binary search lookups - Endgame Tablebases — Syzygy tablebase detection with analytical evaluation for common endgames
- REST API — JSON-based endpoints for game management, moves, draw claims, resignation, FEN/PGN import/export (Agent Protocol)
- Analysis API — Separate
/api/analysis/*endpoints for deep game analysis with real-time progress tracking - WebSocket API — Full real-time API at
/wsmirroring REST endpoints with push notifications and game subscriptions - Swagger/OpenAPI — Auto-generated interactive API docs at
/swagger-ui/ - Terminal Interface — Colored board display with interactive move input for local two-player games
- Modern Web UI — TypeScript SPA with @bquery/bquery, Tailwind CSS v4, Vite — interactive SVG board, analysis panel, FEN/PGN tools, promotion dialog, WebSocket auto-reconnect. Compiled into the binary via
rust-embed - Docker Support — Multi-stage Dockerfile and docker-compose.yml with volume mounts for game data, opening books, and tablebases
- Internationalization — 8 languages (EN, DE, FR, ES, ZH, JA, PT, RU) with auto-detection and per-request API selection
- Self-Update — Automatic version checks and
checkai updatefor in-place binary updates - npm Package —
@josunlp/checkaion GitHub Packages — the full chess engine compiled to WebAssembly, usable as a Node.js CLI or JavaScript library
Linux / macOS:
curl -fsSL https://raw.githubusercontent.com/JosunLP/checkai/main/scripts/install.sh | shWindows (PowerShell):
irm https://raw.githubusercontent.com/JosunLP/checkai/main/scripts/install.ps1 | iexTip: For production use, download and verify the script before running it. See the Getting Started guide for details.
git clone https://github.com/JosunLP/checkai.git
cd checkai
# Build web UI (requires Bun)
cd web && bun install && bun run build && cd ..
# Build the Rust binary
cargo build --releasecheckai serve # Default: http://0.0.0.0:8080
checkai serve --port 3000 # Custom port
checkai serve \
--book-path books/book.bin \
--tablebase-path tablebase/ \
--analysis-depth 30 # With opening book + tablebasesOpen http://localhost:8080/ for the Web UI or /swagger-ui/ for interactive API docs.
docker compose up -d # Build and start
docker compose logs -f # Follow logs
docker compose down # StopThe chess engine is also available as a Node.js package via GitHub Packages:
# Configure GitHub Packages registry
echo "@josunlp:registry=https://npm.pkg.github.com" >> ~/.npmrc
# Install as CLI
npm install -g @josunlp/checkai
checkai fen
checkai search "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1" --depth 15
# Or use as library
npm install @josunlp/checkaiimport { engine } from "@josunlp/checkai";
const moves = engine.legalMoves(engine.startingFen());
const result = engine.bestMove(engine.startingFen(), 10);See the npm README for the full API reference.
checkai play| Method | Path | Description |
|---|---|---|
POST |
/api/games |
Create a new game |
GET |
/api/games |
List all games |
GET |
/api/games/{id} |
Get full game state |
DELETE |
/api/games/{id} |
Delete a game |
POST |
/api/games/{id}/move |
Submit a move |
POST |
/api/games/{id}/action |
Special action (resign, draw claim) |
GET |
/api/games/{id}/moves |
List legal moves |
GET |
/api/games/{id}/board |
ASCII board display |
GET |
/api/games/{id}/fen |
Export FEN notation |
POST |
/api/games/fen |
Import game from FEN |
GET |
/api/games/{id}/pgn |
Export PGN notation |
| Method | Path | Description |
|---|---|---|
POST |
/api/analysis/game/{id} |
Submit game for analysis |
GET |
/api/analysis/jobs |
List all analysis jobs |
GET |
/api/analysis/jobs/{id} |
Get job status & results |
DELETE |
/api/analysis/jobs/{id} |
Cancel or delete a job |
Connect to ws://localhost:8080/ws for real-time bidirectional communication.
| Action | Fields |
|---|---|
create_game |
— |
list_games |
— |
get_game |
game_id |
delete_game |
game_id |
submit_move |
game_id, from, to, promotion? |
submit_action |
game_id, action_type, reason? |
get_legal_moves |
game_id |
subscribe / unsubscribe |
game_id |
list_archived / get_archived |
game_id |
replay_archived |
game_id, move_number? |
Full API documentation with request/response schemas: REST | WebSocket | Analysis
# Create a game
curl -X POST http://localhost:8080/api/games
# → { "game_id": "550e8400-...", "message": "New chess game created. White to move." }
# Submit a move (1. e4)
curl -X POST http://localhost:8080/api/games/{game_id}/move \
-H "Content-Type: application/json" \
-d '{"from": "e2", "to": "e4"}'
# Get legal moves
curl http://localhost:8080/api/games/{game_id}/moves
# Resign
curl -X POST http://localhost:8080/api/games/{game_id}/action \
-H "Content-Type: application/json" \
-d '{"action": "resign"}'
# Claim draw
curl -X POST http://localhost:8080/api/games/{game_id}/action \
-H "Content-Type: application/json" \
-d '{"action": "claim_draw", "reason": "threefold_repetition"}'
# Submit game for deep analysis
curl -X POST http://localhost:8080/api/analysis/game/{game_id} \
-H "Content-Type: application/json" \
-d '{"depth": 30}'
# → { "job_id": "a1b2c3d4-...", "message": "Analysis submitted ..." }
# Get analysis results
curl http://localhost:8080/api/analysis/jobs/{job_id}const ws = new WebSocket("ws://localhost:8080/ws");
ws.onopen = () => {
ws.send(JSON.stringify({ action: "create_game", request_id: "1" }));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === "response" && msg.action === "create_game") {
const gameId = msg.data.game_id;
ws.send(JSON.stringify({ action: "subscribe", game_id: gameId }));
ws.send(JSON.stringify({
action: "submit_move", game_id: gameId, from: "e2", to: "e4"
}));
}
if (msg.type === "event") {
console.log("Game event:", msg.event, msg.data);
}
};| Command | Description |
|---|---|
e2e4 |
Move piece (from-to notation) |
e7e8Q |
Pawn promotion (append piece letter) |
moves |
List all legal moves |
board |
Show current board |
resign |
Resign the game |
draw |
Claim a draw (if eligible) |
history |
Show move history |
json |
Game state as JSON |
help |
Show help |
quit |
Quit |
CheckAI checks for new versions on startup. Update manually:
checkai updatecheckai/
├── build.rs # Ensures web/dist/ exists for rust-embed
├── Cargo.toml # Dependencies and project metadata
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # Container orchestration
├── .github/workflows/
│ ├── ci.yml # CI (fmt, clippy, test, build)
│ ├── release.yml # Release (binaries + Docker image)
│ └── docs.yml # Documentation → GitHub Pages
├── scripts/
│ ├── install.sh # Installer (Linux / macOS)
│ ├── install.ps1 # Installer (Windows)
│ ├── uninstall.sh # Uninstaller (Linux / macOS)
│ └── uninstall.ps1 # Uninstaller (Windows)
├── docs/ # VitePress documentation site
├── locales/ # i18n YAML files (8 languages)
├── wasm/ # WebAssembly crate (wasm-pack)
│ ├── Cargo.toml # WASM crate manifest
│ └── src/
│ ├── lib.rs # WASM bindings (game mgmt, export, board)
│ └── search.rs # Search with web-time::Instant
├── npm/ # npm package (@josunlp/checkai)
│ ├── package.json # Scoped to GitHub Packages
│ ├── bin/checkai.mjs # Node.js CLI entry point
│ ├── src/index.mjs # Library API exports
│ └── README.md # npm package documentation
├── web/ # TypeScript Web UI (bQuery + Tailwind + Vite)
│ ├── src/ # 12 TypeScript source modules
│ ├── dist/ # Vite production build (embedded into binary)
│ └── index.vite.html # Vite HTML entry point
└── src/
├── main.rs # Entry point, CLI, server setup
├── types.rs # Core types (pieces, board, JSON protocol)
├── movegen.rs # Move generation and validation
├── game.rs # Game state management
├── api.rs # REST API handlers + OpenAPI
├── ws.rs # WebSocket API + broadcaster
├── storage.rs # Persistent storage (zstd compression)
├── export.rs # Export (text, PGN, JSON)
├── eval.rs # PeSTO evaluation + king safety + mobility
├── search.rs # Alpha-beta (PVS, TT, LMR, NMP, SEE, futility)
├── analysis.rs # Analysis orchestrator (async job queue)
├── analysis_api.rs # Analysis REST endpoints
├── opening_book.rs # Polyglot opening book reader
├── tablebase.rs # Syzygy endgame tablebase interface
├── zobrist.rs # Zobrist hashing
├── terminal.rs # Terminal interface
├── i18n.rs # Internationalization helpers
└── update.rs # Self-update + version checkFull documentation at https://josunlp.github.io/checkai/
| Section | Description |
|---|---|
| Getting Started | Installation and first steps |
| REST API | Full REST endpoint reference |
| WebSocket API | Real-time bidirectional API |
| Analysis API | Deep game analysis endpoints |
| Agent Protocol | JSON protocol for AI agents |
| Chess Rules | FIDE 2023 rule reference |
| Architecture | Module overview and design decisions |
| npm Package | WASM npm package API reference |
The raw agent protocol specification is also available at docs/AGENT.md.