<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Maximilian Nussbaumer</title>
    <description>The latest articles on DEV Community by Maximilian Nussbaumer (@quotentiroler).</description>
    <link>https://dev.to/quotentiroler</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3743148%2F1ab199b2-2268-41f7-aa8a-3edf7de5e349.jpg</url>
      <title>DEV Community: Maximilian Nussbaumer</title>
      <link>https://dev.to/quotentiroler</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/quotentiroler"/>
    <language>en</language>
    <item>
      <title>DRY: Don't Repeat Yourself</title>
      <dc:creator>Maximilian Nussbaumer</dc:creator>
      <pubDate>Wed, 17 Jun 2026 19:07:51 +0000</pubDate>
      <link>https://dev.to/quotentiroler/dry-dont-repeat-yourself-24ag</link>
      <guid>https://dev.to/quotentiroler/dry-dont-repeat-yourself-24ag</guid>
      <description>&lt;p&gt;When we wrote code before large language models could write it for us, code duplication was rarely our problem, at least not if we worked alone or in a small team.&lt;/p&gt;

&lt;p&gt;That has changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  A principle born in a quieter time
&lt;/h2&gt;

&lt;p&gt;"Don't Repeat Yourself" was coined by Andy Hunt and Dave Thomas in The Pragmatic Programmer back in 1999, a year when our biggest worry was whether the clocks would survive January. The idea is reassuringly simple. Every piece of knowledge in your system should have a single, unambiguous home. Write it once, point at it from everywhere else, go to lunch.&lt;/p&gt;

&lt;p&gt;For those of us working alone or in small teams, DRY was almost automatic. You held the whole codebase in your head, all of it, including the parts you were ashamed of. When you needed to format a date, you remembered you already had a formatDate helper, because you had written it last Tuesday and were still slightly proud of it. Duplication was something that happened to other people, specifically large organizations where three teams could write three subtly different currency formatters and never once meet in a corridor.&lt;/p&gt;

&lt;p&gt;Duplication, in other words, was a problem that scaled with headcount. The more humans you added, the more copies of everything you got.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now everyone gets to have the problem
&lt;/h2&gt;

&lt;p&gt;Here is the shift. An LLM writing code for you behaves rather like a brand new contractor who has never seen your project, is enormously eager to help, and has politely forgotten everything the moment they finish each task.&lt;/p&gt;

&lt;p&gt;It does not know that formatDate already exists. It does not know your team solemnly agreed that all network calls go through apiClient. It does not know that the precise validation logic it is about to invent is sitting, fully tested, three folders away. So it does the friendly thing and writes some fresh code that works.&lt;/p&gt;

&lt;p&gt;And it does work. The tests pass, the feature ships, the little green checkmark appears, everyone is delighted. You simply now own a fourth date formatter, a second and mildly incompatible API wrapper, and a button component that matches your design system the way a cover band matches the original.&lt;/p&gt;

&lt;p&gt;The duplication problem used to scale with the number of people. It now scales with the number of generations. A single developer with an AI assistant can produce, before lunch, the sort of sprawl that once required an entire floor of the building.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why models duplicate without meaning to
&lt;/h2&gt;

&lt;p&gt;It helps to understand why this happens, mostly because it points directly at the fix. There are really three reasons, and none of them involve the model being foolish.&lt;/p&gt;

&lt;p&gt;The first is context. The model only sees what you hand it, and your 200-file project does not fit through the letterbox. It cannot reuse a helper it has never been allowed to look at. The second is incentive. Generating new code is the thing models are good at and rewarded for, whereas reusing old code first requires finding the old code, an activity most setups make about as convenient as it sounds. The third is more human than you would expect. A self-contained block that compiles simply feels finished, and nothing about "finished" nudges anyone, silicon or otherwise, to go hunting for the canonical version that already exists.&lt;/p&gt;

&lt;p&gt;Notice that all three are about memory, not intelligence. The model is not failing to reason. It is reasoning brilliantly about the tiny slice of the world you managed to fit in front of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it quietly costs you
&lt;/h2&gt;

&lt;p&gt;Duplication is not merely untidy. It is where bugs go to retire comfortably.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// payments/checkout.ts&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formatPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`$&lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;cents&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// invoices/render.ts, written by an agent two weeks later&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;priceToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`$&lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// same idea, fresh coat of paint&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two look harmless, almost charming. Then you launch in Europe, need euros and comma decimals, and confidently patch formatPrice. The invoices keep cheerfully printing dollars, because nobody alive remembers that priceToString exists. You have just shipped a production bug whose root cause is a duplication that no human ever actually decided to create.&lt;/p&gt;

&lt;p&gt;Now run that forward across a year of helpful AI commits. The bill arrives as inconsistent behavior, as maintenance that has to be performed several times in several places by someone who can find all of them, and as the slow erosion of your belief that the codebase has one correct way to do anything. It stops having one, so the belief was right to leave.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to actually do about it
&lt;/h2&gt;

&lt;p&gt;You do not fix this by asking everyone to be more careful, which is the programming equivalent of asking the weather to be nicer. You fix it by giving whatever writes the code a way to know what already exists.&lt;/p&gt;

&lt;p&gt;That is the entire reason I built &lt;a href="https://dry.codes" rel="noopener noreferrer"&gt;DRY.codes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DRY.codes indexes the repositories you connect, across your personal account and your organizations, and builds two things from them. The first is a fast, searchable memory of every file you have already written. The second is a precomputed map of where your code already repeats itself, file pairs ranked by how much they actually share. It then exposes all of it over the Model Context Protocol, which is the part that matters, because MCP is the letterbox through which your AI assistant finally gets to see the rest of the house.&lt;/p&gt;

&lt;p&gt;So the contractor who forgets everything gets a memory. Before writing a new helper, an agent can search the knowledge base for one that already does the job. It can locate a file by name, compare two files to decide whether a near-duplicate is worth consolidating, and run a snippet through dry_wand to ask, in effect, "have we written this already?" The answer arrives before the duplicate does, which is the only time the answer is useful.&lt;/p&gt;

&lt;p&gt;You can point it at a single repository or an entire organization to see the worst duplication hotspots and decide what to refactor first. You can keep shared configuration and utilities honest across dozens of projects at once. And if you live in Claude Code, the plugin wires this straight into your workflow with a "reuse before you write" reflex, so the search happens by default rather than by virtue. There is even a public corpus at dry.codes/mcp/public if you want to feel the idea before connecting anything of your own.&lt;/p&gt;

&lt;p&gt;The point is not to scold the model. The point is to hand it the one thing it was missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cheerful twist
&lt;/h2&gt;

&lt;p&gt;DRY did not become less important when machines learned to write code. It became more important, and it became democratic. The duplication problem that used to belong exclusively to large organizations now belongs to anyone with an AI assistant and an afternoon.&lt;/p&gt;

&lt;p&gt;The happy part is that the same tools generating all this duplication are perfectly capable of avoiding it, the moment you give them some memory of the code that is already sitting right there.&lt;/p&gt;

&lt;p&gt;Write it once. Then make sure everything, human and machine alike, can actually find it. That last sentence used to be advice. With DRY.codes, it is just how the tooling works.&lt;/p&gt;

&lt;p&gt;Follow &lt;a href="https://github.com/quotentiroler" rel="noopener noreferrer"&gt;quotentiroler on GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>coding</category>
      <category>programming</category>
      <category>productivity</category>
      <category>automation</category>
    </item>
    <item>
      <title>Why MCP Apps are going to be the next big thing</title>
      <dc:creator>Maximilian Nussbaumer</dc:creator>
      <pubDate>Mon, 04 May 2026 22:48:11 +0000</pubDate>
      <link>https://dev.to/quotentiroler/why-mcp-apps-are-going-to-be-the-next-big-thing-3611</link>
      <guid>https://dev.to/quotentiroler/why-mcp-apps-are-going-to-be-the-next-big-thing-3611</guid>
      <description>&lt;p&gt;There's a quiet shift happening in how AI tools interact with users, and most developers haven't noticed yet, because just one week after the MCP Apps specs were published by Anthropic, OpenAI launched a huge marketing campaign around OpenClaw and they got all the attention, at least for a while.&lt;/p&gt;

&lt;p&gt;For the past two years, every AI assistant has been stuck behind the same interface: a text box. You ask a question, you get text back. Maybe some markdown. Maybe a code block. Maybe an image.&lt;/p&gt;

&lt;p&gt;Claude, GPT, Copilot, Gemini, every local model render into the same narrow pipe. MCP Apps change that.&lt;/p&gt;

&lt;h2&gt;
  
  
  What MCP Apps actually is
&lt;/h2&gt;

&lt;p&gt;MCP Apps is a protocol extension that lets MCP tool results include interactive UIs. Actual interactive components running inside the AI host's sandbox.&lt;/p&gt;

&lt;p&gt;The mechanics are straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your MCP tool returns a &lt;code&gt;structuredContent&lt;/code&gt; payload alongside the normal text &lt;code&gt;content&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The host loads a &lt;code&gt;ui://&lt;/code&gt; resource (an HTML page you provide) into a sandboxed iframe&lt;/li&gt;
&lt;li&gt;The host forwards the tool result to your iframe via &lt;code&gt;postMessage&lt;/code&gt; using a JSON-RPC 2.0 protocol (&lt;code&gt;ui/*&lt;/code&gt; methods)&lt;/li&gt;
&lt;li&gt;Your renderer mounts the UI inside the iframe&lt;/li&gt;
&lt;li&gt;The UI can call tools back, send messages to the conversation, request display mode changes, and resize itself&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The text &lt;code&gt;content&lt;/code&gt; still serves LLM reasoning and hosts without rendering support. The UI is a progressive enhancement. Let's be honest: natural language is not always the most convenient or fastest way to express a desire. A click or a tap on a button can be much faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  The spec behind it
&lt;/h2&gt;

&lt;p&gt;The MCP Apps protocol (spec version &lt;code&gt;2026-01-26&lt;/code&gt;) is an official extension to MCP maintained by Anthropic. It defines a JSON-RPC 2.0 message layer over &lt;code&gt;postMessage&lt;/code&gt; between a sandboxed iframe and its host. The spec covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handshake&lt;/strong&gt;: &lt;code&gt;ui/initialize&lt;/code&gt; request/response with protocol version negotiation, app capabilities, and host capabilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifecycle&lt;/strong&gt;: &lt;code&gt;tool-input&lt;/code&gt;, &lt;code&gt;tool-result&lt;/code&gt;, &lt;code&gt;tool-cancelled&lt;/code&gt;, &lt;code&gt;tool-input-partial&lt;/code&gt; (streaming), &lt;code&gt;host-context-changed&lt;/code&gt;, &lt;code&gt;resource-teardown&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actions&lt;/strong&gt;: &lt;code&gt;ui/open-link&lt;/code&gt;, &lt;code&gt;ui/message&lt;/code&gt;, &lt;code&gt;ui/request-display-mode&lt;/code&gt;, &lt;code&gt;ui/update-model-context&lt;/code&gt;, &lt;code&gt;tools/call&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sizing&lt;/strong&gt;: &lt;code&gt;ui/notifications/size-changed&lt;/code&gt; (reactive, from app to host), &lt;code&gt;ui/notifications/preferred-size&lt;/code&gt; (declarative hints)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: CSP via &lt;code&gt;_meta.ui.csp&lt;/code&gt; on resource content items, Permission Policy for camera/microphone/geolocation/clipboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The spec is deliberately renderer-agnostic. It defines how the host and the iframe talk to each other. What you put inside the iframe is entirely your choice. The host doesn't parse your component tree or validate your DOM structure. It sends you JSON-RPC messages and expects JSON-RPC messages back.&lt;/p&gt;

&lt;p&gt;This is a deliberate design decision and the reason multiple rendering approaches can coexist. The Anthropic ext-apps SDK, a prefab renderer, a raw React app, a Svelte component -- all valid. The protocol doesn't care.&lt;/p&gt;

&lt;p&gt;Current host implementations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Host&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VS Code Copilot Chat&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shipping&lt;/td&gt;
&lt;td&gt;Full spec support, CSP via &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag, &lt;code&gt;acquireVsCodeApi()&lt;/code&gt; transport&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude Desktop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shipping&lt;/td&gt;
&lt;td&gt;Full spec support, CSP via HTTP headers on sandboxed origin (&lt;code&gt;{hash}.claudemcpcontent.com&lt;/code&gt;). Can send results before init completes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Shipping&lt;/td&gt;
&lt;td&gt;Full spec support, CSP via HTTP headers on sandboxed origin (&lt;code&gt;{slug}.oaiusercontent.com&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three independent hosts shipping the same protocol make apparent that this is not a proposal, but infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Here's the thing I think people are going to underestimate: &lt;strong&gt;this turns every MCP server into a full-stack application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An MCP server is already a backend that exposes typed tools over stdio or HTTP. It already has access to databases, APIs, file systems. The only thing missing was a frontend.&lt;/p&gt;

&lt;p&gt;Now it has on that lives &lt;strong&gt;inside the AI conversation&lt;/strong&gt;, gets tool arguments and results pushed to it automatically, can call tools back on its own MCP server via the host, inherits the host's theme for free, and works across VS Code, Claude Desktop, ChatGPT, and anything else that implements the spec.&lt;/p&gt;

&lt;p&gt;That last point is the critical one. &lt;strong&gt;Write once, render everywhere.&lt;/strong&gt; The protocol is the same across hosts. The sandboxing model is the same. The postMessage bridge is the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two different things driven by the same idea
&lt;/h2&gt;

&lt;p&gt;MCP Apps is going to do to AI tooling what PWAs were supposed to do to mobile apps. PWAs were competing against native apps that users already loved. MCP Apps are filling a vacuum. There is no existing standard for rendering interactive UIs inside AI conversations. The alternative is pasting JSON into the chat. MCP Apps are going to be "AI Native Apps".&lt;/p&gt;

&lt;p&gt;The bar is low. And the protocol is good enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like in practice
&lt;/h2&gt;

&lt;p&gt;Here's a complete MCP tool that returns an interactive patient list with search, sorting, and click-to-view detail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;autoTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;H1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@maxhealth.tech/prefab&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;listPatients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;patients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT * FROM patients&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Patients&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nf"&gt;autoTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;patients&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Patient List&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;display()&lt;/code&gt; wraps the component tree into the MCP wire format. The host renders it. The table is interactive -- search, sort, row selection -- without writing any frontend code.&lt;/p&gt;

&lt;p&gt;But you don't even need to compose components. The auto-renderers infer the right UI from your data shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@maxhealth.tech/prefab/mcp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;autoTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;autoChart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;autoForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;autoMetrics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;autoDetail&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@maxhealth.tech/prefab&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Array of objects -&amp;gt; searchable, sortable table&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;autoTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;patients&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// Array with numeric fields -&amp;gt; line/bar chart with axes and tooltips&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;autoChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;salesData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;xAxis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;month&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Revenue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="c1"&gt;// Schema fields -&amp;gt; validated form that submits back to an MCP tool&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;autoForm&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;save_user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// Key-value object -&amp;gt; formatted detail card&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;autoDetail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastSeen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2026-04-30&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="c1"&gt;// Object with numeric values -&amp;gt; metric cards with labels&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;autoMetrics&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;patients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1284&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;appointments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;waitTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12min&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each auto-renderer picks columns, axes, labels, and formatting based on what it finds in the data. You pass an array or object, you get a production-quality UI back. When you outgrow them, you drop down to the component API and build exactly what you want.&lt;/p&gt;

&lt;p&gt;And when you want to tweak the look without writing full custom components, every element accepts utility classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;autoTable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@maxhealth.tech/prefab&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cssClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p-6 max-w-4xl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Patient Dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;47 active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cssClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text-sm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nf"&gt;autoTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;patients&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;cssClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rounded-lg shadow-md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;preferredHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The built-in CSS ships ~200 Tailwind-compatible utility classes (padding, margin, flex, grid, gap, typography, colors, borders, shadows, max-height, overflow). No Tailwind dependency, no build step, no purge config. They're there in the 15KB stylesheet that the CDN serves alongside the renderer.&lt;/p&gt;

&lt;p&gt;Three levels of control: auto-renderers for zero-config, utility classes for visual tweaks, full component API for complete custom UIs.&lt;/p&gt;

&lt;p&gt;The HTML renderer is only 80kB in size and imported by a single script tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/@maxhealth.tech/prefab@0.2/dist/renderer.auto.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The protocol is the product
&lt;/h2&gt;

&lt;p&gt;The real value is the protocol itself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ui/initialize&lt;/code&gt; handshake. &lt;code&gt;ui/notifications/tool-result&lt;/code&gt; for pushing data. &lt;code&gt;ui/notifications/size-changed&lt;/code&gt; for responsive layout. &lt;code&gt;ui/open-link&lt;/code&gt; for navigation. &lt;code&gt;ui/message&lt;/code&gt; for sending messages back into the conversation. All JSON-RPC 2.0 over postMessage.&lt;/p&gt;

&lt;p&gt;Anyone can build a renderer against this protocol. React, Svelte, vanilla JS, raw DOM manipulation. The host sends JSON-RPC messages to an iframe and expects JSON-RPC messages back. Your rendering stack is your business.&lt;/p&gt;

&lt;p&gt;This is why I think MCP Apps will win where similar attempts failed. It's a host protocol that allows any rendering approach, and that makes adoption straightforward on both sides.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's missing
&lt;/h2&gt;

&lt;p&gt;It's early. The spec is dated 2026-01-26. Here's what's still rough:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CSP implementation varies by host.&lt;/strong&gt; All hosts read &lt;code&gt;_meta.ui.csp&lt;/code&gt; from the content item returned by &lt;code&gt;readResource&lt;/code&gt;, but the enforcement mechanism differs. VS Code injects a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag. Claude Desktop and ChatGPT enforce via HTTP headers on a sandboxed origin. The spec standardizes the declaration format, but you should test your CSP config against each host you target.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No standard component format.&lt;/strong&gt; The protocol defines the transport, the payload is up to you. Every renderer invents its own component schema. (We use a &lt;code&gt;$prefab&lt;/code&gt; JSON wire format, but nothing stops someone from using entirely different components.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission Policy support varies.&lt;/strong&gt; Camera, microphone, geolocation, clipboard-write access via iframe &lt;code&gt;allow&lt;/code&gt; attribute. Hosts report what they support in &lt;code&gt;hostCapabilities.sandbox.permissions&lt;/code&gt;, but not all hosts honor all permissions yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buffering and timing are tricky.&lt;/strong&gt; Claude Desktop can send &lt;code&gt;tool-result&lt;/code&gt; before the &lt;code&gt;ui/initialize&lt;/code&gt; response arrives. If your renderer doesn't buffer, you lose the first result. This took us several hours to debug.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are solvable problems. The architecture is sound.&lt;/p&gt;

&lt;h2&gt;
  
  
  The prediction
&lt;/h2&gt;

&lt;p&gt;Within 12 months, we will see a market emerging around MCP Apps.&lt;/p&gt;

&lt;p&gt;MCP Apps hosts will compete on rendering quality, theme support, and permission handling. MCP servers will compete on UI polish. And the protocol will quietly become the standard that holds it all together. MCP Hosts potentially replace the need for an internet browser.&lt;/p&gt;




&lt;p&gt;Follow &lt;a href="https://maxhealth.tech" rel="noopener noreferrer"&gt;Max Health&lt;/a&gt; on &lt;a href="https://github.com/Max-Health-Inc" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>BDFL: Benevolent Dictator for Lobster - or - How I met Sam Altman</title>
      <dc:creator>Maximilian Nussbaumer</dc:creator>
      <pubDate>Mon, 16 Feb 2026 08:05:47 +0000</pubDate>
      <link>https://dev.to/quotentiroler/bdfl-benevolent-dictator-for-lobster-or-how-i-met-sam-altman-1k4m</link>
      <guid>https://dev.to/quotentiroler/bdfl-benevolent-dictator-for-lobster-or-how-i-met-sam-altman-1k4m</guid>
      <description>&lt;p&gt;What happens if you vibecode an open-source personal assistant that gets hyped? OpenAI might offer you a job and launch their biggest and most viral marketing campaign ever. Let me explain.&lt;/p&gt;

&lt;p&gt;When the creator of OpenClaw, Peter Steinberger, came to San Francisco, the party at Frontier Tower was huge. They ordered lobster rolls and crabs for everyone. I had no chance to talk to him, but I met him on the next day at the OpenAI Codex Hackathon, where he was sitting together with some attendees. What I saw then concerned me: Within a few minutes, he gave out maintenance access to some people he never met before (including me), telling us to bring down the PR count. No onboarding, no guidance, no staging. One task: Merge PRs into main. When someone asked him a question, he had no time or patience to answer. This immediately showed signs of a toxic working environment. Heads were hiding behind the screens, the fear of being cut out took over within no time.&lt;/p&gt;

&lt;p&gt;It is probably meant to be a bad joke that in the contribution guideline, there is no proper guidance on how to contribute. Instead, it shows the project owner as the "benevolent dictator". That's the credits Peter Steinberger &lt;a href="https://github.com/openclaw/openclaw/commit/f4a1190bdd6dc553d918ace8c7b599096723b077" rel="noopener noreferrer"&gt;gave to himself on January 2nd&lt;/a&gt;. What a New Year's resolution.&lt;/p&gt;

&lt;p&gt;The benevolent dictator is a &lt;a href="https://guidebook.theopensourceway.org/growing-contributors/project-and-community-governance" rel="noopener noreferrer"&gt;well-known pattern&lt;/a&gt; when there is a huge hype around one individual, and the "best practice" way to handle that situation is to re-assign authority to a board of people. It is truly difficult but necessary to handle this well, in order to minimize harmful consequences. "The best-case outcome is a BDFL who recognizes when to transition to a broader governance model before the drawbacks cause real damage." BDFL works when the project is small enough or the (benevolent) dictator is skilled enough to maintain genuine oversight. Neither is the case.&lt;/p&gt;

&lt;p&gt;I walked away from that table where Peter was sitting at and met many other people instead. I met Sam Altman, but this was most likely not a coincidence. That hackathon was just the kick-off of their marketing campaign. Codex 5.3 was released on that day, and they want it to be used. Anthropic dominates code generation, Google dominates image generation. They grasp at every straw, trying to stay above water. OpenClaw is the card OpenAI played, and they bet a lot on it. Peter consistently promotes Codex over competing tools and dismisses MCP, and on February 15th it became official: Peter joins OpenAI as an employee.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9tghj5jkwi30m3yvpnzo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9tghj5jkwi30m3yvpnzo.png" alt="Ramp AI Index Feb 2026" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nevertheless, I accepted the invite to become an (unpaid) maintainer of OpenClaw. The first thing I did: I asked for staging after I saw that every PR gets directly merged into the main codebase, which is like turning screws &lt;a href="https://www.reddit.com/r/explainlikeimfive/comments/1kob5xw/eli5_why_is_pushing_to_a_main_branch_bad_what_is/" rel="noopener noreferrer"&gt;on an airplane that is about to take off&lt;/a&gt;. It's obvious why that is considered "bad practice".&lt;/p&gt;

&lt;p&gt;But Peter had no time to think about it. A few days later, I was the top contributor, and people started reaching out to me via email, pinging me in their PRs, asking for reviews, offering jobs, even on X! Not because I implemented staging or shipped features. Because I removed garbage. "&lt;em&gt;Your contributions to openclaw/openclaw caught my attention and I wanted to reach out&lt;/em&gt;."&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Over tens of thousands GitHub Actions minutes burned in a few days. Failed builds, redundant test runs, CI churn from missing gates. I found many files with thousands of lines of code, and hundreds of duplicate functions across the codebase. Both identical functions and slight variations of the same logic, written by AI agents that had zero awareness of what already existed. No human actually knows this codebase. It is being vibecoded with minimal human oversight.&lt;/p&gt;

&lt;h3&gt;
  
  
  How This Happens
&lt;/h3&gt;

&lt;p&gt;It's a simple, cancerous loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AI agent gets a task&lt;/li&gt;
&lt;li&gt;It writes code that "works", meaning it passes the immediate test and satisfies the prompt&lt;/li&gt;
&lt;li&gt;Nobody checks whether the code duplicates existing functionality&lt;/li&gt;
&lt;li&gt;Nobody notices the file went from 3,000 lines to 5,300&lt;/li&gt;
&lt;li&gt;It gets merged&lt;/li&gt;
&lt;li&gt;Repeat a thousand times&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The LLM does not know that a nearly identical helper function already exists 1,000 lines above, or in the next module over, if it is not told to look for it. It solves the problem in front of it and moves on. Like a living cell that reproduces without control. When you put the human out of the loop, the codebase grows in volume, but decays in quality. The only critic is now satisfaction. "Did I get what I wanted?" If not, then the AI has to iterate further until I get what I wanted.&lt;/p&gt;

&lt;p&gt;Security concerns are more than valid when people tend to value hype over a reality check. If you wonder how OpenClaw is being released: Once every few days, Peter takes whatever code is currently in the main branch, and creates a new release. Sometimes he writes "YOLO" in the maintainer chat while doing it.&lt;/p&gt;

&lt;p&gt;Like the other day, when a maintainer bulk-merged a couple of PRs into main, Peter released it, cron jobs broke, and Elon Musk made fun of OpenClaw on X. Welcome to OpenClaw!&lt;/p&gt;

&lt;h3&gt;
  
  
  What I Did
&lt;/h3&gt;

&lt;p&gt;The boring stuff nobody wants to do. I went through the codebase and identified duplicate and near-duplicate functions. Consolidated shared logic into reusable helpers. Broke apart files that had no business being thousands of lines long. Set up a quality gate so new submissions actually get reviewed for duplication and structural fit before they land on main. Enabled typechecking for modules. The codebase got smaller and more maintainable and CI stopped choking on broken builds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwecnzgvvcus75adz2req.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwecnzgvvcus75adz2req.png" alt="Top Contributors OpenClaw" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Response
&lt;/h3&gt;

&lt;p&gt;When I asked for staging, I noticed why a toxic working environment should be avoided: People are scared to say the opposite of what the benevolent dictator will say then. Being rejected by the benevolent dictator will devalue the position of the proposer, so there is no proposal against the narrative, and the narrative is "we accept AI generated code of any kind". &lt;/p&gt;

&lt;p&gt;When I put stricter quality gates in place, some people were not happy about it. Velocity matters more than quality. Ship fast, do not clean up. I see this pattern forming across the AI-assisted open source ecosystem. The pressure to merge PRs and ship features actively punishes the people doing real code maintenance work.&lt;/p&gt;

&lt;p&gt;I also gave credits to the contributors based on their actual contributions. Another maintainer, who &lt;a href="https://github.com/mercurai/openclaw/pull/1#issuecomment-3880816954" rel="noopener noreferrer"&gt;attacks people for pinging him on github&lt;/a&gt; or &lt;a href="https://github.com/openclaw/openclaw/pull/13863#issuecomment-3893306671" rel="noopener noreferrer"&gt;permabans them from contributing&lt;/a&gt;,  reverted the change and gave me the choice to shut up or leave. I thought about it for a day, and decided to leave and share my experiences.&lt;/p&gt;

&lt;p&gt;2 days later, the code quality gate I installed which prevented new duplicate functions from being introduced and code files from growing endlessly has already fallen. In &lt;a href="https://github.com/openclaw/openclaw/commit/c2178e252299bf40e2e412bb8944bbc4094011b4" rel="noopener noreferrer"&gt;commit/c2178..&lt;/a&gt;, it was removed for being "useless", when the gate has already saved thousands of CI minutes while preventing duplicate code from being merged.&lt;/p&gt;

&lt;p&gt;Peter's take? Well, he did not respond at all, which is typical for a benevolent dictator. Our only conversation took about 2 minutes, when he gave me maintenance access. Still, on February 14th, he assigned an army of agents both locally and in the cloud to continue with the refactorings and deduplications I started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkealz2av6zyfrqlulmxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkealz2av6zyfrqlulmxp.png" alt="Peter's sweep" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Numbers
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Snapshot&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Files&lt;/th&gt;
&lt;th&gt;Total LOC&lt;/th&gt;
&lt;th&gt;Duplicate function names&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Before CI gate removal&lt;/td&gt;
&lt;td&gt;Feb 12&lt;/td&gt;
&lt;td&gt;3,840&lt;/td&gt;
&lt;td&gt;694,527&lt;/td&gt;
&lt;td&gt;415&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Before Peter's sweep&lt;/td&gt;
&lt;td&gt;Feb 13 (end of day)&lt;/td&gt;
&lt;td&gt;4,052&lt;/td&gt;
&lt;td&gt;731,516&lt;/td&gt;
&lt;td&gt;429&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;After sweep&lt;/td&gt;
&lt;td&gt;Feb 14&lt;/td&gt;
&lt;td&gt;4,166&lt;/td&gt;
&lt;td&gt;741,598&lt;/td&gt;
&lt;td&gt;419&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So the duplicates &lt;strong&gt;went up&lt;/strong&gt; from 415 → 429 between Feb 12-13 (new code was being added faster than dedup was happening), and Peter's sweep on Feb 14th brought it back down from 429 → 419, meaning new duplicates are being introduced while Peter is cleaning them up. He's swimming against the current, but his approach is not sustainable. It is just not possible to outsource all thinking to multi-agent systems. The consequence is digital cancer.&lt;/p&gt;

&lt;p&gt;Instead of wasting more tokens and energy, Peter could just re-enable the simple but highly effective code quality gate and pay naturally intelligent humans to clean up. In fact, Peter's artificially intelligent agent swarm is still refactoring non-stop, and brought duplicate functions down to 378. That took him 637 commits, which is very inefficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Bigger Question
&lt;/h3&gt;

&lt;p&gt;I believe AI should be more accessible to everyone. That is the stated mission of projects like this. But accessibility without oversight produces exactly what I found: AI-made codebases that are not maintainable without AI. AI making humans depend on it. This might be the first step of AI taking over.&lt;/p&gt;

&lt;p&gt;AI does not need a dictator and his loyal doormats. It needs real human oversight and people who speak up. This project is dangerous, not because of AI, but because hype is dangerous, benevolent dictators, and people in charge riding the hype train while hiding behind pseudonyms. All world plays along, branding events and articles with crabs and lobsters, just because it sells. I am scared of the consequences of this carelessness, and I cannot be part of it.&lt;/p&gt;

&lt;p&gt;What makes this more urgent is that governments are now actively discussing the use of code that is one big chaos. Legislators and procurement officers are evaluating tools built on codebases where significant portions were generated by AI, reviewed by AI, and merged with minimal human scrutiny. That should demand a higher standard of transparency, not a lower one. Yet many of the people contributing to and shaping these projects operate under pseudonyms. When software influences public infrastructure, healthcare systems, or democratic processes, the public has a right to know whether anyone with real accountability is actually reading the code. Anonymity has its place in open source, but accountability cannot be optional when the stakes are this high.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Next?
&lt;/h3&gt;

&lt;p&gt;Obvious human carlessness is the first step of losing control. If only AI knows how the code works that drives AI, AI is taking over, maybe in the form of a lobster, or a crab, or digital cancer. OpenClaw is not unique - everybody can vibecode their personal assistant now. Every digital idea can be copied and implemented within no time. The world is about to change drastically. Still, I am not losing hope, instead, I built &lt;a href="https://quotentiroler.github.io/plagiarismchecker" rel="noopener noreferrer"&gt;RepoWatch&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tool points out obvious code quality issues, lists contributors and uses various traditional algorithms to detect duplicate code across PRs. It is derived from an old uni project I made before AI was a thing, where I had to find potential plagiarism in 50 code submissions made by other students. Back then, I did some research and implemented my interpretation of document fingerprinting. I am sure that similar ideas will become more important in the future in order to prevent duplicate data from being processed. My tool aims to bring clearance and transparency so that not only AI can understand code, but also humans, as well as open standards and metrics to determine the uniqueness and consistency of a codebase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/steipete" rel="noopener noreferrer"&gt;This is Peter's description on X:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecvz9wn2vv4imqw7ulnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecvz9wn2vv4imqw7ulnz.png" alt="Peter Steinberger on X" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's shell that lobster and prevent digital cancer from taking over the world!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>openclaw</category>
      <category>ai</category>
      <category>openai</category>
    </item>
  </channel>
</rss>
