Gary Fougerolle GF
Thai Break

Thai Break

Completed

Round three of a rivalry running since 2019

#thai-break#chessboxing#combat#chess

On 29 April 2026, in a boxing club rented for four hours in Ko Samui, I faced my best friend, Saad, for the third time in seven years. English boxing and chess, alternating, until one of us broke, in the ring or on the board. I lost on time, in a winning position, which, for this format, is probably the most instructive defeat there is.

Date
Location
Ko Samui, Thailand
Discipline
Chessboxing
Result
Win for Saad El Chungo, on time

What it is

Thai Break is the third edition of a match between two friends running since 2019. No club, no federation, no event open to the public: two people who agreed one night in 2019 and never really stopped.

The rules are written nowhere, but they settled on their own across editions:

  • The discipline changes every time: savate in 2019, MMA in 2023, chessboxing in 2026.
  • The aliases never change: Gary la Bête against Saad El Chungo, from day one.
  • There has to be a real setup: a referee, a judge, timed rounds, a decision that counts.
  • There has to be a poster: a dedicated logo, an online event, a live stream.

Three editions so far. The first took place at the Carré Magique, a corner of INSA Lyon we named ourselves, and that the whole campus still calls that today without knowing where the name comes from. It was savate, and Saad won on points.

The second, OneForce, took its name from the professional rivalry we carried into the ring: me at Salesforce, Saad at Onepoint. That time it was MMA, and I won on points.

The third, Thai Break, is chessboxing: rounds of English boxing alternating with games of chess. It is also the one that took the most logistics. Twelve of us flew out to Ko Samui, picked after poring over Thailand’s weather, and we rented an entire boxing club for the occasion. It came down to the clock. And it is the one I built an app for.

The app

More than anything, this edition was a testbed for leveling up on agentic development. I built the app with Claude Code, in a few days where the same work would have taken me months otherwise. What interested me here was as much that way of building as the fight itself. I go into how it was built in detail further down; for now, just what it does.

The app runs the whole flow of a chessboxing match: timing the boxing and chess rounds, and automatically capturing the moves from a connected board.

  • Chessnut e-board: connect a Chessnut Air / Air+ over Bluetooth to automatically capture every legal move and switch the turn without touching anything. It is the centrepiece of the app, and the thing I come back to further down (iOS/Android dev build).
  • Individual chess clocks: per-player time (9 min by default) and increment (0 by default).
  • Round configuration: chess round (3 min), boxing round (3 min), interval (1 min).
  • Tap to switch: during chess rounds, each player taps their panel once they have moved.
  • Pause: pause and resume the match at any time.
  • Restore seconds: add +5, +10 or +15s to a player (referee use).
  • Game history: saved games with date, winner, times and round reached; JSON export.
  • Round change sound: a phase beep on every transition between rounds.
  • Custom interval music: assign your own audio to intervals 1 to 10 (iOS/Android).
  • Cross-platform: web, iOS and Android.

It is the technical artefact of Thai Break. Without it, the format would be impossible to referee cleanly: two chess clocks, two boxing timers, and transitions you cannot miss.

The game

This is the app that timed the third edition, on 29 April. Here is the game it recorded, to replay move by move.

Starting position
Saad El Chungo – Gary La Bête · 1-0 (on time)

The level of play has nothing to do with what we are capable of with a clear head. That is the trap of the format: between games, you take rounds of English boxing, and calculation suddenly costs far more. Our moves fall well below our real level, we pile up mistakes, we double-check every line because we no longer trust ourselves, and it is often the clock that ends up deciding. I even lost a winning position on time, which is probably the fairest way to understand this sport.

Building the app with Claude Code

As I said above, this edition was as much an excuse to level up on agentic development as it was to fight. I wrote the app with Claude Code, talking to it rather than typing every line. Three things stood out, and the last one lands right on my own field.

The UI

The most obvious first: the interface. Buttons, clocks, setup screen, game history: everything that usually takes hours of styling came out almost right on the first pass, in NativeWind (Tailwind on React Native). I described the screen, it laid out the structure and the classes, I adjusted.

Cross-platform

A single codebase for web, iOS and Android, through Expo. Claude Code knows the traps specific to each target (the Bluetooth module unavailable on web, storage that has to fall back to a file on iOS) and handles them without my having to discover them one by one.

Integration, the real subject

This is where it gets interesting for me: my job is integration. Making two systems that were never designed to talk to each other do exactly that.

The system on the other side, here, is the Chessnut Air+ e-board. The idea: when a player makes a move on the physical board, the app detects it and switches the clock automatically. No more tapping the screen.

Except there is a catch. Chessnut publishes neither an SDK nor documentation for its protocol. The board speaks Bluetooth, but in a dialect the manufacturer keeps to itself.

And this is where Claude Code impressed me: on its own, it went looking for public repositories where enthusiasts had already reverse-engineered the protocol (rmarabini/chessnutair for the frames, ChessnutPy for the LED commands), then rebuilt the integration from there. I never handed it the docs; it went and found them.

The result is a very classic integration loop: you listen to an inbound event stream, transform and validate it, then push an outbound state back.

BLE integration loop between the Chessnut board and the app: inbound notification, decode, diff, chess.js validation, then LED write-back.

In plain terms:

  1. Connection. Over Bluetooth Low Energy (react-native-ble-plx), the app scans, connects, sends an init code (0x21 0x01 0x00) and subscribes to the board’s notifications.
  2. Inbound event. On every piece movement, the board pushes a frame: the full state of all 64 squares.
  3. Transformation. The app decodes that binary frame into a readable position.
  4. Validation. It compares against the previous position to work out the move played, and has chess.js validate it, an engine that knows the rules (castling, en passant, promotion). An illegal move is ignored.
  5. Effect. If the move is legal: switch the clock, append it to the PGN, check for checkmate or a draw.

Decoding the binary stream

The tricky step is number 3. The board does not send “the knight goes to f3”; it sends 34 raw bytes. Two of header, then 32 that describe the 64 squares, one square per nibble (half a byte).

Decoding a Chessnut frame: 34 bytes, header then two squares per byte, each code from 0 to 12 becomes a piece, reassembled into a FEN position.

Each value from 0 to 12 encodes a piece (0 = empty square, 7 = white pawn, 12 = white king…). The app reassembles a position in FEN, the standard chess notation. That FEN becomes the pivot model of the whole integration: the common language between the physical board and the chess engine.

Writing back: the LEDs

The integration does not only run one way. The app also sends commands back to the board, on its LEDs: the validated move highlighted, a misplaced piece in red, the whole board lit between rounds and at the end of the match. Same reverse-engineered protocol (0x0A 0x08 followed by an 8-byte bitmap, one bit per square).

And like any real-time stream, it needed robustness: a debounce so intermediate positions are not registered when a piece is slid across, correction detection when a misplaced piece is put back, a starting-position check before the game begins. Nothing exotic for anyone who does integration, except it all came out of a conversation, not a month of reverse-engineering. A pair partner that reads the docs for me, writes the connector, and leaves me on the part I care about: the architecture of the flow.

From this app to my day job

I am a Solution Engineer at Postman, and this small project says something broader. Building with AI changes the speed: this app, done in a few days, would have taken me months otherwise. But what works for a side project does not transfer as-is to a company.

First gap: the local-only project does not exist. My app lived on my machine, one developer, no constraints. In a company, everything is connected, shared, exposed to other teams. You need governance: who is allowed to call which API, within what limits, under what contract. Without it, the agent’s speed only accelerates the damage.

Second gap: documentation quality. If Claude Code could wire up the board, it is because enthusiasts had documented the protocol. An agent only exploits a repo or an API well if it is properly described. In a company it is the same rule: a poorly documented API is invisible to an LLM, a well-specified one becomes a tool it knows how to use. That is exactly what Postman addresses, documenting, specifying and governing APIs so that humans and agents alike can use them.

Then there is testing. When a human barely reviews the committed code, because it came out of a conversation rather than a keyboard, tests become the real safety net. They are no longer an optional step, they are what guarantees that what the agent produced actually does what you think. Here too, Postman covers the ground end to end.

One last point, more specific to AI: not all models are equal depending on the use. We have tooling to benchmark LLMs and pick the most relevant one on three concrete criteria, answer quality, response time and the number of tokens consumed. On a side project you use whatever model is at hand. At scale, that choice gets measured.

That is what makes this project interesting beyond the fight: the same gesture, getting two systems to talk through an agent, goes from a few days of tinkering to an engineering discipline the moment you put it into production.


What is chessboxing?
A hybrid sport alternating rounds of chess and rounds of English boxing. You can win by checkmate as well as by knockout, or on the decision.
How does the app detect moves played on the board?
The Chessnut Air+ e-board sends the state of all 64 squares over Bluetooth Low Energy. The app decodes each frame, compares it against the previous position to work out the move played, then validates it with chess.js before switching the clock.
Is the Chessnut Bluetooth protocol documented?
No, Chessnut publishes neither an SDK nor documentation. The protocol was reconstructed from public repositories, chiefly rmarabini/chessnutair for the position frames and ChessnutPy for the LED commands.
What stack is the app built with?
Expo and React Native, with NativeWind for styling, on a single codebase for web, iOS and Android. The Bluetooth connection runs through react-native-ble-plx and is only available on iOS and Android.