Writing 4 min read
A Rubik's Cube in Go, written by a local LLM
Just for fun: a native 3D Rubik's Cube in Go and OpenGL that scrambles and solves itself. A local Qwen 3.8 Flash Next wrote all of it, with Claude Code as the harness.
This one is just for fun. I asked a language model running on my own hardware to build a Rubik’s Cube in Go, and this is what came back:
One full cycle: solved, ten turns to scramble, a pause, ten turns back. The program rendered every frame of this clip itself. Click the clip to pause it.
The code is on GitHub at Suaroman/gorubik, under the MIT license.
What you are looking at
It is a desktop program, not a web page. There is no browser, no HTML and no game engine behind it: about 6,000 lines of Go, about 1,000 lines of GLSL in 22 shader files, and two Go packages for the window and the OpenGL bindings. It loads no image files. The cube, the studio it sits in and the reflections on the stickers are all computed when the program starts.
The cube is built the way a real one is: 26 separate pieces (8 corners, 12 edges, 6 centers), each with its own position, its own orientation and its own stickers. A turn moves exactly nine of them. The sequence never changes:
| Phase | What happens |
|---|---|
| Solved | the cube turns slowly for 2 seconds |
| Scramble | R U F' D L' B R' U' F D', half a second per turn |
| Pause | 2 seconds, still scrambled, still rotating |
| Solve | D F' U R B' L D' F U' R', the exact inverse |
| Hold | solved for 10 seconds, then the cycle starts again |
On the laptop it was tuned on (an NVIDIA RTX A5000, 1600×1000 with 8× antialiasing), the project’s README reports about 600 frames per second with the frame cap off, or roughly 2.4 milliseconds of GPU time per frame.
Who wrote it
Not me. I wrote the prompt, and a model wrote the program.
- The model is Qwen 3.8 Flash Next, running locally on my workstation. Nothing went to a cloud API.
- The harness is the Claude Code CLI, pointed at that local server. Claude Code supplies the loop: read files, edit them, run the build, look at the result, try again. The model supplies every decision inside that loop.
- The prompt is in the repository as
PROMPT.md. It asks for a real mechanical cube, studio lighting, soft shadows, and proof that the cube really ends up solved. It ends with the reaction I was hoping for: “That was written in Go?”
Three things worth a look
The cube state cannot drift. Each piece’s position is three whole numbers, each one -1, 0 or +1. Its orientation is a small matrix of whole numbers, one of the 24 ways a cube can be turned. A face turn multiplies by another whole-number matrix. There are no fractions anywhere in the puzzle’s state, so twenty turns later there is no rounding error to clean up. “Solved” means every piece is exactly home, and the check is plain integer equality.
It proves the ending. The prompt said not to fake the final state, so the program can check itself without opening a window:
$ go run ./cmd/gorubik -verify
cubies: 26
scramble: R U F' D L' B R' U' F D'
solve: D F' U R B' L D' F U' R'
after scramble: solved=false moves=10
after solve: solved=true moves=20
all 26 cubies home and unrotated after 20 moves
PASS: 20 turns executed, state finished bit-exactly solved
It measured the picture. The prompt also said that a successful build is not the same as a good picture. So the
model gave the program a -capture flag that renders any moment of the timeline to a PNG, and wrote two small Python
tools that read those images and report the color of each sticker family as numbers. The README describes one bug
that this caught: two arguments to an OpenGL call were swapped, one graphics driver quietly ignored the mistake, and
the reflections were empty on the machine that mattered. The same -capture flag is how I made the clip at the top
of this page.
The model behind it
The model runs on a workstation with two NVIDIA RTX PRO 6000 cards, served with SGLang. These numbers come from the notes in my own start script:
| Model | Qwen/Qwen3.8-Flash-Next-FP8 |
| Server | SGLang, split across both cards (tensor parallel 2) |
| Context window | 262,144 tokens |
| Speed | 116 to 122 tokens per second, measured with about 100,000 tokens of context |
| Memory | about 87 GB of VRAM in use on each card |
| Power | each card capped at 350 W |
The part of the start script that matters, trimmed:
sglang serve \
--model-path Qwen/Qwen3.8-Flash-Next-FP8 \
--tp 2 --ep 2 \
--context-length 262144 \
--mem-fraction-static 0.85 \
--chunked-prefill-size 8192 \
--reasoning-parser qwen3 \
--tool-call-parser qwen3_coder \
--port 8000
The last two parsers are what make it usable from a coding harness: one separates the model’s reasoning from its answer, the other turns its tool calls into something the client can run.
The speed at long context is the number I care about. A coding session like this one sends the whole conversation back on every turn, so the context is rarely small.
Run it yourself
You need Go 1.24 or newer and a C compiler, because the window library is reached through cgo. On Linux or WSL:
git clone https://github.com/Suaroman/gorubik
cd gorubik
./build.sh # Linux: bin/gorubik
./build.sh windows # cross-compile from WSL: bin/gorubik.exe
./bin/gorubik
The README lists the packages to install first, and has the long
version of everything above: the lighting, the shadows, the shader pipeline and the mathematics of a face turn.
Esc or Q quits, H shows a debug overlay, R restarts the sequence.