This repository provides a tool to automatically run (single-elimination) knock-out tournaments on Lichess, making use of Lichess Swiss tournaments with manually-provided pairings. Visualizations of the knock-out brackets are automatically visualized and kept up-to-date, and hosted on GitHub, with a direct link in the tournament description.
Below are some examples of tournaments which were run with this tool, and the associated brackets.
To use this, you need to have a Lichess account, and you need to be the team leader of a Lichess team. To run the script in the cloud, you further need a GitHub account. The below description is for the cloud instantiation, as it provides the full functionality of automated visual knock-out bracket generation (similar to e.g. Challonge) which gets hosted on GitHub and linked in the tournament description, for players to track the progress of the tournament.
To run the script locally, you need to have Python installed with the necessary packages, as outlined in the installation instructions.
For users to join, they need to have a Lichess account and be a member of the same team in which these tournaments are organized.
There are two ways to use this tool:
The latter method has a major drawback which should be carefully considered when choosing this option. GitHub Actions has a limit of 6 hours on the time it lets any action run. Since the script needs to be active from the moment a tournament is created until the moment the tournament finishes, this for instance rules out:
Both methods of using this script should be fairly straightforward to use, if you follow the steps outlined in this README. If you get stuck getting the tool to work, feel free to contact me for help.
Below are installation instructions which apply both for running the script locally and for running the script on the cloud.
yourname/lichess-knockout.config.ini.config.ini as desired.python main.py -c config.ini -l <LICHESSTOKEN> -g <GITHUBTOKEN>, and keep the script running until the event is over.GITHUBTOKEN and LICHESSTOKEN in the GitHub Actions of the repository..github/workflows/runner.yml to adjust the time schedule accordingly (see more details below).yourname/lichess-knockout.Repository access, select Only select repositories and select the repository you just created.Permissions and Repository permissions, find the header Contents and set it to Read and write.github_.... Save this string, you will need it later. At the same time, do not share this string with anyone, as it would allow others (limited) access to your GitHub repository.tournament:write and this should automatically be selected when clicking this link.lip_.... Save this string, you will need it later. At the same time, do not share this string with anyone, as it would allow others (limited) access to your Lichess account.config.ini.
config.ini and (if doing this through the browser) edit it by clicking the pencil in the top right corner.The Cult with URL https://lichess.org/team/the-cult you would use the-cult.config.ini as desired.
config.ini, other parameters under [Options] can be modified to change various tournament settings.main.py.python main.py -c config.ini -l <LICHESSTOKEN> -g <GITHUBTOKEN> where you replace <LICHESSTOKEN> and <GITHUBTOKEN> with your tokens lip_... and github_....GITHUBTOKEN and LICHESSTOKEN in the GitHub Actions of the repository.
https://github.com/{yourgithubname}/{yourclonedreponame}/settings/secrets/actions.GITHUBTOKEN; paste the token starting github_...; and click “Add secret”.LICHESSTOKEN; paste the token starting lip_...; and click “Add secret”..github/workflows/runner.yml to adjust the time schedule accordingly (see more details below).The file config.ini can be modified to change the parameters of the tournament. For most of these parameters, the same restrictions apply as on the corresponding Lichess API endpoint. Some additional details on (the requirements on) these parameters are given below.
EventName describes the name for the tournament on Lichess, and is bound by the same constraints as specified in the Lichess API. In particular, special characters (including e.g. exclamation marks) should be avoided, and the maximum length of the tournament name is 30 characters.TieBreak can be set to decide who wins in case a match ends in a tie: the player with the lowest rating (rating), or the player with fewer white games (color, but only in combination with an odd GamesPerMatch).MinutesToStart specifies how soon the event starts after this script starts running. Concretely, this therefore specifies how long the tournament is open for registration on Lichess. To scheduleClockInit and ClockInc must satisfy constraints specified by the Lichess API.To change how often the script runs (and creates a tournament, waits for the start, keeps track of the event, sends pairings to Lichess, etc.), one has to edit the schedule in the GitHub Actions specification, at .github/workflows/runner.yml. The format of the schedule is given in the Cron format. A useful tool for finding a suitable Cron format for your desired frequency is Crontab.guru. Some examples of schedules:
0 * * * *: At the start of every hour.30 * * * *: Half an hour past every hour.0 */2 * * *: At the start of every even hour.0 1-23/2 * * *: At the start of every odd hour.0 */4 * * *: Every 4 hours.0 8,18,22 * * *: Every day at 08:00, 18:00, and 22:00.30 20 * * 6: At 20:30 on every Saturday.
All the times and dates above are UTC times/dates, so please take this into account when planning a schedule to suit your needs.Note 1: These times are when the script starts running; not when the event starts. If you want to run knock-out events every evening at 20:00 with a 2-hour registration period, you would set MinutesToStart: 120 in config.ini, and schedule the script to start running two hours before the start of the event, e.g., using 0 18 * * *.
Note 2: The Lichess API and GitHub Actions have rate limits on how often you can query the API, how often you can run these schedules, and how many tournaments can be created. Setting the schedule to create a knock-out tournament every 5 minutes will likely result in Lichess rate-limiting your account’s access to the API, and in extreme cases blocking your ability to create tournaments altogether.
Note 3: As with other things on GitHub, there can be delays both in uploaded files (such as the tournament bracket) being visible online, but also in the script being started; if the schedule is set to run at 12:00, the GitHub Action may only trigger around 12:05. This is neither intended nor a bug in the script; it seems to be an unfortunate but inevitable side effect of using GitHub Actions to automate these procedures in the cloud.
In some cases, a single schedule may not be sufficient. For instance, if you want to run a daily blitz event at 18:00 and a daily bullet event at 22:00, you need two different configurations. Since the GitHub Actions script calls the main python script and passes on the name of the configuration file as one of the arguments, one can create several independent schedules:
config.ini to config-2.ini and editing this configuration file, with different tournament settings;.github/workflows/runner.yml to .github/workflows/runner-2.yml, updating the Cron schedule for this series of tournaments, and replacing config.ini in this script with config-2.ini to use the other configuration.GitHub Actions will automatically pick up on the new .yml file if it is placed inside this directory, and will automatically run these scripts at the scheduled times.
The solution in this script, to host knock-out tournaments as Swiss events in disguise, comes with benefits as well as drawbacks.
On the positive side, this solution means that users can easily find and join the event via the corresponding Lichess Swiss event in the associated team, and the script will make sure to include a link to the up-to-date knockout bracket in the tournament description. This means that events are easy to find for users, and that they do not have to leave Lichess to find information about the event (except for viewing the bracket, hosted externally). The time until the tournament starts and until new rounds start can also be easily tracked via the Swiss event. Moreover, using the Swiss functionality means that no complicated authorization flows are needed to make manual pairings between users and force them to play games - we can simply provide the pairings to Lichess directly via the Lichess API for Swiss events, and Lichess will make sure the right players will play against one another. Lichess will automatically handle absent players, and assign wins to their opponents if needed.
On the negative side, this (unofficial) solution via Swiss events means that Lichess will think it is hosting a Swiss event, rather than a knock-out event. Therefore, on the tournament page, Lichess will rank players based on their total points, which may not reflect the players’ standings in the knock-out bracket - someone winning their first match 2-0 and losing 1-1 on tiebreaks in the second match has more points than someone winning 1.5-0.5 and winning 1-1 on tiebreaks.
The latter drawback of inconsistent rankings can potentially be overcome if Lichess allows Swiss tournament organizers to overrule the standard scoring/ranking of events. Allowing scoring to be altered would potentially open up the Swiss system to abuse of tournament organizers who manipulate the scoring system to make certain players win/lose, but it would also allow knock-out events to be scored properly.
Below a list of things that would be nice to address in the future, or which have been done recently.
MaxParticipants is reached) optional./schedule-next-round with fixed wait times between rounds.