InsightsHow it works
How it works
You type a question. A program written with only eight different commands prints an answer. In between, your question goes one route, and the last stretch of that route is then repeated once for every piece of the answer. You need no programming to follow it.
Letters become numbers
One question goes the whole route here, with the answer that the program of brnfck-smollm2-135m prints for it:
What is the capital of France?The capital of France is Paris.
Start where the question goes in. The machine below has a row of nine boxes that all hold 0, and three keys. Above the keys stands the question, with a mark on the letter that comes next. Press , and watch the first box. Then press > and , again, a few times:
The first box went to 87 and the next one to 104. Brainfuck has no letters, only numbers: 87 is the number computers use for W, and 104 is the one for h. A space is a number too, 32. Each press of , took the next letter of the question and put its number in the box where the machine was working.
That key is one of the eight commands of brainfuck. Each command is written as one character and does one small thing: , reads a letter, and > and < move the place where the machine works by one box. The row of boxes is called the tape, one box is a cell, and the mark under the working cell is the pointer. A program is a list of commands, carried out from left to right.
If you clicked a box, the pointer jumped to it. That is a shortcut of this figure, and so is the slider that chooses the next letter. A brainfuck program can do neither: it moves one cell at a time and reads the letters in the order you typed them.
I'm showing nine cells, and each holds a number from 0 to 255. The tape of brnfck-smollm2-135m has 188,012,789 cells, and each holds a number from 0 to 4,294,967,295. That program is 1,030,902,380 characters long, and the command , occurs in it exactly once. It stands inside a stretch that repeats, so it is used again for every letter you type.
Numbers become word pieces
Here is the question again, one character to a box, with each space drawn as ␣. Under it are seven buttons. Press them one after the other, or click a letter, and watch which boxes light up:
Each button lit up a whole word with the space in front of it, or a single sign such as the question mark. Such a chunk is a word piece: a common word, or a part of a rarer one (elsewhere it is called a token). The model reads and writes text one word piece at a time, never one letter at a time. brnfck-smollm2-135m knows 49,152 word pieces, and each has a number: “␣capital” is 3,575 and “␣France” is 4,649.
These are the seven word pieces of this question and their numbers in brnfck-smollm2-135m. One thing is left out of the drawing: a few fixed lines that tell the model to be a helpful assistant are put around your question, and with those the tape holds 37 word pieces.
To cut the letters into word pieces, the program looks up which letters belong together in a list of all word pieces, which lies on the tape like everything else.
Look up, multiply, add
For every word piece the tape holds a row of numbers of its own. The small tape below has three such rows of two numbers each, for three word pieces that are numbered 0, 1 and 2 here. Cell 0 holds the number of the word piece to fetch. Choose one with the upper slider, press Play, and follow the pointer. Drag Step to go through the same run by hand, forwards and backwards:
The number you chose did not stay in cell 0. It moved three cells to the right and lost one, and again, until it was 0. At that moment the pointer stood in front of the right row. Brainfuck has no command for “go to row 2”, and its tape has no index. So a program finds a row the way you find a house in a street without numbers: by walking along and counting doors.
The sixteen commands above the cells are the whole program for this walk. Its square brackets make a part of it repeat; they come back further down. The three rows are a small example with numbers I picked. The table of brnfck-smollm2-135m has 49,152 rows of 576 numbers each, so its walk is very much longer.
A row of numbers is where the calculating starts. The next tape has four cells: three numbers, and a total. Each number has a slider. Move the sliders and watch the cell marked “total”. Then drag Step to the left to see how that total was made:
Each number was multiplied by the value of its slider, and the three results were added up in the last cell. The value on a slider is a weight: a number that says how strongly one number counts in a total. A model is a very long list of weights, 135 million of them in brnfck-smollm2-135m, with a fixed recipe that says what is multiplied by what. The weights were found by training the model, long before and not in brainfuck [1].
If you dragged the run back, you saw the three numbers shrink to 0 while the total grew. A brainfuck program can only read a cell by emptying it. These are small whole numbers, with weights from 0 to 5. The weights of the model can also be below zero, and one total there adds up hundreds of products, not three.
The totals are not the answer. They become the numbers for the next round of multiplying and adding, with other weights. One such round over all the numbers of a word piece is called a layer. brnfck-smollm2-135m has 30 layers, and it takes every word piece through all of them: about 134 million multiplications for one word piece.
Looking back at the earlier word pieces
The model is about to choose the first word of its answer. Below are four word pieces of the question, each with a score for how useful it is at this moment. Move the scores and watch the bars:
The four bars always add up to 100%. A word piece with a high score gets a large share, and raising one score lowers the share of all the others. In every layer, each word piece gives every earlier word piece such a score, and then takes in their numbers in those shares. This is called attention: the part of a layer that looks back at the earlier word pieces.
Here you set the scores by hand, and a share is simply a score divided by the sum of all four. In the model the scores come out of multiplying and adding, as in the figure with the three weights, and the shares are worked out so that a high score counts for more still.
On the tape the earlier word pieces lie side by side. The pointer walks past all of them and carries its running totals along, like a waiter going down a row of tables with one tray.
Pick the next word piece, print it, go round again
After the last layer the program works out a score for every word piece the model knows: how well would this one fit as the next word piece? Below are five of them. Move the scores and watch which one is marked:
Only one thing counts: which score is the highest. How far ahead it is makes no difference, and the others are dropped. For the question followed here, after “The capital of France is”, the highest score goes to “␣Paris”. The five scores above are made up. brnfck-smollm2-135m has 49,152 scores each time, and the program has to find the highest of them with the commands you have seen.
The program works out these scores only after its last layer. But the numbers that go from layer to layer are on the tape, and the same last step can be given the numbers of any layer. The figure below did that for a real answer to the question followed here. Each column is one word piece the program printed, each row one layer, and each cell the word piece that would have won if the program had stopped after that layer. Yellow: the word piece that was printed. The paler the colour, the smaller its share. Choose a program:
Every cell comes from a real run of the program. While it answered, the numbers after each layer were copied from its tape (tools/map-data/lens.js), checked against the whole-number model they should equal (all of them were equal), and given to the program’s own last step: the one it runs after its last layer. The share is that of the scores of all word pieces, as in the figure “Looking back”. For brnfck-qwen3.5-0.8b the top row comes from the model’s multi-token prediction head, which the same tool runs in floating point on the numbers of the last layer: from them and the word piece just printed it guesses the one after it. The program itself does not have that head.
The answer is not there from the start. In the first layers the cells show word pieces that have little to do with the question: bits of code, pieces of other languages. The printed word piece comes up in the last layers. Paris comes first, and stays first, after layer 28 of 30 in brnfck-smollm2-135m, 22 of 24 in brnfck-qwen2.5-0.5b, 23 of 28 in brnfck-qwen2.5-1.5b, and only in the last of its 24 layers in brnfck-qwen3.5-0.8b. Every layer adds a little to the same row of numbers, and only the sum of all of them points clearly at “␣Paris”.
The winner is a number, 7,042 for “␣Paris”, and it has to become letters again. The tape below holds the six characters of that word piece as numbers. The program above it is made of two commands: >, and a new one, . Press Play and watch the line “Printed”. With the upper slider you change the number in cell 1:
Each . printed the cell under the pointer as one character: 80 came out as P, and with another number in that cell another letter came out. So . is the opposite of ,. Like the comma, it occurs exactly once in the whole program of brnfck-smollm2-135m, inside a stretch that repeats, and it is used for every letter of every answer. brnfck-qwen2.5-0.5b, brnfck-qwen2.5-1.5b and brnfck-qwen3.5-0.8b also have one of each.
Where is that one full stop?
Once, in more than a billion characters. The figure below finds it. Each strip is the framed part of the strip above it, opened up, down to the characters themselves:
Every strip is the text of its part, squeezed: each thin column shows how many of its characters are each command, in the colours of the commands. The yellow frame marks what the next strip opens up. The characters at the bottom are copied from the program file.
Now the round can be closed. The next figure shows the answer as it grows. Drag Round to the right, or press Play:
What is the capital of France?
Each round printed one word piece. The printed word piece then went back in, as if you had typed it yourself, and the whole route ran again, from the row of numbers through the 30 layers to the highest score, now with one more word piece on the tape. That is all an answer is: the same calculation again and again, each time over a text that is one word piece longer.
It ends when the highest score goes to a special word piece that means “end”. For this answer that was the eighth round, after seven printed word pieces. These seven and their numbers are what the program of brnfck-smollm2-135m prints for this question.
Multiplying with eight commands
You have used six of the eight commands: , . > < and, in the figures that ran by themselves, + and −, which add one to a cell and take one off. The last two are the square brackets. The program below works on two cells. Press Play, or drag Step, and watch both cells. The two upper sliders change the program:
With the sliders as they were, every round took 1 from the left cell and added 4 to the right one. The left cell started at 3, so after three rounds it was empty and the right cell held 12. The program multiplied 3 by 4, and there is no “times” command anywhere in it.
The brackets [ and ] mean: repeat what stands between us until the cell under the pointer is zero. Such a repeat is called a loop. “Is this cell zero?” is the only question a brainfuck program can ask, and everything the chat model does is built from that question. The multiplying in a layer is this loop, with a number from a row in the left cell and a weight as the plus signs. It is what ran in the figure with the three weights.
Notice what the cells cannot hold: 0.5, or any other fraction. Brainfuck has whole numbers only, and the models were made with fractions. So each model was first converted to arithmetic with whole numbers. The converted version picks the same next word piece as the original model in 94.8% of the tested cases for brnfck-smollm2-135m (345 of 364), in 96.6% for brnfck-qwen2.5-0.5b (477 of 494) and in 97.2% for brnfck-qwen2.5-1.5b (318 of 327). The program follows a rounded copy of the model, not the model itself.
A loop like this one only counts down. Comparing two numbers, dividing, and multiplying numbers below zero are built from the same loop in less obvious ways. The lessons build them one at a time.
Why it is slow and heavy
Take the loop of the last figure, with 4 added each round, and put a larger number in the left cell. The upper bar counts the work when every command is carried out by itself. The lower bar counts it when the loop is done as one multiplication. Drag the slider:
The slider goes from 1 to 1,000,000 in steps that grow, and the upper bar is squeezed in the same way: each time the count becomes ten times as large, the bar grows by the same length. Drawn to scale it would not fit.
The upper count grows with the number in the cell: eight commands for every round, so a million in the left cell is eight million commands. The lower count stays at 1. The right cell ends at the same number both ways.
Software that carries out a brainfuck program is called an interpreter, and one thing an interpreter does is a step. The interpreter in your browser does not act out the commands one by one. It first translates the program into the computer's own instructions (machine code; the kind a browser runs is called WebAssembly). While translating, it recognises simple loops like this one and replaces each by one operation: “add 4 times the left cell to the right cell, and empty the left cell”. And the program was written so that its heavy work has exactly these simple shapes.
It is still a great deal of work. One word piece of brnfck-smollm2-135m costs 1.6 to 1.9 billion steps measured, and takes about 0.6 to 1.0 seconds on the one desktop computer where it was timed [5]. An answer of seven word pieces is that eight times over. Done one command at a time it would take far too long, and for that reason the whole program has never been run that way: that both ways give the same result was checked on small test models.
Why is it this fast?
Brainfuck itself is not fast. Three things together make a word piece of brnfck-smollm2-135m take 0.6 to 1.0 seconds:
- Machine code. The browser turns the commands into WebAssembly, instructions the computer carries out directly.
- Whole loops in one operation. Simple loops, like the one that multiplies, are recognised and done in one go. The result is the same as running one command at a time; for the whole program that was checked on small test models only.
- A program written for that. The expensive work of the model has exactly those shapes.
The third point needed new building blocks, because brainfuck can only count. Each row below is one of them: the steps it takes by plain counting, and the steps it takes as it was built for this program.
| Building block | By counting | As built here |
|---|---|---|
| Divide, round and keep within limits | 1.2 to 1.5 million | about 100 |
| Multiply two numbers that can be negative | about 195,000 | about 43 |
| Look up one of 256 values in a table | about 500 | about 68 |
| Find the highest of 512 scores | 119,000 to 595,000 | about 5,000 |
Even so, one word piece of brnfck-smollm2-135m is 1.6 to 1.9 billion steps: 1.60 billion early in an answer, 1.92 billion at the last position the program has room for. Starting up takes 9 to 16 seconds when the file comes from the same computer. Qwen2.5-0.5B, Qwen2.5-1.5B and Qwen3.5-0.8B have more weights than SmolLM2-135M, so they take longer: about 2.3 seconds for a word piece of brnfck-qwen2.5-0.5b, 7 to 12 seconds for brnfck-qwen2.5-1.5b and about 5.6 seconds for brnfck-qwen3.5-0.8b. The lesson “peeling off bits” shows the trick behind the first row of the table.
A billion characters of numbers
Speed is one cost. Size is the other. The 135 million weights must be on the tape before the first letter is read, and brainfuck has no command for “put 93 here”. Choose a number and compare two programs that write it into a cell:
| Way | The program | Characters | Leaves in the cell |
|---|---|---|---|
| Counting | |||
| In fives |
Counting takes one plus sign for every unit. The program in fives writes the number the way we write 93 with two digits and not with ninety-three tally marks: a few plus signs, a short loop that multiplies by five, a few more plus signs. Both programs ran in your browser, and the last column is what each left in its cell. For a small number counting is the shorter of the two. For a large one it is far longer.
This is a small example. In the program of brnfck-smollm2-135m the loop that multiplies is written once for a block of up to 8,192 cells, so per cell little more than the plus signs is left. It also uses digits below zero and other multipliers than five. That way its first 1,004,387,443 characters fill 163,494,188 cells, at about 6 characters for each counted. As rows of plus signs the same numbers would take about 43 trillion characters estimated.
Those first characters are the writing part of the program: they put SmolLM2-135M on the tape and read nothing. The last 26.5 million characters are the engine. The engine holds the one comma and the one full stop, and it does everything on the route above: reading the question, cutting it into word pieces, the layers, choosing and printing. Drawn to scale, the two parts look like this:
Nearly all of the program only writes numbers. The part that answers is the sliver at the right end. Inside the program takes both parts apart.
A bigger model has more weights, and everything grows with them. Choose a model and compare:
- The model
- Weights
- The program
- The tape
- Free memory the browser needs
- Start-up
- Time for one word piece
Counts are counted in the program files. Times were measured on one desktop computer with the program file on its own disk; they depend on how busy the machine is. measured
The tape is the heavy part. A cell that can hold a number up to 4,294,967,295 takes 4 bytes of your computer's memory, so the 188,012,789 cells of brnfck-smollm2-135m are 717 MiB, and its chat page needs about 1.5 GB of free memory. The tape of brnfck-qwen2.5-1.5b is 6.81 GiB. That is more than a browser tab can address in the usual way, so it needs a browser with 64-bit WebAssembly memory and about 8 GB free.
All four were tried in one desktop Chromium browser only; brnfck-qwen3.5-0.8b ran there from start to answer too. A phone will most likely not manage brnfck-smollm2-135m, brnfck-qwen2.5-0.5b or brnfck-qwen3.5-0.8b, and it cannot run brnfck-qwen2.5-1.5b at all.
How long would it take with pencil and paper?
The work behind those seconds is counted in steps. A step is one thing the interpreter does: add a run of plus signs, test a loop, or do a small multiplying loop in one go. The browser gets through two to three billion of them a second. A person with pencil and paper might manage one.
reads a word piece of the questionprints a word piece of the answerdecides the answer is done
Every bar is one real run, counted step by step with the project's interpreter, and ends today. It is split into the word pieces of the run: point at one, or press it, to see its share. The dates count back from now at one step a second, without sleep; the events above the line are approximate.
Questions and numbers
What was checked, what was not, and every number with the condition it was measured under.
What does “pure brainfuck” mean, and what does it not mean?
Done by the brainfuck program
- Writing the model's weights and its list of word pieces onto the tape (for brnfck-smollm2-135m: 135 million weights and 49,152 word pieces)
- Turning your typed question into word pieces
- All layers of the model, for every word piece
- Choosing the next word piece
- Printing it as text
Done outside it
- Handing the program the letters of your question
- Showing the letters it prints
- Carrying out the eight commands (the interpreter)
What goes into a program is letters and what comes out is letters. The word pieces, the weights and the arithmetic are all inside it. This holds for brnfck-smollm2-135m, brnfck-qwen2.5-0.5b, brnfck-qwen2.5-1.5b, brnfck-qwen3.5-0.8b and brnfck-qwen2.5-coder-0.5b: each has only the eight commands, exactly one , and one ., and its only input is the question. brnfck-qwen3.5-0.8b-vision also has only the eight commands and one ., but three ,: one reads a picture before the question, two read the question (its first character, then the others).
What it does not mean:
- The models were not made in brainfuck. SmolLM2-135M-Instruct was trained by Hugging Face [1], Qwen2.5-0.5B-Instruct and Qwen2.5-1.5B-Instruct by Alibaba Cloud [7], Qwen3.5-0.8B by the Qwen team of Alibaba Cloud and Qwen2.5-Coder-0.5B-Instruct by Alibaba Cloud, all in the usual way. For brnfck-qwen2.5-coder-0.5b, Qwen2.5-Coder-0.5B-Instruct was then taught to write brainfuck on a graphics card, also not in brainfuck. Brainfuck only runs them.
- The numbers were rounded. Brainfuck has whole numbers only, so each model was first converted to whole-number arithmetic. That version picks the same next word piece as the original model in 94.8% of the tested cases for brnfck-smollm2-135m (345 of 364), 96.6% for brnfck-qwen2.5-0.5b (477 of 494) and 97.2% for brnfck-qwen2.5-1.5b (318 of 327). For brnfck-qwen3.5-0.8b it is 95.1% (214 of 225 positions of its answers): the program computes its whole-number version bit for bit, and that version was compared with the original.
- It needs cells of 32 bits. A cell here holds a number from 0 to 4,294,967,295 and goes round to 0 after that. Many brainfuck interpreters have cells that hold 0 to 255; on those these programs print nonsense.
- It needs a fast interpreter. See “Why is it this fast?” One command at a time would take far too long.
- The chat page keeps a copy of the tape. The writing part reads no input, so the tape it leaves behind is the same for every question. The chat page of brnfck-smollm2-135m runs it once and starts every question from a copy of that tape. The pages of brnfck-qwen2.5-0.5b and brnfck-qwen2.5-1.5b save only the cells that an answer changes and put those back. The outcome is the same. brnfck-qwen3.5-0.8b does not do this yet: the file that describes it does not list the cells an answer changes, so the Chatbot loads it again for each question.
- The program text was not typed. It was written out by a generator, a JavaScript program. What runs is only the brainfuck.
- An earlier version read its weights as input. For brnfck-smollm2-135m that program was 30,841,969 characters and read 355,761,802 bytes of model data with the comma command before your question. The present program writes the same numbers itself, and so do brnfck-qwen2.5-0.5b, brnfck-qwen2.5-1.5b and brnfck-qwen3.5-0.8b: the two tapes were compared cell for cell (“How do I know the program does what it says?”).
How do I know the program does what it says?
What was checked for brnfck-smollm2-135m [6]:
- The file holds 1,030,902,380 characters and every one of them is one of the eight commands. There is exactly one
,in the whole file. - The first 1,004,387,443 characters, the writing part, contain no
,and no. - The tape after the writing part is equal to the tape that the earlier version (the one that read its weights as input) had after reading its data file: 180 checksums over all 188,012,789 cells, and the pointer on the same cell.
- For 10 test questions the program prints exactly the text that a plain whole-number version of the model (the reference) gives.
- The engine was compared with that reference on 279 generated word pieces over 5 prompts: all the same.
- On small test models the complete program was also run under a slow interpreter that goes one command at a time and checks that the pointer never leaves the tape.
What was checked for brnfck-qwen2.5-0.5b and brnfck-qwen2.5-1.5b [8]:
- Each file holds only the eight commands: 4,169,659,608 characters for brnfck-qwen2.5-0.5b and 11,430,468,880 for brnfck-qwen2.5-1.5b. Each has exactly one
,and one. - The tape that the program writes is equal to the tape after loading the model's data files: 628 checksums for brnfck-qwen2.5-0.5b and 1,744 for brnfck-qwen2.5-1.5b.
- For test questions each program prints exactly the text of the reference. Answers were compared up to 30 word pieces.
What was checked for brnfck-qwen3.5-0.8b (all 11 checks passed):
- The file holds 7,709,034,855 characters, only the eight commands, with exactly one
,and one. - The tape after the writing part, the first 7,448,657,450 characters, is equal to the loaded model: 1,018 checksums (SHA-256) over all 1,067,424,772 cells.
- Asked “What is the capital of France?”, it prints exactly the text of the reference: 30 word pieces.
What was checked for brnfck-qwen3.5-0.8b-vision (all 21 checks passed):
- The file holds 8,931,101,427 characters, only the eight commands, with three
,and one. - The tape after the writing part, the first 8,214,809,705 characters, is equal to the loaded model: 1,142 checksums (SHA-256) over all 1,197,356,368 cells.
- Shown four photos and asked six questions about them, it prints exactly the text of the reference each time. Looking at a picture says how its part for pictures was checked.
What you can check yourself. The button reads the whole program of brnfck-smollm2-135m in your browser and counts every character. Over the internet the program comes as compressed pieces (about 180 MB in all, each checked against its checksum; the same pieces the chat page of brnfck-smollm2-135m uses, and kept in your browser in the same way). On your own computer it is read as one file of 1 GB.
| Command | Counted for the project | Counted in your browser |
|---|---|---|
+ | 289,126,304 | - |
− | 264,879,589 | - |
< | 459,121,488 | - |
> | 15,327,993 | - |
[ | 1,223,502 | - |
] | 1,223,502 | - |
. (print) | 1 | - |
, (read) | 1 | - |
| Anything else | 0 | - |
| Total | 1,030,902,380 | - |
You can also take the program file (1 GB, one very long line) and run it with any brainfuck interpreter that has 32-bit cells and a tape of at least 188,012,789 cells. Or repeat the project's own checks: see “Can I run it myself?”
Why are the models wrong so often?
Because they are small. SmolLM2-135M-Instruct [1] has 135 million weights; the well-known chat services use models that are very much larger. The original model, run in the normal way, makes the same kind of mistakes: wrong sums, invented facts, answers that wander off.
Size helps. Asked for 12 + 30, the program of brnfck-smollm2-135m printed “12 + 30 = 32”. The program of brnfck-qwen2.5-1.5b printed “12 + 30 = 42”. brnfck-qwen2.5-0.5b, brnfck-qwen2.5-1.5b and brnfck-qwen3.5-0.8b usually get simple sums and simple facts right. They are still wrong on harder facts.
brnfck-qwen3.5-0.8b runs Qwen3.5-0.8B, which has about 752 million weights. Asked “What is the capital of France?”, the program began its answer with “The capital of France is Paris.” It gave 56 for 7 times 8 and Amsterdam as the capital of the Netherlands. Asked in Dutch where Leeuwarden lies, it said “in de Oostzee”, in the Baltic Sea: wrong.
Brainfuck adds nothing and removes nothing. It only runs a model. The one difference is the rounding to whole numbers, described under what “pure brainfuck” means. Do not rely on anything a model says.
Can I run it myself?
Yes, with the project folder on your own computer: the code is on GitHub, under the MIT licence. It needs Node.js 24 and Python 3.12 and nothing else. The README in that folder gives every step: what works straight away, how to build a program from the model's files, and how to check it. To open these pages, run this in the project folder and go to http://localhost:8766/:
python tools/serve.py
This small server can send a part of a file, which the program map needs for its deepest zoom.
The programs are too large to come with the project folder. Download them from the folder bf/ on Hugging Face into site/programs/, or build each one from the model's files (the README says which files and which commands; brnfck-qwen2.5-0.5b takes a few minutes to build). Once a program is there, ask it a question without a browser. The five commands are for brnfck-smollm2-135m, brnfck-qwen2.5-0.5b, brnfck-qwen2.5-1.5b, brnfck-qwen3.5-0.8b and brnfck-qwen3.5-0.8b-vision, which also reads a picture (a PNG file):
node compiler/smollm/pure/ask.js "What is pi?" node compiler/qwen/program/ask.js --model 0.5b "What is 7 times 8?" node compiler/qwen/program/ask.js "What is the capital of France?" node compiler/qwen3.5/program/ask.js "What is 7 times 8?" node compiler/qwen3.5/vision/ask.js compiler/qwen3.5/vision/pictures/cat.png "Describe this picture in one sentence."
brnfck-qwen2.5-1.5b runs on an interpreter with 64-bit memory and needs about 10 GiB of free memory. It takes 90 to 169 seconds to start and 7 to 12 seconds for each word piece. Asked “What is the capital of France?”, it printed “The capital of France is Paris.” It also ran in one desktop Chromium browser, in the chat with brnfck-qwen2.5-1.5b: ready in 2 min 27 s, the same answer, 9.0 seconds per word piece (measured on 11 October 2026).
The program of brnfck-smollm2-135m is one file of 1 GB: brnfck-smollm2-135m.bf.
To repeat the checks on the billion-character program:
node compiler/smollm/pure/verify.js
What it needs: an interpreter with 32-bit cells that go round (after the highest number comes 0), and a fast one. In the browser brnfck-smollm2-135m needs about 1.5 GB of free memory, brnfck-qwen2.5-0.5b about 4 GB, brnfck-qwen2.5-1.5b about 8 GB and a browser with 64-bit WebAssembly memory, brnfck-qwen3.5-0.8b about 5 GB, and brnfck-qwen3.5-0.8b-vision about 7 GB and a browser with 64-bit WebAssembly memory. They have only been tried in one desktop Chromium browser; phones will most likely not manage brnfck-smollm2-135m, brnfck-qwen2.5-0.5b or brnfck-qwen3.5-0.8b, and a phone cannot run brnfck-qwen2.5-1.5b or brnfck-qwen3.5-0.8b-vision.
brnfck-qwen3.5-0.8b. It runs in the chat with brnfck-qwen3.5-0.8b and needs about 5 GB of memory. Your browser downloads 1.36 GB; the program is ready after 2 min 10 s to 2 min 37 s and takes about 5.6 s for each word piece. It cannot clear its memory after an answer yet, so the Chatbot loads it again for a second question. On the command line (Node.js, one desktop) it took 103 seconds to start and 5.56 seconds for each word piece of the answer (median). Its tape of 1,067,424,772 cells fits a 32-bit memory. 18 of its 24 layers are of another kind, Gated DeltaNet, explained on Compare the models. The program follows its whole-number recipe exactly. Ask it yourself on that page runs the model in floating point with its DeltaNet layers in whole numbers: close to the program, but not what it computes.
brnfck-qwen3.5-0.8b-vision. It runs in the chat with brnfck-qwen3.5-0.8b-vision, with one of four photos or a picture of your own, and needs about 7 GB of free memory. Your browser downloads 1.51 GB. It too is loaded again for each question. On the command line (Node.js, one desktop) it took 86.5 s to start, 650 s for the picture and the question about the cat, and 6.59 s for each word piece of the answer (median). In the browser (Chromium 152, the same computer, one run) it was ready after 1 min 40 s, took 13 min 43 s for the picture and the question and 5.6 s for each word piece: 17 min 44 s in all. Its tape of 1,197,356,368 cells takes 4.46 GiB and needs 64-bit memory. Looking at a picture explains how it looks at a picture.
Has this been done before?
An earlier public project (lobotoml) ran a neural network of 7 neurons in brainfuck, for the XOR function [3]. A search for an earlier language model or chat model in brainfuck found none. The search was limited, so this is not a claim to be the first.
The numbers
| What | Value | Kind |
|---|---|---|
| The model | SmolLM2-135M-Instruct | model |
| Weights | about 135 million | model |
| Layers | 30 | model |
| Word pieces it knows | 49,152 | model |
| Program length | 1,030,902,380 characters | counted |
| Characters that write the model | 1,004,387,443 | counted |
| Characters of the engine | 26.5 million | counted |
| Cells the writing part fills | 163,494,188 | counted |
| Characters per filled cell | about 6.1 | counted |
| The same by plain counting | about 43 trillion characters | estimated |
| Tape | 188,012,789 cells of 32 bits (717 MiB) | counted |
| Read commands in the file | 1 | counted |
| Start-up | about 9 to 16 seconds | measured |
| Time per word piece | about 0.6 to 1.0 seconds | measured |
| Work per word piece | 1.6 to 1.9 billion steps | measured |
| What | brnfck-smollm2-135m | brnfck-qwen2.5-0.5b | brnfck-qwen2.5-1.5b | brnfck-qwen3.5-0.8b | brnfck-qwen3.5-0.8b-vision |
|---|---|---|---|---|---|
| The model | SmolLM2-135M-Instruct | Qwen2.5-0.5B-Instruct | Qwen2.5-1.5B-Instruct | Qwen3.5-0.8B | Qwen3.5-0.8B with its part for pictures |
| Weights | about 135 million | about 494 million | about 1.54 billion | about 752 million (the text part) | about 853 million (752 million of text, 101 million for pictures) |
| Program length, in characters | 1,030,902,380 | 4,169,659,608 | 11,430,468,880 | 7,709,034,855 | 8,931,101,427 |
| Characters that write the tape | 1,004,387,443 | 4,100,831,733 | 11,334,697,744 | 7,448,657,450 | 8,214,809,705 |
| Tape, in cells of 32 bits | 188,012,789 | 657,597,114 | 1,827,870,014 (6.81 GiB) | 1,067,424,772 (3.98 GiB) | 1,197,356,368 (4.46 GiB) |
| Start-up | about 9 to 16 s | 33 to 47 s | 90 to 169 s on the command line; 2 min 27 s in the browser | 2 min 10 s to 2 min 37 s in the browser; 103 s on the command line | 1 min 40 s in the browser, then 13 min 43 s for the picture and the question; 86.5 s on the command line, then 650 s |
| Time per word piece | about 0.6 to 1.0 s | about 2.3 s | 7 to 12 s on the command line; 9.0 s in the browser | about 5.6 s in the browser; 5.56 s on the command line (median) | 5.6 s in the browser; 6.59 s on the command line (median) |
| Same next word piece as the original model | 94.8% (345 of 364) | 96.6% (477 of 494) | 97.2% (318 of 327) | 95.1% (214 of 225), its whole-number version against the original | 97.5% (79 of 81) on four photos, its whole-number version against the original |
| Checksums of the tape, all equal | 180 | 628 | 1,744 | 1,018 | 1,142 |
| Runs in | the browser | the browser, about 4 GB of memory | a desktop browser, about 8 GB of free memory (ran in one desktop Chromium browser), or the command line, about 10 GiB free | the browser, about 5 GB of memory | a desktop browser, about 7 GB of free memory, or the command line |
Times were measured on one desktop computer with the program file on its own disk. They depend on how busy the machine is.
What all this does not show
- The figures simplify. The row lookup, the three weights, the scores and the number written in fives use small or made-up numbers. brnfck-smollm2-135m also uses digits below zero and other multipliers than five.
- The route is that of brnfck-smollm2-135m. The question, its word pieces, the character count and the first table of numbers are of the program with 135 million weights. brnfck-qwen2.5-0.5b, brnfck-qwen2.5-1.5b and brnfck-qwen3.5-0.8b are built in the same way; their numbers are in the table of the models side by side.
- The answers can be wrong. brnfck-smollm2-135m is often wrong, also on simple sums. brnfck-qwen2.5-0.5b, brnfck-qwen2.5-1.5b and brnfck-qwen3.5-0.8b usually get simple sums and facts right but are still wrong on harder facts. Brainfuck adds nothing and removes nothing; do not rely on anything a model says.
- The numbers were rounded. The whole-number versions pick the same next word piece as the original models in 94.8%, 96.6%, 95.1% and 97.2% of the tested cases, not in all.
- Only some questions were compared. brnfck-qwen2.5-0.5b and brnfck-qwen2.5-1.5b printed exactly the reference text for the test questions, with answers compared up to 30 word pieces; brnfck-qwen3.5-0.8b for one question, also of 30 word pieces. Other questions were not compared.
- It needs cells of 32 bits and a fast interpreter. One command at a time would take far too long, and that it gives the same result was checked on small test models only.
- The times come from one computer. They depend on how busy the machine is. The chat pages have only been tried in one desktop Chromium browser. brnfck-qwen2.5-1.5b ran there from start to answer on 11 October 2026: ready in 2 min 27 s, then 9.0 seconds per word piece (measured). It needs about 8 GB of free memory; a phone cannot run it.
- The search for earlier work was limited. There is no claim to be the first.
The words used here, in one line each
- Command
- One of the eight characters brainfuck understands:
+ − < > [ ] , .Each does one small thing. A program is a list of commands. - Tape
- The program's memory: one long row of cells. brnfck-smollm2-135m has 188,012,789 of them, brnfck-qwen2.5-1.5b 1,827,870,014.
- Cell
- One place on the tape. It holds one whole number.
- Pointer
- The cell the program is at. Commands work on the cell under the pointer.
- Loop
- The commands between
[and], repeated until the cell under the pointer is zero. - Word piece
- A word or a part of a word. The model reads and writes text one word piece at a time. Elsewhere it is called a token.
- Weight
- One of the numbers the model learned in training. It says how strongly one number counts in a total.
- Layer
- One round of the model's calculation over all the numbers of a word piece, with weights of its own. brnfck-smollm2-135m has 30.
- Attention
- The part of a layer in which a word piece looks back at the earlier word pieces and takes in more from the useful ones.
- Writing part
- The long first part of the program. It puts the model on the tape and neither reads nor prints.
- Engine
- The short last part. It reads the question, calculates with the weights and prints the answer.
- Interpreter
- The software that carries out a brainfuck program. In the chatbot: your browser, which first turns the commands into machine code.
- Step
- One thing the interpreter does. A simple loop done as one multiplication is one step.
Credits and licences
- SmolLM2-135M-Instruct, the model of brnfck-smollm2-135m, is made by Hugging Face and published under the Apache 2.0 licence: huggingface.co/HuggingFaceTB/SmolLM2-135M-Instruct.
- Qwen2.5-0.5B-Instruct and Qwen2.5-1.5B-Instruct, the models of brnfck-qwen2.5-0.5b and brnfck-qwen2.5-1.5b, are made by Alibaba Cloud and published under the Apache 2.0 licence: huggingface.co/Qwen/Qwen2.5-0.5B-Instruct and huggingface.co/Qwen/Qwen2.5-1.5B-Instruct.
- Qwen3.5-0.8B, the model of brnfck-qwen3.5-0.8b, is made by the Qwen team of Alibaba Cloud and published under the Apache 2.0 licence: huggingface.co/Qwen/Qwen3.5-0.8B.
- stories260K, a small story model that an earlier program ran, comes from Andrej Karpathy's llama2.c project. That project is published under the MIT licence, and so is the tinyllamas collection of model files it belongs to.
- Brainfuck is a language designed by Urban Müller in 1993.
Where to go next
Inside the program measures the two parts you met here, the writing part and the engine. The program map shows them as one picture. The lessons let you build the loop, the lookup and the harder arithmetic yourself.
- -Inside the programArticleTake the writing part and the engine apart, with figures drawn from the program itself.
- []Compare the modelsArticleWatch the memory of Qwen3.5-0.8B fade and be written over, word piece by word piece.
- []Trained in brainfuckArticleThree programs that train a network themselves, from random weights. Train one in your browser and watch its loss fall.
- <>Program mapThe whole programSee every character of it in one picture, and zoom in until you can read the commands.
- +LearnTwo coursesStart from the eight commands, then build the copy, the multiplication and the search for the highest score.
- ,Ask brnfck-smollm2-135mChatbotPut a question of your own through the route you just followed.
- ,Ask brnfck-qwen2.5-0.5bChatbotSlower, and right more often.
Notes and sources
- SmolLM2-135M-Instruct, the model of brnfck-smollm2-135m. Made by Hugging Face and published under the Apache 2.0 licence.
- llama2.c, a project by Andrej Karpathy, published under the MIT licence, and the tinyllamas collection of model files it belongs to (also MIT). The small story model stories260K comes from there.
- lobotoml, an earlier public project: a neural network of 7 neurons in brainfuck, for the XOR function.
- Brainfuck, a language designed by Urban Müller in 1993.
- Measurements. Counts are counted in the program file (the eight commands, counted; you can repeat the count in your browser). Times and steps were measured on one desktop computer with the program file on its own disk (the building blocks, brnfck-smollm2-135m and the models side by side). The steps per word piece come from the counts under “Where the time goes” in Inside the program.
- Checks of brnfck-smollm2-135m. The same text as the whole-number reference for 10 test questions; 279 generated word pieces over 5 prompts all the same; 180 checksums over all 188,012,789 cells. See “How do I know the program does what it says?”
- Qwen2.5-0.5B-Instruct and Qwen2.5-1.5B-Instruct, the models of brnfck-qwen2.5-0.5b and brnfck-qwen2.5-1.5b. Made by Alibaba Cloud and published under the Apache 2.0 licence.
- Checks of brnfck-qwen2.5-0.5b and brnfck-qwen2.5-1.5b. Only the eight commands, one read command and one print command; the written tape equal to the tape after loading the data files (628 and 1,744 checksums); the reference text printed exactly for the test questions, with answers compared up to 30 word pieces.