10 interesting stories served every morning and every evening.




1 824 shares, 35 trendiness

Eight years of wanting, three months of building with AI

For eight years, I’ve wanted a high-qual­ity set of de­v­tools for work­ing with SQLite. Given how im­por­tant SQLite is to the in­dus­try1, I’ve long been puz­zled that no one has in­vested in build­ing a re­ally good de­vel­oper ex­pe­ri­ence for it.

A cou­ple of weeks ago, af­ter ~250 hours of ef­fort over three months3 on evenings, week­ends, and va­ca­tion days, I fi­nally

re­leased syn­taqlite

(GitHub), ful­fill­ing this long-held wish. And I be­lieve the main rea­son this hap­pened was be­cause of AI cod­ing agents.

Of course, there’s no short­age of posts claim­ing that AI one-shot their pro­ject or push­ing back and de­clar­ing that AI is all slop. I’m go­ing to take a very dif­fer­ent ap­proach and, in­stead, sys­tem­at­i­cally break down my ex­pe­ri­ence build­ing syn­taqlite with AI, both where it helped and where it was detri­men­tal.

I’ll do this while con­tex­tu­al­iz­ing the pro­ject and my back­ground so you can in­de­pen­dently as­sess how gen­er­al­iz­able this ex­pe­ri­ence was. And when­ever I make a claim, I’ll try to back it up with ev­i­dence from my pro­ject jour­nal, cod­ing tran­scripts, or com­mit his­to­ry5.

In my work on Perfetto, I main­tain a SQLite-based lan­guage for query­ing per­for­mance traces called

PerfettoSQL. It’s ba­si­cally the same as SQLite but with a few ex­ten­sions to make the trace query­ing ex­pe­ri­ence bet­ter. There are ~100K lines of PerfettoSQL in­ter­nally in Google and it’s used by a wide range of teams.

Having a lan­guage which gets trac­tion means your users also start ex­pect­ing things like for­mat­ters, lin­ters, and ed­i­tor ex­ten­sions. I’d hoped that we could adapt some SQLite tools from open source but the more I looked into it, the more dis­ap­pointed I was. What I found ei­ther was­n’t re­li­able enough, fast enough6, or flex­i­ble enough to adapt to PerfettoSQL. There was clearly an op­por­tu­nity to build some­thing from scratch, but it was never the most im­por­tant thing we could work on”. We’ve been re­luc­tantly mak­ing do with the tools out there but al­ways wish­ing for bet­ter.

On the other hand, there was the op­tion to do some­thing in my spare time. I had built lots of open source pro­jects in my teens7 but this had faded away dur­ing uni­ver­sity when I felt that I just did­n’t have the mo­ti­va­tion any­more. Being a main­tainer is much more than just throwing the code out there” and see­ing what hap­pens. It’s triag­ing bugs, in­ves­ti­gat­ing crashes, writ­ing doc­u­men­ta­tion, build­ing a com­mu­nity, and, most im­por­tantly, hav­ing a di­rec­tion for the pro­ject.

But the itch of open source (specifically free­dom to work on what I wanted while help­ing oth­ers) had never gone away. The SQLite de­v­tools pro­ject was eter­nally in my mind as something I’d like to work on”. But there was an­other rea­son why I kept putting it off: it sits at the in­ter­sec­tion of be­ing both hard and

te­dious.

If I was go­ing to in­vest my per­sonal time work­ing on this pro­ject, I did­n’t want to build some­thing that only helped Perfetto: I wanted to make it work for any

SQLite user out there8. And this means pars­ing SQL ex­actly

like SQLite.

The heart of any lan­guage-ori­ented de­v­tool is the parser. This is re­spon­si­ble for turn­ing the source code into a parse tree” which acts as the cen­tral data struc­ture any­thing else is built on top of. If your parser is­n’t ac­cu­rate, then your for­mat­ters and lin­ters will in­evitably in­herit those in­ac­cu­ra­cies; many of the tools I found suf­fered from hav­ing parsers which ap­prox­i­mated the SQLite lan­guage rather than rep­re­sent­ing it pre­cisely.

Unfortunately, un­like many other lan­guages, SQLite has no for­mal spec­i­fi­ca­tion de­scrib­ing how it should be parsed. It does­n’t ex­pose a sta­ble API for its parser ei­ther. In fact, quite uniquely, in its im­ple­men­ta­tion it does­n’t even build a parse tree at all9! The only rea­son­able ap­proach left in my opin­ion is to care­fully ex­tract the rel­e­vant parts of SQLite’s source code and adapt it to build the parser I want­ed10.

This means get­ting into the weeds of SQLite source code, a fiendishly dif­fi­cult code­base to un­der­stand. The whole pro­ject is writ­ten in C in an

in­cred­i­bly dense style; I’ve spent days just un­der­stand­ing the vir­tual table

API11 and

im­ple­men­ta­tion. Trying to grasp the full parser stack was daunt­ing.

There’s also the fact that there are >400 rules in SQLite which cap­ture the full sur­face area of its lan­guage. I’d have to spec­ify in each of these grammar rules” how that part of the syn­tax maps to the match­ing node in the parse tree. It’s ex­tremely repet­i­tive work; each rule is sim­i­lar to all the ones around it but also, by de­f­i­n­i­tion, dif­fer­ent.

And it’s not just the rules but also com­ing up with and writ­ing tests to make sure it’s cor­rect, de­bug­ging if some­thing is wrong, triag­ing and fix­ing the in­evitable bugs peo­ple filed when I got some­thing wrong…

For years, this was where the idea died. Too hard for a side pro­jec­t12, too te­dious to sus­tain mo­ti­va­tion, too risky to in­vest months into some­thing that might not work.

I’ve been us­ing cod­ing agents since early 2025 (Aider, Roo Code, then Claude Code since July) and they’d def­i­nitely been use­ful but never some­thing I felt I could trust a se­ri­ous pro­ject to. But to­wards the end of 2025, the mod­els seemed to make a sig­nif­i­cant step for­ward in qual­i­ty13. At the same time, I kept hit­ting prob­lems in Perfetto which would have been triv­ially solved by hav­ing a re­li­able parser. Each workaround left the same thought in the back of my mind: maybe it’s fi­nally time to build it for real.

I got some space to think and re­flect over Christmas and de­cided to re­ally stress test the most max­i­mal­ist ver­sion of AI: could I vibe-code the whole thing us­ing just Claude Code on the Max plan (£200/month)?

Through most of January, I it­er­ated, act­ing as semi-tech­ni­cal man­ager and del­e­gat­ing al­most all the de­sign and all the im­ple­men­ta­tion to Claude. Functionally, I ended up in a rea­son­able place: a parser in C ex­tracted from SQLite sources us­ing a bunch of Python scripts, a for­mat­ter built on top, sup­port for both the SQLite lan­guage and the PerfettoSQL ex­ten­sions, all ex­posed in a web play­ground.

But when I re­viewed the code­base in de­tail in late January, the down­side was ob­vi­ous: the code­base was com­plete spaghet­ti14. I did­n’t un­der­stand large parts of the Python source ex­trac­tion pipeline, func­tions were scat­tered in ran­dom files with­out a clear shape, and a few files had grown to sev­eral thou­sand lines. It was ex­tremely frag­ile; it solved the im­me­di­ate prob­lem but it was never go­ing to cope with my larger vi­sion, never mind in­te­grat­ing it into the Perfetto tools. The sav­ing grace was that it had proved the ap­proach was vi­able and gen­er­ated more than 500 tests, many of which I felt I could reuse.

I de­cided to throw away every­thing and start from scratch while also switch­ing most of the code­base to Rust15. I could see that C was go­ing to make it dif­fi­cult to build the higher level com­po­nents like the val­ida­tor and the lan­guage server im­ple­men­ta­tion. And as a bonus, it would also let me use the same lan­guage for both the ex­trac­tion and run­time in­stead of split­ting it across C and Python.

More im­por­tantly, I com­pletely changed my role in the pro­ject. I took own­er­ship of all de­ci­sion­s16 and used it more as autocomplete on steroids” in­side a much tighter process: opin­ion­ated de­sign up­front, re­view­ing every change thor­oughly, fix­ing prob­lems ea­gerly as I spot­ted them, and in­vest­ing in scaf­fold­ing (like lint­ing, val­i­da­tion, and non-triv­ial test­ing17) to check AI out­put au­to­mat­i­cally.

The core fea­tures came to­gether through February and the fi­nal stretch (upstream test val­i­da­tion, ed­i­tor ex­ten­sions, pack­ag­ing, docs) led to a 0.1 launch in mid-March.

But in my opin­ion, this time­line is the least in­ter­est­ing part of this story. What I re­ally want to talk about is what would­n’t have hap­pened with­out AI and also the toll it took on me as I used it.

I’ve writ­ten in the past

about how one of my biggest weak­nesses as a soft­ware en­gi­neer is my ten­dency to pro­cras­ti­nate when fac­ing a big new pro­ject. Though I did­n’t re­al­ize it at the time, it could not have ap­plied more per­fectly to build­ing syn­taqlite.

AI ba­si­cally let me put aside all my doubts on tech­ni­cal calls, my un­cer­tainty of build­ing the right thing and my re­luc­tance to get started by giv­ing me very con­crete prob­lems to work on. Instead of I need to un­der­stand how SQLite’s pars­ing works”, it was I need to get AI to sug­gest an ap­proach for me so I can tear it up and build some­thing bet­ter”18. I work so much bet­ter with con­crete pro­to­types to play with and code to look at than end­lessly think­ing about de­signs in my head, and AI lets me get to that point at a pace I could not have dreamed about be­fore. Once I took the first step, every step af­ter that was so much eas­ier.

AI turned out to be bet­ter than me at the act of writ­ing code it­self, as­sum­ing that code is ob­vi­ous. If I can break a prob­lem down to write a func­tion with this be­hav­iour and pa­ra­me­ters” or write a class match­ing this in­ter­face,” AI will build it faster than I would and, cru­cially, in a style that might well be more in­tu­itive to a fu­ture reader. It doc­u­ments things I’d skip, lays out code con­sis­tently with the rest of the pro­ject, and sticks to what you might call the standard di­alect” of what­ever lan­guage you’re work­ing in19.

That stan­dard­ness is a dou­ble-edged sword. For the vast ma­jor­ity of code in any pro­ject, stan­dard is ex­actly what you want: pre­dictable, read­able, un­sur­pris­ing. But every pro­ject has pieces that are its edge, the parts where the value comes from do­ing some­thing non-ob­vi­ous. For syn­taqlite, that was the ex­trac­tion pipeline and the parser ar­chi­tec­ture. AIs in­stinct to nor­mal­ize was ac­tively harm­ful there, and those were the parts I had to de­sign in depth and of­ten re­sorted to just writ­ing my­self.

But here’s the flip side: the same speed that makes AI great at ob­vi­ous code also makes it great at refac­tor­ing. If you’re us­ing AI to gen­er­ate code at in­dus­trial scale, you have to refac­tor con­stantly and con­tin­u­ous­ly20. If you don’t, things im­me­di­ately get out of hand. This was the cen­tral les­son of the vibe-cod­ing month: I did­n’t refac­tor enough, the code­base be­came some­thing I could­n’t rea­son about, and I had to throw it all away. In the rewrite, refac­tor­ing be­came the core of my work­flow. After every large batch of gen­er­ated code, I’d step back and ask is this ugly?” Sometimes AI could clean it up. Other times there was a large-scale ab­strac­tion that AI could­n’t see but I could; I’d give it the di­rec­tion and let it ex­e­cute21. If you have taste, the cost of a wrong ap­proach drops dra­mat­i­cally be­cause you can re­struc­ture quick­ly22.

Of all the ways I used AI, re­search had by far the high­est ra­tio of value de­liv­ered to time spent.

I’ve worked with in­ter­preters and parsers be­fore but I had never heard of Wadler-Lindig pretty print­ing23. When I needed to build the for­mat­ter, AI gave me a con­crete and ac­tion­able les­son from a point of view I could un­der­stand and pointed me to the pa­pers to learn more. I could have found this my­self even­tu­ally, but AI com­pressed what might have been a day or two of read­ing into a fo­cused con­ver­sa­tion where I could ask but why does this work?” un­til I ac­tu­ally got it.

This ex­tended to en­tire do­mains I’d never worked in. I have deep C++ and Android per­for­mance ex­per­tise but had barely touched Rust tool­ing or ed­i­tor ex­ten­sion APIs. With AI, it was­n’t a prob­lem: the fun­da­men­tals are the same, the ter­mi­nol­ogy is sim­i­lar, and AI bridges the gap24. The VS Code ex­ten­sion would have taken me a day or two of learn­ing the API be­fore I could even start. With AI, I had a work­ing ex­ten­sion within an hour.

It was also in­valu­able for reac­quaint­ing my­self with parts of the pro­ject I had­n’t looked at for a few days25. I could con­trol how deep to go: tell me about this com­po­nent” for a sur­face-level re­fresher, give me a de­tailed lin­ear walk­through” for a deeper dive, audit un­safe us­ages in this repo” to go hunt­ing for prob­lems. When you’re con­text switch­ing a lot, you lose con­text fast. AI let me reac­quire it on de­mand.

Beyond mak­ing the pro­ject ex­ist at all, AI is also the rea­son it shipped as com­plete as it did. Every open source pro­ject has a long tail of fea­tures that are im­por­tant but not crit­i­cal: the things you know the­o­ret­i­cally how to do but keep de­pri­or­i­tiz­ing be­cause the core work is more press­ing. For syn­taqlite, that list was long: ed­i­tor ex­ten­sions, Python bind­ings, a WASM play­ground, a docs site, pack­ag­ing for mul­ti­ple ecosys­tem­s26. AI made these cheap enough that skip­ping them felt like the wrong trade-off.

It also freed up men­tal en­ergy for UX27. Instead of spend­ing all my time on im­ple­men­ta­tion, I could think about what a user’s first ex­pe­ri­ence should feel like: what er­ror mes­sages would ac­tu­ally help them fix their SQL, how the for­mat­ter out­put should look by de­fault, whether the CLI flags were in­tu­itive. These are the things that sep­a­rate a tool peo­ple try once from one they keep us­ing, and AI gave me the head­room to care about them. Without AI, I would have built some­thing much smaller, prob­a­bly no ed­i­tor ex­ten­sions or docs site. AI did­n’t just make the same pro­ject faster. It changed what the pro­ject was.

There’s an un­com­fort­able par­al­lel be­tween us­ing AI cod­ing tools and play­ing slot ma­chi­nes28. You send a prompt, wait, and ei­ther get some­thing great or some­thing use­less. I found my­self up late at night want­ing to do just one more prompt,” con­stantly try­ing AI just to see what would hap­pen even when I knew it prob­a­bly would­n’t work. The sunk cost fal­lacy kicked in too: I’d keep at it even in tasks it was clearly ill-suited for, telling my­self maybe if I phrase it dif­fer­ently this time.”

The tired­ness feed­back loop made it worse29. When I had en­ergy, I could write pre­cise, well-scoped prompts and be gen­uinely pro­duc­tive. But when I was tired, my prompts be­came vague, the out­put got worse, and I’d try again, get­ting more tired in the process. In these cases, AI was prob­a­bly slower than just im­ple­ment­ing some­thing my­self, but it was too hard to break out of the loop30.

Several times dur­ing the pro­ject, I lost my men­tal model of the code­base31. Not the over­all ar­chi­tec­ture or how things fit­ted to­gether. But the day-to-day de­tails of what lived where, which func­tions called which, the small de­ci­sions that ac­cu­mu­late into a work­ing sys­tem. When that hap­pened, sur­pris­ing is­sues would ap­pear and I’d find my­self at a to­tal loss to un­der­stand what was go­ing wrong. I hated that feel­ing.

The deeper prob­lem was that los­ing touch cre­ated a com­mu­ni­ca­tion break­down32. When you don’t have the men­tal thread of what’s go­ing on, it be­comes im­pos­si­ble to com­mu­ni­cate mean­ing­fully with the agent. Every ex­change gets longer and more ver­bose. Instead of change FooClass to do X,” you end up say­ing change the thing which does Bar to do X”. Then the agent has to fig­ure out what Bar is, how that maps to FooClass, and some­times it gets it wrong33. It’s ex­actly the same com­plaint en­gi­neers have al­ways had about man­agers who don’t un­der­stand the code ask­ing for fan­ci­ful or im­pos­si­ble things. Except now you’ve be­come that man­ager.

The fix was de­lib­er­ate: I made it a habit to read through the code im­me­di­ately af­ter it was im­ple­mented and ac­tively en­gage to see how would I have done this dif­fer­ently?”.

Of course, in some sense all of the above is also true of code I wrote a few months ago (hence the

sen­ti­ment that AI code is legacy code), but AI makes the drift hap­pen faster be­cause you’re not build­ing the same mus­cle mem­ory that comes from orig­i­nally typ­ing it out.

There were some other prob­lems I only dis­cov­ered in­cre­men­tally over the three months.

I found that AI made me pro­cras­ti­nate on key de­sign de­ci­sion­s34. Because refac­tor­ing was cheap, I could al­ways say I’ll deal with this later.” And be­cause AI could refac­tor at the same in­dus­trial scale it gen­er­ated code, the cost of de­fer­ring felt low. But it was­n’t: de­fer­ring de­ci­sions cor­roded my abil­ity to think clearly be­cause the code­base stayed con­fus­ing in the mean­time. The vibe-cod­ing month was the most ex­treme ver­sion of this. Yes, I un­der­stood the prob­lem, but if I had been more dis­ci­plined about mak­ing hard de­sign calls ear­lier, I could have con­verged on the right ar­chi­tec­ture much faster.

Tests cre­ated a sim­i­lar false com­fort35. Having 500+ tests felt re­as­sur­ing, and AI made it easy to gen­er­ate more. But nei­ther hu­mans nor AI are cre­ative enough to fore­see every edge case you’ll hit in the fu­ture; there are sev­eral times in the vibe-cod­ing phase where I’d come up with a test case and re­alise the de­sign of some com­po­nent was com­pletely wrong and needed to be to­tally re­worked. This was a sig­nif­i­cant con­trib­u­tor to my lack of trust and the de­ci­sion to scrap every­thing and start from scratch.

Basically, I learned that the normal rules” of soft­ware still ap­ply in the AI age: if you don’t have a fun­da­men­tal foun­da­tion (clear ar­chi­tec­ture, well-de­fined bound­aries) you’ll be left eter­nally chas­ing bugs as they ap­pear.

Something I kept com­ing back to was how lit­tle AI un­der­stood about the pas­sage of time36. It sees a code­base in a cer­tain state but does­n’t feel time the way hu­mans do. I can tell you what it feels like to use an API, how it evolved over months or years, why cer­tain de­ci­sions were made and later re­versed.

The nat­ural prob­lem from this lack of un­der­stand­ing is that you ei­ther make the same mis­takes you made in the past and have to re­learn the lessons or you fall into new traps which were suc­cess­fully avoided the first time, slow­ing you down in the long run. In my opin­ion, this is a sim­i­lar prob­lem to why los­ing a high-qual­ity se­nior en­gi­neer hurts a team so much: they carry his­tory and con­text that does­n’t ex­ist any­where else and act as a guide for oth­ers around them.

In the­ory, you can try to pre­serve this con­text by keep­ing specs and docs up to date. But there’s a rea­son we did­n’t do this be­fore AI: cap­tur­ing im­plicit de­sign de­ci­sions ex­haus­tively is in­cred­i­bly ex­pen­sive and time-con­sum­ing to write down. AI can help draft these docs, but be­cause there’s no way to au­to­mat­i­cally ver­ify that it ac­cu­rately cap­tured what mat­ters, a hu­man still has to man­u­ally au­dit the re­sult. And that’s still time-con­sum­ing.

There’s also the con­text pol­lu­tion prob­lem. You never know when a de­sign note about API A will echo in API B. Consistency is a huge part of what makes code­bases work, and for that you don’t just need con­text about what you’re work­ing on right now but also about other things which were de­signed in a sim­i­lar way. Deciding what’s rel­e­vant re­quires ex­actly the kind of judge­ment that in­sti­tu­tional knowl­edge pro­vides in the first place.

Reflecting on the above, the pat­tern of when AI helped and when it hurt was fairly con­sis­tent.

When I was work­ing on some­thing I al­ready un­der­stood deeply, AI was ex­cel­lent. I could re­view its out­put in­stantly, catch mis­takes be­fore they landed and move at a pace I’d never have man­aged alone. The parser rule gen­er­a­tion is the clear­est ex­am­ple37: I knew ex­actly what each rule should pro­duce, so I could re­view AIs out­put within a minute or two and it­er­ate fast.

When I was work­ing on some­thing I could de­scribe but did­n’t yet know, AI was good but re­quired more care. Learning Wadler-Lindig for the for­mat­ter was like this: I could ar­tic­u­late what I wanted, eval­u­ate whether the out­put was head­ing in the right di­rec­tion, and learn from what AI ex­plained. But I had to stay en­gaged and could­n’t just ac­cept what it gave me.

When I was work­ing on some­thing where I did­n’t even know what I wanted, AI was some­where be­tween un­help­ful and harm­ful. The ar­chi­tec­ture of the pro­ject was the clear­est case: I spent weeks in the early days fol­low­ing AI down dead ends, ex­plor­ing de­signs that felt pro­duc­tive in the mo­ment but col­lapsed un­der scrutiny. In hind­sight, I have to won­der if it would have been faster just think­ing it through with­out AI in the loop at all.

But ex­per­tise alone is­n’t enough. Even when I un­der­stood a prob­lem deeply, AI still strug­gled if the task had no ob­jec­tively check­able an­swer38. Implementation has a right an­swer, at least at a lo­cal level: the code com­piles, the tests pass, the out­put matches what you asked for. Design does­n’t. We’re still ar­gu­ing about OOP decades af­ter it first took off.

Concretely, I found that de­sign­ing the pub­lic API of syn­taqlite was where this hit home the hard­est. I spent sev­eral days in early March do­ing noth­ing but API refac­tor­ing, man­u­ally fix­ing things any ex­pe­ri­enced en­gi­neer would have in­stinc­tively avoided but AI made a to­tal mess of. There’s no test or ob­jec­tive met­ric for is this API pleas­ant to use” and will this API help users solve the prob­lems they have” and that’s ex­actly why the cod­ing agents did so badly

at it.

This takes me back to the days I was ob­sessed with physics and, specif­i­cally, rel­a­tiv­ity. The laws of physics look sim­ple and Newtonian in any small lo­cal area, but zoom out and space­time curves in ways you can’t pre­dict from the lo­cal pic­ture alone. Code is the same: at the level of a func­tion or a class, there’s usu­ally a clear right an­swer, and AI is ex­cel­lent there. But ar­chi­tec­ture is what hap­pens when all those lo­cal pieces in­ter­act, and you can’t get good global be­hav­iour by stitch­ing to­gether lo­cally cor­rect com­po­nents.

Knowing where you are on these axes at any given mo­ment is, I think, the core skill of work­ing with AI ef­fec­tively.

Eight years is a long time to carry a pro­ject in your head. Seeing these SQLite tools ac­tu­ally ex­ist and func­tion af­ter only three months of work is a mas­sive win, and I’m fully aware they would­n’t be here with­out AI.

But the process was­n’t the clean, lin­ear suc­cess story peo­ple usu­ally post. I lost an en­tire month to vibe-cod­ing. I fell into the trap of man­ag­ing a code­base I did­n’t ac­tu­ally un­der­stand, and I paid for that with a to­tal rewrite.

The take­away for me is sim­ple: AI is an in­cred­i­ble force mul­ti­plier for im­ple­men­ta­tion, but it’s a dan­ger­ous sub­sti­tute for de­sign. It’s bril­liant at giv­ing you the right an­swer to a spe­cific tech­ni­cal ques­tion, but it has no sense of his­tory, taste, or how a hu­man will ac­tu­ally feel us­ing your API. If you rely on it for the soul” of your soft­ware, you’ll just end up hit­ting a wall faster than you ever have be­fore.

What I’d like to see more of from oth­ers is ex­actly what I’ve tried to do here: hon­est, de­tailed ac­counts of build­ing real soft­ware with these tools; not week­end toys or one-off scripts but the kind of soft­ware that has to sur­vive con­tact with users, bug re­ports, and your own chang­ing mind.

...

Read the original on lalitm.com »

2 698 shares, 38 trendiness

Google AI Edge Gallery-app

AI Edge Gallery is the pre­mier des­ti­na­tion for run­ning the world’s most pow­er­ful open-source Large Language Models (LLMs) on your mo­bile de­vice. Experience high-per­for­mance Generative AI di­rectly on your hard­ware—fully of­fline, pri­vate, and light­ning-fast.

Now Featuring: Gemma 4

This up­date brings of­fi­cial sup­port for the newly re­leased Gemma 4 fam­ily. As the cen­ter­piece of this re­lease, Gemma 4 al­lows you to test the cut­ting edge of on-de­vice AI. Experience ad­vanced rea­son­ing, logic, and cre­ative ca­pa­bil­i­ties with­out ever send­ing your data to a server.

Core Features

- Agent Skills: Transform your LLM from a con­ver­sa­tion­al­ist into a proac­tive as­sis­tant. Use the Agent Skills tile to aug­ment model ca­pa­bil­i­ties with tools like Wikipedia for fact-ground­ing, in­ter­ac­tive maps, and rich vi­sual sum­mary cards. You can even load mod­u­lar skills from a URL or browse com­mu­nity con­tri­bu­tions on GitHub Discussions.

- AI Chat with Thinking Mode: Engage in fluid, multi-turn con­ver­sa­tions and tog­gle the new Thinking Mode to peek under the hood.” This fea­ture al­lows you to see the mod­el’s step-by-step rea­son­ing process, which is per­fect for un­der­stand­ing com­plex prob­lem-solv­ing. Note: Thinking Mode cur­rently works with sup­ported mod­els, start­ing with the Gemma 4 fam­ily.

- Ask Image: Use mul­ti­modal power to iden­tify ob­jects, solve vi­sual puz­zles, or get de­tailed de­scrip­tions us­ing your de­vice’s cam­era or photo gallery.

- Audio Scribe: Transcribe and trans­late voice record­ings into text in real-time us­ing high-ef­fi­ciency on-de­vice lan­guage mod­els.

- Prompt Lab: A ded­i­cated work­space to test dif­fer­ent prompts and sin­gle-turn use cases with gran­u­lar con­trol over model pa­ra­me­ters like tem­per­a­ture and top-k.

- Mobile Actions: Unlock of­fline de­vice con­trols and au­to­mated tasks pow­ered en­tirely by a fine­tune of FuntionGemma 270m.

- Tiny Garden: A fun, ex­per­i­men­tal mini-game that uses nat­ural lan­guage to plant and har­vest a vir­tual gar­den us­ing a fine­tune of FunctionGemma 270m.

- Model Management & Benchmark: Gallery is a flex­i­ble sand­box for a wide va­ri­ety of open-source mod­els. Easily down­load mod­els from the list or load your own cus­tom mod­els. Manage your model li­brary ef­fort­lessly and run bench­mark tests to un­der­stand ex­actly how each model per­forms on your spe­cific hard­ware.

- 100% On-Device Privacy: All model in­fer­ences hap­pen di­rectly on your de­vice hard­ware. No in­ter­net is re­quired, en­sur­ing to­tal pri­vacy for your prompts, im­ages, and sen­si­tive data.

Built for the Community

AI Edge Gallery is an open-source pro­ject de­signed for the de­vel­oper com­mu­nity and AI en­thu­si­asts alike. Explore our ex­am­ple fea­tures, con­tribute your own skills, and help shape the fu­ture of the on-de­vice agent ecosys­tem.

Check out the source code on GitHub:

https://​github.com/​google-ai-edge/​gallery

Note: This app is in ac­tive de­vel­op­ment. Performance is de­pen­dent on your de­vice’s hard­ware (CPU/GPU). For sup­port or feed­back, con­tact us at google-ai-edge-gallery-an­droid-feed­back@google.com.

...

Read the original on apps.apple.com »

3 595 shares, 52 trendiness

arman-bd/guppylm: A ~9M parameter LLM that talks like a small fish.

This pro­ject ex­ists to show that train­ing your own lan­guage model is not magic.

No PhD re­quired. No mas­sive GPU clus­ter. One Colab note­book, 5 min­utes, and you have a work­ing LLM that you built from scratch — data gen­er­a­tion, to­k­enizer, model ar­chi­tec­ture, train­ing loop, and in­fer­ence. If you can run a note­book, you can train a lan­guage model.

It won’t pro­duce a bil­lion-pa­ra­me­ter model that writes es­says. But it will show you ex­actly how every piece works — from raw text to trained weights to gen­er­ated out­put — so the big mod­els stop feel­ing like black boxes.

GuppyLM is a tiny lan­guage model that pre­tends to be a fish named Guppy. It speaks in short, low­er­case sen­tences about wa­ter, food, light, and tank life. It does­n’t un­der­stand hu­man ab­strac­tions like money, phones, or pol­i­tics — and it’s not try­ing to.

It’s trained from scratch on 60K syn­thetic con­ver­sa­tions across 60 top­ics, runs on a sin­gle GPU in ~5 min­utes, and pro­duces a model small enough to run in a browser.

Vanilla trans­former. No GQA, no RoPE, no SwiGLU, no early exit. As sim­ple as it gets.

* Experiences the world through wa­ter, tem­per­a­ture, light, vi­bra­tions, and food

* Is friendly, cu­ri­ous, and a lit­tle dumb

60 top­ics: greet­ings, feel­ings, tem­per­a­ture, food, light, wa­ter, tank, noise, night, lone­li­ness, bub­bles, glass, re­flec­tion, breath­ing, swim­ming, col­ors, taste, plants, fil­ter, al­gae, snails, scared, ex­cited, bored, cu­ri­ous, happy, tired, out­side, cats, rain, sea­sons, mu­sic, vis­i­tors, chil­dren, mean­ing of life, time, mem­ory, dreams, size, fu­ture, past, name, weather, sleep, friends, jokes, fear, love, age, in­tel­li­gence, health, singing, TV, and more.

Downloads the pre-trained model from HuggingFace and lets you chat. Just run all cells.

pip in­stall torch to­k­eniz­ers

python -m gup­pylm chat

from datasets im­port load­_­dataset

ds = load­_­dataset(“ar­man-bd/​gup­pylm-60k-generic”)

print(ds[“train”][0])

# {‘input’: hi gup­py’, output’: hello. the wa­ter is nice to­day.’, category’: greeting’}

Why no sys­tem prompt? Every train­ing sam­ple had the same one. A 9M model can’t con­di­tion­ally fol­low in­struc­tions — the per­son­al­ity is baked into the weights. Removing it saves ~60 to­kens per in­fer­ence.

Why sin­gle-turn only? Multi-turn de­graded at turn 3-4 due to the 128-token con­text win­dow. A fish that for­gets is on-brand, but gar­bled out­put is­n’t. Single-turn is re­li­able.

Why vanilla trans­former? GQA, SwiGLU, RoPE, and early exit add com­plex­ity that does­n’t help at 9M params. Standard at­ten­tion + ReLU FFN + LayerNorm pro­duces the same qual­ity with sim­pler code.

Why syn­thetic data? A fish char­ac­ter with con­sis­tent per­son­al­ity needs con­sis­tent train­ing data. Template com­po­si­tion with ran­dom­ized com­po­nents (30 tank ob­jects, 17 food types, 25 ac­tiv­i­ties) gen­er­ates ~16K unique out­puts from ~60 tem­plates.

...

Read the original on github.com »

4 565 shares, 34 trendiness

Why Switzerland Has 25 Gbit Internet and America Doesn't

What Can Be Done

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.

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 and are mostly to 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.

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.

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.

But here’s the cru­cial part. Switzerland did­n’t ar­rive at this model by ac­ci­dent. It did­n’t 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.

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.

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.

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.

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. 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.

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. 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.

What Can Be Done

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. 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.Cre­ate 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.Sup­port 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.

...

Read the original on sschueller.github.io »

5 560 shares, 33 trendiness

Microsoft Hasn’t Had a Coherent GUI Strategy Since Petzold

A few years ago I was in a meet­ing with de­vel­op­ers and some­one asked a sim­ple ques­tion: What’s the right frame­work for a new Windows desk­top app?”

Dead si­lence. One per­son sug­gested WPF. Another said WinUI 3. A third asked if they should just use Electron. The meet­ing went side­ways and we never did an­swer the ques­tion.

That si­lence is the story. And the story goes back thirty-plus years.

When a plat­form can’t an­swer how should I build a UI?” in un­der ten sec­onds, it has failed its de­vel­op­ers. Full stop.

In 1988, Charles Petzold pub­lished Programming Windows. 852 pages. Win16 API in C. And for all its bulk, it rep­re­sented some­thing re­mark­able: a sin­gle, co­her­ent, au­thor­i­ta­tive an­swer to how you write a Windows ap­pli­ca­tion. In the busi­ness, we call that a strategy’.

Win32 that fol­lowed was big­ger but still co­her­ent. Message loops. Window pro­ce­dures. GDI. The men­tal model was a bit whacky, but it was one men­tal model. Petzold ex­plained it. It was the F=MA of Windows. Simple. Powerful. You learned it. You used it. You were suc­cess­ful.

Clarity is your friend! One OS, one API, one lan­guage, one book. There was no com­mit­tee de­bat­ing man­aged-code al­ter­na­tives. There was just Win32 and Petzold, and it worked. This was Physics not Chemistry (this works but only for this slice of the pe­riod table. And only un­der these pres­sures.  And only within this tem­per­a­ture. And only if the Moon is in the 7th house of Jupiter).

What hap­pened next is a mas­ter­class in how a com­pany with bril­liant peo­ple and enor­mous re­sources can pro­duce a thirty-year boof-a-rama by op­ti­miz­ing for the wrong things.  AKA Brillant peo­ple do­ing stu­pid things.

Win32 had real lim­i­ta­tions, so Microsoft did what Microsoft does: it shipped some­thing new for the de­vel­oper con­fer­ence. Several some­things.

MFC (1992) wrapped Win32 in C++. If Win32 was in­el­e­gant, MFC was Win32 wear­ing a tuxedo made of other tuxe­dos. Then came OLE. COM. ActiveX. None of these were re­ally GUI frame­works — they were com­po­nent ar­chi­tec­tures — but they in­fected every cor­ner of Windows de­vel­op­ment and in­tro­duced a level of cog­ni­tive com­plex­ity that makes Kierkegaard read like Hemingway.

I sat through a con­fer­ence ses­sion in the late nineties try­ing to un­der­stand the dif­fer­ence be­tween an OLE doc­u­ment, a COM ob­ject, and an ActiveX con­trol. I looked at the pre­sen­ter like they had a rat’s tail hang­ing out of his mouth for the en­tire hour.

Microsoft was­n’t sell­ing a co­her­ent story. It was sell­ing tech­nol­ogy prim­i­tives and telling de­vel­op­ers to fig­ure out the story them­selves. That’s the Conference Keynote Cluster***k — Microsoft op­ti­mized for an ex­ec­u­tive im­press­ing peo­ple with their keynote and not the suc­cess of the users or de­vel­op­ers.

At PDC 2003, Microsoft un­veiled Longhorn — gen­uinely one of the most com­pelling tech­ni­cal vi­sions the com­pany had ever put in front of de­vel­op­ers. Three pil­lars: WinFS (a re­la­tional file sys­tem), Indigo (unified com­mu­ni­ca­tions), and Avalon — later WPF — a GPU-accelerated, vec­tor-based UI sub­sys­tem dri­ven by a de­clar­a­tive XML lan­guage called XAML. Developers saw the Avalon demos and went nuts. It was the right vi­sion.

It was also, in the words of Jim Allchin’s in­ter­nal memo from January 2004, a pig.”

By August 2004, Microsoft an­nounced a com­plete de­vel­op­ment re­set. Scrapped. Start over from the Server 2003 code­base. And af­ter the re­set, lead­er­ship is­sued a quiet di­rec­tive: no f***ing man­aged code in Windows. All new code in C++. WPF would ship along­side Vista, but the shell it­self would not use it.

The Windows team’s bit­ter­ness to­ward .NET never healed. From their per­spec­tive, gam­bling on a new man­aged-code frame­work had pro­duced the most em­bar­rass­ing fail­ure in the com­pa­ny’s his­tory. That bit­ter­ness cre­ated a thir­teen-year in­sti­tu­tional civil war be­tween the Windows team and the .NET team that would ul­ti­mately or­phan WPF, kill Silverlight, doom UWP, and give us the GUI ecosys­tem boof-a-rama we have to­day.

WPF shipped in late 2006. It was re­mark­able — XAML, hard­ware-ac­cel­er­ated ren­der­ing, real data bind­ing. If Microsoft had made it the de­fin­i­tive an­swer and in­vested re­lent­lessly, the story might have ended dif­fer­ently. Instead, in 2007, they launched Silverlight: a stripped-down browser plu­gin to com­pete with Flash, cross-plat­form, el­e­gant, and the foun­da­tion for Windows Phone. Around 2010 it looked like the rich client fu­ture.

Then at MIX 2010, a Microsoft ex­ec­u­tive said in a Q&A that Silverlight was not a cross-plat­form strat­egy — it was about Windows Phone. HTML5 was now pol­icy. The Silverlight team was not told this was com­ing. Developers who had bet their LOB ap­pli­ca­tions on Silverlight found out from a con­fer­ence Q&A.

Silverlight was­n’t killed by tech­ni­cal fail­ure. The tech­nol­ogy was fine. It was killed by a busi­ness strat­egy de­ci­sion, and de­vel­op­ers were the last to know.

Remember that pat­tern. We’ll see it again.

Apple had sold 200 mil­lion iPhones. The iPad was eat­ing into PC sales. Microsoft’s an­swer was Windows 8 and Metro — a touch-first run­time called WinRT that was de­lib­er­ately not built on .NET. Remember the Windows team’s bit­ter­ness? Here it man­i­fests. WinRT was a na­tive C++ run­time. Clean break from WPF, WinForms, and a decade of de­vel­oper in­vest­ment in .NET.

There were ac­tu­ally two sto­ries be­ing told si­mul­ta­ne­ously in­side Microsoft. The Windows team was build­ing WinRT. The .NET team was still evan­ge­liz­ing WPF. Different build­ings, dif­fer­ent VPs, dif­fer­ent road maps.

What de­vel­op­ers heard at //Build 2012: the fu­ture is WinRT, and also HTML+JS is first-class, and also .NET still works, and also C++ is back, and also you should write Metro apps, and also your WPF code still runs fine. That is not a strat­egy. That is a Hunger Games stage where six teams are fight­ing for your at­ten­tion.

Enterprise de­vel­op­ers took one look at UWPs sand­box­ing, its Store de­ploy­ment re­quire­ment, and its miss­ing Win32 APIs, and walked away. The frame­work de­signed to win them into the mod­ern era had been op­ti­mized for a tablet app store that never ma­te­ri­al­ized.

Windows 10 brought Universal Windows Platform — write once, run on PC, phone, Xbox, HoloLens. Compelling on pa­per. The prob­lem: Windows Phone was dy­ing, and Microsoft’s own flag­ship apps — Office, Visual Studio, the shell it­self — weren’t us­ing UWP. The mes­sage was clear even if no one said it out loud.

When UWP stalled, the of­fi­cial an­swer be­came it de­pends. Use UWP for new apps, keep WPF for ex­ist­ing ones, add mod­ern APIs via XAML Islands, wait for WinUI 3, but also WinUI 2 ex­ists for UWP specif­i­cally, and Project Reunion will fix every­thing, ex­cept we’re re­nam­ing it Windows App SDK and it still does­n’t fully re­place UWP and…

Project Reunion / WinUI 3 rep­re­sents gen­uine progress. But ask your­self why the prob­lem ex­isted at all. UWPs con­trols were tied to the OS be­cause the Windows team owned them. The .NET team did­n’t. The de­vel­oper tools team did­n’t. Project Reunion was an or­ga­ni­za­tional workaround dressed up as a tech­ni­cal so­lu­tion.

One de­vel­op­er’s sum­mary, writ­ten in 2024: I’ve been fol­low­ing Microsoft’s con­stant changes: UAP, UWP, C++/CX re­placed by C++/WinRT with­out tool sup­port, XAML Islands, XAML Direct, Project Reunion, the restart of WinAppSDK, the chaotic switch be­tween WinUI 2.0 and 3.0…” Fourteen years. Fourteen piv­ots. That per­son de­serves a medal and an apol­ogy, in that or­der.

Here is every GUI tech­nol­ogy ac­tu­ally ship­ping on Windows to­day:

* Win32 (1985) — Still here. Still used. Petzold’s book still ap­plies.

* MFC (1992) — C++ wrap­per on Win32. Maintenance mode. Lives in en­ter­prise and CAD.

* WinForms (2002) — .NET wrap­per on Win32. Available but dis­cour­aged.” Still fastest for data-en­try forms.

* Electron — Chromium + Node.js. VS Code, Slack, Discord. The most widely de­ployed desk­top GUI tech­nol­ogy on Windows right now — and Microsoft had noth­ing to do with it.

* Avalonia — Open source WPF spir­i­tual suc­ces­sor. Used by JetBrains, GitHub, Unity — de­vel­op­ers who stopped wait­ing for Microsoft.

* Uno Platform — WinUI APIs on every plat­form. More com­mit­ted to WinUI than Microsoft is.

* Delphi / RAD Studio — Still alive. Still fast. Still in ver­ti­cal mar­ket soft­ware.

* Java Swing / JavaFX — Yes, still in pro­duc­tion. The en­ter­prise never for­gets.

Seventeen ap­proaches. Five pro­gram­ming lan­guages. Three ren­der­ing philoso­phies. That is not a plat­form. I might not have a dic­tio­nary de­f­i­n­i­tion for the term boof-a-rama but I know one when I see it.

Every failed GUI ini­tia­tive traces back to one of three causes: in­ter­nal team pol­i­tics (Windows vs. .NET), a de­vel­oper con­fer­ence an­nounce­ment dri­ving a pre­ma­ture plat­form bet (Metro, UWP), or a busi­ness strat­egy pivot that or­phaned de­vel­op­ers with­out warn­ing (Silverlight). None of these are tech­ni­cal fail­ures. The tech­nol­ogy was of­ten gen­uinely good — WPF was good, Silverlight was good, XAML is good. The or­ga­ni­za­tional fail­ure was the prod­uct.

You ei­ther have a Plausible Theory of Success that cov­ers the full life­cy­cle — adop­tion, in­vest­ment, main­te­nance, and mi­gra­tion — or you have a de­vel­oper con­fer­ence keynote.

One is a strat­egy. The other is a thirty-year boof-a-rama.

Charles Petzold wrote six edi­tions of Programming Windows try­ing to keep up with each new thing Microsoft an­nounced. He stopped af­ter the sixth, which cov­ered WinRT for Windows 8. That was 2012.

...

Read the original on www.jsnover.com »

6 492 shares, 19 trendiness

Artemis II crew see first glimpse of far side of Moon

The crew for Nasa’s Artemis II mis­sion have de­scribed see­ing the far side of the Moon for the first time.

Nasa as­tro­nauts Reid Wiseman, Victor Glover, and Christina Koch, and Canadian Space Agency as­tro­naut Jeremy Hansen have en­tered the third day of their mis­sion on the Orion space­craft that will carry them around the far side of the Moon and back to Earth.

Something about you senses that is not the Moon that I’m used to see­ing,” Koch said.

The crew shared a photo they took of the Orientale basin of the Moon, which Nasa said marked the first time the en­tire basin has been seen with hu­man eyes”.

As of 23:00 BST on Saturday, Nasa’s on­line dash­board showed the Artemis II space­craft was more than 180,000 miles (289,681km) from Earth.

...

Read the original on www.bbc.com »

7 331 shares, 18 trendiness

love2d/love: LÖVE is an awesome 2D game framework for Lua.

LÖVE is an awe­some frame­work you can use to make 2D games in Lua. It’s free, open-source, and works on Windows, ma­cOS, Linux, Android, and iOS.

We use our wiki for doc­u­men­ta­tion. If you need fur­ther help, feel free to ask on our fo­rums, our Discord server, or our sub­red­dit.

We use the main’ branch for de­vel­op­ment of the next ma­jor re­lease, and there­fore it should not be con­sid­ered sta­ble.

There are also branches for cur­rently re­leased ma­jor ver­sions, which may have fixes and changes meant for up­com­ing patch re­leases within that ma­jor ver­sion.

We tag all our re­leases (since we started us­ing mer­cu­r­ial and git), and have bi­nary down­loads avail­able for them.

Experimental changes are some­times de­vel­oped in a sep­a­rate love-ex­per­i­ments repos­i­tory.

Files for re­leases are in the re­leases sec­tion on GitHub. The site has links to files and ad­di­tional plat­form con­tent for the lat­est re­lease.

There are also un­sta­ble/​nightly builds:

* Builds for some plat­forms are au­to­mat­i­cally cre­ated af­ter each com­mit and are avail­able through GitHub’s CI in­ter­faces.

* For ubuntu linux they are in ppa:bartbes/​love-un­sta­ble

* For arch linux there’s love-git in the AUR.

The test suite in test­ing/ cov­ers all the LÖVE APIs, and tests them the same way de­vel­op­ers use them. You can view cur­rent test cov­er­age from any ac­tion.

You can run the suite lo­cally like you would run a nor­mal LÖVE pro­ject, e.g.:

love test­ing

See the readme in the test­ing folder for more info.

The best places to con­tribute are through the is­sue tracker and the of­fi­cial Discord server or IRC chan­nel.

For code con­tri­bu­tions, pull re­quests and patches are wel­come. Be sure to read the source code style guide. Changes and new fea­tures typ­i­cally get dis­cussed in the is­sue tracker or on Discord or the fo­rums be­fore a pull re­quest is made.

Follow the in­struc­tions at the mega­source repos­i­tory page.

Because in-tree builds are not al­lowed, the Makefiles needs to be gen­er­ated in a sep­a­rate build di­rec­tory. In this ex­am­ple, folder named build is used:

Download or clone this repos­i­tory and copy, move, or sym­link the ma­cOS/​Frame­works sub­folder into love’s plat­form/​xcode/​ma­cosx folder and the shared sub­folder into love’s plat­form/​xcode folder.

Then use the Xcode pro­ject found at plat­form/​xcode/​love.xcode­proj to build the love-ma­cosx tar­get.

Download the love-ap­ple-de­pen­den­cies zip file cor­re­spond­ing to the LÖVE ver­sion be­ing used from the Releases page, un­zip it, and place the iOS/​li­braries sub­folder into love’s plat­form/​xcode/​ios folder and the shared sub­folder into love’s plat­form/​xcode folder.

Or, down­load or clone this repos­i­tory and copy, move, or sym­link the iOS/​li­braries sub­folder into love’s plat­form/​xcode/​ios folder and the shared sub­folder into love’s plat­form/​xcode folder.

Then use the Xcode pro­ject found at plat­form/​xcode/​love.xcode­proj to build the love-ios tar­get.

See readme-iOS.rtf for more in­for­ma­tion.

...

Read the original on github.com »

8 305 shares, 16 trendiness

Running Google Gemma 4 Locally With LM Studio’s New Headless CLI & Claude Code

Cloud AI APIs are great un­til they are not. Rate lim­its, us­age costs, pri­vacy con­cerns, and net­work la­tency all add up. For quick tasks like code re­view, draft­ing, or test­ing prompts, a lo­cal model that runs en­tirely on your hard­ware has real ad­van­tages: zero API costs, no data leav­ing your ma­chine, and con­sis­tent avail­abil­ity.

Google’s Gemma 4 is in­ter­est­ing for lo­cal use be­cause of its mix­ture-of-ex­perts ar­chi­tec­ture. The 26B pa­ra­me­ter model only ac­ti­vates 4B pa­ra­me­ters per for­ward pass, which means it runs well on hard­ware that could never han­dle a dense 26B model. On my 14” MacBook Pro M4 Pro with 48 GB of uni­fied mem­ory, it fits com­fort­ably and gen­er­ates at 51 to­kens per sec­ond. Though there’s sig­nif­i­cant slow­downs when used within Claude Code from my ex­pe­ri­ence.

Google re­leased Gemma 4 as a fam­ily of four mod­els, not just one. The lineup spans a wide range of hard­ware tar­gets:

The E” mod­els (E2B, E4B) use Per-Layer Embeddings to op­ti­mize for on-de­vice de­ploy­ment and are the only vari­ants that sup­port au­dio in­put (speech recog­ni­tion and trans­la­tion). The 31B dense model is the most ca­pa­ble, scor­ing 85.2% on MMLU Pro and 89.2% on AIME 2026.

Why I picked the 26B-A4B. The mix­ture-of-ex­perts ar­chi­tec­ture is the key. It has 128 ex­perts plus 1 shared ex­pert, but only ac­ti­vates 8 ex­perts (3.8B pa­ra­me­ters) per to­ken. A com­mon rule of thumb es­ti­mates MoE dense - equiv­a­lent qual­ity as roughly sqrt(to­tal x ac­tive pa­ra­me­ters), which puts this model around 10B ef­fec­tive. In prac­tice, it de­liv­ers in­fer­ence cost com­pa­ra­ble to a 4B dense model with qual­ity that punches well above that weight class. On bench­marks, it scores 82.6% on MMLU Pro and 88.3% on AIME 2026, close to the dense 31B (85.2% and 89.2%) while run­ning dra­mat­i­cally faster.

The chart be­low tells the story. It plots Elo score against to­tal model size on a log scale for re­cent open-weight mod­els with think­ing en­abled. The blue-high­lighted re­gion in the up­per left is where you want to be: high per­for­mance, small foot­print.

Gemma 4 26B-A4B (Elo ~1441) sits firmly in that zone, punch­ing well above its 25.2B pa­ra­me­ter weight. The 31B dense vari­ant scores slightly higher (~1451) but is still re­mark­ably com­pact. For con­text, mod­els like Qwen 3.5 397B-A17B (~1450 Elo) and GLM-5 (~1457 Elo) need 100-600B to­tal pa­ra­me­ters to reach sim­i­lar scores. Kimi-K2.5 (~1457 Elo) re­quires over 1,000B. The 26B-A4B achieves com­pet­i­tive Elo with a frac­tion of the pa­ra­me­ters, which trans­lates di­rectly into lower mem­ory re­quire­ments and faster lo­cal in­fer­ence.

This is what makes MoE mod­els trans­for­ma­tive for lo­cal use. You do not need a clus­ter or a high-end GPU rig to run a model that com­petes with 400B+ pa­ra­me­ter be­he­moths. A lap­top with 48 GB of uni­fied mem­ory is enough.

For lo­cal in­fer­ence on a 48 GB Mac, this is the sweet spot. The dense 31B would con­sume more mem­ory and gen­er­ate to­kens slower be­cause every pa­ra­me­ter par­tic­i­pates in every for­ward pass. The E4B is lighter but no­tice­ably less ca­pa­ble. The 26B-A4B gives you 256K max con­text, vi­sion sup­port (useful for an­a­lyz­ing screen­shots and di­a­grams), na­tive func­tion/​tool call­ing, and rea­son­ing with con­fig­urable think­ing modes, all at 51 to­kens/​sec­ond on my hard­ware.

LM Studio has been a pop­u­lar desk­top app for run­ning lo­cal mod­els for a while. Version 0.4.0 changed the ar­chi­tec­ture fun­da­men­tally by in­tro­duc­ing llm­ster, the core in­fer­ence en­gine ex­tracted from the desk­top app and pack­aged as a stand­alone server.

The prac­ti­cal re­sult: you can now run LM Studio en­tirely from the com­mand line us­ing the lms CLI. No GUI re­quired. This makes it us­able on head­less servers, in CI/CD pipelines, SSH ses­sions, or just for de­vel­op­ers who pre­fer stay­ing in the ter­mi­nal.

* llm­ster dae­mon: a back­ground ser­vice that man­ages model load­ing and in­fer­ence with­out the desk­top app

* Parallel re­quest pro­cess­ing: con­tin­u­ous batch­ing in­stead of se­quen­tial queu­ing, so mul­ti­ple re­quests to the same model run con­cur­rently

* Stateful REST API: a new /v1/chat end­point that main­tains con­ver­sa­tion his­tory across re­quests

# Linux/Mac

curl -fsSL https://​lm­stu­dio.ai/​in­stall.sh | bash

# Windows

irm https://​lm­stu­dio.ai/​in­stall.ps1 | iexlms dae­mon up­lms run­time up­date llama.cpp

lms run­time up­date mlxlms get google/​gemma-4-26b-a4b

The CLI shows you the vari­ant it will down­load (Q4_K_M quan­ti­za­tion by de­fault, 17.99 GB) and asks for con­fir­ma­tion:

↓ To down­load: model google/​gemma-4-26b-a4b - 64.75 KB

└─ ↓ To down­load: Gemma 4 26B A4B Instruct Q4_K_M [GGUF] - 17.99 GB

About to down­load 17.99 GB.

? Start down­load?

❯ Yes

No

Change vari­ant se­lec­tion

If you al­ready have the model, the CLI tells you and shows the load com­mand:

✔ Start down­load? yes

Model al­ready down­loaded. To use, run: lms load google/​gemma-4-26b-a4blms lsYou have 10 mod­els, tak­ing up 118.17 GB of disk space.

LLM PARAMS ARCH SIZE DEVICE

gemma-3-270m-it-mlx 270m gem­ma3_­text 497.80 MB Local

google/​gemma-4-26b-a4b (1 vari­ant) 26B-A4B gem­ma4 17.99 GB Local

gpt-oss-20b-mlx 20B gp­t_oss 22.26 GB Local

llama-3.2-1b-in­struct 1B Llama 712.58 MB Local

nvidia/​nemotron-3-nano (1 vari­ant) 30B nemotron_h 17.79 GB Local

ope­nai/​gpt-oss-20b (1 vari­ant) 20B gpt-oss 12.11 GB Local

qwen/​qwen3.5-35b-a3b (1 vari­ant) 35B-A3B qwen35­moe 22.07 GB Local

qwen2.5-0.5b-in­struct-mlx 0.5B Qwen2 293.99 MB Local

zai-org/​glm-4.7-flash (1 vari­ant) 30B glm4_­moe_lite 24.36 GB Local

EMBEDDING PARAMS ARCH SIZE DEVICE

text-em­bed­ding-nomic-em­bed-text-v1.5 Nomic BERT 84.11 MB Local

Worth not­ing: sev­eral of these mod­els use mix­ture-of-ex­perts ar­chi­tec­tures (Gemma 4, Qwen 3.5, GLM 4.7 Flash). MoE mod­els punch above their weight for lo­cal in­fer­ence be­cause only a frac­tion of pa­ra­me­ters ac­ti­vate per to­ken.

Start a chat ses­sion with stats en­abled to see per­for­mance num­bers:

lms chat google/​gemma-4-26b-a4b –stats ╭─────────────────────────────────────────────────╮

👾 lms chat │

│ Type exit or Ctrl+C to quit │

│ Chatting with google/​gemma-4-26b-a4b │

│ Try one of the fol­low­ing com­mands: │

│ /model - Load a model (type /model to see list) │

│ /download - Download a model │

│ /clear - Clear the chat his­tory │

│ /help - Show help in­for­ma­tion │

With –stats, you get pre­dic­tion met­rics af­ter each re­sponse:

Prediction Stats:

Stop Reason: eosFound

Tokens/Second: 51.35

Time to First Token: 1.551s

Prompt Tokens: 39

Predicted Tokens: 176

Total Tokens: 215

51 to­kens/​sec­ond on a 14” MacBook Pro M4 Pro (48 GB) with a 26B model is solid. Time to first to­ken at 1.5 sec­onds is re­spon­sive enough for in­ter­ac­tive use.

See what is cur­rently loaded:

lms psI­DEN­TI­FIER MODEL STATUS SIZE CONTEXT PARALLEL DEVICE TTL

google/​gemma-4-26b-a4b google/​gemma-4-26b-a4b IDLE 17.99 GB 48000 2 Local 60m / 1h

The model oc­cu­pies 17.99 GB in mem­ory with a 48K con­text win­dow and sup­ports 2 par­al­lel re­quests. The TTL (time-to-live) auto-un­loads the model af­ter 1 hour of idle time, free­ing mem­ory with­out man­ual in­ter­ven­tion.

lms ps –json | jq

* vision”: true and trainedForToolUse”: true - Gemma 4 sup­ports both im­age in­put and tool call­ing

* maxContextLength”: 262144 - the model sup­ports up to 256K con­text, though the de­fault load is 48K

Before load­ing a model, you can es­ti­mate mem­ory re­quire­ments at dif­fer­ent con­text lengths us­ing –estimate-only. I wrote a small script to test across the full range:

The base model takes about 17.6 GiB re­gard­less of con­text. Each dou­bling of con­text length adds roughly 3-4 GiB. At the de­fault 48K con­text, you need about 21 GiB. On my 48 GB MacBook Pro, I can push to the full 256K con­text at 37.48 GiB and still have about 10 GB free for the OS and other apps. A 36 GB Mac could com­fort­ably run 200K con­text with head­room.

lms load google/​gemma-4-26b-a4b –estimate-only –context-length 48000

Model: google/​gemma-4-26b-a4b

Context Length: 48,000

Estimated GPU Memory: 21.05 GiB

Estimated Total Memory: 21.05 GiB

Estimate: This model may be loaded based on your re­source guardrails set­tings.

This is use­ful for ca­pac­ity plan­ning. If you want to run Gemma 4 along­side other ap­pli­ca­tions, check the es­ti­mate at your tar­get con­text length first.

Here is the full script I used to gen­er­ate the table above. You can swap in any model name and con­text length list to pro­file a dif­fer­ent model:

#!/usr/bin/env bash

model=“google/​gemma-4-26b-a4b”

con­texts=(4096 8000 16000 24000 32000 48000 64000 96000 128000 200000 256000)

table_­con­texts=()

table_gpu=()

table_­to­tal=()

for ctx in ${contexts[@]}”; do

out­put=“$(lms load $model” –estimate-only –context-length $ctx” 2>&1)”

parsed_­con­text=“$(printf %s\n’ $output” | awk -F’: ′ /^Context Length:/ {print $2; exit}’)”

parsed_gpu=“$(printf %s\n’ $output” | awk -F’: +′ /^Estimated GPU Memory:/ {print $2; exit}’)”

parsed_­to­tal=“$(printf %s\n’ $output” | awk -F’: +′ /^Estimated Total Memory:/ {print $2; exit}’)”

table_­con­texts+=(“${parsed_­con­text:-$ctx}“)

table_gpu+=(“${parsed_gpu:-N/​A}“)

table_­to­tal+=(“${parsed_­to­tal:-N/​A}“)

done

printf | Model | Context Length | GPU Memory | Total Memory |\n’

printf |–-|–-:|–-:|–-:|\n’

for i in ${!table_contexts[@]}”; do

printf | %s | %s | %s | %s |\n’ \

$model” ${table_contexts[$i]}” ${table_gpu[$i]}” ${table_total[$i]}”

done

...

Read the original on ai.georgeliu.com »

9 259 shares, 21 trendiness

Advanced Search for YouTube

Try ad­just­ing your search terms or fil­ters

...

Read the original on playlists.at »

10 234 shares, 108 trendiness

Age Verification as Mass Surveillance Infrastructure

Peter Thiel con­trols both Palantir (surveillance an­a­lyt­ics) and Persona’s pri­mary in­vestor (Founders Fund) while Persona’s leaked source code ex­poses 269 ver­i­fi­ca­tion checks and gov­ern­ment re­port­ing mod­ules for FinCEN/FINTRAC

SDK de­com­pi­la­tion re­veals a hard­coded AES key (rotated in v1.15.3 af­ter dis­clo­sure), zero cer­tifi­cate pin­ning, silent car­rier phone ver­i­fi­ca­tion via Vonage, and 7 si­mul­ta­ne­ous an­a­lyt­ics ser­vices

Paravision pow­ers Persona’s fa­cial recog­ni­tion but is not listed on the sub­proces­sors page. Ranked #1 at DHS Biometric Rally

LinkedIn runs 4 iden­tity ver­i­fi­ca­tion ven­dors (AU10TIX since 2021, Persona, CLEAR, DigiLocker) and a par­al­lel Chinese sur­veil­lance stack with Sesame Credit so­cial scor­ing, ShanYan car­rier auth, and gov­ern­ment de­vice iden­ti­fiers in the same APK

197 sub­do­mains enu­mer­ated on with­per­sona.com ex­pos­ing 40+ clients (Roblox, Robinhood, Kaggle, Playboy, Italian gov­ern­ment). 65 stag­ing sub­do­mains ex­pose in­ter­nal ML ser­vices, TigerGraph, and the AAMVA gate­way

Roblox em­beds the full Persona SDK in a chil­dren’s game with NFC pass­port read­ing and a flow users can­not exit

Legislative man­dates across 25+ US states, Brazil, and the UK cre­ate the manda­tory mar­ket. Meta spent $26.3M lob­by­ing to push this leg­is­la­tion

No ads, no cor­po­rate fund­ing, no grants. Infrastructure, se­cu­rity, and re­search tools run en­tirely on do­na­tions.

Fund this pro­ject

Independent de­com­pi­la­tion of the Persona Wallet APK v1.14.0 (SDK v2.32.3, built March 11, 2026) and analy­sis of the web in­quiry bun­dle from cdn.with­per­sona.com (inquiry-main.js, 1.8MB) re­veals the full scope of Persona’s sur­veil­lance ca­pa­bil­i­ties. The APK was ob­tained from APKPure and de­com­piled with jadx 1.5.5. The Roblox APK v2.714.1091 was de­com­piled sep­a­rately to con­firm the SDK in­te­gra­tion. All find­ings are from pub­licly avail­able APKs and client-side JavaScript served to every user. New

Every copy of the Persona SDK con­tains a hard­coded AES-256-GCM en­cryp­tion key in TrackingEventUtilsKt.java line 22:

All teleme­try events are encrypted” with this key be­fore trans­mis­sion to POST https://​tg.with­per­sona.com/​t. Since the key is em­bed­ded in every pub­licly down­load­able APK, any­one can de­crypt the pay­loads. The en­cryp­tion pipeline se­ri­al­izes events to JSON, wraps them as {“events”: , en­crypts with AES-256-GCM us­ing a 12-byte ran­dom IV, then Base64-encodes the ci­pher­text and sends it as {“e”: . This is ob­fus­ca­tion, not se­cu­rity. A stand­alone Python de­cryp­tor was built and ver­i­fied in round-trip test­ing.

The SDK does not im­ple­ment cer­tifi­cate pin­ning. The OkHttpClient builder cre­ates a stan­dard client with­out cer­tifi­catePin­ner(). Combined with the hard­coded AES key, a stan­dard MITM proxy with a user-in­stalled CA cer­tifi­cate can cap­ture and de­crypt all Persona teleme­try from any app that em­beds the SDK.

What to look forThe okhttp­Client() method builds an OkHttpClient with­out call­ing cer­tifi­catePin­ner(). The builder chain is: addNet­work­In­ter­cep­tor → read­Time­out → write­Time­out → con­nect­Time­out → addIn­ter­cep­tor (loop) → build(). No pin­ning step ex­ists.

jadx -d out per­sona-wal­let.apk && grep -rn certificatePinner\|CertificatePinner” out/ - re­turns zero re­sults

pub­lic fi­nal OkHttpClient okhttp­Client(…) {

OkHttpClient. Builder builder­AddNet­work­In­ter­cep­tor =

new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {

pub­lic fi­nal Response in­ter­cept(In­ter­cep­tor.Chain chain) {

// … adds Persona-Version, Persona-Device-*, VTDGJLGG head­ers …

re­turn chain.pro­ceed(builder­Head­er3.build());

TimeUnit time­U­nit = TimeUnit.MINUTES;

OkHttpClient.Builder builder­Con­nect­Time­out = builder­AddNet­work­In­ter­cep­tor

.readTimeout(1L, time­U­nit)

.writeTimeout(1L, time­U­nit)

.connectTimeout(1L, time­U­nit);

Iterator it = set.it­er­a­tor();

while (it.hasNext()) {

builder­Con­nect­Time­out.addIn­ter­cep­tor((In­ter­cep­tor) it.next());

re­turn builder­Con­nect­Time­out.build();

// No cer­tifi­catePin­ner() call any­where in this chain.

A user go­ing through Persona ver­i­fi­ca­tion is tracked by seven an­a­lyt­ics ser­vices at the same time:

The Android SDKs Sentry con­fig­u­ra­tion sets io.sen­try.traces.sam­ple-rate = 1 (100% of ses­sions), io.sen­try.traces.user-in­ter­ac­tion.en­able = true, and io.sen­try.at­tach-view-hi­er­ar­chy = true. Every user ses­sion is fully traced with in­ter­ac­tion record­ing and UI hi­er­ar­chy cap­ture.

io.sen­try.dsn = https://​ad039950…@o175220.in­gest.us.sen­try.io/​4506939573993472

io.sen­try.traces.sam­ple-rate = 1 // 100% of ses­sions traced

io.sen­try.traces.user-in­ter­ac­tion.en­able = true // taps, clicks, ges­tures

io.sen­try.at­tach-view-hi­er­ar­chy = true // full UI tree on er­rors

ActivityLifecycleIntegration - tracks ac­tiv­ity start/​stop/​re­sume/​pause

FragmentLifecycleIntegration - tracks frag­ment life­cy­cle

UserInteractionIntegration - cap­tures user taps and ges­tures

NetworkBreadcrumbsIntegration - logs net­work con­nec­tiv­ity changes

ViewHierarchyEventProcessor - cap­tures view hi­er­ar­chy snap­shots

io.sen­try.an­droid.re­play.* - ses­sion re­play (record and re­play user ses­sions)

jadx -d out per­sona-wal­let.apk && find out/ -path *mx_com.mixpanel*” -name *.java” | wc -l

jadx -d out per­sona-wal­let.apk && find out/ -name firebase-*.properties”

Key classes found:

mx_­com.mix­panel.an­droid.mp­met­rics.Mix­pan­elAPI

mx_­com.mix­panel.an­droid.mp­met­rics.An­a­lyt­ic­sMes­sages

mx_­com.mix­panel.an­droid.mp­met­rics.Mix­pan­elAc­tiv­ityLife­cy­cle­Call­backs

mx_­com.mix­panel.an­droid.mp­met­rics.Per­sis­ten­tI­den­tity

mx_­com.mix­panel.an­droid.mp­met­rics.Sys­tem­In­for­ma­tion

20+ files to­tal. mx_­com pre­fix = repack­aged/​em­bed­ded build.

SystemInformation col­lects:

- Device model, OS ver­sion, screen di­men­sions

- Mobile car­rier name

- Bluetooth sta­tus

- NFC sta­tus

fire­base-an­no­ta­tions.prop­er­ties

fire­base-com­po­nents.prop­er­ties

fire­base-en­coders-json.prop­er­ties

com.google.an­droid.data­trans­port.cct.in­ter­nal.Cli­entInfo

Firebase com­po­nent reg­is­trars loaded at startup

The SDK can silently ver­ify a user’s phone num­ber through the mo­bile car­rier with zero user in­ter­ac­tion. The PhoneNumberSna com­po­nent uses Vonage (Ericsson sub­sidiary) to make an HTTP re­quest over the de­vice’s cel­lu­lar con­nec­tion. The car­rier in­ter­cepts the re­quest and ver­i­fies that the SIM card’s phone num­ber matches the num­ber en­coded in the URL. The re­quest fol­lows up to 10 redi­rects through car­rier au­then­ti­ca­tion in­fra­struc­ture. Results are auto-sub­mit­ted to Persona’s back­end with count­down=0, mean­ing the ver­i­fi­ca­tion hap­pens in­stantly. The user never sees, touches, or ap­proves the car­rier-level ver­i­fi­ca­tion.

From the de­com­piled source: the PhoneNumberSnaComponent im­ple­ments AutoSubmitableComponent. When ver­i­fi­ca­tion com­pletes, UiState.Displaying.AutoSubmit fires with count­down=0 and the form is sub­mit­ted im­me­di­ately.

pub­lic VonageSnaClient(Context con­text, SilentNetworkAuthConfig con­fig, Moshi moshi) {

this.con­fig = con­fig;

this.moshi = moshi;

VGCellularRequestClient.Companion.initializeSdk(context);

pub­lic SnaClient.Response per­form­Si­lent­Net­workAuth() throws Exception {

if (!SnaUtils.INSTANCE.isValidSnaCheckUrl(this.config.getCheckUrl())) {

re­turn new SnaClient.Response.Error(…);

JSONObject re­sult = VGCellularRequestClient.Companion.getInstance()

.startCellularGetRequest(

new VGCellularRequestParameters(

this.con­fig.getCheck­Url(), // URL from Persona server

MapsKt.emptyMap(), // head­ers

MapsKt.emptyMap(), // query params

this.con­fig.get­MaxRedi­rects() // fol­lows up to N car­rier redi­rects

), false);

// Carrier val­i­dates SIM -> re­turns suc­cess/​fail­ure JSON

During selfie cap­ture, the SDK streams live video to we­brtc-con­sumer.with­per­sona.com via WebRTC TURN con­nec­tions. The server re­ceives con­tin­u­ous video, not just cap­tured frames. An op­tional recor­dAu­dio flag en­ables au­dio record­ing dur­ing the stream. The SDKs VideoCaptureMethod pri­or­ity prefers Stream (WebRTC) first, falling back to Upload only if stream­ing is un­avail­able.

On-device face de­tec­tion uses Google ML Kit to ex­tract: bound­ing box, Euler an­gles (pitch, ro­ta­tion, tilt), smile prob­a­bil­ity, left/​right eye open prob­a­bil­ity, 10 face land­marks, and 15 face con­tour types. A 3x3 bright­ness grid di­vides the face re­gion into 9 zones and com­putes per-zone lu­mi­nance to de­tect flat pa­per or screen re­flec­tions. All anti-spoof­ing analy­sis is del­e­gated to the server. The terms an­ti_spoof, ac­tive_live­ness, pas­sive_live­ness, and depth do not ap­pear in the SDK code­base.

The SDK im­ple­ments ICAO 9303 BAC/PACE pro­to­col for read­ing e-pass­port chips. Data groups read from the chip:

Signed hashes of all data groups for tam­per de­tec­tion

The data groups are server-con­fig­urable via PassportNfcReaderConfig.enabledDataGroups. The server can re­quest ad­di­tional data groups at any time. Terminal Authentication (EAC-TA) is not im­ple­mented, mean­ing the pass­port chip can­not ver­ify whether Persona is an au­tho­rized reader. Chip Authentication is sup­ported but the ab­sence of Terminal Authentication means the chip has no way to refuse data ex­trac­tion.

The web in­quiry bun­dle con­tains the com­plete Persona plat­form en­tity reg­istry, ex­pand­ing well be­yond the February 2026 leak. 15 ver­i­fi­ca­tion types were not pre­sent in the leaked source or the Android SDK:

Persona now has in­te­gra­tion with 15 dig­i­tal iden­tity sys­tems across 14 coun­tries, in­clud­ing Worldcoin’s iris bio­met­ric World ID. The plat­form also sup­ports Aadhaar (India, 1.4 bil­lion en­rolled), Serpro (Brazil, 220 mil­lion), PhilSys (Philippines, 92 mil­lion), Singpass (Singapore), and ECBSV (US SSA Social Security num­ber ver­i­fi­ca­tion).

The web bun­dle re­veals 47 dis­tinct re­port types. The fol­low­ing third-party data in­te­gra­tions were not pre­vi­ously doc­u­mented:

Persona con­nects to Chainalysis and TRM Labs for crypto wal­let screen­ing, Equifax for credit bu­reau data, FINRA and the SEC for se­cu­ri­ties en­force­ment, Sentilink for syn­thetic iden­tity de­tec­tion, MX for fi­nan­cial ac­count ag­gre­ga­tion, and Kyckr for global com­pany reg­istries. The plat­form processes far more than iden­tity ver­i­fi­ca­tion.

The SDK sup­ports 26 dis­tinct gov­ern­ment ID types, in­clud­ing coun­try-spe­cific doc­u­ments: Japan MyNumber Card (myn), Singapore/Malaysia NRIC (nric), Philippines OFWID (ofw), Philippines UMID (umid), Philippines NBI Clearance (nbi), and India PAN Card (pan). US and Canadian dri­ver’s li­censes are parsed via an AAMVA PDF417 bar­code reader that ex­tracts 13 fields: first name, mid­dle name, last name, sex, street ad­dress, city, state, postal code, ID num­ber, is­sue date, ex­pi­ra­tion date, date of birth, and coun­try.

Decompilation of the Roblox APK v2.714.1091 con­firms the full Persona SDK is em­bed­ded un­der the in­ter­nal mod­ule name com.roblox.uni­ver­salapp.fa­cialagees­ti­ma­tion. The in­te­gra­tion bridge at com.roblox.client.per­sonasdk passes ver­i­fi­ca­tion re­sults through a JNI (Java Native Interface) bridge di­rectly into Roblox’s C++ game en­gine. The DisablePauseSessionInPersonaFlow fea­ture flag pre­vents users from paus­ing or back­ground­ing the app dur­ing ver­i­fi­ca­tion, en­sur­ing the con­tin­u­ous WebRTC video stream is not in­ter­rupted.

Roblox’s man­i­fest in­cludes per­mis­sions for cam­era, au­dio record­ing, NFC, bio­met­ric au­then­ti­ca­tion, fin­ger­print, Bluetooth, and con­tacts (READ_CONTACTS, un­usual for a game). The full 21-endpoint API sur­face and all sur­veil­lance ca­pa­bil­i­ties doc­u­mented above are avail­able in­side Roblox, an app where 67% of users are un­der 16.

The Persona client is a state­less ren­derer. The server dic­tates every step, every com­po­nent, and every tran­si­tion via 38 UI com­po­nent types and 12 in­quiry states. There is no hard­coded step se­quence in the SDK. The server can dy­nam­i­cally in­sert, re­order, or skip any step for any user based on risk scor­ing, tem­plate con­fig­u­ra­tion, or real-time de­ci­sions. This means the ver­i­fi­ca­tion pipeline ex­pe­ri­enced by one user can be com­pletely dif­fer­ent from an­other, and users have no way to pre­dict or au­dit what data col­lec­tion steps will be trig­gered.

Every API re­quest is signed with four ob­fus­cated head­ers: NHMJLNRS (HMAC-SHA256 hash of JWT sub, time­stamp, and re­quest body), STPBWSBB (Unix time­stamp), DNLGNZLZ (secondary hash in­cor­po­rat­ing header val­ues), and TLJLGGDG (list of signed header names). A fifth header, VTDGJLGG, re­ports whether a de­bug­ger is at­tached to the process via Debug.isDebuggerConnected(). This flag is in­cluded in the signed header set, mak­ing it tam­per-ev­i­dent. Google Play Integrity ver­i­fi­ca­tion runs with up to 5 re­tries and a 1-second de­lay be­tween at­tempts.

The fol­low­ing keys are em­bed­ded in pub­licly served client-side code. All were con­firmed ac­tive through test­ing:

Sentry or­ga­ni­za­tion ID is o175220. All three Sentry DSNs map to the same or­ga­ni­za­tion. The web in­quiry bun­dle also con­tains Datadog RUM ap­pli­ca­tion ID and client to­ken, and an Osano CMP (consent man­age­ment) ac­count iden­ti­fier.

The web ver­i­fi­ca­tion flow loads faceapi.js (1.3MB), which in­cludes an age_­gen­der_­model for client-side age and gen­der es­ti­ma­tion. This ML model runs in the browser be­fore any data is sent to Persona’s servers. The doc­u­ment OCR mod­ule (microblink.js, 91KB) per­forms MRZ read­ing di­rectly in the browser.

DNS TXT record analy­sis of with­per­sona.com re­veals do­main ver­i­fi­ca­tion to­kens from com­pa­nies con­firm­ing ac­tive in­te­gra­tion re­la­tion­ships: New

Meta spent $26.3M lob­by­ing for age ver­i­fi­ca­tion laws via the Digital Childhood Alliance while si­mul­ta­ne­ously main­tain­ing a do­main ver­i­fi­ca­tion in­te­gra­tion with Persona, the com­pany that would profit from those laws. Meta is also a found­ing plat­form part­ner of the OpenAge Initiative (Dec 2025), where Persona is an iden­tity ver­i­fi­ca­tion mem­ber (Jan 2026).

Certificate trans­parency con­firms ope­nai-watch­listdb.with­per­sona.com has been op­er­a­tional since November 16, 2023. Testing en­vi­ron­ment at ope­nai-watch­listdb-test­ing.with­per­sona.com re­solves to the same GCP Kansas City IP (34.49.93.177). Twenty-two cer­tifi­cates to­tal, re­newed every two months, still ac­tive as of March 18, 2026. Twenty-seven months of con­tin­u­ous op­er­a­tion be­fore pub­lic aware­ness via the February 2026 leak. OpenAI has never pub­licly dis­closed this watch­list data­base. Winbuzzer

...

Read the original on tboteproject.com »

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

10HN is also available as an iOS App

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

If you like 10HN please leave feedback and share

Visit pancik.com for more.