info lines plus a final bestmove.
Architecture
GUI ↔ Engine over stdin/stdout
Arena · Lichess · Cutechess
text lines
Stockfish · your engine
Lifecycle
Full Session Flow
← id name MyEngine 1.0
← id author FujiBit
← option name Hash type spin default 16 min 1 max 65536
← uciok
# GUI configures options, then:
→ isready
← readyok
→ ucinewgame
→ position startpos moves e2e4 e7e5 g1f3
→ go wtime 300000 btime 300000 winc 3000 binc 3000
← info depth 8 score cp 25 nodes 120034 nps 2400000 pv e2e4 e7e5 g1f3
← info depth 14 score cp 34 nodes 823401 pv e2e4 e7e5 g1f3 b8c6 f1b5
← bestmove b1c3 ponder g8f6
# User moves, or time runs out — GUI may send:
→ stop
→ quit
uci → engine prints id, option list, uciok. GUI sends isready → readyok when initialized.
position startpos or position fen … moves … sets the board. ucinewgame clears TT and game state.
go starts search thread. Engine streams info then bestmove. stop aborts; quit exits process.
Commands
Essential UCI Commands
Enter UCI mode. Engine identifies itself and lists configurable options.
← uciok
Sync point — engine finished loading books, threads, NNUE weights.
← readyok
Change Hash size, Threads, MultiPV, skill level, etc.
Set board from startpos or FEN, optionally apply move list.
Start search. Limits: depth, movetime, wtime/btime, nodes, infinite.
→ go movetime 3000
Stop search and return bestmove so far, or terminate engine process.
→ quit
Output
Reading info Lines
Sent after each iterative-deepening depth (or periodically). GUI updates eval bar, PV line, and node count in real time.
bestmove e2e4 — engine's chosen move. Optional ponder g1f3 — expected opponent reply for ponder search while waiting. Promotion: e7e8q.
Implementation
Threading Model
Reads stdin line by line. Handles uci, position, setoption. Spawns/joins search on go/stop. Must never block inside search.
Runs iterative deepening + alpha-beta. Emits info to stdout. Checks stop flag and time budget. Joins cleanly on stop/quit.
Time controls
go Parameters Cheat Sheet
| Parameter | Meaning | Example |
|---|---|---|
depth N | Search exactly N plies (test / analysis) | go depth 10 |
movetime ms | Fixed time for this move | go movetime 5000 |
wtime / btime | Remaining clock in ms | go wtime 180000 btime 200000 |
winc / binc | Fischer increment per move | go winc 3000 binc 3000 |
movestogo N | Moves until next time control | go movestogo 20 |
nodes N | Stop after N nodes searched | go nodes 1000000 |
infinite | Search until stop (analysis mode) | go infinite |
Engine author checklist
- Flush stdout after every line (GUI waits on output)
- Never print debug to stdout — use stderr or log file
- Honor
stopwithin milliseconds; join search thread onquit - Parse move list in
positionwith make/unmake, don't rebuild from scratch each time - Report
score mate Nwith correct sign from engine's perspective - Support at least
HashandThreadsoptions for serious GUIs
UCI vs WinBoard (XBoard)
Older protocol still used by some legacy tools. Modern engines and GUIs overwhelmingly use UCI. If you build a new engine today, implement UCI only — one protocol, one test harness (Arena or go depth 6 from stdin).
Complete the engine series
UCI is the outer shell — search, TT, and move gen live inside.
Related: Search Algorithm · Transposition Table · All Blogs