TUI chess in Java — play against your choice of AI engines in your terminal.
./scripts/chess.sh playThis builds the JVM distribution if needed, then launches the game.
Install the native binary via Homebrew:
brew tap d-led/homebrew-d-led
brew install console-chessOn Windows, install via Chocolatey:
choco install console-chessSee the package at Chocolatey.
Pre-built native binaries from the latest main build:
| Platform | Download |
|---|---|
| Linux x64 | console-chess-linux |
| macOS arm64 | console-chess-macos-arm64 |
| Windows x64 | console-chess-windows.exe |
Unzip, make executable (chmod +x console-chess), then run ./console-chess.
On Windows, run the native binary from Windows Terminal (the Windows 11 default) or a VT-enabled console:
.\console-chess.exeThe binary bundles JLine's JNI terminal provider, so it needs no extra install.
The board is drawn through the Unicode console API, so chess glyphs render
regardless of the console code page — no chcp change required. If you run it
in a legacy conhost window and the pieces show as garbage, switch the console
font to a Unicode one (e.g. Cascadia Mono) or use Windows Terminal.
| Key | Action |
|---|---|
Arrows / hjkl |
Move cursor |
| Enter / Space | Select piece, confirm move |
q |
Quit |
While the engine is searching, the status line shows ⌛ thinking ⌛; the board keeps drawing
meanwhile, and moves are ignored until it answers.
console-chess --version # or -VThe version is resolved at build time in priority order: an explicit
-Pversion=x.y.z (the release workflow passes the tag), then the vX.Y.Z git
tag on the current commit, then 0.0.0-SNAPSHOT.
Four engines behind a common ChessEngine interface. Select with -e:
./scripts/chess.sh play # default: noise, medium
./scripts/chess.sh play -e stockfish -d hard # further args go to the app
console-chess -e noise -d easy # ELO ~750
console-chess -e noise -d hard # ELO ~1250
console-chess -e adam # ELO ~1600, minimax + piece-square tables
console-chess -e greedy # ELO ~500, captures everything
console-chess -e stockfish -d easy # Stockfish capped at ELO 1350
console-chess -e stockfish -d hard # Stockfish capped at ELO 2800
console-chess -e noise -d medium -s 42 # reproducible with seedThe stockfish engine runs the Stockfish chess engine as a
subprocess over the UCI protocol. brew install console-chess and choco install console-chess
install Stockfish automatically (on Homebrew, add --without-stockfish to skip it); when running
the raw binary you can install it separately with brew install stockfish. Stockfish does not
need to be present for the other engines.
| Engine | ELO | Description |
|---|---|---|
noise (default) |
750–1250 | Material + center + mobility + configurable noise |
adam |
~1600 | Minimax search + piece-square positional tables |
greedy |
~500 | Always captures highest-value piece |
stockfish |
1350–2800 | Stockfish via UCI subprocess, Elo-limited by -d |
All commands live in ./scripts/chess.sh:
./scripts/chess.sh play # build if needed, then run (JVM); args go to the app
./scripts/chess.sh build # build JVM distribution only
./scripts/chess.sh test # run all tests
./scripts/chess.sh native # build native binary (GraalVM)
./scripts/chess.sh nrun # build native if needed, then run
./scripts/chess.sh ci # test + native build./scripts/update-dependencies.sh lists dependencies and Gradle plugins with newer versions and can
write them into build.gradle.kts:
./scripts/update-dependencies.sh # list updates to the latest release versions
./scripts/update-dependencies.sh --milestone # include milestone / pre-release versions
./scripts/update-dependencies.sh --check # exit 1 when updates are available (for CI)
./scripts/update-dependencies.sh --apply # write the updates, then run the testsMajor updates (JUnit 5 -> 6, JLine 3 -> 4) usually need code changes: --apply still writes them,
and the test run tells you whether they worked. Nothing is committed, so review the diff of
build.gradle.kts afterwards.
Dependabot covers the same ground on GitHub, weekly and without anyone asking: one PR for Gradle
dependencies and build plugins (patch and minor grouped, majors on their own) and one for the
actions the workflows use — see .github/dependabot.yml. JLine major updates are ignored there on
purpose, for the reason recorded in build.gradle.kts. The script above is the local alternative,
and it additionally reports the Gradle wrapper version.
./scripts/tui-smoke-test.py <binary> runs the TUI in a real terminal (a pty on Unix, a ConPTY on
Windows via pywinpty) and fails when the board does not render, when JLine falls back to its dumb
terminal, or when the app does not quit on q. CI runs it against the native binary on Linux, macOS
and Windows, which is the only place a terminal provider that cannot load on Windows shows up.
./gradlew installDist && python3 scripts/tui-smoke-test.py build/install/console-chess/bin/console-chessProduces a dependency-free binary. Requires GraalVM — set GRAALVM_HOME or the script defaults to:
/Library/Java/JavaVirtualMachines/graalvm-25.jdk/Contents/Home
GRAALVM_HOME=/path/to/graalvm ./scripts/chess.sh native
./build/native/nativeCompile/console-chesssrc/main/java/chess/
├── ChessApp.java # Entry point
├── engine/
│ ├── Color.java # OUTLINE / FILLED
│ ├── Piece.java / PieceType.java
│ ├── Square.java / Move.java
│ ├── Board.java # 8×8 grid + move execution
│ ├── MoveGenerator.java # Legal move generation + check detection
│ ├── Fen.java # Position → FEN serialization
│ └── GameState.java # Turn management + game status
├── ai/
│ ├── ChessEngine.java # Interface: name() + selectMove()
│ ├── NoiseEngine.java # ELO 750-1250 (default)
│ ├── AdamEngine.java # ELO ~1600, minimax + piece-square tables
│ ├── GreedyEngine.java # ELO ~500, captures everything
│ ├── StockfishEngine.java # Stockfish via UCI subprocess (UciChannel)
│ ├── UciChannel.java # stdio abstraction for UCI engines
│ └── SubprocessUciChannel.java # ProcessBuilder-backed UciChannel
└── tui/
├── ChessModel.java # tui4j Model: board, cursor, piece selection
└── virtual/
├── VirtualTerminal.java # Captures rendered output for testing
└── GamePrinter.java # Renders GameState to VirtualTerminal
- Java 21 + Gradle 8.14 (native image built with GraalVM 25)
- tui4j — terminal UI (Elm Architecture)
- JUnit 5 + AssertJ — unit tests
- ApprovalTests — snapshot testing
- GraalVM — optional native binary
AdamEngine is a Java port of the evaluation and search logic from
adam-mcdaniel/chess-engine
(MIT license). The piece-square positional tables and negamax minimax
search are adapted from that project.

