Here are the first 32 bytes of the reference file, and nine things about them that surprise people. Every figure came from a run.

4641 4642  0200 4000  cb88 71ed  0000 0000
0000 0000  0800 d001 0000  0700 5002 0000

FAFB, the magic · version 2, flags, source CRC, offsets · counts and indexes

The idea is from 1985

Magic bytes, named chunks, a table that indexes them — that is IFF, the Amiga Interchange File Format, the design RIFF later riffed on. A brick is that pattern pointed at AI context instead of sampled audio.

There is no chunk 14

Thirteen content chunks, closed. Anything else an author writes folds into context, losslessly, sorted. A format with a fixed shape can be finished. An open one never can, because the output depends on which optional keys happened to be present.

All 32 bytes are spoken for

There is no spare room, by design, and the layout is frozen. Every new capability arrives as a chunk or a flag bit that older readers skip — which is what chunks were invented for.

A comment changes the file, not the context

Add one comment line to the source and the compiled file gets a new hash: four bytes of CRC move. Every content chunk stays byte-for-byte identical, because the compiler re-serializes the YAML and the comment never reaches a chunk.

So a brick has two identities. A Content ID over what the AI actually reads, and a file digest over every byte. Dedupe on the first. Sign the second.

same content, one comment apart
sha256  e88c3966dc100026...
sha256  f5cfe2e264d594f3...
differing bytes: 4  ·  chunk payloads: identical

It is not a compressor

On a small .faf the brick comes out bigger than its source. A 32-byte header, a section table, a string table and per-chunk framing cost more than they save when there is nothing to save.

What you buy instead: any chunk located without parsing the file, a truncation order decided in advance, and a CRC sealed to the source it came from.

faf compile  ·  drive folder
1246 -> 1414 bytes (113.5% of source)  ·  7 chunks  ·  wire v2.0

It cuts from the tail, never the middle

Every chunk carries a priority, and a reader fitting a brick into a token budget drops whole tiers from the end — 64, then 128, then 150–200 — so what is left is always a prefix of the full rendering. Identity chunks at 255 never drop.

Cutting one chunk out of the middle would be smaller and wrong: it leaves a hole that shifts everything after it, and a prompt cache keyed on the prefix would miss.

The token count is a hint, and it under-counts

Each section stores bytes/4 as a size hint. Measured across 79 real project.faf files, that under-counts by about a tenth on GPT tokenizers and a fifth on Gemma's — so budgeting with it overflows.

79 files  ·  199,110 bytes of YAML
o200k_base   55,259 tok   3.60 B/tok   bytes/4  -9.9%
Gemma 3      62,240 tok   3.20 B/tok   bytes/4 -20.0%

The score is carried, not computed

A brick copies the source's scores block through, unchanged. It is a claim as of the source it was sealed to, not a number the compiler worked out. If you need a current score, run a scorer.

The same discipline, one step further: a brick never signs itself. A file asserting its own signature proves nothing, so signatures live outside it, over the digest.

Drop the first line and it is YAML again

Each payload is the chunk name, a colon, a newline, then the value at column zero. Strip that first line and the rest parses straight back, nesting intact. Parse the whole payload and you get nonsense — the name binds to null.

One trap worth knowing: payloads are YAML 1.2, where yes and off are plain strings. A 1.1 parser such as PyYAML reads them as booleans.

Two programs, same bytes

The compiled brick is specified exactly enough that an independent build lands on the identical file: same 592 bytes, byte for byte, from the same source. The YAML serializer is version-pinned for the same reason — the payload bytes are the identity, so a patch bump that re-quotes one scalar would silently change it.

cmp  product CLI 0.9.5  <->  reference golden master
592 bytes  ·  identical

Read the bytes

This page is the tour. The FAF Format is the readable specification, and BINARY-FORMAT.md is the wire itself — header table, chunk table, identities, limits.

.faf is the source. .fafb is the compiled form. Recompile, never migrate.