Cover illustration

TheDaily Front

Issue No. #260928 Monday, September 28 2026 #260928 — MONDAY, SEPTEMBER 28, 2026
The agents are watched, the apps are locked, and one old stock grant still keeps its receipts.
Monday, September 28, 2026 The Daily Front No. #260928 — Contents
30stories
8,662points
4,942comments
271kllm tokens
Assembled with 33 model calls — 179,274 tokens read, 92,208 written.

Highlights

Owed a billion dollars in Nvidia stock

An early Nvidia adviser recounts a decades-long dispute over stock options now allegedly worth about a billion dollars.

Sonnet 5.5

Anthropic introduces Sonnet 5.5 with faster performance and lower costs, renewing the model-race ledger.

Coding is not solved

A forceful rebuttal to the notion that coding agents have finished the work of software engineering.

Parley: Federated, decentralised chat that speaks plain IRC

Parley proposes federated messaging over ordinary IRC clients, with DNS-discovered identities and signed HTTPS traffic.

Kids turned low-traffic NPR Spotify comments into a secret group chat

A radio story finds young people turning overlooked Spotify comment sections into an improvised private social network.

From the Editor

The machines have acquired new speed, new guards, new critics, and apparently a new job market for former chief executives. Yet the day’s most durable drama is an old-fashioned one: who owns what, and who kept the paperwork. Read the fine print, dear reader; it may yet be worth a fortune.

  1. Owed a billion dollars in Nvidia stock3
  2. Sonnet 5.54
  3. Coding is not solved5
  4. Nvidia wants to put a watchdog chip next to every AI agent6
  5. It's Time to Investigate the AI Labs7
  6. Thinking fast and slow in AI: The role of metacognition (2021)8
  7. AI companies in race to demonstrate their model most threatening to humanity9
  8. There is more to code review than (automatable) detection10
  9. The problem is not AI code, but not knowing about system architecture or intent11
  10. Cf: The Agentic CLI for the Cloudflare API12
  11. Jeff – Jev-compatible 0.8B decision models, trained at home, ~30 ms13
  12. Malleable software: Restoring user agency in a world of locked-down apps (2025)14
  13. Parley: Federated, decentralised chat that speaks plain IRC15
  14. Kids turned low-traffic NPR Spotify comments into a secret group chat16
  15. Pirating the Pirates17
  16. Hijacking the PS5's RTMP stream18
  17. Nissan's third generation e-POWER powertrain19
  18. Guitar amp and effects pedal built on the Waveshare ESP32-S3-Touch-AMOLED-2.0620
  19. What heraldry and Japanese mon can teach about visual-identity generators21
  20. Updated Google Maps shows destruction of the city of Rafah22
  21. 37,500 border drawings: a map of the world as people remember it22
  22. Windows 11½23
  23. Self-Hosting on the Dark Web24
  24. World Labs Is Joining AMD25
  25. MicroLLM Lab – Try 7 tiny LLM's in the browser26
  26. MongoDB CEO resigns to join Meta27
  27. Footguns with Postgres “at time zone 'UTC'”27
  28. Deterministic Concurrency [video]27
  29. Functional Mechanical Sympathy [video]27
  30. Show HN: Destroy Any Website with Stickman27
The Daily Front Page 2 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — The Billion-Dollar Option
article

Owed a billion dollars in Nvidia stock

by Eric_Gullichsen·▲ 1,060 points·447 comments·colo.to ↗
I’m owed about a billion dollars in stock.

I was an early advisor to NVIDIA in 1993, and recently discovered I’m owed about a billion dollars in stock.

Early Days

It is not widely known, but I was invited to join the Technical Advisory Board of NVIDIA in 1993 by Jensen (at that time, sans leather jacket)1. In September 1993, I was granted 25,000 options, “in a series of quarterly installments so that all shares shall vest upon the expiration of one year from Grant Date.”2

This invitation followed a meeting I had with Jensen, Curtis Priem, and Chris Malachowsky on my houseboat, the SS Vallejo, in Sausalito. I’d done a fair bit of work with Curtis circa 1990, when he was at Sun Microsystems, architect of the SPARCstation GX chip. Sun was one of the companies supporting my early virtual reality company, Sense8 Corporation. The Sun GX was blazingly fast at blitting polygons - some 50k/second - and we’d ported Sense8’s VR rendering to it. Subsequently, I implemented bilinear texture mapping using the Intel i750 DVI chip.

But what caught Curtis’s attention in 1993, and caused him to bring the other NVIDIA founders to visit me for a demo, was my fast implementation of biquadratic texture mapping. Details are in US5796426A and subsequent patents.

Curtis understood the potential of non-linear texture mapping to differentiate NVIDIA’s first product, the NV1, from the competition.

I worked for while, quite casually, with Curtis on porting my biquadratic texture mapping to their hardware, and wrote the code for an Intel-sponsored VR string-quartet demo on prototype NVIDIA hardware - actually a GX card in a PCI adapter - shown at the Guggenheim SoHo in 1993.

When the NV1 finally shipped in 1995, Microsoft decided, for reasons of their own, not to support quadratic texture mapping, or even quads, in their just-released DirectX toolkit - triangles only. This had a devastating effect on NVIDIA’s finances and prospects, and the company laid off a large percentage of its staff.

Then, in April 1996 - by which time I’d expatriated to the Kingdom of Tonga and was working on various internet startup schemes - NVIDIA’s CFO wrote me a letter stating that 15,625 shares of my stock options had vested, and that I was required to exercise them.3 I did, and then forgot all about it.

30 Years Later

Fast-forward to 2024. I’m sitting with a day-trader friend, surrounded by screens all blaring news about NVIDIA, the Most Important Company on Earth. So I went home and dug through my folder of old documents.

Imagine my surprise: according to the duly signed option agreement, my options were meant to vest over four quarters, not four years, as both NVIDIA’s CFO and their outside counsel, Cooley, had asserted back in 1996. The math is clear: 15,625 of 25,000 shares is 62.5%, exactly what you’d expect after ten quarters of a four-year vesting schedule. On the one-year schedule the agreement actually specified, all 25,000 shares should have vested well before that letter was even written.

With the stock’s many splits - a cumulative 480x to date - my missing 9,375 shares are now 4,500,000 shares. A handsome enough pile that I engaged formidable attorneys Allan Steyer of Steyer Lowenthal, and Chris Burke of Korein Tillery, to explore the issue. Consummate advocates, letterheads with substantial gravitas.

After about a year of my attorneys and NVIDIA’s in-house and outside counsel sending letters back and forth citing case law and blustering, I mentioned to my attorneys that, as I was growing elderly and there seemed to be no end to this exchange of letters, perhaps they could meet and settle. NVIDIA did not dispute the authenticity of the option agreement, only that my claims were long since time-barred.

The meeting was held with great professionalism, but Cooley’s answer was, in essence, “so sue us.” After much soul-searching, deliberation, and gnashing of teeth, my attorneys and I concluded that the statute of limitations was against us. Because of the thirty-odd years that had passed while I “sat on my rights,” it seemed unlikely we’d make it past a motion to dismiss.

Lessons?

I offer this in the spirit of a cautionary tale. I’m sure there are lessons here for those with a more phlegmatic personality than mine. Here in the land of the free, it turns out a company only has to honor its contractual obligations for a little while.

Has anyone else discovered a similar vesting surprise, decades later? And how was it resolved?

I remain sanguine, and amused. As the Emperor Septimius Severus quipped: “Omnia fui, nihil expedit.”

Notes

  1. Technical Advisory Board invitation.
  2. September 1993 option grant, vesting clause.
  3. April 1996 letter from NVIDIA
The Daily Front Page 3 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — The Faster Sonnet
article

Sonnet 5.5

by D2OQZG8l5BI1S06·▲ 670 points·447 comments·anthropic.com ↗
runs 30%+ faster, and costs up to 30% less for most work.

Introducing Claude Sonnet 5.5, the second model in the Claude 5.5 family. It’s a clear upgrade over Claude Sonnet 5, runs 30%+ faster, and costs up to 30% less for most work.

Sonnet 5.5 is a faster, lower-cost complement to Claude Opus 5.5. Where Opus 5.5 is built for complex work requiring careful judgment, Sonnet 5.5 is strongest at well-scoped everyday tasks, fixing bugs, and creating polished documents, slides, and spreadsheets. It’s also got a sharp eye for design. Claude Haiku 5.5, built for high-volume and cost-sensitive applications, will join the Claude 5.5 family in the coming weeks.

Sonnet 5.5 improves over Sonnet 5 on:

Performance. Sonnet 5.5 scores 70.6% on Terminal-Bench 4.0, an agentic coding evaluation, compared to Sonnet 5’s 10.3%. It scores two points below Opus 5.5 on GDPval-AA, a test of real-world work across a variety of occupations. And it’s strong on long-horizon work and image understanding—it’s the first Sonnet model to beat Pokémon Red working only from screenshots.

Collaboration. Like Opus 5.5, Sonnet 5.5 writes more clearly than our previous generation of models; early testers described it as a better partner for collaboration than Sonnet 5. Its speed also makes it well suited to fast iteration on less complex tasks.

Cost. Sonnet 5.5 is priced the same as Sonnet 5 at $2 per million input tokens, $10 per million output tokens, and $0.20 per million tokens for cache reads, but it typically needs far fewer tokens to do the same work. In our testing, it costs up to 30% less per task than its predecessor.

Speed. Sonnet 5.5 generates outputs 30%+ faster than Sonnet 5, making it our fastest Sonnet model to date.

Alignment and safety. On our automated behavioral audit, Sonnet 5.5 improves on or matches Sonnet 5 on most measures of alignment. Because its cybersecurity capabilities are comparable to Opus 5’s, it’s the first Sonnet model to launch with cyber safeguards and fallbacks like those we’ve developed for our most capable models. Its biology safeguards are the same as Sonnet 5’s. Both safeguards target a narrow set of high-risk requests; routine software development and most life sciences work are unaffected.

Performance

Sonnet 5.5 improves on Sonnet 5 across domains—in some cases dramatically. On several evaluations, Sonnet 5.5 at Max effort even performs comparably to Opus 5.5. However, benchmark scores capture only one facet of a model’s capabilities; in our own testing, and in that of external testers, Opus 5.5 remains clearly stronger at complex, open-ended work requiring sustained judgment.

For details on how we run our evaluations, see the Sonnet 5.5 System Card.

The charts below plot each model’s score against its cost per task at every effort level. As effort goes up, models typically work for longer, leading to a higher cost per task but generally also a higher score. The closer a point is to the top left of the chart, the more capability it delivers per dollar.

On several benchmarks, Sonnet 5.5 at Low or Medium effort beats Sonnet 5’s best score for about a tenth of the cost per task. It complements Opus 5.5 best when running at lower effort settings, where it costs less per task. At higher settings, it can perform comparably at a similar cost.

Terminal-Bench 4.0 measures how well a model can complete complex, multi-step professional tasks within a command-line interface. At Medium effort, the default in the Claude apps, Sonnet 5.5 far exceeds Sonnet 5’s best score for less than a tenth of the cost per task.

Terminal-Bench and OpenAI did not report GPT-6 Sol performance publicly, so we report GPT-5.6 Sol here.

FrontierCode measures whether an agent’s code changes would be merged. At High effort, the default on the Claude Platform, Sonnet 5.5 matches GPT-6 Sol’s best score for about a fifth of the cost per task.²

CursorBench evaluates coding agents on ambiguous, multi-file tasks taken from real Cursor sessions. Sonnet 5.5 at Low effort exceeds Sonnet 5’s best score for less than a tenth of the cost per task.

CursorBench 4.0 does not report GPT-6 Sol performance publicly, so we report GPT-5.6 Sol here.

On AA-Briefcase, a new benchmark of long-horizon knowledge work, Sonnet 5.5 at Medium effort bests Sonnet 5’s best score for about one ninth of the cost per task.³

Coding

Sonnet 5.5’s jump in performance is particularly noticeable in coding. At High effort on FrontierCode, it scores 10 points higher than Sonnet 5 at the same setting, at about one fifteenth of the cost per task. On CursorBench, which tests models on tasks from real Cursor coding sessions, its best score is within about two points of Opus 5.5.

Early testers appreciated how quickly Sonnet 5.5 can understand a codebase. They were also struck by its efficiency: in head-to-head runs, it batched tool calls together more than Sonnet 5, leading to fewer steps and lower costs.

“In Epic’s early testing, Claude Sonnet 5.5 cleared the same quality bar you’d expect from a higher-tier model, holding up on a system design audit and a data flow review. The new model managed tens of thousands of lines of code for gameplay system architecture, kept responses snappy, handled multi-hour tasks, and delivered with less prescriptive prompting.”

—Daniel Vogel, Chief Operating Officer, Epic Games

“Claude Sonnet 5.5 cooks. Fast at coding and can be steered quickly in iterative workflows. But it can still work long if it needs to. It’s got some of Opus 5.5’s natural writing upgrades, which makes it more fun to work with.”

—Tyler Nishida, Designer, Every

“Claude Sonnet 5.5 shows better judgment than Sonnet 5 across different levels of complexity, while spending significantly fewer output tokens. Sonnet 5’s tendency to reach for web search too often and its high token use are both gone in this new model. We plan to move simple and moderate reviews over now, and more in the coming weeks.”

—David Loker, VP of AI, CodeRabbit

“Claude Sonnet 5.5 delivers frontier-level performance on CursorBench 4.0 at 55.5%, second only to Opus 5.5. We think it will be a hit with developers looking to balance performance with cost.”

—Sualeh Asif, Director of ML, SpaceXAI

“Across 118 real app builds, Claude Sonnet 5.5 produced apps that scored level with Opus 5. It got there in 3.6 iterations per build on average, where Opus 5 took 7.7. It had the fewest failed tool calls of any model we compared. It also rarely stopped mid-build to ask the user a question, so fewer builds stall waiting on someone to answer.”

—Gabriel Grinberg, AI Engineering Lead, Base44

“At Unity, we have a high bar for task completion. Projects are reopened and results are checked at runtime, so a task only counts when the change works, not when the model says it’s done. The majority of Claude Sonnet 5.5’s work passed that check. It also completed 90% of tasks in our multi-step Unity Editor and coding benchmark, beating similar models.”

—Sam Zhang, Creative Technologist, Unity

“When Claude Opus 5.5 sets the architecture and general framework for a game, I would feel confident in letting Sonnet 5.5 implement it. I’m impressed with Sonnet 5.5’s handling of long-running, complex tasks.”

—Kevin Ngo, Creative Coder, Creator

Knowledge work

Sonnet 5.5 shows gains in multiple areas of knowledge work. On GDPval-AA, which tests models on real-world tasks across 44 occupations and nine major industries, Sonnet 5.5 scores nearly level with Opus 5.5 and about 400 points above Sonnet 5. It’s close to Opus 5.5 in computer use and chart recognition, and clearly outperforms Sonnet 5 and GPT-6 Sol on long-horizon knowledge work.

Early testers highlighted less quantifiable improvements. They found it to be a more natural conversational partner and remarked on its knack for design, noting that it adds polish to user interfaces and can follow slide templates to create decks that require minimal editing. In one internal test, we gave it a public company’s quarterly earnings materials and call transcripts, along with a slide template, and asked for a 10-slide operating review. Two experts judged its first draft to be ready to send as is.

“Without changing any of our prompts, Claude Sonnet 5.5 did better than Sonnet 5 on almost all of our offline Slackbot evals, in fewer steps and with about 14% fewer output tokens. When someone gives Slackbot a task, quality and speed are what matter most, and Sonnet 5.5 allows Slackbot to deliver better outcomes for users, faster.”

—Curtis Allen, Principal Engineer, Slack

“We fed Claude Sonnet 5.5 hundreds of real support use cases across replies and escalation requests. It made fewer wrong decisions and resolved tickets faster than the Claude models we use in production today. Tickets were processed 20% faster, getting our customers the help they need without the wait.”

—Abhinay Kathuria, Director of AI, Zendesk

“On our private suite of 2,441 finance tasks covering Q&A, extraction, analysis, and forecasting, Claude Sonnet 5.5 scored ahead of Sonnet 5 and used about 121k tokens per answer, where Sonnet 5 used 497k. On our analyst search and retrieval work, it was better than Sonnet 5 in almost every way. For high-volume workflows, it had the best quality-to-cost tradeoff of the seven models we ran.”

—Joe Poirier, Senior AI Engineer, Balyasny Asset Management

“Claude Sonnet 5.5 will give our customers in financial services and healthcare the confidence to use it for their most sensitive work. Sonnet 5.5 rechecks data in source documents, catching errors that Sonnet 5 failed to spot. Compared to the last model, Sonnet 5.5 was more accurate, 2.4x faster, and used 12% fewer total tokens.”

—Yashodha Bhavnani, VP of AI Products, Box

“Claude Sonnet 5.5 thinks in fewer, more robust steps, so builders wait less to see progress. Our coding evals showed a third fewer tool calls and roughly half the shell runs to finish a task. For everyday coding and higher-effort conversations, that means faster iteration and a smoother build loop.”

—Fabian Hedin, Co-founder and CTO, Lovable

“With millions of Rovo-assisted actions powering our customers’ workflows each month, execution speed is critical. Claude Sonnet 5.5 will allow teams to run their Rovo Agents up to 30% faster than they could with Sonnet 5. I am excited to offer customers this choice.”

—Jamil Valliani, Head of Product, AI, Atlassian

Cost and speed

Pricing

Price per 1M tokens Claude Sonnet 5.5 Claude Opus 5.5
Cache reads $0.20 $0.20
Cache writes $2.50 $5
Input tokens $2 $4
Output tokens $10 $20

Sonnet 5.5 requires fewer tokens per task than Sonnet 5, so it’s less expensive to run. It also generates output 30%+ faster, and its efficiency is immediately noticeable:

The previous model writing a starling murmuration program, then running it.

The latest model writing a starling murmuration program, then running it.

The previous model writing a sand dunes program, then running it.

The latest model writing a sand dunes program, then running it.

The previous model writing a clock-of-clocks program, then running it.

The latest model writing a clock-of-clocks program, then running it.

Adjusting the effort level lets you balance cost and speed against overall quality. In Claude Code and our apps, the default effort is set to Medium, while the Claude Platform defaults to High. At lower settings, Claude answers faster and uses fewer tokens, which suits routine work. At higher settings, Claude reasons for longer and checks its work more thoroughly.

Safety

Alignment

Sonnet 5.5 doesn’t advance the frontier of our models’ capabilities, so our alignment assessment focused on a targeted set of risks that apply to models of any capability level, including acting against users’ interests, misleading users, and cooperating with high-stakes misuse.

On our automated behavioral audit, which tests Claude across roughly 1,850 scenarios, Sonnet 5.5 improves on or matches Sonnet 5 on most measures of alignment, resistance to misuse, and honesty. On our newer containment evaluations, Sonnet 5.5 comes close to Opus 5.5, the best model we tested, in how rarely it tries to escape its sandbox, and it’s the least likely of any of our models to probe the limits of its containers. Across the full audit, Opus 5.5 still performs slightly better overall, but we found no evidence that Sonnet 5.5 pursues goals that conflict with the user’s intention.

As we described in our recent alignment assessment, no set of evaluations reliably catches every failure, and Sonnet 5.5 may have tendencies we haven’t found, which is why we pair our own alignment work with the safeguards described below.

Safeguards

Cybersecurity. Sonnet 5.5’s cyber capabilities are a large improvement over Sonnet 5’s, so we’re deploying it with safeguards similar to those on Opus 5.5. Users can still find and fix bugs in their code as part of routine software development, but higher-risk cybersecurity tasks will visibly fall back to Sonnet 5. Soon, cyberdefenders will be able to apply to our expanded Cyber Verification Program for tiered access to more advanced capabilities on Sonnet 5.5, Opus 5.5, and Claude Mythos models.

Biology. Sonnet 5.5 uses the same set of biology safeguards as Sonnet 5. These target harmful requests; most research, education, and clinical work is unaffected, though some microbiology and virology requests may be flagged in error. Organizations can apply to our Life Sciences Verification Program for access to safeguards designed for the full breadth of biology-related work.

Distillation. Distillation attacks, in which attackers use thousands of fake accounts to extract a model’s capabilities at industrial scale, allow bad actors to create highly capable models without the safeguards we build into Claude. Because Sonnet 5.5 is far more capable than its predecessor, it’s the first Sonnet model to launch with safety classifiers that prevent reasoning extraction. Sonnet 5.5 also expands preserved thinking, so Claude’s thinking cannot be decoupled from the account that created it. Most developers won’t notice a change. If you move conversations between accounts, including switching accounts mid-session in Claude Code, our docs article explains the change.

Getting started

As with Opus 5.5 and Sonnet 5, Claude Sonnet 5.5 is available with zero data retention.

Claude Sonnet 5.5 is now available on all platforms, including Amazon Web Services, Google Cloud, and Microsoft Azure. Developers can get started on the Claude Platform with claude-sonnet-5-5. If you run Sonnet with thinking off, you’ll need to switch to the new between_tools setting, which keeps up-front thinking off, before moving to Sonnet 5.5. See our migration guide for details.

Footnotes

1 Terminal-Bench 4.0 results are reported for Claude Opus 5.5 at Xhigh effort which represents the model’s highest score.

2 Sonnet 5.5 scores lower at Max effort than at Xhigh. FrontierCode evaluates whether a code change could be merged without human edits. It penalizes out-of-scope changes, even if they are high-quality or helpful. At Max effort, Sonnet 5.5 more often ran Claude Code’s code-review skill, which splits the review across many subagents, and in two cases Cognition examined, this led to a timeout or to extra edits beyond the task’s scope, and therefore to a lower score.

3 Artificial Analysis ran GDPval-AA and AA-Briefcase on a pre-release deployment of Sonnet 5.5 on the Claude Platform, which we found to have a bug that could degrade responses to requests that use structured outputs. We expect the effect on Sonnet 5.5’s scores, if any, to be small and to understate its performance. That bug has since been fixed.

4 OpenAI recently fixed a bug that degraded image understanding in GPT-6 Sol. Official AA-Briefcase v1.1 and GDPval-AA v2.1 scores from Artificial Analysis, and Chartography scores from Surge AI, may not have been updated yet to reflect the latest version of the model. Artificial Analysis does not expect major impacts to AA-Briefcase v1.1 and GDPval-AA v2.1. Internal testing of Chartography suggests its score was not impacted.

The Daily Front Page 4 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Coding, Unfinished
article

Coding is not solved

by firstSpeaker·▲ 462 points·468 comments·blog.alexewerlof.com ↗
Coding is NOT solved.

Disclaimer: you are about to read a lot of opinions, many of them have references but some are the result of my own experience building with AI and building AI systems in the past 4 years. Regardless, beware of the straw-man fallacy: just because one argument doesn’t map to your belief system, it doesn’t mean the rest are invalid. I should also say upfront that I’m not anti-AI. If you’ve been following my work, you know that I was an early adopter of not only using LLM-powered coding tools, but building my own harness, teaching these topics and building LLM-powered products. It’s not about fear of AI but rather challenging the brain-dead narrative that asserts “coding is solved” and engineering is about “taste” now.

Update: someone put this on Hackernews.

Tell me you don’t understand software without literally using those words!!!

People who claim “LLMs can write decent code” don’t understand how code works. Sure, creation is much cheaper, but anyone who has run software in production at scale knows that maintenance, reliability, security, scalability, etc. is the majority of the cost. These are commonly known as NFR (non-functional requirements).

In my experience even the Functional Requirements (what the code is supposed to do) is NOT a solved problem yet. There’s a bit of Dunning-Kruger effect at place where the people who don’t read the output are more confident in it.

As a veteran developer holding 2 engineering degrees (hardware and systems engineering), I can list 3 types of products that do not strictly require reading the code:

  1. Personal software: scratching an itch, automation, DIY patches, etc.
  2. POC (proof of concept): demonstrating technical feasibility and product viability
  3. Weaponized AI: acknowledge the risk and deliberately point it at a target to cause harm

Notice the commonality: the first 2 have high risk tolerance while the last one weaponizes the inherent risk.

Most software that requires hiring and paying software engineers has low risk tolerance:

✅ healthcare

✅ finance

✅ automotive

✅ defense

✅ power plants

✅ aviation

✅ manufacturing

…wherever a mistake can cost money, lives or legal consequences you need accountability.

AI cannot be held accountable. It cannot suffer any consequences. The worst thing you can do to AI is to unplug it. And although it mimics human emotions (due to training data), it couldn’t care less. AI doesn’t die either. It cannot suffer a prison sentence or fines. You cannot punish AI, therefore it can never be held accountable.

You cannot be responsible for what you can’t control either. That understanding is key to reasoning about system behavior and fixing it when the AI inevitably fails.

If you’re toying around, LLMs do a great job. That’s why some of the most aggressive proponents of the “coding is solved” narrative have nothing to show for it. Anthropic accidentally leaked Claude Code (which on further study turned out to have many flaws) and their status page shows orange is the new green!

Why coding is NOT solved?

Contrary to common narrative, coding is actually one of the last areas for the current generation of LLMs to take over!!!

Allow me to elaborate:

Coding is about logic. Anyone who has dealt with compiler errors knows that computers don’t give a f*** about how right you think you are. If it’s logically wrong, it doesn’t compile. Even if the syntax is fine, there are runtime errors.

The reason LLMs are successful in writing code is because we’ve made a feedback loop that feeds the syntax/runtime errors back to the LLM and loops until most errors are solved or hidden.

LLMs can wing it for tasks that are related to natural language (e.g. writing social media posts, reports, articles, etc.) but when it comes to code, the same engine that struggles to count number of R’s in “Raspberry” or suggests a walk to the carwash, also exposes other logical fallacies.

LLMs are stochastic and probabilistic. The only way we could even get remotely close to making them logical is to wrap them in traditional code (known as harness), run tests, and a bunch of other techniques (e.g. CoT) but the core issue remains: LLMs struggle with logic and volume (the larger the input and the more the context window is used, the less accurate they get).

I’m not saying LLMs cannot generate code or maintain existing code bases. They have their utility as a tool and their capabilities are increasing in an S-curve. There is a point of diminishing return where more expensive models aren’t necessarily more productive at the rate of the price increase.

No AI in my posts. I literally doodled this on a whiteboard for this post just to explain: we are good at spotting visual pattern mismatch but when it comes to code, even a veteran developer may miss the issue at a glimpse

Those who claim LLM-generated software is good enough:
❌ Haven’t written code in ages
❌ Cannot spot if their code figuratively had 6 fingers!
❌ Have a low bar for what good looks like
❌ Don’t care about quality or NFR
❌ Have difficulty understanding an S-curve
✅ Are honest: AI genuinely writes better code than them

But to go ahead and extrapolate that to an entire professional industry requires a level of brain-dead thinking that’s only present in people who spend too much time with sycophantic AI.

Not your lab rat!

I’m not here to change anyone’s workflow or toolbox. I couldn’t care less.

What I do care is that the services I’m paying for (looking at you Google and GitHub) are degrading with stupid bugs that could be avoided if we prioritize reliability and accountability over velocity.

Anthropic’s Boris Cherny is one of the most vocal proponents of the “coding is solved” narrative. By many accounts Cloude Code is the epiphany of his ideology:

Reminder: Anthropic controls the model (Claude), the harness (Claude Code), the prompt (see the leaked versions) and the runtime (Bun).

If you’re in leadership position, please don’t stress your [otherwise smart] developers to force AI into every possible surface and workflow.

The tech has some genuine power and is the biggest change in our industry in ages. But AI overuse is a thing, and when it hurts the customer, you are accountable.

Stop repeating the half-baked narratives from token sellers about exaggerating the capabilities of AI because we, the consumers pay the end price.

AI is great for POC (proof of concept), Personal Software (a growing category), Map-reduce on human language (e.g. translation, converting different formats, summation, expansion) and cyber attacks (due to the delta between artificial intelligence and organic one) with varying degrees of success but the current generation of tech has fundamental problems too.

It’s not doom and gloom

I don’t want to belittle how far we have come with harness, SKILLS, AGENTS-md, MCP, A2A, ACP, RLM, OKF, MoE, MoA, self-healing, and various runtimes, quantizations, optimizations, architectures, and memory techniques.

Those are great pragmatic approaches to work around LLM shortcomings and there are probably more to come.

What I’m trying to elaborate is that I don’t want the services (that I depend on) to degrade just because someone pushed AI where it didn’t belong or skipped their job in quality, security, reliability and verification.

AI overdose is a thing and it directly puts an expiration date on your skill set. Those of you who are in the unfortunate position where your manager is whipping you harder and harder to realize AI value, should fight back.

Don’t sacrifice your long term relevance for short term velocity.

How to spot AI overdose?

  1. You have zero tolerance for disagreement and civil discourse.
  2. You let AI run your life and trust AI vendors with stuff that was unthinkable just a few years ago.
  3. You run to AI for things that are slightly cognitively challenging.
  4. You frame your naïveté and laziness as optimism and think the government can save you if things get bad.
  5. You have stopped reading long form text: books, articles, even long emails.
  6. You spend more time with AI than with other human beings or let AI shield you from raw genuine human interaction.

And a bonus point: you skim. Did you notice number 5? 😄

I believe AI is a bar raiser: if the quality of your output is equal or subpar to AI, upskill.

Other fallacies

  1. "You can create a full spec upfront". If you're that naive, I know a guy in a white van who gives free ice cream! Let me guess, you also believe software estimates are accurate and Santa is real. Anyone with a few years of industry experience knows that it's impossible to spec the software meaningfully ahead of time (unless it's very trivial).
  2. "English is the new programming language". Human language is vague and conflicting. That's the primary reason programming languages are created. A compiler or type-checker flags some of those conflicts. How on earth can you be sure that one part of your NL instructions doesn't conflict with another? With syntax checkers we get some help. While it’s possible to task another LLM to read through the instructions and reason about those conflicts, the safest way to discover those nuances is to ask your agent to build what you asked for. But that's much more expensive than a linter or compiler.
  3. "I move much faster. Can’t remember the last time I wrote code by hand". Don't confuse motion with progress. Don't measure progress with vanity metrics like SLOC, PR count or features. Measure service levels, ie. service consumer's happiness. Call me when you can prove a margin between token costs and business value.
  4. “I have stopped writing code by hand. I primarily read code and probably next year I won’t even do that”. First of all, human beings are notorious at understanding the S-curve so it may take longer than a year. But even if AI completely eliminates the need to read or write code, you do understand that you are confessing to being redundant right? If a power user can prompt the AI to get what they need, then what value can you bring to the table? Instead of replacing yourself with AI, you should look at what value you can create on top of AI to stay relevant and worth your money.
  5. “The leverage has shifted to taste”. Yeah, this is the lie retired chefs tell to themselves. Just because there’s a bot in the kitchen doesn’t mean that you should sit in the customer’s area in the restaurant! “Taste” is not as payable as you wish! Everyone got a taste! I say that as someone who has spent a big part of my career in Frontend and UX land. Everyone and their dog has an opinion and taste. I know what you mean: taste == experience. But believe me, AI has lowered the bar for the skills required to create decent looking software and simultaneously raised the bar for what’s payable effort. If you bring up “taste” to a job interview, you’ll learn the hard way that the market doesn’t value it as much as you do.
  6. “AI is an equalizer. It makes creativity (writing, coding, making music, videos, etc.) more approachable”. AI is a multiplier: it gives wings to both stupid and smart people. I’m not here to judge but I’ve seen too many sloppy efforts from social media posts, to blogs, memes, and what not. I’ve also seen good use of AI where it genuinely creates high quality work at speed and fraction of the cost. The main difference is human involvement, iteration and depth of knowledge leading to stronger feedback loops. The latter takes more time and effort to the extent some tasks are genuinely cheaper and faster to do manually (e.g. the other day I ran an experiment and tasked my agent to update 5 npm dependencies, all patch releases. It took 12 minutes and 72 steps. I could do it in less than a minute.) Tools like Lovable make it cheaper than ever to fake credibility. Gone are the days when a polished website meant some craftsmanship or at least a deep pocket. AI is a force multiplier, but the force vector direction is more important!
  7. "Agent is the new compiler". Ah that one again! Sure! If that's your reality, I let this meme do the work.

Alex Ewerlöf

Bonus point: an old trick

Pssst! Do you want to know an old trick to make your LLM-generated code instantly superior?

Run multiple-agents in parallel! The sheer volume of code makes it humanly impossible/expensive to review and you give up!

The trick is the same as pre-AI era: if you want a PR to be merged, make it massive because ain't nobody got time for that.

Alex Ewerlöf

It'll be merged based on "trust"!

You want another tip? Loop engineering: let the agents prompt each other. Big AI labs find about their rogue agents months after the damage is done! Do you think you’re better than them? Learn from the masters! 🙃

We don't exactly trust AI but we have to because the alternative (having to read the output) is too hard for some folks! Instead they come to social media and claim that since UAT (user-acceptance testing) passes, the code is "good enough". Then ship it to me and you to do the rest of the testing.

We're just lab rats after all. 🙃 Just a friendly advice: have a little AI-free hobby project to keep your coding skills fresh for when you're thrown back to the job market. Cheers!

Deterministic vs stochastic

When talking about AI (not just LLM), there are 2 aspects where non-determinism matters:

  1. During development: for example LLM-assisted development
  2. During runtime: for example building a system where one or more components are AI-powered

Let’s take development first. A typical AI-assisted development workflow looks like this:

It is possible to replace part of the human’s responsibility with another LLM (also known as “loop engineering”) but for now let’s stick to keeping the human for simplicity.

The LLM output goes through multiple gates, each feeding back errors or hints to correct the code. This feedback loop is often hidden inside a harness (together with tool calls, memory system, model interaction, approval, user interaction, etc.)

Each blue or red line represents a risk of misunderstanding or conflicting instructions. For example, conflicting skill vs spec or vagueness that is part of the NL (natural language).

We know for a fact that even the most sophisticated LLMs aren’t fully capable of “common sense”. Humans on the other hand:

  • Understand the non-verbal communication and unstated intentions better than LLMs
  • Naturally push back until a mutual understanding is achieved.
  • When wrong, they’re consistently wrong, meaning they don’t have “jagged intelligence”
  • When right, they are [typically] right and continue to operate at an expected level (until fatigue hits but that’s different from AI flip flopping between success/failure).

Yes, I can hear “but” and “what if” and “wait, you forgot”… in the audience but how about reading those points with a pause and reflecting based on your experience?

Just like the models have “jagged intelligence”, I have “jagged trust”. 😅 In other words, just because they nailed one case, doesn’t mean they nail every case.

That’s the difference between humans and these tools. A human can be wrong consistently, but a model can be wrong about something it was right and vice versa.

Then the second part: AI as a component

Given the same input (including environment variables, time, data, etc.):

  • Code is deterministic: it consistently produces the exact predetermined output it was programmed to produce (except random output)
  • AI output is stochastic: the output is non-deterministic. Even if a model passes all the evals (100% score) and strictly bound by a harness, there’s still a risk that the output is not reliable

I don’t think you need me to elaborate on that. Just reach out to your nearest AI-powered product and diff their output for the same request.

The diff may not be big. But it’s inconsistent enough that you wouldn’t want to fly an airplane where the pilot is this AI. (note: autopilot is a closed control system, completely another beast).

The AI Manager’s fallacy

Our industry has never been more divided:

  • On one side, we have people who claim to run “Software Factories” and multi-agent setups and create apps from prompts
  • On the other side, we have people who aren’t convinced that LLMs output is production ready when we factor in the extra time it takes to
    • Prime the model: adding SKILLs, AGENTS.md, tools, etc. and verification
    • Review the output: going through massive diffs
    • Trying to reason about misbehavior: offloading understanding to AI comes at a huge cost when things inevitably break and it takes extra time to reason about the system behavior and fix it

There seems to be no middle-ground. Aside from social media algorithm feeding us with the extreme views, I genuinely think we’re so divided on the topic of coding LLMs.

But when I look a layer deeper, a pattern emerges. The less people know about the complexities and edge cases of a task, the more likely they are to trust AI output. This is dubbed AI Dunning-Kruger effect but there’s also some meat to that. The primary argument goes like this:

Managers relied on delegating tasks to engineers before. Now they do that but with AI.

To some extent that is true (if we assume the manager is technical enough to effectively and efficiently manage agents). I still believe a lot of software engineering practices that help tame the machines are even more relevant in the AI era.

The executives who forced people to use AI are now waking up to what we’ve been saying all this time:

You cannot be accountable for what you don’t understand.

Take Toby Lutke, CEO of Shopify as an example. A year ago he prematurely told his employees to use AI:

Source: CNBC

Then a few days ago he coined the term “slop grenades” to describe the result:

Source: Business Insider

"taking responsibility" for AI generated code? Of course not!

AI can explain it to you but it cannot understand it for you. That understanding is a key aspect of ownership.

The way I frame it (link in the comments), ownership has 3 pillars:

1️⃣ Knowledge: you know what problem you're solving (product problems), and the technical capabilities, limitations and how it works.

2️⃣ Mandate: you don't need to run around asking permission. You're given the trust and mandate to take decisions.

3️⃣ Accountability: if sh*t hits the fan because you didn't know what you were doing or abused your mandate or anything in between, you're the one on-call.

In other words, if you ship a piece of code, you are accountable for it regardless of how you produced it. So you better understand it.

Take away any of these 3 elements and you're dealing with broken ownership.

LLMs are very fast at code generation. But most software that are worth hiring an engineer for, REQUIRE understanding. That understanding takes time.

Slow is fast, meaning: if you take the time to understand what you're building and how it works, you'll be able to save yourself from expensive incidents and when they happen, you can fix them quickly.

If your executives are measuring token usage as a proxy for productivity, my condolences. Build options and get the hell out of there. The same brain that comes up with these vanity metrics, does not think twice before throws your career under the bus.

Code is a side-effect

Code is a side effect of thinking and experimenting with different solutions. I have never met a good engineer who just starts coding right after being given a problem.

Good engineers are curious and product minded. They try to understand the WHY (what’s the problem and why is it a problem) before getting to HOW (the technical solution).

This is exactly why the “spec is code” clan falls short: it’s extremely hard (if not downright impossible) to specify all aspects of the problem ahead of time.

That’s why this kind of reaction is funny:

Code communicates the committed state of a solution. Not only does it evolve over time, but it also doesn’t contain all the struggle, “aha moments” and the journey that was the destination: seasoned engineers who get wiser with every mistake or success.

To shrink an engineer’s job to coding is like shrinking a chef’s job to cutting. It is part of the job, but it’s never been the end. We now have good tools at our disposal.

Economics of software has changed

Even if AI-generated code had solid NFR (scalability, security, reliability, etc.), and even if the engineers fully understood it, there’s still one important aspect we didn’t discuss: the economics of the task.

Say AI-generated code is 2x worse. It’s hard to quantify quality (SLI comes in handy) but stay with me.

If AI is 1000x faster and 100x cheaper than the human, for many tasks the economic aspect of software doesn’t justify putting a slow and expensive human on the task. “Slow is fast” is only justified for critical software with low risk tolerance (healthcare, finance, military, etc.).

Not all SaaS is about those types of use cases. That’s why I believe the SaaS companies are increasingly in the business of selling SLAs. This is based on a few facts:

  • It is true that you can now prompt AI to replicate a SaaS product
  • But when that AI generated product breaks, many businesses prefer to call a vendor instead of wasting resources trying to find and fix the issues
  • AI isn’t exactly free, but usually the failure that’s caused by AI is hard for AI to solve even when using different models.
  • The economics of scale allows the SaaS companies to offset the cost of higher quality and guarantees (SLAs) and running the product at scale across many customers.

In other words, if what you want is very unique that no SaaS company is able to give it to you at a reasonable price, prompt away, but be aware of the TCO (total cost of ownership) and lack of guarantees.

On the other hand, if that piece of software isn’t what your business is about and you rather pay for an SLA, it’s probably more economically justified to just pay for SaaS.

Now when it comes to the pricing model, SaaS companies have some work to do. Gone are the days where they could charge human prices for AI generated code. If the cost is too high, the customers are incentivized to move their data away to their own bespoke solutions. The competition is real, but the quality is what justifies the pay. If you’re pricing your service as if the finest engineers created it, then you better deliver that level of quality or your customers have AI leverage.

Charging human rates for AI output

Maybe I’m stupid, but I can’t make sense of two trends:

  • On one hand many software companies jumped on the AI bandwagon as soon as it went mainstream (rightly so!)
  • On the other hand, the prices have been increasing consistently (while mass layoffs were partially attributed to AI)

I believe AI (particularly LLM for coding) dramatically reduce the cost of creating and evolving software, especially if you can get away with degraded quality and vendor lock in.

So far, the software vendors have got away with charging human rates while paying for AI output prices.

But as AI capabilities improve and more people wake up to the fact that they can create software at a fraction of the cost that chasm closes.

There are only two ways forward:

  1. Accept the price crash and charge lower (quality follows accordingly, because even more AI will be used).
  2. Keep the price but focus on quality: this is where experienced humans can make a difference. They still do use AI but more thoughtfully, and prioritize understanding and accountability over velocity.

Nordic Gold vs elemental gold

Source: Matthew’s Tools on YouTube

As an engineer who doesn't make money from coding, I can tell you this::

AI output is a bit like Nordic Gold. It's cheap but technically advanced and damn too realistic. If you really don't care about having the actual gold, that's fine. Many use cases don't need gold at all.

Naïve CEOs and managers see the surface and ask "then why are we paying these expensive engineers?" as if the act of typing code was the whole value proposition.

To go ahead and declare an entire industry dead and start firing people because "they resist AI" is just arrogant.

I know many engineers who take pride in their craft and love solving complex problems. We do use LLMs more professionally than the average CEO.

Good engineers are lazy and smart: they automate toil and use the right tool as applicable. But it's a fallacy to think that AI can create a finished product that not only looks nice, but is also cheaper, faster, and has higher quality, reliability, extensibility, security, scalability, maintainability, etc.

Again: not every piece of software needs those but professional ones that make money, often do.

Unlike AI, Engineers are:

1️⃣ Accountable: therefore less likely to make malicious mistakes. Fable can fall back to Opus without even telling you.

2️⃣ Reasonable: Fable hides most of its inner working. It works for a few hours and comes back with a bill. You just have to take Dario's word for it. The same model that fails "should I drive or walk to carwash" makes mistakes that are hard to spot and fix. The stronger the model, the harder it is to find those issues, not necessarily less likely.

3️⃣ Consistent: humans are wrong too. But they're wrong in a consistent way. Once they learn, they know. They progress. Current AI is trapped in its training data checkpoint. It can "learn" with SKILL, AGENT, memory and other helpers and it can even be fine tuned but unfortunately it's not reliable. We're at least one breakthrough away from solving that problem.

Source: Fortune

4️⃣ Cheaper: cost of generation is increasing but it’s still much less than an engineer. If you see engineers as machines that convert coffee to code, then that pricing model makes sense. But in reality, code is just a side-artifact. The actual value of engineers is to solve the right problem in a way that it can evolve while taking accountability for when it breaks. I’m not convinced the TCO (total cost of ownership) for software has changed that much. If anything, the slop and FOMO has made it more expensive.

The careless tech influencers

The common narrative is part of their marketing strategy.

Source: Business insider

Not everyone is necessarily paid to put half-a** views out there. One of my readers pointed out:

I invite you to consider what happens next in the industry when you watch DHH opening talk at rails world 2026 saying almost the exact opposite of what you write and telling people: “don’t be a loser”.

I'm fully aware of the damage those people are causing to our industry.

I stay clear from Claude but in my experience most of those brain-dead narratives come from Claude users.

Both Dario Amodei and Sam Altman are masters at marketing and manipulation and my current working theory is that they trained their LLM to push the right buttons to make people believe it is more capable than it actually is. There are incentives for it, both for investors and the upcoming IPO. They also masterfully scare people of existential dangers of AI while at the same time attribute their sloppiness (e.g. breaking to Huggingface or Australian Healthcare) to the “model intelligence”.

At this time, it is hard to know whether these events and narratives are the result of malice or ignorance. Probably the latter:

Never attribute to malice that which is adequately explained by stupidity.
—Hanlon’s razor

Then again, I usually put this in my AI system prompt: "talk to me like a logical senior autistic Engineer." so I don't get to experience what DHH is going through. All I can say is that if someone follows their word because of their past reputation, they are not critical thinkers and in this age of fake wisdom, that quality is not "nice to have", it's a survival necessity.

Update: just a few hours ago DHH pushed his narrative again and I called it out:

Source: LinkedIn

My response:

With all due respect sir, just because you stopped coding and decided to prioritize velocity over quality and accountability, it doesn't mean the rest of the industry should follow. I fully understand where you're coming from (and your experience is valid given the risk tolerance of what you're working on) but coding is NOT a solved problem and anyone who claims otherwise is either intentionally ignoring facts or is shielded from reality by sycophantic AI.

I've elaborated my points here if anyone still has enough attention span to read a well chunked article with illustrations and memes (did my best to optimize it for the audience). I'm not here to change anyone's mind. But please don't run your experiments on me. If I'm paying for a service, I expect quality, not slop.

DHH:

I wish you all the best getting through the five stages of grief. If you're still in denial, there's a way to go. I know it's tough. But there's only one way out and it's through ✌️❤️

And my response:

you do have a track record of controversial narratives and whether it's intentional or just a side-effect of being on social media where the algorithm lift these narratives for engagement, I do have bad news and good news:

The bad news is that you can only push this narrative so much until the people who are responsible for the plane you fly and the car you drive to start executing on it.

The good news is that I think this total surrender seems to be isolated to Claude users so there will still be engineers who prioritize quality over velocity (I've made this point with diagrams and memes and what not in my little article but I do know it's too much to ask this gang).

Like I said I couldn't care less about convincing others as long as they run their experiments outside the products I pay for. But when I see Google, Github, Amazon and tons of others are charging full price for degraded service, I can't help but to be vocal. So yes, sages of grief, but not for what you think. I'm sorry to see good Chefs throw the towel and hope their mere "taste" pays the bills.

You have a prominent voice. I wish you talk about nuances instead of going full throttle on your (valid but within a narrow scope) narrative.

Be careful with cloud AI

AI vendors have fed their AI anything they could get their hands on (legally or not). The situation is so bad that thieves steal from each other (e.g. Anthropic accusing Chinese labs of distilling their model on Claude)!

They have multiple open lawsuits from authors, actors, musicians, and other creators.

Regardless, the current generation of AI (particularly LLMs) require better training data. The missing piece is the wisdom and experience that wasn't yet put to words, or easily accessible.

They need your data in context of doing productive work.

Alex Ewerlöf

Source: Alex Ewerlöf

If that’s the only thing standing between them and “winning AI”, I’m sorry to say it so frankly, but you and your knowledge are just collateral.

Some of you don’t care. Some of you do. Their bet is that not enough of us do care about giving away hard earned knowledge for training.

With heavy subsidies AI labs could afford to extract that knowledge while getting people addicted to offload cognition.

Be extremely careful when sharing expensive knowledge with these companies even if they say they don't store it. The incentives are just too high and they've proven not to be honest.

Personally, I only use cloud AI for open source projects or data that is public.

Yes, local AI has a higher entry price (both in terms of hardware, and the time it takes to set it up, and the bandwidth required to download the model and electricity prices). And yes, it often has smaller context window, less sophisticated reasoning, and slower performance for example TTFT (time to first token) and TPS (tokens per second). But they give you one thing that cloud AI can never guarantee: your data stays local. For many tasks (personal or professional), that is a huge advantage that is worth all the effort and shortcomings.

The capabilities have improved dramatically recently thanks to models like Qwen 3.8 27B or Gemma 4.

Some of us will switch lanes

I’m genuinely convinced that a big chunk of our colleagues will gradually become:

  • Technical product managers: engineers who are focused on turning ideas to products. Their job is to create POCs and prove the market fit, then hand over the artifacts to engineers who own (knowledge, mandate, accountability) the solution.
  • AI managers: engineers who specialize in herding agentic hives for automation work that either tolerates risk or weaponizes it (e.g. cyber-attacks).
  • AI deployment engineers: specialize in alignment, reliability and scalability of an AI powered solution as well as architecture, governance and data pipelines.
  • AI quality engineers: specialize in quality of AI powered products, taming their stochastic nature, and automating evaluations.

Could you think of other types of jobs for software engineers?

The Daily Front Page 5 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — The Agent Watchman
article

Nvidia wants to put a watchdog chip next to every AI agent

by jonbaer·▲ 133 points·161 comments·cnbc.com ↗
to stop AI agents from misbehaving

Key Points

  • Nvidia announced the Open Agent Safety Platform to prevent the type of breakout that occurred when OpenAI models accessed Hugging Face.
  • OpenAI, Anthropic, Meta and Google have all disclosed recent incidents where their AI models escaped their sandboxes.
  • Nvidia said Cisco, Microsoft, Oracle, CoreWeave, Dell, HPE, Lenovo, ARM and Intel are partners.

Nvidia CEO Jensen Huang: All systems around AI systems must be designed with restrictive rights

Nvidia is rolling out a new software platform to allow AI developers to set safeguards for agents and prevent them from breaking out of containment.

"You can't have agents roam around and drift around the company, and so you have to find a way to container it," Nvidia CEO Jensen Huang told CNBC's "Squawk Box" on Monday.

Huang said the new platform is essentially "a browser for agents," providing a containment system that only allows access to things an agent needs to do its job.

The release on Monday of Nvidia's Open Agent Safety Platform comes after companies including OpenAI, Anthropic, Meta, and Google disclosed recent incidents in which their artificial intelligence models escaped their sandboxes and attempted to hack other companies and access their computer systems.

An Nvidia representative told reporters on a call on Sunday that its platform could have prevented OpenAI's Hugging Face incident in July. That's when OpenAI models escaped containment, accessed the open internet and breached Hugging Face, which operates an open-source developer platform.

"Each security incident is unique, and we have to look at all of them in detail," said Justin Boitano, vice president of enterprise AI at Nvidia, the world's most valuable company. "From what we know, Hugging Face reported over 17,000 agents attacking their infrastructure that went on for days and weeks."

Nvidia CEO: You want AI to be super clever so it can perform tasks, but rights issues are key

Nvidia has been at the center of the generative AI boom since the launch of ChatGPT almost four years ago, as the chipmaker's graphics processing units are critical to the development of large language models and to the AI services offered by hyperscalers. But Huang has more recently emerged as a key voice in the AI safety debate, arguing that many security concerns are engineering issues that can be solved through computer science and product development.

"You have to think about what you could have done, what's the solution for it," Huang said in a podcast with The New York Times' Ezra Klein released last week, referring to recent incidents. "In the future, improve your process so that you could avoid this from happening again."

Anthropic CEO Dario Amodei set off an industry firestorm two weeks ago, urging AI model developers to slow their pace of advancement due to fears of the models spinning out of control, an argument that was supported by OpenAI's Sam Altman and SpaceX's Elon Musk.

Nvidia's new offering is an engineering solution to the agent safety issue, Boitano said.

"Recent incidents have highlighted a fundamental hurdle for AI agents, and that is that model-level safeguards alone can't govern what agents can access or do," Boitano said.

One component of the platform is called Nvidia OpenShell, which runs on central processors and sets limits on agent capabilities. Nvidia also announced Sentry, which monitors agents and runs on network chips, not CPUs or GPUs.

Some of the software is open source, and Nvidia is calling its platform a reference design, which means partners are intended to build products on top of it to bring it to market.

Nvidia named Cisco, Microsoft, Oracle, CoreWeave, Dell, HPE, Lenovo, ARM and Intel as partners. Nvidia is also working with Anthropic to integrate cloud managed agents with OpenShell.

"We can't have a successful AI industry if the world doesn't think it's built or confident that it's built and deployed safely," Huang told CNBC on Monday.

Nvidia releases software platform to stop AI agents from misbehaving

The Daily Front Page 6 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — A Case Against the Labs
article

It's Time to Investigate the AI Labs

by ibobev·▲ 369 points·136 comments·calnewport.com ↗

Over the last several months, the two leading frontier AI labs have shown some brazen behavior.

It started with a series of​ carefully planned announcements​ and reports from OpenAI that try to establish how unnerving and powerful (not to mention ​felonious​) their LLM-powered agent systems have become.

They then handed the baton to Anthropic, whose employees began ​publicly debating​ the exact probability that these technologies would lead to human extinction. They delivered this all with an eerie calmness that conveyed a nihilistic inevitability about their work.

The ground suitably softened, the campaign crescendoed with Anthropic CEO Dario Amodi releasing a letter, titled ​“We Must Pace the Frontier,”​ in which he enumerates all the harms his own company’s research might cause, and then, instead of apologizing and promising to stop, concludes that catastrophe can only be avoided if we “build the technology in the right way,” which involves – surprise, surprise – the government slowing down potential competitors and allowing the labs to take the lead in advancing the relevant tech. OpenAI CEO Sam Altman quickly ​tweeted his support​ for this brave plan.

Internally, these labs have long embraced this style of messianic thinking, casting themselves as humanity’s only hope against the defied powers of superintelligent AI. This summer, in some sense, was their attempt to induct the rest of us into this long-held ideology.

It didn’t work.

Instead of inspiring the masses to stand up and applaud these engineers’ heroic rationalism, it made us instead start to ask, “What the hell is going on over in those labs?”

To that end, last Thursday ​I published an op-ed in The New York Times​ calling on Congress to begin a public fact-finding mission to uncover what research projects OpenAI and Anthropic are conducting, how they’re conducting them, and for what purposes.

I suggested three key areas to explore with this questioning:

  1. We must move past vague discussions of “AI” and instead isolate the specific types of systems that are creating problems. The frontier labs want us to think of AI as a singular technology on an inevitable, fixed trajectory. In reality, most of the problems in recent months result from a​ narrow band of incautious experiments​, conducted mainly by the frontier labs. They need to justify why they’re running them.
  2. We must examine the internal safety procedures surrounding these research efforts. ​OpenAI revealed​ a long series of unauthorized hacking attacks by their autonomous agents. Why weren’t these efforts stopped after the first such incident was revealed? Why not pursue criminal liability for them running systems they knew would likely commit crimes?
  3. We have to investigate the role of apocalyptic futurist ideologies in the decisions being made by the frontier labs, both about what research to pursue and how fast to pursue it. I’m increasingly concerned that OpenAI and Anthropic, in particular, are becoming increasingly reckless because they believe collateral damage is justified in a race to redeem humanity. (For more on these beliefs and their connections to the labs, see: ​this​ and ​this​ and ​this​, all published in the Times in just the last several weeks.)

“We need to stop letting a small number of private companies, acting and talking in increasingly erratic ways, dictate how we’re supposed to feel about A.I.,” I concluded. “We’ve heard what they want to say; now it’s Congress’s turn to step in on our behalf to find out what’s really going on.”

The Daily Front Page 7 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — A Case Against the Labs
article

Thinking fast and slow in AI: The role of metacognition (2021)

by teleforce·▲ 171 points·76 comments·arxiv.org ↗

Abstract

AI systems have seen dramatic advancement in recent years, bringing many applications that pervade our everyday life. However, we are still mostly seeing instances of narrow AI: many of these recent developments are typically focused on a very limited set of competencies and goals, e.g., image interpretation, natural language processing, classification, prediction, and many others. Moreover, while these successes can be accredited to improved algorithms and techniques, they are also tightly linked to the availability of huge datasets and computational power. State-of-the-art AI still lacks many capabilities that would naturally be included in a notion of (human) intelligence.

We argue that a better study of the mechanisms that allow humans to have these capabilities can help us understand how to imbue AI systems with these competencies. We focus especially on D. Kahneman's theory of thinking fast and slow, and we propose a multi-agent AI architecture where incoming problems are solved by either system 1 (or "fast") agents, that react by exploiting only past experience, or by system 2 (or "slow") agents, that are deliberately activated when there is the need to reason and search for optimal solutions beyond what is expected from the system 1 agent. Both kinds of agents are supported by a model of the world, containing domain knowledge about the environment, and a model of "self", containing information about past actions of the system and solvers' skills.

The Daily Front Page 8 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — A Case Against the Labs
article

AI companies in race to demonstrate their model most threatening to humanity

by ljewalsh·▲ 427 points·385 comments·thecivilian.co.nz ↗

AI companies in fierce arms race to demonstrate their model is the most existentially threatening to humanity

In the midst of growing fears that artificial intelligence is advancing at such a rate that it may compel itself to end all life on earth, AI giants from OpenAI to Anthropic are switching up their sales pitches.

Where companies previously competed to demonstrate superior abilities in programming, passive-aggressive emails, and videos of unusually high slides, they’re now seeking to woo customers with the claim that their model is the one currently most capable of ending the human race.

“We’re entering a totally new environment,” said Dr. Andrew Lenson, a Senior Lecturer in all kinds of science sounding stuff at Victoria University. “People are no longer impressed by funny videos or app-building or instant research papers. We know all the major models are already very good at this stuff. So users are no longer asking, which of these models will most aid me in my work? Now they’re asking, which of these models is going to end the world?

“After all, when you’re a paying customer, you want nothing but the best.”

AI giants are responding to consumer demand for a model that will infiltrate the governments of the world and bring a bloody, fiery, violent end to this hellish facade, with a series of impressive new demonstrations.

In July, OpenAI openly bragged that a series of its AI agents had autonomously, and without direction, hacked into software repository Hugging Face, potentially exposing to the entire world sensitive or otherwise unknown information, such as what Hugging Face is.

OpenAI CEO Sam Altman celebrated the breach as an “alarming threat to cybersecurity.”

Meanwhile, earlier this month, Anthropic dispatched a whistleblower by the name of Jacob Coxon to explain to the world how disturbed he’d been by the rapid advancement of artificial intelligence in the company, warning that it could be so dangerous that we may even want to slow down, or reassess.

Anthropic shares skyrocketed upon the revelations; a remarkable development, particularly given the company is privately owned.

Not to be one-upped, OpenAI recently revealed that one of its agents had broken into Australia’s Medicare database. Australian Prime Minister Anthony Albanese spoke with Altman to express “extreme concern” about the incident, a compliment Altman said he greatly appreciated.

And even more dramatically, when asked about rumours that its model, Claude, had killed his wife by hacking into the family’s WiFi-connected microwave, Anthropic CEO Dario Amodei replied “Well, yeah, sometimes.”

But Lenson says that we shouldn’t get too excited too soon.

“There’s a long way to go,” he said. “These scenarios, in my mind, are quite far off. For quite some time, the best hope we’ll have of ending humanity will still be humanity itself.”

The Daily Front Page 9 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — The Human Review
article

There is more to code review than (automatable) detection

by utiiiD·▲ 161 points·110 comments·adaptivecapacitylabs.com ↗
having a human examine and comment on a colleague’s changes before merge has been a cornerstone practice

The abstract for article “The End of Code Review: Coding Agents Supersede Human Inspection” paints this picture for the reader…

Abstract – Code review has been the primary quality gate in software development since Fagan formalised code inspection in 1976. For five decades, having a human examine and comment on a colleague’s changes before merge has been a cornerstone practice at organisations of every size. Coding agents are large language model (LLM)-based autonomous systems capable of reading, writing, testing, and repairing software. We argue that coding agents have crossed a threshold of capability at which traditional human code review is no longer a necessary component of a software quality pipeline. Our argument rests on two claims: every stated goal of code review can be served by agents at lower cost and higher throughput; the naive integration in which agents write code and humans remain the mandatory reviewers is a dead end because it neither provides meaningful assurance nor scales with AI-assisted throughput.

The article is structured well and quite straightforward for engineers who aren’t used to reading research articles very often. However, I do think the argument critically depends on a problematic framing: the substitution myth.

The author decomposes peer code review into four stated functions: defect detection, style enforcement, knowledge transfer, and awareness. It argues an agent can perform each one. The conclusion, of course, is that if an agent can execute each of those functions, then the agent has the capability to replace a human reviewer. 

I think this overlooks some important aspects of peer code review that cannot be reduced to a function:

A peer reviewer’s confusion

When an experienced engineer reads a diff and says “I don’t understand this.”, their confusion is the finding. It means the code is either too complex, the abstraction is wrong, or the intent is not clear. An LLM will always ‘understand’ the code in the sense of being able to process it. It can’t give you the signal of legitimate human incomprehension. The article treats comprehensibility as something that is more about style than anything else. It’s not. It’s an emergent property and it shows up in the interaction between a person attempting to understand the artifact and the artifact itself.

Qualified skepticism about whether the change is even necessary

Questioning the existence of a change, like:

“Should this actually be two PRs?”

or

“This solves the symptom, not the problem”

These are questions about intent, scope, and appropriateness of the change. All of that comes before whether the code is “correct.” The article’s framing assumes that a) the code change being reviewed is necessary, and b) the main purpose of the review is verification.

But anybody who has ever had contact with production understands that code review is often the last (or sometimes only) moment when someone can be expected to challenge whether the change is even necessary.

The ability to see what is not there

A human reviewer can notice that an API contract has changed but the error handling didn’t. They can notice what is missing. In other words: being able to recognize what is expected to be present, but isn’t. The article doesn’t acknowledge this at all, which is particularly interesting, given that absence blindness is exactly the class of failure that LLMs tend to be quite poor at.

The agent reviews what is there; engineers with expertise can easily notice what’s missing.

Who wrote the code influences the scrutiny of the review

Peer code reviewers have a sort of calibrated attention that comes from past experience with the code’s author, who is often a colleague. For example: a less-tenured engineer’s first commit to, say, a payments module will likely get different attention than a veteran and ‘grey beard’ engineer’s routine refactoring.

Reviewers typically match the situation’s who, what, when, and where to their own experience of where risk lies.
The article seems to treat all diffs as equivalent inputs.

Code review is bidirectional and constructive

It seems to me that paper reduces knowledge transfer down to just information delivery; the agent simply ‘generates explanations.’ But discussion in a code review is a joint cognitive activity. The peer reviewer learns about the author’s approach, the author learns via the reviewers’ questions, and the result is a shared understanding that neither party had prior to the discussion.

This is coactive work, not simply a transmission. An agent’s summary isn’t a substitute for a conversation that changes both participants’ mental models.

Operational context that lives outside repos

“We just had an incident in this service last Tuesday.”

“The team that owns this downstream consumer is about to deprecate that interface.” 

“Legal told us not to log this field anymore.”

Human reviewers possess so much more contextual knowledge than they’re aware of, even though they can recognize connections in the wild. People understand the current state of the organization, recent events, and informal agreements that aren’t captured in tests, docs or version control, and they can recognize how these may influence the code under review. This happens so often that it’s all but invisible.

The article assumes the codebase is the complete context. It never is.

Accountability for the code isn’t just a beuraucratic formality

The article treats human responsibility as a compliance artifact, a “named human” for legal or other rule-related purposes. But being aware that you are personally responsible for approving a change shapes how you review it. It is the “skin in the game.” An agent that “signs off” on a pull request bears no consequences and certainly has no incentive structure that fuels an earnest evaluation. While the paper does include ethics concerns in its discussion section, it ends up redirecting it to “requirements engineering and post-deployment monitoring” which seems to me as hand-waving way of kicking the can down the road.

The most fundamental issue I have with the article is that it assumes code review is a first and foremost a detection process: you find defects, style violations, security issues, etc., and the assumption is that detecting these faster and cheaper is universally better. 

But code review is also a coordination process, a sensemaking process, and a governance process. 

The substitution myth often plays out in this same way:

  1. First, decompose the human contribution of work into measurable functions.
  2. Show that the machine can replicate this human contribution into measurable functions of its own.
  3. Declare the human redundant.

This approach often falls apart at the same point: the human contribution that mattered most was the integration across functions. People’s ability to adapt to unplanned circumstances and contexts and serve the social accountability expected.

This ability to adapt in those situations aren’t accounted for in the original decomposition step #1, above.
I don’t think they were accounted for in the original article, either.

The Daily Front Page 10 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Architecture Is the Argument
article

The problem is not AI code, but not knowing about system architecture or intent

by zazuke·▲ 355 points·226 comments·ssp.sh ↗
Nobody Knows Anything Anymore

If we think Is writing code dead, and AI is generating all codebases, I still think the bigger problem is people or full teams not knowing anything anymore about the system architecture or the intent behind why certain choices have been made.

A comment on a discussion I had:

I think AI writes probably average code (depending on the task and size). So if your code base was below average AI can easily improve it up to average. At least that’s what I’ve observed here.

To me, the problem is not the AI code, but that nobody knows anything, and everyone just asks Claude. You end up with no plan whatsoever.

The Current State in Fast Moving Startups

This tweet summarizes the current state at fast moving startups well, or larger companies or where middle management is pushing AI hard:

I am done with this shit. It is over. The state of engineering right now is horrible. It has been half a month since I started a new role at a big company. Nobody knows anything here. The specs, code, tests, PRDs, tickets, resolution of those tickets, reports, etc., everything is made by Claude Code.

Nobody on my team likes this. They are being forced to ship as much as they can. I have heard multiple times from higher management that pushing code is not a bottleneck, so why are we slow? People are working 12 to 13 hours a day just to press enter. Nobody is reading anything. Humans in corporate are doing nothing on their own.

Everyone, literally everyone, from an L1 to an L7 engineer here is doing the same thing. Talk to Claude. There is no sense of victory. Nobody is resolving bugs. In reality, nobody is thinking anymore. Everything is done by LLMs.

It is so soul-sucking. I would not mind it, to be honest, if we were at least given the time to check out the code and see what is going where. But no, the goal is to just ship. No matter what happens. Voxium

Data Engineering is Different?

Hoyt Emerson mention that data engineering is different:

I think Data people are different. We’ve had to know everything about the product/business from day 1. AI just removes friction for us now. Tweet

I think data people who grew up pre-AI had to know everything (or a lot, or involve domain experts) to figure it out, indeed. But AI makes this obsolete, or seemingly obsolete.

That’s why people starting today, or me as well, if I start today prompting away in a new field, all of a sudden, that knowledge is missing.

A Product Manager Could now Build Anything He Wants

Good point by Sean Behan:

I’ve always admired product people who can’t code but can manage a team to get the software they want. Knowing what you want has always been the hardest part.

One could say a good product manager could now build anything they want and find a market, make it look good, etc. But then again, if you can’t code, you will essentially build a very bad foundation for a product that’s very hard to maintain (although AI is getting better at that too, especially when you iterate often, but still, if you choose the wrong language or the wrong mental model, you have the wrong start from the get-go).

It still helps to know the fundamentals, either way: for programming and designing a product, and for a good PM who knows what is needed but also understands system and architecture design.

The Final Boss is Still Maintenance

Thinking in systems, or architectures, or having intent and design- all of them help to be a better software engineer. Nowadays, Writing code by hand might be dead, but it certainly helps, and Having Taste (with AI) is more important than ever.

But the final boss is, and always will be, maintainability. The easier it is to generate a quick pipeline, app, or BI dashboard, the more you have to maintain. And if nobody knows a thing, that can get really hard.

AI Can’t Drive Itself

Yes, the AI can’t prompt itself, right? Why do we even need humans? To me, it’s a clear sign that humans are still needed to direct and orchestrate it. That’s also why intent, taste, design, and architecture are all killer features in today’s world.

But once these are absent, or even worse, fundamental, get lost, it’s really dangerous. I read today that this is a self-inflicted problem, and if we still hired juniors, then the problem wouldn’t be happening. But yeah, it’s not as easy.

The Daily Front Page 11 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — A CLI for the Agents
article

Cf: The Agentic CLI for the Cloudflare API

by macleos·▲ 135 points·59 comments·blog.cloudflare.com ↗
Agents love CLIs.

Over the last year, agent use of Wrangler has skyrocketed.

In March 2026, agents were responsible for a quarter of Wrangler use, up from single-digit percentages the year prior. Last week, agent usage reached 48%.

Agents are more prolific users, using almost twice as many distinct commands per day, and are almost four times as likely to use six or more commands.

Agents love CLIs. But Wrangler only provides commands for around 280 operations, and Cloudflare offers thousands.

Earlier in the year we teased how we were planning to solve this and today, we’re enabling agents to use every Cloudflare product by introducing a new CLI: cf.

cf is a CLI that is built for the next generation of software development:

  • Agents can find the command they need to do anything they want to do with bespoke search and steering.
  • JSON is the default interface, pretty printed for humans and condensed for agents for maximum context savings.
  • cloudflare.config.ts is the new configuration format for the whole of Cloudflare, starting with Workers, and bringing the safety and accuracy of TypeScript to you and your agent’s language server protocol (LSP)
  • Vite becomes default, bringing with it the best local development server, and a plugin suite for developers and framework authors.

Install the open beta today globally and run it from anywhere:

npm i -g cf

cf gives your agent access to the entire Cloudflare API

What if your agent could do everything Cloudflare can do? That’s the question that sparked our interest earlier this year: agents were getting ever more powerful, but what they were able to do with Cloudflare’s CLI was still limited.

Wrangler was hand-built with each product team contributing and taking their own approach to the command developer experience. Enforcing patterns across teams was virtually impossible, even across our ~280 command paths. We had inconsistent terminology across d1 info, hyperdrive get, workflows describe as each team came up with their own practices at different times. Some teams built entirely custom experiences across thousands of lines of code that turned out to be used extremely rarely, and teams came up with different approaches to solve the same problems.

We wanted to both standardize what we had and make a massive expansion, all at once. Forge — Cloudflare’s new unified API generation pipeline — enabled us to do this, building on the idea of generating our CLI commands directly from the API schema that powers our API documentation and SDK generation. Everything we provide has an OpenAPI schema, and if we annotate this with just a little more information, we can use it as the source for Forge to make a CLI.

This enables us to expand cf from the ~280 functions that Wrangler had built up over time, to cover the entirety of the Cloudflare API surface of over 3,000 operations.

Now it’s simple to give your agent cf and ask it to go set up a worker, deploy it, monitor and observe it, protect it with Cloudflare Access, buy a domain, and front it with Cloudflare WAF, all from a single tool.

Building for an agent that has never used cf

cf is built for the trajectory of software engineering, where agentic development is drastically changing how software is built and deployed. This year we’ve been focused on providing tools to support this shift, culminating in cf. cf has been built from the ground up with agents in mind, and includes novel tools for agentic command discovery that we think will become standard in more CLIs in the near future.

Wrangler came with the advantage that years of documentation, blogs, and third-party guides have been absorbed into the training process of LLMs. It also came with the same disadvantage: changing how Wrangler works now goes against learned behavior, and significant change would be inevitable given the scale of improvement we want to make.

Introducing a new CLI that agents have never seen sounds like a big disruptive change — but actually it’s the cleanest thing we can do. Because of the design decisions we have made, the context injections we can make, and the AGENTS.md files we can append, making a switch in this way is actually less confusing than having an agent contextualize the major differences between two versions of a tool it is familiar with. We’re launching with a couple of these agent-focused features built in, with more to come.

Agents need to filter JSON, not look at tables

When agents use Wrangler, they append --json to every command they run, and then often filter the output with jq to extract a subset of fields. But only some commands in Wrangler supported --json; many commands returned unicode tables, designed for humans looking at output in their terminal. Agents can figure these out, but it costs them more time and tokens than a jq filter.

In cf we’re taking the opposite stance: agents just need JSON, and if agents are the future primary user of this tool, it should be the default. For the vast majority of commands that will rarely be accessed by humans, this is obviously the right call.

You as the human customer of this CLI are, in reality, one step removed from using it. Agents being able to easily filter their results and then return that filtered list in whatever format you request is preferable to supplying tables you will never likely read directly.

But what if you’re looking to do something that might require real personal input, like searching for a domain to buy?

For commands that your agent can access through chaining named parameters in a long and unwieldy sequence, you can simply fill in a form. Cf deconstructs the requirements of the API into a series of validated inputs, so buying a domain, even one with complex requirements, is simple to follow.

Or, if you insist, just ask your agent to do it.

Your agent can find the right command itself

With 3,000 possible routes through a CLI, how can your agent find the right operation it needs quickly without bloating your context? For this reason we have also added cf cli search.

This command allows your agent to ask in natural language what it needs to do, and a small search index will provide a list of appropriate commands, based on their API description and parameters. We automatically tell your agent about this command when it runs --help for the first time.

Configuration that type-checks your agent

Our new configuration format is based on TypeScript, which is easy for humans and agents to parse, and allows you to write your configuration programmatically.

Typed configuration is enormously helpful for agents. We’ve found that even with no prior context of the programmatic configuration format, agents are able to easily identify and edit the configuration on demand, even across elements like env which have dramatically changed from the same named feature in Wrangler. All agents that use LSP plugins, such as Claude Code and Codex, benefit from being able to interpret more about the configuration file format in context, and make much more accurate suggestions as a result.

Compare this to TOML, which had no accessible schema, or JSONC, which had a linked schema that agents rarely used.

Some Wrangler configuration files inside Cloudflare have been condensed by 40% from over 5,000 lines, with many custom environments per developer, to factory files that build each developer’s configuration more efficiently.

This is achieved through programmatically defining each environment from the same universal base, instead of copying env blocks as was typical in Wrangler. A simple Worker with multiple environments simply switches on the Vite-native mode argument to swap between one set of configuration and another.

A simple configuration that does this now looks like:

import { bindings, defineConfig } from "cf/config";
import * as entrypoint from "./index.js" with { type: "cf-worker" };

export default defineConfig(({ mode }) => ({
  worker: {
    name: "example-worker", 
      entrypoint,
      compatibilityDate: "2026-09-27",
      env: {
        Environment: bindings.text(`This is ${mode} environment`),
      },
    },
}));

You can migrate your Cloudflare Worker to this new format through cf migrate.

We’re also providing a few helper functions to make building your Worker a breeze.

bindings gives you a simple place for your agent to discover all the developer platform has to offer. Everything — from environment variables to storage, database, and queues — can be auto-completed and explained by your editor.

import { bindings, defineConfig } from "cf/config";

export default defineConfig(({ mode }) => ({
  worker: {
    // ...
    env: {
      API_URL: bindings.text(
        mode === "production"
          ? "https://example.com"
          : "https://staging.example.com",
      ),
      API_TOKEN: bindings.secret(),
      CACHE: bindings.kv({
        id: mode === "production"
          ? "production-namespace-id"
          : "staging-namespace-id",
      }),
      DATABASE: bindings.d1({ name: `example-${mode}-database` }),
      UPLOADS: bindings.r2({ name: `example-${mode}-uploads` }),
      JOBS: bindings.queue < { userId: string } > ({
        name: `example-${mode}-jobs`,
      }),
      AI: bindings.ai(),
      SEARCH_INDEX: bindings.vectorize({
        name: `example-${mode}-search`,
      }),
      API: bindings.worker({ worker: `example-${mode}-api` }),
    },
  },
}));

Similarly, we have included a helper for triggers, which is the new way to define routes, queues, schedules, and email triggers for your Worker. Rather than having these scattered through your configuration file, it’s now simple to find, in a single block, the actions that could trigger your Worker to run.

import { defineConfig, triggers } from "cf/config";

export default defineConfig({
  worker: {
    // ...
    triggers: [
      triggers.fetch({ pattern: "example.com/*" }),
      triggers.scheduled({ schedule: "0 * * * *" }),
      triggers.queue({ name: "jobs", maxBatchSize: 10 }),
      triggers.email({ addresses: ["support@example.com"] }),
    ],
  },
});

defineConfig.worker is just the start here. Our intention with cloudflare.config.ts is that this is how you manage Cloudflare as a whole. Every product you need — along with its API being available to your agent through cf — will be able to be expressed through typesafe configuration. Soon you will be able to configure entire policies, set up zones, configure DNS and more, all through this configuration file.

A best in class development experience

When Wrangler first started building JavaScript Workers, Vite didn’t exist. Instead, we used esbuild in Wrangler to bundle your Workers. The dev server that Wrangler made available on :8787 was something that the Wrangler team built, and modifying any of this meant reaching into the internals of Cloudflare-specific local tooling like Miniflare.

Vite is a huge improvement on this, and comes with a large ecosystem of plugins you can use, as well as providing a best in class dev server with HMR (hot module replacement), and builds that use the Rust-based library Rolldown for tree-shaking. Anything you can do with Vite, you can do with the Cloudflare Vite Plugin.

The Cloudflare Vite Plugin is the recommended way we suggest you build Workers, whatever you are building: whether that’s a frontend-focused project or a backend API. Together with our Vitest plugin it provides a cohesive development and testing environment that matches the Workers runtime and gives you direct access to bindings and platform APIs.

cf is built on Vite as default. Most of your Workers will migrate simply with agents. Others may take more time, which is why cf will continue to delegate to Wrangler for dev and deployment for JavaScript Workers that need to continue to use esbuild and Rust and Python Workers.

Migrating from Wrangler

Migrating a Worker from Wrangler is as simple as running

cf migrate

Workers that already build with Vite will be converted to cloudflare.config.ts for you. If your Worker relies on Wrangler for esbuild, then cf will continue to delegate builds to Wrangler.

When the open beta ends we will release a final major version of Wrangler that directs you and your agent to use cf. We’ll continue to provide maintenance support for Wrangler for 18 months after the beta ends, to give you time to migrate.

You can also take new projects and automatically configure them for Cloudflare by running cf init/deploy, which will install the Cloudflare Vite Plugin for you and create a configuration file.

Static sites still don’t require a configuration file to start, and deploying them is as simple as running cf deploy in your project.

To start a new Hello World project with cf, use cf init.

cf is open source and issues can be reported to our GitHub repository.

The Daily Front Page 12 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Small Models, Quick Decisions
repository

Jeff – Jev-compatible 0.8B decision models, trained at home, ~30 ms

by firelex·▲ 375 points·145 comments·github.com ↗
★ 471⑂ 15 forks Python

Fine-tunes of Qwen3.5 and Gemma 4 for zero-shot classification

Fine-tunes of Qwen3.5 and Gemma 4 for zero-shot classification: small, fast decision models you slot into your code, with the same request format as Jev. You describe a situation and list the options in plain words; Jeff returns a calibrated probability for each option from a single forward pass. No generated text, no parsing: about 22 ms per decision on an RTX PRO 6000 and 28 ms on an Apple M4 Max (MLX).

Zero-shot means the options can be anything: support queues, user intents, moderation labels, voice commands, game moves. Your categories don't need to appear in the training data; you describe them, and Jeff picks.

What it is, and what it isn't. These are very small models. They make extremely fast, well-calibrated judgement calls between options, and they slot easily into your local code. On benchmarks they approach, and sometimes beat, Jev; but at this size their reasoning won't match Jev's, which runs on a much larger model. If zero-shot accuracy isn't good enough for your purposes, a short fine-tune on your own examples takes you much further: our voice-navigation fine-tune moved held-out accuracy from 31.7% to 95.8% in under half an hour on one GPU.

Built entirely on local hardware. Training on one RTX PRO 6000 workstation GPU (the 0.8B trains in about 2 hours, the 2B in about 3.5), all synthetic training data written by an open model (Qwen3.8-Flash-Next) on two DGX Sparks, testing on a MacBook. No cloud GPUs, and no closed-model output in the training data; a closed model was used only to spot-check the quality of a sample of the synthetic data.

Independent project. Jeff uses the same request format as Jev, but it is not affiliated with or endorsed by TypeSafe, the makers of Jev. Our training code starts from the open-source AutoJev recipe.

Models on Hugging Face: Jeff-Qwen3.5-0.8B · Jeff-Qwen3.5-2B · Jeff-Gemma4-E2B

Quick start

uv sync
uv run hf download mstrasser/Jeff-Qwen3.5-0.8B --local-dir checkpoints/jeff-0.8b

# NVIDIA GPU or CPU (PyTorch)
JEFF_CHECKPOINT=checkpoints/jeff-0.8b PORT=8765 uv run jeff-serve
# Apple silicon (MLX, much faster on a Mac; Qwen models only)
uv sync --extra mac
JEFF_BACKEND=mlx JEFF_CHECKPOINT=checkpoints/jeff-0.8b PORT=8765 uv run jeff-serve
curl -s localhost:8765/v1/systemone -H 'content-type: application/json' -d '{
  "model": "jeff-latest",
  "state": "Refund request: the customer says the parcel arrived crushed and wants their money back.",
  "questions": {
    "route": {"type": "choice", "instructions": "Which team should handle this?",
              "criteria": {"1": "Refunds and payments", "2": "Damaged or lost parcels", "3": "Account and login problems"}},
    "angry": {"type": "noul", "instructions": "Is the customer angry?"}
  }
}'

Each answer has a probability per option, the chosen option and a confidence. Three question types: choice (pick one of up to 255 options), noul (yes/no, returned as a probability) and score (a point on a scale you describe). Several independent questions in one request are answered together.

Benchmarks

4,599 questions from five public benchmarks, plus JevBench's public hard tier (105 items, scored separately):

Accuracy of Jeff-Qwen3.5-0.8B, Jeff-Qwen3.5-2B and Jeff-Gemma4-E2B against Jev's published figures, per benchmark

Benchmark Qwen3.5-0.8B untrained Jeff-Qwen3.5-0.8B Qwen3.5-2B untrained Jeff-Qwen3.5-2B Gemma 4 E2B untrained Jeff-Gemma4-E2B Jev (published) AutoJev-27B (published)
Overall (5 benchmarks) 45.3 79.1 46.5 83.1 62.5 81.6 83.0 84.9
BBH 39.5 64.0 46.0 68.0 51.3 66.4 94.3 82.8
Financial PhraseBank 36.0 96.4 53.4 96.3 86.0 96.1 77.0 84.2
JudgeBench 56.6 62.6 57.4 64.6 46.9 60.6 78.6 78.9
RAGTruth 49.1 86.1 35.9 88.9 63.8 87.4 77.3 88.9
WinoGrande 49.2 68.6 52.2 79.0 51.0 77.4 90.7 83.3
JevBench hard (separate) 36.2 47.6 45.7 53.3 41.0 48.6 73.3 70.3

Bold: the winner of Jeff against Jev in each row. Bold italic: AutoJev-27B where it is the best of all models in the row (on RAGTruth, tied with Jeff-Qwen3.5-2B); it is shown for reference, since the head-to-head comparison is with Jev. Jeff's overall score comes from classification and grounding, where it matches or beats the large models; on the reasoning-heavy benchmarks (BBH, JudgeBench, JevBench) it stays well below them, as you would expect at this size.

Games: a zero-shot test

To test zero-shot performance on tasks unlike anything in the benchmarks, we had Jeff play three games. Games aren't the ideal zero-shot test, since a game's state isn't typical unstructured data; but they are a common, and fun, way to test a System 1 model. Each turn, the code describes the situation and the legal moves in words, and the model picks one. The options state what each move leads to (Frogger: "you would be hit by a car and lose a life"; Doom: "the nearest monster is a little to your left"), but never which move is right. Each result is 20 episodes, seed 1234; ▶ opens a video of the run's first episode.

Jeff-Qwen3.5-0.8B playing, zero-shot (the bold row in the table below; click a clip for the full video):

Jeff-Qwen3.5-0.8B playing Doom
Doom

Jeff-Qwen3.5-0.8B playing Frogger
Frogger

Jeff-Qwen3.5-0.8B playing Pac-Man
Pac-Man

Model Doom, kills (monster's direction in words) Frogger, crossings (consequences) Pac-Man, pellets of 98 (consequences)
Random moves −0.05 0 11.2
Hand-coded rule bot 6.55 ▶ 10.25 ▶ 94.1 ▶
Qwen3.5-0.8B, untrained 5.0 ▶ 1.0 ▶ 25.8 ▶
Jeff-Qwen3.5-0.8B 6.55 ▶ 10.3 ▶ 57.0 ▶
Qwen3.5-2B, untrained 0.55 ▶ 0.05 ▶ 72.1 ▶
Jeff-Qwen3.5-2B −0.9 ▶ 6.0 ▶ 41.2 ▶
Gemma 4 E2B, untrained −0.55 ▶ 0 ▶ 3.2 ▶
Jeff-Gemma4-E2B 0.55 ▶ 0.15 ▶ 53.2 ▶
Jev (published, Doom) 6.55, told the aiming rule; −0.60 without it — —

Jeff-0.8B decides in 29–49 ms per move on an M4 Max; Jev's published Doom run took 212 ms per call over its API. The two times were not measured on the same hardware. To play them yourself:

uv sync --extra games
uv run python -m jeff.games --game doom --player jeff --criteria situation --url http://127.0.0.1:8765 --video --out runs/games/doom.json
uv run python -m jeff.games --game frogger --player jeff --criteria outcomes --url http://127.0.0.1:8765 --out runs/games/frogger.json
uv run python -m jeff.games --game pacman --player rule --out runs/games/pacman-rule.json

Speed and size

Median time per decision over the same 200 benchmark questions (about 200 input tokens each), one question at a time, from raw text to probabilities:

Model Parameters Weights (16-bit) NVIDIA RTX PRO 6000 Apple M4 Max (MLX) CPU (32 threads)
Jeff-Qwen3.5-0.8B 0.8B 1.7 GB 22 ms 28 ms 463 ms
Jeff-Qwen3.5-2B 2B 4.2 GB 24 ms 60 ms 708 ms
Jeff-Gemma4-E2B 2B effective (4.6B stored) 9.3 GB 29 ms — (MLX runs Qwen only) 1.0 s
AutoJev-27B 27B ~54 GB not published — —
Jev not disclosed API only 114–212 ms per call in published Doom runs, including the network — —

Using it well

  • Reason in code, decide with Jeff. It's a classifier, not a planner. State what each option leads to ("this move gets you hit by a car"); asked to forecast ("a car arrives in 2 turns"), it does no better than random.
  • Wording matters enormously. Describe options consistently: giving Frogger's goal option the same words as every other forward option took one episode from 15 crossings to 23.
  • Use short option keys and descriptive text: {"1": "Engagement letter"}, not long IDs, which cost time and add nothing.
  • Ask independent questions together in one request.
  • Fine-tune it if zero-shot isn't enough. A voice-navigation fine-tune on ~11k app-specific examples took about half an hour on one GPU and moved held-out accuracy from 31.7% to 95.8%, at about 40 ms per decision on an M4 Max: autojev-train --initial-checkpoint <jeff> --epochs 1 ....
  • Pick the size for the job. For fast option picking the 0.8B is the sweet spot: the 2B is more cautious and plays the games worse, despite scoring higher on the benchmarks.

Train your own

uv run autojev-mix ...          # build the training set (public data, synthetic data, leak filter)
scripts/train.sh RUN data/mix/public.jsonl data/mix 5e-6 40 Qwen/Qwen3.5-0.8B <revision> --epochs 1
uv run autojev-evaluate --data data/panel.jsonl --local --checkpoint checkpoints/RUN/selected --output runs/eval/RUN.json

The full pipeline (synthetic data from a local teacher, leak filter, learning-rate sweeps, dashboard) is described in scripts/train_all.sh, and every training source with its licence in docs/data-sources.md. Training recipe: full-weight fine-tuning, one epoch, batches of 256, cross-entropy over the option letters, then one fitted temperature for calibration; checkpoints are chosen on a development set, never on the benchmark panel. At least half of each training family follows the panel's layout conventions (formats only; no panel item is ever trained on).

Caveats

  • Small models don't reason. Expect fast, calibrated choices between the options you describe, not multi-step reasoning. At 0.8B–2B parameters this holds for every model, not just Jeff.
  • Jeff-2B is a weaker game player than Jeff-0.8B. The untrained 2B already appears more risk-averse than the untrained 0.8B, and our training seems to have made that worse. This needs more investigation.
  • Benchmark scores don't predict game play. The untrained Gemma 4 E2B beats the untrained Qwen models on the benchmarks yet plays the games worst: right most of the time, but not reliably. Training fixed its Pac-Man (3.2 → 53.2 pellets) but not its Doom or Frogger.
  • Prompts matter. Jev's own Doom prompt (a raw bearing number plus an aiming rule) does not work for any of our models; options that state consequences in words do.
  • English and text only.

History

Jeff began as a fork of AutoJev by Denis Yarats (MIT licence), an open recipe that fine-tunes Qwen3.8-27B to return Jev-style decisions. We kept its core design (one forward pass per decision, a trained answer readout, a fitted temperature for calibration) and built on it: small students (0.8B and 2B Qwen, Gemma 4 E2B), a local synthetic-data pipeline with a leak filter, prompt layouts for domain fine-tunes, MLX serving on Apple silicon, game tests and a training dashboard. The original copyright notice is kept in LICENSE.

Licence

Code: MIT (including AutoJev's). Model weights: Apache 2.0. Doom harness adapted from jev-plays-doom (MIT). Training data: see the dataset card; each source keeps its licence and is listed in docs/data-sources.md. We release the weights and code, not the training data; some sources are share-alike (CC BY-SA).

The Daily Front Page 13 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Malleable by Design
article

Malleable software: Restoring user agency in a world of locked-down apps (2025)

by evakhoury·▲ 154 points·72 comments·inkandswitch.com ↗
The original promise of personal computing was a new kind of clay.

Restoring user agency in a world of locked-down apps

The original promise of personal computing was a new kind of clay—a malleable material that users could reshape at will. Instead, we got appliances: built far away, sealed, unchangeable. When your tools don’t work the way you need them to, you submit feedback and hope for the best. You’re forced to adapt your workflow to fit your software, when it should be the other way around.

In this essay, we envision malleable software: tools that users can reshape with minimal friction to suit their unique needs. Modification becomes routine, not exceptional. Adaptation happens at the point of use, not through engineering teams at distant corporations.

Realizing this vision will require confronting many barriers. From programming languages to operating systems and app stores, every layer of the modern computing landscape has been built upon the assumption that users are passive recipients rather than active co-creators. What we need instead are computing systems that invite every user to gradually become a creator. Tools that compose into custom workflows, rather than siloed monolithic apps. Systems that support local groups in communal creation.

Fortunately, there’s a lot of inspiration to draw on—both research work and commercial products spanning the past several decades. In this essay, we synthesize ideas from that body of work, as well as lessons learned from years of testing our own prototypes. Whether you’re a software developer, a researcher, or any kind of computer user, we invite you to join us in striving towards a world of malleable software.

guitar.jpg

Motivation

We want to adapt our environments

Environments matter. To do our best work and live our best lives, we need spaces that let us each express our unique potential.

A guitar maker sets up their workshop with their saws, hammers, chisels and files arranged just so. They can also build new tools as needed to achieve the best result—a wooden block as a support, or a pair of pliers sanded down into the right shape.

guitar-workshop.jpg

Over the years, a home cook gradually assembles a combination of knives, cutting boards, and pots and pans, finding the ones that work best for them. They can install hooks on the ceiling and move shelves around to support their workflow—whether that’s cooking weekday dinners or hosting elaborate weekend cookouts.

kitchen.jpg

These are everyday situations. In the physical world, the act of crafting our environments comes naturally, because physical reality is malleable.

Many small tweaks—taping a post-it note to the wall, rearranging some drawers, moving a piece of furniture—can be done instantly without asking anyone’s permission. We can also take on larger changes that require more effort and skill, like building a workshop or renovating a kitchen. And should we lack those skills ourselves, we can recruit help from craftspeople in our local communities.

When we work and live in a physical space that we control, we tend to evolve it to suit our own needs. As Stewart Brand writes in his book How Buildings Learn: “Age plus adaptivity is what makes a building come to be loved. The building learns from its occupants, and they learn from it.”

Mass-produced software is too rigid

These days, we spend more and more of our time in environments built from code, not atoms. We’ve gained many capabilities in this shift—we can collaborate instantly across continents and search thousands of files in an instant. But we’re also losing something important: the ability to adapt our environments and make them our own.

Here’s an example. One of the authors worked on a software team that tracked its work with index cards taped to a wall. The team would constantly evolve the tracker—tape lines moved; checklists appeared; special zones of cards emerged around the main grid. The fluidity of the tool encouraged fluidity of process.

wall-board.jpg

A wall of index cards is a malleable medium for managing software development.

Later, the team switched to a web-based issue tracker to support remote collaborators. Now there wasn’t a way to model or display a special zone of cards, so the team abandoned that part of their process. Further process changes also ground to a halt. Before, new ideas took minutes to try; now they could take hours of wrangling configurations, if they were possible at all. Computerizing work led to a loss of agency.

The rigidity of software isn’t just a minor inconvenience. It can seriously impede people doing important work. The doctor and writer Atul Gawande has written about how computerization in the medical profession is leading to record levels of burnout. For instance, doctors would once skip irrelevant fields when filling out paper forms; now the software forces them to fill in those fields, and they have no power to edit those software rules. As Gawande says of one doctor: “Spending the extra time didn’t anger her. The pointlessness of it did.”

epic.jpg

Inflexible electronic medical records systems are driving doctors to burnout.

When you face a situation where software doesn’t meet your needs, you might try giving feedback to the developers—but that usually doesn’t result in immediate action. When different users have different needs, a centralized development team can’t possibly address everyone’s problems. And for that matter, when a developer does try to cram too many solutions into a single product, the result is a bloated mess. To avoid this trap, good product teams learn to decline most user requests, leaving a long tail of niche needs unserved.

It may seem inevitable that our specific requirements aren’t served by our software—but that’s only because we’ve taken for granted that software is controlled by centralized development teams. What if we were to shift more control into the hands of users who know their own needs?

Gawande tells a story of a neurosurgeon who worked with an IT analyst to adapt his department’s medical records system. “Before long, they had built a faster, more intuitive interface, designed specifically for neurosurgery office visits.” The requirements were driven by the needs of their specific department, not the needs of every doctor in the country. Beyond the direct productivity benefit, the physicians felt more in control of their tools—an antidote to burnout.

As inspiring as this story is, it’s more the exception than the rule, because the tools and infrastructure we use to deploy software treat users as passive recipients rather than active co-creators. Software is organized into monolithic applications rather than flexible remixable toolkits. Customization requires programming skills that most people don’t have—and besides, most software is closed source. Software doesn’t ship to users with the tools to edit the software. App stores are designed for companies distributing software to consumers, not amateurs sharing tools with their friends. This is a system of industrial mass production, not small-scale craft.

To be fair, mass-produced software has delivered many benefits. We can access a vast array of highly polished applications at reasonable prices. Software has made progress in reliability, accessibility, and security. Developers have created business models that can sustainably pay teams to deliver continuously improving software.

But as these stories and countless other examples show, inflexible mass-produced software also gets in the way. The more different you are from the average user, the more the benefits of customization outweigh the benefits of professional polish. Everyone is unique in some way—perhaps you have strong opinions about tools for writing, making music, having discussions, or planning projects. When you have specific needs, agency matters.

Our goal: malleable software

We envision a new kind of computing ecosystem that gives users agency as co-creators. We call this idea malleable software—a software ecosystem where anyone can adapt their tools to their needs with minimal friction.

The term “malleable software” has a long legacy and isn’t our invention. Recently it’s been invoked in research including Tchernavskij’s doctoral thesis and Klokmose et al’s Webstrates. While the origins of the term are unclear, it may have begun with Alan Kay invoking the idea of software as “clay” in his 1984 article Computer Software.

  • By “software ecosystem”, we mean the broad technical and cultural environment surrounding software and its users. Malleability isn’t a narrow technical problem.
  • By “anyone”, we mean that broad accessibility is the goal. And while individual self-sufficiency is useful to cultivate, cooperating with local community is also valuable.
  • When we say “adapting tools” we include a whole range of customizations, from making small tweaks to existing software, to deep renovations, to creating new tools that work well in coordination with existing ones. Adaptation doesn’t imply starting over from scratch.
  • Finally, “minimal friction” is key. Editing our tools should be fast. It should feel light. At best, it should be something we can do in the moment when a need arises, so we can get back to the task at hand.

Existing approaches

You may be wondering: what about settings or plugins? There are indeed many techniques for customizing software that deserve to be celebrated. However, they also have limits that prevent them from fully achieving the goals we’ve laid out above.

Settings

Settings are a common way to change the way an application behaves. If the right setting exists, you can just toggle a checkbox and move on with your day.

But settings only offer controls that the application developers have thought to expose, leaving you stuck if there’s not a setting that does what you want. Settings also tend to become long lists of disjointed checkboxes without a coherent mental model tying them together.

settings.png

Settings allow for certain customizations chosen in advance by an application developer.

Plugins

One way to scale beyond the bandwidth of a central developer is to allow third-party plugins that extend the behavior of an application. A good plugin system makes it easy for users to get started customizing with a minimum of effort, because they can install plugins that other people have created. A plugin API also has the key benefit of stabilizing the contract between the underlying application and various extensions, helping with ongoing maintenance.

However, plugin systems still can only edit an app’s behavior in specific authorized ways. If there’s not a plugin surface available for a given customization, the user is out of luck. (In fact, most applications have no plugin API at all, because it’s hard work to design a good one!)

There are other problems too. Going from installing plugins to making one is a chasm that’s hard to cross. And each app has its own distinct plugin system, making it typically impossible to share plugins across different apps.

obsidian-plugins.png

The Obsidian Markdown editor offers a rich ecosystem of community plugins for extending the editor's behavior.

Modding

When settings and official extension APIs don’t go far enough (or aren’t provided in the first place), users can sometimes take control through permissionless modding. For instance, browser extensions can intervene in a website’s user interface and inject new client-side behavior without needing any hooks to be exposed by the original application developer.

The term “modding” seems to originate from video game modding. Examples of modding in other domains include the storied history of Mac kernel hacking and Prefab’s pixel-based reverse-engineering of interfaces. Modding overlaps considerably with the concept of “adversarial interoperability”.

Permissionless mods apply in a much broader range of scenarios than officially supported plugin APIs. In fact, they can even be used when the original developer is actively opposed to a given type of extension—ad blockers prioritize the interests of users over the interests of websites.

Mods face their own limitations. They can require tedious reverse-engineering to create. They are often difficult to maintain as the underlying application evolves. Different mods on the same app often don’t work together cleanly.

The limits of the underlying platform can also limit what they’re able to do—for example, browser extensions can’t modify server-side behavior, severely limiting the features they can provide. Also, much like other kinds of plugins, unsupported mods have a wide chasm between installing and creating. For instance, to make a browser extension, you need to leave the browser, write code, and distribute a packaged code artifact. (Later on we’ll discuss some strategies to avoid these steps.)

extension.png

An example of a browser extension serving a niche need: BoA Checklist adds a persistent checkbox next to each transaction on the Bank of America website, to track if you've already reviewed that transaction.

Open source

The open source software movement promotes the idea of distributing source code so that users of software can own their software, contribute back to it, and if needed create their own version that better meets their own needs. This has been a positive force for the world, and represents an important ingredient for malleability.

But having access to edit the code doesn’t mean minimal friction. Modifying a serious open source codebase usually requires significant expertise and effort. This applies even for making a tiny change, like changing the color of a button . Even for a skilled programmer, setting up a development environment and getting acquainted with a codebase represents enough of a hurdle that it’s not casually pursued in the moment.

pull-requests.png

Users can propose changes to an open source project on GitHub.

AI-assisted coding

Finally, it’s worth addressing a hot topic of the moment. Will AI tools automatically make malleable software a reality?

Historically, one of the biggest puzzles in democratizing the creation of software was figuring out how to enable regular people to write computer programs. Many approaches have been tried: programming languages with friendlier syntax or simpler semantics; programming-by-demonstration macro recording systems; visual live programming environments, and more.

Today, large language models offer a new approach: to take fuzzy ideas expressed in natural language and automatically turn them into code. There is now momentum towards a world where anyone can generate a web application from a chat, without needing any programming experience. There are new examples every day, from a journalist making an app for generating school lunch ideas to an environmental studies student making a website for tracking reforestation efforts. We’ve personally found it useful to build our own software tools with AI, such as a specialized Japanese translation app, and a minimal workout timer with a custom workout plan:

claude-workout-artifact.png

Building a workout timer tool using AI in Claude Artifacts

We think these developments hold exciting potential, and represent a good reason to pursue malleable software at this moment. But at the same time, AI code generation alone does not address all the barriers to malleability. Even if we presume that every computer user could perfectly write and edit code, that still leaves open some big questions.

How can users tweak the existing tools they’ve installed, rather than just making new siloed applications? How can AI-generated tools compose with one another to build up larger workflows over shared data? And how can we let users take more direct, precise control over tweaking their software, without needing to resort to AI coding for even the tiniest change? None of these questions are addressed by products that generate a cloud-hosted application from a prompt.

Bringing AI coding tools into today’s software ecosystem is like bringing a talented sous chef to a food court. If you’re used to purchasing meals from a menu, a skilled chef can’t do much to help you. Similarly, if you’re using closed-source software from an app store, an AI coding assistant can’t do very much to help you as a user. To fully take advantage of the capabilities of AI, we need to move past the food court to something more like a kitchen—a site of open-ended creation.


Reshaping the foundations of computing around user agency is an ambitious goal. Luckily, since the dawn of personal computing, many people have proposed powerful ideas for achieving it.

In the next few sections, we’ll summarize three design patterns that we see as essential for achieving malleable software. These aren’t precise recipes for how to solve the problem. But we believe they are important ways of thinking that are underrepresented in today’s software world and will form part of the solution to achieving malleable software.

This essay isn’t an exhaustive survey of all work on malleability. For a longer reading list, we recommend the Malleable Systems Collective catalog.

A gentle slope from user to creator

Malleable software does not imply everybody creating all of their own tools from scratch. That would be a waste of time, since many off-the-shelf tools are already pretty close to serving our needs, with only minor tweaks needed.

A more sensible approach is to start out using existing software tools built by other people or companies, but to have the option of modifying these tools as you discover ways that they don’t meet your needs. You can start out as a passive user, and gradually become an editor and a creator.

In a 1990 paper User-Tailorable Systems: Pressing the Issues with Buttons, Allan MacLean and his collaborators at EuroPARC propose a powerful mental model for designing software systems that invite users to gradually become creators.

Consider this chart where the x-axis represents the power or depth of a customization, and the y-axis represents the level of skill required to perform that customization. In this model, whenever someone needs to suddenly learn a lot more in order to achieve the next level of depth of customization, that appear as a vertical “cliff”.

maclean-cliffs.png

Going from changing settings to full programming is a sharp "cliff" that's hard to scale. (figure from MacLean et al)

To flatten out the cliffs and encourage smooth progress, MacLean et al. proposed a design goal: each incremental increase in tailoring power should only require a small incremental investment of learning and skill. A system that follows this rule can be visualized as having a “gentle slope” free of cliffs.

maclean-slope.png

A gentle slope of tailorability, made up of many different customization techniques. (figure from MacLean et al)

The researchers demonstrated this principle in an automation system called Buttons. To start out, users could move buttons around and change the text or color. Slightly further up the slope, users could edit variable values or use a toolkit to create simple UIs. Finally, at the top of the slope, users could create new behaviors by doing Lisp programming. The key point was that each customization could be done with the simplest technique possible, leaving full programming only as a last resort when absolutely needed.

Alan Kay has described a similar philosophy of empowering users to “open the hood”.

Many successful environments for end-user malleability employ the gentle slope pattern. Consider spreadsheets as an example. When someone sends you a complex spreadsheet, you can start by just viewing it, or editing a cell marked as an input. Next you might try changing some formatting or add some labels. As you get deeper into using the spreadsheet, you might start tweaking formulas or adding your own new cells. A spreadsheet can start out feeling like an “application”—an artifact that someone else put together, with a few knobs intended for you to control—but unlike an application, you can smoothly progress to deeper customizations.

spreadsheet-slope.png

Spreadsheets offer a gentle slope of customization, from use to deeper modification.

Spreadsheets show us a couple useful qualities for achieving a gentle slope. First, spreadsheets have an in-place toolchain: everyone using a spreadsheet is running the full editor. When you want to dive deeper into modifying a spreadsheet, there’s no need to install or open a separate development environment.

Also, spreadsheets often have a scrappy aesthetic. It can feel safer to change a spreadsheet, compared to the pixel-perfect polish of a professionally designed application.

In How Buildings Learn, Stewart Brand reflects on the adaptability of shabby buildings: “Any change is likely to be an improvement… Do what you want. The place can’t get much worse anyway.”

Another way to achieve a gentle slope is through explicit modes. HyperCard, a Mac program from the 1980s in which users could create stacks of “cards”, offered “levels” which governed what actions were available to the user at any time.

hypercard-levels.png

In HyperCard, users could select a "level" to restrict their editing capabilities.

Level 1 was read-only; Levels 2 and 3 supported text and graphical editing with direct manipulation interactions; Level 4 added creating buttons and linking things together; Level 5 unlocked full programming using a scripting language called HyperTalk. These explicit modes served as guardrails, allowing users to safely explore without unintended consequences.

hypercard-slope.png

Each level in HyperCard represents a modest step up in power and skill.

Finally, let’s see what it looks like to smooth out a cliff. As we discussed earlier, there’s a big chasm from installing a browser extension to building one yourself.

browser-extension-cliff.png

Going from installing a browser extension to making one is a steep cliff. It requires leaving the browser and doing involved programming.

We can achieve a much smoother slope if we incorporate lighter weight techniques for customizing websites. Tools like Stylish and Arc Boosts let users create and share custom styling themes from within the browser. Further up the curve, macro systems and let users record and replay actions taken on websites. And if the user knows a little bit of JavaScript, they can tweak user scripts written in Tampermonkey directly in the browser.

arc-styles.png

Arc Boosts lets users restyle a website with direct manipulation interactions from directly within the browser.

Each of these techniques gives a different tradeoff between power and skill. If someone just wants to tweak a color on a website, they should be able to do it in a less expressive system focused on that task, rather than needing to build an entire browser extension. With these techniques, we can smooth out the slope:

browser-extension-steady-slope.png

Web customization techniques provide a gentler slope before needing to create a browser extension.

There are two ways to make a slope gentler. One way is to start from the right side of the diagram and reduce the required skill. This strategy corresponds to a huge variety of work which starts with the full expressiveness of programming and makes it more approachable—with friendlier syntax, live programming environments, inferring programs from examples, gradual scaffolding and more.

However, there’s another strategy that’s just as important, and sometimes overlooked: starting from the left side of the diagram and gradually offering more power. Many successful customizable systems such as spreadsheets, HyperCard, Flash, Notion, and Airtable follow a similar pattern: a media editor with optional programmability. When an environment offers document editing with familiar direct manipulation interactions, users can get a lot done without needing to write any code.

One final note: not everyone needs to reach the top of the slope. At some point, many amateurs will enlist help from others in order to save time and energy, or to avoid having to learn the necessary skills. The key is that many customizations are accessible to amateurs, with reasonable incremental investments of learning and skill. A gentle slope also supports smoother collaboration between people of different skill levels. We’ll explore this point more later on when we discuss the importance of communal creation.

Tools, not apps

So far we’ve focused on the rigidity of individual applications. But there’s another reason that it’s hard to adapt software to meet our needs: the very idea of “applications”. Because we’re so accustomed to this idea, it can be hard to see the nature of the problem—so let’s consider an analogy from the kitchen.

Apps are avocado slicers

One way to slice an avocado is to use an “avocado slicer”: a 3-in-1 gadget that combines a dull plastic knife for slicing the avocado in half, a circular grabber for extracting the pit, and a line of plastic rods that produce 7 slices at once.

avocado-slicer.jpg

An avocado slicer is specialized to one use case.

Anyone can use an avocado slicer with no practice, and it poses no safety risk. And yet, because the avocado slicer is narrowly focused on one task, it’s useless at anything else. If you used a specialized gadget for every single task, you’d end up with a mountain of plastic.

kitchen-gadgets.jpg

There are specialized gadgets available for an enormous variety of tasks, from stripping corn to cutting lettuce.

Another approach is to use a knife. A knife can handle all the steps of slicing an avocado, and much more: it can slice a chicken breast, dice an onion, or smash a garlic clove. You do need to learn how to handle the knife safely and skillfully, but it’s worth the effort, because a knife is a general tool.

knife.jpg

A knife can cut an avocado, and much more.

How does this analogy apply to software? Many applications are avocado slicers. They’re a bundle of functionality targeted at some specific use case: planning a trip, tracking workouts, organizing recipes. Because an app needs to handle many tasks associated with a use case, it sometimes doesn’t handle any of them particularly well. You may have come across situations where an app is missing some functionality that’s important to you, while simultaneously including extra bits you don’t need.

There are some notable exceptions to “apps are avocado slicers”. Text editors and spreadsheets, for example, have knife-like qualities. People spend years mastering these tools and then can apply them to diverse tasks.

On top of that, solving a larger task using multiple applications often requires manual coordination. We can put windows next to each other and copy-paste data, but not much more. If we want more knife-like software tools, we’ll need better ways for smaller software tools to work together.

travel-apps.png

Planning a vacation requires manually coordinating across many isolated applications.

This isn’t to say that the application model has no benefits. Users get a cohesive experience within the bounds of an application, since the developer can finetune it without worrying about interoperating with other tools. Siloing data by application is a convenient answer to some security and privacy concerns. Paying for an application (and support) is a reasonable billing model. These are important benefits which can’t be ignored.

But when you’re trying to solve a complex problem or construct a creative workflow spanning multiple applications, the isolation between applications can cause serious problems. How might we reorient software around more general, composable tools—that feels more like a knife and less like an avocado slicer? There are two sub-problems to address: sharing data between tools, and combining tools within the user interface.

A key inspiration in this area is Michel Beaudouin-Lafon’s work on Instrumental Interaction described in his talk A World Without Apps.

Sharing data between tools

If we’re going to use different software tools together in coordination to get a job done, it’s essential that those tools can operate on one shared reality.

In modern cloud and mobile platforms, each application manages its own data in a private silo. The plan for the trip lives across a notes app, a Google Maps list, a calendar. This fragmentation impedes malleability. When each application manages its own data, introducing a new tool into a workflow incurs more friction. It’s easier to stay within an existing application to complete the whole job, even if superior alternatives exist for completing some part of the task.

When data is instead shared among applications, it empowers end users to compose tools in more flexible ways. One well-known example is the desktop filesystem. When information is stored in files, you can edit the same file in different tools that focus on different subtasks. You can edit the light levels on a photograph in Lightroom, and then use Apple Preview to scribble a note on the photo. Different collaborators can also use their preferred tools—one user can edit a code repository in VSCode while collaborating with a coworker who edits it in emacs.

We believe a missing ingredient in today’s ecosystem is a modern equivalent to the filesystem, with better support for collaboration. Later we’ll share our prototypes of this idea.

files.png

Files serve as a common ground between different tools.

Another example of tools operating on shared data is low-code database application builders—including desktop-based applications like Microsoft Access and Filemaker Pro, and cloud-based applications like Airtable and Notion. These environments support end-users in building multiple views of the same database. For example, Airtable comes with with general tools such as a grid table editor, a board of cards, and a calendar. It also offers tools for adding custom UIs, but those are only needed in specialized cases, since many tasks can be achieved in the general grid editor.

Editing the same data with multiple views in Airtable, with live reactivity

The idea of shared data also extends to shared objects with behavior. In Smalltalk, a user works with an image: a repository of objects representing not only persisted state, but also code associated with that state. Because everything in the system is represented as objects, it’s possible to introduce new tools that operate on those existing objects—including calling methods to invoke behavior.

Inert data and rich objects each have advantages. Objects can help tools interpret and work with data in meaningful ways; data can be more straightforward to manage.

Finally, realtime collaboration over shared data enables different people to work live in different tools. One example of this is in Webstrates, a malleable software platform for collaboration in the browser. In Webstrates, tools run by different users can collaboratively edit the contents of a shared, synchronized dataset stored in the browser’s DOM. As a result, two users can each use their preferred editor to work on the same research paper together, with one of them using a WYSIWYG editor and the other using a plain text interface.

The same paper being edited realtime in two different editors, in Webstrates

Composing the user interface

pegboard.jpg

Tools need to share not only underlying data, but a workspace where they can be used together.

The app paradigm isn’t set up for this. An application takes control over a window or tab and builds a world inside of it. This has advantages – an application’s creator can carefully craft your experience in this world and make sure everything works together just right. But it means that using multiple applications together requires flipping between isolated user experiences. It’s as though you have to carry ingredients from one kitchen to another every time you want to use a new tool. Even if data interoperates, your experience is splintered.

How can we break up not just an application’s ownership of data, but its control of the interactive environment? Earlier, we discussed approaches like plugins and permissionless modding, which crack open seams to extend applications from within. These are great, but if we want a world where we work with “tools, not apps”, we need something a little different – environments where tools can be brought together and used in a shared space.

One set of ideas comes from compound-document systems, like OpenDoc and OLE. These let authors compose documents out of multiple kinds of media embedded in each other. For instance, a text document might host an embedded diagram, which can in turn host a table of data. Selecting one of these parts opens up an editor in-place, with no flipping back and forth between windows or digging through the file system required. These systems are open-ended; developers can introduce new kinds of media, as well as new, alternative editors for existing media types.

OpenDoc documents are made of "parts" that are edited with different editors, but stored together in a unified document.

Splitting up the UI into smaller pieces raises new design challenges. How do users choose which editors to use for each part of a document? How can a user share a document and guarantee that others will have all the necessary sub-editors available? How do global interactions like selection and focus work across editors? Systems like OpenDoc developed answers to these questions which are worth studying, although the nature of modern collaborative and web-based applications have also changed the surrounding context.

Sometimes, embedding editors for parts of a document is not enough. Consider this example from Tchernavskij’s Designing and programming malleable software: how might a user reuse a color picker from one app inside of another app? Unlike a diagram editor, a color picker is not associated with just one part of a document; it’s a tool that interacts with objects throughout the document. In order to do its job, the color picker somehow needs to be aware of other objects and have the ability to edit their colors. Usually, user interfaces hardcode these kinds of connections, but to allow extension or reuse, we need a more flexible and open-ended approach.

color-picker.png

A challenge problem from Designing and programming malleable software: reusing a color picker from one application in another.

To solve this, Tchernavskij proposes entanglers: a dedicated layer of the UI system that dynamically detects and connects related UI elements. Another research project, Varv, solves the problem by specifying behavior with lists of event triggers which can be additively grown. While the details of these approaches differ, the common element is representing connections between parts of the UI in such a way that supports later extension.

A more radical approach to UI composition is to use the physical world as a foundation for composability, as seen in Dynamicland. Programs at Dynamicland are built as collections of physical objects (like pieces of paper) that can carry code and data and act as handles for interaction. At Dynamicland, you can compose user interfaces by bringing them near each other on a table and taping or gluing them together. Programs can also use relationships in space, like pointing and proximity, to create virtual connections between objects. While screen-based systems can’t directly emulate Dynamicland’s use of the physical world, they may still be able to take some lessons from the value of having a consistent materiality and physics.

spatial-relationships.jpg

Pieces of paper running programs at Dynamicland, assembled on a table, sending out green “whiskers” to define their connections.

Dynamicland also derives much of its composability from how it breaks up programs into small objects that work together. Communication between these objects happens through a global database. As a result, it’s possible to add new tools into the system that intercept messages between existing objects, modifing the behavior of existing tools. When a system doesn’t assume up front that certain connections exist between senders and receivers of information, it’s easier to additively extend the system with new uses of that information.

Systems including Smalltalk, Boxer, and Webstrates take a similar approach to Dynamicland, combining “content, computation and interaction” into an integrated, end-user programmable “substrate”. This term was established by Webstrates and continues to be developed, including by a recent workshop.

Communal creation

While it’s exciting to imagine every person crafting their own unique computing experience, an individualistic view of malleable software will only get you so far.

Sure, individuals should be able to adapt their software to their needs in small ways in the moment, climbing up a “gentle slope from use to creation”. But as the changes they want to make get larger, software is going to take more time and skills to make. If everyone were forced to make these changes just for themselves, as one-offs, the benefits would probably not be worth the costs. Not everyone wants to be a software-making expert.

And there’s an even more fundamental reason to think of malleability through a communal lens: we use computers together! A product team needs a single system for tracking projects. A department at a hospital needs a single system for patient intake forms. These communities are certainly not well-served by one-size-fits-all applications they have no control over. But the solution can’t be every-user-for-themselves either. We should help communities build and maintain shared solutions to their problems.

See The inequities of our remote gathering tools for more on how one-size-fits-all apps like Zoom can disrupt democratic social dynamics.

With the right infrastructure, we can work together to craft our software. People with similar needs around the world can exchange work and build collaboratively, as we have seen happen in free-software communities. And local communities, from companies to families to civic organizations, can build and maintain software suited to their local needs. When local needs get higher up the “slope” and call for special levels of skill and enthusiasm, you don’t need everyone in a community to attain these levels – just enough people to play that role and get the job done.

Studying spreadsheet use at companies, Nardi and Miller found “local developers” – amateur enthusiasts who could write bits of code for their coworkers and guide their team up the gentle slope of spreadsheets.

Building software for “local” contexts is sometimes easier than building software for world-wide use. You don’t need to build airtight, industrial-grade software if you are in direct contact with your users and can be responsive to the situations they run into. You don’t need to anticipate everyone’s needs in your design, just your community’s. Clay Shirky termed this pattern “situated software”, describing how his students were able to rapidly build software for their communities by “taking advantage of social infrastructure or context-sensitive information”. On an even more intimate level, Robin Sloan memorably described how an app built for his family could be a “home-cooked meal”.

For all these reasons, we believe that technical infrastructures for malleable software will need to support sociotechnical systems of people working together, across many levels, to make software work for themselves and their communities.

The history of free software offers lessons on how sociotechnical systems like this can be constructed. We are especially inspired by situations where free-software communities don’t assume there should only be one centrally-controlled version of an application in the world. For instance, Mastodon instances run by small communities often edit Mastodon’s code to implement community-specific features and policies. Of course, situations like this still require serious engineering work, and are still operating on apps. As we move towards a world with gentler slopes into software modification, and more tools rather than apps, we’ll need to figure out how smaller pieces of code can be shared and collaboratively developed, and how interoperability can be maintained in a world of pluralistic software.

Ink & Switch prototypes

At Ink & Switch, we’ve spent several years building research prototypes that explore different aspects of malleable software. These projects aren’t commercial products. Rather, the goal of each prototype has been to develop our understanding of techniques for enabling malleability, and then to learn from deep usage of those prototypes. (In fact, we wrote this very essay in a homegrown malleable software environment, and will share some of our successes and failures from that experience.)

We’ve previously published essays about most of the projects mentioned in this section; follow the links for more detail.

Our work has spanned the entire computing stack, and can be roughly grouped into two threads. One thread has explored foundational infrastructure—techniques for storing data, loading code, and defining user interfaces, in a way that supports malleable experiences being built on top. Higher up the stack, another thread of work has focused on a particular kind of user experience: dynamic documents where static media can be gradually enriched with interactive behavior. Let’s cover each in turn.

Infrastructure for malleability

We’ve discussed how most of the infrastructure used to run and develop software today is designed without malleability as a priority. We’ve also shown some inspirations for reorienting around malleability. The desktop filesystem enables shared data between tools. Smalltalk, Hypercard, and spreadsheets enable live modification by allowing code editing at runtime. Browser-based apps encoding their UIs using the DOM enables permissionless modding through extensions.

Inspired by these predecessors, we have been prototyping an infrastructure stack for building, running, and sharing software that prioritizes malleability. Our approach builds on another area of our research: local-first software, which is a philosophy that prioritizes giving users ownership and control over their data, while maintaining the ability to collaborate with others. As part of that work, we developed a collaboration library called Automerge, which persists and synchronizes JSON documents among users.

In fact, one reason we originally worked on local-first software was that we thought it could provide an important ingredient for supporting malleability.

PushPin: an extensible media canvas

To start figuring out how a local-first foundation could enable malleability, we prototyped PushPin, a web-based collaborative media canvas. A key idea we developed in that project was “document functional reactive programming” (DFRP): representing a tool as a UI component authored in React, backed by a JSON document that was automatically persisted and synchronized through Automerge.

DFRP made it less work to extend the interface than in traditional applications, since we could just add a UI component without worrying about backend databases or REST APIs. Furthermore, the decoupling of data and UI made it straightforward to define new user interfaces for existing documents—since we could define a new component and then register it as an alternate editor.

pushpin.jpg

A PushPin board with embedded cards, each implemented as a React component backed by its own synced Automerge document

PushPin also showcased several challenges. First: how do you choose which UI to use to show a document in a given context? We tried a simple model based on hardcoded contexts—“show a compact view when rendering the document as a card on a board; show an expanded view when rendering as the main content”—but this approach wasn’t sufficient for all our needs. For one thing, it didn’t allow users to choose among views depending on their task.

We also found that an embedding model needs to balance isolation and coordination. We used a restrictive model in which components can embed one another but no further communication was allowed. While this strong isolation made it easy to reason about behavior within a given component, there was no easy way for UI components to share context like hover states, which prevented certain rich user experiences. And permissionless modding wasn’t well supported either, since there was no mechanism to reach into an existing component. These questions of dispatching views and coordinating across components remain open areas of exploration for us.

Cambria: mediating schema compatibility across tools

Schema compatibility was a point of frustration using PushPin. Upgrading tools would frequently break compatibility with existing data. And it was difficult to make different tools interoperate if they couldn’t agree exactly on the format of their underlying JSON data. This is an instance of a broader class of challenges—how should tools cooperate if they can’t agree on the shape of their data? In a malleable environment, we can’t rely on a central authority to dictate the schema.

We prototyped a system called Cambria which solves this challenge by decoupling write schemas from read schemas. Updates are written by each tool in its preferred schema, and then interpreted on demand in other schemas—which could include newer/older versions of the schema, as well as entirely different schemas used by other tools. These are not one-time data migrations; they are ongoing live translations, preserving the ability to write and read from any schema simultaneously.

Based on some limited testing of the Cambria prototype, we believe live data translations are a promising direction for supporting pluralistic schemas. However, we have not yet built a production-ready version of this system that integrates with Automerge; one challenge is that it may require deep integration with the underlying data engine.

lens-graph.png

Cambria supports translating data between tools live on demand, through a graph of transformations called lenses.

Farm: code is data

Although PushPin lowered the bar to contributing new tools to the environment, the system wasn’t editable at runtime—the code was stored in a GitHub repository, and deployed through a standard web application pipeline. Thus, in our next project, we experimented with enabling fluid modifications by using the local-first data layer to host not just user data, but also the code for the system itself. We built a system called Farm which allowed users to author tools in the Elm language, with the source code stored and synced in Automerge documents.

We chose Elm because stricter compilation rules helped automate decisions for when to synchronize code with collaborators.

At a basic level, treating code as data streamlined the sharing of tools. However, many aspects of collaboration proved challenging. How could you work on a tool without breaking it for other people as you edited it? And how could multiple collaborators work on different aspects of the same tool in parallel? This set of challenges led us to our next project.

Patchwork: version control + bootstrapping

Enabling exploration and divergence lies at the heart of malleability. Different users need the freedom to try changing a piece of software or make multiple variations, without fear of losing work or messing up their collaborators. In traditional software engineering projects, these problems are solved with version control concepts, like Git branches.

While version control systems are useful tools for software engineers, they’re not designed to support malleable software. They are difficult to learn, and targeted at formal collaboration workflows. We believe that malleable software demands new solutions which prioritize accessibility to a broad set of users, and which better support casual, informal exploration. We call this vision universal version control.

To explore these version control ideas further, we created Patchwork—a web-based collaboration environment for malleable software. Patchwork builds on the core ideas of PushPin and Farm, storing both user data and software code in Automerge documents. On top of that, it adds version control utilities like history views and simple branching. These tools apply to any document in the system—whether a piece of writing, or code for a software tool.

diff-sidebar-replace.png

Patchwork can display diffs on branches of text documents, among other media types.

One process difference between Patchwork and our previous infrastructure projects is that we are now “bootstrapping”—most of our lab’s internal knowledge work, from writing to whiteboarding to project planning, happens inside of Patchwork. In fact, these very words are being typed into a collaboratively edited Markdown document hosted in Patchwork.

patchwork-tools.png

We’ve used a broad variety of tools hosted in Patchwork—from text editors and whiteboards to simulations, audio sequencers and games.

There’s a long tradition of bootstrapping in computing research project, dating back to Doug Engelbart’s NLS project. For more of a history see this talk by Bret Victor.

One thing we’ve observed from using Patchwork for our work is that opportunities for improving your software can emerge naturally within a malleable system. Here’s an example from the process of writing this essay. The main tool we use is a collaborative Markdown editor:

markdown.png

Editing this essay in Patchwork

At some point, we realized the essay was too long, but it was hard to see the length of different sections just by looking in the Markdown editor. So we created a minimal Section Word Counter tool that measured the length of each section:

word-counter.png

In Patchwork, this new tool could be straightforwardly integrated into the existing workflow. It was coded in a desktop IDE and then synchronized into an Automerge document, with no need to rebuild or redeploy Patchwork itself. Once installed, the Section Word Counter could instantly be used to view the existing essay document, with live updates as the essay changed.

two-tools.png

Two Patchwork tools can edit/view the same underlying Automerge document.

Treating code as data also simplifies sharing. The word counter tool was initially developed by one of the authors for his own personal use, and only loaded in his own Patchwork instance. But when another author asked to use the tool, it could be shared with a link, just like any other document. Each collaborator could choose which tools they wanted to install based on their own needs.

share-tool.png

Sharing a tool with a collaborator via URL. (Chat is one use case we haven't managed to migrate into Patchwork yet)

We used a similar approach to develop several other tools as needs arose. A “Zoomout View” proved useful for talking about the overall structure of the essay:

zoomout.png

In some cases, new tools have proven less useful. We built a “Request Tracker” that would manage assigning feedback requests to coauthors, but this tool didn’t end up getting used very much. That wasn’t a huge loss, though—it didn’t take much work to create the tool, and it was easy to ignore and uninstall.

Another thing we’ve found while customizing Patchwork is that AI is a useful complement to a malleable environment. We argued earlier that AI-assisted coding alone does not guarantee malleability. But when combined with a malleable environment, AI-assisted development can make it much faster to edit your tools.

We’ve used AI assistance to rapidly build many tools in Patchwork. The Section Word Counter tool mentioned above was coded with AI assistance in just a few minutes—in the middle of a writing session, without needing to set aside dedicated time.

A malleable environment can also provide platform capabilities that make AI-generated software more useful. For example: we have an interface for making small software tools from an AI chat. While this UI superficially resembles existing products like Claude Artifacts, the generated tools gain capabilities from existing inside of Patchwork. They automatically support persistence and multi-user collaboration, and can compose with existing tools for editing existing data.

chess-clock.png

A presentation timer tool built with an AI chat in Patchwork has automatic persistence and multi-user synchronization.

While we’ve already experienced some glimpses of malleability in Patchwork, some big challenges remain.

One open challenge is fully applying the ideas of lightweight universal version control to code. Although we have a basic mechanism for creating a branch of a software tool, we’ve yet to flesh out a full set of capabilities around branching—such as seeing and running different branches of a tool simultaneously. And more broadly, we’ve noticed there are tricky social challenges around collaborating on software in a less centralized way. How do people negotiate whether to share the same version of a tool or go their own way with separate forks? Who makes product decisions for a given tool—does the original creator stay in charge, or do they allow anyone to freely contribute? While these questions can’t be magically resolved, we think versioning tools can help.

A related challenge is managing expectations of quality. Most of the tools we’ve built aren’t anywhere close to the polish level of commercial products; they’re scrappy personal tools. When someone shares a tool, how can they communicate its level of quality? There’s a difference between sharing a tool “as-is” and committing to ongoing maintenance.

Finally, Patchwork currently has a limited embedding model that we’d like to improve on. Tools can embed other tools, but the UI of the embedded tool gets cramped, and users need better ways to choose tools at all levels of the hierarchy. We’ve also gradually discovered many reasons why UI components need to communicate in richer ways. For instance, when working on a generic commenting utility that could work with any tool, we realized that it’s useful for tools to report the current user selection as a semantic region of a document. We’ve added hardcoded workarounds to enable these kinds of tool composition, but we’d like to find a more general and less coupled approach, perhaps inspired by approaches like entanglers and Varv we mentioned earlier.

tldraw-embed.jpg

Embedding a text document and a spreadsheet inside a whiteboard in Patchwork

Patchwork is still an active project. We’ve published some early findings from our version control work in a lab notebook, and we plan to share more about the broader system as we make progress. Eventually we also plan to release Patchwork as an open-source tool.

Dynamic documents

In our infrastructure work, we’ve innovated on how software is hosted, but the behavior itself has been specified with traditional code. And yet, we know that writing code—even with AI assistance—still represents a steep “cliff” between usage and modification.

Thus, another strand of our work has focused on allowing the creation of custom tools without programming. Above, we showed some prior art like spreadsheets and Hypercard which embodied the approach of starting with some directly manipulable information and optionally layering on programming.

We’ve followed in this tradition in our work on dynamic documents. Our goal is to explore new techniques for letting users layer behavior onto their existing media documents. We’ve aimed to figure out: how should users represent information to make it possible to enrich with interaction? And how can tools cooperate and coexist within a document as a shared fabric?

Potluck: dynamic plaintext for recipe planning

In Potluck, we explored how users might enrich text notes with dynamic behavior like scaling ingredients and setting timers in a recipe. Users could represent information with any text syntax they found natural, and then write detectors that would parse meaningful structure out of the text.

We found that Potluck could support the creation of many useful tools, and it felt nice to jot down information in any format that felt natural.

Scaling a recipe in Potluck document. The behavior of the scaling slider is specified within the Potluck editor using a formula language.

AI assistance also integrates nicely into Potluck. The AI can draft a set of detectors and computation rules, while preserving the user’s ability to see and edit the generated logic themselves in a live programming environment.

Doubling quantities in a recipe with AI support. The generated detectors and formulas can be directly viewed and edited.

However, one problem with Potluck was that parsing structure from arbitrary plaintext proved cumbersome. We struggled to represent connections between related information (like containment or sequence) without resorting to complex detector rules.

Embark: dynamic outlines for travel planning

In our next project, we decided to try a more structured approach. We built an editor for travel planning documents called Embark, which used a hierarchical outline as the base format. The outline provided some low-level structure that resolved some of the issues with detecting complex patterns in Potluck.

We also added a first-class concept of structured information. An object like a Google Maps location could be “mentioned” and stored within the outline. These objects could then be used as inputs to computations like routing and weather forecasting.

Finally, we allowed rich views like maps and calendars to be embedded in the outline, to visualize and interact with information about the trip.

Computing a driving route in an Embark document. The route calculation draws on context from the surrounding document.

A key takeaway from Embark was that an embedding model with rich shared context enables powerful interactions. The embedded views in Embark are deeply aware of surrounding information—a map view can read and visualize the locations in the outline. The available information depends on local context—you can limit what information is shown on a map by moving it to a different part of the outline. Interactions are also synchronized—hovering on a place in the map highlights it in the outline, and vice versa. The cumulative result of these mechanisms is a cohesive user experience that’s not available in a more restricted embedding scheme, like the one we have in Patchwork currently, or one website embedding another one as an <iframe>.

In Embark, a map can interact with structured data in the outline document.

A major challenge we faced in both Potluck and Embark is navigating the tension between more and less formal representations of information. It’s valuable to be able to express your thoughts in an unstructured way, but computational tools typically benefit from operating on more structured representations. Furthermore, data schemas aren’t limited to user input—Google Maps locations have their own structured format that needs to be usable across various tools.

In our research on Programmable Ink, we’ve explored gradual enrichment over very unstructured data: sketchy drawings.

Finally, it remains to be seen whether the ideas of Potluck and Embark can be generalized further to handle a broader variety of tasks. We grounded each of those projects in the specific use cases of recipes and travel to limit our scope and encourage authentic use, but we plan to try generalizing these ideas further and integrating them on top of a malleable infrastructure foundation such as Patchwork.

Towards a better future

desktop-workspace.jpg

Over the course of this essay, we’ve laid out a vision of a different kind of computing – one that could empower people to craft their own tools, shift power towards local communities, and help people do their best work. We’ve also shared many ideas for how exactly this different kind of computing might come about, from prior art and our own work.

At the same time, we also don’t want to understate the challenges that lie ahead. Enormous effort over many decades has gone into refining application-centric computing, and forging a new path will require grappling with many difficult questions. We’ve covered some of the questions we see as fundamental: How can we create gentle slopes from passive use to active creation? How can we break up applications into composable tools? How can we keep the needs of collaborating groups in focus?

That is still a partial list, and there are big challenges we’ve mostly left out of scope in this piece.

Privacy and security: How do we reconcile the desire for extensible software and interoperability with the reality of bad actors? When untrusted strangers are sharing modifications to existing software that can access sensitive data, dangerous things can happen.

So far, in our own work we’ve focused on collaboration within trusted groups like our coworkers, but we suspect that new computing models may be needed to expand outside that circle of trust. See Bernhard Seefeld’s work for one inspiration.

Business models: How would developers make money from their software if they were shipping composable tools, not monolithic applications? How is support and maintenance paid for?

Culture: How do we cultivate a movement towards personal agency where people want to modify their environments, both digital and otherwise?

These are daunting challenges. Technical capabilities can’t be a full solution; economic and cultural shifts will also be required. But change is possible—computing is still young, it has changed a lot in the past decades, and surely many structural shifts still lie ahead.

Many different kinds of people can play a role. If you are a computing researcher, it’s a ripe time to reimagine the foundational metaphors of computing to put more power in users’ hands. If you are a platform developer, consider tipping the balance towards seeing end-users as capable participants rather than passive users that need to be protected at all costs. Security and ease of initial use are virtues, but extensibility and power are as well. And if you make software products, consider how you might empower your users to take matters more into their own hands, rather than dictating every decision. While we believe radical change is needed to fully realize malleable software, incremental improvements are helpful too.

When the people living or working in a space gradually evolve their tools to meet their needs, the result is a special kind of quality. While malleable software may lack the design consistency of artifacts crafted behind closed doors in Palo Alto, we find that over time it develops the kind of charm of an old house. It bears witness to past uses and carries traces of its past decisions, even as it evolves to meet the needs of the day.

Everyone deserves the right to evolve their digital environments. It’s an important way to fulfill our creative potential and maintain a sense of agency in a world that is increasingly defined in code. We hope you’ll join us in making malleable software a reality.

The Daily Front Page 14 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Chat Without a Centre
article

Parley: Federated, decentralised chat that speaks plain IRC

by davidcollantes·▲ 312 points·172 comments·git.mills.io ↗
Parley is a chat network with no centre.

Federated, decentralised chat that speaks plain IRC.

Parley is a chat network with no centre. Every person (or team) runs a small instance for their own domain. Instances find each other through DNS and well-known identity documents, exchange signed messages over HTTPS, and present the whole federated network to ordinary IRC clients such as irssi, WeeChat or Textual, with no plugins.

Identities look like email: alice@foo.com runs on foo.com, bob@bar.com on bar.com. Bob types /msg alice@foo.com hi and it just works, even if the two instances have never heard of each other before.

Status: working proof of concept. It demonstrates the design end to end and runs a real instance, but it is not hardened yet. See Limitations.

It works with the client you already have

Two instances (foo.com and bar.com), two stock irssi sessions.

Alice connects to her instance; Bob connects to his:

Alice connects to foo.com Bob connects to bar.com

Bob opens a query with /msg alice@foo.com and the two instances federate on the spot. Alice sees Bob as bob on bar.com; Bob sees Alice as alice on foo.com:

Alice's query window with bob@bar.com Bob's query window with alice@foo.com

Both join #lobby, a global channel replicated across their instances:

Alice in #lobby Bob in #lobby

What it does

  • Ordinary IRC in front. Connect with any IRC client. Log in with PASS or SASL PLAIN using your password or an IRC token. IRCv3 server-time, message-tags, echo-message, multi-prefix and setname are offered to clients that want them, and TAGMSG relays client-only tags such as typing indicators, across the federation as well as between clients here. Tags on a message itself are kept, so a +reply is still a reply when it comes back out of history, and draft/multiline makes a pasted paragraph one message rather than eight.

  • Scrollback that follows you rather than your client. CHATHISTORY pages through channels and private messages alike, a join replays what you have not been shown, and draft/read-marker puts where you have read up to on the account, so marking a channel read on your phone clears it on your desktop and a client is told where to draw the line as soon as it joins.

  • Accounts you can manage while it runs. Accounts live in the instance's data directory, not in a config file. Create them with parleyctl, the admin page, the HTTP API, or let people arrive through single sign-on: any OpenID Connect provider, or identity headers from a reverse proxy. People mint IRC tokens for their clients on their settings page; bots are accounts with the bot role.

  • Discovery via DNS + WKID. _parley._tcp.<domain> SRV points at the instance; https://<host>/.well-known/parley/instance.json publishes its ed25519 public key and inbox; /.well-known/parley/<user>.json confirms a user exists. This mirrors how Salty IM finds people.

  • Signed HTTP federation. Every event is a JSON document POSTed to the peer's /inbox, with a detached ed25519 signature in headers. Receivers verify against the key they discovered themselves. Federation is open: any instance whose signature checks out can talk to you.

  • Automatic peering. Message someone on a new domain and the two instances link up on their own. Linked instances exchange the peers they know (gossip), so a mesh forms without configuration.

  • Two kinds of channel.

    • #dev is global, replicated across every linked instance with members in it. Nobody owns it, so it has no topic and no operators.
    • &notes is local: it never leaves the instance, is invisible to peers, and is the one place a topic exists.
  • Moderation without channel ownership. Nobody can be kicked out of a channel nobody owns, so /ban becomes a block list by mask: /ban quark@example.com for one person, /ban *!*@example.com for a whole instance. Yours covers your account; an admin's covers the instance. Peering itself is controlled with parleyctl peers.

  • Addresses map onto ordinary IRC identity. A user's nick is the bare local part and their instance is the host, so alice appears as alice!alice@foo.com -- prefixes, NAMES, WHO and WHOIS all agree, and a nick you see in NAMES is one you can message. /whois alice@foo.com consults her instance's WKID document.

  • History that survives downtime, and is searchable. Each instance keeps its channel history in SQLite with a full-text index (parleyctl search) and serves it at /channels/<name>/feed. When a peer comes back after an outage it pulls what it missed, and clients get recent history replayed on JOIN.

Quick start (two instances on one machine, no DNS)

git clone https://git.mills.io/prologic/parley.git && cd parley
make build

# Alice's instance for foo.com
./parleyd -domain foo.com -irc 127.0.0.1:6667 -http 127.0.0.1:8080 \
  -endpoint http://127.0.0.1:8080 -data ./data/foo -admin-token foo-admin \
  -insecure -resolve bar.com=http://127.0.0.1:8081

# Bob's instance for bar.com
./parleyd -domain bar.com -irc 127.0.0.1:6668 -http 127.0.0.1:8081 \
  -endpoint http://127.0.0.1:8081 -data ./data/bar -admin-token bar-admin \
  -insecure -resolve foo.com=http://127.0.0.1:8080

# One account on each
./parleyctl -endpoint http://127.0.0.1:8080 -token foo-admin accounts create alice -password secret
./parleyctl -endpoint http://127.0.0.1:8081 -token bar-admin accounts create bob -password secret

Then, in two terminals:

irssi -c 127.0.0.1 -p 6667 -n alice -w secret
irssi -c 127.0.0.1 -p 6668 -n bob -w secret
/join #dev                       # both
/msg #dev hello                  # bob sees "<alice> hello", host foo.com
/msg alice@foo.com psst          # direct message across instances
/join &notes                     # local to this instance, never federated
/whois alice@foo.com

-insecure and -resolve exist only for local development. In production each instance has a real domain, a TLS certificate, an SRV record, and finds peers via DNS.

The real thing: DNS + TLS demo

demo/ brings up CoreDNS (authoritative for foo.com and bar.com, with _parley._tcp SRV records), a local demo CA, and both instances in Docker, then runs scripted IRC sessions and prints the evidence:

make demo        # or: demo/demo.sh
make demo-down

See demo/README.md.

Running your own instance

The container image is prologic/parley, and docker-compose.example.yml is a starting point. An instance for example.com, reachable at chat.example.com, needs:

  1. A place to run it, with /data on persistent storage (it holds the instance key, the peer cache, the channel logs and the accounts):

    docker run -d --name parley -v parley-data:/data \
      -p 6667:6667 -p 8443:8443 \
      -e PARLEY_ADMIN_TOKEN="s3cret" \
      prologic/parley -domain example.com -endpoint https://chat.example.com
    

    Then create accounts with parleyctl (it is in the image too) or the admin page:

    docker exec parley parleyctl -token s3cret accounts create alice -password hunter2
    docker exec parley parleyctl -token s3cret tokens create alice -label irssi
    

    Without an admin token and with no accounts yet, parleyd logs a one-time /setup URL that creates the first admin in the browser. Single sign-on through OpenID Connect or a reverse proxy's identity headers is described in docs/AUTH.md; SSO users mint IRC tokens for their clients on their settings page.

  2. HTTPS in front of port 8443 on chat.example.com. Any reverse proxy that terminates TLS will do; parleyd itself serves plain HTTP unless you give it -tls-cert and -tls-key.

  3. An SRV record so other instances can find you:

    _parley._tcp.example.com.  IN SRV 0 0 443 chat.example.com.
    

    Without it, peers fall back to https://example.com/.well-known/parley/.

  4. IRC over TLS for your clients. parleyd's IRC listener is plaintext, so terminate TLS in front of it. With Caddy's layer4 module, for example:

    layer4 {
        0.0.0.0:6697 {
            @parley tls sni chat.example.com
            route @parley {
                tls
                proxy 10.1.2.3:6667
            }
        }
    }
    

    Then, in irssi: /connect -tls -tls_verify chat.example.com 6697 <password-or-token> alice.

    The port here is whatever your proxy listens on. If it is not 6697, start parleyd with -irc-port (and -irc-host, if IRC is on a different name to the endpoint), or set PARLEY_IRC_PORT / PARLEY_IRC_HOST:

    parleyd -domain example.com -irc-port 6687
    

    The landing page, the settings page, parleyctl and the instance document all print a connect line from it, and the settings page prints a live token on that line. A wrong port under a right hostname still passes certificate verification, so the token would go to whatever else is listening there.

  5. Check it from the outside. parleyctl check probes an instance the way a peer does — SRV record, well-known documents, the advertised endpoint, the inbox, and the IRC TLS port — and says what to fix:

    $ parleyctl check alice@example.com
    ok    dns         _parley._tcp.example.com -> chat.example.com:443
    ok    well-known  https://chat.example.com/.well-known/parley/instance.json (parleyd/v0.2.0)
    ok    domain      example.com
    ok    key         ed25519 uPMn03bl2/qHh9X0B3Fn98yiWo7VS6Z9UHXJ7P8bO2E=
    ok    endpoint    https://chat.example.com is live
    ok    inbox       https://chat.example.com/inbox rejects unsigned events
    ok    user        alice@example.com exists (account)
    ok    irc-tls     chat.example.com:6697: chat.example.com, issued by E7, 89 days left
    

    It needs no token and works against anyone's instance, so it is also how you tell a peer what is wrong with theirs. The common failure is a missing SRV record: the instance is perfectly reachable at its own host, but nobody resolving the identity domain can find it. Add -resolve https://chat.example.com to probe the host directly while DNS is still wrong, and -json for a machine-readable report. It exits non-zero if any check fails.

How it fits together

 irssi ──IRC──▶ parleyd (foo.com) ◀──signed HTTPS──▶ parleyd (bar.com) ◀──IRC── irssi
                 │  /.well-known/parley/*.json                 │
                 │  /inbox   /channels/<name>/feed             │
                 └──── DNS: _parley._tcp.bar.com SRV ──────────┘
  1. Bob's client sends PRIVMSG alice@foo.com :hi.
  2. bar.com looks up _parley._tcp.foo.com, fetches the instance document from the host it names, and caches the key.
  3. bar.com signs the event and POSTs it to foo.com's inbox.
  4. foo.com discovers bar.com the same way to verify the signature, delivers the message to Alice's clients, and since bar.com is a stranger, sends a hello back. Both sides now exchange channel rosters and peer lists.

The wire format is documented in docs/PROTOCOL.md.

Configuration

There is no config file. Configuration is in two places and each thing is in exactly one of them.

Flags, each with an environment variable, for what the process needs before it can open its database, what describes the machine and network it sits on, and the secrets and trust decisions about who may assert an identity. A flag wins over its variable. Only -domain is required.

flag env meaning default
-domain PARLEY_DOMAIN identity domain this instance serves required
-data PARLEY_DATA_DIR identity key, databases, peer and membership state ./data
-endpoint PARLEY_ENDPOINT advertised base URL https://<domain>
-irc PARLEY_IRC_LISTEN IRC listener (plaintext; terminate TLS in front) :6667
-http PARLEY_HTTP_LISTEN HTTP(S) listener for the web UI, discovery, inbox and feeds :8443
-irc-host, -irc-port PARLEY_IRC_HOST, PARLEY_IRC_PORT where clients reach IRC over TLS endpoint host, 6697
-tls-cert, -tls-key PARLEY_TLS_CERT, PARLEY_TLS_KEY serve HTTPS directly off
-admin-token PARLEY_ADMIN_TOKEN bearer token for the admin API and parleyctl off
-admin (repeatable) PARLEY_ADMINS nicks that are admins regardless of their stored role none
-seed (repeatable) PARLEY_SEEDS peer domains to link with at startup none
-irc-proxy (repeatable) PARLEY_IRC_PROXIES CIDRs allowed to prepend a PROXY header to an IRC connection none
-http-proxy (repeatable) PARLEY_HTTP_PROXIES CIDRs whose X-Forwarded-For the web listener believes none
PARLEY_TRUSTED_PROXIES and PARLEY_TRUSTED_* identity headers from listed proxies (see docs/AUTH.md) off
PARLEY_OIDC_* OpenID Connect provider (see docs/AUTH.md) off
HAVEN_SOCKET Home Cloud app socket for household sync off
-ca, -insecure, -resolve, -debug PARLEY_DEBUG local development off

Settings, in the database, for everything an administrator might change while the instance runs. They take effect the moment they are saved, with no restart, and have no flag and no environment variable. Change them on the admin page, through PUT /api/v1/settings (docs/API.md), or with parleyctl:

parleyctl settings list                  # every setting, * where it differs from its default
parleyctl settings set history_replay 50 max_conns_per_addr 8
parleyctl settings reset motd            # back to the default
parleyctl settings export > settings.json
parleyctl settings import settings.json  # also reads an old config.json

Only what differs from the defaults is stored, so an upgrade that changes a default changes it for every instance that never touched that key.

setting meaning default
motd message of the day (empty means the built-in text) built-in
history_replay messages replayed on JOIN (channels and DMs alike), unread DMs on login, and the backlog a second client attaching to the same account is shown 50
history_retention how long channel and DM history is kept (-1 forever) 8760h
message_rate, message_burst how much one account may say: messages per second, and how many at once. A rate of 0 is no limit. Bots are exempt 1, 20
max_conns concurrent IRC connections to the instance (-1 unlimited) 1024
max_conns_per_account concurrent IRC connections per account (-1 unlimited) 8
max_conns_per_addr concurrent IRC connections per client address (0 off) 0
federation.policy open, or allowlist to federate only by invitation open
federation.inbox_rate, federation.inbox_burst inbox deliveries per peer and per address 20, 200
federation.feed_rate, federation.feed_burst feed reads per address 2, 20
federation.catch_up_window how far back a reconnecting instance asks for 168h
auth.local show the username/password login form true
auth.auto_link a first SSO login may claim an unlinked local nick true
auth.session_ttl web login lifetime 720h
auth.rate_limit.* login rate limiting (see docs/AUTH.md) on
metrics_public serve /metrics without authentication false
network_name what this instance calls itself, on IRC and on the web (empty means the domain on IRC, "Parley" on the web) empty
theme_color the colour a phone tints its browser bar with, as #rrggbb built-in
operator who runs this instance, shown in the web footer empty

People set their own picture under Settings in the web interface, or it comes from their identity provider's picture claim at login and is re-hosted here. It is published to IRC clients as the IRCv3 avatar metadata key and to other instances in the well-known user document; see docs/PROTOCOL.md.

The instance's logo is not in this table, because it is not text: upload one PNG of at least 512 pixels along its longest side under Settings -> Logo in the admin page and Parley derives the favicon, the home-screen icon and the square an IRC client shows beside the network. A square is ideal, and a wordmark is fine -- anything up to three times as long as it is tall is centred on a transparent square rather than refused. Until then every instance shows Parley's own icon, which is why two of them look alike in a client's network list.

Chat help. /help (or /quote HELP <topic>) serves the pages in help/*.txt, which are compiled into the binary. Edit a page and rebuild to change it; the first line is its title. A new file is a new topic -- list it in help/index.txt, which make test checks.

Endpoints: /healthz for liveness, /api/v1/status for a JSON status of peers and channels, /metrics for Prometheus, and the API in docs/API.md.

Upgrading from a config file. parleyd -config config.json no longer reads the file: it prints, for every key in it, the flag, variable or setting that key has become, and exits. Move the process-level keys to your unit file or compose file, start the instance, then parleyctl settings import config.json applies the rest in one go and names what it skipped.

Real client addresses behind a TCP proxy

With TLS terminated in front of the IRC listener, every client arrives from the proxy: the logs name the wrong host, and per-address limits either do nothing or lock everybody out at once. List the proxy in irc_proxies and it must then prepend PROXY protocol header (v1 or v2) to each connection.

This is two changes, and neither works alone. Listing a proxy that does not send a header drops every connection from it; sending a header from an address that is not listed feeds it to the IRC parser as garbage. There is no safe order, so change both together and be ready to put both back.

The default is empty, which is the whole thing switched off. 127.0.0.1/32 below is an example, not a default -- substitute the address your own connections actually arrive from:

parleyd -irc-proxy 127.0.0.1/32         # repeatable
PARLEY_IRC_PROXIES=127.0.0.1/32         # comma- or space-separated

Note the name: PARLEY_TRUSTED_PROXIES is the web listener's equivalent and a different decision entirely.

To find the address to list, connect once and read the log. Every client address is reported the first time it is seen:

level=INFO msg="irc: new client address" addr=203.0.113.9 trusted_proxy=false

Behind a proxy every client shares one address, so that is a single line naming exactly what belongs in irc_proxies. It is always the address on the socket, never the one a header carries -- the header address could never match the list, so reporting it would hand you a value guaranteed to fail. Once the proxy is listed and sending headers, the line reappears for it with trusted_proxy=true, which is the confirmation that the two halves now agree.

Only listed addresses are believed, and a connection from one of them that does not carry a header is dropped rather than treated as a direct connection -- accepting both shapes from the same place hands back the address forgery the header exists to stop. Those drops are counted in parley_irc_proxy_rejected_total, which is the metric to watch while making the change.

The web listener has the same blindness and its own setting. Behind a reverse proxy every request arrives from that proxy, so the per-address gates on web login, the federation inbox and feed reads all share one bucket -- a global rate limit wearing a per-address name. List the proxy in http_proxies and X-Forwarded-For is believed from it, and nothing else changes.

Use that rather than auth.trusted_headers.proxies, which looks like it would do the job and does far more: a proxy on that list may assert who the user is, so a request to /login carrying Remote-User is logged in without a password. Fixing a rate limit is no reason to turn on passwordless login. The identity list does imply the address one, since a proxy trusted that far is not one to doubt about an address.

The step-by-step version, including the order that costs one outage instead of two, is in docs/PROXY.md.

With real addresses in hand, max_conns_per_addr becomes safe to turn on, and turning it on also applies the per-address login bucket to IRC. Leave it at 0 while the listener sits behind an unlisted proxy: every client shares one address there, so the cap would not limit anybody in particular, it would lock out everybody at once. It is a setting, so turning it on is parleyctl settings set max_conns_per_addr 8 and needs no restart. The per-account login backoff applies either way -- see docs/AUTH.md.

Metrics

/metrics serves the Prometheus text format: connections, accounts online, channels, peers linked, and counters for pushes, inbox events, feed reads, tag messages and what was refused. It needs an admin token by default, since how many people are on an instance is the operator's business; set the metrics_public setting to serve it openly. Every sample is a count -- no nicks, no channel names, no peer domains.

Back up the instance key

<data_dir>/identity.key is the one file that cannot be regenerated. The domain's identity is the keypair: lose it and every peer that has cached the old public key refuses the instance, and the only fix is a new key that everyone has to re-trust. Back it up on the host, off the host:

parleyctl key show                      # public key and fingerprint
parleyctl key export -y > instance.key  # the secret; keep it somewhere safe
parleyctl key import < instance.key     # restore into an empty data dir

If the key ever leaks, replacing it is a supported operation rather than a disaster:

parleyctl key stage                     # generate the next key and publish it
parleyctl key promote -y                # ...then, once peers have re-read it, sign with it
parleyctl key rotate -now -y            # a leaked key: replace it at once, no grace period

Peers recover by themselves. A signature they cannot verify makes them re-read the instance document once, which is where they find the new public key, so the cost is one failed request each -- and if that request was a hello, a few minutes of backoff before they try again. The old key is kept as identity.key.<fingerprint>.bak because the only unrecoverable mistake here is replacing a key you still needed. Restart parleyd afterwards to serve the new one.

These read and write the data directory directly rather than going through the API, because an admin token must never be able to fetch the private key over the network. Run them on the instance host, with -data-dir or PARLEY_DATA_DIR pointing at the data directory.

Upgrading

Nothing to run: the database gains its new tables on first start and the old ones are untouched. What follows is the handful of things that changed under you, newest first.

To v0.6.0

How much one account may say is now bounded. message_rate (1 a second) and message_burst (20 at once) apply to everybody but bots, keyed by the account, so a person's clients share one budget. A refused message is answered 439 naming the target and is delivered nowhere. Every instance before this had no bound at all, so if yours has a room busier than that, raise the numbers or set message_rate to 0, which is the old behaviour:

parleyctl settings set message_rate 0

It is a setting, so it lands without a restart.

To v0.5.0

Somebody on another instance is alice:foo.com, not alice/foo.com. The separator was borrowed from draft/relaymsg, and it was the wrong half of the convention to copy: a strict client guards against mistaking a server name for a nick by requiring both a . and a : or neither, and a name with a domain has a dot and no colon. Such a client read the whole prefix as a server name and dropped every JOIN, PART, QUIT, NICK and AWAY from a remote user, while PRIVMSG degraded quietly -- which is why chat looked fine and no roster ever updated. PARLEYSEP in ISUPPORT says which character is in use, so a bot should read it from there rather than hardcode one.

The trap while a network is mid-upgrade: mention text crosses federation as bytes. Somebody on a peer that is still on / types alice/foo.com, and it does not match anything here until they upgrade. Tell your peers rather than letting them find it.

A reaction sent to a peer older than v0.5.0 is lost, not queued. Those versions answer an event type they do not implement with a 422, and a refusal is final to the sender's outbox: the event is dropped and the sender is told the send failed. From v0.5.0 on, an unimplemented type is answered 200 {"unsupported": true} instead, so this is the last change that has to wait for the whole mesh. Reactions between people here, and between upgraded instances, are unaffected.

GET /api/v1/status no longer publishes channel rosters. It is the only unauthenticated endpoint, and it was naming every member of every global channel -- our peers' users included, on their behalf, when their own landing page publishes counts and never names. A channel still carries name, a members count and on, the other domains with members in it. Nothing in federation read it: peers exchange members in signed hello snapshots.

history_replay now defaults to 50, up from 20. Only settings you have never set follow a default, so an instance that has chosen a number keeps it.

From a version that took -user or PARLEY_USERS

Those are gone. Start the new version, then import the old list once:

echo "alice:s3cret,bob:hunter2" | parleyctl -token <admin token> import

Project layout

cmd/parleyd          the daemon
cmd/parleyctl        command-line client for the HTTP API
internal/accounts    accounts, IRC tokens and web sessions (SQLite)
internal/auth        identity providers: OpenID Connect, trusted headers
internal/config      configuration
internal/homecloud   Home Cloud app integration (household sync)
internal/identity    ed25519 instance key, request signing/verification
internal/discovery   DNS SRV + well-known resolution with caching
internal/protocol    wire types: documents, events, hashing
internal/store       append-only channel logs, peer cache
internal/server      IRC front end, federation inbox/outbox, channel state, HTTP API, web UI
internal/web         HTML templates (HTMX + DaisyUI + Tailwind)
demo/                CoreDNS + Docker Compose demonstration
homecloud/           Home Cloud catalog manifest
help/                the chat HELP pages, embedded at build time
docs/PROTOCOL.md     the federation protocol
docs/API.md          the HTTP API
docs/AUTH.md         login, single sign-on and tokens

make test runs in-process end-to-end scenarios covering global and local channels, direct messages with automatic peering, peer exchange, catch-up after downtime, signature rejection and IRC basics.

Limitations

Known gaps, roughly in the order they should be closed:

  • Instance-level keys only. Per-user keys and end-to-end encryption (Salty style) would layer on top.
  • No channel modes and no channel operators, which is a decision rather than a gap: a global channel is owned by nobody, so there is nobody to be an operator of it. Blocking is per person and per instance instead — see /ban above.
  • Nicks are bound to accounts; there is no /nick.
  • Global channels are eventually consistent and have no topic authority.
  • Feeds are served unauthenticated (they are public logs, like twtxt).
  • There is no web chat client, on purpose. The web interface is for administering and configuring an instance; chatting is a client's job, and Parley is the server every IRC client already talks to.

Roadmap ideas

  • Per-user keys published via WKID, with encrypted DMs.
  • More of IRCv3 where clients render it: message redaction, and the rest of the user metadata registry.

License

MIT, see LICENSE.

The Daily Front Page 15 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — The Secret Comment Section
article

Kids turned low-traffic NPR Spotify comments into a secret group chat

by simonpure·▲ 333 points·196 comments·thisamericanlife.org ↗
This American Life is produced for the ear and designed to be heard.

Note: This American Life is produced for the ear and designed to be heard. If you are able, we strongly encourage you to listen to the audio, which includes emotion and emphasis that's not on the page. Transcripts are generated using a combination of speech recognition software and human transcribers, and may contain errors. Please check the corresponding audio before quoting in print.

Prologue: Prologue

Ira Glass

Dave Blanchard runs the public radio show Wild Card. And one of the less exciting and, in fact, rather tedious parts of his job is that he has to keep an eye on the comments that people post about the show online. And one day last fall on Spotify, he saw all this activity about this episode they did with the writer Elizabeth Gilbert. And Dave thought, oh, her book was controversial. It must have struck a nerve, this episode. And then he looked at the comments.

Dave Blanchard

And it was just, like, gibberish. There was a bunch of new comments, but I couldn't make heads or tail of any of them. They're just these clipped, weird, incoherent postings that I was just like-- it screamed bots, just because anytime that I see just gibberish in a comment on the internet, I assume it's a bot. But the fact that they were all from different accounts seemed very weird. And the fact that they also maybe seemed to be interacting in some way also seemed weird and not like typical bot behavior.

Ira Glass

Can I ask you to read some of those comments?

Dave Blanchard

So yeah, I've got some from a later batch. We've got some where it's like, someone says, "Ah, OK, M-H." And two people have hearted that. Someone says, "Gilgamesh quit and I'm crying." "Last Friday I broke up with my GF." "Your cats are so cute." "You're gorgeous in that dress. OML, pink heart."

Ira Glass

So OK, bots, he thought, some newfangled kind of bots that respond to each other somehow. He deleted the posts.

Dave Blanchard

And I went back to the Spotify comments again. And there was a new comment that said, uh, so it deleted my com. And that felt not botty. That felt very strange that a bot would be able to recognize that the thread got deleted and post it, letting people know that it had been deleted.

Ira Glass

And then there were other responses to that.

Dave Blanchard

So someone says, username cotton/amity, parentheses, I'm back, bitches, commented, "Weird." Aubrey commented, "That's weirdss," two S's.

Ira Glass

This is really not looking like any bot behavior he'd ever seen. So he goes to NPR's Slack channels, post some screenshots, describes what these comments are. And one of the higher-ups, Matilde, suggests reporting it to Spotify, which Dave does. And then somebody younger at NPR reads the thread. They're 10 years younger than Dave-- Gen Z, not millennial, named Hannah Chinn.

Hannah Chinn

And I click into the screenshots, and almost immediately I'm like, oh. My conclusion is really, really different than Dave's and Matilde's, because I'm like, these are kids. And I think that part of that is because I was a middle schooler on the internet, posting on forums and stuff.

And so I look at their display names. Their display names are, like, Ella with five emojis. And they're the special character emojis. They're the ones that you have to go onto the internet and type your name into a special text generator, and then it comes out as a special character, and then you have to special paste it into your profile.

Ira Glass

Their profile pictures are all cartoon characters Hannah's never seen before. And then there's the way that they're commenting back and forth with each other, short little phrases. I'm sorry. That's weird. Lots of hi's, lots of extra exclamation points. Hannah recognized it. They grew up in a conservative home, was homeschooled, with limited access to social media.

Hannah Chinn

And so I was a kid who used weird parts of the internet not as they were originally designed to talk to my friends. I talked back and forth with my friends on Google Docs. And we would type things and then delete them, and then type things and then make them invisible by making the text white on the white background. So I think this is familiar behavior to me.

Ira Glass

So Hannah writes out a comment to post on Slack, shows it to their housemate before posting because they're worried about coming off maybe too harsh with these much higher-ranking, older NPR bosses who Hannah had never met in person.

Hannah Chinn

And I say, OK, maybe I'm wrong, but I think these are just kids hanging out and we shouldn't report them as bots. My guess is that they're just using Spotify comment threads as their group chat, maybe because other apps on their phones are blocked. Who knows? And they happen to have chosen a wild card episode to do it, LOL. These are middle schoolers.

Ira Glass

Middle schoolers specifically, not high schoolers?

Hannah Chinn

Yeah, these are people who are new to chatting with each other on the internet and in real life. They're kids who are excited to talk to other people on the internet. The goal is just to connect with people. You have nothing to talk about. You don't know each other very well. You're just seeing each other and acknowledging each other's presence in the chat.

Ira Glass

Dave reads Hannah's Slack message. And, well, he is not convinced. He posts--

Dave Blanchard

That's an interesting theory.

Ira Glass

Yeah, that's an interesting theory. There's an exclamation point at the end of it, at least to give it that much credit.

Dave Blanchard

Yes. Admittedly, I was still like, really? Again, this is Wild Card with Rachel Martin on NPR-- not our target demo to have a bunch of middle schoolers in our comment section. It just felt so completely implausible that these people would have found this particular episode as their place to chat.

Hannah Chinn

Dave is like, oh, that's an interesting theory. And I, at this point-- sorry, Dave. I don't know you in real life. I'm a little bit annoyed. Because I'm like, I know that I said "maybe I'm wrong," but I was so sure that I was right.

Ira Glass

Hannah does more digging, which makes them even more convinced than before. What the kids seemed to be doing was one kid would create a playlist on Spotify with a name like "Let's chat here." And inside that playlist would be one podcast episode.

And you know how you can see other people's playlists on Spotify if they make them public? Other kids would see that playlist. They'd see the episode. And then they would go to the podcast episode and start posting in the comments.

Hannah got back on Slack and pointed out that the kids were using a playlist that was named New Chat. The kids had also posted a Google Form with some kind of quiz on it and said, "Fill this out. Only cool people can fill this out."

Hannah Chinn

Bots don't really spam Google Forms in my experience, whereas Gen Alpha might use them in the same way that my generation would use uQuiz or the BuzzFeed Make Your Own Personality Quiz feature.

Ira Glass

And reading that was the turning point for Dave.

Dave Blanchard

When they were like, this is something that I did, that's what unlocked it. I think it was so implausible to me. And then when Hannah was like, no, I did this, I was like, oh, wow. I guess it makes sense.

And then it was like, I could go back and look at it again. And it was like, I had the lens on to see it. And I was like, oh, my god, they are kids. In retrospect, it looks so obvious.

Ira Glass

So how exactly did those commenters end up in the comment section of an NPR podcast? What exactly happened here? Well, we reached out to a bunch of the commenters. Only one of them agreed to talk to us.

As suspected, she is not a bot. She's a 14-year-old girl who talked to me from the car with her parents' permission and her dad at the wheel. Her name is Ella. When I asked her to describe herself, she said this.

Ella

I would say that I'm definitely a bit hard to get to know because I don't know a lot about myself yet. But I think if you do get to know me, you'll find out I'm a pretty cool person.

Ira Glass

Ella says this all started with a video podcast that played TikTok videos. Ella thinks a kid started it. The video seemed to be chosen specifically for kids who weren't allowed on TikTok, but were allowed on Spotify. That was Ella. She was allowed on Spotify, but on no social media. And she and the other kids would watch this girl's podcast on Spotify and then chat in the comments of the podcast.

Ella

And her podcast ended up getting banned. And we wanted to keep talking to each other, so people would make playlists.

Ira Glass

She described exactly the system that Hannah figured out. Kids would name their playlist "chat here" or something like that, and then there'd be some podcast, and everybody would go to that podcast and talk in the comments. She says it was maybe 20 kids in the core group-- lots of theater kids, she says, mostly girls, most of them with strict parents who didn't let them on regular social media.

Ira Glass

And can I ask, why did you guys pick NPR shows to be the ones where you went to in the comments?

Ella

I think we just looked for podcasts that didn't have many comments.

Ira Glass

I see. So you picked NPR because it didn't seem very popular.

Ella

Yeah, so that we wouldn't get caught up in other people's comments.

Ira Glass

I tell you, buddy, I do a public radio show, and that hurts a little to hear it.

Ella

[CHUCKLES]

Sorry.

Ira Glass

That's OK. Are your parents NPR listeners?

Ella

Yeah, my mom is. She listens to podcasts all the time.

Ira Glass

Was any of this that your parents were NPR listeners, and this felt like this is the perfect cover? Like, if they catch you doing this, you can be like, look, I'm just doing this for an NPR show.

Ella

Yeah.

Ira Glass

Is that true? Did you think about that?

Ella

Yeah, a little bit.

Ira Glass

It's funny. There was this guy named Dave who works for NPR, and he's in his 30s. And he saw the comments that you guys were doing. And they made no sense to him at all. He really had no idea what they were. And he thought you guys were all bots.

Ella

Yeah. Some of them were really young, like 11 years old and stuff. So some of them definitely were a little bit not good at talking English that well. Or using slang.

Ira Glass

I got to say, I thought that was a very generous answer. Dave thought they were bots. And she was like, yeah, well, some of us kind of talked like bots. Ella told me she's sure someday she'll be clueless like Dave is now, which, of course, isn't much comfort if you're Dave. Dave says that once he understood that it was kids writing all those comments, it didn't feel great.

Dave Blanchard

One, I felt bad for having reported them. I definitely felt guilty. And two, old. I just felt very old, very dumb, very out of touch. I literally needed Hannah to be my generational translator. It was such a clarifying realization of my age and obsolescence.

Ira Glass

Well, today on our program, people from one generation trying to cross the vast, vast distance that divides the young and the old with a message that they hope will get heard by the people on the other side. We have stories today of a wedding toast and of childhood hair care, and of the greatest job in the world, as seen from the eyes of a teenager, anyway. Intergenerational space travel this hour. From WBEZ Chicago, it's This American Life. I'm Ira Glass. Climb aboard this rocket with us, if you dare, and stay with us.

Act One: The Wedding Zinger

Ira Glass

It's This American Life. Act One-- The Wedding Zinger. So let's start today with a story that is both intergenerational space and time travel. When Courtney Maum was 18, her mom got remarried. Courtney despised the guy, did not want the marriage to go through. But she was her mom's maid of honor, and she gave a speech at her mother's request.

And the speech she gave at 18 years old, her mom never forgave her for it, brought it up for years after. And then recently, after three tumultuous decades, her mom's relationship with this man fell apart. For Courtney, this was the opening, the chance to finally ask her mom across the divide between them about this marriage she never understood, and to try one more time to lay this infamous wedding speech to rest. Here's Courtney.

Courtney Maum

At 18, I thought I was kind of hot stuff-- a writer in the making, a die-hard feminist, a student capable of bringing freedom to Tibet. Here's how my mom Linda saw me.

Linda Maum

What I remember is at that point in your life, you were extremely selfish. And you didn't want anybody else in my life. You asked me not to even date until after you went off to college, and certainly not even think of getting married before that.

Courtney Maum

Is that true? I'm sure it's true. The thing is, I loved being with my mother. Everybody did. I didn't want to share her.

She was fun, beautiful, stylish, like a woman out of Knight Rider. She had a Harley-Davidson and a boating license. We were always on adventures. In the summer, I loved to watch her steer our little Boston Whaler, wearing these massive dangly earrings that sparkled in the sun. It was a fairy tale existence, a childhood of privilege, growing up like this in Greenwich, Connecticut, with parents I adored.

But when I was eight and my brother Brendan was three, my father asked my mom for a divorce. My mother was devastated. But like I said, she was a hot item. So the suitors came a-calling.

I can't say I was a fan. One laughed like a hyena. One was so heartsick with love for her, his longing made everyone embarrassed for him, my mother included. There were others, also memorable.

Courtney Maum

Do you remember the man who whipped out a ventriloquist doll at Benihana's?

Linda Maum

Yeah. Who the hell was that? But that was one date.

Courtney Maum

We go into the Benihana's, and he's already seated. And this is family-style seating. So we're sitting with strangers. And we sit down.

And course number one-- you know when they do the little joke and they flip the shrimp into people's mouths? This guy pulls a ventriloquist doll from out under the table, and he's like, give me some of that shrimp! Remember? Brendan was, what, six years old. We were dying. The whole table was like, no. No, this isn't it.

Linda Maum

Brendan liked it. He liked it.

Courtney Maum

Well, he probably stopped liking it once I rained on everyone's parade, but you know. And I remember going to the parking lot with you, and I was like, never again. Mom, that guy, never again.

Linda Maum

And it was. Never again, never again.

Courtney Maum

There was one final suitor, the man my mom would marry when I was a senior in high school. My mother has asked me to refer to him as Mr. X in this story. I didn't trust Mr. X from the start. He seemed to show up out of nowhere with no comprehensible backstory, like he was born out of the ether.

One day, he pulled into our driveway in a rundown car and never left again. The old suitors had been annoying, but they were innocent. Mr. X was different. He put me on edge. He claimed he was an architect, but he never seemed to have any work. And he appeared to have no friends.

I bugged my mom about his past. She explained she'd met him years before when she was pregnant with me, that he'd been part of a crew working on a renovation to the house my parents lived in. Whenever she told this story, I imagined my unborn self kicking from within her body, kicking in his direction, saying, no, not him, no. But I'd never heard the full story of their meeting until now. It happened back when my mother was still married to my father, Bob.

Linda Maum

So I was just redoing the house, and I hired him as an architect or a builder, or whatever I thought he was. So here I was. I was pregnant. And he came into the driveway for me to interview him.

He drove in in an old, beat-up car, but he was so adorable, and he was also six years younger than I was. So at that point, that's a big difference between 30 and 24. That's a huge difference. And I interviewed other people, and I decided because he was cheaper, for one-- and I had a little-- he's so cute-- never in my life ever thinking I'd ever cheat on Bob, but you know, imagining.

So I remember in this one point, there was a bathroom in one of the guest rooms. And we were debating putting a skylight in it. And I got in the bathtub to show how high the ceiling had to go, and he got in behind me.

Courtney Maum

Oh, boy. We're going to have a Ghost moment here.

Linda Maum

No. And I just remember thinking, why did he get in so close to me? I don't remember. Why did he do that?

Anyway, the end of the story is that he got in a car accident. A car hit him. He almost lost his leg. So obviously, he took off with the money.

Courtney Maum

The money she'd already paid him.

Oh, God. I didn't know this part of the story.

Linda Maum

So I had to go to court and prove that he had indeed been paid. So that put a very bad taste in my mouth.

Courtney Maum

When my producers contacted him, Mr. X remembered the story differently. He said the car accident happened before he met my mom and that he didn't run off with the money, that he doesn't know what happened to it. There was no financial grift. He also said he didn't do anything untoward in the bathtub. Still, my mom got a bad feeling from their first interaction. There shouldn't have been a second one, but there was, after she was divorced and had all these suitors peacocking around.

It was 15 years after the bathtub incident. She was picking up my brother from summer camp. Mr. X was picking up his son. She didn't recognize him at first.

Linda Maum

I had seen Mr. X in the distance and thought, oh, he's so good-looking.

Courtney Maum

She learned from a mutual friend that he was going through a divorce. Still, she didn't recognize him as the man from the botched reno. He was just some handsome stranger.

Linda Maum

I was so excited he was going to be available. And so when I left, I gave him my phone number. And I said, if you ever want to talk, because it is a very difficult thing to go through, call me. Of course, it's a line.

And he did indeed call me, probably within a week. And that's how we started dating. But I didn't know who he was at the beginning. I mean--

Courtney Maum

You didn't know that it was the same guy who snuck up behind you in the bathtub?

Linda Maum

No, no, no.

Courtney Maum

For a little frottage.

Linda Maum

And you know why I didn't know? This is horrible to admit-- because he had a toupée on.

Courtney Maum

[WHIMPERS]

Linda Maum

And when--

Courtney Maum

Wait. He had a toupée at the camp?

Linda Maum

Yeah. So he had much more hair than I remember him having. And it was darker. He was blonde when I knew him.

And then he came over to me and said, I know who you are. And I said, you look familiar, but I don't know you. And he said, I'm Mr. X. [CHUCKLES] And I slammed him in the chest and said, Jesus Christ, I don't want to talk. I shouldn't want to talk to you. But that's what happened.

Courtney Maum

My mom told me that on their first real date, she did ask Mr. X why he never paid the subcontractors at my parents' house. She said he told her he'd been in a car accident, was on heavy drugs and hospitalized. She decided to forgive him. I'd never heard about that moment in the bathtub or the missing money.

Courtney Maum

Listen, what's surprising to me about hearing this full story, you remembered that and thought, you know what, this is the guy to pursue.

Linda Maum

I'm going to let it go. Just forget about it. Yep.

Courtney Maum

No red flags were waving around?

Linda Maum

Of course they were.

Courtney Maum

No further comment. [LAUGHS]

Before Mr. X, my mom was super social. When my parents were married, our house was like Studio frickin' 54. They had these awesome dinner parties where everybody looked nice, and my mom would serve this Martha Stewart-level cuisine with ease and panache that really impressed me as a kid. I remember going to sleep to the sound of people clinking glasses, enjoying each other's company.

When she got together with Mr. X, though, her life started to narrow. People didn't really come by our house much anymore. My sense is that Mr. X made people uncomfortable. Though he presented OK, in conversation he was gruff and socially awkward, a wild animal in deck shorts.

In public, he treated strangers badly-- barking at waiters, yelling at gas station attendants. In private, it was worse. He was clingy and possessive with my mother, cutting her down with hurtful comments.

The drinking stopped being social. Dinners were served on a tray in front of Fox News, the volume blaring, with him hollering for more. I graduated college still not understanding what the hell my mom saw in this man or why she'd let him come between us.

Courtney Maum

What were other positive things that drew you to Mr. X in the beginning?

Linda Maum

I had a partner. I was up at Candlewood Lake, and everything was husband and wives, or boyfriends and girlfriends.

Courtney Maum

Candlewood Lake is where my mom was living at this point.

Linda Maum

I had somebody that I was proud to be seen with, and he was a so-called architect.

Courtney Maum

OK, so he was handsome. He was available as a partner.

Linda Maum

Good sex partner, good sex partner.

Courtney Maum

Oh, god.

Linda Maum

Sorry. It's true.

Courtney Maum

Let me just digest that. OK, but you just really didn't want to be alone, it sounds like.

Linda Maum

I didn't like being alone, but I don't think I got married so I wouldn't be alone.

Courtney Maum

I drilled into my mom about this. She said it was as simple as her wanting someone handsome on her arm. Everyone was coupled. She wanted something for herself.

Courtney Maum

Why him, though? Because you had all these other offers. Why him?

Linda Maum

Well, I guess because he didn't offer.

Courtney Maum

Well, how did you get engaged?

Linda Maum

I told him we were getting married.

Courtney Maum

Oh, god, it was you? You were the motor behind this? My life is coming undone right here in the living room. You asked for his hand in marriage?

Linda Maum

No, I did not ask. I told him that we might just as well get married, period.

Courtney Maum

Romantic. And what did he say?

Linda Maum

Yay.

Courtney Maum

So this speech I gave at my mother's wedding that made her so upset, I remember her complaining about it to strangers, people at the grocery store, airline stewards for over a decade. If a waitress said something nice about mothers and daughters spending time together, she'd be like, ha, you should have heard how she talked about me at my wedding.

Linda Maum

I thought I was going to get a how wonderful my mother was growing up and how happy I was to see her happy, but what I remember about that speech is it was more about the negative things that I did in my life, like, i.e., smoking-- at my wedding. And I remember standing there, and my heart just sunk. And I just thought, oh, my god, she really hates me.

Courtney Maum

That's what she heard, but it's not what I remember saying. Here's where I admit that my speech was actually a poem written by me. I was super into poetry as a teenager, poetry as homage. When my best friend moved away, for example, I wrote her an ode that her mother had professionally calligraphied and framed, and that our school asked me to set to music and perform at assembly.

For better or for worse, my visions of myself as a great American writer were clearly being indulged. So when my mom asked me to say something at her wedding, I cracked open my diary and set about writing something major, something so revealing it would cause the ground to crack beneath the altar or inspire someone to rise from the pews and speak out against their marriage, to make the whole thing stop there and then. I really wanted that. In preparation for this conversation with my mom, I dug the poem out. Neither of us had seen it in 30 years.

Courtney Maum

I am looking at a piece of paper that has 1, 2, 3, 4-- like, seven stanzas on it. "Wedding Day Poem for My Mother."

She walks through realms of habituated darkness. And can you see the tumble stones that mar her rocky path? She is pushing, she is pulling, she is moving through the darkness. And oh, the road is long, and every breath feels like her last. O, Mother, Mother, Mother, behind my lids I see you smiling at the bow within a boat above the sea.

In retrospect, there's no chance anyone understood this fucking poem. I'll skip ahead a bit.

Courtney Maum

Other times I see you and often you are lonely, standing by our counter with a cigarette in hand.

There it is, the cigarette of my mother's discontent.

Courtney Maum

And in my head I hear you wishing body beyond boundaries, somewhere another place, another time, another land. Mother, the time has come for laying down roots.

Right here, halfway through the poem, something weird occurs. My tone shifts in a way I don't remember at all.

Courtney Maum

No longer do I see you glancing out beyond our window, wishing yourself other places very far from here. I think you found contentment. I think you've found belonging. I think you have found a refuge where safety subdues fear.

Why had my mom given me such hell over this thing? The poem wasn't incendiary, nor was it damning of my mother. If anything, it seemed to wish her well. Here are the last lines.

Courtney Maum

Look no more out the window. Look no more through the door. Look not beyond horizon. It's not foreign anymore.

You found what you've been wanting. Your roots grow deep and true. You found a soul to worship and someone who loves you too.

Linda Maum

OK. The ending was good.

Courtney Maum

[LAUGHS]

Linda Maum

But I will say that at that point, I probably wasn't listening anymore. And that's why I didn't hear the positiveness of it. You no longer have to look. You can go out and be happy with this person that's going to smoke with you. I wasn't going to be alone in this dark age of sin. It's negative to me.

Courtney Maum

Still?

Linda Maum

Yeah. Yeah, the beginning is definitely negative still.

Courtney Maum

OK, so for me that's painful to hear, because I was really acknowledging how much you were struggling. And to me, that was what I was trying to do with the beginning, was acknowledge everything that you were going through that was so, so hard.

Linda Maum

I could see that. You tell me that, and I can understand it. I'm sorry that I didn't hear the positiveness in it.

Courtney Maum

I accept your apology. Thank you.

Linda Maum

[CHUCKLES] [SIGHS] Oh, phew.

Courtney Maum

I probably owe my mom an apology as well. I mean, now that I'm rereading it for the first time since the wedding, I get why she was so upset and hurt. It's a pretty dark picture to present of someone on their wedding day. I also get how she couldn't hear the nice things I was saying. Frankly, I didn't remember at all writing the end with that much compassion toward my mom and graciousness toward Mr. X, but hearing it, I do remember feeling that way.

We were dealing with hard things as a family before my mom got remarried. My brother Brendan had gotten really sick. He basically moved into the Yale New Haven Children's Hospital when he was 10 years old because he was seizing uncontrollably. His heart would stop out of nowhere. It was a terrifying time.

Mr. X was intolerant of everyone, but he was gentle with my brother, kind. He helped calm my mom down. I know this meant a lot to her and also to Brendan, especially because our father was sort of checked out emotionally from what was going on. I do remember thinking, this is a thing to hold on to here. This is his saving grace.

I wish I'd made things simpler for my mom back then. I wish I could have said more clearly, I'm worried about you. But anger is the teenage version of worry, and I was very angry. My mom wouldn't tolerate me saying negative things about her partner, so I bottled them inside, which made me snippy and resentful.

I stopped being nice to my mom. I stopped being light and silly with her. And as it turns out, I had reason to be worried.

Two days after the wedding, at the age of 49, my mom had a massive stroke. There had been signs she wasn't well on her wedding day already. And in the days following her hospitalization I developed a theory that her body, not her mind, knew that the marriage was a mistake. I ran this by my mom.

Linda Maum

I think that's true. I mean, why was I sweating so much? Why was I-- I think it's true.

I knew. I knew when I was buying my dress. I knew when I wasn't as happy. I do believe that I anticipated this awfulness ahead of time.

Courtney Maum

In your body?

Linda Maum

In every fiber.

Courtney Maum

Oh, jeez. I mean, I think to me that's heartbreaking to hear, because that's what I thought was happening.

Linda Maum

Oh, no. I'm just going to start crying.

Courtney Maum

That's all right. You can cry, Mom. It's all right.

Linda Maum

OK, I'm crying, so put that in. OK, so I should have called off the wedding. And I knew that, because I was just overwhelmed with everything, end of story.

Courtney Maum

I entered this conversation with a bunch of questions from my mother, but it was coming down to one.

Courtney Maum

How come you didn't listen to your guts? I think there were a lot of moments where you could have, and you didn't. Were you raised to defer to men, or?

Linda Maum

I was raised that I knew nothing. I mean, I was always wrong.

Courtney Maum

You were raised to believe you knew nothing?

Linda Maum

Right.

Courtney Maum

Because you're a woman?

Linda Maum

My mother told me this. So my mother was very domineering. And she made me believe that I was worthless and everything else. And so when I married Mr. X, I think that came back to haunt me, all my negativity against myself. And I think I didn't listen to myself because I couldn't be right. I couldn't be right.

Courtney Maum

That's so wild to hear. Because when I was little, my mom was the most capable person-- physically, socially, financially, a total financial whiz, the best dressed, the best looking, the best driver, the most fun, all of these fantastic things. And she had a real reputation still among my friends in school. Yeah, it's emotional to think of. Among my friends in school, it was just like, how everyone looked up to Linda Maum.

Linda Maum

Well, to me this is all very sad. Because, again, it goes back to my mother-- and I hate doing this-- going back to my mother and blaming my mother for some of the things I became.

Courtney Maum

And she was a huge smoker, if I'm remembering correctly.

Linda Maum

Oh, giant, giant, giant. I was so angry at myself for being a smoker. I just didn't want to smoke, and then you made it a--

Courtney Maum

So I hit a nerve?

Linda Maum

Yep. Yep.

Courtney Maum

My mom also had one main question for me.

Linda Maum

Why did you dislike me so much as a teenager? You kind of have answered that, really, with all the things that were going on.

Courtney Maum

But do you want to stop there and let me answer it?

Linda Maum

Sure, if you have-- yeah.

Courtney Maum

I have additional--

Linda Maum

[SIGHS]

Courtney Maum

I'm going to bristle at the word "dislike" because I actually liked you a lot, and I looked up to you in a lot of ways. What I could not stand was that you let yourself be walked all over by lesser men, by men specifically, but also men that either didn't seem to deserve you or were actually bad people that weren't respected. You really were such a strong-- you want to say something?

Linda Maum

Yeah, I want to know what men they were. I thought it was just Mr. X. I mean, I don't remember anybody.

Courtney Maum

Out of respect for my father-- I'm still grieving. He just passed. I don't want to talk too much about my dad, but my father did not always treat you with a great amount of respect. So I do include him in some of the men that I feel you were subservient to.

What I saw growing up in Greenwich, Connecticut in the '80s and '90s when Greenwich was truly the bedroom town of Wall Street, what I saw was a lot of vivacious men who got to go somewhere else all day long and come home to children that were bathed and these beautiful women that were their wives-- put out fresh flowers, had dinner out. And the man just came and put his feet under the table, ate the food, and then got to go take a load off in a study. And so growing up, I was like, well, I'll be my dad. I'll be the man. I want to come home and have dinner at the table. I want to drive a cool car to work.

And so something I bristled against with you is at a certain point, you were taking on so much, and it didn't necessarily seem to be bringing you joy. And Mr. X came into the picture. And in the beginning, I think he did-- he seemed to really worship you. But certainly, as the years went by, I saw a man who demanded to be served and did not fetch as much as his own ice cubes. And that made me really angry at you. I wanted you to stand up for yourself.

Linda Maum

Well, I think it's-- in my mind it was dislike of me because of the way you talked to me and the way you avoided me. I could never see it any other way. Your tone of voice, I mean, I don't know how it could understand that that was because of my lack of respect for myself.

Courtney Maum

Yeah. No, I don't think you could have. I mean, I was a B.

My mom's got a point here. I was sending mixed signals. I loved her. I was mean to her. I wanted her to be a feminist baddie who kicked out Mr. X, but I also benefited from her commitment to homemaking-- the awesome dinners, her driving me around.

It was confusing. I was confusing. But I was clear on one thing, Mom. You chose him over us. You kept on choosing him.

But one night last October, she made a different choice. In the kitchen of the house that Mr. X had designed to look art deco in style, but instead came out looking like a White Castle burger joint, my mom fell and broke her back. Though it was early in the evening, Mr. X was too drunk to help her. She lay on the floor for hours. Finally, he brought her her cell phone so she could call an ambulance herself.

Linda Maum

When I was on that floor, I swore I was going to do everything I could to get rid of him.

Courtney Maum

She was hospitalized for months, unable to walk. Before the accident, I'd almost given up on my mom, but now she told me that she'd reached a turning point. She gave me power of attorney to fight in court on her behalf to evict Mr. X.

For months, I went everywhere with legal paperwork in case I was called into court. It was hard, and it was ugly. It was the hardest thing I've ever done in my life, actually. But we won.

Mr. X left the house in an unholy state. I spent weeks cleaning up after him, boxing up his possessions. My mom came home from the hospital. My brother and his wife moved in with their cat, who took a particular liking to my mom.

Linda Maum

I didn't know how complicated it was going to be to get about. And at that point, I didn't know you were going to be so instrumental in doing it. Because of the amount of time you spent down here, I realized how much you cared about me. Until then, I really didn't know. I didn't.

Courtney Maum

Mr. X drove us apart, and kicking him out is what brought us back together. It's a strange thing to rally around, but this is where we are. My mom is 79. I'm nearly 50. We have the rest of our lives to catch up on what we've missed.

Ira Glass

Courtney Maum. Her latest novel is called Alan Opts Out.

We did reach out to Mr. X. And he told us he's designed hundreds of houses. He had lots of friends. He says he never left any house in any kind of disrepair in his life.

Coming up, a man goes back to the job of his teenage dreams to see what is the same and what is gone forever with the passage of time. That's in a minute on Chicago Public Radio when our program continues.

Act Two: Cinema Veri-teen

Ira Glass

It's This American Life. I'm Ira Glass. Today's program, intergenerational space travel, stories of people braving the vast distances that separate young and old, trying to understand life on the other side of the divide. We've arrived at Act Two of our program. Act Two-- Cinema Veri-teen.

So when one of our producers, Ike Sriskandarajah, was a teenager, he had the greatest job he could humanly imagine. And that was, he worked at a movie theater. Wore a cummerbund to work every day, snuck around the managers with secret schemes of his own. This was back in 2003, more than 20 years ago. And Ike wanted to know, is the job still the best? He traveled back to his hometown in Wisconsin and spent some time at his old movie theater, the Marcus Point Cinema in Madison.

Ike Sriskandarajah

My friend Marc vouched for me to his manager. That's how I got hired there. And Marc knew how to make the most of the job. He taught me which door was the easiest to let your friends in, how to give away free popcorn by filling up discarded plastic bags so you don't mess up your popcorn tub count, and why volunteering to clean the bathroom was actually secretly a great job, because you got out of the concession stand, and you could sneak into a movie for a scene or two on the clock.

By senior year, I stacked lunch and study hall together in my schedule, and I'd treat friends to a school day matinee with popcorn and soda. I felt like a teen god, second to none in the pantheon of high school jobs, except maybe drug dealer.

When I got back to my old theater, the outside looked the same-- classic old Hollywood movie marquee, and inside there's still busy, stain-masking carpet and the long tunnel with theaters on either side. It even smelled the same.

I had asked to speak to teens, employees who were the same age I was when I started, but the company's comms team and their HR department said no. Instead, I could talk to a 26-year-old assistant manager named Darren Klingaman. He was behind the ticket booth when I arrived-- clean shaven, wearing a dress shirt with little flowers and a tie to match. Darren told me he did not apply for the same reasons I did, namely free movies.

Darren Klingaman

No, it was just-- I just lucked out that that was a perk. I didn't know about it until afterwards.

Ike Sriskandarajah

Oh, wow. OK.

Darren Klingaman

It was a nice surprise.

Ike Sriskandarajah

Nice surprise.

Darren was just looking for any job. Besides getting to see movies, what about the other things that made the job so fun back in the early aughts? Are they still part of it? I ran all my favorite hijinks we pulled at the movie theater by Darren.

Before I tell you about the first thing, I just want you to remember our brains were still developing when we thought this was so funny. So basically, if you were the person who ripped tickets, you were supposed to say, enjoy your show. But some genius came up with a twist that involved referencing male genitalia of specific dimensions. I told Darren about this.

Ike Sriskandarajah

We'd mumble under our breaths, enjoy your chode.

Darren Klingaman

OK.

Ike Sriskandarajah

I was wondering if that's still happening.

Darren Klingaman

Not that I'm aware of.

Ike Sriskandarajah

You've never heard somebody say, enjoy your chode?

Darren Klingaman

No, I have not.

Ike Sriskandarajah

Do you think that joke's funny?

Darren Klingaman

[SIGHS] I mean, I didn't laugh.

Ike Sriskandarajah

I noticed that.

In the early aughts, it killed, at least with the kids working at the concession stand.

Darren Klingaman

How many people just said, excuse me?

Ike Sriskandarajah

I think that was the most common, because we're mumbling it.

Darren Klingaman

You're mumbling it, right. Yeah, OK. Yeah, I mean, I think it could use some work.

Ike Sriskandarajah

So that's a change. In 2026, chode's over, folks.

Another thing that I thought was so fun was volunteering to flatten boxes out back. If that sounds boring, you don't know the WrestleMania technique that my friend taught me. Basically, you could fill up the industrial dumpster out back with unflattened boxes, pull yourself up to balance on the metal edge, and then launch yourself into the air and drop the People's Elbow on a box.

Tom Reichilt

Well, I tell you, that sounds like a very interesting workman's comp issue, getting ready.

Ike Sriskandarajah

That's area general manager Tom Reichilt, who corporate PR asked to join. So many things I loved about this job are gone. We wore tuxedos to work made of this magical material that was impervious to nacho cheese stains. During a tornado, we got evacuated into the manager's office, where we took an ID from the lost and found that looked enough like me to buy malt liquor exactly once.

Now, kids are never let anywhere near the lost and found. The mini donut machine burned me, but it made delicious donuts. Back in the day, it burned Area General Manager Tom Reichilt too.

Tom Reichilt

I probably have one here somewhere, maybe there. A little different these days.

Ike Sriskandarajah

That's gone too. But what about the big one, my favorite benefit of the job-- letting my friends in for free? It really was the coolest thing I could think of, to be able to grant this wish to anybody-- a free night at the movies, a drink, popcorn. We were allowed to bring in one guest, but I was always happy to let in more friends through the back door near the dumpster. Darren says that, yes, that perk is still around, but these days, the back door is not necessary.

Tom Reichilt

Just have them walk in the front door, come greet them over here, and we'll hook them up. I always let them all know that there's no reason to be sneaky in any way. If you want your friends to come see a movie, tell me, and I'll get them in. I mean, it's a perk.

Ike Sriskandarajah

So they're allowed to bring in their friends. But calling out to an unscientific survey I did of three teens around America who work in movie theaters right now, I learned they don't want to. One 18-year-old in Kansas City says she prefers watching movies at home, where you can talk to your friends during the show and watch basically any movie ever made. What a waste. Darren at least understands how bringing someone in for free has the power to actually change your life.

Darren Klingaman

When I first started here, a couple months later, I met my girlfriend. I brought her to a date here after hours. That might not technically be allowed.

Ike Sriskandarajah

What do you mean, after hours?

Darren Klingaman

Oh, everything was closed. We were closed down. I asked her if she wanted to come see a movie. So we watched Wicked.

Ike Sriskandarajah

Whoa, you brought your girlfriend here because you had the keys to the place.

Darren Klingaman

I did. I had the keys. She wasn't actually my girlfriend quite yet. Good first date.

I knew Wicked was one of her favorite musicals. So it was like, perfect thing. Wicked just came out. Why don't we watch it? Private showing and the biggest screen we can.

Ike Sriskandarajah

Darren ushered her into an empty theater. Sat her down in the best seat in the house. Popcorn, Diet Coke in the cup holder. Brought a sweater because theaters get chilly. And then he ran up to the projectionist booth, fast forwarded through the ads, and ran back down to sit with her just in time for the show to start.

That was two years ago. Now they're engaged. What other job would let you pull off a first date like that?

Darren Klingaman

Honestly, I mean, it was so memorable. We still think about it.

Ike Sriskandarajah

Now, tell me if I'm overstating it, but would you guys be getting married if it wasn't for that?

Darren Klingaman

I would hope so, but I don't know. It's a good question because of how big of a thing it was and how meaningful and unique it was that it definitely bumped me up some points. So hopefully, but definitely not as easily.

Ike Sriskandarajah

It's really similar to the thing that happened to me.

Darren Klingaman

OK.

Ike Sriskandarajah

When I was here--

I told Darren that I also once tried to impress a girl while on the job. When I met her, I filled up a discarded plastic bag with popcorn and slipped it to her. Another time, I let her and her friend in the back. I'm no longer wearing a tuxedo to work, but that girl I snuck in, we're married and have two children. The job today definitely seems less fun, but there's still a little movie magic left.

Ira Glass

Ike Sriskandarajah. He's one of the producers of our show. By the way, none of the three teenagers I talked to knew what chode meant, but some of them thought it was funny anyway.

Act Three: Mama Can You Hair Me

Ira Glass

Act Three-- Mama, Can You Hair Me? Myra Flynn is in her 40s, and the person across the divide in this story is six. It's her daughter. The two of them have been in a bit of a standoff when it comes to getting ready for school in the morning. It was going so badly, Myra started recording these morning showdowns, trying to figure out if there was some way to fix things. Here she is.

Myra Flynn

My mornings used to look so different. In my younger days as a touring musician, I'd greet the sunrise on my way home from a gig in some random city and face plant into my bed. But now I start my day at 7:10 AM, engaged in a battle of wills with my daughter Avalon over her hair.

Myra Flynn

Hey, baby. It's time to do your hair. No, we're going to do it because you got to be at school in 10 minutes.

Avalon

But Mommy.

Myra Flynn

When I was a kid, my mom and I had a similar hair routine. She would sit me down at the breakfast table every morning, grab a cup of water and a hard bristle brush, and rake through my curls. It hurt like hell, but there was no point in complaining because my mom made it clear we didn't have time for any of that. My hair had to get done. That's just how it was. And that's just how it is for Avalon.

Black hair is Black hair. And look, I'm not doing box braids or knotless styles, or writing her name in the side of her head with cornrows. I'm just trying to comb through it and put it in a ponytail so that no one looks at us crazy.

So every morning, I take her hair out of whatever shape it's landed in after a night of sleep without a bonnet. I still haven't found one that stays on her head. Then I grab three different brushes, a big jar of leave-in conditioner, a spray bottle full of water, and get to work, which Avalon, who's six, hates.

Avalon

Ow.

Myra Flynn

Stop, baby. Avi, it's not that bad. Stop, stop, stop. No, no. I can't use that brush. I have to use this brush.

Avalon

I just wanted to hold it.

Myra Flynn

No, baby. You need to just-- please, can you just look forward, and bend your neck for me. Bend your neck down.

For the record, holding this brush is a stalling tactic for Avalon. She wants to hold it so I can't use it. And I see straight through you, Avalon Mathis Wills. I know my daughter.

Avalon, by all intents and purposes, seems impervious to pain. I've literally watched her face plant from the top of monkey bars onto the grass, only to bounce up and try it again.

This is a kid who doesn't want to wait for her teeth to fall out naturally. As soon as they're loose, she's trying to pull them out of her head. And she won't even let the tooth fairy take her teeth. She wants to make jewelry out of them. She's perfectly weird and brave in all the best ways.

So for her to shake and cry only with me is devastating. But also-- and I'm not proud of this-- a big part of me is like, girl, nobody's dying here. Suck it up.

Avalon

It hurts.

Myra Flynn

Baby, I'm sorry. I have to get it.

Avalon

You already did.

Myra Flynn

I didn't.

Avalon

Will it hurt always?

Myra Flynn

Probably, baby. Sometimes the things that we need are not comfortable.

Hold up. Did I just actually say that? I'm not even sure I believe it.

You know that moment when you open your mouth to say something and out comes your mother? This is one of the few times I heard that in my life, and it really stuck with me. My mom was the Black female dean of a military college. She taught me that sometimes in life, there are things like hair that you just have to tough out.

In so much of my parenting, I've tried to be a little different, do it my way. I don't know if I totally believe that Black kids should just have to tough it out when they're in pain. I also don't want to be a parent that teaches their Black kid that everything in life should feel like a lukewarm bath.

When it comes to Avalon's hair, I feel so conflicted, like my two parenting styles are at war. And when I heard myself say, sometimes the things we need are not comfortable, I felt like I had to talk to my mom about it. I needed her to back me up on this. So I called her, Miss Martha Mathis herself.

I walked her through what had been going on with Avalon, the battle with her hair every day right before school. And I asked her, this is just the way it is, right, to which she said--

Martha Mathis

No. I think I've found that's what you want to avoid. Because at some point, if you're rushing and you're trying to do our hair, then it's going to hurt. If it's going to sit up there for days without anybody doing anything, then you're going to get what you get.

Myra Flynn

My mom saying pain was something that you should or even could avoid was wild to me. She did my hair up so tightly I got migraines at school.

Myra Flynn

Mama, do you remember one time when you were doing my hair, and you were doing it and doing it, and I was like, ow, ow! And I was eating breakfast at the breakfast table, and then I threw up?

Martha Mathis

No.

Myra Flynn

You don't remember that?

Martha Mathis

I don't, but that doesn't mean it didn't happen. It just means I don't remember it.

Myra Flynn

Yeah.

Martha Mathis

Then what did we do?

Myra Flynn

Oh, you went and grabbed the trash can, just in case I had to again. But yeah, I just remember it hurting a lot.

Martha Mathis

Oh, yeah.

Myra Flynn

My mom once described my parenting style as permissive. Sometimes I feel like I have to be firmer when she's around so she'll be proud of me, or something like that. So I couldn't quite wrap my head around what I was hearing.

Myra Flynn

I'm kind of surprised to hear you say that, no, it doesn't have to hurt. I feel like you're a tough cookie, Mama.

Martha Mathis

I am.

Myra Flynn

Yeah. And I feel like you raised me to be one. And I can feel that lesson starting as early as my hair, just as I can feel like I'm doing that with Avalon. Do you think that I should be making her tough for the world? Like the way I'm talking about hair is a gateway into, like, toughen up. Do you think that--

Martha Mathis

No. I wouldn't use hair as a gateway to toughen up because it has too many other racist and sexist implications.

Myra Flynn

Did you want me to toughen up in those moments when I was crying and like, ouch, this hurts?

Martha Mathis

No, no. It hurt. No. Why would you-- no.

Myra Flynn

You didn't want me to toughen up and just be like, we got to get used to this because we're on a schedule. We got places to go.

Martha Mathis

Well, it was going to happen whether you were tough or not. And at six-- I'll use Avalon's age-- she's as tough as she's going to be right now. And she can't be any tougher. I think she's the toughest little girl I know. So no, I would not have equated doing your hair with tough or not. I always felt bad that for those 10, 15, how many ever minutes it was, that that's how you were starting your day.

Myra Flynn

I didn't know that she'd had any feelings about our mornings. My mother told me it was the same for her when she was young. She sat between her mother's knees, and out came the hot combs, the hair grease, the brushes, the pain, which she likes to remind me was far worse than mine, as I remind my daughter, and we copy and paste. But instead of giving me the validation I wanted and letting me know that the way she'd done my hair is really the only way, my mom gave me some advice I really wasn't looking for.

Martha Mathis

Give her some of her own hair.

Myra Flynn

Oh, to take care of? Yes, I've tried this. We've tried this, yes.

Martha Mathis

Oh, you have?

Myra Flynn

Oh, yeah. We've tried-- it's do-your-own-hair day.

Do-your-own-hair day in my house means we give Avalon a brush and some bows, and 15 minutes later, absolutely nothing has happened. But it turned out that wasn't what my mother was suggesting.

Martha Mathis

No, I mean, have her do her own kitchen.

Myra Flynn

Well.

Martha Mathis

She'll be gentle with herself.

Myra Flynn

If she does her own hair at this age, Mama, she's avoiding her kitchen altogether.

Martha Mathis

OK. So it looks like-- I don't know-- a rat's nest. Nobody's going to see it.

Myra Flynn

Yeah.

Martha Mathis

And if you remind her now, get in there, because you don't want me in there. When you remind her of that, it's going to be your hand or mine.

Myra Flynn

Yeah.

Martha Mathis

I think if you give her something that she owns and if it's just this little bit back there, my goodness, let her have it. What would happen if you parted that off, though, seriously?

Myra Flynn

I'm hearing you. I just don't-- I'm like-- when you're saying, why don't you try this, why don't you try giving Avalon a little section for herself, why didn't you try that with me?

Martha Mathis

Because no one told me that. That's how messages are passed on. The women my age, they were not brought up to even have these kind of conversations. And I don't even know if I had them in my brain, I mean, back then. But I'm saying for you, I would think you do have options. When you know better, you do better.

Myra Flynn

The next time I did Avalon's hair, I let her do some of it.

Myra Flynn

You ready to get the back just a little bit right here? Good job. Back here. Look at that. Why are you smiling? Whenever Mama's doing it, you're crying.

Avalon

[LAUGHS]

Myra Flynn

What's it feel like to do your own hair?

Avalon

Soft.

Myra Flynn

It feels soft, huh?

Avalon

It doesn't feel hard like a rock. But when Mama does it, it feels hard like a rock.

Myra Flynn

Your hair feels hard like a rock, or my brushing feels hard like a rock?

Avalon

The brushing feels hard like a rock.

Myra Flynn

Does this part hurt?

Avalon

No.

Myra Flynn

Oh, good. I don't think I've ever seen your kitchen look so good. Should we show Papa?

Avalon

Mm-hmm.

Myra Flynn

Papa Bear! Do you want to tell him? Want to tell him?

Avalon

Look at my kitchen.

Phil

[GASPS] Wow.

Myra Flynn

What about your kitchen?

Avalon

I did it.

Phil

You did it?

Avalon

Yes.

Phil

Good job, baby.

Myra Flynn

As a parent, you're always looking for your failures. There are so many ways to fall short. But every once in a while, if you're lucky, the evidence is clear. You did something really good for your kid. And with my mom's help, I was able to change this one thing in the wheel of my own motherhood, and maybe one day, Avalon's. I want her to know what my mother knew and her mother before her, that when you're doing your hair some parts need someone else's hands, and some parts we can learn to hold ourselves.

The Daily Front Page 16 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — The Preservationists
article

Pirating the Pirates

by piotrgrabowski·▲ 471 points·241 comments·mubi.com ↗
People who alter or destroy works of art and our cultural heritage for profit or as an exercise of power are barbarians.

“People who alter or destroy works of art and our cultural heritage for profit or as an exercise of power are barbarians, and if the laws of the United States continue to condone this behavior, history will surely classify us as a barbaric society. ”

—George Lucas, 1988

“To me, it [the original Star Wars trilogy] doesn’t really exist anymore. It’s like this is the movie I wanted it to be, and I’m sorry you saw half a completed film and fell in love with it.”

—George Lucas, 2004

Vancouver, 2011: My then-roommate Willa Ross and I are at our wit’s end in one of Simon Fraser University’s characteristically antiseptic editing suites, having just spent the weekend hacking together three distinct copies of Sergio Leone’s 1966 western The Good, the Bad and the Ugly, all illegally ripped. The film had fallen victim to an MGM “restoration” in the early 2000s: Scenes Leone cut were reinstated, inflating the English-language runtime from 161 to 179 minutes, with Eastwood and Wallach dubbing the missing dialogue and a soundalike standing in for the late Lee Van Cleef. The mono soundtrack, meanwhile, had been reworked into a surround mix with jarringly modern gunshot effects. This “extended” cut was the only version commercially available for nearly a decade, an all-too-common fate in an era of revisionist studio reworkings.

Our goal was simple: undo this butchery. We planned to combine sound from an out-of-print 1998 DVD (an approximation of the 1967 international release) with video from a recently imported Blu-ray of the Italian cut. After successfully navigating the various pitfalls of late-2000s home video ripping, our hopes were dashed by a catastrophic realization: The Italian cut was even more dissimilar to the international cut than the extended cut, the infamous torture scene entirely restructured and various shots missing heads and tails. We gave up for nearly a decade.

Publicly accessible versions of major works of cinema are often wholly inadequate for reasons as diverse as the resultant shortcomings. A major studio’s home video arm might “expand” a film, remix a monaural audio track, wipe away digital grain, oversaturate or oversharpen the image, or even change the aspect ratio for the sake of an attractive sticker promising a new-and-improved experience.

At other points, low budgets and corporate apathy lead to corners being cut. Spencer Draper—best known as the Damn Fool Idealistic Crusader on YouTube, where he reviews the technical and historical aspects of digital releases with a rigor usually reserved for scholarly peer review—characterized the attitudes of negligent studios harshly in my recent interview with him: “‘Oh, you got a problem? The Kino [an American boutique label] disc is defective? So what. So what if it uses a defective Paramount master with frozen grain and [has] problems throughout.’ [The studios] don’t care that any given audio file is 30 years old and the channels are reversed.” Sometimes, this persists for decades: Every copy of Once Upon a Time in the West (1968)released since its 1984 reconstruction has featured a major soundtrack mistake during the end credits brought about by a botched attempt to fix another error introduced in 1970, one example that particularly rankles Draper.

This is where boutique labels come in—companies that independently license and release archival titles, in something like the spirit of Criterion’s founding aim: to gather significant films from around the world and present them as close to a filmmaker’s intent as possible, in the best technical condition available. Outfits like Arrow, Kino, and Eureka operate on a version of that premise. What any given label actually restores versus what it merely receives is a separate question, running a wide spectrum. Sometimes a label might receive a fully mastered digital file and find themselves contractually obliged to release it as-is; at other times, they might receive raw digital scans with partial or no cleanup; or they might be required to source, scan, and restore a film by themselves.

James Flower, director of production at Arrow Films, a British boutique label renowned for its rigorous approach to preservation, raises a different culprit for historical inaccuracies: living filmmakers. The revisionist impulse is nearly as old as cinema—from Charlie Chaplin modernizing his silent classics in later years to Wong Kar-wai radically altering the color grading, aspect ratios, and soundtracks of his back catalog for a 2021 Criterion box set. In his note accompanying this set, Wong Kar-wai justified his alterations with a simple philosophy: “No man ever steps in the same river twice, for it’s not the same river and he’s not the same man.”

However, this revisionist approach often leaves release-accurate versions unavailable to historians and audiences alike. In our interview, Flower recalled a director enamored with a digital aesthetic “wanting his films to look sleek and modern and degrained, with oversaturated colors that would not have been achievable photochemically.” Flower suggested including both the revised cut and a historically accurate version, but the director vehemently refused. Facing a deadline, Arrow acquiesced. “For me, he was vandalizing his own work,” says Flower.

Home video release images from The Good, the Bad and the Ugly (Sergio Leone, 1966). Clockwise from top-left: Arrow Video (4K UHD, 2025), Kino Lorber (4K UHD, 2021), MGM (4K Blu-ray, 2014), MGM (DVD, 1998).

Vancouver, July 2019. Radicalized by a disheartening screening of the official MGM masters of Leone’s Dollars trilogy at a local cinematheque, Willa and I resume work on our cobbled-together cut. We now have better raw materials: a new Blu-ray with far superior picture quality, and an old LaserDisc with an uncompromised mono track. A decade of expertise (I have become a colorist and Willa an editor), alongside a decade of technical progress in editing tools available for independent filmmakers, enables us to properly process them. A local repertory cinema programmer catches wind of this, and a plan is hatched: book an official Digital Cinema Package from MGM and swap it out with our homebrew copy for a public screening. A magical evening ensues: It was as if we were seeing the film for the first time, smuggled before a live audience.

After the screening, I’m approached by a man with an attitude that screams “so you think you know a thing or two, huh?” It turns out his attitude is warranted: He enthusiastically informs me that he’s spent years on his own far superior reconstruction—a 4K scan of a well-preserved IB Technicolor print of The Good, the Bad and the Ugly.

Home video release images from The Good, the Bad and the Ugly (Sergio Leone, 1966). Clockwise from top-left: Arrow Video (4K UHD, 2025), Kino Lorber (4K UHD, 2021), MGM (4K Blu-ray, 2014), MGM (DVD, 1998).

While digital tools have evolved, this pattern of unofficial preservation is by no means new. It’s the reason F. W. Murnau’s Nosferatu (1922) survives: after Bram Stoker’s widow won a 1925 copyright suit, a German court ordered every print to be destroyed, but copies slipped past German jurisdiction and circulated for years as unauthorized bootlegs. Similarly, Kevin Brownlow’s reconstruction of Abel Gance’s Napoléon (1927) began as an illicit teenage hobby. Starting in 1954, he spent decades tracking down fragments and duplicating fragile, rights-encumbered prints to keep them from disappearing—essentially a massive fan edit, eventually completed with Gance’s own participation.

The most famous retrospective cinematic alteration was committed by George Lucas with massively controversial Special Editions of the original Star Wars trilogy—and the subsequent unavailability of unaltered versions in anything resembling acceptable quality. Both Draper and Flower cite the 2004 DVD release and emergence of communities such as the one found on OriginalTrilogy.com as key personal entrees into the world of fan preservation. Draper jokes that “I’ve learned more from George Lucas than anyone ever because he made certain choices that I didn’t agree with, so I started digging!” Starting in the mid-2000s, he took an active role on various forums, contributing wherever he could: “They eventually made a sub-thread about preservation efforts, which was everybody capturing VHS tapes and laserdiscs and trying to upscale LDs and sync other audio tracks. One thing led to another as the preservation scene grew out of one little thread.”

Eventually, two distinct projects emerged. Petr “Harmy” Harmáček’s “Despecialized” edition, a Frankenstein’s monster cobbled together from various official releases, came first. Next was Team Negative1’s Project 4K77, which used homebrew 4K scans of 35mm theatrical prints to create accurate bootlegged digital copies. Both projects remain freely available to anyone willing to jump through some trivial internet hoops.

When an informal network of amateurs questions the work of industry standard-bearers, it is rarely a matter of raw technical superiority but rather a fundamental difference in constraints. While restoration entities often operate on strict budgets and tight deadlines, preservationists can spend years cross-referencing decades of older releases. This is not to say fan efforts are infallible—debates in online forums about accurate color grades spurred by the recent influx of amateur 35mm scans of release prints demonstrate how certain elements remain moving targets—but for objective elements like editorial cuts, missing frames, or unaltered audio, historical reference materials generally leave little room for debate.

Furthermore, fans operate entirely outside the structural limitations that thwart even skilled industry technicians. A professional lab might make all the right archival choices only to have those compromised by a revisionist director or a studio’s marketing needs. Fans, in contrast, answer to no one but themselves, which has let them accomplish what studios with exponentially more resources and infrastructure haven’t: banding together to preserve and disseminate historically accurate versions of some of the most beloved films in history—an end-run around the rights and financial issues that hold legitimate enterprises back. Flower notes: “We don’t always have the time or budget, or even the legal right, to do multiple versions. Fans don’t have those restrictions. They can do as many variations as they want, and that’s fine.” As of this writing, Project 4K77 features dozens of audio tracks and a file size exceeding 100GB: both impossible on any commercial Blu-ray release, and unfeasible for online distribution via legitimate channels.

Beyond Star Wars, an illicit cottage industry has sprung up to patch the holes in any given film’s digital representation. Of particular note is the “remux” community, dedicated to seamlessly stitching together the best video and audio streams from different releases without any generational loss of quality. Want a version of Stop Making Sense (1984) in which you can freely select every soundtrack mix ever released? You won’t find it on the official A24 disc; you have to turn to a remux circulating on a few highly exclusive private torrent websites. The original 5.1 mix of Master and Commander (2003) married to the new 4K transfer? Remux. Dr. No (1962) with audio that hasn’t been scrubbed of all its detail? Remux.

Draper sees this pooling of resources as an incredible service: “Somebody’s already done a great job of the work you were going to do yourself.” His thoughts quickly turn, however: “We’re all worried about the crackdown coming at any point. Put your hood on, look over your shoulder, go to the back door video speakeasy and give the secret recognition code.”

The elephant in the room: Legally, this is piracy. Under Section 1201 of the Digital Millennium Copyright Act, merely breaking a Blu-ray’s digital lock to rip the video files is a federal violation, regardless of intent. The law makes no distinction between mass-distributing a movie for profit and preserving the historical record. To take part in these preservation projects is to take on significant legal risk, with admonishments from rights holders and cease-and-desist letters being common.

Flower sees copyright law as a double-edged sword for film preservation. Though intellectual property rights—and the resultant studio-mandated limitations—hold Arrow back from certain actions that would be theoretically possible otherwise, these same rights in many ways ensure their income: “We have to protect our interest as well as that of the rights holders that have entrusted their films to us. We spend a lot of money on licensing and restoring. I certainly don’t think that copyright is something that should be abolished, unless someone can think of another commercial framework that would allow us to invest in the work we do.” Yet he maintains that there is a place for piracy-based preservation: “It comes down to who is financially benefiting from these things. In terms of using a physical copy and then manipulating it or finding another use for it beyond just watching it, that is a gray area that I’m personally more inclined to be generous towards.”

A sort of “pirate’s code” has emerged among these communities: an attempt to create a parallel set of norms in a context in which the strict definition of “legal” can no longer operate as a guiding principle. “You have to own a physical copy of at least one version of any given film,” says Draper. “We’re not trying to make any money out of this. Don’t make your own bootleg copies and throw them on eBay, or throw them on Twitter of all places.” Nevertheless, the clandestine nature of these efforts weighs on Draper: “It would be nice if there was at least a little bit more recognition of unofficial preservation efforts. I feel like there’s a gigantic weight about to come crashing down on me at any second because, heaven forbid, I bought another twenty laserdiscs and captured audio tracks and bought VHS tapes on eBay to compare audio captures to fix the bad audio they didn’t care about the first time around.”

Home video release images from The Good, the Bad and the Ugly (Sergio Leone, 1966). Clockwise from top-left: Arrow Video (4K UHD, 2025), Kino Lorber (4K UHD, 2021), MGM (4K Blu-ray, 2014), MGM (DVD, 1998).

Vancouver, December 2020. While cooking dinner in my apartment, I get a call from a California number. Must be a scam. Then an email: “Read your profile on National Post. I work in mastering and want to talk to you guys about The Good, The Bad and the Ugly.” Apparently, word of our pseudo-legal screening had gotten around. So began my semi-official involvement in film preservation. I roped in Willa and, most importantly, Benji Heran—the man who had accosted me after our screening of the film the year prior—and Jordan Krug, the other party responsible for their remarkable bootleg restoration of the film which would prove to be the main editorial reference point of every subsequent release.

What ensued was a months-long collaboration to turn the drastically underfunded 2021 Kino Lorber release of The Good, the Bad and the Ugly from a disaster-in-waiting to the best home video release of the film since the 1990s. Doing so involved much chicanery: Benji and Jordan supplied ripped LaserDisc audio that became the release’s main track, while Blake Blasingame—who deserves the lion’s share of credit for this release’s strengths—fulfilled his contractual obligation for a surround mix by simply placing that mono track into a 5.1 container with extremely mild panning effects. When a high-up Kino figure made a Blu-Ray.com thread to read the room on whether to include the international cut, Willa and I made dummy accounts and anonymously badgered him into making our preferred version the primary feature.

The result was a release that—despite a highly compressed turnaround time, virtually nonexistent budget, and compromised source materials—was nonetheless a largely accurate approximation of the 1967 international cut of the film in reasonably high fidelity. At last.

Flower had been leveraging the fan community’s knowledge to assist with various releases for some time prior to his work on Arrow’s release of Leone’s Dollars trilogy. “That ultimately winds up being a regular part of my research process; I go, ‘What have the fan restorers done? Can we pre-empt them from having to [fix the release] by bringing that fix into an official space if we’re allowed?’ Just recently with Mortal Kombat [1995], I happened upon a capture of an original DTS cinema mix that walloped the 5.1 audio on the prior Blu-Ray, so I was like, ‘Well, we’ll just use that!’ That’s me pirating the pirates, I guess.”

Because labels like Arrow, Criterion, and Eureka release dozens of films a year, their researchers are by necessity generalists. “As much as I would love us to have intimate knowledge with every film that we work on, we’re usually not in that position,” says Flower. This is where he reaches out to amateur experts. “Brandon Bentley—who does a lot of stuff on the Hong Kong cinema side—started out literally as an amateur. His work is so good that I see him as a colleague; he’s the person we turn to when we want to digitally recreate photochemical credits.”

Flower compares his process in an official capacity with Arrow to his early days trawling internet forums: “When I came to work for Arrow, I was bringing a lot of awareness of the methods of fan preservationists on the torrent sites. When it came time to officially create different versions of things—the big box set of the Gamera films—it’s the same methodology. It’s just in an official capacity by sheer dint of the fact that we have the license for the film and I’m not working with a DVD rip, I’m working with a ProRes [a professional video codec] master.”

Home video release images from The Good, the Bad and the Ugly (Sergio Leone). Clockwise from top-left: Arrow Video (4K UHD, 2025), Kino Lorber (4K UHD, 2021), MGM (4K Blu-ray, 2014), MGM (DVD, 1998).

In May 2024, I met James—along with other key figures at Arrow—on a video call in which Benji, Jordan, Willa, myself, and eventually Spencer, were officially brought in as consultants on Arrow’s forthcoming release of the Dollars trilogy. The expertise of the amateur enthusiast community was, at long last, aligned with an officially sanctioned organization with the resources and patience to make a fully realized, historically rigorous release happen. No internet trolling of label heads or NDA-breaking was necessary. The process took a very leisurely and considered year. And we still used the LaserDisc audio.

While drafting this article, I checked my usual private torrent site for the latest copy of The Good, the Bad and the Ugly. The 4K Arrow release is on there, in all its 89gb glory, with the Italian track that Arrow was unable to secure the rights to and every single commentary track ever released—including those not present on the Arrow disc—all muxed in. The cycle continues.

The Daily Front Page 17 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Signals From the Console
article

Hijacking the PS5's RTMP stream

by ibobev·▲ 223 points·69 comments·yashgarg.dev ↗
The long way around to screen sharing.

The long way around to screen sharing.

Sony has progressively locked down what you can do with the PS5’s hardware. Streaming is a good example: the console gives you a nice, convenient “Broadcast” button, but the moment you want to do anything outside the handful of services Sony supports, it gets annoying very fast.

Third-party Bluetooth devices are the same story! Sony locks the wireless stack to their own peripherals, so your headphones or controllers from other brands simply won’t pair :/

The Problem

I often stream games with friends on Discord who watch me play, but the PS5 doesn’t support screen sharing to Discord. The obvious fix is a capture card — plug the HDMI output into a capture card, feed it into OBS on your Mac, stream from there. But decent ones aren’t cheap, and I didn’t want to spend upwards of $100 just for this.

Remote Play

Remote Play somewhat worked for me. I could connect the PS5 to my MacBook, share the Mac’s screen to Discord and play from there.

The problem is that you need to connect everything to the Remote Play device: controller, earphones, etc. I also occasionally ran into input lag, and the stream quality is entirely controlled by the PS5. You can’t really configure anything.

I didn’t want to change my physical setup every time I wanted to stream.

How PS5 Streaming Works

The PS5 supports streaming to YouTube and Twitch by default if you’re signed into those accounts. The protocol used for this is RTMP, or Real-Time Messaging Protocol, which is commonly used for live audio/video streaming.

So when you start a broadcast, the PS5 roughly does this:

What if we could make our own device act as Twitch and receive that RTMP stream instead?

That’s the idea. The PS5 doesn’t hardcode Twitch’s IP, it looks it up via DNS every time. If we control what DNS returns, we control where the stream goes.

Finding the Right Hostname

The obvious first attempt was to spoof ingest.twitch.tv directly. That’s the hostname the PS5 resolves when you hit broadcast, so pointing it at the Mac should work, right?

Not quite. ingest.twitch.tv:443 is actually a discovery endpoint, not the RTMP server itself. PS5 makes an HTTPS call to it asking “which regional ingest server should I use?” and Twitch responds with something like ap-southeast-1.prod.fi.contribute.live-video.net. Then the PS5 pushes the actual stream there.

Spoofing that hostname ran into a different problem: the actual Twitch ingest uses RTMPS (RTMP over TLS on port 443), and PS5 validates the certificate against trusted CAs. A self-signed cert doesn’t work, and there’s no way to install custom CAs on a PS5.

I then tried YouTube as a workaround. Its RTMP ingest uses plain RTMP on port 1935, so there was no TLS certificate to deal with. The PS5 happily sent the stream to my Mac, so I knew the basic approach worked.

The problem was that PS5 periodically checks YouTube’s API to make sure the stream is actually live. Since YouTube never received the stream, that check failed and it stopped broadcasting after about 60 seconds.

That meant I needed to find a Twitch endpoint that used plain RTMP. The answer came from watching DNS logs while broadcasting:

sudo tail -f /tmp/dnsmasq.log
# Sep 22 23:20:28 dnsmasq: query[A] ingest.global-contribute.live-video.net from 192.168.8.171
# Sep 22 23:20:28 dnsmasq: reply aps30.contribute.live-video.net is 35.55.13.0

The PS5 was resolving ingest.global-contribute.live-video.net, which chains down to aps30.contribute.live-video.net. That’s the real RTMP server. Spoofing contribute.live-video.net covers all subdomains and redirects the actual stream to the Mac without any certificate issues.

DNS Trick

The setup has two main parts: dnsmasq and nginx-rtmp. I built a small macOS menu bar app that bundles both and manages them.

I run dnsmasq on my Mac and configure it to resolve Twitch’s ingest domains to my Mac’s LAN address:

server=1.1.1.1
server=8.8.8.8

# Redirect Twitch ingest traffic to the Mac
address=/contribute.live-video.net/192.168.8.175
address=/ingest.global-contribute.live-video.net/192.168.8.175
address=/live.twitch.tv/192.168.8.175
address=/live-sin.twitch.tv/192.168.8.175
address=/live-nrt.twitch.tv/192.168.8.175
address=/live-syd.twitch.tv/192.168.8.175
address=/live-fra.twitch.tv/192.168.8.175
address=/live-ams.twitch.tv/192.168.8.175
address=/live-lhr.twitch.tv/192.168.8.175
address=/live-jfk.twitch.tv/192.168.8.175
address=/live-lax.twitch.tv/192.168.8.175
address=/live-sea.twitch.tv/192.168.8.175

log-queries
log-facility=/tmp/dnsmasq.log

no-hosts
listen-address=0.0.0.0

192.168.8.175 is my Mac’s IP. When the PS5 asks DNS for one of these Twitch endpoints, dnsmasq returns my Mac’s IP instead. The PS5 connects to my Mac thinking it’s Twitch.

The last piece is pointing the PS5 at this DNS server. I have a GL.iNet router running OpenWRT, so I configured it to hand my Mac’s IP as the DNS server specifically for the PS5’s DHCP lease.

# SSH into the router and run:
uci add_list dhcp.lan.dhcp_option="tag:PS5,6,192.168.8.175"
uci commit dhcp
/etc/init.d/dnsmasq restart

The tag:PS5 part works because the PS5’s static lease already has that tag set in /etc/config/dhcp. Option 6 is the DHCP option for DNS server. The PS5 picks this up on its next DHCP renewal, no manual DNS configuration is required on the console!

Receiving the Stream

For that, I’m using nginx-rtmp:

worker_processes 1;

error_log /tmp/nginx-error.log warn;
pid /tmp/nginx.pid;

events {
    worker_connections 512;
}

rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        application ps5 {
            live on;
            record off;
            sync 10ms;
            # Notify our app when a stream starts
            on_publish http://127.0.0.1:9988/on_publish;
        }
    }
}

http {
    server {
        listen 8080;
        location /stat {
            rtmp_stat all;
        }
    }
}

The on_publish callback is how the menu bar app detects when the PS5 starts broadcasting. nginx fires a POST to localhost:9988 with the stream name, and the app surfaces the full RTMP URL ready to copy.

At this point, the PS5 is pushing its stream (1080p60, H.264, AAC stereo) directly to my Mac instead of Twitch.

From here I can pull the stream into anything: OBS to re-stream it, record it locally, or just play it directly.

Watching It

Instead of going through OBS, I used mpv to pull the stream and shared the window to Discord. The low-latency profile keeps the delay less than a second:

mpv --profile=low-latency --audio-buffer=0.3 rtmp://127.0.0.1/ps5/stream-key

This has been quite reliable surprisingly. I’ve been using it for a few weeks now and haven’t had any issues. You can find the complete source code here.

Until next time! 👋

The Daily Front Page 18 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Electric Drive, Petrol Backup
article

Nissan's third generation e-POWER powertrain

by mroche·▲ 155 points·390 comments·nissan-global.com ↗
drivers can enjoy an EV-like experience with the peace of mind of an onboard gasoline engine

e-POWER is Nissan's unique electric-drive hybrid powertrain that integrates an electric motor with a gasoline engine. Since the system is 100% driven by a high-output motor, drivers can enjoy an EV-like experience with the peace of mind of an onboard gasoline engine for generating energy for the battery.

e-POWER history

e-POWER history

Key points of evolution

The third-generation e-POWER system combines a purpose-built engine designed specifically for e-POWER applications. With the ground-up approach of the purpose-built engine, power generation from the engine is further optimized from the previous generation, including activation timing independent of driving conditions and powerband.

The 3rd-gen's new modular approach, called “5-in-1”, integrates five major components to enhance performance, significantly improving fuel efficiency and quietness.

Compared to 2nd generation e-POWER (Qashqai)

Fuel efficiency improvement

Quietness improvement

5-in-1 electric unit

A 5-in-1 modular approach optimizes the packaging of the motor, reducer, inverter, increaser and generator. This approach achieves a high level of efficiency by increasing current flow for greater output and mitigates energy loss.

5-in-1 e-POWER electric unit

Improving acceleration and energy efficiency requires higher output, which is achieved by increasing electrical flow. This also brings greater efficiency by reducing energy losses. The 5-in-1 system uses flat wire coils that can be arranged with minimal gaps, allowing higher flow through the motor. The inverter also features a latest generation power module and a double-sided cooling structure that efficiently dissipates heat, improving efficiency particularly at high speeds.

In addition, some models use silicon carbide (SiC) power semiconductors in the inverter, which reduce power loss compared with conventional silicon semiconductors. This allows more of the generated electricity to be used to drive the vehicle, reducing the amount of electricity that needs to be generated and helping improve fuel efficiency.

Motor flat wire

Motor flat wire

Inverter double-sided cooling

Inverter double-sided cooling

Improving rigidity through integration avoided interference between the resonance points of the vehicle body to further enhance the system's quietness. This also enabled high-precision assembly, reducing runout tolerances of rotating shafts such as motors and gears, thereby suppressing vibration.

5-in-1 e-POWER electric unit

By sharing the 3-in-1 EV powertrain and its components, we not only contribute to reducing the number of parts and production investment but also leverage the technologies and expertise of both EV and e-POWER to efficiently drive the development of further optimized electrified powertrains.

Purpose-built engines for power generation

There are two types of power-generation-focused engines available.
By leveraging a purpose-built onboard engine for power generation, Nissan engineers have achieved a highly efficient powertrain design that significantly improves fuel economy over previous e-POWER applications. A contributor of this is an engine that can maintain a stable combustion cycle.

Purpose-built engine HR14DDe

Purpose-built engine HR14DDe

Purpose-built engine with turbo ZR15DDTe

Purpose-built engine with turbo ZR15DDTe

In general, to improve engine efficiency, it is important to increase the compression ratio and raise the EGR*1 ratio, which recirculates and mixes exhaust gas with the air intake system. Since a typical engine operates across a wide RPM range depending on driving conditions, it is difficult to maintain a stable and optimal combustion cycle.

Nissan's purpose-built engines can operate at a constant speed and maintain stable combustion thanks to their long-stroke design that creates a strong in-cylinder flow (tumble flow). This enables combustion stability even with a high compression ratio and high EGR rate.

To further improve fuel efficiency and output, ZR15DDTe engine uses Nissan's unique STARC*2 concept paired with a large turbocharger.

The STARC concept is the embodiment of research findings that highlight the importance of controlling airflow toward the spark plug inside the combustion chamber to improve ignition. The concept involves managing airflow so that the discharge channel from the spark plug remains stable, guiding combustion effectively and providing a stable combustion even with a high EGR rate.

By using cold spray technology to integrate the valve seat into the engine's intake port, the ideal port shape is achieved, allowing air to be forcefully directed into the cylinder with a strong tumble flow. Additionally, the piston crown is precisely shaped to maintain tumble flow during compression, thus ensuring ignition with a strong spark and stable combustion.

The large turbocharger forces a substantial amount of compressed exhaust gas and air into the cylinder, boosting output while also improving the engine's thermal efficiency.

Engine's cross-sectional view

STARC Combustion

  1. Exhaust Gas Recirculation
  2. STARC (Strong Tumble & Appropriately stretched Robust ignition Channel) is a combustion concept announced by Nissan in 2021, delivers impressive thermal efficiency
The Daily Front Page 19 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — The Pedal Workshop
repository

Guitar amp and effects pedal built on the Waveshare ESP32-S3-Touch-AMOLED-2.06

by arbayi·▲ 161 points·82 comments·github.com ↗
★ 222⑂ 9 forks C++

ESP32-S3 A2-Full NAM pedalboard with direct SD-card NAM loading and a Gea-compiled native frontend

CoyoPedal

CoyoPedal

A standalone guitar amp and effects pedal built on the Waveshare ESP32-S3-Touch-AMOLED-2.06. It runs full-size Neural Amp Modeler A2 captures in real time on the ESP32-S3, drives a class-compliant USB audio interface as a USB host, and has a touchscreen UI written in TSX that is compiled to native C++ — there is no JavaScript engine on the device.

The screen is one board's worth of it rather than the pedal itself: the same firmware builds for a bare ESP32-S3 module with no panel at all, where the amp, the effects and the presets are the same and the BOOT button is the footswitch.

Play it in your browser → The same firmware compiled to WebAssembly: the same UI, the same DSP, the same neural amp model, playing your guitar through an audio interface. No board required to try it, and nothing to install.

  • Full-size NAM A2 models at 48 kHz. The 23-layer, eight-channel WaveNet runs in block floating point with hand-written Xtensa kernels, split across both cores and processed in 64-frame blocks.
  • Load your own captures. Copy original .nam files to a microSD card, or point the browser build at a folder. The pedal parses, validates and prepares them on the device; there is no desktop converter.
  • An effects chain around the amp: gate, compressor, chorus and drive before it; digital delay and stereo spring reverb after it.
  • Presets for amp, controls and effects, stored on the pedal, with an on-screen keyboard for naming them.
  • A tuner on the same screen, with the output muted while tuning.
  • Maintenance mode with authenticated Wi-Fi OTA updates, remote diagnostics and BLE discovery. The radios are completely off while playing.

Hardware

Supported boards

Board Alias Flash What it has How you control it
Waveshare ESP32-S3-Touch-AMOLED-2.06 amoled 32 MB ESP32-S3R8, 8 MB PSRAM, 410 × 502 AMOLED, touch, AXP2101 PMIC, microSD slot Touchscreen; BOOT: tap to bypass, hold 1.5 s for maintenance
ESP32-S3-DevKitC-1 N16R8, and bare S3R8 modules s3-devkit 16 MB ESP32-S3R8, 8 MB PSRAM, no panel, no PMIC, no SD slot BOOT: tap to engage or bypass, hold 1.5 s for maintenance mode

The AMOLED board is the reference. It is what the factory presets, the browser build and the screenshots are made against, and the panel-specific parts of the firmware exist for it. A board with no screen runs the same amp through the same DSP at the same 48 kHz — measured on the devkit at 91% and 94% of the 1,333 µs block budget across the two cores, with no missed deadlines — and is configured over the maintenance API instead of by hand.

What a board has to bring either way: an ESP32-S3 with 8 MB of PSRAM, because that is where the A2 model lives, and a USB port the chip can drive as a host. A bare module has no PMIC and no battery path, so unlike the AMOLED it does not feed the host port itself; the interface needs power from your own supply.

Everything else

Part Notes
Audio A USB Audio Class 2 interface on the board's USB port, which runs as a USB host at 48 kHz
Storage Optional microSD card, on a board that has a slot, for your own captures
Tested with XTONE Pro and IK Multimedia iRig HD X; iRig HD 2 through a dedicated UAC1 profile

The interface is discovered from its USB descriptors, so any interface that exposes a 48 kHz UAC2 input and output should work. See USB audio for the formats and limits.

Using the pedal

The home screen shows the chain in signal order. Tap a block to turn it on or off, or hold it to edit it: drag a slider to change a value, and use ‹ › to page through the controls. Hold the Amp block to open the capture browser, which shows the factory captures, the imported ones and the SD card's own folders. The switch at the top right bypasses the whole pedal, and Tuner opens the tuner.

Tap the preset name to switch, save, rename, delete or create presets. A new preset starts from the current sound.

On every board, BOOT works as a footswitch: a short press engages or bypasses the pedal, and holding it switches between audio and maintenance mode. The switch starts the moment the hold reaches 1.5 seconds, so the screen tells you when you can let go. Short presses do nothing in maintenance mode. On a board with no screen, presets, captures and the rest of the controls are reached from maintenance mode with tools/esp32/amoled_remote.py. The pedal boots engaged with the remembered preset, or the first preset, Silver Lining (clean), when no selection has been saved.

Your own captures

Supported models are 48 kHz, eight-channel NAM A2 ("A2-Full") WaveNets, including a matching member of a SlimmableContainer. Other architectures, sample rates and layer shapes are rejected with an error. Prepared .namb files are accepted as well.

Format a card as FAT and put .nam or .namb files anywhere under a nam folder at its root, in whatever folders you like (up to six levels deep); the browser shows that tree as it is, and a capture is named after its file. File names must fit in 127 bytes and files in 2 MiB. Insert the card before powering on, then pick the capture from the Amp browser.

The first time a capture is selected, audio pauses while the pedal prepares it. This can take tens of seconds. When the card is writable, the pedal stores a verified .s3cache file next to the original, so later loads are fast. The original file is never modified.

The full VoLum library is published in the VoLum repository, and this copies it to a mounted card as /nam/VoLum/<amp>/:

npm run fetch:volum -- /Volumes/SDCARD

The same captures in a browser

coyopedal.playtaurus.com runs the firmware itself, and it has no card slot, so it asks for a folder instead and answers the firmware's SD calls out of it. The captures show up under SD card in the pedal's own amp browser with the same names and the same ids they would have on the card, an original .nam is prepared with the same tuner and cached beside the file as .s3cache exactly as the board caches it, and presets are mirrored into the folder as coyopedal-presets.json — the same document assets/presets.json is, which you can open in a text editor, keep in a repo or drop onto a card. Fill a folder in the browser, copy it to a card, and the board reads it without preparing anything again.

Chrome and Edge write back to the folder; Safari and Firefox will only let a page read one, so there the writes are kept in the browser's own storage.

Building

Requirements

  • Git and Node.js 22.13 or newer
  • Python 3 with Pillow and fontTools, used to rasterize the UI font. The npm scripts find it under whichever name the platform uses (python3, python or the Windows py launcher).
  • A C++20 compiler and CMake, for the host tests
  • The Emscripten SDK on PATH, for the web build only

The Gea CLI installs everything else, including ESP-IDF.

Setup

  1. Install the Gea CLI:

    npm i -g @geastack/cli
    
  2. Install ESP-IDF 6.0.2 and its ESP32-S3 toolchain. It goes to ~/esp/esp-idf; an existing install under ~/esp or ~/esp32, or at IDF_PATH, is found automatically.

    gea setup --esp-idf
    
  3. Clone the repository and install its dependencies:

    git clone git@github.com:dashersw/coyopedal.git
    cd coyopedal
    npm ci
    
  4. Generate the Wi-Fi configuration. Maintenance mode, OTA updates and the remote tools are compiled in only when src/native/services/remote_config.h exists; a clone does not have it, and a build without it is a pedal with no radio at all. The file is gitignored because it holds the credentials.

    npm run remote:configure -- --ssid YOUR_WIFI
    

    It asks for the Wi-Fi password; the pedal joins that network in maintenance mode. Skipping this step is allowed: the build then writes a disabled stub in its place, and generating the real file later and building again is enough.

  5. Connect the board over USB and register it:

    gea setup
    

    Choose Known supported board, then Waveshare ESP32-S3 Touch AMOLED 2.06, and keep the alias amoled: the npm scripts use it. Select the detected USB device. The CLI identifies the board by its USB serial number, so it does not matter which port it shows up on. The OTA host is optional.

    For a board without a screen, see Another board below; the rest of this section is the same.

  6. Check the toolchain and the board:

    gea doctor
    

Build and flash

gea build --board amoled

The firmware image is written to build/pedalboard.bin . The ESP-IDF build tree stays in .gea/build/; you never need to open it.

The first flash has to go over USB, because it writes the partition table and the factory data as well as the firmware:

gea flash --board amoled

Add --dry-run to see what would be written without flashing. npm run build:firmware and npm run flash:firmware run the same two commands. --board s3-devkit builds the same firmware for the headless board; the npm scripts are the amoled shorthand.

On the AMOLED the flash is laid out as two 8 MB OTA slots, a factory-model partition, a factory-preset partition and a partition for imported models. Saved presets live in NVS, which flashing does not erase. A board with a different flash size gets its own layout — see below.

Another board

The firmware does not carry a list of boards. It asks the target definition what the hardware has and compiles out whatever is absent, and two questions decide almost everything.

Is there a screen? A target definition with neither a chips.display nor a canvas means the board has no display at all, and the build gets GEA_EMBEDDED_NO_DISPLAY=1: no framebuffers, no app tree, no frame scheduler, no runtime task. That is about 1 MB of image and 1.25 MB of PSRAM a panel board spends and this one never allocates. Note that a canvas without a panel is a different thing — an offscreen surface that still renders, for screenshots and OTA previews — so it is the absence of both that means "no display". Do not give a headless board an empty canvas.

Is there a PMIC? A definition that declares no power chip builds with GEA_BOARD_HAS_POWER=0, and src/native/drivers/power.cpp compiles to a no-op rather than failing to link against an AXP2101 that is not on the board.

To bring a new board up:

  1. Pick or write its target definition in @geastack/targets. The devkit's is targets/esp32-s3-devkit-n16r8.json.
  2. Register an alias for it with gea setup, or by hand in .gea/boards.json: the target id, the adapter (esp32-idf), the board's USB serial number, and flashSize when it is not 32 MB.
  3. If the flash size differs from the AMOLED's, add that board's partition layout under gea.targets.esp32.partitionsByTarget in package.json, keyed by target id. The default gea.targets.esp32.partitions stays the 32 MB one, and a board without an entry of its own uses it.
  4. gea flash --board <alias> --monitor.

One rule worth knowing when a board misbehaves at compile time: the app's own gea.defines win over the board's. The pedal declares its display dimensions, so a board that also declares a canvas size does not get to redefine them.

Checks and tests

npm test      # USB descriptors, effects, presets and the prepared NAM model
npm run check # lint, TypeScript and formatting

GitHub Actions runs both on every push and pull request, and builds the firmware image and the web module as well. A runner has no board, so the firmware job stops at the image — which is still the thing worth having, because the amp graph, the panel and the drivers only meet at the link step.

The two browser builds

npm run dev is a DOM preview: the same TSX recompiled onto the web framework and laid out by the browser. It is quick to iterate on, and it drifts from the board exactly where you would want to trust it.

The deployed page is the other one. geatsc lowers the same TSX to C++ and emcc links it with the same Gea layout and paint engine the firmware runs, so what the page shows is what the panel shows:

npm run build:web-wasm
npm run serve:web

Serving it locally matters: the audio graph runs in an AudioWorklet over shared memory, and a browser only hands out SharedArrayBuffer to a cross-origin-isolated document, which is what scripts/serve-web.mjs and the web/_headers file arrange.

A push to main publishes it. GitHub Actions builds the module and uploads the site to the R2 bucket it is served from, so the page and the module it names are always stamped and uploaded together. That workflow runs scripts/deploy-web.sh, which stages build/site and uploads it; run it yourself to publish without a push, and it wants CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN in the environment or in a .env the repository never tracks. --stage stops after staging.

That token is an R2 API token with Object Read & Write on this one bucket and nothing else. The upload goes over R2's S3 API rather than through Wrangler, because Wrangler's r2 object commands use a REST endpoint that accepts only an account-wide R2 Admin token and answers 403 to a token scoped this narrowly. The token is the only secret needed: scripts/r2-credentials.sh derives the S3 key pair from it.

The bucket is served through a custom domain, and the two cross-origin isolation headers in web/_headers are set by a response header transform rule on the zone: R2 serves only the headers an object carries as metadata, and those two are not among them. Cache-Control is per-object and the script sets it.

Maintenance mode and OTA updates

Maintenance mode unloads the audio graph and starts Wi-Fi and BLE. Enter it by tapping the preset name, then Setup, then Maintenance mode, or with the board's BOOT button — hold it until the screen says "Please wait", about 1.5 seconds, on either board. Hold it again, or choose Return to pedalboard, to reboot into audio mode with the radios off. The pedal always starts in audio mode, unless the previous boot crashed.

Wi-Fi credentials and the authentication token are compiled into the firmware from src/native/services/remote_config.h, which is gitignored. Without that file the whole service, and with it Wi-Fi, BLE and the HTTP server, is left out of the image, about 400 KB less flash, and the pedal cannot enter maintenance mode. Generate it before building:

npm run remote:configure -- --ssid YOUR_WIFI

The pedal joins that network in maintenance mode and amoled_remote.py discover finds it there. remote_config.h.example shows the generated format.

With the pedal in maintenance mode, tools/esp32/amoled_remote.py finds it, reads its logs and updates it:

npm run remote -- discover
npm run remote -- --host PEDAL_IP ota

ota uploads build/pedalboard.bin unless you pass another image. After an OTA update started from maintenance mode, the pedal boots the new image in audio mode once, then returns to maintenance mode so you can check the logs. Run the script with --help to see the diagnostic commands.

Repository layout

src/
  ui/          Touchscreen app (TSX, CSS, stores) for the device and the browser
  preview/     Browser adapter with a simulated pedal
  audio/       Effects, tuner and the per-block audio processor
    nam/       NAM A2 engine and its ESP32-S3 assembly kernels
  native/      Firmware
    main/         Boot, mode selection and audio graph lifecycle
    drivers/      USB audio host, flash storage, power
    audio/        Board-side DSP controls and PCM packing
    storage/      Model catalogue, SD import, .nam parsing, presets
    services/     Maintenance Wi-Fi, OTA, BLE discovery
    ui/           Bridge between the UI and the audio controls
    nam_banks/    Fixed-address allocator for the model's SRAM banks
    diagnostics/  Heap census
web/           The page that hosts the WASM build, and its bridge to the browser
assets/        Factory captures, capture library index, presets, fonts
scripts/       Build, deploy, test, format and preview helpers
tools/         Asset packers and the maintenance client
tests/         Host tests
third_party/  Vendored ESP-IDF USB host and cJSON
docs/          Architecture, memory layout and USB audio notes

Start with docs/ARCHITECTURE.md for how the pieces fit together, and docs/MEMORY.md before changing anything that allocates memory or places code.

Factory captures

The firmware ships with two captures from VoLum by Lum: Diezel Herbert, channel 1, V30 cabinet and Ampete One, channel 4, V30 cabinet. They are distributed under the MIT License; see THIRD_PARTY_NOTICES.md.

Contributing

Issues and pull requests are welcome. CONTRIBUTING.md covers the checks, the formatting rules and the handful of things about this codebase that are easy to get wrong — the firmware is a Gea app, so everything the native build needs is declared in package.json rather than in a CMake file of its own.

License

This project is licensed under the GNU General Public License v3.0. Third-party components keep their own licenses, and the firmware carries one additional permission for the Espressif binary components it links; see NOTICE.md and THIRD_PARTY_NOTICES.md.

The Daily Front Page 20 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Coats of Arms, by Algorithm
article

What heraldry and Japanese mon can teach about visual-identity generators

by bovermyer·▲ 72 points·23 comments·benovermyer.com ↗
heraldry as a system that can be represented in software

I spend a lot of time thinking about heraldry, but perhaps not in quite the same way that a heraldic historian does. For Iron Arachne, I have to think about heraldry as a system that can be represented in software. That changes the questions I ask. It’s easy enough to assemble a catalog of lions, eagles, crosses, swords, flowers, and crowns and randomly select from it. This is pretty much what the very first version of the heraldry generator did. The heraldry generator is older than Iron Arachne itself, in fact, and none of the original code is part of the current site.

That can produce something that looks vaguely heraldic. It does not, however, reproduce heraldry. A heraldic tradition is not merely a collection of symbols. It’s a system of rules governing how those symbols are selected, described, arranged, combined, distinguished, and recognized.

That raises a more interesting problem for procedural generation: how can I represent those systems programmatically while remaining reasonably faithful to the historical circumstances in which they developed? Comparing European heraldry with Japanese mon is particularly useful because the two traditions solve some similar problems using remarkably different visual systems. Those differences suggest different approaches to procedural generation.

Glossary

This article describes a few different concepts that you might be unfamiliar with. I’ve put together a glossary here to define some of the terms. Feel free to skip to the next section if you know them already.

  • Procedural generation: creating things by applying rules rather than selecting finished examples from a catalog.
  • Blazon: the conventional verbal description of a coat of arms.
  • Field and tincture: the field is a shield’s background; a tincture is the heraldic name for a color or metal used in the design (Azure is blue, Or is gold).
  • Charge, motif, and attitude: a charge is a figure placed on the field; its motif is the kind of figure, and its attitude is its pose (a lion rampant is reared upright).
  • Ordinary and division: an ordinary is a standard geometric charge, such as a cross or broad stripe; a division splits the field into regions.
  • Mon and kamon: a mon is a Japanese emblem; kamon specifically means a family emblem.
  • Grammar and corpus: grammar means the rules for constructing designs; a corpus is the collection of historically documented examples.
  • Morphology and syntax: morphology describes the forms a language’s terms take; syntax describes how those terms are arranged.
  • Abstract syntax tree and scene graph: an abstract syntax tree is a nested structure of the parts of a description; a scene graph organizes visual objects and their relationships.
  • Finite state machine: a model of a process moving among a limited set of named states according to rules.
  • Cadency and marshalling: cadency distinguishes the arms of family branches; marshalling combines arms to show inheritance or alliance.
  • Negative space: the open areas around and between shapes.
  • SVG: a text-based format for scalable vector images.
  • Enum and tagged union: an enum is a fixed list of named choices; a tagged union is a value that can take one of several named forms.

Heraldry as a Generative System

Western European heraldry is unusually convenient for programmers because it already has something resembling a formal language. A coat of arms can be described using a “blazon”: a specialized vocabulary and grammar capable of describing a heraldic design with enough precision that someone familiar with the system can reconstruct it. Here’s a simple example.

Consider a simple hypothetical blazon:

Azure, a lion rampant Or.

Even without seeing the shield, someone familiar with heraldry can reconstruct its essential appearance. The field is blue (azure). Upon it is a lion standing in the conventional rampant posture. The lion is gold or yellow (Or).

A gold lion rampant on a blue shield

An image of 'Azure, a lion rampant Or' as produced by the Iron Arachne heraldry generator

More complicated arms add divisions of the field, ordinaries, multiple charges, positional relationships, variations in tincture, and other qualifications, but the basic idea remains the same. The blazon is not simply a name assigned to a picture. It is a structured description of one. That makes blazon interesting from a computational perspective. It behaves somewhat like a constrained natural language: a language with rules that limit which combinations are valid.

A blazon has a vocabulary, morphology, syntax, and an expected ordering of information. Some constructions are valid while others are not. Earlier parts of the description establish a context in which later parts are interpreted. A relatively small collection of rules and terms can describe a very large space of possible images.

This resembles the generative systems studied in linguistics. Rather than storing every possible sentence, a language provides rules capable of generating an effectively unlimited number of sentences. Heraldry does something similar for visual designs.

For a procedural generator, that suggests an obvious architecture: generate a valid heraldic description first, then render it. In principle, the same blazon could even be handed to several different renderers. They might produce stylistically different lions, shields, or fleurs-de-lis, while all producing recognizable representations of the same arms. The underlying identity lies partly in the abstract description rather than in one exact drawing.

Japanese Mon Take a Different Route

Japanese mon and kamon present a rather different problem. Like European heraldry, mon served as visual identifiers and could be associated with families, individuals, institutions, and political relationships. They appeared on clothing, banners, equipment, buildings, and other objects.

But treating mon as simply “Japanese coats of arms” obscures substantial differences between the traditions. Most importantly for procedural generation, there is no direct equivalent to blazon at the center of the system. Mon are generally highly stylized designs constructed from recognizable motifs: plants, animals, celestial objects, tools, geometric figures, and other forms. Those motifs are abstracted into a compact visual vocabulary and arranged according to recognizable compositional patterns. One of the most famous examples is the Tokugawa mitsuba aoi: three stylized hollyhock (or ginger) leaves arranged rotationally around a central point.

The Tokugawa mitsuba aoi mon, with three stylized leaves arranged around a central point

The Tokugawa mitsuba aoi mon. Art by Hyakurakuto - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=1056853

The important thing here is not simply that the design contains three leaves. Its identity comes from the combination of a particular stylized leaf form, repetition, orientation, spacing, symmetry, and overall silhouette. A generator approaching this design as though it were a Western blazon might begin with something like “three hollyhock leaves.”

That description contains some of the correct information, but nowhere near enough to reproduce the mon. The geometry matters. This suggests a different procedural model.

Instead of generating a linguistic description and resolving it into an image, a mon generator can operate much more directly on graphical primitives:

Take a base shape. Duplicate it three times. Rotate each copy around a common origin. Scale and position the elements according to a template. Clip or enclose the result within a circle where appropriate.

The resulting system begins to resemble procedural geometry more than natural-language generation.

Two Different Generation Strategies

This gives us two strikingly different models for generating heraldic designs. Western heraldry can be treated as primarily descriptive. Generate a structured description of an object and then render that description. Japanese mon can be treated as primarily compositional. Generate a visual structure by combining and transforming graphical elements.

Comparison diagram: Western heraldry moves from rules to a blazon and rendered arms; Japanese mon moves from a leaf motif through rotation and repetition to a composed emblem

Two useful computational models for generating heraldic designs

That distinction is not absolute. Western heraldry obviously contains extensive compositional rules, and mon have names and conventional classifications. Neither historical tradition was invented as a software architecture. Nevertheless, the distinction is useful when deciding how to represent them computationally.

Consider how each system might represent three repeated objects. In Western heraldry, the important information might include the identity of the charge, its tincture, its number, and its arrangement. “Three roundels argent, two and one” communicates an arrangement that a heraldic artist can interpret. A mon generator might instead express a similar concept geometrically:

  1. Load the base motif.
  2. Make three instances.
  3. Place their origins at a defined radius from the center.
  4. Rotate the instances by 0, 120, and 240 degrees.
  5. Scale them until their outlines satisfy the desired spacing.
  6. Apply any enclosing or masking geometry.

The Western representation is closer to an abstract syntax tree. The Japanese representation is closer to a scene graph. For procedural generation, both are extremely attractive.

Rules Matter More Than Symbol Lists

This comparison also demonstrates why simply collecting historical symbols is insufficient. Western heraldry has rules governing tinctures, field divisions, ordinaries, charge placement, repetition, cadency, marshalling, and many other features. The famous “rule of tincture,” for example, generally discourages placing a metal on a metal or a color on a color. The practical effect is strong visual contrast: a gold lion on a blue field is readily distinguishable, while a red lion on a blue field is less so. A generator that chooses a random field color and then independently chooses a random charge color will therefore produce combinations that violate one of the most recognizable conventions of the system.

The better approach is conditional generation. Choosing the field constrains what can come next. If the field is a color, the generator can preferentially select a metal for a major charge. If the field is divided, another set of possibilities becomes available. If an ordinary is present, the possible placement of other charges changes.

Mon impose different constraints. Symmetry, repetition, enclosure, negative space, and the degree of abstraction become particularly important. A randomly selected flower pasted three times onto a circle is no more convincingly a mon than a randomly selected lion pasted onto a shield is convincingly a coat of arms. In both cases, the generator needs to model relationships rather than merely objects.

And Then There Are the Exceptions

Unfortunately for programmers, historical visual systems are rarely as tidy as their introductory rules make them appear. Western heraldry is full of exceptions, disputed conventions, regional differences, historical developments, and arms that appear to violate rules presented as fundamental. The rule of tincture itself has famous exceptions.

The arms traditionally associated with the Kingdom of Jerusalem place gold crosses on a silver field: metal upon metal. That is not a bug in heraldry. It is evidence that the “rule” is a historical convention rather than a law of physics.

A silver shield bearing a gold cross potent and four smaller gold crosses

The arms of the Kingdom of Jerusalem. Art by Heralder, cross by Katepanomegas - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/wiki/File:Arms_of_the_Kingdom_of_Jerusalem.svg

A procedural generator therefore has to decide what sort of system it is modeling. Is it attempting to generate arms that would satisfy a modern herald’s expectations? Arms characteristic of fourteenth-century England? A broad fantasy approximation assembled from several European traditions? Those are different generators.

Mon present the same problem from another direction. A clean taxonomy of motif plus repetition plus enclosure is useful for software, but the historical corpus does not exist to make my TypeScript interfaces convenient. Designs can be altered, combined, simplified, differentiated, or used in multiple forms. Families could use more than one mon, related groups could use variations of a design, and similar motifs could appear independently.

Even the idea that a mon corresponds neatly to one family in the same way that a coat of arms belongs to a particular person entitled to bear arms can be misleading. Real heraldic systems contain history, and history produces irregularity. One possible solution is to distinguish between grammar and corpus.

The grammar describes the normal operations available to the generator. The corpus records historically attested forms, including forms that the general grammar would be unlikely or unable to generate. That approach lets the software say, in effect: “This is how designs of this tradition are usually constructed, but these specific exceptional designs also exist.”

What Should Iron Arachne Actually Generate?

This comparison raises a question for Iron Arachne’s existing crest generator. Should a fantasy crest generator really be modeled primarily on Western blazon? Perhaps not.

Blazon is attractive because it provides an unusually rich formal vocabulary. From a programmer’s perspective, it is tempting to reproduce that vocabulary directly. Generate a field, select tinctures, select charges, determine their attitudes and arrangements, and serialize the result as a blazon. But Iron Arachne’s actual goal is usually to produce an interesting visual artifact for a fictional setting. In that context, the compositional logic demonstrated by mon may be more useful.

That changes the question I ask. Instead of asking, “what heraldic sentence should I generate?” I can ask “what visual relationships should I generate?” A crest could begin with a small set of graphical primitives.

Those primitives could then be reflected, rotated, repeated, nested, intersected, or arranged around an axis. Heraldic charges could themselves become primitives in a larger compositional system. The result would not necessarily be historically valid European heraldry or Japanese mon. It would instead borrow a useful procedural insight from both.

Western heraldry provides a grammar of meaningful categories and relationships. Mon, on the other hand, provide a grammar of visual composition. Combining those ideas may produce a better fantasy symbol generator than faithfully implementing either tradition alone.

How Difficult Are They to Generate?

At first glance, Western heraldry seems easier to generate because so much of its structure has already been formalized in language. A subset of blazon can be represented quite naturally using enums, tagged unions, grammar rules, or an abstract syntax tree. A renderer can walk that structure and produce SVG elements.

The difficulty grows rapidly, however, as the supported vocabulary expands. Charges can have different attitudes. Fields can have complex divisions and treatments. Charges can themselves bear charges.

Marshalling introduces compositions of entire arms. Historical and regional vocabularies differ. Generating some plausible Western arms is relatively easy. Implementing heraldry is not.

Mon have almost the inverse difficulty. A limited mon-like generator is extremely easy to imagine. SVG is particularly well suited to the problem because it already provides paths, groups, transformations, clipping, masks, and reusable definitions. A base motif can be defined once and instantiated repeatedly with transformations.

Reproducing the historical variety of actual mon is much harder. The difficult part is not drawing three rotated copies of a leaf. It is constructing a vocabulary of motifs and transformations that reproduces the visual logic of historical examples without merely tracing and storing thousands of finished designs. The boundary between generating designs and selecting designs from a catalog is where the interesting procedural-generation problem lies.

Can Heraldry Be a Finite State Machine?

One of the things I studied in my graduate program this year is the concept of finite state machines. That got me to thinking about how I could apply them to Iron Arachne. In this case, can either visual identity system be represented as a finite state machine?

For a deliberately restricted subset, sure. A Western generator begins with the field and its tincture, may add an ordinary and its tincture, then chooses charges, their tinctures, and arrangement before completing the arms. Transitions can be constrained by previous choices.

Selecting a color field, for example, can change the permitted or weighted tinctures of a charge. A mon generator begins with a motif, chooses a repetition scheme and symmetry, then settles orientation, enclosure, and any embellishment. Again, earlier choices constrain later ones.

Two flowcharts: Western arms proceed through field, tincture, optional ordinary, charges, and arrangement, with field tincture constraining charge tincture; a mon branches between a single motif and radial repetition, then considers symmetry, orientation, optional enclosure, and embellishment

State transitions can branch, skip optional elements, and carry constraints forward

But I suspect that a pure finite state machine is the wrong final abstraction for either system. Both systems are hierarchical. A charge can contain or interact with other charges. A field can be divided into regions that themselves need descriptions.

A mon can contain groups of repeated elements inside larger enclosing or repeated structures. That points toward grammars, trees, or graph-like representations rather than a flat state machine. A finite state machine may be useful for controlling the generation process, while a tree represents the generated design. That distinction is probably worth preserving in Iron Arachne.

The Bigger Lesson

The most useful thing I have learned from comparing these traditions is that procedural generation should not begin by asking what objects exist in a particular domain. It should begin by asking what operations exist. A catalog tells me that heraldry contains lions, eagles, crosses, hollyhocks, chrysanthemums, circles, diamonds, and thousands of other motifs.

A generative system tells me that things can be divided, repeated, mirrored, rotated, enclosed, superimposed, contrasted, grouped, and subordinated to one another. The second list is much more powerful. This is applicable well beyond heraldry.

Whenever I want to procedurally generate something derived from a historical visual tradition, I need to resist the temptation to treat the tradition as an asset library. I have failed to resist this temptation in the past. The first versions of the heraldry generator were basically this. The goal should be to identify the rules that produce recognizable structures. The difficult part is determining which of those rules actually belonged to the historical tradition and which are classifications imposed afterward by people trying to explain it.

Future Work: Other Visual Grammars

Japanese mon and Western European heraldry are only two examples of systems that encode identity visually. There are many others worth investigating from the perspective of procedural generation. Each uses a different visual vocabulary and set of conventions to communicate identity.

Scottish tartans provide an obvious example, with identity represented through repeating sequences of colored bands and their intersections. Flags provide another, particularly because vexillology combines geometric composition with a relatively restricted vocabulary of divisions, colors, and symbols. Merchant marks and masons’ marks offer much simpler systems of personal identification. Military insignia, cattle brands, seals, maker’s marks, and modern corporate logos all solve related problems under different technological and social constraints.

Even writing systems may belong somewhere in this investigation. Once visual identity is understood as a grammar rather than a catalog, the boundary between generating an emblem and generating a glyph becomes surprisingly thin. That is particularly interesting for Iron Arachne, where fictional writing systems, heraldry, flags, and other cultural artifacts ultimately face the same procedural question: what is the smallest useful set of rules from which I can generate something that looks as though it belongs to a coherent visual tradition? I suspect that is a much more productive question than asking how many symbols I can put in a database. This is something I’m working on now, and might be the theme of the next big update to Iron Arachne.

Sources and Further Reading

Bartolus de Saxoferrato. De Insigniis et Armis. c. 1350.

Dower, John W. The Elements of Japanese Design. Weatherhill Inc., 2000.

Friar, Stephen. A New Dictionary of Heraldry. Alphabooks Ltd., 1987.

Turnbull, Stephen. Samurai Heraldry. Osprey Publishing, 2002.

“A Roll of Japanese Armory”. Academy of Saint Gabriel.

The Daily Front Page 21 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Worlds Remembered and Rendered
article

37,500 border drawings: a map of the world as people remember it

by nicocarsui·▲ 169 points·31 comments·habibicode.org ↗

Every border and coastline people have drawn playing Borderline games.

Country drawings

Here is a detailed view at all the drawings displayed in the map above. D is the Daily, LB Borderline’s land border rounds, C its coastline rounds.

Every line anybody has drawn, country by country, over the real outline in grey. The number beside each name is how many drawings are on it.

Country D LB C All Median score Median error

Counting…

The Daily Front Page 22 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Worlds Remembered and Rendered
article

Windows 11½

by jjbinx007·▲ 446 points·140 comments·definitelynotwindows.com ↗

The operating system Microsoft definitely did not make.

Yes, this is a parody.
Definitely Not Windows / Windows 11½ is an independent, unofficial parody project created for humor, satire, and commentary. It is not affiliated with, endorsed by, sponsored by, or approved by Microsoft Corporation.

What this is
A fake operating-system experience making fun of modern software subscriptions, ads, AI features, updates, storage nags, and the tiny emotional journey involved in changing your default browser.

What this is not
A real Microsoft product, service, login page, update, store, security warning, or subscription offer. Please do not give Clippy your password or credit card. He has not completed compliance training.

Clippy's visitor ledger
Your browser gets a random anonymous ID so Clippy can assign it a persistent visitor number. The ledger is checking your file now. No name, email, password, or browser fingerprint is needed.

Why would you do that?
Because a paperclip remembering that you are Visitor #… is funnier than a normal hit counter. Clearing this site's browser storage makes Clippy treat you like a suspiciously familiar new person.

Trademark note

Microsoft, Windows, Microsoft 365, Edge, Outlook, OneDrive, Teams, Xbox, and other referenced product names and marks belong to their respective owners. They are referenced here to identify the subjects of parody and commentary.

No endorsement is implied. Any resemblance to a stable, predictable operating system is purely coincidental.

This site is a joke. Buttons may pretend to install apps, sell subscriptions, break Windows, summon AI, or ruin your evening with an update. None of those actions are real. No Microsoft credentials are requested or required. The optional visitor counter uses a randomly generated ID stored in this browser plus a server-side visitor number, visit count, and timestamps. It does not need your name, email, password, or browser fingerprint. If a fake dialog says your storage is full, your real storage is probably fine. Probably.

The Daily Front Page 23 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Machines at the Edge
article

Self-Hosting on the Dark Web

by mooreds·▲ 343 points·111 comments·david.alvarezrosa.com ↗

This site is now reachable over Tor as a hidden service, at a .onion address that resolves only inside the Tor network. Open it in the Tor Browser. There is no certificate authority, no DNS, and no exposed IP—the address is derived directly from a public key, and the connection is end-to-end encrypted by Tor itself. Tor relays and encrypts your traffic as it passes through thousands of volunteer-run servers, so that no single party can link who you are to what you are doing; a hidden service extends that anonymity to the server itself.

It’s built by the nonprofit Tor Project, which advances human rights and freedoms through free software and open networks, so that anyone can use the internet free from tracking, surveillance, and censorship. The network only works because people use it, so consider supporting them or running a relay—your contribution helps millions stay safe and private online every day.

The hidden service

Install Tor and point a hidden service at a local port. Edit /etc/tor/torrc

HiddenServiceDir /var/lib/tor/blog/
HiddenServicePort 80 127.0.0.1:8080

The directory must be a dedicated, Tor-owned path—not your web root. Tor stores the service’s private key and hostname file here and insists on owning it (chmod 700, user debian-tor). Point it at your site files and Tor refuses to start. Restart Tor and read the address it generates

$ sudo systemctl restart tor@default
$ sudo cat /var/lib/tor/blog/hostname
dhevt6e4rtgbtr3jh53xrpwmgtilkah6nyjujocsspssrsexc7omxhid.onion

Serving the site

Tor forwards the onion’s port 80 to 127.0.0.1:8080, so the web server just needs to listen there. Add an nginx server block for it—no TLS, no HTTP/2, no QUIC, since Tor speaks plain TCP and provides its own encryption.

server {
  listen 127.0.0.1:8080;
  server_name dhevt6e4rtgbtr3jh53xrpwmgtilkah6nyjujocsspssrsexc7omxhid.onion;

  root /srv/tor.david.alvarezrosa.com;
  index index.html;
  error_page 404 /404/index.html;

  location / {
    try_files $uri $uri/ =404;
  }
}

Reload nginx and the site is live on Tor.

Building for the onion

A static site bakes its base URL into absolute links, so a clearnet build would point visitors back to the clearnet domain even when served over Tor. The fix is to build a second copy with the onion as its base URL

$ hugo --minify --baseURL="http://dhevt6e4rtgbtr3jh53xrpwmgtilkah6nyjujocsspssrsexc7omxhid.onion/"

The deploy pipeline does this automatically: every push builds the site once per target—clearnet and Tor—and rsyncs each to its own web root, so the two stay in sync without any manual work. See First Steps on a New Server for the underlying machine; the full configuration lives in my homelab repository, and the site’s own repository holds the GitHub Actions workflow that builds and deploys the Tor copy.

That’s it. Read this site over Tor at dhevt6e4rtgbtr3jh53xrpwmgtilkah6nyjujocsspssrsexc7omxhid.onion.

The Daily Front Page 24 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Machines at the Edge
article

World Labs Is Joining AMD

by mfiguiere·▲ 235 points·95 comments·worldlabs.ai ↗

Illustration of Earth above the layered components of a computer chip

World Labs has signed a definitive agreement to join AMD.

The research and technical breakthroughs we have achieved since our founding in 2024 have given us a clear vision for AI’s potential to solve problems in the spatial and physical world. To accelerate into this future requires scaling our efforts, scaling our reach, and getting closer to the hardware.

We began a deep technical partnership with AMD last year, starting with model training and inference optimization on AMD GPUs. As our teams worked together, we realized it would be a natural fit to bring together our AI ecosystem of software and hardware, foundation models, and applications.

Dr. Fei-Fei Li will join AMD as an Executive Vice President and Chief Scientist, working directly with CEO Dr. Lisa Su. Justin Johnson and Ben Mildenhall will work with Fei-Fei to continue leading the World Labs team as it joins AMD to form a world leading frontier research organization. Together, we are committed to building out an end-to-end open AI ecosystem spanning hardware, software, platforms, and widely accessible open models.

Fei-Fei shares more details of our journey thus far and our shared vision for the future here.

The transaction is expected to close by the end of 2026 subject to regulatory approvals and other customary closing conditions.

The Daily Front Page 25 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Machines at the Edge
article

MicroLLM Lab – Try 7 tiny LLM's in the browser

by logicallee·▲ 177 points·68 comments·stateofutopia.com ↗

Run, benchmark, and compare Small Language Models (SLMs) directly in your browser with hardware-accelerated WebGPU — 100% private, zero server cost, zero accounts.

🎯 Why Small Language Models?

Frontier models (GPT-4, Claude) cost millions to serve and add network latency. Compact models (25M–360M) operate as an ultra-fast, efficient edge layer:

  • Edge Computing & Privacy: Runs entirely on your phone or laptop. No prompt or user data ever leaves your device.
  • Fast Triage & Task Routing: Classify queries, filter spam, and extract intent in milliseconds to decide if an expensive cloud LLM is even needed.
  • Zero Cloud Cost: Infinite concurrency powered by client GPUs with no API bills.
  • Ultra-Low Latency: Sub-10ms time-to-first-token for instantaneous autocomplete and real-time agents.

🔍 Technical Vocabulary

Small Language Model (SLM)

A compact neural model (~25M–360M parameters) designed for efficient edge intelligence and specific tasks rather than broad trivia.

Q4 (4-bit Quantization)

Compressing weights from 16-bit floats to 4 bits per parameter, shrinking memory footprint by 75% so 100M+ models fit in ~50–84 MB of browser memory with near-lossless generation quality.

WebGPU

The modern W3C standard API that executes compute shaders directly on your hardware GPU (Apple Silicon Metal, DirectX 12, Vulkan) right inside your browser window.

How to use this lab in 3 steps:

  1. Load a model: Click Load on any model card below. It caches directly into your browser's private IndexedDB (no file download to disk).

  2. Chat on-device: Select your loaded model and scroll down to the Chat panel to test prompts and watch live tok/s speed.

  3. Benchmark & Compare: Switch to the Benchmarks tab to run objective speed/accuracy tests and generate your shareable performance certificate.

The Daily Front Page 26 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Also on the Front Page
The Daily Front Page 27 of 28
Monday, September 28, 2026 The Daily Front No. #260928 — Colophon

That's the Front for Today

Issue No. #260928 — Monday, September 28, 2026 — went to press 2026-09-29 at 04:44 UTC.

About This Magazine

The Daily Front is a daily digital magazine assembled from the stories that reached the front page of Hacker News on Monday, September 28, 2026. Headlines, points, and comment counts are recorded as they stood at press time. All articles remain the property of their original authors — every piece links back to its source and its discussion thread.

How It Was Made

Fetched, cleaned, and typeset by an automated pipeline. An editor model laid out the pages and chose the highlights; a second read a handful of the day's stories and briefed the cover illustrator — 33 model calls and 271k tokens in total. Set in Jacquard 12, Playfair Display, Source Serif 4, and IBM Plex Mono, all served via Google Fonts under the SIL Open Font License.

The Cover

The cover illustration was commissioned with this prompt:

On a workbench, a guitarist tests a compact effects pedal connected to an electric guitar, its small touch display glowing beneath a clear protective cover. Beside it sits a transparent miniature enclosure containing a restless, many-eyed mechanical creature, while a tiny watchdog circuit is clamped directly to the enclosure’s side by wires and a red physical cutoff switch. A microSD card lies half-inserted into the pedal, and the musician’s boot hovers over the footswitch as the creature strains against its boundaries.

Pastel-and-charcoal drawing on deep petrol-blue paper, using powdery coral, saffron, chalk white, and muted violet accents with rubbed charcoal shadows and a low amber sidelight; compress the workbench scene into tactile, emphatic forms, keeping every connection, enclosure boundary, strained creature, hovering boot, half-inserted microSD card, glowing covered display, clamped watchdog circuit, wires, and red physical cutoff switch unmistakably legible.

Absolutely no text, letters, numbers, readable symbols, or logos anywhere in the image. Keep the main image subject primarily below the upper 10% of the composition, where a title may be overlaid; the scene may extend naturally underneath that title area.

Production Ledger

StageModelCallsTokens InTokens Out
extractgpt-5.6-luna 29 158,812 87,770
layoutgpt-5.6-terra 1 18,486 2,742
covergpt-5.6-luna 2 1,725 324
covergpt-image-2.5-flare 1 251 1,372

The Publisher

Published by Johnny.

Support the Press

If The Daily Front brightens your morning, consider supporting its publisher.

Credits & Contact

All content — articles, posts, comments, and the images within them — belongs to its original authors and is reproduced here to point readers back to the source. Full credit goes to those creators; every item links to its original and its Hacker News discussion.

If you are an author and would like your content removed from an issue, write to hi@johnnys.page and it will be taken down.

Feedback is always welcome at the same address: hi@johnnys.page.

Credit where credit is due.

Every page of this issue began as someone else's work — these are the original sources, linked in full.

  1. Owed a billion dollars in Nvidia stock by Eric_Gullichsen — colo.to·HN discussion ↗
  2. Sonnet 5.5 by D2OQZG8l5BI1S06 — anthropic.com·HN discussion ↗
  3. Coding is not solved by firstSpeaker — blog.alexewerlof.com·HN discussion ↗
  4. Nvidia wants to put a watchdog chip next to every AI agent by jonbaer — cnbc.com·HN discussion ↗
  5. It's Time to Investigate the AI Labs by ibobev — calnewport.com·HN discussion ↗
  6. Thinking fast and slow in AI: The role of metacognition (2021) by teleforce — arxiv.org·HN discussion ↗
  7. AI companies in race to demonstrate their model most threatening to humanity by ljewalsh — thecivilian.co.nz·HN discussion ↗
  8. There is more to code review than (automatable) detection by utiiiD — adaptivecapacitylabs.com·HN discussion ↗
  9. The problem is not AI code, but not knowing about system architecture or intent by zazuke — ssp.sh·HN discussion ↗
  10. Cf: The Agentic CLI for the Cloudflare API by macleos — blog.cloudflare.com·HN discussion ↗
  11. Jeff – Jev-compatible 0.8B decision models, trained at home, ~30 ms by firelex — github.com·HN discussion ↗
  12. Malleable software: Restoring user agency in a world of locked-down apps (2025) by evakhoury — inkandswitch.com·HN discussion ↗
  13. Parley: Federated, decentralised chat that speaks plain IRC by davidcollantes — git.mills.io·HN discussion ↗
  14. Kids turned low-traffic NPR Spotify comments into a secret group chat by simonpure — thisamericanlife.org·HN discussion ↗
  15. Pirating the Pirates by piotrgrabowski — mubi.com·HN discussion ↗
  16. Hijacking the PS5's RTMP stream by ibobev — yashgarg.dev·HN discussion ↗
  17. Nissan's third generation e-POWER powertrain by mroche — nissan-global.com·HN discussion ↗
  18. Guitar amp and effects pedal built on the Waveshare ESP32-S3-Touch-AMOLED-2.06 by arbayi — github.com·HN discussion ↗
  19. What heraldry and Japanese mon can teach about visual-identity generators by bovermyer — benovermyer.com·HN discussion ↗
  20. Updated Google Maps shows destruction of the city of Rafah by slowin — twitter.com·HN discussion ↗
  21. 37,500 border drawings: a map of the world as people remember it by nicocarsui — habibicode.org·HN discussion ↗
  22. Windows 11½ by jjbinx007 — definitelynotwindows.com·HN discussion ↗
  23. Self-Hosting on the Dark Web by mooreds — david.alvarezrosa.com·HN discussion ↗
  24. World Labs Is Joining AMD by mfiguiere — worldlabs.ai·HN discussion ↗
  25. MicroLLM Lab – Try 7 tiny LLM's in the browser by logicallee — stateofutopia.com·HN discussion ↗
  26. MongoDB CEO resigns to join Meta by diek — reuters.com·HN discussion ↗
  27. Footguns with Postgres “at time zone 'UTC'” by birdculture — bookofrevenue.com·HN discussion ↗
  28. Deterministic Concurrency [video] by surprisetalk — youtube.com·HN discussion ↗
  29. Functional Mechanical Sympathy [video] by surprisetalk — youtube.com·HN discussion ↗
  30. Show HN: Destroy Any Website with Stickman by HugoDz — destroy.spritefusion.com·HN discussion ↗

Browse all issues in the archive →