chess diagnostic with claude & stockfish
  • Python 88.9%
  • CSS 4.4%
  • HCL 2.5%
  • Shell 1.9%
  • Dockerfile 1.7%
  • Other 0.6%
Find a file
chipster d86828ce62
Some checks failed
Build & push Docker image / build (push) Failing after 3m51s
fix(entrypoint): ne pas écraser .credentials.json si c'est un symlink
Quand l'infra déploie chessia avec claude_credentials_link_to_host_user,
data/claude/.credentials.json devient un symlink vers le fichier du compte
chipster du host. Source de vérité = host claude CLI qui refresh les tokens
en continu. L'entrypoint ne doit PAS le réécrire (risque d'écraser des
refresh frais ou de write-faillir si le mount sous-jacent est RO).
2026-05-08 23:09:50 +02:00
.forgejo/workflows ci: container catthehacker (docker-cli préinstallé pour login-action) 2026-04-21 19:43:35 +02:00
chessia fix(notify): logger les erreurs de publish ntfy au lieu de tout swallow 2026-05-08 21:03:14 +02:00
docker fix(entrypoint): ne pas écraser .credentials.json si c'est un symlink 2026-05-08 23:09:50 +02:00
infra/module feat(docker): volume persistant /home/chessia/.claude pour les refresh tokens 2026-04-21 13:22:25 +02:00
tests Initial commit: ChessIA v0.2.4 2026-04-19 20:59:32 +02:00
.dockerignore feat: containerisation — Dockerfile + pipeline Forgejo Actions (v0.3.9) 2026-04-21 12:51:13 +02:00
.env.example feat: auth Basic pour ntfy (self-host) (v0.2.11) 2026-04-19 22:17:54 +02:00
.gitignore chore: nettoyage repo (retrait export.sh + samples PGN, .gitignore étoffé) 2026-04-20 18:54:04 +02:00
CLAUDE.md Initial commit: ChessIA v0.2.4 2026-04-19 20:59:32 +02:00
Dockerfile feat(docker): volume persistant /home/chessia/.claude pour les refresh tokens 2026-04-21 13:22:25 +02:00
pyproject.toml chore: bump 0.3.8 → 0.3.9 (containerisation commit précédent) 2026-04-21 12:51:43 +02:00
README.md feat(docker): volume persistant /home/chessia/.claude pour les refresh tokens 2026-04-21 13:22:25 +02:00

ChessIA

Pipeline d'analyse pédagogique de parties d'échecs en français, cible FIDE 1600+.

Flux : PGN → Stockfish (multi-PV, seuils adaptatifs) → détection des coups critiques → Claude (routage Opus/Sonnet selon sévérité) → rapport HTML interactif avec graphique d'éval, mini-viewers et explications structurées.

Deux modes d'utilisation :

  • CLI (chessia partie.pgn -o rapport.html)
  • Web (chessia-web) — formulaire d'upload + historique + suivi live + notifications push

Installation

python -m venv .venv && source .venv/bin/activate
pip install -e ".[web]"                    # extras [web] pour le serveur
cp .env.example .env                       # renseigner STOCKFISH_PATH

Prérequis

  • Stockfish UCI avec NNUE (tablebases recommandées). vendor/stockfish/stockfish par défaut.
  • CLI claude (Claude Code) authentifiée via l'abonnement Max — le pipeline passe par claude -p (pas l'API Anthropic).

Variables d'environnement (.env)

Variable Défaut Rôle
STOCKFISH_PATH Chemin du binaire UCI (obligatoire)
STOCKFISH_THREADS 3 Threads Stockfish (Pi4 = 3, laisser 1 core pour l'OS)
STOCKFISH_HASH_MB 512 Hash table Stockfish en Mo
CLAUDE_CONCURRENCY 3 Appels Claude parallèles
CLAUDE_MODEL_BLUNDER opus Modèle pour blunders / occasions manquées
CLAUDE_MODEL_FORCE Override tous les modèles (debug)
CHESSIA_REPORTS_DIR ~/.chessia-reports Dossier des rapports
CHESSIA_WEB_HOST / CHESSIA_WEB_PORT 127.0.0.1:8000 Écoute du serveur web
NTFY_SERVER / NTFY_TOPIC / NTFY_USER / NTFY_PASSWORD Notifs push début/fin de diag (voir ntfy.sh)

Usage

CLI

chessia partie.pgn -o rapport.html                   # analyse les deux camps
chessia partie.pgn --side white -o rapport.html      # limiter au côté Blancs

Serveur web

chessia-web                   # uvicorn sur 127.0.0.1:8000
  • / : formulaire d'upload (fichier PGN ou coller du texte, drag & drop)
  • /history : tableau des diagnostics avec filtres et polling live
  • /watch/<id> : suivi live d'un diag en cours (progress bar + timeline + logs colorés)
  • /report/<id> : rapport final avec TOC sticky, coups critiques repliables, export PDF
  • /example : redirige vers un rapport terminé aléatoire (démo sans uploader son PGN)

Régénérer des rapports existants

Quand l'UI évolue, régénérer les rapports terminés avec le nouveau template (le numéro de version d'origine est préservé dans le rapport) :

python -m chessia.regen                    # tous les jobs done
python -m chessia.regen --dry-run          # aperçu
python -m chessia.regen --job <id>         # un seul job

Le script crée un report.html.bak.<timestamp> avant chaque overwrite.

Pipeline

Phase 1 — Stockfish scan

Analyse chaque demi-coup avec multipv=2 (détecte les coups brillants : meilleur coup dans une position où les candidats sont proches).

Phase 2 — Re-analyse des coups critiques

Pour chaque coup flaggé blunder / mistake / inaccuracy / missed_win, ré-évalue avec multipv=3 pour fournir les 3 candidats à Claude.

Phase 3 — Explications Claude

Pour chaque coup critique, prompt structuré en 5 sections :

  1. Diagnostic — nom précis du motif tactique/positionnel
  2. Analyse comparative des 3 candidats Stockfish
  3. Ligne principale détaillée sur 6 à 10 demi-coups avec éval [+0.53], [+M3]
  4. Raison profonde (principe échiquéen violé)
  5. Exercice d'entraînement ciblé

Le prompt est enrichi par phase (ouverture / milieu / finale) et inclut :

  • Code ECO + nom d'ouverture (détection offline via chessia/data/eco.json)
  • Features positionnelles calculées (pions passés/doublés/isolés, paire de fous, contrôle centre)
  • Top 5 moments de tension de la partie
  • 15 derniers demi-coups d'historique

Catégories de coups

Catégorie Seuil NAG
blunder ≥ 200 cp de perte ?? ($4)
mistake ≥ 100 cp ? ($2)
inaccuracy ≥ 50 cp ?! ($6)
missed_win gain décisif lâché (+300 → <150) !? ($5)
brilliant meilleur coup dans position contestée (gap top1-top2 ≤ 60 cp) !! ($3)

Les seuils sont adaptatifs : ils montent avec la décisivité de la position via une sigmoid win_prob(cp) — moins de faux positifs sur positions déjà gagnées/perdues.

Rapport HTML

  • Autonome : styles inlinés, échiquier interactif via CDN lichess-pgn-viewer
  • Graphique d'éval SVG de la partie avec marqueurs colorés sur les coups notables
  • Coups critiques repliables (<details> natifs), sommaire sticky à gauche
  • Navigation clavier ↑ ↓ / j k pour sauter de coup en coup
  • Mini-viewer Lichess par bloc critique avec la variante Stockfish (PV 14 demi-coups)
  • Cases mentionnées par Claude mises en surbrillance sur le diagramme
  • Export PDF via window.print() (mise en page impression optimisée)
  • Light mode (toggle ☾/☀ avec persistance localStorage)

Architecture

chessia/
├── __main__.py            # CLI entrypoint
├── web.py                 # Serveur FastAPI (historique, watch, notifs, regen)
├── pipeline.py            # Orchestration : engine + claude + rapport
├── engine.py              # Wrapper Stockfish (python-chess UCI)
├── critical.py            # Détection (blunder/mistake/inaccuracy/missed_win/brilliant)
├── explain.py             # Appels Claude via subprocess claude -p
├── cache.py               # Cache FS des explanations (sha256 fen|ply|model)
├── eco.py                 # Détection offline ECO + nom d'ouverture
├── position_features.py   # Features positionnelles (pions, roi, centre, fous)
├── progress.py            # ETA (EMA) + cancel/pause contextvars
├── report_html.py         # Rendu rapport (graphique, TOC, mini-viewers, print CSS)
├── board_svg.py           # Diagramme SVG avec highlighted squares
├── regen.py               # Script CLI regen rapports (avec backup)
├── data/eco.json          # Base ECO (3700 entrées, lichess-org/chess-openings, CC0)
└── static/                # Design system partagé (styles.css + theme.js)

Voir CLAUDE.md pour les conventions de développement et les règles non-évidentes depuis le code.

Déploiement Docker

Image multi-stage (build Stockfish from source + Python + Node.js pour Claude Code CLI).

Build local

docker build -t chessia:dev .

Run

docker run -d \
  --name chessia \
  -p 8000:8000 \
  -v chessia-reports:/data/reports \
  -v chessia-cache:/data/cache \
  -v chessia-claude:/home/chessia/.claude \
  -e CLAUDE_CREDENTIALS_JSON="$(cat ~/.claude/.credentials.json)" \
  -e NTFY_SERVER=https://ntfy.exemple.com \
  -e NTFY_TOPIC=chessia-diag \
  -e NTFY_USER=chessia \
  -e NTFY_PASSWORD=... \
  git.greil.fr/chipster/chessia:latest

Volumes à persister

Mount Contenu
/data/reports Rapports HTML + meta.json des diagnostics
/data/cache Cache des explications Claude (évite les re-appels)
/home/chessia/.claude OAuth refresh tokens Claude Code (mis à jour automatiquement par le CLI). Persister ce volume évite d'avoir à ré-injecter CLAUDE_CREDENTIALS_JSON à chaque redémarrage tant que le refresh token reste valide

Secrets de run

  • CLAUDE_CREDENTIALS_JSON : contenu du fichier ~/.claude/.credentials.json de l'utilisateur Claude Code Max. L'entrypoint l'écrit dans /home/chessia/.claude/.credentials.json au démarrage.
  • NTFY_* : optionnel, pour les push mobiles (voir section Env ci-dessus).

Déploiement via tofu-maison

Le repo expose un module OpenTofu dans infra/module/ compatible avec le pattern du repo tofu-maison (provider kreuzwerker/docker en SSH vers le LXC cible).

Côté tofu-maison, dans docker/services.tf :

module "chessia" {
  source = "git::ssh://git@git.greil.fr/chipster/chessia.git//infra/module?ref=main"

  image         = "git.greil.fr/chipster/chessia:latest"
  external_port = 8000

  claude_credentials_json = var.chessia_claude_credentials_json
  ntfy_server             = "https://ntfy.exemple.com"
  ntfy_topic              = "chessia-diag"
  ntfy_user               = "chessia"
  ntfy_password           = var.chessia_ntfy_password
}

Puis tofu -chdir=docker init && tofu -chdir=docker apply.

Un workflow .forgejo/workflows/deploy.yml dans ce repo trigger automatiquement un apply de tofu-maison quand :

  • le module infra/module/** change (push main)
  • le build Docker termine avec succès (nouveau tag à tirer)
  • déclenché manuellement depuis l'UI Forgejo

Secret repo supplémentaire requis :

Secret Usage
TOFU_MAISON_TOKEN Token Forgejo avec write:repository sur mat/tofu-maison (pour déclencher son workflow apply.yml)

CI Forgejo Actions

Workflow dans .forgejo/workflows/docker-build.yml :

  • Trigger : push sur main, tag v*, ou déclenchement manuel
  • Build : image AMD64 (linux/amd64)
  • Push : git.greil.fr/chipster/chessia avec tags sha-<short>, latest (main), <version> (tags semver)
  • Cache layers : stockées en registry (:buildcache)
  • Runner : self-hosted

Secrets Forgejo à configurer dans les settings du repo :

Secret Usage
REGISTRY_USERNAME User pour push vers le registry Forgejo
REGISTRY_TOKEN Token d'accès avec scope write:package

Licence

Code : usage personnel. data/eco.json dérivé de lichess-org/chess-openings sous CC0.