Open-source project
pychess/pychess avatar
pychess/pychess

PyChess is a GTK chess client written entirely in Python, engines and all

PyChess - desktop chess client for Linux/Windows/macOS

817 stars226 forksPythonGPL-3.0

At a glance

What is it?
PyChess is a free chess client for Linux, Windows and macOS, developed primarily for GNOME and written from the user interface down to the chess engine in Python. It supports UCI and CECP engines, online play over FICS, and a range of variants, and it ships as a source checkout you run with uv rather than only as a binary.
Who is it for?
PyChess fits a GNOME desktop user who wants a chess client that is genuinely open source, scriptable and free, and it fits a developer who wants to read or modify a chess application end to end in one language rather than a bundled binary. It does not fit a user on a non-GNOME Linux desktop, or a Windows or macOS user who wants a one-click installer, because the platform support is uneven and the macOS path depends on the Homebrew setup in INSTALL_MACOS.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One language from the interface down to the engine

The distinguishing claim in the README is that the entire PyChess codebase, from the user interface to the chess engine, is written in Python, and the project is released under the GNU Public License.

That is unusual for a desktop application. A GTK chess client would normally be a C or Vala shell around a Python or C engine, with a build step and a native toolchain to install. PyChess inverts that: the GUI toolkit is bound through PyGObject rather than being the primary language, and the game logic and the built-in engine are Python as well.

The practical consequence is that the whole application is readable, hackable and scriptable by one person. There is no boundary where the interesting logic stops and native code begins, which is the usual reason a desktop application ends up hard to extend.

The project is a GTK client developed primarily for GNOME but compatible with various Linux desktop environments, and its stated goals include following the GNOME Human Interface Guidelines, offering an interface suitable for both beginners and experienced players, and letting users play against the computer, find the best moves with Hint Mode and reach a range of chess engines.

The project homepage is pychess.github.io, the licence is GPL-3.0 with a LICENSE file at the root, and the pyproject.toml records the licence as GPL-3.0-or-later.

Engines, difficulty levels and a built-in fallback

The engine support is the core of the feature list, and it comes in two protocols.

PyChess supports UCI and CECP chess engines with 8 different difficulty levels. UCI is the protocol that modern engines like Stockfish speak, and CECP is the older Chess Engine Communication Protocol used by engines such as GNU Chess. Supporting both means you can point it at almost any engine binary that already exists, which is a much larger ecosystem than the handful of engines that ship with any given client.

There is also a built-in Python chess engine. That matters more than it sounds. When you install the client and want to play one game immediately, you do not have to find, download and configure an external engine first. It also gives you a reference implementation to read when you want to understand how the client talks to an engine.

Hint Mode draws arrows on the board indicating the best move based on the chosen analysis engine. That is the feature that turns a chess client into a training tool rather than only an opponent, and it is listed separately in the README because it depends on the analysis engine rather than on the game engine.

The other feature-level details worth knowing: the board is resizable, there is pre-drag support so you can pick a piece up before moving it, there are move and capture sounds and animations, and games can be undone, paused and resumed. The built-in opening book is there too.

Variants are supported including Atomic, Crazyhouse, Fischer Random, also called Chess 960, and more.

Files, formats and the online mode

PyChess handles the standard interchange formats, with compatibility for PGN, EPD and FEN.

PGN is the game record format you export to a study file or import from a tournament. EPD is the position description format, and FEN is the board position notation. Supporting all three means the client can be dropped into an existing workflow rather than being a place where positions live.

The online side is FICS, the Free Internet Chess Server, with Timeseal support. Timeseal is the client side of the protocol that pipes a move over a telnet connection rather than sending it in the clear, so a game on FICS does not leak the move over the wire. FICS is an old server with a specific audience, and the README positions it as the online play option, with logging in and playing people from around the world.

The build system also reflects that chess tooling is a first-class use case. There are scripts called pgn2ecodb.py, pgn2ecodb.sh and pgn2ecodb-win.bat, which is the pattern for converting a PGN collection into an engine opening database, alongside create-engine.sh and create-engine-win.bat for building engines, a built-in opening book in pychess_book.bin, and a pgn2ecodb step in the packaging scripts.

The repository also carries a learn directory, which is where the built-in tutorial content lives, and a flags directory, plus lang for translations and a theme preview script for the board and piece assets.

Running from a checkout with uv

The README covers both the packaged path and the development path, and the development path is where the project is most specific.

For end users, the instruction is to visit the PyChess download page on GitHub, download the latest release for the platform, and follow the platform instructions, with the macOS case pointing at the Homebrew based setup in INSTALL_MACOS. On Linux you launch it from the application menu or run pychess in the terminal, on Windows you double-click the executable, and on macOS you run ./macos/run.sh from a checkout or pychess if it is installed.

For contributors, the setup is a clone, a system package step and a dependency install.

bash
git clone https://github.com/your-username/pychess.git
cd pychess

Python 3.11 or newer is required, and the GTK and GObject system packages have to be installed for your platform, with INSTALL holding the Debian and Ubuntu package list and INSTALL_MACOS the Homebrew equivalents. Dependencies are installed with uv.

bash
uv sync --group dev

A plain pip workflow is offered as an alternative, with the pinned requirements.

bash
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

And then the client runs from the project root.

bash
uv run python pychess

The uv.lock file is committed, so the dependency versions are pinned. The requirements.txt that the pip path uses pins the same versions, with pexpect, psutil, pycairo, PyGObject, SQLAlchemy and websockets as the direct dependencies and pytest as the test-only one.

The reason uv matters here is that PyGObject needs a system GTK stack behind it, which pip cannot install. So the system packages are the hard part of setup, and the Python-level dependencies are the easy part.

Tests, lint and type checking, all through uv

The contribution workflow is unusually explicit about tooling, which is a good sign for a project with this many contributors.

Tests use unittest for the main suite, run through the testing directory.

bash
uv run python -m unittest discover -s testing -p "*.py" -v

Lint and format are handled by Ruff, and the type check is Pyright, described as being configured as a gradual baseline.

bash
uv run --only-group dev ruff check .
uv run --only-group dev ruff format .
bash
uv run --only-group dev pyright

The only-group dev flag is the interesting part. It runs the command with just the dev dependency group installed, so the lint and type check tools do not need to be in the runtime environment. The ruff configuration in pyproject.toml sets a line length of 88, targets py311, points src at lib and testing, and selects the E, F and UP rule sets, which is the pycodestyle error set, pyflakes and pyupgrade.

Pyright being a gradual baseline rather than a full strict check is the honest way to introduce a type checker into a codebase of this size without rewriting it. The dependency group declares pytest, pyright and ruff, while the runtime dependencies stay separate.

The project also uses pre-commit, indicated by the badge in the README and the .pre-commit-config.yaml file at the root, so a lot of the lint enforcement happens before a reviewer sees the change.

Where the packaging shows the seams

The setup.py and the repository layout reveal the parts of PyChess that are not the chess client.

Windows packaging is handled with cx_Freeze, and the script exits with an error if that import fails. It also checks for PyGObject on Windows and, if it is missing, prints a message pointing at a SourceForge page for a Windows build of pygobject and exits. That is a hard dependency on a third party distribution channel, and it is the clearest sign in the repository that the Windows story is the least smooth.

The setup.py also does something specific and useful: it looks for the gettext msgfmt binary, first with shutil.which and then through the Homebrew prefix including the keg-only paths, so that translations can be compiled on a Mac where gettext is not on the default PATH. The .tx directory at the root is the Transifex configuration, and the TRANSLATORS file at the root credits the people doing that work. There is a lang directory for the translation files, a create_template.po.sh script, and the theme preview scripts.

Packaging for Linux is scripted too, with create_deb.sh, create_rpm_py312.sh, a debian directory, stdeb.cfg and a pychess-engine.spec file, alongside pychess.desktop and pychess.metainfo.xml for the desktop entry and the appstream metadata. The macOS directory holds run.sh and the Homebrew path, and the top level pychess script is what the setuptools configuration installs as a script file.

None of that is glamorous, but it is the part that decides whether the project is usable on a machine other than the developer's, and it is spread across a dozen scripts with Windows and Unix variants for each.

Where PyChess is the wrong tool

The first limitation is the desktop environment. This is a GTK client developed primarily for GNOME, and it targets the X11 Applications :: GTK classifier with an Operating System :: POSIX entry in the metadata. On a modern Wayland-only session, or on a desktop where GTK is not what your toolkit integration expects, you are outside the supported path. The project does not claim a native Windows or macOS client of the same quality; the Windows path depends on a third party PyGObject build and the macOS path on Homebrew.

The second limitation is that the strongest features depend on things outside the client. Hint Mode needs an analysis engine, strong play needs a strong UCI engine, and the opening book is a file rather than a computed opening tree. The built-in Python engine is there so the client is usable immediately, but nobody would choose it for serious analysis.

The third is the language trade-off itself. Writing everything in Python is what makes the codebase approachable, and it also means the parts that need to be fast, such as engine communication and any per move computation, are not fast by construction. The pexpect dependency is a hint here, since it is how you talk to a process over a pipe, and psutil is there for process inspection.

The fourth is the version 1.x maturity. The releases are 1.0.6 on 2025-09-13, 1.1.0 on 2025-09-22 and 1.2.0 on 2026-09-19, with the last push on 2026-10-19, so the project is active, but the version number is still in the 1.x range and the classifiers call it Development Status :: 3 - Alpha. The version is dynamic, read from the pychess.VERSION attribute in lib, so the number comes from the source rather than from packaging metadata.

How it compares with a board game site or a scripted engine

The obvious alternative is a website. Chess.com and Lichess give you an opponent instantly, they work on every platform, and they need no installation, no engine configuration and no system packages.

What you get in exchange for that is a client you cannot modify. A website decides which analysis it offers, whether it shows an engine line, whether it works offline, and what it does with your games. PyChess gives you the full control surface: any UCI or CECP engine you can find, your own opening database, your own PGN files, local play with no network at all.

For a player who wants to analyse with their own engine and keep their games on their own disk, that difference is the whole argument. For anyone who just wants to play a game, the website wins by a wide margin and PyChess is a project to install.

The other alternative is running an engine directly. If you only want Stockfish to think and you do not want a GUI at all, the engine binary is faster to start, easier to script and lighter to run. PyChess adds a board, a move list, undo, pause, variants and a FICS client, none of which an engine has.

There is also the scripting angle, which is where the Python choice pays off. Because the whole application is Python, the boundary between the client and a script you write is thin. A project like this is not primarily aimed at production chess servers; it is aimed at people who want to understand, extend or automate a chess program they can read all the way through.

Editorial conclusion

PyChess fits a GNOME desktop user who wants a chess client that is genuinely open source, scriptable and free, and it fits a developer who wants to read or modify a chess application end to end in one language rather than a bundled binary. It does not fit a user on a non-GNOME Linux desktop, or a Windows or macOS user who wants a one-click installer, because the platform support is uneven and the macOS path depends on the Homebrew setup in INSTALL_MACOS. Before adopting, read INSTALL and INSTALL_MACOS for the GTK and GObject system packages your platform needs, check that your Python is 3.11 or newer since pyproject.toml requires it, and try the built-in engine first so you can tell whether a problem is the client or a third party engine you installed.

Frequently asked questions

What is PyChess and which platforms does it support?

PyChess is a free chess client developed primarily for GNOME but compatible with various Linux desktop environments, and it supports Linux, Windows and macOS. The README states that the entire codebase, from the user interface to the chess engine, is written in Python.

Which chess engines can I use with PyChess?

PyChess supports UCI and CECP chess engines with 8 different difficulty levels, and it also includes a built-in Python engine so you can play without configuring an external one. Hint Mode arrows indicate the best move based on the chosen analysis engine.

How do I run PyChess from source?

Install Python 3.11 or newer and the GTK and GObject system packages for your platform, then run uv sync --group dev in the checkout and launch with uv run python pychess. A pip alternative is documented, using python -m venv venv, source venv/bin/activate and pip install -r requirements.txt.

Does PyChess support online play and different chess variants?

Yes. Online play is supported on FICS, the Free Internet Chess Server, with Timeseal support. Variants include Atomic, Crazyhouse and Fischer Random, also known as Chess 960, and the client handles PGN, EPD and FEN files.

How do I run the PyChess tests and linters?

The main suite uses unittest, run with uv run python -m unittest discover -s testing -p "*.py" -v. Ruff handles linting and formatting with uv run --only-group dev ruff check . and uv run --only-group dev ruff format ., and Pyright is run with uv run --only-group dev pyright.

Official sources

  1. License: GPL-3.0
  2. Project website
  3. pychess/pychess on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pychess-pychess.svg)](https://hysenlabs.com/projects/pychess-pychess)

Was this useful?