10 interesting stories served every morning and every evening.

Half-Baked Product

weli.dev

The Founder

A freshly minted founder de­cides to get into the oven busi­ness. He can’t bake a cake or knead bread, but he knows the kitchen ap­pli­ance mar­ket in­side and out. He’s an­a­lyzed every busi­ness in Spain and reached a con­clu­sion: if he sells a new oven to the coun­try’s pizza mak­ers, pas­try chefs, and bak­ers, he only needs to cap­ture 10% of the mar­ket to be­come a bil­lion­aire.

10% al­ways looks small when you type it into an Excel spread­sheet.

The founder is very good. He builds a plan that, on pa­per, is flaw­less and air­tight: man­u­fac­ture a more ef­fi­cient oven us­ing new tech­nol­ogy. Selling it is easy. Want to work more ef­fi­ciently? Buy our oven. End of pitch. The founder has ex­pe­ri­ence talk­ing to in­vestors and raises enough money to build an MVP.

The Engineer

The founder looks for some­one who knows how to build ovens and finds an en­gi­neer from a pres­ti­gious school. The en­gi­neer has spent 10 years build­ing ovens and knows how to make one. More than that: he’s the kind of per­son who spends all day talk­ing and ar­gu­ing about ovens. He goes to oven con­fer­ences. When he gets home at night, he ar­gues for hours on Italian fo­rums about which type of oven is best. The Italian fo­rums are, to him, the ul­ti­mate source of oven-truth.

He’s tired of build­ing ovens at Corporate Oven. Ten years mak­ing the same oven he’s told to make. He wants the free­dom to build his own.

The founder of­fers him 20% of the com­pany and to­tal free­dom to build the per­fect oven. The salary is­n’t great, but there’s the promise: if things go well, some­day he could be a mil­lion­aire. And some­thing more im­por­tant than money: he’ll fi­nally get to build the oven of his dreams.

He signs.

The MVP

With lit­tle money and lots of en­thu­si­asm, they build an MVP. Two months later it’s done. It’s a func­tional oven and, more im­por­tantly, it has one im­prove­ment over tra­di­tional ovens: you in­put the amount of flour, yeast, and wa­ter, and the oven au­to­mat­i­cally knows when to stop for a per­fect bake.

In the­ory.

In prac­tice it does­n’t work very well, but it’s good enough for an MVP. They go to mar­ket and sell 5 pro­to­types: two bak­ers the founder knows, the en­gi­neer’s mother who bakes cakes, and two oven en­thu­si­asts who buy it out of cu­rios­ity.

The feed­back is unan­i­mous:

My bread came out burnt.” The cake was raw.” Every sin­gle pizza burns.”

But all things con­sid­ered, it’s pos­i­tive: a third of the time, the pro­to­type worked and pro­duced the per­fect cake, bread, or pizza.

This is just a pro­to­type. Imagine when we ship the real prod­uct. Trust us.”

And with that, the founder goes to see an old col­league who now works at a VC: In 2 months we’ve built a pro­to­type, we al­ready have 5 cus­tomers, and it’s very promis­ing. We just need money to scale, build a bet­ter ver­sion, and sell to every bak­ery and pas­try shop in Spain.”

Nobody asks whether the 5 cus­tomers would buy again.

The founder is very good. He raises 5 mil­lion. Ovens Inc. is born.

Forum of the Bakers

They start im­prov­ing the pro­to­type. The en­gi­neer re­al­izes some­thing: build­ing an al­go­rithm that cal­cu­lates bak­ing time for cakes, piz­zas, and bread is quite a bit more com­plex than it looked. Every dough is its own uni­verse. They need to hire more en­gi­neers.

The en­gi­neer knows ex­actly where to look. On the Italian fo­rums there are two users he’s spent years ar­gu­ing with about con­vec­tion and re­frac­tory stone: Mario and Luigi. He’s never met them in per­son, but he knows their opin­ions on ovens bet­ter than his own fam­i­ly’s. He of­fers them the same deal he got: low salary, lots of free­dom, the per­fect oven.

They sign.

Meanwhile, the founder needs to sell ovens, but Facebook and Instagram ads get no trac­tion. Turns out no­body buys a fif­teen-thou­sand-euro in­dus­trial oven be­cause it popped up in their sto­ries. So he hires a leg­endary sales team: the best sales­peo­ple in all of Spain. People who have never sold ovens, who know noth­ing about ovens, but who are hun­gry to sell and very ex­cited about the com­pany.

At first it goes badly. Few peo­ple want a new oven; they’re happy with the one they have. Why switch? Most small busi­nesses don’t care about a 15% ef­fi­ciency gain: the risk of switch­ing is too high. If Juan’s Bakery swaps ovens and the new oven fails, Juan loses his cus­tomers and shuts down. For Juan, ef­fi­ciency is op­tional; to­mor­row’s bread is not. Better to stick with the old oven, even if it’s worse on pa­per. He’d only switch if Manolo’s Bakery across the street started sell­ing cheaper bread thanks to a more ef­fi­cient oven and he had no choice. But Manolo thinks ex­actly the same as Juan, so no­body moves. Perfect equi­lib­rium. Economists have a name for this; Juan and Manolo call it com­mon sense.

Big busi­nesses are an­other story. For them, 15% ef­fi­ciency means mil­lions saved every year. And one sales­per­son man­ages to make con­tact with Pepepizza.

The Decision

Meanwhile, over in en­gi­neer­ing, things aren’t go­ing any bet­ter. The al­go­rithm is un­sta­ble. They’ve got­ten the fail­ure rate down from two thirds to one third, but each point of im­prove­ment costs twice as much as the last. And then comes the un­com­fort­able dis­cov­ery: if the oven only does two of the three things (bread, cakes, or pizza), the al­go­rithm fails just 5% of the time.

The en­gi­neer brings the pro­posal to the founder: let’s sac­ri­fice one mar­ket and have a prod­uct that works.

The founder gets an­gry. He promised the VCs 10% of Spain’s oven mar­ket. The en­tire mar­ket. We can’t sac­ri­fice any of them.”

It’s not just greed. The 5 mil­lion was raised with the en­tire mar­ket on the slide. The founder is­n’t choos­ing be­tween right and wrong: he’s choos­ing which promise to break.

The en­gi­neer goes back to his desk with his three doughs and his 33% fail­ure rate.

Mallorca

Back to sales: there’s con­tact with Pepepizza, but en­ter­prise deals don’t close over email. The founder flies to Pepepizza head­quar­ters and meets the owner. They hit it off. They hit it off so well they go to Mallorca to­gether. Nobody knows what was dis­cussed there. What’s known is that when they come back, there’s a deal. Nobody has tried the oven yet. No need. Enterprise sales is­n’t about ovens.

The hand­shake comes first. The re­quire­ments come later.

And they come. Pepepizza’s op­er­a­tions team sends the list to sales: their kitchens are cus­tom-built, so they need ovens with spe­cific di­men­sions. Oh, and a ro­tat­ing base like the one they al­ready have.

Sales replies: No prob­lem.”

The founder is eu­phoric. Pepepizza wants to buy an ini­tial batch of 500 ovens. Five hun­dred. That’s more rev­enue than every­thing since they started. For Pepepizza it’s a small pi­lot, a trial in a few lo­ca­tions be­fore de­cid­ing any­thing. For Ovens Inc. it’s bet­ting the en­tire com­pany.

Engineer, we need 500 ovens for Pepepizza. They want spe­cific di­men­sions and a base that spins. Let’s make it hap­pen.”

The en­gi­neer does­n’t faint only be­cause he’s al­ready sit­ting down.

The al­go­rithm barely works for pizza. The mold di­men­sions have spent 5 months be­ing op­ti­mized in CAD for the stan­dard size. And no­body, ever, has dis­cussed ro­tat­ing bases on the Italian fo­rums. If it’s not on the Italian fo­rums, does it even ex­ist?

The en­gi­neer opens the CAD file in front of the founder. He shows him why the new di­men­sions break the en­tire ther­mal de­sign. The founder looks at the screen, looks at the blue­prints, looks at the en­gi­neer.

But this is just chang­ing a num­ber, right?”

We can’t. Not un­til we fix the al­go­rithm and re­design the in­verter for the new sizes. That’s 5 more months.”

The Miracle

It’s not 5 months.

After many lost week­ends and en­tire nights run­ning on Red Bull, in 3 weeks there’s a pro­to­type for Pepepizza. Compromises were made. The al­go­rithm still fails plenty, but at least the di­men­sions are right. The ro­tat­ing base? Doesn’t ex­ist yet. Pepepizza is promised an add-on in a cou­ple of months.” Pepepizza says fine.

The Candle Button

Sales has had a rev­e­la­tion: if you sell the oven that ex­ists to­day, you don’t sell ovens. You have to sell the oven that will ex­ist in 6 months. Promise fea­tures. It worked last time: they promised Pepepizza the im­pos­si­ble and the team de­liv­ered in 3 weeks. What could go wrong?

Sales, of course, has no idea what hap­pens af­ter the con­tract is signed. The com­mis­sion is paid at sign­ing. Whatever comes next is an­other de­part­men­t’s prob­lem.

Though there’s some­thing no­body in en­gi­neer­ing wants to look at: Ovens Inc. does­n’t live off sell­ing ovens (for now). It lives off rais­ing rounds. And rounds are raised with pro­jec­tions, and pro­jec­tions are man­u­fac­tured out of what­ever sales promises. The No prob­lem” peo­ple are also the only life raft.

And then the daily re­quests be­gin:

A lot of our po­ten­tial cus­tomers make birth­day cakes. When they ask if we have spe­cial birth­day-cake fea­tures, we have to say no, and we lose them. Can we add the fea­ture?”

The founder has no doubts. Last time a fea­ture was re­quested, they es­ti­mated 5 months and did it in 3 weeks. And this is much eas­ier. It’s just a sim­ple but­ton that adds can­dles.”

The en­gi­neer is climb­ing the walls. They still haven’t fin­ished clean­ing up the Pepepizza wreck­age. This is ab­solutely not what peo­ple dis­cuss on the Italian fo­rums. Adding a can­dle but­ton is an in­sult to the state of the art, or rather, the state of the oven.

But he caves.

Just this once.”

Sales sells 2 more ovens a month thanks to the new but­ton. Or so they be­lieve. They have no way of check­ing whether they’d have sold them any­way with­out the but­ton.

The Second-Highest Priority

Soon af­ter, more fea­ture re­quests ar­rive.

My oven at home con­nects to the fire­place. Does yours?”

I make a lot of wed­ding cakes, what have you got for me?”

Do you have a Ramadan mode?”

They build all of them.

Engineering stops try­ing to build a good oven and starts adding but­tons and fea­tures. Nobody made that de­ci­sion. It just hap­pened, one ticket at a time.

And there’s a de­tail every­one seems to ig­nore: each but­ton takes longer than the last. The can­dle but­ton took three days. The fire­place one, a week. The lat­est one took three. It’s not that the en­gi­neers are get­ting slower: it’s that every new but­ton has to co­ex­ist with all the pre­vi­ous but­tons.

Meanwhile, cus­tomers who buy the oven re­turn it within a week. The rea­son? The bread and cakes still burn 10% of the time. The MVP prob­lem. The orig­i­nal one. The one from day one. Underneath the twelve new but­tons sits the same al­go­rithm from the very first day, and a baker who loses one out of every ten batches is not con­soled by the fact that the oven does can­dles.

When a cus­tomer calls to can­cel, sup­port tries to re­tain them by of­fer­ing what’s avail­able: the new but­ton from the lat­est re­lease. The baker whose bread keeps burn­ing is of­fered Ramadan mode. The baker leaves any­way. It gets logged as feed­back. Engineering has no time to stop and re­think their ap­proach, be­cause stop­ping is­n’t in the back­log.

And then the worst day ar­rives. Pepepizza calls:

Where is the ro­tat­ing base?”

The founder swal­lows hard. The ticket has been sit­ting on the kan­ban board for a month and a half. It’s not that no­body saw it: it’s that every week some­thing jumped ahead of it. The can­dle but­ton. The fire­place thing. The Ramadan thing. The ro­tat­ing base was al­ways the sec­ond-high­est pri­or­ity, and the sec­ond-high­est pri­or­ity never gets done. So he an­swers with con­vic­tion:

Almost fin­ished.”

The Request

Guys, these next two weeks we’re go­ing to fo­cus on the ro­tat­ing base,” says the founder.

The team can’t be­lieve it. They al­ready said the ro­tat­ing base was im­pos­si­ble. They al­ready ex­plained why. Besides, Mario has va­ca­tion planned, the va­ca­tion he was promised af­ter the Pepepizza crunch. And Luigi’s per­for­mance has been slip­ping for weeks and no­body knows why.

The en­gi­neer tries one more time:

We can’t do the ro­tat­ing base right now. We need to refac­tor, con­sol­i­date, and add an ab­strac­tion layer for com­part­ments and but­tons. Otherwise, every new fea­ture takes twice as long as the last. Also, Mario has va­ca­tion planned, and I’m not sure Luigi is in a good place to be asked for more.”

The founder nods. He gets it. He gets all of it.

But this is a startup. And star­tups are built with blood and sweat. Everyone here has to sac­ri­fice. You have two weeks.”

And he’s not say­ing it from the couch: the founder takes the low­est salary in the com­pany and has­n’t had a va­ca­tion in two years (Mallorca was work). He’s the first to live the speech. That is ex­actly the prob­lem.

When Everything Is Urgent, Nothing Is

There’s a new crunch. This time with less en­thu­si­asm and less pas­sion. The first one was an epic feat; this one is pa­per­work. Mario can­cels his va­ca­tion. Luigi keeps show­ing up. Nobody asks how he’s do­ing.

Two weeks later, the re­sult: a ro­tat­ing base that re­quires three spe­cial but­ton com­bi­na­tions. It’s in­com­pat­i­ble with every other mode, but it’s not like no­body tested it.

It gets in­stalled at Pepepizza. Pepepizza’s re­sponse:

It does­n’t ro­tate clock­wise. We’re go­ing with Corporate Oven.”

The team: dev­as­tated. They just lost their most im­por­tant cus­tomer. Nobody in prod­uct ever com­mu­ni­cated that it had to ro­tate clock­wise. Somewhere be­tween sales, the founder, and the back­log, the sin­gle most im­por­tant re­quire­ment of the pro­ject sim­ply never ex­isted.

And the worst part is­n’t los­ing Pepepizza. The worst part is that the changes made for the ro­tat­ing base will haunt the oven’s de­sign un­til the end of time. The cus­tomer leaves now. Their ro­tat­ing base stays for­ever.

No Blockers

A month later, Mario leaves the com­pany. He’s not go­ing to a com­peti­tor and he has­n’t found any­thing bet­ter: he leaves be­cause it’s the only way he can see to get a va­ca­tion. In the retro, it gets writ­ten down as a learning.”

Luigi stays. He now main­tains the can­dle but­ton. It’s his spe­cialty, they say. Nobody re­mem­bers who de­cided that, but it’s his spe­cialty. He keeps show­ing up every day, keeps do­ing his work. On the Italian fo­rums, peo­ple ask why Luigi has­n’t posted in 5 months. In standups he says no block­ers” and every­one moves on to the next per­son.

Epilogue

Six months later.

Ovens Inc. is still alive. Technically. There’s money for eight more months and a new ver­sion of the pitch deck where the word oven” no longer ap­pears: it’s now an intelligent bak­ing plat­form.”

The en­gi­neer left in March. He did­n’t slam the door or write a vi­ral thread about his ex­pe­ri­ence. One day he sim­ply stopped ar­gu­ing in meet­ings, a month later he stopped show­ing up, and his farewell was a three-line email. Nobody has touched his code since. Nobody dares.

The founder has it all fig­ured out: the prob­lem was never the plan. The prob­lem was the ex­e­cu­tion. He needs an­other en­gi­neer.

And he finds one.

Young, grad­u­ated from a pres­ti­gious school, has spent years build­ing ovens at Corporate Oven and he’s tired. More than that: he’s the kind of per­son who spends all day talk­ing and ar­gu­ing about ovens. He goes to oven con­fer­ences. When he gets home at night, he ar­gues for hours on Italian oven fo­rums about which type of oven is best. On the fo­rum an old user warns Make sure that you sup­port ro­tat­ing bases day 1”. The young en­gi­neer laughs. Who uses ro­tat­ing bases in an oven?

The founder of­fers him 5% of the com­pany. It can’t be 20 any­more; there’s been di­lu­tion (funding-round stuff, it’s com­pli­cated). But the salary does­n’t mat­ter, be­cause he’s of­fer­ing the im­por­tant thing: to­tal free­dom to build the per­fect oven.

The kid smiles.

Valve open source the Steam Machine e-ink screen so you can make your own

www.gamingonlinux.com

While Valve will not be mak­ing and pro­vid­ing their own e-ink dis­play for the Steam Machine, they have opened it up so any­one can now do it. Valve orig­i­nally teased it with the first lot of re­view­ers that got their hands on it.

All of it is avail­able on their GitLab un­der the MIT li­cense, which goes over every­thing you need to make your own and stick it on the front of your fancy new Steam Machine.

Image Credit - Gamers Nexus

They’re now call­ing it the Inkterface” and there’s a good few things you’ll need to make it in­clud­ing:

1 x Adafruit ESP32 Feather with 2MB PSRAM. 1 x Adafruit eInk Breakout Friend. 1 x Adafruit 5.83″ Monochrome eInk Panel. 13 x M2.5 x 5mm Pan Head Machine Screws. 4 x 1/4″ x 1/4″ x 3/16″ Stepped Magnet SB443-OUT.

1 x Adafruit ESP32 Feather with 2MB PSRAM.

1 x Adafruit eInk Breakout Friend.

1 x Adafruit 5.83″ Monochrome eInk Panel.

13 x M2.5 x 5mm Pan Head Machine Screws.

4 x 1/4″ x 1/4″ x 3/16″ Stepped Magnet SB443-OUT.

Valve even pro­vided a video on the GitLab show­ing it be­ing put to­gether, which we’re re-host­ing to make it eas­ily view­able for you:

Pretty cool to see.

Maybe we will see some other ven­dors ac­tu­ally do them pre-built for us. JSAUX teased they would be do­ing it back in November 2025, and check­ing back to­day they’ve said they still plan to do Ink & Pixel ver­sions”. If the Steam Machine is pop­u­lar enough - no doubt we’ll have other ac­ces­sory brands do var­i­ous ver­sions of their own.

🌐 External Sources: git­lab.steamos.cloud, x.com/​jsaux­of­fi­cial, gamer­snexus.net Article taken from GamingOnLinux.com.

The Free Market Lie: Why Switzerland Has 25 Gbit Internet and America Doesn't

stefan.schueller.net

You may have heard about 25 Gbit sym­met­ri­cal in­ter­net in Switzerland. This is of­ten cited as the fastest ded­i­cated (non-shared) res­i­den­tial con­nec­tion in the world. However, did you ever won­der why Switzerland has such fast in­ter­net at a rea­son­able price while the United States and other coun­tries like Switzerland’s neigh­bor Germany are falling be­hind?

What is the fun­da­men­tal dif­fer­ence be­tween the coun­tries that leads to such a stark dif­fer­ence in in­ter­net speeds and prices?

Free mar­kets, reg­u­la­tion, tech­nol­ogy, or all three?

Let’s take a closer look at the sit­u­a­tion in Switzerland, Germany, and the United States.

Note

This ar­ti­cle is writ­ten by me and spell checked with AI. Many of the im­ages are gen­er­ated by AI. They are mostly to ex­plain cer­tain points and break up the wall of text.

This Article is also avail­able as a video (My first):

As men­tioned, in Switzerland, you can get 25 Gigabit per sec­ond fiber in­ter­net to your home, sym­met­ric and ded­i­cated. If you don’t need such ex­treme speed, you can get 1 or 10 Gigabit from mul­ti­ple com­pet­ing providers for very lit­tle money. All over a con­nec­tion that is­n’t shared with your neigh­bors. In fact, some­one could of­fer 100 Gigabit or more to­day; there is noth­ing pre­vent­ing this other than the cost of end­point equip­ment.

In the United States, if you’re lucky enough to have fiber, you might get 1 Gigabit. But of­ten it’s shared with your neigh­bors. And you usu­ally have ex­actly one choice of provider. Maybe two, if you count the ca­ble com­pany that of­fers slower speeds for the same price.

In Germany, you are in a some­what sim­i­lar sit­u­a­tion to the United States. Fiber ser­vice is lim­ited to one provider and is of­ten shared with your neigh­bors.

The United States prides it­self on free mar­kets. On com­pe­ti­tion. On let­ting busi­nesses fight it out. A dereg­u­lated mar­ket with no brakes.

Germany, on the other hand, is fa­mous for over-reg­u­la­tion, mak­ing it dif­fi­cult for busi­nesses to op­er­ate, yet it is in a sim­i­lar sit­u­a­tion to the United States.

Switzerland has a highly reg­u­lated tele­com sec­tor with strong over­sight and gov­ern­ment-backed in­fra­struc­ture pro­jects, but reg­u­la­tions in Switzerland dif­fer from those in Germany.

So why is the coun­try that wor­ships free mar­kets pro­duc­ing stag­na­tion, mo­nop­o­lies, and in­fe­rior in­ter­net, while the coun­try with heavy reg­u­la­tion is pro­duc­ing hy­per-com­pe­ti­tion, world-lead­ing speeds, and con­sumer choice?

And at the same time, the coun­try with the most reg­u­la­tion is suf­fer­ing the same prob­lems as the coun­try with the least.

The an­swer re­veals a fun­da­men­tal truth about cap­i­tal­ism and reg­u­la­tion that most peo­ple get wrong.

To un­der­stand the fail­ure, you have to un­der­stand what econ­o­mists call a natural mo­nop­oly.”

A nat­ural mo­nop­oly is an in­dus­try where the cost of build­ing the in­fra­struc­ture is so high, and the cost of serv­ing an ad­di­tional cus­tomer is so low, that com­pe­ti­tion ac­tu­ally de­stroys value.

Think about wa­ter pipes. It would be in­sane to have three dif­fer­ent wa­ter com­pa­nies each dig­ging up your street to lay their own pipes. You’d have three times the con­struc­tion, three times the dis­rup­tion, three times the cost. And at the end of it, you’d still only use one of them.

The ra­tio­nal so­lu­tion is to build the in­fra­struc­ture once, as a shared, neu­tral as­set, and let dif­fer­ent com­pa­nies com­pete to pro­vide the ser­vice over that in­fra­struc­ture.

That’s how wa­ter works. That’s how elec­tric­ity works in most places. And in Switzerland, that’s how fiber op­tic in­ter­net works.

But in the United States and Germany, they did the op­po­site.

In Germany, the free mar­ket” ap­proach meant let­ting any com­pany dig up the street to lay their own fiber. The re­sult is called overbuild.” Multiple net­works run­ning in par­al­lel trenches, of­ten just me­ters apart.

Billions of eu­ros spent on re­dun­dant con­crete and as­phalt. Money that could have been spent on faster equip­ment, lower prices, or con­nect­ing rural ar­eas, in­stead wasted on dig­ging the same hole twice, lit­er­ally.1

But is­n’t Germany heav­ily reg­u­lated? Yes, but the reg­u­la­tions fo­cus heav­ily on in­fra­struc­ture com­pe­ti­tion rather than duct shar­ing en­force­ment.

Germany cham­pi­ons in­fra­struc­ture com­pe­ti­tion, mean­ing it prefers mul­ti­ple com­pa­nies lay­ing their own ca­bles rather than shar­ing a sin­gle net­work. At the same time, the reg­u­la­tory sys­tem wastes enor­mous amounts of time on wait­ing for dig­ging per­mits and on court­room bat­tles just to ob­tain ba­sic in­for­ma­tion about ex­ist­ing ducts.

Germany also has a large in­cum­bent, Deutsche Telekom, which uses ex­ist­ing reg­u­la­tions to its com­pet­i­tive ad­van­tage against smaller ISPs. While Germany does have laws re­quir­ing Deutsche Telekom to share its ducts with com­peti­tors, in prac­tice smaller ISPs face un­rea­son­able hur­dles such as high fees, pro­ce­dural de­lays, and le­gal dou­ble bur­dens that un­der­mine ef­fec­tive ac­cess.

Sharing ducts is not as bad as dig­ging two trenches but it is still a waste of re­sources.

The United States took a dif­fer­ent path, but the re­sult is equally bad. Instead of over­build, they got ter­ri­to­r­ial mo­nop­o­lies, in some places paid for by the fed­eral gov­ern­ment.

In most American cities, you don’t have a choice of fiber providers. You have what­ever in­cum­bent hap­pens to serve your neigh­bor­hood. Comcast has one area. Spectrum has an­other. AT&T has a third.

This is mar­keted as com­pe­ti­tion. But it’s not. It’s a car­tel. Each com­pany gets its own pro­tected ter­ri­tory, and con­sumers get no choice. If you don’t like your provider, your only al­ter­na­tive is of­ten DSL from the 1990s or a cel­lu­lar hotspot.

This is what hap­pens when you let nat­ural mo­nop­o­lies op­er­ate with­out over­sight. They don’t com­pete on price or qual­ity. They ex­tract rent.

And be­cause these net­works are built on the cheap us­ing P2MP, or shared ar­chi­tec­ture, your gigabit” con­nec­tion is shared with your en­tire neigh­bor­hood. At 8 PM, when every­one streams Netflix, that gi­ga­bit be­comes 200 megabits. Or 100. Or less.

The provider still charges you for gigabit.” They just don’t tell you that you’re shar­ing it with 31 other house­holds.

And it gets worse. In the United States, even if a com­peti­tor wanted to chal­lenge the in­cum­bent, they of­ten can’t. Because the Point of Presence, the cen­tral hub where all the fiber lines from homes con­verge, is pri­vate. It be­longs to Comcast or AT&T. Your fiber ter­mi­nates in their build­ing. A com­peti­tor can’t just in­stall equip­ment there. They would have to build their own net­work from scratch, dig­ging up the same streets, to reach you.

Now look at Switzerland. Here, the phys­i­cal in­fra­struc­ture, the fiber in the ground, is treated as a neu­tral, shared as­set. It’s built once, of­ten by a pub­lic or semi-pub­lic en­tity.

Every home gets a ded­i­cated 4-strand fiber line. Point-to-Point. Not shared. Not split 32 ways.

That ded­i­cated fiber ter­mi­nates in a neu­tral, open hub. And any in­ter­net ser­vice provider can con­nect to that hub.

Init7, Swisscom, Salt, or a tiny lo­cal ISP, they all have equal ac­cess to the phys­i­cal line that goes into your home.2

This means you, the con­sumer, have gen­uine choice. When you sign up with a provider, you sim­ply give them your OTO (Optical Termination Outlet) num­ber, the unique iden­ti­fier printed on the fiber op­tic plate in your home. It tells the provider ex­actly which fiber con­nec­tion is yours. That’s it. No tech­ni­cian needs to visit. No one needs to dig up your street. You just call, give them the num­ber, and within days (not al­ways the case…), your new ser­vice is ac­tive.

And be­cause your home has four sep­a­rate fiber strands, you’re not locked into a sin­gle provider. You can have Init7 on one strand, Swisscom on an­other, and a lo­cal util­ity on a third. You can switch providers with a phone call. You can try a new provider with­out can­cel­ing your old one first. The com­pe­ti­tion hap­pens on price, speed, and cus­tomer ser­vice but not on who hap­pens to own the ca­ble in front of your house.

In Switzerland, you can get 25 Gigabit per sec­ond fiber to your home. Today. Symmetric. Dedicated. Not shared with your neigh­bors.

In Switzerland, you have a choice of a dozen or more providers in most cities. Prices are com­pet­i­tive. Customer ser­vice mat­ters be­cause you can leave at any time.

In the United States, the ma­jor­ity of house­holds have only one choice for high-speed in­ter­net. Speeds are lower. Prices are higher. And the tech­nol­ogy is of­ten a decade be­hind.

The free mar­ket” promised in­no­va­tion. It de­liv­ered rent-seek­ing. The in­cum­bents have no in­cen­tive to up­grade be­cause you have nowhere else to go.

American broad­band prices have risen faster than in­fla­tion for decades. Speeds have in­creased only when a com­peti­tor, usu­ally a mu­nic­i­pal util­ity, forces the in­cum­bent to re­spond.

Without com­pe­ti­tion, there is no in­no­va­tion. There is only profit ex­trac­tion.

Switzerland did­n’t ar­rive at this model by ac­ci­dent nor did it hap­pen be­cause tele­com com­pa­nies were feel­ing gen­er­ous. It hap­pened be­cause reg­u­la­tors forced it to hap­pen.

Back in 2008, when the in­dus­try sat down at the Round Table or­ga­nized by the Federal Communications Commission, it was Swisscom, the in­cum­bent it­self, that pushed for the four-fiber Point-to-Point model. The com­pany ar­gued that a sin­gle fiber would cre­ate a mo­nop­oly and that reg­u­la­tion would be nec­es­sary.3

So the stan­dard was set. Four fibers per home. Point-to-Point. Open ac­cess for com­peti­tors on Layer 1 - the phys­i­cal fiber it­self.4

Then, in 2020, Swisscom changed course. The com­pany an­nounced a new net­work ex­pan­sion strat­egy, this time us­ing P2MP, the shared model with split­ters. On pa­per, they ar­gued it was cheaper and faster to de­ploy.

GEPON P2MP Splitter

But the ef­fect was clear. Under the P2MP de­sign, com­peti­tors would no longer have di­rect ac­cess to the phys­i­cal fiber. Instead of plug­ging into their own ded­i­cated fiber strand, they would have to rent ac­cess from Swisscom at a higher net­work layer - ef­fec­tively be­com­ing re­sellers of Swisscom’s in­fra­struc­ture. The open, com­pet­i­tive ma­trix that had been care­fully built over years would dis­ap­pear.

The small ISP Init7 filed a com­plaint with Switzerland’s com­pe­ti­tion au­thor­ity, COMCO, which later opened an in­ves­ti­ga­tion. In December 2020, they is­sued a pre­cau­tion­ary mea­sure: Swisscom could not con­tinue its P2MP roll­out un­less it guar­an­teed the same Layer 1 ac­cess that the orig­i­nal stan­dard pro­vided.5

Swisscom fought this all the way to the Federal Court. They lost. In 2021, the Federal Administrative Court con­firmed COMCOs mea­sures, stat­ing that Swisscom had failed to demon­strate sufficient tech­no­log­i­cal or eco­nomic grounds” to de­vi­ate from the es­tab­lished fiber stan­dard.5 In April 2024, COMCO fi­nal­ized its rul­ing, fin­ing Swisscom 18 mil­lion francs for vi­o­lat­ing an­titrust law.6

Note

Swisscom is 51% owned by the Swiss Confederation. So, in sim­ple terms, 51% state-owned and 49% pri­vately/​in­sti­tu­tion­ally owned. Whether this makes the fine symbolic” is a mat­ter of opin­ion.

The re­sult? Swisscom was forced to re­turn to the four-fiber, Point-to-Point ar­chi­tec­ture it had orig­i­nally cham­pi­oned.3 Competitors re­tained their di­rect, phys­i­cal ac­cess to the fiber net­work. The walled gar­den was pre­vented.

Whether in­tended or not, the ef­fect of Swisscom’s P2MP shift was clear: com­peti­tors would have been locked out of the phys­i­cal in­fra­struc­ture.

Swisscom is a bit of a walk­ing con­tra­dic­tion. Being ma­jor­ity state-owned, it’s sup­posed to be a pub­lic ser­vice. But it’s also a pri­vate com­pany, and max­i­miz­ing profit ben­e­fits the state cof­fers. But that is some­thing for an­other blog post.

This is the para­dox that con­fuses so many peo­ple.

The American and German ap­proach of let­ting in­cum­bents build mo­nop­o­lies, al­low­ing waste­ful over­build, and re­fus­ing to reg­u­late nat­ural mo­nop­o­lies is of­ten called a free mar­ket.’

But it’s not free. And it’s not a mar­ket.

True cap­i­tal­ism re­quires com­pe­ti­tion. But in­fra­struc­ture is a nat­ural mo­nop­oly. If you treat it like a reg­u­lar con­sumer prod­uct, you don’t get com­pe­ti­tion. You get waste, or you get a mo­nop­oly.

The Swiss model un­der­stands this. They built the in­fra­struc­ture once, as a shared, neu­tral as­set, and then let the mar­ket com­pete on the ser­vices that run over it.

That’s not anti-cap­i­tal­ist. It’s ac­tu­ally bet­ter cap­i­tal­ism. It di­rects com­pe­ti­tion to where it adds value, not to where it de­stroys it.

The free mar­ket does­n’t mean let­ting pow­er­ful in­cum­bents do what­ever they want. It means cre­at­ing the con­di­tions where gen­uine com­pe­ti­tion can thrive.

So what can other coun­tries learn from Switzerland? Here are the key pol­icy changes that would help:

Mandate open ac­cess to phys­i­cal in­fra­struc­ture - re­quire in­cum­bents to share fiber ducts and dark fiber with com­peti­tors at cost-based prices. This is not socialism” - it is how elec­tric­ity and wa­ter work.

Mandate open ac­cess to phys­i­cal in­fra­struc­ture - re­quire in­cum­bents to share fiber ducts and dark fiber with com­peti­tors at cost-based prices. This is not socialism” - it is how elec­tric­ity and wa­ter work.

Enforce Point-to-Point ar­chi­tec­ture - re­quire that every home gets ded­i­cated fiber strands, not shared split­ters. This en­sures com­peti­tors can ac­cess the phys­i­cal layer, not just re­sell band­width.

Enforce Point-to-Point ar­chi­tec­ture - re­quire that every home gets ded­i­cated fiber strands, not shared split­ters. This en­sures com­peti­tors can ac­cess the phys­i­cal layer, not just re­sell band­width.

Create a neu­tral fiber stan­dard - es­tab­lish na­tional stan­dards that re­quire multi-fiber de­ploy­ment to every home, as Switzerland did in 2008.

Create a neu­tral fiber stan­dard - es­tab­lish na­tional stan­dards that re­quire multi-fiber de­ploy­ment to every home, as Switzerland did in 2008.

Empower com­pe­ti­tion au­thor­i­ties - give reg­u­la­tors like COMCO real teeth to en­force these rules. Fines must be large enough to mat­ter.

Empower com­pe­ti­tion au­thor­i­ties - give reg­u­la­tors like COMCO real teeth to en­force these rules. Fines must be large enough to mat­ter.

Support mu­nic­i­pal fiber - al­low cities and towns to build their own fiber net­works when in­cum­bents fail to serve res­i­dents ad­e­quately.

Support mu­nic­i­pal fiber - al­low cities and towns to build their own fiber net­works when in­cum­bents fail to serve res­i­dents ad­e­quately.

If you care about faster in­ter­net and lower prices, push your rep­re­sen­ta­tives to sup­port these poli­cies. The tech­nol­ogy ex­ists. The money ex­ists. What is miss­ing is the po­lit­i­cal will to de­mand real com­pe­ti­tion.

Bundesnetzagentur: Bun­desnet­za­gen­tur pub­lish­es fi­nal re­port on the mon­i­tor­ing of du­pli­cate fi­bre in­fra­struc­ture pro­jects (July 2025) - https://​www.bun­desnet­za­gen­tur.de/​Shared­Docs/​Pressemit­teilun­gen/​EN/​2025/​20250730_­Dop­pelaus­bau.html ↩︎

Bundesnetzagentur: Bun­desnet­za­gen­tur pub­lish­es fi­nal re­port on the mon­i­tor­ing of du­pli­cate fi­bre in­fra­struc­ture pro­jects (July 2025) - https://​www.bun­desnet­za­gen­tur.de/​Shared­Docs/​Pressemit­teilun­gen/​EN/​2025/​20250730_­Dop­pelaus­bau.html ↩︎

Init7: Fiber7 PoPs - Business Infrastructure - https://​www.init7.net/​de/​busi­ness-in­fra­struk­tur/​fiber7-pops/ ↩︎

Init7: Fiber7 PoPs - Business Infrastructure - https://​www.init7.net/​de/​busi­ness-in­fra­struk­tur/​fiber7-pops/ ↩︎

Computerworld.ch: Swisscom krebst zu­rueck (February 2023) - https://​www.com­put­er­world.ch/​the­men/​tech­nolo­gie-und-in­no­va­tion/​swiss­com-krebst-zu­rueck ↩︎ ↩︎

Computerworld.ch: Swisscom krebst zu­rueck (February 2023) - https://​www.com­put­er­world.ch/​the­men/​tech­nolo­gie-und-in­no­va­tion/​swiss­com-krebst-zu­rueck ↩︎ ↩︎

Swissinfo.ch: Fibre-optic stan­dards sim­plify net­work­ing (January 2013) - https://​www.swiss­info.ch/​eng/​busi­ness/​fi­bre-op­tic-stan­dards-sim­plify-net­work­ing/​31974894 ↩︎

Swissinfo.ch: Fibre-optic stan­dards sim­plify net­work­ing (January 2013) - https://​www.swiss­info.ch/​eng/​busi­ness/​fi­bre-op­tic-stan­dards-sim­plify-net­work­ing/​31974894 ↩︎

Federal Administrative Court (BVGer) me­dia re­lease: Swisscom must com­ply with fi­bre-op­tic stan­dards (December 2021) - https://​www.bvger.ch/​en/​news­room/​me­dia-re­leases/​swiss­com-must-com­ply-with-fi­bre-op­tic-stan­dards-1063 ↩︎ ↩︎

Federal Administrative Court (BVGer) me­dia re­lease: Swisscom must com­ply with fi­bre-op­tic stan­dards (December 2021) - https://​www.bvger.ch/​en/​news­room/​me­dia-re­leases/​swiss­com-must-com­ply-with-fi­bre-op­tic-stan­dards-1063 ↩︎ ↩︎

COMCO (Swiss Competition Commission): Swisscom fine for vi­o­lat­ing fi­bre-op­tic stan­dards (April 2024) - https://​www.swiss­info.ch/​eng/​sci­ence/​comco-gives-swiss­com-2025-dead­line-in-fi­bre-op­tic-dis­pute/​76393735 ↩︎

COMCO (Swiss Competition Commission): Swisscom fine for vi­o­lat­ing fi­bre-op­tic stan­dards (April 2024) - https://​www.swiss­info.ch/​eng/​sci­ence/​comco-gives-swiss­com-2025-dead­line-in-fi­bre-op­tic-dis­pute/​76393735 ↩︎

reuters.com

www.reuters.com

Please en­able JS and dis­able any ad blocker

The Anti-Amazon

phenomenalworld.org

We are in a new age of lo­gis­ti­cal prowess, led by the dy­namism of Amazon as it strives to carry out dizzy­ingly com­plex forms of or­der ful­fill­ment and de­liv­ery. With the age of agen­tic com­merce just around the cor­ner—think of go­ing to ChatGPT and hav­ing an AI agent scour every web­site for the cheap­est of­fer­ing of the spe­cific dog food you buy—there is an ex­pec­ta­tion that the fu­ture of re­tail is near in­fi­nite as­sort­ment and ul­tra-fast de­liv­ery. Consumers want the ex­act fla­vor of the ex­act thing that they’re look­ing for, and they want it at their doorstep now. It seems some­times that we are test­ing the bounds of in­fra­struc­tural ca­pac­ity and au­toma­tion in lo­gis­tics to ful­fill this dream.

There are a few things wrong with this dream, how­ever, and the first, as I’ll re­view in a mo­ment, is sim­ply that it might not be so de­sir­able. Even if you think it is prefer­able at an in­di­vid­ual level, there are good rea­sons to ques­tion the so­cial value of the lo­gis­ti­cal com­plex­ity that it ne­ces­si­tates. Home de­liv­ery of sin­gle-pack­aged items en­tails an en­tirely dif­fer­ent cost struc­ture than freight trucks dri­ving to con­sumer-fac­ing ware­houses de­liv­er­ing en­tire pal­lets of goods to be dri­ven home by cus­tomers them­selves. Two com­pa­nies have emerged with ideal-type busi­ness mod­els that dra­ma­tize the dif­fer­ent economies at each end of this spec­trum: Amazon and Costco. Late to the e-com­merce game, min­i­mally in­vested in their dis­tri­b­u­tion net­work, and com­mit­ted as ever to an ar­ti­fi­cially-lim­ited as­sort­ment, Costco is the anti-Ama­zon. It em­bod­ies the pre­cise op­po­site of every­thing imag­ined by the e-com­merce fu­tur­ists—and yet some­how its rev­enue has grown by an av­er­age of more than 10 per­cent every year for the last five years.

Constraint and so­cial­ity

In some cases, con­sumers might want ac­cess to full prod­uct as­sort­ment: when, for in­stance, there’s a spot in the home that only fits a fur­nish­ing of cer­tain di­men­sions, or when mak­ing a ma­jor elec­tron­ics pur­chase. But in gen­eral, scrolling through op­tions and read­ing through re­views on­line for every con­sump­tion choice is over­whelm­ing and anx­i­ety-pro­duc­ing: infinite, mean­ing­less op­tions can re­sult in some­thing like a con­sumer fugue state,” The Atlantic once ar­gued.

One bril­liant fea­ture of the Costco ex­pe­ri­ence is, para­dox­i­cally, the con­straint: as op­posed to Amazon, with its near in­fi­nite as­sort­ment, or even Walmart, which has ap­prox­i­mately 130,000 SKUs (stock keep­ing units, or dis­tinct items) in the av­er­age Supercenter, any given Costco will only hold 4,000 SKUs to choose from. While most re­tail­ers to­day as­sume that con­sumers want ever greater as­sort­ment, Costco’s pop­u­lar­ity speaks to a coun­ter­vail­ing de­sire for less choice. Indeed, the pre-se­lec­tion of items for sale in their ware­houses is part of the value propo­si­tion: not only are you go­ing to get a lot of a par­tic­u­lar thing for a good price, but you also won’t have to de­lib­er­ate over mi­cro-dif­fer­ences in a more ro­bust as­sort­ment.

In other words, win­now­ing se­lec­tion is a ser­vice, not a lim­i­ta­tion—es­pe­cially with Costco’s prod­uct cat­a­log. Costco is not known for hav­ing the cheap­est goods, but it is known for hav­ing the cheap­est price on its goods, and that is be­cause its buy­ing team has closer re­la­tion­ships with sup­pli­ers than any other big re­tailer. Such scrutiny and com­mu­ni­ca­tion point away from low-road sup­pli­ers. This is a struc­tural ef­fect of Costco’s con­scious choice to of­fer a low SKU count: fewer prod­ucts to in­ves­ti­gate means more time to in­ves­ti­gate each prod­uct, and a nat­ural grav­i­ta­tion away from the bar­gain base­ment. That its mem­ber-cus­tomers have come to ex­pect a cer­tain qual­ity of every­thing in their stores re­in­forces this dy­namic.

The low SKU count also al­lows Costco nat­u­rally to do some­thing that Amazon does by squeez­ing sup­pli­ers: a low or even neg­a­tive cash con­ver­sion cy­cle (CCC). The CCC is a cor­po­rate fi­nance mea­sure of how long it takes to turn in­ven­tory into cash through sales. Amazon of­ten ne­go­ti­ates de­layed pay­ment terms with sup­pli­ers, lean­ing on them to al­low pay­ment win­dows longer than the thirty-day in­dus­try norm. Meanwhile, given the speed of its e-com­merce busi­ness, Amazon is of­ten re­ceiv­ing pay­ment from con­sumers way be­fore it has to pay sup­pli­ers, es­sen­tially giv­ing the re­tailer in­ter­est-free cash. Costco en­joys the same ben­e­fit of a short or neg­a­tive CCC, but with­out hav­ing to anger sup­pli­ers sim­ply be­cause fewer SKUs means a faster-mov­ing in­ven­tory for the SKUs that they do carry. In other words, when a Costco store re­ceives a ship­ment of a par­tic­u­lar item from a sup­plier, it is of­ten go­ing to sell every unit in that ship­ment in less than a month, thanks to its scale and the sim­ple fact that that par­tic­u­lar item is go­ing to be the only va­ri­ety in store.

Costco’s in-store ex­pe­ri­ence is an­other draw for cus­tomers, and this too runs counter to the pre­vail­ing view in the future of re­tail” con­ver­sa­tion. While the e-com­merce share of re­tail has been steadily grow­ing, it’s still un­der 17 per­cent in the United States, and one won­ders in a so­ci­ety as anti-so­cial as our own if cus­tomers find in-per­son shop­ping, de­graded a social” ven­ture as it is, de­sir­able even in its in­con­ve­nience.

Shopping at Costco is al­ways some­what har­ried: no shop­per can avoid lines at the reg­is­ters or traf­fic jams in the aisles, even on the week­days. It is the pre­cise op­po­site of e-com­merce con­ve­nience. And yet mem­bers not only don’t seem to mind the nui­sance, they pos­i­tively em­brace it. Costco no­tably spends very lit­tle on ad­ver­tis­ing, but it does­n’t re­ally need to, given the re­mark­able amount of free at­ten­tion it gets by word of mouth and on so­cial me­dia from en­thu­si­as­tic shop­pers talkin’ deals.” Costco has be­come a re­tail des­ti­na­tion with a very loyal mem­ber­ship base (its an­nual mem­ber­ship re­newal rate is typ­i­cally above 90 per­cent) while of­fer­ing a sparse, no-frills re­tail ex­pe­ri­ence.

Benefits of sim­plic­ity

But con­sumer pref­er­ence is only one met­ric by which to judge the de­sir­abil­ity of assortment and home de­liv­ery” vs. constraint and in-per­son shop­ping.” It should be re­mem­bered that the term logistics” comes from a mil­i­tary con­text—the French word for the art of mov­ing, quar­ter­ing, and sup­ply­ing troops”—and lo­gis­ti­cal suc­cess in busi­ness means most fun­da­men­tally the suc­cess with which goods are sup­plied to the cus­tomers who need them. Applied so­cially, our un­der­stand­ing of lo­gis­ti­cal suc­cess must be based not only on how goods are be­ing sup­plied to any par­tic­u­lar per­son, with their own smat­ter­ing of in­di­vid­ual pref­er­ences, but also on how they are be­ing sup­plied as a whole.

At the so­cial level, lo­gis­ti­cal suc­cess can be mea­sured in terms of cost ef­fi­ciency. This cost can be un­der­stood in ac­count­ing terms as over­head: the ware­houses, the ve­hi­cle fleet, fuel costs, fork­lifts. An en­ter­prise is more ef­fi­cient when it can spread these costs over a larger vol­ume of goods. A cost-ef­fi­cient op­er­a­tion is also sim­ple, in that it’s re­li­able and not prone to dis­rup­tion. The more com­pli­cated an op­er­a­tion, the more likely it is to fail. A sim­ple op­er­a­tion also puts fewer de­mands on trans­porta­tion in­fra­struc­ture—an ur­gent ques­tion in con­gested ur­ban en­vi­ron­ments.

To put it crudely, hav­ing some­one in a Sprinter van de­liver a re­cently-pur­chased tooth­brush to your doorstep is sim­ply not a uni­ver­sal­iz­able ac­tion, from ei­ther a busi­ness or lo­gis­ti­cal stand­point. It is a mod­ern feat that Amazon is ca­pa­ble of do­ing this, but that it can be done does not mean that it should, nor even that it can be done writ large. For most con­sump­tion, it is far more ef­fi­cient for peo­ple to han­dle the last-mile de­liv­ery” them­selves by go­ing to stores and buy­ing a good amount of stuff when they do so. This keeps de­liv­ery vans off the road, and it min­i­mizes car trips for nec­es­sary pur­chases. For the re­tail­ers, it sup­presses un­nec­es­sary mark-up both by keep­ing over­head costs low and by sim­pli­fy­ing over­all lo­gis­ti­cal op­er­a­tions.

Costco’s in­come state­ments as re­ported in its Form 10-K in­clude the stan­dard op­er­at­ing ex­pense cat­e­gory for Selling, General, and Administrative” costs. This cat­e­gory is con­sis­tently and qual­i­ta­tively lower than any of its com­peti­tors’—10 per­cent of sales, com­pared to Amazon’s de­liv­ery costs of 40 per­cent of non-AWS sales. One of the rea­sons for this is the bare bones na­ture of the Costco dis­tri­b­u­tion net­work. At Costco’s depots” (as op­posed to their stores, which the com­pany calls warehouses”), all in- and out­bound in­ven­tory is cross-docked in pal­let quan­ti­ties: full pal­lets come in from sup­pli­ers on one side of the build­ing, work­ers on elec­tric pal­let jacks move those pal­lets from one side to the other, and full pal­lets are loaded onto trucks bound for stores. There is no pal­let break­down at a Costco de­pot, no con­veyor belts, no fancy au­toma­tion.

Such low over­head not only al­lows Costco to de­liver on low prices to their cus­tomers; it also al­lows the com­pany to pay rel­a­tively high wages to their work­ers. According to Indeed, Walmart pays re­tail sales as­so­ci­ates an av­er­age of $16.23 an hour, and Amazon pays ware­house as­so­ci­ates an av­er­age of $19.14 an hour. Costco pays front end as­so­ci­ates an av­er­age of $21.29 an hour. This has al­lowed Costco to achieve an as­ton­ish­ingly low rate of la­bor turnover: com­pared to 60 per­cent turnover in re­tail gen­er­ally and 150 per­cent in Amazon ware­houses, the an­nual work­force turnover rate at Costco is just 6 per­cent. This is of­ten treated in the busi­ness press as a mat­ter of com­pany culture,” but it has a clear eco­nomic un­der­pin­ning. When you min­i­mize over­head, you can sim­ply pay work­ers more with­out squeez­ing your over­all mar­gin.

As I’ve said else­where, it’s ironic that Jeff Bezos orig­i­nally got the idea for Prime, Amazon’s mem­ber­ship model, from for­mer Costco CEO Jim Sinegal. Prime en­ti­tles mem­bers to free two-day de­liv­ery on over 300 mil­lion prod­ucts (in ad­di­tion to stream­ing ser­vices). With such a wide range of pos­si­ble sin­gle-item or­ders, free de­liv­ery en­cour­ages less bundling of cus­tomer pur­chases. Whereas Costco mem­ber­ship helps to re­duce over­head, Amazon mem­ber­ship in­creases it. Meeting two-day de­liv­ery de­mand re­quires dra­matic in­vest­ments in their dis­tri­b­u­tion net­work, which is re­flected in the higher share of sales ac­counted for by Amazon’s de­liv­ery costs. Lower over­head means more for work­ers, but it also means less or­ga­ni­za­tional stress on those work­ers, as Costco em­ploy­ees are not sub­ject to the quo­tas and sur­veil­lance that Amazon’s e-com­merce busi­ness de­mands.

We don’t typ­i­cally praise Costco for its lo­gis­tics in the way that we do Amazon. But the for­mer in fact of­fers a far more lo­gis­ti­cally el­e­gant and so­cially ben­e­fi­cial model of goods pro­vi­sion than the lat­ter. Amazon dom­i­nates when it comes to lo­gis­ti­cally-com­plex op­er­a­tions, but there is no in­her­ent rea­son to pre­fer com­pli­cated op­er­a­tions to sim­ple ones. If any­thing, sim­plic­ity should be the rule. Why do you need to fig­ure out how to in­te­grate ro­botic arms into a ful­fill­ment op­er­a­tion dom­i­nated by au­tonomous mo­bile units when you can cross-dock full pal­lets? Is it more lo­gis­ti­cally im­pres­sive to solve dif­fi­cult prob­lems or to elim­i­nate the need to solve them in the first place?

That said, there is no ques­tion that, in a bet­ter so­ci­ety than the one we have, key parts of Amazon’s op­er­a­tion would be re­tained for of­fer­ing func­tions that con­tribute to the so­cial good. The ca­pac­ity to de­liver pre­scrip­tion med­i­cines same-day to the el­derly is a gen­uine so­cial con­tri­bu­tion. (Academics who like to talk about counter-logistics,” a po­lit­i­cal ori­en­ta­tion aimed at dis­man­tling lo­gis­ti­cal power, tend to ig­nore the pos­i­tive so­cial ben­e­fits that mod­ern lo­gis­tics pro­vides.)

But if we’re look­ing for a gen­er­al­iz­able model for the so­cial pro­vi­sion of goods, Costco of­fers a foun­da­tion­ally use­ful blue­print for every­day per­sonal con­sump­tion while Amazon does not. Amazon is hop­ing that its foray into gro­cery and every­day es­sen­tials will en­cour­age more or­der bundling, and given the im­por­tance it’s ac­cord­ing to this seg­ment, it will no doubt con­tinue to make head­way there. But to date it has still not been able to make the con­ver­sion away from be­ing an on­line con­ve­nience store, which tells you some­thing im­por­tant about its model: Amazon is there to fill in the gaps of a dom­i­nant mode of goods pro­cure­ment, not to re­place it.

Lessons for pub­lic gro­cery

In May, New York City mayor Zohran Mamdani re­it­er­ated his ded­i­ca­tion to cre­at­ing a pub­lic op­tion in gro­cery, an­nounc­ing plans to roll out one pub­lic gro­cery store in each bor­ough, with two lo­ca­tions in the Bronx and Manhattan al­ready scouted. The pub­lic gro­cery store is a model long over­due for wide­spread test­ing out, and as ex-Whole Foods Vice President Errol Schweizer has force­fully ar­gued, there is al­ready a shin­ing ex­am­ple of it in the mil­i­tary com­mis­sary sys­tem. Commissary prices are typ­i­cally 25 – 30 per­cent lower for vet­er­ans and mil­i­tary fam­i­lies.

The may­or’s crit­ics have un­sur­pris­ingly set­tled on the cri­tique that Mamdani’s plan will use tax­payer dol­lars to make life even harder for strug­gling gro­cers in NYC—conceding the idea that it will in­deed re­sult in cheaper gro­ceries for New Yorkers. This is the ter­rain on which they want the dis­course to play out be­cause they ex­pect, not with­out some jus­ti­fi­ca­tion, that spend­ing on this pro­ject will in­volve an in­ef­fi­cient use of re­sources that is not worth the so­cial ben­e­fit it pro­vides. They will be comb­ing through the re­ceipts to find that one ex­pense that il­lus­trates gov­ern­ment in­ef­fi­ciency or even graft.

One sim­ple way to keep over­head low and stay cash pos­i­tive is to fol­low the Costco model: low SKU count, high vol­ume. The low SKU count is not only a way to have a de­sir­able cash con­ver­sion cy­cle (an im­por­tant way of beat­ing back crit­ics on the right); it also cre­ates the op­por­tu­nity to de­velop re­la­tion­ships with good sup­pli­ers. There will be a temp­ta­tion to in­vest in giv­ing these stores that retail look,” with con­sul­tants jump­ing in to em­pha­size the im­por­tance of shelf place­ment and sig­nage. To my mind, the aisles could look much more like Costco ware­houses, but with full case stacks in­stead of pal­lets, pro­vided that shop­pers know the city has made the ef­fort on the front end to work with high-road sup­pli­ers. A solid mar­ket­ing cam­paign around the re­la­tion­ships that the city has de­vel­oped with lo­cal sup­pli­ers will do more to drive traf­fic than the usual re­tail gim­micks.

Volume is the other key con­sid­er­a­tion, and if I were on Mamdani’s team, I would deem­pha­size the one in each bor­ough” line. Mamdani has said that these stores will buy and sell at whole­sale prices” in part by centraliz[ing] ware­hous­ing and dis­tri­b­u­tion,” but cen­tral ware­hous­ing and dis­tri­b­u­tion on five stores does­n’t mean much. When Costco had five stores, they had no cen­tral dis­tri­b­u­tion net­work be­cause they did­n’t need it. Volume will be what makes cen­tral­iz­ing ware­hous­ing and dis­tri­b­u­tion worth­while, and for that Mamdani’s team will need to be open to achiev­ing the scale economies that the math will point to. Errol Schweizer and food sys­tems ex­pert Raj Patel have ar­gued as much else­where, sug­gest­ing at least twenty stores.

There are many other lessons to learn from Costco, but one that sticks out to me as per­fectly re­pro­ducible within the con­text of pub­lic gro­cery stores is choos­ing a sin­gle loss leader that the sys­tem be­comes known for: in Costco’s case, the $1.50 hot dog and soda combo (that price has not changed for over forty years). For NYCs pub­lic gro­cery stores, how about a $2.12 ha­lal wrap?

It’s worth not­ing that Costco traces its lin­eage back to Fedco, or the Federal Employees Distributing Company, a mem­ber­ship store started by post of­fice em­ploy­ees in 1948. Fedco was es­sen­tially copied by Sol Price when he cre­ated Price Club, Costco’s pri­mary com­peti­tor un­til the two merged in 1993. The ba­sic idea be­hind Fedco was that fed­eral em­ploy­ees could lever­age their col­lec­tive buy­ing power to elim­i­nate tra­di­tional re­tail store markup. It was, in essence, a re­mark­able tes­ta­ment to the power of the pub­lic purse, one that in­spired the cre­ation of a re­tail be­he­moth that nat­u­rally holds lessons for ex­er­cis­ing that power once more.

Filed Under

GitHub - jamesob/local-llm: Everything I know about running LLMs locally

github.com

jame­sob’s guide to run­ning SOTA LLMs lo­cally

Note: noth­ing in this README aside from the ta­bles was writ­ten by AI.

Have $2k burn­ing a hole in your pocket and want some lo­cal, state-of-the-art ma­chine in­tel­li­gence?

How about $40k?

If Dario and Altman are giv­ing you heart­burn (they should be), read on to fig­ure out how to run this new kind of com­put­ing lo­cally.

In this repo you’ll find

the hard­ware I use to run SOTA lo­cally,

why I bought what and lit­tle-known se­crets for con­fig­ur­ing it,

why I bought what and lit­tle-known se­crets for con­fig­ur­ing it,

how I run speech-to-text (STT) lo­cally,

ready-to-run con­fig­u­ra­tion for run­ning mod­els I think are good within Docker con­tain­ers.

Contents

My setup

I was lucky/​dumb enough to buy 4x RTX Pro 6000s back when they were cheaper. Because RAM is now so ex­pen­sive, I opted to build a last-gen DDR4 sys­tem to host these cards, the parts for which I got off eBay. This al­lowed me to keep base sys­tem cost rea­son­able while still get­ting a lot of VRAM.

Another some­what un­usual thing I did was to use PCIe4 switches (from c-payne.com). This al­lows the GPUs to com­mu­ni­cate to one an­other directly” at wire speeds dur­ing the allre­duce step in ten­sor par­al­lelism, rather than hav­ing to send all data through the PCI root com­plex. The up­shot of this is re­duced la­tency be­tween the cards with less of a need for ex­pen­sive PCIe5 hard­ware.

Consequently, I’m spend­ing money on VRAM (where it counts) rather than on a PCIe5/DDR5 base sys­tem, which is ter­rif­i­cally ex­pen­sive as of July 2026.

My par­tic­u­lar BOM is de­tailed be­low.

How much are you will­ing to spend?

~$2k

A great way to go is 2x RTX 3090s for a to­tal of 48GB VRAM to­tal. You can then run Qwen3.6 – 27B, which is an awe­some model.

You can also run SOTA speech-to-text (STT) with whis­per-large-v3, which I find very use­ful. That’s the model - you’d then ac­cess it with my cross-plat­form stt har­ness.

I’ve found lo­cal STT sur­pris­ingly use­ful - and I feel com­fort­able us­ing it, un­like a hosted equiv­a­lent. You can find a ready-to-run con­fig in ./runners/stt that only as­sumes the pres­ence of ~11GB of VRAM on an Nvidia GPU.

~$40k

At this price level, you get the next step up in model in­tel­li­gence. Something pretty close to Claude Opus.

You’d buy 4x RTX 6000 Pros for a to­tal of 384GB of VRAM.

Current best mod­els for 4x RTX6kPRO

Other ap­proaches

Note: these are my rec­om­men­da­tions, but there are other com­pletely valid ways to spend your money. For ex­am­ple, there’s prob­a­bly also some regime where rather than get­ting 4 rtx6kpros, you al­lo­cate most of your money to build­ing out a linked 4x DGX Spark clus­ter for a to­tal of 512GB VRAM and use that as the slow, big brain to drive Qwen3.7 – 27b to do the rote tasks quickly.

Hardware

Here’s the hard­ware I wound up pur­chas­ing for the 4x RTX 6000 pro ma­chine.

Base sys­tem

A mod­est, last-gen EPYC sys­tem pur­chased in parts al­most en­tirely from eBay.

GPUs

c-payne PCIe Gen4 Switch Sub-BOM (c-payne.com)

GPU mount

I had to cus­tom fab­ri­cate a wood en­clo­sure for the PCI switch and GPUs, which took about a day.

I found the PCI switch’s builtin fan very loud and seem­ingly use­less, so I sim­ply un­plugged that from the board.

Hoarding model weights

I save all model weights lo­cally on a ZFS filesys­tem that’s repli­cated across the two 8TB dri­ves, which is mounted at ~/storage.

For any model I want to run, I first down­load the model us­ing

hf down­load <model-name> –local-dir ~/storage/<model-name>

Running mod­els

Once the model weights are cached lo­cally, I have a spe­cific di­rec­tory for each model that con­tains a docker-com­pose.yml file that cor­dones off the run­ning of each model to its own Docker con­tainer.

You can find these con­fig­u­ra­tions in ./runners/.

Each con­tainer mounts in ~/storage/models in read-only mode to ob­tain the weights that I’ve cached lo­cally.

I then use open­code hosted on a VM on an­other ma­chine to ac­cess the mod­els once they’re serv­ing on http://​clank.j.co:5000.

I use a net­work-in­ter­nal DNS server to point clank.j.co to the LLM ma­chine, but you could sim­ply do http://&​lt;llm-ma­chine-ip>:5000 too.

The har­ness it­self

I cre­ated a VM and clanked up an ap­pli­ca­tion that ba­si­cally just cre­ates a tmux ses­sion for each di­rec­tory within the VMs ~/src tree, which then runs an open­code in­stance that backs up to the in­fer­ence ma­chine’s HTTP API (http://​clank.j.co:5000).

One key to mak­ing the open­source mod­els good is tool­ing them prop­erly; a sum­mary of my skills/ is:

camo­fox, kagi.com API key, and searXNG for web brows­ing and search,

Telegram bot for com­mu­ni­ca­tion and alert­ing,

a lo­cal pri­vate Gitea in­stance for col­lab­o­rat­ing on source code.

The clanker will ei­ther work with me in­ter­ac­tively in a ses­sion, or can be farmed off to work on Gitea is­sues and file PRs there.

All this hap­pens in a sand­boxed VM where the only com­mu­ni­ca­tion back to the host sys­tem hap­pens via a shared filesys­tem mount, so the thing can go ham and in­stall what­ever it wants.

Getting the PCI switches to work prop­erly

There was a lot of fid­dling with the BIOS in or­der to make sure the moth­er­board was­n’t down­reg­u­lat­ing the PCI switch speeds.

BIOS Configuration (ROMED8 – 2T)

Reducing gain on the redriver

Per c-payne’s ad­vice, I did re­duce the gain to lvl 3” us­ing his tool, which was prob­a­bly the most finicky part of the process.

The gain level is go­ing to be a func­tion of how long your SAS con­nec­tor ca­bles are.

Picking the right SAS ca­bles

I screwed up and or­dered too few of the ca­bles from c-payne di­rectly, so I bought what I thought was the same SAS ca­ble off of Amazon. There was ac­tu­ally a slight dif­fer­ence that was caus­ing is­sues, and I had to re­order ca­bles - so dou­ble-check that you’re get­ting the right stuff!

Kernel / GRUB Parameters

# /etc/default/grub GRUB_CMDLINE_LINUX=“iommu=off amd_iommu=off nomod­e­set” sudo up­date-grub

# nvidi­a_uvm P2P fix echo options nvidi­a_uvm uvm_dis­able_hmm=1’ | sudo tee /etc/modprobe.d/uvm.conf sudo up­date-initramfs -u

Without iommu=off, NCCL hangs on multi-GPU P2P.

ACS Disable (critical for switch P2P)

With ACS en­abled (default), P2P traf­fic gets bounced through the CPU root port in­stead of stay­ing in­side the switch fab­ric, negat­ing the switch en­tirely. pcie_ac­s_over­ride re­quires a patched ker­nel, so we dis­able via set­pci at run­time.

# /usr/local/bin/disable-acs.sh #!/bin/bash if [ $EUID -ne 0 ]; then echo ERROR: must be run as root” exit 1 fi

for BDF in $(lspci -d *:*:*” | awk {print $1}’); do set­pci -v -s ${BDF} ECAP_ACS+0x6.w > /dev/null 2>&1 if [ $? -ne 0 ]; then con­tinue fi echo Disabling ACS on $(lspci -s ${BDF})” set­pci -v -s ${BDF} ECAP_ACS+0x6.w=0000 done

Run on every boot via sys­temd oneshot:

# /etc/systemd/system/disable-acs.service [Unit] Description=Disable PCIe ACS for GPU P2P After=multi-user.target

[Service] Type=oneshot ExecStart=/usr/local/bin/disable-acs.sh

[Install] WantedBy=multi-user.target

Verify: lspci -vvv | grep ACSCtl should show all mi­nus signs, and nvidia-smi topo -m should show PIX be­tween all four GPUs (not PHB/NODE).

Use ./tools/measure-gpu-speed.sh to mea­sure this eas­ily.

GPU Power Limiting

In or­der to avoid in­stalling a 220V cir­cuit, I (probably un­wisely) run this rig on a sin­gle 110V cir­cuit, but I power reg­u­late the cards.

Persistence mode + power cap ap­plied at boot via sys­temd (install-gpu-power-limit.sh):

sudo nvidia-smi -pm 1 sudo nvidia-smi -pl 350 # 350W per GPU (default 600W)

350W/GPU = 1,400W GPU load, sized for the PSU bud­get. During the in­terim sin­gle-1700W-PSU phase (before the 240V cir­cuit), cards ran at ~260W (4×260 = 1,040W GPUs + ~280W sys­tem ≈ 1,320W to­tal).

Verify: nvidia-smi –query-gpu=index,power.limit,power.draw –format=csv

Result

Upstream: Gen4 x16 (~30 GB/s to CPU). P2P through switch: 27.5 GB/s uni­di­rec­tional / 50.4 GB/s bidi­rec­tional, 0.37 – 0.45 µs la­tency, i.e. Gen4 line rate. Note: lspci may still show down­stream GPU links as 2.5GT/s (downgraded)” at idle if ASPM is ac­tive any­where; this is cos­metic. Links re­train to Gen4 un­der load.

Resources

A fre­quently up­dated repo on get­ting the most out of 4, 6, or 8 RTX 6000 Pro cards: https://​github.com/​lo­cal-in­fer­ence-lab/​rtx6kpro

Indie PCI switches that I use: https://​c-payne.com

RTX6kPRO dis­cord server; lotta guys bench­ing and test­ing new mod­els: https://​dis­cord.gg/​QM­N­vFkuDN

Espionage Against the European Parliament: Member of Committee Investigating Spyware Hacked with Pegasus - The Citizen Lab

citizenlab.ca

Key Findings

Former Member of the European Parliament, Stelios Kouloglou, was re­peat­edly hacked with NSO Group’s Pegasus spy­ware while on the com­mit­tee in­ves­ti­gat­ing Pegasus spy­ware abuses.

Kouloglou was in­fected dur­ing key pe­ri­ods of PEGA com­mit­tee ac­tiv­ity, and the spy­ware would have likely cap­tured non-pub­lic in­for­ma­tion about com­mit­tee ac­tiv­i­ties, pos­si­bly breach­ing EU par­lia­men­tary con­fi­den­tial­ity and priv­i­lege frame­works.

We are not at­tribut­ing these in­fec­tions to a par­tic­u­lar gov­ern­ment at this time, and found no in­di­ca­tions that the Greek Government is re­spon­si­ble. Instead, we note an over­lap be­tween the first in­fec­tion and a pre­vi­ously iden­ti­fied Pegasus cam­paign tar­get­ing Russian and Belarusian-speaking ex­iled jour­nal­ists and ac­tivists in Europe, sug­gest­ing a Pegasus cus­tomer with au­tho­riza­tion to spy in mul­ti­ple European coun­tries is re­spon­si­ble.

Background

Stelios Kouloglou is a promi­nent Greek in­ves­tiga­tive jour­nal­ist who was elected as a Member of the European Parliament in 2015. He re­ported for Greek ra­dio and TV from Paris (1983 – 84), Moscow (1989 – 93), and Yugoslavia (1992 – 95). He later founded and re­ported for Television Without Borders (TVXS) start­ing in 2008.

Kouloglou was elected to the European par­lia­ment as an in­de­pen­dent in the Syriza par­ty’s elec­toral list (affiliated with the Left). He was elected to the next par­lia­men­tary term in the 2019 European elec­tions.

Kouloglou was a sub­sti­tute mem­ber of the European Parliament’s Committee of Inquiry to in­ves­ti­gate the use of Pegasus and equiv­a­lent sur­veil­lance spy­ware (PEGA Committee) from March 24, 2022 to July 18, 2023. The PEGA Committee was es­tab­lished on March 10, 2022 fol­low­ing the 2021 pub­li­ca­tion of the Pegasus Project and other re­port­ing which re­vealed European gov­ern­ments used spy­ware to sur­veil jour­nal­ists, ac­tivists, politi­cians, and other cit­i­zens. Led by MEP Sophie in t Veld, the PEGA Committee was tasked to in­ves­ti­gate the scope of spy­ware us­age in con­tra­ven­tion of EU law, fo­cus­ing on Pegasus and equiv­a­lent sur­veil­lance spy­ware.”

While sit­ting as an MEP, Kouloglou con­tin­ued to write opin­ion pieces and re­port for TVXS. He left the Syriza party in October 2023 and sat as an in­de­pen­dent un­til the elec­tions of June 2024, af­ter which he served as a mem­ber of the New Left. His par­lia­men­tary term ended in July 2024.

Kouloglou Infected with Pegasus Spyware

In May 2026, Kouloglou con­tacted the Citizen Lab and we con­ducted a foren­sic analy­sis of ar­ti­facts from his iPhone. We found with high con­fi­dence that his de­vice was suc­cess­fully in­fected with Pegasus spy­ware on or around October 21, 2022, and again on March 6 and 7, 2023.

On 2022 – 10-21 10:16, there was a lookup for a HomeKit email ad­dress rauhare­po888 [@]gmail.com. Two min­utes later, a Pegasus process used mo­bile data. We as­sess that the phone was hacked with the PWNYOURHOME zero-click ex­ploit at this point. PWNYOURHOME ap­peared to first in­volve the at­tacker send­ing a spe­cially crafted NSKeyedArchive that landed in HomeKit, fol­lowed by ma­li­cious con­tent that landed in MessagesBlastDoorService. Apple mit­i­gated the first is­sue with a change to HomeKit in iOS 16.3.1, though we as­sess that they fixed the MessagesBlastDoorServiceissue ear­lier, likely in iOS 16.1.

We ad­di­tion­ally saw Pegasus ac­tiv­ity on Kouloglou’s de­vice be­tween 2023 – 03-06 09:49 and 2023 – 03-07 07:30 that we as­sess is likely linked to the same ex­ploit. On the 2022 and 2023 dates, we as­sess that the de­vice was run­ning iOS 15.5 (19F77).

These find­ings do not pre­clude the pos­si­bil­ity of ad­di­tional in­fec­tions that we have been un­able to cap­ture due to lim­i­ta­tions of avail­able foren­sic data.

Apple Notifications

Further val­i­dat­ing our find­ing of tar­get­ing, our foren­sic analy­sis shows Kouloglou re­ceived mul­ti­ple Apple threat no­ti­fi­ca­tions about tar­get­ing with mer­ce­nary spy­ware on three oc­ca­sions: March 2, 2023, August 29, 2023, and April 10, 2024. It is im­por­tant to note that threat no­ti­fi­ca­tions from Apple and other com­pa­nies are not real-time alerts. They are typ­i­cally sent to users in batches, of­ten months or more af­ter tar­get­ing takes place.

Kouloglou re­ports to us that he did not re­call re­ceiv­ing the Apple no­ti­fi­ca­tions we ob­served.

Targeting Context and PEGA Committee Activities

Kouloglou helped the Citizen Lab re­con­struct his ac­tiv­i­ties dur­ing the pe­ri­ods when he was tar­geted with Pegasus spy­ware (see the de­tailed time­line in the Appendix). Throughout the pe­riod un­der con­sid­er­a­tion, Kouloglou wrote nu­mer­ous ar­ti­cles and gave fre­quent in­ter­views about spy­ware abuses. We sum­ma­rize the key con­tex­tual de­tails in the fol­low­ing sec­tions.

First Pegasus Infection Period: PEGA Hearing Prep, Country Visits

The date of the first known Pegasus in­fec­tion of Kouloglou’s de­vice — October 21, 2022 — aligns with a par­tic­u­larly in­tense pe­riod of ac­tiv­ity around the PEGA Committee’s de­lib­er­a­tions and in­ves­ti­ga­tions.

First, a se­ries of PEGA Committee hear­ings were about to com­mence fol­low­ing the in­fec­tion date, in­clud­ing Big Tech and Spyware” (October 26), Spyware and e-pri­vacy” (October 26), and spy­ware and fun­da­men­tal rights (October 27).

Importantly, the PEGA Committee was also in the midst of prepa­ra­tions for the pub­li­ca­tion of its first draft re­port. Drafts of the re­port were be­ing dis­cussed and cir­cu­lat­ing among PEGA Committee mem­bers and their staff in the weeks lead­ing up to this pub­li­ca­tion. Kouloglou con­firms that the first in­fec­tion date (October 21, 2022) co­in­cided with a pe­riod of in­tense dis­cus­sion and ex­change that pri­mar­ily took place over text mes­sages and email. The first draft of the PEGA Committee Report was de­liv­ered by MEP in t Veld on November 8, 2022. The draft fo­cused on al­le­ga­tions of spy­ware in Poland, Hungary, Greece, Cyprus, and Spain.

In ad­di­tion to the hear­ing and re­port draft­ing, PEGA Committee mem­bers had vis­ited sev­eral European coun­tries as part of their mis­sion. Throughout October, the PEGA com­mit­tee was plan­ning its re­search vis­its to Greece and Cyprus sched­uled for November 1 to 4, 2022. Kouloglou helped with plan­ning and par­tic­i­pated in both vis­its as part of the PEGA Committee de­lib­er­a­tions. Kouloglous’ de­vice was hacked ten days prior to the start of this trip, at a time when com­mu­ni­ca­tions were be­ing ex­changed about the vis­its.

Meeting with Thanasis Koukakis

On October 21, 2022, the ex­act date of the in­fec­tion, Kouloglou was in the hos­pi­tal for elec­tive surgery. He was vis­ited in his hos­pi­tal room by Greek in­ves­tiga­tive jour­nal­ist Thanasis Koukakis, who has worked closely on mer­ce­nary spy­ware is­sues in Greece, and had tes­ti­fied to the PEGA Committee the pre­vi­ous month. In March 2022, the Citizen Lab had con­firmed Koukakis was him­self tar­geted with Intellexa’s Predator spy­ware and he was at this time pur­su­ing le­gal reme­dies and for­mal com­plaints with rel­e­vant au­thor­i­ties in Greece about the spy­ing. Koukakis memo­ri­al­ized his meet­ing with Kouloglou with a pho­to­graph (Figure 2).

Given that the in­fec­tion took place while Kouloglou was a pa­tient at a Greek hos­pi­tal, it is pos­si­ble that con­fi­den­tial med­ical in­for­ma­tion could have been in­ter­cepted from his de­vice, in­clud­ing dis­cus­sions go­ing on in his room. If the spy­ware cap­tured con­ver­sa­tions be­tween Kouloglou and med­ical staff, or de­tails stored on the phone con­cern­ing ap­point­ments, med­ical re­sults, di­ag­noses, and other health re­lated in­for­ma­tion, then the hack­ing of his de­vice may im­pli­cate Greece’s laws con­cern­ing con­fi­den­tial­ity of health-re­lated data, which are con­sid­ered a spe­cial cat­e­gory of per­sonal data and are sub­ject to en­hanced pro­tec­tions (Law 4624/2019 un­der the Greek Penal Code).

Second Pegasus Infection Period: Intense PEGA Deliberations

Kouloglou’s de­vice was hacked with Pegasus spy­ware a sec­ond time, on March 6 and 7, 2023. According to Kouloglou, dur­ing this time frame, the PEGA com­mit­tee was en­gaged in in­tense dis­cus­sions re­lated to the fi­nal draft­ing process. On March 6, 2023 Kouloglou trav­eled from Athens to Brussels and was in Brussels on March 6 and 7 dur­ing the time­frame of the in­fec­tion.

It may also be sig­nif­i­cant that, at this time, PEGA Rapporteur MEP in t Veld was in Greece as part of a mis­sion with the LIBE Committee (Committee on Civil Liberties, Justice and Home Affairs), which is a stand­ing com­mit­tee of the European Parliament pri­mar­ily re­spon­si­ble for draft­ing leg­is­la­tion and pro­vid­ing de­mo­c­ra­tic over­sight around is­sues con­cern­ing hu­man rights, data pro­tec­tion, asy­lum, im­mi­gra­tion, and anti-dis­crim­i­na­tion. On that mis­sion, the LIBE del­e­ga­tion ques­tioned the Greek Director of the National Transparency Authority and other of­fi­cials on the Greek spy­ware scan­dal (report para 183).

As with the pre­vi­ous in­fec­tion dates, the date of this in­fec­tion was also fol­lowed by a string of PEGA hear­ings and a re­search trip to Spain (although Kouloglou did not par­tic­i­pate in that trip him­self). This in­fec­tion took place ap­prox­i­mately two months prior to the adop­tion of the first PEGA Committee re­port (May 8, 2023).

Separately, Kouloglou and Thanasis Koukakis had made ten­ta­tive plans over WhatsApp to meet on or around March 6 and 7, 2023, but ul­ti­mately their in per­son meet­ing did not take place.

The European Parliament Under Surveillance

This is the first time a mem­ber of the PEGA Committee has been pub­licly iden­ti­fied as a vic­tim of Pegasus spy­ware while serv­ing on the Committee.

There have been a few pub­lic cases of MEP tar­get­ing prior to the cre­ation of the PEGA Committee. Four Catalan MEPs were ei­ther di­rectly or in­di­rectly tar­geted with Pegasus: MEP Diana Riba’s de­vices were in­fected in October 2019. Catalan MEP Jordi Solé was tar­geted in June 2020, just prior to tak­ing his seat in the European Parliament. Two other Catalan MEPs were tar­geted through their staff or fam­ily mem­bers: Clara Ponsati (July 2020) and Carles Puigdemont (October 2019 and July 2020). Riba, Solé, and Puigdemont all joined the PEGA Committee: Riba as Vice-Chair, Puigdemont as a mem­ber, and Solé as a sub­sti­tute. They tes­ti­fied about their ex­pe­ri­ences to the PEGA Committee, along­side Antoni Comín and Nikos Androulakis (whose de­vice was tar­geted with Predator spy­ware).

Outside of the PEGA Committee, in February 2024, Politico re­ported that MEPs on the se­cu­rity and de­fence sub­com­mit­tee were asked to have their phones checked af­ter traces of spy­ware were found on two de­vices. French MEP Nathalie Loiseau, chair of the com­mit­tee, con­firmed she was tar­geted with Pegasus. The European Parliament’s IT Services in­formed Bulgarian MEP Elena Yoncheva that her de­vice had been tar­geted in late October 2023.  In May 2024, fol­low­ing the con­clu­sion of the PEGA Committee pro­ceed­ings, German MEP Daniel Freund an­nounced he had been tar­geted with Candiru’s mer­ce­nary spy­ware.

Attribution

While we as­sess with high con­fi­dence that Kouloglou was tar­geted and in­fected with NSO Group’s Pegasus mer­ce­nary spy­ware, we are not at­tribut­ing these in­ves­ti­ga­tions to a spe­cific NSO Group cus­tomer.

Since 2022, when the Citizen Lab first dis­cov­ered the hack­ing of Thanasis Koukakis’ de­vice with Predator spy­ware, the Greek gov­ern­ment has been em­broiled in a grow­ing sur­veil­lance scan­dal in­volv­ing abu­sive tar­get­ing of civil so­ci­ety. However, we have no in­di­ca­tions that this hack­ing was the work of the Greek gov­ern­ment. There are no re­ports that Greece is or was a cus­tomer of NSO Group or a user of Pegasus spy­ware. While the Greek gov­ern­ment is known to have ex­ten­sively abused Intellexa’s Predator mer­ce­nary spy­ware, the Citizen Lab is un­aware of any tech­ni­cal in­di­ca­tors sug­gest­ing Greek se­cu­rity and in­tel­li­gence ser­vices had ac­cess to NSO Group’s Pegasus spy­ware.

However, we be­lieve that the same op­er­a­tor tar­geted both Kouloglou in 2022 and the tar­gets we high­lighted in our May 2024 joint re­port with Access Now. In that re­port, we found that seven Russian and Belarusian-speaking in­de­pen­dent jour­nal­ists and op­po­si­tion ac­tivists based in Europe were tar­geted and/​or in­fected with NSO Group’s Pegasus mer­ce­nary spy­ware. One of the redacted Apple IDs (Email 1) from that re­port is rauhare­po888[@]gmail.com, the same HomeKit email that tar­geted Kouloglou. In our un­der­stand­ing of Pegasus in­fec­tion in­fra­struc­ture dur­ing this pe­riod, we be­lieve that these emails are unique to spe­cific op­er­a­tors. We are un­able to say whether the sec­ond in­fec­tion in 2023 is sim­i­larly con­nected to this op­er­a­tor, or a dif­fer­ent op­er­a­tor.

We fur­ther note that in­fec­tions ap­pear to have been pre­sent on his phone in at least two European ju­ris­dic­tions (We fur­ther note that in­fec­tions ap­pear to have been pre­sent on his phone in at least two European ju­ris­dic­tions (Greece and Belgium). Based on what we know of NSO Group’s li­cens­ing, this would likely in­di­cate that the cus­tomer had a li­cense that en­abled in­fec­tions in mul­ti­ple EU ju­ris­dic­tions, nar­row­ing the list of po­ten­tial Pegasus op­er­a­tors that could be re­spon­si­ble for this case.

Conclusion

The in­fec­tion of a European MEP and PEGA Committee mem­ber’s de­vice is a sig­nif­i­cant and trou­bling find­ing. It is made more trou­bling by the fact that we are un­sure of the sta­tus of the phones of many of the other Committee mem­bers dur­ing the time of its pro­ceed­ings. Short of a com­pre­hen­sive screen­ing, there is no way to know whether any other PEGA Committee mem­bers or their staff may have been sim­i­larly in­fected.

Whichever en­tity is re­spon­si­ble for the hack­ing, the in­fec­tion could have ex­posed strictly con­fi­den­tial ex­changes among PEGA Committee mem­bers and their staff, and other sen­si­tive and con­fi­den­tial par­lia­men­tary pro­ceed­ings, in­clud­ing to par­ties un­der in­ves­ti­ga­tion by the Committee it­self.

The find­ing that a PEGA Committee mem­ber was tar­geted with Pegasus spy­ware dur­ing the Committee’s work high­lights the se­ri­ous threat that mer­ce­nary spy­ware poses to the in­tegrity of de­mo­c­ra­tic processes.

As out­lined above, this case is not the first that a Member of the European Parliament has had their de­vices ei­ther tar­geted or hacked with mer­ce­nary spy­ware, which il­lus­trates the cor­ro­sive na­ture of un­reg­u­lated mer­ce­nary hack­ing.

While we are un­able to con­clu­sively at­tribute these in­fec­tions to a par­tic­u­lar gov­ern­ment agency at this time, and we have no ev­i­dence that the Greek gov­ern­ment was re­spon­si­ble for this case, over­lap with an op­er­a­tor re­spon­si­ble for hack­ing the de­vices of ex­iled Russian and Belarusian-speaking jour­nal­ists and ac­tivists based in Europe war­rants fur­ther in­ves­ti­ga­tion.

Recommendations

In light of our dis­cov­ery, we rec­om­mend that European Union in­sti­tu­tions open im­me­di­ate in­ves­ti­ga­tions to de­ter­mine the scope and scale of this breach of EU pri­vacy and process.

MEPS and Staff: Get Screened

We urge MEPs and their staff that par­tic­i­pated in the PEGA Committee to im­me­di­ately seek foren­sic screen­ing for signs of spy­ware in­fec­tion, and pre­serve work and per­sonal de­vices that may have been tar­geted.

The Directorate-General for Information Technologies and Cybersecurity (DG ITEC) of­fers this spy­ware screen­ing.

The Directorate-General for Information Technologies and Cybersecurity (DG ITEC) of­fers this spy­ware screen­ing.

Exercise vig­i­lance for state-spon­sored at­tack warn­ings, and seek prompt ex­pert as­sis­tance when such warn­ings are re­ceived.

The work of MEPs ex­poses them to more so­phis­ti­cated threats. EU MEPs should en­able Lockdown mode (iPhone) and Advanced Protect for Android. This mode strongly in­creases the pro­tec­tion of a de­vice against mer­ce­nary spy­ware. The DG ITEC may be able to pro­vide ad­di­tional cy­ber­se­cu­rity guid­ance.

European Parliament: Investigate, Increase Reporting & Screening

The European Parliament should con­duct an im­me­di­ate in­ves­ti­ga­tion into spy­ware at­tacks tar­get­ing MEPs and par­lia­men­tary processes, given the sur­veil­lance of the PEGA com­mit­tee de­tailed in this re­port.

Since some time has passed since this par­tic­u­lar at­tack, prompt in­ves­ti­ga­tion is a mat­ter of ur­gency to en­sure that foren­sic traces are not lost.

Since some time has passed since this par­tic­u­lar at­tack, prompt in­ves­ti­ga­tion is a mat­ter of ur­gency to en­sure that foren­sic traces are not lost.

We urge the Parliament to com­mis­sion an an­nual re­port on cy­ber and sur­veil­lance threats to the Parliament and mem­bers to iden­tify ar­eas of vul­ner­a­bil­i­ties, and make rec­om­men­da­tions on how to in­crease par­lia­men­tary se­cu­rity.

Such a re­port could be pro­duced by the European Parliamentary Research Service (EPRS) or other en­ti­ties.

Such a re­port could be pro­duced by the European Parliamentary Research Service (EPRS) or other en­ti­ties.

DG ITEC of­fers op­tional screen­ing for spy­ware for MEPs and staff. This case sug­gests that this ca­pa­bil­ity may be un­der­used. We urge DG ITEC to de­velop a plan to achieve sub­stan­tially higher screen­ing rates, and pub­lish yearly sta­tis­tics on the num­ber of de­vices screened and rates of dis­cov­ery.

We also urge DG ITEC to reg­u­larly cir­cu­late spe­cific guid­ance for MEPs and staff about vig­i­lance to state spon­sored at­tack warn­ings from com­pa­nies like Apple and Google.

We also urge DG ITEC to reg­u­larly cir­cu­late spe­cific guid­ance for MEPs and staff about vig­i­lance to state spon­sored at­tack warn­ings from com­pa­nies like Apple and Google.

We rec­om­mend that DG ITEC con­sider (optionally) col­lect­ing (optionally) and pro­vid­ing to large plat­forms ac­count in­for­ma­tion as­so­ci­ated with MEPs and their staff. DG ITEC could re­quest ad­di­tional scrutiny be de­voted to threats against these ac­counts, and that plat­forms in­form them when they send these ac­counts state-spon­sored threat warn­ings. This in­for­ma­tion could en­sure that state-spon­sored at­tack warn­ings are quickly acted on and that pat­terns are ob­served.

European Commission: Screen Commissioners & Staff for Spyware

We urge the European Commission to un­der­take their own in­ves­ti­ga­tion and screen­ing to de­ter­mine whether com­mis­sion­ers or com­mis­sion staff have been tar­geted with mer­ce­nary spy­ware.

We urge the Commission’s Directorate-General for Digital Services (DG DIGIT) to de­velop a com­pre­hen­sive spy­ware screen­ing and re­sponse ca­pa­bil­ity, along­side reg­u­lar screen­ings, and we note that DG ITEC may be a use­ful in­ter­locu­tor in this en­deavor.

Parliamentary Assembly of the Council of Europe (PACE): Screen Members & Staff for Spyware

Given past PACE com­mit­tee work on mer­ce­nary spy­ware abuses in Europe, we urge an in­ves­ti­ga­tion into whether Members or staff have been tar­geted with mer­ce­nary spy­ware.

We urge the Council’s Directorate of Information Technology (DIT) to con­sult with peer or­ga­ni­za­tions and con­duct reg­u­lar screen­ing of PACE Members and their staff for signs of mer­ce­nary spy­ware tar­get­ing.

National Parliaments: Screen and Secure Your Members

While this case con­cerns a MEP, there is a long his­tory of law­mak­ers tar­geted with Pegasus and sim­i­lar mer­ce­nary spy­ware. We com­mend the DG ITEC for hav­ing de­vel­oped tech­niques for screen­ing mem­bers and we en­cour­age the se­cu­rity ser­vices and over­sight bod­ies of na­tional par­lia­ments to copy this model.

Tech Companies: Make Your Threat Warnings Count

This case il­lus­trates that a re­cip­i­ent of mul­ti­ple threat warn­ings failed to no­tice them. Since the goal of these no­ti­fi­ca­tions should be for a tar­get to take ac­tions, en­sur­ing that the tar­get sees and un­der­stands them is crit­i­cal. UX re­search, in­clud­ing with past no­ti­fi­ca­tion re­cip­i­ents, will be key to cre­at­ing no­ti­fi­ca­tions that cap­ture a re­cip­i­en­t’s at­ten­tion, ex­plain the is­sue, and make the next steps easy.

Note on Research Ethics

All re­search in­volv­ing hu­man sub­jects con­ducted at the Citizen Lab is gov­erned un­der re­search ethics pro­to­cols re­viewed and ap­proved by the University of Toronto’s Research Ethics Board.

Acknowledgements

Thanks to Rebekah Brown and Adam Senft for care­ful re­view, and to Anna Mackay and Claire Posno for com­mu­ni­ca­tions and lay­out sup­port. We are very grate­ful to Stelios Kouloglou and Thanasis Koukakis for con­sent­ing to be named in and par­tic­i­pat­ing in this re­search. Special thanks to Zacharias Kesses and TNG.

Appendix: Timeline of PEGA Deliberations and Infection Dates

On March 20 – 23, PEGA does a re­search mis­sion to Spain. Kouloglou does not travel with this del­e­ga­tion.

Wordgard

wordgard.net

Wordgard [wɜrd-gɑrd] noun A gar­den for cul­ti­vat­ing words. Open-source JavaScript li­brary im­ple­ment­ing an in-browser rich-text ed­i­tor.

Semantic Rich Text Editor System

Wordgard pro­vides a set of tools for build­ing con­tent ed­i­tors. It is not a free-form HTML ed­i­tor, but one where you con­trol pre­cisely what kind of con­tent you sup­port.

Its main dis­tin­guish­ing fea­ture is a pow­er­ful pro­gram­ming in­ter­face that makes the li­brary a good foun­da­tion for cus­tomized ed­i­tors—even com­plex, de­mand­ing ones.

Wordgard is open source un­der a per­mis­sive li­cense (MIT). It is be­ing de­vel­oped on code.haver­beke.berlin. Bug re­ports are very wel­come. Pull re­quests are not ac­cepted.

If you are us­ing Wordgard com­mer­cially, there is a so­cial (but no le­gal) ex­pec­ta­tion that you help fund its main­te­nance. Start here.

Discussing the pro­ject or ask­ing ques­tions is best done on the fo­rum. Bugs should be re­ported through the is­sue tracker.

Introducing the Safari MCP server for web developers

webkit.org

In Safari Technology Preview 247, we’re in­tro­duc­ing the Safari MCP server — a Model Context Protocol server for web de­vel­op­ers that makes your web de­vel­op­ment and de­bug­ging work­flow faster and more pow­er­ful. We know agents are in­creas­ingly in­te­gral to the cod­ing process and the Safari MCP server gives your agent the abil­ity to know how your code ac­tu­ally ren­ders in the browser by con­nect­ing it to a Safari browser win­dow.

Any MCP-compatible client can con­nect to the Safari MCP server. By con­nect­ing your agent to a Safari browser win­dow, your agent can em­u­late what your users ex­pe­ri­ence, giv­ing it the in­for­ma­tion it needs to de­bug more au­tonomously, like ac­cess to the DOM, net­work re­quests, screen­shots, and con­sole out­put.

It speeds up your de­bug­ging process and lets you stay in the com­fort of your ter­mi­nal, which means fewer rounds of hop­ping win­dows and typ­ing prompts to de­bug your code.

The use cases

If you build for the web, then you know about the de­bug­ging dance. It usu­ally goes some­thing like this:

You see some­thing wrong with your site in the browser. You open the con­sole to hunt it down. You click into the styles tab. You see what’s bro­ken. You go back to your code to fix it. Or maybe you take a screen­shot, de­tail the prob­lem to your agent, and let it do the fix­ing for you. Hopefully it gets it right, the bug is fixed, and you can move on.

But when it is­n’t fixed, you go through the work­flow again — Browser. Prompt. Agent.

And again and again, un­til you fi­nally squash the bug.

Regardless of the browser or tools you use, the de­bug­ging work­flow is a lot of clicks, tools, and win­dow hop­ping to make a sin­gle fix, but it does­n’t have to be that way. If you’re al­ready us­ing agents in your de­vel­op­ment work­flow, the Safari MCP server makes your de­bug­ging faster and more ef­fi­cient.

The Safari MCP server en­ables your agent to do more de­bug­ging and trou­bleshoot­ing on its own. Here are just a few ex­am­ples of what it can help with:

Web de­vel­op­ment in Safari. The next time you de­velop in Safari, you’ll ben­e­fit from an up­graded work­flow. Your agent al­ready helps you with your code, now it can do even more by check­ing out how your code ac­tu­ally ren­ders in Safari.

Improve com­pat­i­bil­ity with Safari. Testing in just one browser means miss­ing po­ten­tial bugs in an­other, giv­ing those users a sub­par ex­pe­ri­ence. With the Safari MCP server, your agent can open your site in Safari, in­spect com­puted styles, check lay­out, and com­pare it against what you ex­pect with­out switch­ing win­dows.

Analyze per­for­mance. See what parts of your site are slow­ing things down. The Safari MCP server lets your agent eval­u­ate JavaScript on the page to sur­face per­for­mance met­rics, like nav­i­ga­tion tim­ing and re­source load times, so it can pin­point what’s slow­ing your site down and work on the right fix.

Check for ac­ces­si­bil­ity. The Safari MCP server lets your agent check for com­mon ac­ces­si­bil­ity is­sues like miss­ing la­bels, im­proper ARIA at­trib­utes, and poor con­trast, so you can catch prob­lems that im­pact your users.

Verify any user state. Know that the page is work­ing and look­ing as it should. Your agent can check the state of the form, query an el­e­ment us­ing a se­lec­tor, con­firm spe­cific in­ter­ac­tions, show dif­fer­ent states of a check­out flow, and more. Spend less time on these man­ual checks and em­power the agent to do it for you.

These are just a few of the use cases. However you de­cide to im­ple­ment it, the Safari MCP server helps your agent do more for you and re­duce all the back and forth that web de­vel­op­ment of­ten re­quires. An eas­ier work­flow means more bugs squashed, hap­pier users, and a bet­ter prod­uct.

The tools

Here are the avail­able tools and what they do:

With the Safari MCP server, you no longer have to write the per­fect prompt, care­fully de­scrib­ing to your agent what you’re ex­pe­ri­enc­ing in the browser. You can give your agent the abil­ity to find out for it­self.

How to get started

First you’ll need to in­stall Safari Technology Preview. Once in­stalled, make sure you en­able Safari Settings > Advanced > Show fea­tures for web de­vel­op­ers. Then go to Safari Settings > Developer > Enable re­mote au­toma­tion and ex­ter­nal agents.

If you’re us­ing Claude, you can use the fol­low­ing com­mand in your ter­mi­nal:

claude mcp add sa­fari-mcp-stp — “/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver –mcp

If you’re us­ing Codex, you can use the fol­low­ing com­mand in your ter­mi­nal:

codex mcp add sa­fari-mcp-stp — “/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver –mcp

For other agents, you can put the fol­low­ing in your mcp.json or con­fig.json :

safari-mcp-stp”: { command”: /Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver, args”: [“–mcp”] }

Note that while the above code names the server sa­fari-mcp-stp, you can name it what­ever you like, even just sa­fari. Once you have the Safari MCP server in­stalled, try one of the fol­low­ing prompts:

Find bugs on my site in Safari

How ac­ces­si­ble is my site in Safari?

See how my web­site per­forms in Safari

While each agent works a lit­tle dif­fer­ently, it should­n’t need to be told to use the Safari MCP server ex­plic­itly — it’ll fig­ure it out on its own. Simple prompts like the ones above are enough to kick­start the MCP.

Here’s how a con­ver­sa­tion with an agent us­ing the Safari MCP server might go:

You: Got a bug re­port — some­thing’s bro­ken in Safari on the flight page. Can you fig­ure out what’s go­ing on?

Agent: Sure, let me take a look.

Agent: I found two dis­tinct bugs on the flight page in Safari. Want me to fix them both?

You: Yes. Anything else here that might be caus­ing prob­lems for Safari users?

Agent: Yes, two more things worth flag­ging. The re­sults re­veal an­i­ma­tion is silently bro­ken and the API server startup log is wrong. Should I tackle both as well?

All you need is an ini­tial re­quest to get started, and with the help of the Safari MCP server, your agent can take it from there.

The Safari MCP server runs en­tirely on your lo­cal ma­chine and makes no net­work calls of its own. It also does not have ac­cess to your per­sonal in­for­ma­tion in Safari (e.g. AutoFill or other browser ac­tiv­ity). When it cap­tures page con­tent, screen­shots, or con­sole logs, that data goes di­rectly to the agent you’re run­ning — not to Apple. What hap­pens to that data from there de­pends on the agent and model you’re us­ing. As with any agent you give ac­cess to your browser, only use ones you trust.

Why we built this

There are many ways to build for the web, both with and with­out AI. If AI is a part of your work­flow, we think this tool will help make it even more pro­duc­tive. And if it is­n’t, that’s OK too.

By cre­at­ing this re­source, we hope to make it eas­ier than ever to test and de­bug in Safari by help­ing your agent un­der­stand how things look and work in the browser.

If you end up giv­ing it a try or if this is your first time us­ing an MCP server, let us know what you think.

Find us on­line: Saron Yitbarek on BlueSky, Jen Simmons on Bluesky / Mastodon, and Jon Davis on Bluesky / Mastodon. If you run into any is­sues, file a WebKit bug re­port. Filing is­sues re­ally does make a dif­fer­ence.

GitHub - teamchong/pxpipe: cut Fable 5 token usage by rendering text context as images

github.com

Cut Claude Code’s in­put to­kens by ren­der­ing bulky con­text as im­ages — the same sys­tem prompt, tool docs, and his­tory, in a frac­tion of the to­kens.

An im­age’s to­ken cost is fixed by its pixel di­men­sions, not by how much text is in­side it. Dense con­tent (code, JSON, tool out­put) packs ~3.1 chars per im­age-to­ken vs ~1 char per text-to­ken on real Claude Code traf­fic. px­pipe is a lo­cal proxy that ex­ploits that gap: it rewrites the bulky parts of your re­quest (system prompt, tool docs, older his­tory) into com­pact PNGs be­fore the re­quest leaves your ma­chine.

Savings are work­load-de­pen­dent — px­pipe wins on to­ken-dense con­tent and leaves sparse/​small re­quests un­touched — so these are mea­sured snap­shots, not con­stants. The pri­mary, durable re­sult is in­put-to­ken re­duc­tion: dense sys­tem prompts, tool docs, and his­tory go in as com­pact im­ages in­stead of text (the ex­am­ple above is ≈25k text to­kens ren­dered as ≈2.7k im­age to­kens), every re­quest mea­sured against its own coun­t_­to­kens coun­ter­fac­tual. Dollars are down­stream of that — at cur­rent Fable list prices the to­ken cut lands as a ~59 – 70% lower end-to-end bill (~72 – 74% on com­pressed re­quests; full pric­ing math in the FAQ). But list prices can change to­mor­row and the to­ken count won’t, so to­kens — not dol­lars — are the num­ber to watch. Reproduce both from ~/.pxpipe/events.jsonl.

This is what the model sees in­stead of text:

~48k char­ac­ters of sys­tem prompt + tool docs (this re­po’s own README, FINDINGS, and source), ≈25k to­kens as text, ≈2.7k im­age to­kens as this page. Produced by the real trans­form­Re­quest pipeline: white­space-mini­fied, re­flowed into full rows with ↵ mark­ing orig­i­nal new­lines, OCR in­struc­tion ban­ner co-ren­dered on top. The model reads ren­ders like this at 100/100 on a clean eval (see bench­marks).

Demo

Fable 5 demo (the de­fault, 100/100 reader):

Both demos with both panes on Fable 5 (plain left, px­pipe right).

Fable reads what Opus can’t. The im­aged phrase-count that Opus re­fuses (see the Opus demo be­low): the px­pipe arm counts the ex­act to­ken 10/10 across 39 im­aged filler files (matches grep ground truth line-for-line) and gets the multi-step ledger arith­metic right (8037 → … → 15,021).

Same an­swers, ~7× cheaper. Session to­tals af­ter both demos: plain $42.21, con­text 96% full (964.5k/1M — one task away from forced com­paction) vs px­pipe $6.06 with con­text to spare (73.5k/1M).

Honest caveat, vis­i­ble in the clip: the px­pipe arm an­swered the count first and needed one fol­low-up nudge to also print the ledger bal­ance in the re­quested one-line for­mat; the plain arm fol­lowed the for­mat on the first try. Legibility is solved on Fable — sin­gle-re­ply for­mat com­pli­ance is the re­main­ing rough edge.

Opus 4.8 demo (Opus dis­abled by de­fault):

Side-by-side — plain Claude (left) vs px­pipe (right), both on Opus 4.8 (opt-in; px­pipe is tuned for Fable — see the Fable clip above). Click the im­age to watch (Google Drive).

Demo 1 — fix a fail­ing test suite: both pass; the dash­board shows px­pipe cut the re­quest to a frac­tion of the to­kens (real, server-mea­sured con­text/​to­ken re­duc­tion).

Demo 2 — a big file-con­text (40 files, ~382k to­kens) plus a math ques­tion and a count this phrase” task: the math an­swer (a small text nee­dle) reads on both. The phrase-count needs read­ing the im­aged filler — so px­pipe-on-Opus can’t read it and hon­estly sur­faces that it won’t fab­ri­cate a num­ber (the doc­u­mented lossy limit: ex­act val­ues stay text). Plain, mean­while, bogs down count­ing file-by-file.

Try it (30 sec­onds)

npx px­pipe-proxy # proxy on 127.0.0.1:47821 ANTHROPIC_BASE_URL=http://​lo­cal­host:47821 claude # point Claude Code at it

Open http://​127.0.0.1:47821/ for a live dash­board: to­kens saved, per-ses­sion stats, every text→im­age con­ver­sion side by side, a global kill switch, and run­time model chips in­clud­ing GPT 5.6 and GPT 5.5.

Nothing else changes. Responses stream nor­mally; px­pipe only com­presses the re­quest (your con­text go­ing up), never the mod­el’s out­put. Recent turns stay text; the sys­tem prompt, tool docs, and older bulk his­tory are im­aged.

The hon­est part, read be­fore re­ly­ing on it

It is lossy. px­pipe is a gist tier, not a loss­less store. In a nee­dle-in-haystack eval, ex­act 12-char hex strings in­side dense im­aged con­tent came back 0/15 on Opus and 13/15 on Fable 5, and the fail­ure mode is silent con­fab­u­la­tion: a plau­si­ble wrong value, not an er­ror. Anything you need back byte-ex­act (IDs, hashes, se­crets, ex­act num­bers) must stay text. Recent turns do; a ded­i­cated ver­ba­tim-risk guard is not built yet.

Exact-recall es­cape hatch. px­pipe only im­ages Fable re­quests (PXPIPE_MODELS=claude-fable-5), so any sub­agent on a non-Fa­ble model passes through as text. Route work that needs byte-ex­act val­ues to one — glob­ally with CLAUDE_CODE_SUBAGENT_MODEL=claude-sonnet-4 – 6, or per-agent with model: son­net in the agent front­mat­ter. It reads from source (file/JSONL), not the im­aged his­tory. This cov­ers ex­act-re­call you route on pur­pose; it does not catch a silent mis­read you did not ex­pect — that is the un­built guard above.

Does it break real work? Parity in what we mea­sured: a 10-instance SWE-bench Lite pi­lot (the easy sub­set) re­solved 10/10 on both arms, px­pipe ON at $27 vs OFF at $54 to­ken-equiv­a­lent, and 19 SWE-bench Pro pairs (harder, long-hori­zon) re­solved 14/19 ON vs 15/19 OFF at -60% per-re­quest: ver­dicts agree on 18/19, and the sin­gle split (one ON fail) re-re­solved 3/3 when repli­cated, i.e. run-to-run agen­tic vari­ance, not com­pres­sion. Small n, de­tails and caveats be­low.

Savings are work­load-de­pen­dent. It wins on to­ken-dense con­tent (~1 char/​to­ken: code, JSON, hashes) and loses money on sparse English prose (~3.5 chars/​to­ken). The built-in gate only im­ages con­tent where the math wins, cal­i­brated against N=391 pro­duc­tion rows.

Model scope: one PXPIPE_MODELS CSV con­trols which model bases get im­aged across both fam­i­lies — de­fault claude-fa­ble-5,gpt-5.6 (GPT 5.5 is opt-in; it de­grades on im­aged con­text). Set PXPIPE_MODELS=off to dis­able imag­ing en­tirely, or use ~/.config/pxpipe/config.json with { models”: off” } (or a list). For GPT, px­pipe keeps tool de­f­i­n­i­tions in na­tive JSON (only ver­bose schema prose moves into the im­age) so tool-call­ing stays re­li­able; un­like the Claude path, the GPT path does not add or de­pend on Anthropic cache_­con­trol prompt-cache mark­ers. The dash­board chips can flip any model live with­out chang­ing client con­figs. Opus 4.7/4.8 was the orig­i­nal Claude scope but mis­read ~7% of ren­ders (10200→9400), so it was turned off by de­fault once Fable 5 hit 100/100 with iden­ti­cal im­age billing — opt it back in at your own risk via PXPIPE_MODELS or the dash­board chips. Everything else passes through un­touched.

Benchmarks (reproducible)

Measured with novel ran­dom-num­ber prob­lems the model can­not have mem­o­rized:

SWE-bench Lite pi­lot (end-to-end task qual­ity)

10 SWE-bench Lite in­stances, Claude Code + Fable 5, paired runs through px­pipe ON vs OFF, graded with the of­fi­cial swebench Docker har­ness:

The −65% is per-re­quest (count_tokens probe of each body be­fore com­pres­sion), so it has no turn-count con­found. n=10/​arm, Lite skews easy. Run to­tals, re­ceipts, caveats: eval/​swe-bench/.

SWE-bench Pro bench (harder, long-hori­zon)

19 com­pleted pairs across two runs (2 dropped: check­out failed both arms), same setup, of­fi­cial SWE-bench_Pro-os Docker har­ness:

Verdicts agree on 18/19 (three in­stances failed both arms, one with byte-iden­ti­cal patches across arms). The sin­gle split (navidrome, ON fail) was repli­cated 3x on the ON arm: all three runs pro­duced an iden­ti­cal patch and re­solved, so the orig­i­nal loss was run-to-run agen­tic vari­ance, not com­pres­sion. Receipts: eval/​swe-bench-pro/.

We also ran GSM8K: 96% im­aged. But GSM8K is in train­ing data, so the model re­calls mem­o­rized an­swers through its own mis­reads, in­flat­ing the score, so we lead with the clean novel-num­ber eval in­stead. Reproduce: eval/​gsm8k/ · eval/​nee­dle-haystack/ · eval/​gist-re­call/ · full analy­sis in FINDINGS.md.

FAQ

Is the head­line end-to-end, or only on the re­quests you touched? End-to-end, the whole bill. Most com­pres­sion tools re­port sav­ings only on the in­put slice they touched, which flat­ters the num­ber. The end-to-end de­nom­i­na­tor is every pro­duc­tion re­quest: the small ones px­pipe cor­rectly left un­touched, all cache writes and reads, and all out­put to­kens (which the proxy never com­presses). On a 13,709-request snap­shot that was 59% ($100 → ~$41); a later 8,904-compressed-request trace mea­sured ~70%. Compressed-only runs higher (~72 – 74%) and is quoted sep­a­rately, never as the head­line. The ex­act fig­ure is work­load-de­pen­dent — re­pro­duce it on your own log.

How is the math mea­sured? Both sides of the same re­quest, at the same mo­ment. For every /v1/messages POST the proxy fires a free coun­t_­to­kens probe on the orig­i­nal un­com­pressed body (the coun­ter­fac­tual) in par­al­lel with the real for­ward, and reads Anthropic’s ac­tu­ally-billed us­age block off the re­sponse. Both land in the same row of ~/.pxpipe/events.jsonl, so there is no turn-count or run-to-run con­found. Dollar con­ver­sion uses Fable 5 list ra­tios: in­put ×1.0, cache write ×1.25, cache read ×0.1, out­put ×5. Cache pric­ing is ap­plied iden­ti­cally to both sides, so the caching dis­count can­cels and can­not be dou­ble-counted as savings”. Re-derive it your­self from the events log: the for­mula and field names are doc­u­mented in src/​core/​base­line.ts.

What does it ac­tu­ally com­press? Three kinds of in­put blocks, each be­hind a prof­itabil­ity gate:

large tool_re­sult bod­ies (file reads, com­mand out­put, logs) above ~6k chars of to­ken-dense con­tent

older col­lapsed his­tory: turns be­hind the live tail get re-ren­dered as im­age pages, re­cent turns al­ways stay text

the sta­tic sys­tem prompt + tool docs slab

Everything else passes through byte-iden­ti­cal: your mes­sages, re­cent turns, the mod­el’s out­put (it is the re­sponse, the proxy never touches it), sparse prose, and any­thing too small to win. Non-Fable mod­els pass through en­tirely.

Has it ever failed for real, out­side the bench­marks? Yes, once in weeks of daily use: the model re­called a per­son’s name from im­aged chat his­tory and got it con­fi­dently wrong. No er­ror, just a plau­si­ble wrong name. That is the doc­u­mented fail­ure mode: ex­act strings in im­aged con­tent are not byte-safe. Coding ses­sions tol­er­ate this be­cause the agent re-reads files be­fore edit­ing; pure chat re­call has no such check.

How it works

tool_re­sult string ──► wrap at 1928px-wide columns ──► pack ~92,000 chars/​page ──► PNG[]

The proxy in­ter­cepts /v1/messages, rewrites el­i­gi­ble bulk his­tory into im­age blocks, splices them back cache-friendly (static pre­fix pre­served, so prompt caching keeps work­ing), and for­wards. Per-request events log to ~/.pxpipe/events.jsonl.

The eco­nom­ics: a 1928×1928 im­age costs ≈4,761 vi­sion to­kens and holds up to ≈92,000 chars (≈48,000 text to­kens at the ob­served den­sity), so plain text is cheaper only when it runs denser than ~19 chars/​to­ken. Claude Code tran­scripts are far be­low that (observed 1.91 chars/​to­ken, N=391). The run­time es­ti­ma­tor (estimateImageCount) plus a chars/​to­ken gate de­cides per-re­quest; sparse prose is left as text.

Library use (no proxy)

Same en­gine, no proxy. Render text → PNGs, or run the full cache-safe trans­form:

im­port { ren­der­Text­ToP­ngs, trans­for­mAn­throp­icMes­sages } from pxpipe”;

const imgs = await ren­der­Text­ToP­ngs(tool­Re­sult­Text); // RenderedImage[] const { body, ap­plied, info } = await trans­for­mAn­throp­icMes­sages({ body: re­quest­Bytes, model: claude-fable-5”, });

op­tions.keepSharp(block) pins blocks as text (override the heuris­tic for IDs, hashes, paths); op­tions.emitRe­cov­er­able re­turns the orig­i­nals of im­aged blocks so a state­ful caller can re­cover them — the two halves of the fi­delity con­tract for the lossy lim­i­ta­tion be­low. Runtime is pure-JS (Node and edge/​Work­ers); @napi-rs/canvas is build-time only. Full API, types, and con­stants: src/​core/​in­dex.ts.

Development

pnpm in­stall && pnpm test # 376 tests pnpm run build # re­gen­er­ates dist/

Limitations

Lossy: see the hon­est part” above. Verbatim re­call from im­ages is un­re­li­able.

Render la­tency: en­cod­ing PNGs adds time to large re­quests be­fore they leave (partly off­set by the model in­gest­ing fewer to­kens). Responses stream nor­mally.

ASCII/Latin-1 well tested; CJK works but con­ser­v­a­tively.

Runtime is pure-JS — runs on Node and edge/​Work­ers. @napi-rs/canvas is a build-time-only dev dep (regenerating the glyph at­las), not a run­time dep.

Fable 5 only.

Roadmap

Everything above is mea­sured. Everything here is not. These are hy­pothe­ses, not claims; they ship as num­bers with an n or they get cut.

Sharper glyphs. The 13/15 ver­ba­tim gap is partly font leg­i­bil­ity, not just the model. A per-char con­fu­sion ma­trix across ren­der styles is paused mid-run (eval/glyph-matrix/); if a zero-cost style low­ers read er­ror, the gate com­presses harder at the same fi­delity.

Effective con­text. Dense text car­ries at ~3x fewer to­kens as im­ages. If that holds in the live win­dow and not just the bill, 1M to­kens holds ~2x the real con­tent. Open ques­tion: can a task need­ing ~2M raw con­text run in­side Fable’s 1M once the bulk is im­aged?

Less ac­tive text, sharper model. Long con­texts de­grade rea­son­ing as they fill. Imaging old bulk shrinks what the model ac­tively reads while keep­ing it reach­able. Hypothesis: same in­for­ma­tion, smaller ac­tive con­text, bet­ter long-task ac­cu­racy.

One bet: longer ef­fec­tive con­text and a sharper model on long tasks, from the same Fable 5. Numbers or re­trac­tion, no hype be­tween.

License

MIT.

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.