Repository navigation
Creating my first test 2
Welcome! This guide outlines the process for contributing code, network updates, and parameter tuning to Stockfish. Following these steps will help make the process smooth for both you and the project maintainers.
Before you start, please familiarize yourself with our core principles.
- Be Respectful: Always interact politely and kindly with others. See the Open Source Etiquette Guidebook.
- Join the Community: Participate in the Stockfish Discord server. This is the primary place to communicate with maintainers and other developers.
- Keep Changes Small: Submit focused, atomic changes. Small, self-contained patches are easier to review, test, and understand.
- One Idea Per Test: Each test should focus on a single idea. Avoid bundling multiple changes into one patch.
- Passing Tests ≠ Automatic Merge: Even if your change passes all tests, it still requires a review from the maintainers. Complex patches must provide significant benefits to be considered for merging.
First, you need to set up your development environment. You only need to do this once.
Ensure you have the following installed:
- A recent C++ compiler
- Git command line tools
- A GitHub account
- A Git client (e.g., GitHub Desktop, GitKraken, or the command line)
Create your own copy (a "fork") of the official Stockfish repository on GitHub.
- Navigate to
httpshttps://github.com/official-stockfish/Stockfish. - Click the Fork button in the top-right corner.
- For more help, see GitHub's guide: Fork a Repo.
Create a local copy of your forked repository on your computer.
git clone https://github.com/YOUR-USERNAME/Stockfish.git
cd StockfishImportant
You must fork the repository first and then clone your fork. Cloning the official repository and trying to push changes will not work.
This is the main loop you will follow for every contribution.
Before starting new work, always sync your local master branch with the official Stockfish master branch. This prevents merge conflicts.
You can do this manually with Git commands, which is the recommended approach:
# Add the official repository as a remote named "upstream" (only needs to be done once)
git remote add upstream https://github.com/official-stockfish/Stockfish.git
# Fetch the latest changes from the official repository
git fetch upstream
# Switch to your local master branch
git checkout master
# Reset your master branch to match the official master
# WARNING: This discards any local changes on your master branch!
git reset --hard upstream/master
# Push the updated master branch to your GitHub fork
git push origin master --forceAlternatively, use this automated script
- Save the script below as
sync-with-official.sh. -
Edit the
cd /path/to/your/Stockfish/srcline to point to thesrcdirectory of your local Stockfish clone. - Run it from your terminal with
sh sync-with-official.sh.
#!/bin/sh
# Change directory to the path of the script
cd "${0%/*}"
# !!! EDIT THIS LINE to point to your local Stockfish src directory !!!
cd /path/to/your/Stockfish/src
echo "Syncing local master branch with official-stockfish/master..."
# Add 'upstream' remote if it doesn't exist
git remote add upstream https://github.com/official-stockfish/Stockfish.git 2>/dev/null || true
echo "--> Switching to local 'master' branch..."
git checkout master
echo "--> Fetching latest changes from 'upstream'..."
git fetch upstream
echo "--> Resetting local 'master' to match 'upstream/master'..."
git reset --hard upstream/master
echo "--> Pushing updated 'master' to your GitHub fork ('origin')..."
git push origin master --force
echo "--> Recompiling Stockfish..."
make clean
make build -j
make net
echo "Sync complete."Create a new branch for your feature or idea. From there, you can make your changes. The exact process depends on the type of contribution.
Standard Code Changes
This is the most common workflow for functional changes, simplifications, or bug fixes.
-
Create a New Branch:
# Make sure you are on the master branch first git checkout master # Create and switch to a new branch git checkout -b my-new-idea
-
Edit the Code: Modify the source files in the
srcdirectory. -
Compile: Follow the Compiling from source guide. The basic command from the
srcdirectory ismake build -j. -
Get the Bench Signature: Run the bench command to get a unique identifier for your changes.
The output will contain a line like
./stockfish bench
Nodes searched : 4190940. The number4190940is your signature. -
Commit and Push:
git commit -am "A clear and descriptive commit message" git push origin my-new-idea
Testing a New NNUE Net
-
Upload the Net: Upload your
.nnuefile to Fishtest. You will need an account. By uploading, you license your network under CC0. -
Follow Naming Convention: The network file must be named
nn-SHA.nnue, whereSHAis the first 12 characters of itssha256sum.# Example command to get the SHA sha256sum my-net.nnue | cut -c1-12
- Create a Branch: Create a new branch for the test.
-
Update the Code: In
src/evaluate.h, change the default value ofEvalFileDefaultNameto the name of your new net (e.g.,"nn-d123456789ab.nnue"). -
Commit and Push: Commit and push your changes as you would for a standard code change. Do not add an
EvalFileUCI option; Fishtest does not support it and will only use the default net.
Tuning with SPSA
SPSA is used to automatically tune evaluation or search parameters.
-
Create a Branch:
git checkout -b my-spsa-tuning -
Expose Variables:
- Move the variables you want to tune to the global scope of the
Stockfishnamespace. - Remove the
constqualifier.
- Move the variables you want to tune to the global scope of the
-
Flag Variables with
TUNE: Use theTUNEmacro to mark the variables for tuning.- Variables must be of type
int,Score, orValue. -
Example:
// Original variables int myKing = 10; Score myBonus = S(5, 15); // Add this line after their definition TUNE(myKing, myBonus);
- Variables must be of type
-
Set Custom Ranges (Optional): By default, a variable
vis tuned in the range[0, 2*v]. You can override this.-
Set a fixed range:
TUNE(SetRange(-100, 100), myKing); -
Use a lambda for complex ranges:
auto myFunc = ...; TUNE(SetRange(myFunc), myVar); -
Return to default:
TUNE(SetRange(-100, 100), myKing, SetDefaultRange, myQueen);
-
Set a fixed range:
-
Add Post-Update Functions (Optional): If a function needs to run after parameters are updated, add its name to the
TUNEmacro.void my_post_update() { /* ... */ } TUNE(myKing, my_post_update);
-
Compile and Get Parameters: Compile your code and run
./stockfish. It will print a comma-separated list of parameters. Copy this list. - Get Bench Signature, Commit, and Push: Follow the same final steps as a standard code change.
Technical Details of SPSA in Fishtest
The SPSA algorithm in Fishtest works in a loop of two steps:
-
Evaluation: A mini-match is played using two different values for a parameter:
value - Ckandvalue + Ck. -
Update: The parameter's value is updated based on the match result:
value = value + (Ck * Rk) * (wins - losses).
The Ck and Rk values decrease over time to allow for large adjustments at the beginning and fine-tuning at the end. The Fishtest UI requires you to provide the starting value, min/max clipping range, and the final Ck and Rk values for each parameter. The list you copied in step 6 contains all this information.
Warning
Do not run too many tests at once. Having many active tests significantly reduces the testing throughput for everyone.
Please follow our Testing Methodology when choosing test parameters.
- Go to https://tests.stockfishchess.org/tests/run.
-
Test repository:
https://github.com/YOUR-USERNAME/Stockfish -
Test branch: The name of your branch (e.g.,
my-new-idea). -
Base repository / branch: Leave these as the defaults (
official-stockfish/Stockfish,master). -
Test signature: The bench number you got earlier. (If you add
Bench: [number]to your commit message, this will be auto-filled). - Info: A short but clear description of your change.
- For SPSA Tests: Paste the comma-separated list you copied earlier into the SPSA Parameters box.
- Click Submit test.
If your test passes STC and LTC, congratulations! You are ready to create a pull request.
-
Sync First: Ensure your branch is up-to-date with the official
masterbranch to avoid conflicts. - Go to Your Fork: Navigate to your forked repository on GitHub.
- Open the PR: GitHub will usually show a prompt to "Compare & pull request". Click it.
-
Checklist for a Great PR:
- Single Commit: Is your PR a single, clean commit? If not, please squash your commits.
- Clear Commit Message: The message should explain the reasoning behind the patch. This will become the PR description.
- Link Test Results: Include links to your passed STC and LTC tests on Fishtest.
-
Provide Bench Signature: The last line of your commit message must be either
No functional changeorBench: XXXXXXX. -
Ensure Portability: Push your branch to a helper branch named
github_cion your fork (git push -f origin HEAD:github_ci) to trigger continuous integration checks.
Click to see example commit messages
Example 1: Functional Change
Simplify away nnue scale pawn count multiplier
Removes 2x multipliers in nnue scale calculation along with the pawn count term that was recently reintroduced.
Passed non-regression STC:
https://tests.stockfishchess.org/tests/view/64305bc720eb941419bdf72e
LLR: 2.95 (-2.94,2.94) <-1.75,0.25>
Total: 38008 W: 10234 L: 10021 D: 17753
Passed non-regression LTC:
https://tests.stockfishchess.org/tests/view/6430b76a028b029b01ac9bfd
LLR: 2.94 (-2.94,2.94) <-1.75,0.25>
Total: 91232 W: 24686 L: 24547 D: 41999
Bench: 4017320
Example 2: Non-Functional Change
Set the length of GIT_SHA to 8 characters
Previously, the length of git commit hashes could vary depending on the git environment. This change standardizes it.
No functional change
Use these guidelines to choose the correct test parameters on Fishtest. For a visual aid, see the graphical SPRT calculator.
Definitions
- TC (Time Control): The time allotted for games.
-
STC (Short Time Control):
10s + 0.1sincrement. -
LTC (Long Time Control):
60s + 0.6sincrement. -
SPRT (Sequential Probability Ratio Test): The statistical model used to determine if a change is stronger or weaker.
SPRT(elo0, elo1)defines the bounds for passing or failing a test. - Simplification: A change that makes the code smaller, faster, or easier to understand without losing strength.
Functional Changes (Standard Workflow)
This is the process for nearly all changes intended to improve playing strength.
- Run an STC Test: Use the default "STC" test type.
-
Run an LTC Test: If the STC test passes, run a second test using the "LTC" test type. If the
masterbranch has not changed, you can use the "Reschedule" button on your passed test page. - Submit PR: If both tests pass, you are ready to create a pull request.
Functional Changes (Simplifications & Bug Fixes)
For changes that simplify code or fix bugs, we don't require a strict Elo gain. The goal is to ensure no Elo is lost.
- Follow the same STC -> LTC workflow as above, but use non-regression SPRT bounds. Manually set
elo0to-1.75andelo1to0.25. This requires a custom game task.
Non-Functional Changes (e.g., Speedups)
Changes that don't alter search logic but improve performance (Nodes Per Second) should first be tested locally.
-
Local Benchmarking: Use a tool like
perfon Linux or specialized tools like FishBench/BuildTester on Windows to measure the NPS gain.# Example perf command for reliable measurement sudo perf stat -r 5 -a -B -e cycles:u,instructions:u ./stockfish bench > /dev/null
- Fishtest Verification: If the speedup is significant (around 0.5% or more) and the change is not trivial, it should be tested on Fishtest using the standard STC -> LTC workflow to confirm the Elo impact. A speedup translates to Elo gain, so it is tested like any other functional patch.
- Cleanups and Refactoring: Trivial changes (typos, comments, dead code) that don't change the bench can often be submitted directly via PR without testing. More complex refactoring should be run through non-regression tests to ensure no crashes or unexpected slowdowns occur.
Advanced Fishtest Options
These options on the test creation page should only be used if you have a specific reason.
- Auto-purge: Toggles the automatic removal of statistically unusual games. Disable this when testing time management.
- Time odds: Uses different time controls for the base and test branches.
- Custom book: Uses a custom opening book for tests.
- Disable adjudication: Prevents games from ending early based on score.
Optional Git Commit Hook
This Git hook automatically builds Stockfish and adds the Bench: XXXXXXX line to your commit message if it finds the keyword autobench.
- Save the code below to
.git/hooks/commit-msgin your local Stockfish repository. - Make it executable:
chmod +x .git/hooks/commit-msg. - Use the word
autobenchon its own line in your commit message.
#!/bin/sh
set -e
if [ -z "$1" ]; then exit 1; fi
if ! git diff --exit-code --quiet; then
echo "Working directory is not clean; cannot generate bench" >&2
exit 0
fi
KEYWORD="autobench"
if ! grep -q -- "$KEYWORD" "$1"; then exit 0; fi
# Build Stockfish from the root directory
(cd src && make -j build)
# Obtain signature
signature=$(./src/stockfish bench 2>&1 | grep "Nodes searched" | awk '{print $4}')
# Replace keyword with bench message
sed -i.bak "/^${KEYWORD}\$/c\Bench: $signature" "$1" && rm "$1.bak"- Zugzwang Test Suite: Must be used for patches affecting verification search.
- More Bench Positions