You can also download the original document from Shredder Chess. This document will contain any updates and examples for my own notes.
There are 3 things to adjust. Skill, move times, and depths. See some source at lichess.
The specification is independent of the operating system. For Windows, the engine is a normal exe file, either a console or "real" windows application.
all communication is done via standard input and output with text commands,
The engine should boot and wait for input from the GUI, the engine should wait for the "isready" or "setoption" command to set up its internal parameters as the boot process should be as quick as possible.
the engine must always be able to process input from stdin, even while thinking.
all command strings the engine receives will end with '\n', also all commands the GUI receives should end with '\n', Note: '\n' can be 0x0d or 0x0a0d or any combination depending on your OS. If you use Engine and GUI in the same OS this should be no problem if you communicate in text mode, but be aware of this when for example running a Linux engine in a Windows GUI.
arbitrary white space between tokens is allowed Example: "debug on\n" and " debug on \n" and "\t debug \t \t\ton\t \n" all set the debug mode of the engine on.
The engine will always be in forced mode which means it should never start calculating or pondering without receiving a "go" command first.
Before the engine is asked to search on a position, there will always be a position command to tell the engine about the current position.
by default all the opening book handling is done by the GUI, but there is an option for the engine to use its own book ("OwnBook" option, see below)
if the engine or the GUI receives an unknown command or token it should just ignore it and try to parse the rest of the string in this line. Examples: "joho debug on\n" should switch the debug mode on given that joho is not defined, "debug joho on\n" will be undefined however.
if the engine receives a command which is not supposed to come, for example "stop" when the engine is not calculating, it should also just ignore it.
The move format is in long algebraic notation. A nullmove from the Engine to the GUI should be sent as 0000. Examples: e2e4, e7e5, e1g1 (white short castling), e7e8q (for promotion)
These are all the command the engine gets from the interface.
uci tell engine to use the uci (universal chess interface), this will be sent once as a first command after program boot to tell the engine to switch to uci mode. After receiving the uci command the engine must identify itself with the "id" command and send the "option" commands to tell the GUI which engine settings the engine supports if any. After that the engine should send "uciok" to acknowledge the uci mode. If no uciok is sent within a certain time period, the engine task will be killed by the GUI.
debug [ on | off ] switch the debug mode of the engine on and off. In debug mode the engine should send additional infos to the GUI, e.g. with the "info string" command, to help debugging, e.g. the commands that the engine has received etc. This mode should be switched off by default and this command can be sent any time, also when the engine is thinking.
isready this is used to synchronize the engine with the GUI. When the GUI has sent a command or multiple commands that can take some time to complete, this command can be used to wait for the engine to be ready again or to ping the engine to find out if it is still alive. E.g. this should be sent after setting the path to the tablebases as this can take some time. This command is also required once before the engine is asked to do any search to wait for the engine to finish initializing. This command must always be answered with "readyok" and can be sent also when the engine is calculating in which case the engine should also immediately answer with "readyok" without stopping the search.
setoption name
register this is the command to try to register an engine or to tell the engine that registration will be done later. This command should always be sent if the engine has sent "registration error" at program startup. The following tokens are allowed:
ucinewgame this is sent to the engine when the next search (started with "position" and "go") will be from a different game. This can be a new game the engine should play or a new game it should analyse but also the next position from a testsuite with positions only. If the GUI hasn't sent a "ucinewgame" before the first "position" command, the engine shouldn't expect any further ucinewgame commands as the GUI is probably not supporting the ucinewgame command. So the engine should not rely on this command even though all new GUIs should support it. As the engine's reaction to "ucinewgame" can take some time the GUI should always send "isready" after "ucinewgame" to wait for the engine to finish its operation.
position [fen
go start calculating on the current position set up with the "position" command. There are a number of commands that can follow this command, all will be sent in the same string. If one command is not sent its value should be interpreted as it would not influence the search.
stop stop calculating as soon as possible, don't forget the "bestmove" and possibly the "ponder" token when finishing the search
ponderhit the user has played the expected move. This will be sent if the engine was told to ponder on the same move the user has played. The engine should continue searching but switch from pondering to normal search.
quit quit the program as soon as possible
id
uciok Must be sent after the id and optional options to tell the GUI that the engine has sent all infos and is ready in uci mode.
readyok This must be sent when the engine has received an "isready" command and has processed all input and is ready to accept new commands now. It is usually sent after a command that can take some time to be able to wait for the engine, but it can be used anytime, even when the engine is searching, and must always be answered with "isready".
bestmove
copyprotection this is needed for copyprotected engines. After the uciok command the engine can tell the GUI, that it will check the copy protection now. This is done by "copyprotection checking". If the check is ok the engine should send "copyprotection ok", otherwise "copyprotection error". If there is an error the engine should not function properly but should not quit alone. If the engine reports "copyprotection error" the GUI should not use this engine and display an error message instead! The code in the engine can look like this TellGUI("copyprotection checking\n"); // ... check the copy protection here ... if(ok) TellGUI("copyprotection ok\n"); else TellGUI("copyprotection error\n");
registration this is needed for engines that need a username and/or a code to function with all features. Analog to the "copyprotection" command the engine can send "registration checking" after the uciok command followed by either "registration ok" or "registration error". Also after every attempt to register the engine it should answer with "registration checking" and then either "registration ok" or "registration error". In contrast to the "copyprotection" command, the GUI can use the engine after the engine has reported an error, but should inform the user that the engine is not properly registered and might not use all its features. In addition the GUI should offer to open a dialog to enable registration of the engine. To try to register an engine the GUI can send the "register" command. The GUI has to always answer with the "register" command if the engine sends "registration error" at engine startup (this can also be done with "register later") and tell the user somehow that the engine is not registered. This way the engine knows that the GUI can deal with the registration procedure and the user will be informed that the engine is not properly registered.
info the engine wants to send information to the GUI. This should be done whenever one of the info has changed. The engine can send only selected infos or multiple infos with one info command, e.g. "info currmove e2e4 currmovenumber 1" or "info depth 12 nodes 123456 nps 100000". Also all infos belonging to the pv should be sent together e.g. "info depth 2 score cp 214 time 1242 nodes 2124 nps 34928 pv e2e4 e7e5 g1f3" I suggest to start sending "currmove", "currmovenumber", "currline" and "refutation" only after one second to avoid too much traffic. Additional info:
option This command tells the GUI which parameters can be changed in the engine. This should be sent once at engine startup after the "uci" and the "id" commands if any parameter can be changed in the engine. The GUI should parse this and build a dialog for the user to change the settings. Note that not every option needs to appear in this dialog as some options like "Ponder", "UCI_AnalyseMode", etc. are better handled elsewhere or are set automatically. If the user wants to change some settings, the GUI will send a "setoption" command to the engine. Note that the GUI need not send the setoption command when starting the engine for every option if it doesn't want to change the default value. For all allowed combinations see the examples below, as some combinations of this tokens don't make sense. One string will be sent for each parameter.
name
type
default
min
max
var
This is how the communication when the engine boots can look like:
GUI engine
// tell the engine to switch to UCI mode uci
// engine identify
id name Shredder
id author Stefan MK
// engine sends the options it can change // the engine can change the hash size from 1 to 128 MB option name Hash type spin default 1 min 1 max 128
// the engine supports Nalimov endgame tablebases
option name NalimovPath type string default
// the engine can switch off Nullmove and set the playing style option name Nullmove type check default true option name Style type combo default Normal var Solid var Normal var Risky
// the engine has sent all parameters and is ready uciok
// Note: here the GUI can already send a "quit" command if it just wants to find out // details about the engine, so the engine should not initialize its internal // parameters before here. // now the GUI sets some values in the engine // set hash to 32 MB setoption name Hash value 32
// init tbs setoption name NalimovCache value 1 setoption name NalimovPath value d:\tb;c\tb
// waiting for the engine to finish initializing // this command and the answer is required here! isready
// engine has finished setting up the internal values readyok
// now we are ready to go
// if the GUI is supporting it, tell the engine that is is // searching on a game that it hasn't searched on before ucinewgame
// if the engine supports the "UCI_AnalyseMode" option and the next search is supposed to // be an analysis, the GUI should set "UCI_AnalyseMode" to true if it is currently // set to false with this engine setoption name UCI_AnalyseMode value true
// tell the engine to search infinite from the start position after 1.e4 e5 position startpos moves e2e4 e7e5 go infinite
// the engine starts sending infos about the search to the GUI // (only some examples are given)
info depth 1 seldepth 0
info score cp 13 depth 1 nodes 13 time 15 pv f1b5
info depth 2 seldepth 2
info nps 15937
info score cp 14 depth 2 nodes 255 time 15 pv f1c4 f8c5
info depth 2 seldepth 7 nodes 255
info depth 3 seldepth 7
info nps 26437
info score cp 20 depth 3 nodes 423 time 15 pv f1c4 g8f6 b1c3
info nps 41562
....
// here the user has seen enough and asks to stop the searching stop
// the engine has finished searching and is sending the bestmove command // which is needed for every "go" command sent to tell the GUI // that the engine is ready again bestmove g1f3 ponder d8f6
UCI could easily be extended to support Chess960 (also known as Fischer Random Chess).
The engine has to tell the GUI that it is capable of playing Chess960 and the GUI has to tell the engine that is should play according to the Chess960 rules. This is done by the special engine option UCI_Chess960. If the engine knows about Chess960 it should send the command 'option name UCI_Chess960 type check default false' to the GUI at program startup. Whenever a Chess960 game is played, the GUI should set this engine option to 'true'.
Castling is different in Chess960 and the white king move when castling short is not always e1g1. A king move could both be the castling king move or just a normal king move. This is why castling moves are sent in the form king "takes" his own rook. Example: e1h1 for the white short castle move in the normal chess start position.
In EPD and FEN position strings specifying the castle rights with w and q is not enough as there could be more than one rook on the right or left side of the king. This is why the castle rights are specified with the letter of the castle rook's line. Upper case letters for white's and lower case letters for black's castling rights. Example: The normal chess position would be: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w AHah -
Copyright © 2025, Lee Patterson