v1.0.1 — Real-time chess analysis sidekick with anti-detection engine.
python -m chess_coach — Desktop GUI (PyQt6) ·
python -m chess_coach web — Web UI (FastAPI)
Chess Coach is a dual-mode chess analysis application that sits alongside your play on chess.com or lichess. It runs Stockfish 18 under the hood and feeds you the top 5 engine lines — but through an anti-detection humanizer that introduces calibrated, human-like imperfections so the advice looks natural.
The project enforces zero-tolerance code quality: 95 tests, strict type-checking, and automated linting across 6 CI jobs.
| Core | Details |
|---|---|
| Stockfish 18 MultiPV | Top 5 lines with evaluation, principal variation, depth 18 |
| Anti-Detection Humanizer | Progressive ELO (800–2800), calibrated error injection, time-pressure modelling, complexity detection |
| 471 ECO Openings | A00–E99, longest-prefix matching, real-time naming |
| Dual Mode | Desktop (PyQt6) / Web (FastAPI) — same core, identical behaviour |
| Evaluation Visualizer | Eval bar, colour-coded labels, best-move arrow overlay |
| Undo / Redo | Full move stack with board state caching |
| PGN Import / Export | Standard PGN parse, replay, export with custom headers |
| Sound Feedback | Programmatic WAV generation (60ms sine wave) |
The humanizer is the core differentiator. Rather than returning raw Stockfish output, it applies a calibrated error model:
| Mechanism | Behaviour |
|---|---|
| Progressive ELO | Starts at configurable target (default 1500), climbs 20–50 per game, 15% chance of dip, capped at target+500 |
| Error Injection | 0.5% blunder / 3% mistake / 10% inaccuracy — each with distinct move-selection strategies |
| Accuracy Calibration | Kaufman-study formula: acc(ELO) = (ELO/100 + 64) / 100 — from 72% (800 ELO) to 92% (2800 ELO) |
| Complexity Detection | Endgame (≤16 pieces) and book lines (≤8 fullmoves, ≥28 pieces) treated as non-complex; sharp positions get +15–50 ELO and 1.6×–2× error rate multipliers |
| Risk Detection | Coherence scoring via accuracy variance — flags sessions that deviate from human-like patterns |
| Session Persistence | Personality survives across games; warm-up period (5 games) for data accumulation |
# Clone + install
git clone https://github.com/krsnaSuraj/chess-coach.git
cd chess-coach
pip install -r requirements.txt
# Place Stockfish 18 binary at project root as stockfish.exe
# (or configure a custom path in config.yaml)
# Desktop mode
python -m chess_coach
# Web mode — serves at http://localhost:8000
python -m chess_coach web
# Custom port
python -m chess_coach web 8080FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt . && pip install -r requirements.txt
COPY . .
# Mount stockfish binary at runtime
CMD ["python", "-m", "chess_coach", "web"]docker build -t chess-coach .
docker run -p 8000:8000 -v /path/to/stockfish:/app/stockfish.exe chess-coachAll settings live in config.yaml at the project root.
engine:
path: "stockfish.exe" # Stockfish binary path
threads: 2 # CPU threads for analysis
hash: 64 # Hash table size (MB)
movetime: 2000 # Desktop mode: ms per move
web_movetime: 2.0 # Web mode: seconds per move
multipv: 5 # Principal variation count
humanizer:
enabled: true # Set false for raw Stockfish output
target_elo: 1500 # Starting skill level
personality: balanced # balanced | aggressive | solid
error_injection:
blunder_rate: 0.005 # 0.5% chance of hanging material
mistake_rate: 0.03 # 3% chance of suboptimal move
inaccuracy_rate: 0.10 # 10% chance of minor imprecision
session:
warmup_games: 5 # Games before risk detection activates
persist_personality: true
display:
dark_square: "#B58863" # Board colour scheme
light_square: "#F0D9B5"
arrow_color: "#00FF00"
arrow_opacity: 0.6src/chess_coach/ # 15 modules
├── __init__.py # Package version (1.0.1)
├── __main__.py # CLI: desktop / web / port dispatch
├── config.py # YAML config loader, port allocation, IP resolver
├── game_controller.py # Thread-safe board state machine + undo/redo
├── engine_handler.py # Stockfish UCI wrapper with QThread isolation
├── server.py # FastAPI server — 6 REST endpoints
├── humanizer.py # Anti-detection engine (380 lines)
├── chess_board.py # PyQt6 interactive board widget (drag-drop, SVG, animation)
├── coach_dashboard.py # Desktop eval bar + feedback panel
├── main_window.py # Desktop orchestrator (signal/slot wiring)
├── eco_handler.py # Longest-prefix ECO opening matcher
├── eco_data.py # 471 opening entries (ECO A00–E99)
├── pgn_handler.py # PGN parse / export / replay
├── promotion_dialog.py # Underpromotion picker
└── sound_manager.py # Programmatic WAV generation + playback
static/ # Web frontend
├── index.html # SPA with colour picker, drag-drop, arrow overlay
├── chessboard.css # Dark theme board styling
├── js/ # chess.js + chessboard.js + jQuery
├── img/ # Wikipedia-style piece PNGs (12 files)
└── sounds/ # move.wav (generated programmatically)
tests/ # 95 tests across 5 modules
├── test_config.py # 14 — YAML loading, validation, error handling
├── test_eco.py # 13 — database integrity, 50+ opening matches
├── test_game_controller.py # 22 — state machine, undo/redo, game-over detection
├── test_humanizer.py # 27 — ELO calibration, error injection, session metrics
└── test_pgn_handler.py # 19 — parse, export, replay, roundtrip
| Method | Endpoint | Request Body | Response |
|---|---|---|---|
GET |
/api/health |
— | {status, engine_running} |
POST |
/api/start_game |
{"human_is_white": bool} |
UnifiedResponse with opening analysis |
GET |
/api/game_state |
— | Current board + coach analysis |
POST |
/api/human_move |
{"move_uci": str} |
Updated board + opponent analysis |
POST |
/api/undo |
— | Revert to previous state |
POST |
/api/redo |
— | Restore undone state |
All stateful endpoints return UnifiedResponse:
{
"ok": true,
"mode": "coach",
"fen": "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1",
"coach": {
"best_move": "e2e4",
"eval": "+0.37",
"pv": "e2e4 e7e5 g1f3 b8c6",
"depth": 18,
"opening": "[C20] King's Pawn Game",
"label": "You are better",
"eval_color": "#3fb950",
"thinking": ["Depth 18: +0.37"]
}
}Every push runs 8 CI jobs:
| Job | Tools | Config |
|---|---|---|
| Test (×6) | pytest + coverage | Ubuntu/Windows × Python 3.10/3.11/3.12 |
| Lint | ruff 0.15, black, mypy | Strict mode, zero-tolerance |
| Security | bandit + pip-audit | Vulnerability scanning |
ruff check src/ tests/ # zero warnings
black --check src/ tests/ # consistent formatting
mypy src/chess_coach/ # 0 errors across 15 files
pytest tests/ -q --tb=short # 95/95 passedpip install -e ".[test]"
python -m pytest tests/ --cov=chess_coach --cov-report=term-missing- Python ≥ 3.10
- Stockfish 18 binary at project root (or custom path in
config.yaml) - Qt6 (for desktop mode only) — provided by PyQt6
| Mode | Windows | Linux | macOS |
|---|---|---|---|
| Desktop (PyQt6) | ✅ | ✅ (requires libgl1, libegl1) |
❌ (untested) |
| Web (FastAPI) | ✅ | ✅ | ✅ |
1.0.1 — declared in pyproject.toml, __init__.py:__version__, __main__.py docstring.
MIT — see LICENSE.