<?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: Vincent Tran</title>
    <description>The latest articles on DEV Community by Vincent Tran (@0xgosu).</description>
    <link>https://dev.to/0xgosu</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%2F2435529%2F3d8e6fd3-a6ef-41e2-bcf7-dbc8d04d17e1.jpeg</url>
      <title>DEV Community: Vincent Tran</title>
      <link>https://dev.to/0xgosu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/0xgosu"/>
    <language>en</language>
    <item>
      <title>Claude Opus 5: A Frontier Model That Is Cheap Enough to Actually Use</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Sat, 25 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/claude-opus-5-a-frontier-model-that-is-cheap-enough-to-actually-use-2ngp</link>
      <guid>https://dev.to/0xgosu/claude-opus-5-a-frontier-model-that-is-cheap-enough-to-actually-use-2ngp</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhbvw25bdv1a7wx6josx8.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhbvw25bdv1a7wx6josx8.jpg" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anthropic released &lt;strong&gt;Claude Opus 5&lt;/strong&gt; on July 24, 2026. It is available in Claude Code, Claude Cowork, the Claude apps, and the API as &lt;code&gt;claude-opus-5&lt;/code&gt;, and it is now the default model on Claude Max and the strongest model offered on Claude Pro.&lt;/p&gt;

&lt;p&gt;The headline numbers are good. What makes this release worth writing about is not that a frontier lab shipped a better model — that happens on a schedule now — but &lt;em&gt;where&lt;/em&gt; the improvement landed. Opus 5 costs the same as Opus 4.8: &lt;strong&gt;$5 per million input tokens and $25 per million output tokens&lt;/strong&gt;. The gains showed up entirely on the other side of the ledger.&lt;/p&gt;

&lt;p&gt;That changes the shape of the decision developers have been making for the past two years.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Old Trade-off Was Intelligence Versus Budget
&lt;/h2&gt;

&lt;p&gt;Anyone who has run an agent loop in production knows the pattern. You start with the strongest available model because it fails less often. Then the bill arrives, and you begin the demotion process: cheap model for the easy steps, expensive model for the hard ones, a router in between, and a growing pile of heuristics deciding which is which.&lt;/p&gt;

&lt;p&gt;That routing layer is not free. It is code you maintain, a source of subtle behavioral inconsistency, and a place where the cheap model’s failures leak into the expensive model’s context. Most teams building on LLMs have some version of it, and most would delete it if the economics allowed.&lt;/p&gt;

&lt;p&gt;Opus 5 is aimed squarely at that situation. Anthropic’s framing is that it “is designed to be used every day: it works more efficiently than other models.” Efficiency here is not a benchmark category — it is the claim that the model reaches the answer in fewer tokens, which makes the strong model affordable for the boring steps too.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Benchmark Results, With the Cost Attached
&lt;/h2&gt;

&lt;p&gt;Anthropic’s published comparisons are consistently phrased as &lt;em&gt;score plus cost&lt;/em&gt;, which is a more useful format than a bare leaderboard row:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontier-Bench v0.1&lt;/strong&gt; — Opus 5 surpasses all other models and more than doubles Opus 4.8’s performance, at a lower cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CursorBench 3.2&lt;/strong&gt; — lands within 0.5% of Fable 5’s peak score, at half the cost per task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ARC-AGI 3&lt;/strong&gt; — Opus 5’s score is three times as high as the next-best model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OSWorld 2.0&lt;/strong&gt; — beats Fable 5’s best result at just over a third of the cost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zapier AutomationBench&lt;/strong&gt; — roughly 1.5× the pass rate of the next-best model for the same spend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Life sciences&lt;/strong&gt; — 10.2 percentage points above Opus 4.8 on organic chemistry, 7.7 points higher on protein-related tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the community leaderboards, Opus 5 is currently sitting at the top of &lt;a href="https://llm-stats.com/benchmarks/swe-bench-verified" rel="noopener noreferrer"&gt;SWE-bench Verified&lt;/a&gt; at around 96% — with the usual caveat that different trackers run different harnesses and report numbers a point or two apart.&lt;/p&gt;

&lt;p&gt;The ARC-AGI 3 result is the one worth staring at. A 3× margin on a benchmark specifically designed to resist memorization is not the kind of gap you get from more training data on the same recipe. Whether it generalizes to work that looks like &lt;em&gt;your&lt;/em&gt; work is, as always, an open question — but it is a different sort of result than another two points on a coding eval.&lt;/p&gt;

&lt;p&gt;Sualeh Asif, co-founder of Cursor, summarized it in the terms that matter to anyone shipping a product on top of these models: “Claude Opus 5 delivers near Fable 5 intelligence at Opus speed and cost.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Effort and Fast Mode: Two Dials Instead of Two Models
&lt;/h2&gt;

&lt;p&gt;The most practically useful change is that the intelligence-versus-cost trade-off has moved inside the model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The effort setting&lt;/strong&gt; lets you tell Opus 5 how hard to think. Turn it up to maximize intelligence on a genuinely difficult problem; turn it down to conserve tokens when you want a faster, cheaper answer. This is the router I described earlier, except it is a parameter instead of an architecture, and the model on both sides of the dial is the same model — same knowledge, same tool-calling behavior, same failure modes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fast mode&lt;/strong&gt; is the orthogonal dial: roughly &lt;strong&gt;2.5× the default speed at twice the base price&lt;/strong&gt;. Note what that actually buys. You are not paying for a better answer, you are paying for the same answer sooner. For an interactive coding session where a human is sitting there waiting, latency is often worth more than tokens. For an overnight batch job, it is worth nothing. Having these as separate knobs means you can make that call per workload instead of per project.&lt;/p&gt;

&lt;p&gt;In Claude Code, fast mode toggles with &lt;code&gt;/fast&lt;/code&gt; and does not swap in a smaller model underneath — a distinction worth confirming, since “fast mode” in other products frequently means exactly that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two API Changes Worth Reading Carefully
&lt;/h2&gt;

&lt;p&gt;Alongside the model, Anthropic shipped two beta features that read like they came directly out of production incident reports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mid-conversation tool changes without invalidating the prompt cache.&lt;/strong&gt; If you have built a long-running agent, you know why this matters. Tool definitions live at the front of the prompt, so changing them — adding a tool as the agent enters a new phase, removing one that is no longer relevant, updating a schema — has historically blown away the cache for the entire conversation. The workarounds were all bad: define every tool up front and accept the context bloat and selection errors, or eat a full re-read on every phase transition. Being able to hand an agent a different toolset partway through a task, without paying for the whole conversation again, makes staged agents meaningfully cheaper to build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automatic fallbacks for safety-classifier-flagged requests.&lt;/strong&gt; When a request trips a safety classifier, it can now be routed automatically to an alternative model — Opus 4.8 by default — rather than failing. If you have ever had a production endpoint return an error because a legitimate user request looked superficially like something else, you understand the appeal. It converts a hard failure into a soft degradation.&lt;/p&gt;

&lt;p&gt;Neither of these is glamorous. Both are the sort of thing you only design after watching a lot of real applications break.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alignment Number
&lt;/h2&gt;

&lt;p&gt;Anthropic reports that Opus 5 scores &lt;strong&gt;2.3 on overall misaligned behavior — the lowest of any of their recent models&lt;/strong&gt;. They also note where it does not lead: it remains behind Mythos 5 on cybersecurity exploitation tasks (though comparable at vulnerability &lt;em&gt;identification&lt;/em&gt;) and on biology research tasks.&lt;/p&gt;

&lt;p&gt;That second sentence is the interesting one. A capability gap disclosed voluntarily in a launch post is a gap the lab decided not to close, and the two named domains are exactly the two where capability and risk are hardest to separate. Reading the omission as a deliberate positioning choice rather than a training shortfall seems reasonable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means If You Are Building Something
&lt;/h2&gt;

&lt;p&gt;A few concrete implications:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Revisit your model routing.&lt;/strong&gt; If you built a cheap-model/expensive-model split to control costs, the effort setting may now do that job with less machinery and fewer behavioral seams. Measure before you rip anything out, but measure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separate the latency decision from the intelligence decision.&lt;/strong&gt; These used to be coupled through model choice. They are now two independent parameters. Interactive workloads and batch workloads should almost certainly be configured differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Restructure staged agents around the tool-change beta.&lt;/strong&gt; If you have been stuffing every possible tool into a single definition block to protect the cache, that constraint is loosening. Smaller, phase-appropriate toolsets tend to produce better tool selection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not skip your own evals.&lt;/strong&gt; Frontier-Bench, CursorBench, ARC-AGI, OSWorld, and AutomationBench are all reasonable proxies, and none of them are your codebase. The cost-per-task framing in Anthropic’s numbers is a good template to copy for your own measurements — score alone has never been the decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pattern Underneath
&lt;/h2&gt;

&lt;p&gt;For most of the current generation of models, “better” has meant “bigger, slower, more expensive, and worth it.” Opus 5 is a release where better meant &lt;em&gt;the same price, more efficiently spent&lt;/em&gt; — beating competitors at a third to a half of their cost per task, and doubling its predecessor without charging more for the privilege.&lt;/p&gt;

&lt;p&gt;That is a healthier direction than a leaderboard climb. A model that is 5% smarter and 3× the price changes what is possible in a demo. A model that is substantially smarter at the same price changes what is affordable in production, and production is where the interesting problems have been waiting.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; &lt;a href="https://www.anthropic.com/news/claude-opus-5" rel="noopener noreferrer"&gt;Anthropic — Introducing Claude Opus 5&lt;/a&gt;, &lt;a href="https://llm-stats.com/benchmarks/swe-bench-verified" rel="noopener noreferrer"&gt;SWE-bench Verified Leaderboard&lt;/a&gt;, &lt;a href="https://www.vellum.ai/blog/claude-opus-5-benchmarks-explained" rel="noopener noreferrer"&gt;Claude Opus 5 Benchmarks Explained — Vellum&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>SIMD for Everyday Programmers: The Parallel Loop Hiding in Plain Sight</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Thu, 23 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/simd-for-everyday-programmers-the-parallel-loop-hiding-in-plain-sight-pco</link>
      <guid>https://dev.to/0xgosu/simd-for-everyday-programmers-the-parallel-loop-hiding-in-plain-sight-pco</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flyhojy4diumleiqyqbt4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flyhojy4diumleiqyqbt4.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most performance work starts with subtraction: remove an allocation, avoid a database round trip, choose a better data structure, or stop doing work that nobody needs. Those changes often beat clever instruction-level tuning.&lt;/p&gt;

&lt;p&gt;But eventually a profiler points at a small loop that really does need to inspect every value. It scans bytes, compares pixels, counts matches, applies a threshold, sums samples, or searches for a delimiter. The algorithm may already be linear and the data may already be contiguous. At that point the remaining question is not how to avoid the loop. It is how much useful work the processor can do on each trip through it.&lt;/p&gt;

&lt;p&gt;That is the approachable part of SIMD: &lt;strong&gt;single instruction, multiple data&lt;/strong&gt;. Instead of loading and comparing one value, a vector instruction applies the same operation across several lanes at once. A 256-bit vector can hold eight 32-bit integers or thirty-two bytes. The exact throughput is not simply the lane count—loads, reductions, branches, cache misses, and surrounding work still cost time—but the processor can retire much more useful work per instruction.&lt;/p&gt;

&lt;p&gt;SIMD is associated with dense intrinsic names, architecture manuals, codecs, and parsing libraries such as simdutf and simdjson. Those projects deserve their reputation for sophistication. They are also a misleading introduction. The common form of vectorization is much less exotic: prepare a vector, load a chunk, operate on all lanes, turn the result into something scalar code can use, then clean up the remainder.&lt;/p&gt;

&lt;p&gt;Once that shape is familiar, SIMD stops looking like a separate discipline. It becomes another way to write a loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Mental Model: One Operation, Several Lanes
&lt;/h2&gt;

&lt;p&gt;Imagine a scalar loop that counts values above a threshold:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;usize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&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;Every iteration loads one value, compares it, and updates state. A vector version groups adjacent values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;values: [12, 91, 34, 88, 7, 63, 55, 2]
threshold: [50, 50, 50, 50, 50, 50, 50, 50]
result: [F, T, F, T, F, T, T, F]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The comparison is element-wise. Lane zero compares with lane zero, lane one with lane one, and so on. There is no inner loop in the source. A vector-capable compiler lowers the operation to the instructions available for the chosen target.&lt;/p&gt;

&lt;p&gt;The vector width depends on both hardware and element size. A 128-bit Arm Neon register can carry four &lt;code&gt;u32&lt;/code&gt; values or sixteen bytes. A 256-bit AVX2 register can carry eight &lt;code&gt;u32&lt;/code&gt; values or thirty-two bytes. Wider elements mean fewer lanes; narrower elements mean more. This is why data representation matters. If an algorithm only needs bytes but expands everything to 32-bit integers, it gives up three quarters of its potential lanes before doing any work.&lt;/p&gt;

&lt;p&gt;SIMD is not the same as threads. Threads run independent instruction streams and involve scheduling and coordination. SIMD keeps one instruction stream and applies an operation across a small fixed group of values. It is local parallelism inside a core, often with no locks, tasks, or worker pools.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Five-Part Vector Loop
&lt;/h2&gt;

&lt;p&gt;Everyday SIMD usually follows five steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Prepare vectors and broadcast constants
&lt;/h3&gt;

&lt;p&gt;A vector-to-vector comparison needs compatible values on both sides. If every input is compared with &lt;code&gt;0x0F&lt;/code&gt;, the scalar threshold must be copied into every lane. This is called a broadcast or splat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;@Vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;@splat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0x0F&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The conceptual value is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup belongs outside the hot loop. A sum or checksum may also initialize one or more vector accumulators here. Rebuilding invariant vectors for every chunk wastes the advantage we are trying to create.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Load one complete vector at a time
&lt;/h3&gt;

&lt;p&gt;Advance by lanes instead of elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;lanes&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;len&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="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;lanes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;lanes&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c"&gt;// Work on the full vector.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bound matters. A normal full-width load cannot read beyond the slice merely because the algorithm plans to ignore those lanes. Some instruction sets provide masked loads, and carefully padded buffers can support other strategies, but the simple portable approach processes only complete chunks here.&lt;/p&gt;

&lt;p&gt;Contiguous input is the friendly case. Pointer chasing, scattered fields, unpredictable lookups, and per-element allocations can cost more than the arithmetic. This is why data-oriented design often comes before explicit SIMD. Arrays of homogeneous values are easy for the cache, easy for prefetchers, and easy to load as vectors. A linked structure may technically be vectorizable with gather operations, but it is rarely the first target to choose.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Apply the lane-wise operation
&lt;/h3&gt;

&lt;p&gt;This is the part people imagine when they hear SIMD:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a vector of booleans. Arithmetic, minimum, maximum, bitwise operations, and many conversions work the same way. The best candidates perform one regular operation over many independent values.&lt;/p&gt;

&lt;p&gt;Branches need more thought. A vector cannot cheaply send lane two through one complex path and lane five through an unrelated path while preserving the full benefit. Simple conditions can often become masks and selects: compute candidate values, then choose per lane. Deep, data-dependent control flow is a warning that the scalar implementation may remain clearer or faster.&lt;/p&gt;

&lt;p&gt;Dependencies between iterations are another warning. If element &lt;code&gt;i&lt;/code&gt; requires the result of element &lt;code&gt;i - 1&lt;/code&gt;, the lanes are not independent. Some reductions and prefix-style operations have vector algorithms, but they no longer fit the easy pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Reduce, mask, or store the result
&lt;/h3&gt;

&lt;p&gt;Vector work must eventually answer the original program’s question. There are three common endings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A transform stores the whole output vector.&lt;/li&gt;
&lt;li&gt;An aggregate keeps a vector accumulator and reduces its lanes near the end.&lt;/li&gt;
&lt;li&gt;A scan converts comparison lanes into a bit mask and locates a match.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This step varies more than the first three. It also determines whether an apparent vector speedup survives contact with the rest of the algorithm. Comparing eight values in parallel is not useful if code immediately loops over all eight booleans one by one on every iteration.&lt;/p&gt;

&lt;p&gt;Good scan loops make the common path cheap. If all lanes are ordinary data, reduce the boolean vector with &lt;code&gt;and&lt;/code&gt; and immediately continue to the next chunk. Only when a chunk contains an exceptional value does the code build a mask and inspect its position. The expensive path runs rarely, while long ordinary runs move a vector at a time.&lt;/p&gt;

&lt;p&gt;For sums, several independent vector accumulators can help the processor overlap work, followed by one horizontal reduction. Floating-point reductions require extra care: changing the grouping changes rounding, because floating-point addition is not associative. LLVM documents this explicitly and usually requires relaxed floating-point rules for the fastest reordered reduction.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Finish with the scalar tail
&lt;/h3&gt;

&lt;p&gt;If the input length is not divisible by the lane count, the vector loop leaves a remainder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;len&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="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Original scalar operation.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the scalar tail. It is deliberately boring. For an eight-lane vector it handles zero to seven values, so a straightforward loop is usually better than elaborate masking.&lt;/p&gt;

&lt;p&gt;Keeping the original scalar implementation has another benefit: it can be the fallback for targets where the program has no selected vector path. One piece of simple code becomes both the correctness reference and the cleanup path.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Real Scan from a Terminal
&lt;/h2&gt;

&lt;p&gt;Mitchell Hashimoto’s Ghostty example makes the pattern concrete. A terminal receives decoded code points and wants to batch a run of ordinary printable content. It needs to stop when it reaches a low-valued control character relevant to that parser path.&lt;/p&gt;

&lt;p&gt;The scalar form is almost perfect documentation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight zig"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;codepoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;len&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;codepoints&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0x0F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&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 vector version chooses a lane count supported by its target, creates a vector of &lt;code&gt;u32&lt;/code&gt;, and splats the cutoff. It then loads one full chunk and compares every lane with the threshold.&lt;/p&gt;

&lt;p&gt;If every comparison is true, an &lt;code&gt;and&lt;/code&gt; reduction says the entire chunk is ordinary text. The loop advances by the vector width. If any lane fails, the boolean vector is bit-cast into an integer mask. The code inverts the bits so failures become ones, then counts trailing zeros to obtain the first failing lane. It adds that lane offset to &lt;code&gt;end&lt;/code&gt; and exits. The scalar tail handles whatever remains after the last full vector or handles the whole input when no vector path is selected.&lt;/p&gt;

&lt;p&gt;The important optimization is not merely “eight comparisons at once.” It is the shape of the data. Terminal text commonly contains long stretches that take the all-true fast path. The reduction rejects an entire vector with one decision. Detailed work happens only in the chunk containing the boundary.&lt;/p&gt;

&lt;p&gt;Hashimoto reports theoretical lane-count improvements of four times for 128-bit Neon with &lt;code&gt;u32&lt;/code&gt;, eight times for AVX2, and sixteen times for 512-bit vectors. More meaningfully, the measured end-to-end terminal pipeline on an AVX2 desktop improved by roughly five times. That gap between theoretical width and observed application speed is normal. The terminal still has other parsing and state work; vector loads, reductions, mask conversion, and branches are not free; and the CPU can already overlap some scalar instructions.&lt;/p&gt;

&lt;p&gt;This is why benchmark claims need a scope. “The comparison handles eight lanes” describes an instruction. “The scan loop is faster” describes a microbenchmark. “Terminal throughput improved fivefold” describes the surrounding application on one machine and workload. All three can be true without being interchangeable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Compiler Does Not Always Do It
&lt;/h2&gt;

&lt;p&gt;Modern compilers already vectorize many scalar loops. LLVM has a loop vectorizer that widens consecutive iterations and an SLP vectorizer that combines similar neighboring scalar operations. Both are enabled by default. Before writing explicit vector code, build the scalar implementation with real release settings and inspect what happened.&lt;/p&gt;

&lt;p&gt;For Clang, optimization remarks make this visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clang &lt;span class="nt"&gt;-O3&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Rpass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;loop-vectorize &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Rpass-missed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;loop-vectorize &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-Rpass-analysis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;loop-vectorize &lt;span class="se"&gt;\&lt;/span&gt;
  source.c

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These reports tell you which loops were vectorized, which were missed, and which statement blocked the transformation. Compiler Explorer or a local disassembler can show the generated instructions, but optimization remarks are often the faster first answer.&lt;/p&gt;

&lt;p&gt;Auto-vectorization is especially effective for regular arithmetic with clear bounds and independent memory. It becomes harder when the compiler cannot prove that pointers do not overlap, when calls have unknown side effects, when control flow is complicated, or when an early exit must identify an exact element. Compilers can add runtime alias checks, recognize reductions, and vectorize some early exits, but every transformation must preserve language semantics and pass a profitability model.&lt;/p&gt;

&lt;p&gt;Explicit vectors provide intent. They say that operating by lanes is part of the algorithm, not an optional optimization the compiler may rediscover. That predictability is valuable in a proven hot path, but it creates responsibility too: maintainers must preserve the scalar fallback, test multiple architectures, and check that a supposedly generic vector operation did not lower into a slow sequence of scalar calls.&lt;/p&gt;

&lt;p&gt;The right order is therefore:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Measure the release build.&lt;/li&gt;
&lt;li&gt;Fix needless work and hostile data layout.&lt;/li&gt;
&lt;li&gt;Check whether the compiler vectorized the loop.&lt;/li&gt;
&lt;li&gt;Write explicit vectors when the hot path still matters and the result is maintainable.&lt;/li&gt;
&lt;li&gt;Measure again on representative hardware and data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Portable Source Is Not Runtime Dispatch
&lt;/h2&gt;

&lt;p&gt;Generic vector syntax avoids writing separate intrinsic dialects for every instruction set. Zig’s &lt;code&gt;@Vector&lt;/code&gt;, &lt;code&gt;@splat&lt;/code&gt;, comparisons, bitwise operators, and &lt;code&gt;@reduce&lt;/code&gt; express the algorithm without naming AVX or Neon intrinsics. The compiler still generates code for the selected target.&lt;/p&gt;

&lt;p&gt;That distinction matters for distributed binaries. A binary compiled for a conservative baseline cannot assume every user’s newer CPU supports AVX2 or AVX-512. Projects solve this with multiple compiled implementations and runtime dispatch: detect CPU features during startup, then choose the best compatible function. Google Highway is one library designed around portable SIMD and runtime target selection. Ghostty uses that heavier machinery for its hottest specialized paths while simpler generic vectors remain useful elsewhere.&lt;/p&gt;

&lt;p&gt;Runtime dispatch adds binary size, build complexity, and test combinations. It is worthwhile for a widely distributed parser, image library, database, or terminal with heavily exercised kernels. It may be unnecessary for software compiled specifically for one deployment target. “Portable SIMD” can mean portable source, portable baseline behavior, or one binary that dynamically exploits several instruction sets; those are different promises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where SIMD Wins—and Where It Does Not
&lt;/h2&gt;

&lt;p&gt;Good first candidates have several traits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The profiler identifies the loop as meaningful.&lt;/li&gt;
&lt;li&gt;Input is large enough to amortize setup and tail handling.&lt;/li&gt;
&lt;li&gt;Values are contiguous and use compact element types.&lt;/li&gt;
&lt;li&gt;Each lane performs the same comparison, arithmetic, or transformation.&lt;/li&gt;
&lt;li&gt;Iterations are mostly independent.&lt;/li&gt;
&lt;li&gt;The result can be stored, reduced, or represented as a mask cheaply.&lt;/li&gt;
&lt;li&gt;The scalar fallback is simple and testable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Byte scanning, ASCII classification, delimiter search, pixel transforms, audio mixing, checksums, filters, and numeric kernels often fit. Tiny collections, pointer-heavy graphs, allocation-dominated code, unpredictable per-element branches, and I/O-bound request handlers usually do not.&lt;/p&gt;

&lt;p&gt;Memory bandwidth also places a ceiling on improvement. If a loop only copies or adds a trivial value to a huge buffer, the memory subsystem may already be the bottleneck. A wider arithmetic instruction cannot make DRAM deliver bytes indefinitely faster. SIMD shines when it reduces instruction and branch work without merely moving an already bandwidth-limited stream.&lt;/p&gt;

&lt;p&gt;Alignment is less frightening than it once was on mainstream CPUs, which commonly support unaligned vector loads, but “supported” does not mean every address and cache-line crossing has identical cost. Use the language or library’s safe load APIs, avoid reading past allocations, and measure the actual target rather than relying on folklore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Vector Code as an Algorithm
&lt;/h2&gt;

&lt;p&gt;Performance code still needs ordinary correctness tests. The scalar implementation is an excellent oracle: run scalar and vector versions over the same inputs and require identical results.&lt;/p&gt;

&lt;p&gt;Exercise lengths around every boundary: zero, one, &lt;code&gt;lanes - 1&lt;/code&gt;, exactly &lt;code&gt;lanes&lt;/code&gt;, &lt;code&gt;lanes + 1&lt;/code&gt;, several full vectors, and a large irregular length. For a scan, place the exceptional value in every possible lane, at the first element, at the last element, in the scalar tail, and nowhere at all. Include repeated exceptional values and values exactly on both sides of the threshold.&lt;/p&gt;

&lt;p&gt;Then add property-based or randomized comparisons across many inputs. Run on every supported instruction-set path in CI when possible, not just the developer’s laptop. A runtime dispatcher should also be testable with target selection forced, so an AVX2 machine can still exercise the scalar implementation.&lt;/p&gt;

&lt;p&gt;Benchmarks need the same discipline. Prevent dead-code elimination, warm up JITs where relevant, separate setup from the measured kernel, use realistic distributions, and record CPU, compiler, flags, input size, and selected instruction set. Test both best-case long runs and match-heavy data. A scan optimized for rare delimiters may lose its advantage when almost every chunk exits early.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Skill Is Recognition
&lt;/h2&gt;

&lt;p&gt;Most developers do not need to memorize AVX instruction tables. They do benefit from recognizing the vector-shaped loop hiding in ordinary code.&lt;/p&gt;

&lt;p&gt;When a profile reveals a hot scan or transform over contiguous data, ask five questions: What constants should be broadcast? How many values can be loaded safely? Which operation applies independently to every lane? How can the vector result be stored or reduced without serializing all the work? What scalar code handles the remainder and fallback?&lt;/p&gt;

&lt;p&gt;That checklist turns SIMD from a mysterious bag of instructions into a repeatable program structure. Sometimes the compiler has already generated it. Sometimes the data layout must change first. Sometimes the workload is too small or branchy and the correct decision is to keep the clear scalar loop.&lt;/p&gt;

&lt;p&gt;And sometimes twelve careful lines let a terminal advance through ordinary text several code points at a time. That is not a stunt reserved for optimization specialists. It is a practical loop, expressed at the width the processor was built to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mitchellh.com/writing/everyone-should-know-simd" rel="noopener noreferrer"&gt;Mitchell Hashimoto: Everyone Should Know SIMD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=49010648" rel="noopener noreferrer"&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ziglang.org/documentation/master/#Vectors" rel="noopener noreferrer"&gt;Zig language documentation: vectors, &lt;code&gt;@splat&lt;/code&gt;, and &lt;code&gt;@reduce&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://llvm.org/docs/Vectorizers.html" rel="noopener noreferrer"&gt;LLVM documentation: auto-vectorization and diagnostics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/Neon%20Programmers%20Guide/NeonCaseStudy-PNG_Chromium.pdf" rel="noopener noreferrer"&gt;Arm: Neon intrinsics case study in Chromium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/google/highway" rel="noopener noreferrer"&gt;Google Highway portable SIMD library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/simdutf/simdutf" rel="noopener noreferrer"&gt;simdutf Unicode and Base64 routines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/simdjson/simdjson" rel="noopener noreferrer"&gt;simdjson high-performance JSON parser&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>Parallel Programming Is a Coordination Problem</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Tue, 21 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/parallel-programming-is-a-coordination-problem-1c6o</link>
      <guid>https://dev.to/0xgosu/parallel-programming-is-a-coordination-problem-1c6o</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5stxvcnv4tphaaqaqxgi.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5stxvcnv4tphaaqaqxgi.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modern computers contain an extraordinary amount of potential work. A laptop may have a mix of performance and efficiency cores. A server can offer dozens or hundreds of hardware threads. A GPU exposes thousands of smaller execution units. A cluster can add machines until the available compute looks almost limitless.&lt;/p&gt;

&lt;p&gt;Yet adding processors rarely makes a program faster in direct proportion to the processor count. Sixteen cores do not automatically produce sixteen times the throughput. Sometimes they produce a modest improvement. Sometimes they do nothing. Occasionally, a careless parallel version is slower than the serial program it replaced.&lt;/p&gt;

&lt;p&gt;The reason is simple: parallel programming is not mainly about acquiring more power. It is about coordinating the power already available.&lt;/p&gt;

&lt;p&gt;That idea sits at the center of Edgar Ortega’s reflective essay, &lt;a href="https://smolnero.com/posts/the-zen-of-parallel-programming" rel="noopener noreferrer"&gt;The Zen of Parallel Programming&lt;/a&gt;. The essay connects communication among processors with communication within teams and within a person. It is a useful metaphor, but it also points toward a concrete engineering discipline. Every parallel system has to answer the same questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What work can happen independently?&lt;/li&gt;
&lt;li&gt;What information must cross between workers?&lt;/li&gt;
&lt;li&gt;When must workers wait for one another?&lt;/li&gt;
&lt;li&gt;Who owns shared state?&lt;/li&gt;
&lt;li&gt;What happens when the work is uneven?&lt;/li&gt;
&lt;li&gt;How do we know the added coordination costs less than the time it saves?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Answer those questions well and extra processors become useful. Answer them poorly and the program spends its new capacity waiting, copying, contending, and invalidating caches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start With the Dependency Graph, Not the Thread Count
&lt;/h2&gt;

&lt;p&gt;The first job is decomposition: turn one large computation into pieces that can make progress independently.&lt;/p&gt;

&lt;p&gt;Some problems arrive with obvious boundaries. Rendering an image can often be divided into tiles. Processing a collection of independent files can assign one file to each worker. Searching a large space can partition the candidates. A simulation may divide physical space into regions.&lt;/p&gt;

&lt;p&gt;Other problems contain a chain of dependencies. Step B needs the result of step A, and step C needs B. No runtime or clever scheduling policy can make that chain fully parallel. The true structure of the work is a dependency graph, even if the original program is written as a simple loop.&lt;/p&gt;

&lt;p&gt;Two questions reveal whether a proposed split is useful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Can each task run for long enough to justify scheduling it?&lt;/li&gt;
&lt;li&gt;Can it finish without repeatedly consulting or modifying the same state as its neighbors?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If tasks are too small, orchestration dominates. A runtime must create or wake workers, place tasks in queues, transfer arguments, record completion, and possibly merge results. If tasks are too tightly coupled, workers spend their time communicating instead of computing.&lt;/p&gt;

&lt;p&gt;This is the granularity problem. A million tiny tasks may expose abundant theoretical parallelism while delivering terrible performance. Ten large tasks may be efficient individually but leave most of a 64-core machine idle. Good decomposition makes tasks large enough to amortize overhead and numerous enough to keep available workers busy.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Processors Cannot Remove the Serial Part
&lt;/h2&gt;

&lt;p&gt;Amdahl’s law gives the first reality check. If a fraction of a program must remain serial, that fraction limits the maximum speedup no matter how many processors are added.&lt;/p&gt;

&lt;p&gt;Suppose 80% of a workload can run in parallel while 20% must remain serial. With an unlimited number of processors, the parallel portion could approach zero time, but the serial fifth would remain. The theoretical maximum speedup is therefore five times. &lt;a href="https://www.intel.com/content/www/us/en/docs/advisor/user-guide/2025-1/use-amdahl-law.html" rel="noopener noreferrer"&gt;Intel’s explanation of Amdahl’s law&lt;/a&gt; uses this same example and attaches the most important optimization advice: measure the program instead of guessing.&lt;/p&gt;

&lt;p&gt;The basic model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;speedup(N) = 1 / (serial_fraction + parallel_fraction / N)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real systems do worse because this clean formula does not include scheduling overhead, communication, synchronization, cache misses, memory bandwidth, or load imbalance. Those costs can grow as the worker count grows.&lt;/p&gt;

&lt;p&gt;This changes where optimization should begin. Parallelize the expensive part, not the most visually obvious loop. Profile the serial implementation, identify the critical path, and estimate whether the parallelizable portion is large enough to pay for coordination. A fast serial algorithm is often the best foundation for a fast parallel one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Communication Has a Price
&lt;/h2&gt;

&lt;p&gt;Workers need inputs and eventually must expose outputs. The method of communication shapes both correctness and performance.&lt;/p&gt;

&lt;p&gt;With message passing, a worker receives data it owns, computes, and sends a result. Ownership is explicit and interference is limited, but moving data may require serialization, copies, queue operations, or network transfers.&lt;/p&gt;

&lt;p&gt;With shared memory, workers can access the same region directly. That avoids some copying and can be extremely fast. It also creates harder questions: which worker may write, when are changes visible, and how do readers distinguish a complete update from a partial one?&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.python.org/3/library/multiprocessing.shared_memory.html" rel="noopener noreferrer"&gt;Python shared-memory documentation&lt;/a&gt; captures the tradeoff neatly. Shared blocks let processes avoid the serialization and copying involved in sockets or disk, but their lifecycle and access must be managed. At a lower level, the stakes are higher because compilers and processors can reorder independent memory operations.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.kernel.org/core-api/wrappers/memory-barriers.html" rel="noopener noreferrer"&gt;Linux kernel memory-barrier documentation&lt;/a&gt; explains why barriers exist: modern CPUs use reordering, speculation, deferred operations, and store combination to run faster. A barrier constrains the order of specified memory accesses; paired synchronization or atomic operations are still needed to establish when another processor may safely observe an update. These mechanisms are not decorative details. They are part of the contract that makes concurrent state meaningful.&lt;/p&gt;

&lt;p&gt;A useful default is to reduce communication before optimizing it. Give each worker private input and private output where possible. Combine partial results at explicit boundaries. Prefer immutable shared data to mutable shared data. Make ownership visible in the program structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synchronization Is Necessary Waiting
&lt;/h2&gt;

&lt;p&gt;When workers interact, some waiting is unavoidable. A consumer cannot use data before a producer finishes it. A reduction cannot return the final total until every required partial total is available. A phase-based simulation may need all regions to reach the boundary before the next step begins.&lt;/p&gt;

&lt;p&gt;Locks, atomics, barriers, semaphores, channels, futures, and task dependencies express these rules. They protect correctness, but each synchronization point can reduce parallel progress.&lt;/p&gt;

&lt;p&gt;Consider a shared counter protected by one lock. It is correct, yet every worker must line up at the same door. Adding workers increases contention instead of throughput. A better design might give each worker a local counter and sum the counters once at the end. The result is the same, while synchronization moves from every update to one reduction boundary.&lt;/p&gt;

&lt;p&gt;This does not mean locks are bad. It means the size and frequency of the critical section matter. Keep locked regions small, avoid performing slow I/O while holding a lock, and do not protect unrelated state with one global lock merely because it is convenient.&lt;/p&gt;

&lt;p&gt;Be equally careful when removing synchronization. The &lt;a href="https://www.openmp.org/spec-html/5.0/openmpse1.html" rel="noopener noreferrer"&gt;OpenMP specification&lt;/a&gt; explicitly leaves data dependencies, races, and deadlocks to the application developer. A program can compile, run quickly, and still be wrong only once in a million executions.&lt;/p&gt;

&lt;p&gt;Parallel correctness needs stronger evidence than “it worked on my machine.” Use race detectors where the language provides them. Test under varied worker counts. Force unusual scheduling with stress tests. Check invariants, not only final happy-path outputs. Make cancellation and error propagation part of the design, because one failed worker can otherwise leave every other worker waiting forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  Load Balance Decides Who Waits
&lt;/h2&gt;

&lt;p&gt;Even perfectly independent tasks do not help if their sizes vary wildly.&lt;/p&gt;

&lt;p&gt;Imagine eight workers and eight tasks. Seven tasks take one second and the last takes a minute. After one second, seven workers become idle while the remaining worker determines the completion time. The machine is mostly idle even though the work was fully parallelizable.&lt;/p&gt;

&lt;p&gt;Static partitioning works well when task costs are predictable and similar. Divide the input into contiguous chunks, assign each chunk once, and keep scheduling overhead low. Dynamic scheduling is better when costs vary. Workers pull from a shared queue or steal tasks from one another, trading extra coordination for better utilization.&lt;/p&gt;

&lt;p&gt;Chunk size controls the balance. Large chunks reduce queue traffic and can improve memory locality, but they make imbalance more likely. Small chunks spread irregular work more evenly, but increase scheduling and synchronization overhead. The right value is empirical.&lt;/p&gt;

&lt;p&gt;The critical path is more informative than average utilization. A worker that finishes early does not make the result arrive early if another dependency chain remains. Optimize the longest chain of dependent work, and monitor tail latency rather than celebrating a high average CPU percentage.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Memory System Can Become the Bottleneck
&lt;/h2&gt;

&lt;p&gt;Code may have enough independent arithmetic and still fail to scale because all workers compete for memory bandwidth. Adding cores does not proportionally add channels to main memory. Once the memory subsystem is saturated, more threads mostly create more outstanding requests.&lt;/p&gt;

&lt;p&gt;Data layout matters as much as task layout. Sequential access lets caches and prefetchers help. Compact working sets reduce trips to main memory. Keeping related data together improves locality, while separating frequently written per-worker state can prevent destructive interference.&lt;/p&gt;

&lt;p&gt;One subtle failure is false sharing. Two workers may update completely different variables, yet those variables occupy the same cache line. Each write invalidates the other core’s cached copy, so the line bounces between cores even though the program has no logical sharing. &lt;a href="https://www.intel.com/content/www/us/en/docs/onetbb/developer-guide-api-reference/2021-12/memory-allocation.html" rel="noopener noreferrer"&gt;Intel oneTBB’s allocator guide&lt;/a&gt; defines the problem in exactly these terms, and the &lt;a href="https://docs.kernel.org/kernel-hacking/false-sharing.html" rel="noopener noreferrer"&gt;Linux kernel guide&lt;/a&gt; shows common mitigations such as isolating hot data on separate cache lines.&lt;/p&gt;

&lt;p&gt;Padding or reorganizing data can fix false sharing, but it consumes memory and may create new cache problems. Measure before changing layouts. Performance counters, profilers, and scaling curves are better guides than folklore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose a Model That Matches the Work
&lt;/h2&gt;

&lt;p&gt;“Parallel programming” includes several models, and each makes different coordination costs visible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data parallelism
&lt;/h3&gt;

&lt;p&gt;Apply the same operation to different pieces of a collection. Vector instructions, GPU kernels, and parallel loops fit here. This model works best when elements are independent and control flow is regular.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task parallelism
&lt;/h3&gt;

&lt;p&gt;Run different operations concurrently, often through a task graph or work-stealing scheduler. This fits pipelines, recursive divide-and-conquer algorithms, build systems, and applications with irregular work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pipelines
&lt;/h3&gt;

&lt;p&gt;Separate a process into stages so different items occupy different stages at the same time. Throughput improves once the pipeline is full, but the slowest stage limits the rate and buffers introduce backpressure concerns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Actors and message passing
&lt;/h3&gt;

&lt;p&gt;Give each actor private state and communicate through messages. This makes ownership clearer and extends naturally across processes or machines, but mailbox growth, delivery semantics, supervision, and serialization become part of the design.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared-memory threads
&lt;/h3&gt;

&lt;p&gt;Let workers operate in one address space. Communication is cheap and flexible, but races and memory-ordering bugs are easier to create. &lt;a href="https://www.openmp.org/spec-html/5.2/openmpch1.html" rel="noopener noreferrer"&gt;OpenMP&lt;/a&gt;, for example, supports work distribution, tasks, synchronization, and explicit rules for shared and private data.&lt;/p&gt;

&lt;p&gt;No model abolishes coordination. It relocates it. Pick the model whose costs align with the problem and whose correctness rules your team can explain.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Workflow for Parallelizing Code
&lt;/h2&gt;

&lt;p&gt;Parallelization is safer when treated as an experiment with checkpoints.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Define the goal.&lt;/strong&gt; Decide whether success means lower latency, higher throughput, better hardware utilization, or the ability to process a larger problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure the serial baseline.&lt;/strong&gt; Record representative workloads, wall-clock time, CPU time, memory use, and output correctness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find the critical path.&lt;/strong&gt; Profile where time is actually spent and map the data dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose ownership boundaries.&lt;/strong&gt; State what data each worker owns and what, if anything, is shared.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build the simplest correct version.&lt;/strong&gt; Start with coarse tasks and explicit synchronization. Preserve a serial reference implementation when practical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test correctness under stress.&lt;/strong&gt; Vary inputs and worker counts, exercise cancellation and failure, and use race-detection tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure scaling.&lt;/strong&gt; Compare one, two, four, eight, and more workers. A flattening or declining curve tells you where coordination or resources take over.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspect the bottleneck.&lt;/strong&gt; Look separately at contention, task imbalance, cache misses, memory bandwidth, scheduling, and I/O.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tune one cause at a time.&lt;/strong&gt; Change chunk size, data layout, ownership, or synchronization, then remeasure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set a sensible ceiling.&lt;/strong&gt; The fastest worker count may be lower than the available hardware thread count. Make that a supported configuration, not a disappointment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This workflow keeps the serial version as a source of truth and treats speedup as evidence, not an assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Same Pattern Appears in Human Systems
&lt;/h2&gt;

&lt;p&gt;The original essay’s human analogy becomes clearer after the technical details are visible.&lt;/p&gt;

&lt;p&gt;A team can add capable people and still slow down because communication paths multiply. Work can be split on paper yet remain coupled through one reviewer, one deployment pipeline, one shared database, or one person who holds essential context. Meetings become barriers. A central approval becomes a lock. A crowded backlog becomes a task queue with no useful scheduling policy.&lt;/p&gt;

&lt;p&gt;The solution is not silence or isolation. Processors also need communication. The goal is honest boundaries: clear ownership, stable interfaces, timely signals, and synchronization only where the shared outcome requires it.&lt;/p&gt;

&lt;p&gt;The analogy also applies within an individual. Thought, emotion, memory, physical energy, and speech can pull in different directions. Unfinished experiences continue to consume attention like processes that never reached completion. Honest acknowledgement acts as synchronization: it lets the parts of a person share the same state instead of maintaining conflicting versions.&lt;/p&gt;

&lt;p&gt;That is the grounded meaning behind the essay’s image of a fire burning completely. Completion is not erasure. In a program, completed work leaves a result while releasing resources. In a person, processing an experience can preserve the lesson without keeping the whole event active in working memory.&lt;/p&gt;

&lt;p&gt;The metaphor has limits, of course. People are not processors, and human communication should never be reduced to throughput. But the shared lesson survives: capacity divided against itself is not useful capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coordination Is the Real Algorithm
&lt;/h2&gt;

&lt;p&gt;The most important parallel optimization is often not a faster lock or a more advanced runtime. It is a better division of responsibility.&lt;/p&gt;

&lt;p&gt;Strong parallel designs have a visible shape. Independent work is genuinely independent. Shared state is small and intentional. Communication carries necessary information rather than leaking internal details. Synchronization marks real dependencies. The scheduler has enough work to balance without drowning in tiny tasks. Data is laid out for the memory system the program actually runs on.&lt;/p&gt;

&lt;p&gt;More processors amplify that design. They also amplify its mistakes.&lt;/p&gt;

&lt;p&gt;The practical mindset is therefore modest: begin with the problem, measure the serial path, expose independence, communicate less, synchronize deliberately, and watch the system rather than the core count. Parallel speed is not produced by multiplication alone. It emerges when many parts can make progress without obstructing one another.&lt;/p&gt;

&lt;p&gt;That is as close as parallel programming gets to Zen: not limitless power, but power that no longer fights itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://smolnero.com/posts/the-zen-of-parallel-programming" rel="noopener noreferrer"&gt;The Zen of Parallel Programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=48907390" rel="noopener noreferrer"&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.intel.com/content/www/us/en/docs/advisor/user-guide/2025-1/use-amdahl-law.html" rel="noopener noreferrer"&gt;Use Amdahl’s Law and Measure the Program&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.openmp.org/spec-html/5.2/openmpch1.html" rel="noopener noreferrer"&gt;OpenMP API overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.kernel.org/core-api/wrappers/memory-barriers.html" rel="noopener noreferrer"&gt;Linux kernel memory barriers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.kernel.org/kernel-hacking/false-sharing.html" rel="noopener noreferrer"&gt;Linux kernel false sharing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/library/multiprocessing.shared_memory.html" rel="noopener noreferrer"&gt;Python shared memory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>Transcribe.cpp: The Missing Runtime for Local Speech-to-Text</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Mon, 20 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/transcribecpp-the-missing-runtime-for-local-speech-to-text-2i3</link>
      <guid>https://dev.to/0xgosu/transcribecpp-the-missing-runtime-for-local-speech-to-text-2i3</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcstgav4x2cz1fp7cdkki.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcstgav4x2cz1fp7cdkki.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Speech recognition no longer needs a data center. A modern laptop can turn recorded audio into accurate text faster than the audio plays, and it can do so without sending a voice recording to anyone else’s server.&lt;/p&gt;

&lt;p&gt;The hard part is shipping that ability in an application.&lt;/p&gt;

&lt;p&gt;An automatic speech recognition model usually arrives inside the research stack that produced it. One expects PyTorch and CUDA. Another works through Apple’s MLX. A third has an ONNX export that runs on the CPU but leaves the GPU idle. Each family has its own preprocessing, tensor shapes, decoder, tokenizer, streaming state, and packaging conventions. A demo can tolerate those differences; a desktop application for macOS, Windows, and Linux cannot.&lt;/p&gt;

&lt;p&gt;That is the problem &lt;strong&gt;transcribe.cpp&lt;/strong&gt; tries to solve. It is a C/C++ inference library built on ggml, with one public interface over a wide range of speech-to-text architectures. Its first release supports streaming and batch transcription, GPU acceleration through Metal, Vulkan, and CUDA, a CPU path, GGUF model files, and maintained bindings for Python, JavaScript/TypeScript, Rust, and Swift/Objective-C.&lt;/p&gt;

&lt;p&gt;The useful idea is not merely “speech recognition in C++.” It is that model support, hardware acceleration, numerical correctness, and application distribution should be treated as one engineering problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Model Was Never The Whole Product
&lt;/h2&gt;

&lt;p&gt;CJ Pais started transcribe.cpp while maintaining &lt;a href="https://handy.computer/" rel="noopener noreferrer"&gt;Handy&lt;/a&gt;, an open-source dictation application. Handy listens while a keyboard shortcut is held, transcribes locally, and inserts the result into the active text field. It sounds like one small feature. Underneath, it has to record audio, manage model downloads, choose the right inference backend, handle multiple operating systems, package native dependencies, and remain responsive on machines with very different processors.&lt;/p&gt;

&lt;p&gt;Whisper.cpp already provides a strong, portable implementation of OpenAI’s Whisper family. But speech recognition has moved beyond one architecture. Parakeet, Canary, Moonshine, Qwen3-ASR, Granite Speech, Voxtral, SenseVoice, Nemotron, and other families make different trade-offs around latency, languages, model size, streaming, translation, and domain specialization.&lt;/p&gt;

&lt;p&gt;Adding one of those models to an application through its reference implementation is straightforward enough. Supporting ten of them is a multiplication problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The model may require a large Python environment that is awkward to embed.&lt;/li&gt;
&lt;li&gt;Acceleration may exist only for NVIDIA CUDA or only for Apple hardware.&lt;/li&gt;
&lt;li&gt;An ONNX export may be available, but its origin and numerical fidelity may be unclear.&lt;/li&gt;
&lt;li&gt;Preprocessing and decoding logic may live outside the exported graph.&lt;/li&gt;
&lt;li&gt;A mobile or desktop application needs a stable native API and predictable model files.&lt;/li&gt;
&lt;li&gt;Every new engine creates another build, release, and support path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why local AI often looks better in a notebook than in a downloadable product. Model quality is visible, while distribution complexity is hidden.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Runtime, Many Architectures
&lt;/h2&gt;

&lt;p&gt;Transcribe.cpp puts the common tensor work on &lt;a href="https://github.com/ggml-org/ggml" rel="noopener noreferrer"&gt;ggml&lt;/a&gt;, the same low-level machine-learning library that helped make llama.cpp and whisper.cpp practical. Model weights are distributed as GGUF files, and the runtime maps their computation onto the available backend.&lt;/p&gt;

&lt;p&gt;The project currently advertises 16 model families and more than 60 variants. That count includes familiar encoder-decoder systems such as Whisper, streaming transducers, CTC models, and audio-language models. Supporting them does not mean pretending every architecture is identical. Each family still needs its own feature extraction, graph construction, state handling, and decoder. The shared layer is the runtime, file format, hardware abstraction, build system, and public API around those implementations.&lt;/p&gt;

&lt;p&gt;This separation is important. A universal interface is useful only if it preserves the capabilities that distinguish the models. Batch transcription can process a completed recording with full context. Streaming transcription must retain state across audio chunks and produce partial results with low latency. A multilingual audio-language model may also translate or follow a prompt. A medical model may be accurate in one narrow domain but inappropriate elsewhere.&lt;/p&gt;

&lt;p&gt;Transcribe.cpp supplies a common place for those differences rather than forcing every application developer to rediscover them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Portable Acceleration Is The Main Event
&lt;/h2&gt;

&lt;p&gt;CPU inference is a valuable fallback, but local AI becomes much more compelling when it uses hardware already in the machine. The catch is that “the GPU” is not one target.&lt;/p&gt;

&lt;p&gt;On Apple silicon, Metal is the natural path. NVIDIA systems favor CUDA. Vulkan offers a cross-vendor route across many AMD, Intel, NVIDIA, Qualcomm, and ARM devices on Linux, Windows, and Android. Transcribe.cpp exposes all three, plus a tinyBLAS-accelerated CPU path. Its documentation says Metal is enabled automatically on Apple silicon; Vulkan and CUDA can be selected at build time.&lt;/p&gt;

&lt;p&gt;Ggml makes this manageable by representing model work as a computation graph and scheduling supported operations on a backend. The Vulkan scheduler, for example, can place supported graph nodes on the GPU while falling back to the CPU for operations that do not have a Vulkan implementation. That is more realistic than requiring every backend to achieve perfect feature parity before it is useful.&lt;/p&gt;

&lt;p&gt;Portability still has a cost. A graph that runs correctly on one backend may expose numerical, synchronization, memory, or kernel-coverage problems on another. Performance also includes more than the neural network. The host-side decoder can become the bottleneck after GPU acceleration makes the encoder fast. Transcribe.cpp recommends OpenBLAS for that path and reports a roughly 10–15x decoder speedup over its scalar fallback.&lt;/p&gt;

&lt;p&gt;The broader lesson is easy to miss: accelerating the biggest matrix multiplications is not the same as accelerating the application. Audio conversion, feature extraction, memory transfers, decoding, and output handling all sit on the critical path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Correctness Needs Two Kinds Of Tests
&lt;/h2&gt;

&lt;p&gt;Porting a model is not finished when it produces plausible words.&lt;/p&gt;

&lt;p&gt;Speech recognizers are unusually good at hiding implementation mistakes. A wrong normalization constant, padding rule, positional offset, vocabulary mapping, or decoder transition may still yield readable text. Testing a few clean recordings by ear can make a broken port look complete.&lt;/p&gt;

&lt;p&gt;Transcribe.cpp addresses this at two levels. First, it numerically compares intermediate and final tensors against the reference implementation. This is the close-up test: given the same input, does the port perform the same computation within an expected tolerance?&lt;/p&gt;

&lt;p&gt;Second, it runs word error rate sweeps over thousands of utterances. Word error rate counts substitutions, deletions, and insertions relative to a reference transcript, divided by the number of reference words. This is the end-to-end test: even if floating-point values are not bit-for-bit identical, does the system produce equivalent language output across a real corpus?&lt;/p&gt;

&lt;p&gt;The project publishes the models it supports through the Handy organization on Hugging Face and says each has been numerically verified and WER-tested against its source implementation. That does not prove a model is universally accurate. A benchmark corpus may not represent a user’s accent, language, microphone, background noise, or vocabulary. It does provide evidence for a narrower and crucial claim: the port did not quietly make the original model worse.&lt;/p&gt;

&lt;p&gt;These two checks belong together. Tensor comparisons localize implementation errors, while WER testing catches changes that matter to users. A production inference port needs both internal equivalence and external behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  GGUF Turns A Model Into A Shippable Artifact
&lt;/h2&gt;

&lt;p&gt;Reference checkpoints are often optimized for researchers who will load them through the original framework. Applications need something more stable: a model file with weights, metadata, architecture information, and a predictable loader.&lt;/p&gt;

&lt;p&gt;Transcribe.cpp distributes prebuilt GGUF files for supported variants. It also includes conversion tools for source checkpoints and a quantizer with formats ranging from F16 through Q8, Q6, Q5, and Q4 presets.&lt;/p&gt;

&lt;p&gt;Quantization reduces the precision used to store and calculate with weights. Smaller files download faster, consume less memory, and can run on more devices. The trade-off is potential accuracy loss and backend-specific performance behavior. There is no universally best quantization; application developers must balance model size, speed, memory, and WER on representative audio.&lt;/p&gt;

&lt;p&gt;A canonical model artifact has another benefit: it makes a bug reproducible. “This model from this repository, loaded through this Python environment” leaves room for dependency drift and conversion differences. A specific GGUF plus a runtime version is a much tighter unit for testing and support.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API Is Designed To Leave The Demo
&lt;/h2&gt;

&lt;p&gt;The core library exposes a single C header, while official bindings target four application ecosystems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python for scripts, evaluation, and existing machine-learning workflows.&lt;/li&gt;
&lt;li&gt;TypeScript and JavaScript for desktop and server applications in that ecosystem.&lt;/li&gt;
&lt;li&gt;Rust, which Handy itself uses.&lt;/li&gt;
&lt;li&gt;Swift and Objective-C for native Apple software.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maintaining those bindings beside the library matters. Community bindings are valuable, but an application team needs to know that API changes, memory ownership, callbacks, and streaming state will be updated together. A binding that compiles once and then drifts is another abandoned integration path.&lt;/p&gt;

&lt;p&gt;The command-line experience is deliberately small: build with CMake, download a model, and pass a 16 kHz mono WAV file to &lt;code&gt;transcribe-cli&lt;/code&gt;. Real applications will need more. They must resample live audio, manage devices, buffer streaming chunks, download and verify model files, expose progress and cancellation, handle unavailable backends, and package native libraries for every target.&lt;/p&gt;

&lt;p&gt;Transcribe.cpp removes the model-specific inference engines from that list. It does not remove application engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy Is A Property Of The Whole Path
&lt;/h2&gt;

&lt;p&gt;On-device transcription has an obvious privacy advantage: raw speech can remain on hardware the user controls. Handy makes this the center of its promise. Local execution also works without an internet connection, avoids per-minute API charges, and can reduce network latency.&lt;/p&gt;

&lt;p&gt;But “uses a local model” is not by itself a privacy guarantee. The application may retain recordings, sync transcript history, send crash reports, fetch remote corrections, or pass the text into another cloud service. Operating-system permissions, model-download integrity, log files, and temporary audio all matter.&lt;/p&gt;

&lt;p&gt;The runtime gives developers the option to keep inference local. The finished product must preserve that boundary intentionally and explain it accurately.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Version 0.1 Does Not Promise
&lt;/h2&gt;

&lt;p&gt;The project’s author calls the first release rough around the edges, and that is the right framing. A broad compatibility table creates a substantial maintenance obligation. New upstream checkpoints appear, model architectures evolve, ggml changes, GPU drivers regress, and users combine operating systems and hardware that a small project cannot test exhaustively.&lt;/p&gt;

&lt;p&gt;There are also product-level questions outside a general inference runtime:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speaker diarization is model-dependent, not a universal feature.&lt;/li&gt;
&lt;li&gt;Voice activity detection and turn-taking policy shape streaming usability.&lt;/li&gt;
&lt;li&gt;Punctuation, timestamps, translation, and language detection differ by family.&lt;/li&gt;
&lt;li&gt;Real-time performance depends on the exact model, quantization, backend, and device.&lt;/li&gt;
&lt;li&gt;A model’s license and training terms may constrain redistribution even when the runtime is MIT-licensed.&lt;/li&gt;
&lt;li&gt;Accuracy claims need evaluation on the target population and acoustic environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The library is therefore best understood as promising a coherent integration surface, not identical behavior from every model on every machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Better Abstraction For Local AI
&lt;/h2&gt;

&lt;p&gt;Cloud speech APIs became popular partly because they collapse a messy stack into one request. Send audio to an endpoint and receive text. The provider owns accelerators, model deployment, versioning, and scaling.&lt;/p&gt;

&lt;p&gt;Local inference needs an equivalent abstraction, but it cannot hide the user’s hardware. It has to turn heterogeneity into a manageable set of choices: model, quantization, backend, and a stable API. It also needs evidence that a portable port remains faithful to the reference.&lt;/p&gt;

&lt;p&gt;Transcribe.cpp is interesting because it treats all of that plumbing as the product. The project grew from an application maintainer’s practical pain, not from a desire to publish one more speech model. Its success will depend less on a headline benchmark than on whether new model families can be added, tested, packaged, accelerated, and upgraded without making downstream applications absorb the churn.&lt;/p&gt;

&lt;p&gt;That is the missing layer in much of local AI. Capable models already exist. The scarce work is turning them into dependable software that people can install.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://workshop.cjpais.com/projects/transcribe-cpp" rel="noopener noreferrer"&gt;CJ Pais’ transcribe.cpp introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/handy-computer/transcribe.cpp" rel="noopener noreferrer"&gt;transcribe.cpp source, model matrix, build instructions, and bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.mozilla.ai/announcing-transcribe-cpp/" rel="noopener noreferrer"&gt;Mozilla.ai announcement and Builders in Residence context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://handy.computer/" rel="noopener noreferrer"&gt;Handy local speech-to-text application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/handy-computer" rel="noopener noreferrer"&gt;Handy model collection and validation notes on Hugging Face&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ggml-org-ggml.mintlify.app/backends/vulkan" rel="noopener noreferrer"&gt;ggml Vulkan backend documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=48963879" rel="noopener noreferrer"&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>Regressive JPEGs: Making One Image Behave Like Video</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Sun, 19 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/regressive-jpegs-making-one-image-behave-like-video-40ln</link>
      <guid>https://dev.to/0xgosu/regressive-jpegs-making-one-image-behave-like-video-40ln</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9e8pne1ti9112yd40eee.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9e8pne1ti9112yd40eee.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A JPEG is supposed to settle down as it loads. The first glimpse may be fuzzy, but every new byte should make the same photograph more accurate.&lt;/p&gt;

&lt;p&gt;That expectation is built into a conforming progressive scan sequence, but decoders also have to cope with imperfect files. Progressive JPEG gives every scan a header describing which parts of the image it carries. Some permissive decoders will accept a later scan that improperly revisits coefficients already supplied and replace the pixels they previously rendered. Feed such a decoder scans taken from different photographs and the image does not progress toward clarity. It changes its mind.&lt;/p&gt;

&lt;p&gt;Maurycy’s “Regressive JPEGs” experiment pushes that decoder tolerance until a plain &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; element appears to play a short, low-resolution video. There is no GIF container, video element, canvas, CSS animation, or JavaScript. The apparent frames are scan segments in one JPEG-shaped stream arriving over the network.&lt;/p&gt;

&lt;p&gt;The result is a delightful file-format trick. It is also a compact lesson in transform coding, incremental decoding, defensive limits, and the distance between strict conformance and real-world parser behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Progressive JPEG Exists
&lt;/h2&gt;

&lt;p&gt;A baseline JPEG is usually decoded in spatial order. As a slow download arrives, the browser can reveal a sharp strip at the top while the rest remains empty. That was tolerable on fast connections, but it made large images feel painfully slow on the early web.&lt;/p&gt;

&lt;p&gt;Progressive JPEG rearranges the compressed information into multiple full-image scans. An early scan contains enough low-frequency information to display a coarse version of the complete picture. Later scans add detail and precision. The image fills its box quickly, then sharpens in place.&lt;/p&gt;

&lt;p&gt;This is possible because JPEG does not store a photograph as a grid of ready-to-display RGB pixels. The encoder typically converts it to YCbCr: one luminance component, Y, and two color-difference components, Cb and Cr. Because human vision notices fine brightness detail more readily than fine color detail, chroma can often be sampled less densely without an obvious loss.&lt;/p&gt;

&lt;p&gt;Each component is divided into 8-by-8 blocks and transformed into 64 discrete cosine transform coefficients. The first coefficient, called DC, represents the block’s average level. The remaining 63 AC coefficients describe increasingly fine changes within it. Quantization discards precision that is less likely to be noticed, and entropy coding packs the resulting values efficiently.&lt;/p&gt;

&lt;p&gt;A progressive encoder can distribute that material in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spectral selection sends groups of coefficient positions in separate scans: DC first, then bands of AC coefficients.&lt;/li&gt;
&lt;li&gt;Successive approximation sends rough bits first and refines their precision in later scans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A typical scan plan mixes both. It may send rough DC values for all three components, several bands of luminance and chrominance detail, then final refinement bits. The exact plan is an encoder decision rather than a universal sequence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scan Header Is The Doorway
&lt;/h2&gt;

&lt;p&gt;Every scan begins with a Start of Scan marker, &lt;code&gt;FF DA&lt;/code&gt;, followed by a header. Among other things, the header names the included image components, selects entropy tables, gives the starting and ending DCT coefficient positions, and specifies the successive-approximation bits.&lt;/p&gt;

&lt;p&gt;Those fields are normally instructions for improving one image. A decoder may first learn the average value of every block, then learn its broad edges, and finally receive fine texture. Crucially, however, every scan declares its own coefficient range. A later scan is not inherently bound to the visual meaning of an earlier one.&lt;/p&gt;

&lt;p&gt;That creates the opening: construct a JPEG stream whose later scans improperly supply the same coefficient positions again, but take their values from a different source image. This is not a conforming progressive sequence, and libjpeg-family decoders may warn about a bogus progression. A tolerant incremental decoder can nevertheless render the data it has now. When the replacement scan arrives, the canvas changes.&lt;/p&gt;

&lt;p&gt;The simplest proof uses several progressive JPEGs with identical dimensions. Keep one shared set of structural markers and tables, remove the redundant start-of-image, start-of-frame, and end-of-image markers from the additional files, and append their scan segments. Maurycy used a small C program, but the operation is conceptually just bitstream splicing.&lt;/p&gt;

&lt;p&gt;When delivered slowly, the combined file first shows one photograph and then another. The browser still believes it is decoding a single image. The “animation” is a side effect of partial rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why The Obvious Version Breaks Down
&lt;/h2&gt;

&lt;p&gt;Joining complete progressive images is enough for a demonstration, but it is a poor route to video. A normal progressive image may need roughly ten scans. If each visible frame consumes all of them, even a generous decoder limit buys only a few frames.&lt;/p&gt;

&lt;p&gt;It also produces ghosting. Some AC scans introduce new spectral bands, while others refine the precision of values sent earlier. During a transition between spliced images, only part of the coefficient set may have been replaced. The reconstructed block then contains a mixture of both pictures, so the images smear together instead of switching cleanly.&lt;/p&gt;

&lt;p&gt;Starting with baseline JPEG does not solve the problem. A baseline scan can contain DC and AC coefficients together, which sounds perfect for one scan per frame, but a baseline decoder considers the image complete after that scan. Progressive mode has a stricter rule: DC and AC data cannot occupy the same scan.&lt;/p&gt;

&lt;p&gt;The smallest useful progressive frame is therefore a single DC-only scan.&lt;/p&gt;

&lt;p&gt;That scan carries the average value for each transform block, with no higher-frequency texture. It produces a coarse mosaic rather than a flat color. With common 4:2:0 chroma subsampling, the coded data is organized in larger minimum coded units for color, but the luminance transform is still based on 8-by-8 blocks. The precise visual scaling depends on the component sampling and decoder smoothing; the durable point is that each frame is recognizable but intentionally blocky.&lt;/p&gt;

&lt;p&gt;Removing AC data fixes both earlier problems. Each picture needs only one scan, and every scan replaces the complete set of DC values instead of combining new detail with an old frame.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building A One-Scan Frame
&lt;/h2&gt;

&lt;p&gt;The standard libjpeg toolchain already exposes the required control. &lt;code&gt;jpegtran&lt;/code&gt; accepts a scan script, so a source image can be transformed into a progressive JPEG containing only one full-precision DC scan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# frame.scans
0,1,2: 0-0, 0, 0;


jpegtran -scans frame.scans -outfile frame-01.jpg input-01.jpg

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component list &lt;code&gt;0,1,2&lt;/code&gt; selects the three image components. The &lt;code&gt;0-0&lt;/code&gt; range selects only the DC coefficient, and the final values request full precision rather than a later refinement pass.&lt;/p&gt;

&lt;p&gt;Repeat that conversion for same-sized source frames. A merger can copy the common JPEG structure, then append the entropy-coded scan from each DC-only file, and finally write one end-of-image marker. The output still identifies itself as a progressive JPEG. Its unusual behavior emerges only while a decoder consumes it incrementally.&lt;/p&gt;

&lt;p&gt;There are important engineering constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All frames need compatible dimensions, component layout, sampling factors, quantization tables, and coding assumptions.&lt;/li&gt;
&lt;li&gt;Byte stuffing and marker parsing must be handled correctly; blindly searching compressed data for marker-looking bytes is unsafe.&lt;/li&gt;
&lt;li&gt;The server must stream the response instead of buffering the complete object.&lt;/li&gt;
&lt;li&gt;Intermediaries may buffer, recompress, optimize, or reject the file.&lt;/li&gt;
&lt;li&gt;Browser behavior is not a stable playback API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maurycy found that a roughly 90-scan image worked across the browsers tested, with Chrome stopping around that point and Firefox accepting more. That number is an observation, not a guarantee. Versions, libraries, and platform image pipelines can differ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scan Limits Are A Security Boundary
&lt;/h2&gt;

&lt;p&gt;Why would a decoder continue far enough to render a few repeated scans, then refuse more of them? Work amplification.&lt;/p&gt;

&lt;p&gt;Progressive decoding can require a full-image coefficient buffer and repeated output passes. A compact file with an unreasonable number of scans may force disproportionately large allocations or repeated computation. libjpeg-turbo added scan-limit controls specifically so applications can defend against abuse of progressive JPEG. Its command-line tools expose &lt;code&gt;-maxscans&lt;/code&gt;, while its API lets callers choose a limit.&lt;/p&gt;

&lt;p&gt;The animation trick is not remote code execution. Its repeated initial scans are nonconforming input that tolerant decoders may process, and it inhabits the same territory that defensive limits protect. A decoder designed around normal photographic scan plans has good reason to distrust thousands of redundant passes.&lt;/p&gt;

&lt;p&gt;For application developers, the lesson is broader than JPEG: validate decoded cost, not just compressed file size. Pixel dimensions, frame counts, nesting depth, scan counts, expansion ratios, and total work can all matter more than the upload’s byte length.&lt;/p&gt;

&lt;p&gt;For forensic tools and content pipelines, “JPEG” is also too coarse a classification. It can be useful to record whether a file is baseline or progressive, how many scans it contains, which spectral ranges recur, and whether later scans improperly redefine earlier data. A file that a browser accepts as a still image can have highly unusual temporal behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Network Delivery Becomes The Clock
&lt;/h2&gt;

&lt;p&gt;The file contains no frame durations. Its playback rate is whatever rate the decoder receives, processes, and paints new scans.&lt;/p&gt;

&lt;p&gt;On a local disk the changes may happen too quickly to see. On a slow connection they become visible, but congestion and buffering produce irregular timing. A CDN may deliver the whole object in a burst. A browser may wait before repainting. A proxy may transform the JPEG. The same file can look animated in one path and static in another.&lt;/p&gt;

&lt;p&gt;The Hacker News discussion pointed out one partial workaround: if the server writes one small scan, flushes it, waits, and then writes the next, server timing can dominate when the network is fast enough. That makes the demonstration more predictable, but it still does not turn JPEG into a reliable media container. Buffering anywhere in the chain can erase the cadence.&lt;/p&gt;

&lt;p&gt;This is why the technique is interesting precisely where it is impractical. It treats transport progress as presentation state. The image is not merely incomplete while downloading; incompleteness becomes its animation mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Existing Formats Already Solve Animation
&lt;/h2&gt;

&lt;p&gt;If the goal is production animation, use a format designed for it.&lt;/p&gt;

&lt;p&gt;Animated GIF, APNG, animated WebP, AVIF sequences, and video containers encode frame order and timing intentionally. Motion JPEG can send a sequence of independent JPEG images, commonly as a multipart response, which avoids progressive-scan dependencies and permits long-running streams. A &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element adds seeking, buffering behavior, audio, controls, efficient inter-frame compression, and accessibility hooks.&lt;/p&gt;

&lt;p&gt;Those alternatives miss the point of this experiment. The achievement is not a better codec. It is making an old still-image path do something its surrounding software does not expect, while staying close enough to familiar JPEG structure that mainstream decoders play along.&lt;/p&gt;

&lt;p&gt;The related examples are a long tradition: Adam7-interlaced PNG used for changing imagery, endless GIF streams, multipart camera feeds, polyglot files, and server responses whose meaning evolves as bytes arrive. Each one exposes a layer that developers usually treat as invisible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Lesson Is About Specifications
&lt;/h2&gt;

&lt;p&gt;Software rarely implements only the happy-path story we tell about a format. It implements a grammar, state transitions, resource limits, and years of compatibility behavior.&lt;/p&gt;

&lt;p&gt;Progressive JPEG was designed so partial data could be useful. That required decoders to preserve state between scans, understand spectral ranges, accept successive refinements, and repaint an image before the end marker arrived. Once those capabilities exist, replacing earlier data is not a huge conceptual leap. It is merely an unfashionable scan plan.&lt;/p&gt;

&lt;p&gt;That makes regressive JPEGs valuable beyond the joke. They are a small, visual example of several durable engineering ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Incremental parsers expose states that complete-file parsers hide.&lt;/li&gt;
&lt;li&gt;Tolerant parsers can turn nonconforming input into surprising behavior.&lt;/li&gt;
&lt;li&gt;Resource ceilings are part of interoperability, even when the standard does not prescribe them.&lt;/li&gt;
&lt;li&gt;Streaming behavior depends on the entire delivery path, not just file bytes.&lt;/li&gt;
&lt;li&gt;“Supported” means more than “eventually decodes to the correct final image.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most progressive JPEGs still do the sensible thing: reveal a hazy photograph and refine it. One carefully assembled file can instead show that the first picture was only provisional. The browser was never promised a still moment. It was promised a sequence of scans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://maurycyz.com/projects/bad_jpeg/" rel="noopener noreferrer"&gt;Maurycy’s original Regressive JPEGs experiment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=48954851" rel="noopener noreferrer"&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/Graphics/JPEG/" rel="noopener noreferrer"&gt;W3C overview of JPEG and progressive delivery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/Graphics/JPEG/itu-t81.pdf" rel="noopener noreferrer"&gt;ITU-T T.81 / ISO/IEC 10918-1 JPEG specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/learn/images/jpeg/" rel="noopener noreferrer"&gt;web.dev guide to baseline and progressive JPEG rendering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/libjpeg-turbo/libjpeg-turbo" rel="noopener noreferrer"&gt;libjpeg-turbo project and codec documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/libjpeg-turbo/libjpeg-turbo/blob/main/ChangeLog.md" rel="noopener noreferrer"&gt;libjpeg-turbo scan-limit history&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>The Human Attention Bottleneck in Agentic Software Development</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/the-human-attention-bottleneck-in-agentic-software-development-30kg</link>
      <guid>https://dev.to/0xgosu/the-human-attention-bottleneck-in-agentic-software-development-30kg</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhuzmsald6ci1fm6tsy9u.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhuzmsald6ci1fm6tsy9u.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Software development used to make its bottleneck obvious. A developer had to understand a problem, write the code, run it, find the mistake, and try again. The work could be slow, but the person doing it moved through one continuous feedback loop. Effort and understanding grew together.&lt;/p&gt;

&lt;p&gt;Coding agents break that loop into two very unequal halves.&lt;/p&gt;

&lt;p&gt;Generation becomes cheap. A prompt can start a refactor, a test suite, a migration, and a documentation update in parallel. Evaluation remains expensive. Someone still has to decide whether the output matches the real requirement, fits the architecture, handles the dangerous edge cases, and deserves to enter production.&lt;/p&gt;

&lt;p&gt;That someone is now surrounded by more work than they could ever have created by hand.&lt;/p&gt;

&lt;p&gt;This is the hidden cost of agentic development: the machine scales the supply of plausible changes faster than it scales the human capacity to understand them. Teams may ship more while their most experienced engineers spend less time designing and more time supervising an endless queue of almost-right work.&lt;/p&gt;

&lt;p&gt;The problem is not that AI coding tools are useless. They are useful enough to change the shape of the job. The problem is treating human attention as an unlimited compatibility layer between abundant generation and reliable software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Work Is No Longer the Hard Part
&lt;/h2&gt;

&lt;p&gt;Traditional development contains natural friction. Writing a feature takes long enough that a developer must choose what deserves attention. A difficult implementation forces the author to build a mental model. Tests, compiler errors, and debugging provide small, frequent signals of progress.&lt;/p&gt;

&lt;p&gt;An agent removes much of that friction. It can explore an unfamiliar repository, draft a plan, edit many files, and run checks before a person would have finished locating the relevant code. That is a genuine improvement, especially for repetitive changes, unfamiliar syntax, scaffolding, and well-specified maintenance work.&lt;/p&gt;

&lt;p&gt;It also creates an asymmetry. One developer can launch five tasks, but cannot carefully finish five tasks at once. Each session may be independent to the model, while all five share the same reviewer, product context, and production risk.&lt;/p&gt;

&lt;p&gt;The result is a new queue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Agents produce changes in parallel.&lt;/li&gt;
&lt;li&gt;Each change arrives with a polished explanation and mostly passing checks.&lt;/li&gt;
&lt;li&gt;The human reconstructs the intent, inspects the diff, tests assumptions, and finds what automation missed.&lt;/li&gt;
&lt;li&gt;Corrections trigger another generation cycle and another review.&lt;/li&gt;
&lt;li&gt;Meanwhile, completed work from the other sessions keeps arriving.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Throughput at the beginning of the pipeline rises dramatically. The end of the pipeline is still one brain making sequential decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Supervision Is More Tiring Than It Looks
&lt;/h2&gt;

&lt;p&gt;Reviewing generated code is not passive. It demands a different and often harsher form of concentration than writing the same code.&lt;/p&gt;

&lt;p&gt;When you write a function, you know why each branch exists because you made the decisions in order. When an agent writes it, you receive the decisions all at once. You must reverse-engineer the implementation, compare it with an intention that may exist only in your head, and remain alert for code that is locally convincing but globally wrong.&lt;/p&gt;

&lt;p&gt;That last category is particularly expensive. Modern models rarely fail by producing obvious nonsense. They are more likely to use a real API in the wrong layer, invent a repository convention that sounds reasonable, satisfy visible tests while missing the user workflow, or broaden a change beyond its intended boundary. Plausibility increases review cost because the reviewer cannot safely skim.&lt;/p&gt;

&lt;p&gt;Context switching makes the load worse. Supervising several agents means repeatedly swapping among different problem spaces. A database migration, authentication fix, frontend state bug, and deployment change may all be progressing at once. Every switch requires the human to reload constraints that the agent has held in its own context window.&lt;/p&gt;

&lt;p&gt;The machines wait without discomfort. The developer experiences the queue as unfinished mental work.&lt;/p&gt;

&lt;p&gt;This helps explain why agent-assisted days can feel productive and exhausting at the same time. More artifacts are created, but the human spends the day directing, checking, rejecting, and reloading context. The familiar reward of solving a problem is replaced by vigilance.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Output Can Hide Less Progress
&lt;/h2&gt;

&lt;p&gt;Counting generated output makes the new workflow look spectacular. More lines change. More pull requests open. More tasks move into review. Those metrics measure activity near the cheap end of the process.&lt;/p&gt;

&lt;p&gt;They say little about whether the system became easier to operate, whether customers received a correct improvement, or whether maintainers understand what was merged.&lt;/p&gt;

&lt;p&gt;Research is beginning to expose that distinction. An eight-month UC Berkeley study at a technology company found that generative AI expanded the scope and pace of work. Employees took on tasks they previously would not have attempted, filled natural pauses with prompts, and extended work into more hours of the day. The tool did not simply save time; it encouraged people to spend the saved time doing still more work.&lt;/p&gt;

&lt;p&gt;Software maintenance shows a similar downstream effect. A study of open-source projects following GitHub Copilot adoption found more output from peripheral contributors, but also more rework. Core developers reviewed more code while their own original-code productivity declined. The exact numbers belong to that study and should not be generalized to every team, but the mechanism is familiar: inexpensive production transfers cost to the people responsible for quality.&lt;/p&gt;

&lt;p&gt;A systematic review of research on LLM assistants reaches a broader conclusion. Faster development and lower task-starting overhead are real benefits, yet the literature also reports cognitive offloading, flow disruption, inconsistent quality, and reduced collaboration. Productivity cannot be reduced to how quickly code appears.&lt;/p&gt;

&lt;p&gt;The useful unit is not generated code. It is trusted, understood, maintainable change.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reward Loop Has Changed
&lt;/h2&gt;

&lt;p&gt;Programming has always included frustration, but it also contains many small rewards. A confusing subsystem becomes clear. A failing test turns green because the developer understood the cause. A clean abstraction replaces several special cases. A colleague learns something during review.&lt;/p&gt;

&lt;p&gt;Agentic workflows can remove the mechanical work and accidentally remove those rewards with it. The developer may specify the destination, watch the machine travel there, and then inspect the result for hazards. The task completes, but the feeling of authorship is weaker and the burden of responsibility remains.&lt;/p&gt;

&lt;p&gt;This is not universal. Some people care primarily about the finished product and find enormous satisfaction in turning ideas into working software faster. Others enjoy designing the system that lets agents operate safely. The important point is that motivation has moved, not disappeared automatically.&lt;/p&gt;

&lt;p&gt;Teams should notice where the new rewards come from. If engineers no longer gain satisfaction from implementation, they need ownership of outcomes that still feel meaningful: making a user successful, simplifying an architecture, improving a verification system, teaching a teammate, or eliminating a recurring operational problem.&lt;/p&gt;

&lt;p&gt;Without that replacement, organizations can increase delivery volume while quietly making the work less sustainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat Attention as a Capacity Constraint
&lt;/h2&gt;

&lt;p&gt;The first practical change is to stop measuring agent capacity independently of review capacity.&lt;/p&gt;

&lt;p&gt;If one engineer can responsibly validate two substantial changes in a day, generating ten does not create five times the throughput. It creates eight queued liabilities. Work in progress should be limited at the point where judgment is required, not at the point where prompts are cheap.&lt;/p&gt;

&lt;p&gt;A sustainable workflow uses several constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep the blast radius small
&lt;/h3&gt;

&lt;p&gt;Give an agent one coherent outcome with explicit boundaries. Small diffs are easier to understand, easier to test, and easier to discard. A task that mixes behavior changes, cleanup, dependency upgrades, and formatting forces the reviewer to separate several risk profiles at once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make verification part of the assignment
&lt;/h3&gt;

&lt;p&gt;The agent should not merely produce code. It should identify relevant checks, run them, inspect failures, and explain what remains unverified. Automated tests do not replace review, but they reduce the amount of state a reviewer must simulate mentally.&lt;/p&gt;

&lt;p&gt;Verification should include the user-visible path when possible. A test suite can prove that the implementation satisfies its assertions while missing that the wrong thing was built.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separate generation from judgment
&lt;/h3&gt;

&lt;p&gt;Do not ask the same context that produced a plan to be its only critic. Use a fresh review pass, a second model, deterministic tooling, or a human who did not steer the implementation. Independence does not guarantee correctness, but it reduces the chance that one mistaken assumption flows through planning, coding, and approval unchallenged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preserve human-only work
&lt;/h3&gt;

&lt;p&gt;Some work is worth doing manually even when an agent could attempt it. Writing a tricky algorithm, debugging an unfamiliar failure, or pairing on a design may be how an engineer develops the judgment that later makes supervision effective.&lt;/p&gt;

&lt;p&gt;Manual work is not waste merely because automation exists. It can be training, calibration, exploration, or simply the part of the craft that keeps someone engaged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schedule recovery, not just execution
&lt;/h3&gt;

&lt;p&gt;Agents make it tempting to fill lunch, evenings, and every short gap with another prompt. That turns formerly idle moments into background work and keeps several unresolved tasks active in memory.&lt;/p&gt;

&lt;p&gt;Use explicit stopping points. Close sessions that are not worth finishing. Batch reviews instead of reacting to every completion. End the day with a written state that allows both the human and the machine to resume later. Recovery is part of the system’s reliability budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encode Judgment Without Removing It
&lt;/h2&gt;

&lt;p&gt;Experienced engineers repeat many of the same comments: use the existing abstraction, keep authorization at this boundary, do not swallow this error, avoid introducing another source of truth. Agent instructions, repository guides, linters, architectural tests, and reusable checklists can turn those repeated decisions into durable constraints.&lt;/p&gt;

&lt;p&gt;That is a good use of automation. It moves stable knowledge earlier in the process so reviewers can focus on the change-specific questions.&lt;/p&gt;

&lt;p&gt;But not all judgment can be encoded. Architecture involves trade-offs. Product requirements contain ambiguity. Taste depends on context. A rule file can tell an agent what the team usually does; it cannot decide when the current problem justifies an exception.&lt;/p&gt;

&lt;p&gt;The goal is not to automate the reviewer out of existence. It is to reserve human attention for decisions that actually require a human, instead of spending it on conventions a machine could have checked before opening a pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design the Team, Not Only the Prompt
&lt;/h2&gt;

&lt;p&gt;AI assistance can become isolating because a developer can ask a model questions that once started a conversation with a colleague. That is convenient, but it removes opportunities for shared context and informal teaching.&lt;/p&gt;

&lt;p&gt;Teams should deliberately restore those connections. Review difficult agent-produced changes together. Hold short design conversations before parallel work begins. Share failed prompts and discarded approaches, not only successful demos. Rotate who operates and who reviews so knowledge does not concentrate in one exhausted gatekeeper.&lt;/p&gt;

&lt;p&gt;This also protects junior engineers. If entry-level implementation is delegated while senior engineers retain only architecture and review, the organization may remove the path by which people learn to become senior. Learning requires making decisions, seeing consequences, and receiving feedback from other humans. A generated diff followed by a silent approval is a weak substitute.&lt;/p&gt;

&lt;p&gt;The team must decide which tasks are delivery and which tasks are development of capability. Both matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Better Definition of Productivity
&lt;/h2&gt;

&lt;p&gt;Agentic software development needs a wider scorecard. Useful questions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How long does a change take from request to trusted production behavior?&lt;/li&gt;
&lt;li&gt;How much review and rework does it create for other people?&lt;/li&gt;
&lt;li&gt;Can the team explain and operate the resulting system?&lt;/li&gt;
&lt;li&gt;Did the change improve or weaken future development speed?&lt;/li&gt;
&lt;li&gt;Are engineers learning, collaborating, and recovering adequately?&lt;/li&gt;
&lt;li&gt;How many generated tasks were abandoned after consuming review attention?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions make the human cost visible. They also prevent a fast generator from receiving credit for work that merely moved downstream.&lt;/p&gt;

&lt;p&gt;AI coding agents are not ordinary productivity tools. They are capacity multipliers attached to a pipeline whose scarcest resource is judgment. Used carefully, they can remove drudgery, accelerate exploration, and let a small team attempt valuable work that previously stayed on the backlog. Used without limits, they turn senior engineers into overloaded schedulers and quality gates.&lt;/p&gt;

&lt;p&gt;The durable advantage will not come from running the most agents. It will come from building a system in which generated work arrives at a rate humans can understand, verify, and care about.&lt;/p&gt;

&lt;p&gt;The code can now write itself surprisingly often. The responsibility cannot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pydantic.dev/articles/the-human-in-the-loop-is-tired" rel="noopener noreferrer"&gt;The Human-in-the-Loop is Tired&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=48942000" rel="noopener noreferrer"&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.universityofcalifornia.edu/news/ai-promised-free-workers-time-uc-berkeley-haas-researchers-found-opposite" rel="noopener noreferrer"&gt;AI promised to free up workers’ time. UC Berkeley Haas researchers found the opposite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2510.10165" rel="noopener noreferrer"&gt;AI-assisted Programming May Decrease the Productivity of Experienced Developers by Increasing Maintenance Burden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://arxiv.org/abs/2507.03156" rel="noopener noreferrer"&gt;The Impact of LLM-Assistants on Software Developer Productivity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>The Real Computers Behind Jurassic Park's UNIX System</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Thu, 16 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/the-real-computers-behind-jurassic-parks-unix-system-318k</link>
      <guid>https://dev.to/0xgosu/the-real-computers-behind-jurassic-parks-unix-system-318k</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fft3qappgb5cqp8l56x8q.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fft3qappgb5cqp8l56x8q.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The computers in &lt;em&gt;Jurassic Park&lt;/em&gt; are not generic boxes decorated by a prop department. They are a remarkably complete snapshot of elite computing in the early 1990s.&lt;/p&gt;

&lt;p&gt;Look past the dinosaurs and the film becomes a tour through Apple laptops, Macintosh development tools, Silicon Graphics workstations, removable storage arrays, an unreleased wireless communicator, and one of the most recognizable supercomputers ever built. Even the famously theatrical three-dimensional file browser was real software.&lt;/p&gt;

&lt;p&gt;That authenticity matters because the computers are not background furniture. The park exists only because its operators believe a small staff can control a living ecosystem through software. When that assumption fails, the interfaces, machines, and operational shortcuts become part of the plot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Computer Is Miles From The Park
&lt;/h2&gt;

&lt;p&gt;The first machine appears before anyone reaches Isla Nublar. In the mobile trailer at Alan Grant and Ellie Sattler’s dig site sits an Apple PowerBook 100.&lt;/p&gt;

&lt;p&gt;Introduced in 1991, the PowerBook 100 used a 16 MHz Motorola 68000 processor, shipped with 2 MB of memory, and could be expanded to 8 MB. Its monochrome screen reached 640 by 400 pixels, and its internal SCSI hard drive held either 20 or 40 MB. Apple lists its original system software as System 7.0.1.&lt;/p&gt;

&lt;p&gt;Those numbers sound tiny now, but the machine established a laptop arrangement that still feels familiar: a keyboard pushed toward the display with a pointing device and palm rests in front. At 5.1 pounds, it was also the smallest and lightest member of Apple’s first PowerBook family.&lt;/p&gt;

&lt;p&gt;It is an understated opening. The film begins with a plausible field computer rather than a glowing fictional terminal, then steadily raises the hardware budget as the characters approach the park.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Control Room Built From Working Equipment
&lt;/h2&gt;

&lt;p&gt;The main control room is organized around two very different desks.&lt;/p&gt;

&lt;p&gt;Dennis Nedry’s station is a heap of monitors, computers, removable drives, disks, and a handheld device. Ray Arnold’s station is cleaner and more deliberate, with fewer computers, a bank of storage, and a dedicated surveillance display. Behind both operators stand black cabinets covered in blinking red lights, while a wall-sized display turns the room into a mission-control set.&lt;/p&gt;

&lt;p&gt;The production did not achieve that look with empty beige shells alone. A contemporary Silicon Graphics announcement said the company supplied four Indigo systems, seven Indigo Elan workstations, two IRIS 4D/440 VGXT systems, and four IRIS Crimson workstations, with a combined value near $1 million. Apple and other vendors supplied still more hardware.&lt;/p&gt;

&lt;p&gt;There was also a second computer room just off the set. A small graphics team spent months preparing animations, then responded to radio cues by routing the correct material to the monitors visible to the camera. Some displays ran genuine interactive tools; others showed carefully timed playback. The result was a working visual environment even when the actors were not directly operating every screen.&lt;/p&gt;

&lt;p&gt;That distinction explains why the control room has aged better than most fictional interfaces. The graphics were staged, but they were staged with the products, operating systems, and constraints of the period.&lt;/p&gt;

&lt;h2&gt;
  
  
  Silicon Graphics Put 3D On The Desk
&lt;/h2&gt;

&lt;p&gt;Ray Arnold’s workstation is an SGI R4000 Indigo. It appears only briefly, but it represents exactly the class of machine that made the room possible: a UNIX workstation built for engineers, scientists, and graphics professionals who needed interactive visualization.&lt;/p&gt;

&lt;p&gt;Nedry has the more imposing SGI IRIS Crimson. The red tower sits on the floor because it is too large for the desk. Released in 1992, Crimson systems paired MIPS R4000 or R4400 processors with a range of graphics subsystems. Configurations could reach 256 MB of memory and use high-end graphics hardware such as RealityEngine or VGXT.&lt;/p&gt;

&lt;p&gt;In a room full of computers, the Crimson is the machine best suited to the film’s real-time 3D imagery. One monitor spends much of the movie showing a rendered chess set. Other displays show a hurricane model and system diagnostics. These were not consumer effects pasted onto ordinary PCs; SGI sold expensive systems specifically because they could manipulate complex graphics interactively.&lt;/p&gt;

&lt;p&gt;The connection went beyond on-screen product placement. Industrial Light &amp;amp; Magic also used Silicon Graphics systems in the production pipeline that created the film’s digital dinosaurs. In 1993, the same computing culture was both depicting Jurassic Park and helping to build it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Storage Towers Tell Their Own Story
&lt;/h2&gt;

&lt;p&gt;The small black and beige boxes stacked beside the operators are PLI Mini Array external drives. Nedry has five; Arnold has two.&lt;/p&gt;

&lt;p&gt;An advertisement from the period offered capacities up to 1 GB for thousands of dollars per unit. Seven top-capacity arrays would therefore have given the control room roughly 7 GB of external storage. A modern phone can treat that amount as disposable, but a high-end personal computer in 1993 might have shipped with a hard drive measured in the low hundreds of megabytes.&lt;/p&gt;

&lt;p&gt;The stacks also reveal the practical mechanics of old workstations. Before cheap network storage and silent solid-state drives, adding capacity meant physical enclosures, SCSI cables, power supplies, fans, and a conspicuous amount of desk space.&lt;/p&gt;

&lt;p&gt;The film even contains a storage continuity error. The large stack beside Nedry faces one direction in early shots and turns toward the operator after Arnold takes over the desk. It is the sort of mistake that becomes visible only when the props are real enough to have ports, lights, and a correct orientation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Wireless Device From The Future
&lt;/h2&gt;

&lt;p&gt;Near Nedry’s elbow is a Motorola Envoy, a foldable personal communicator with an antenna. The production is surprising because principal photography took place in 1992, while the Envoy did not become nationally available until February 1995.&lt;/p&gt;

&lt;p&gt;The explanation surfaced through the Hacker News discussion. According to a sourced account shared there, frogdesign co-founder Hartmut Esslinger met Steven Spielberg on a flight and showed him the device. The object used in the film was an early mockup.&lt;/p&gt;

&lt;p&gt;The eventual production model was ambitious for its day. It combined a 1 MB RAM handheld computer with wireless data, fax and infrared communications. The radio modem ran at 4,800 bits per second, while the infrared link could reach 38.4 kbit/s.&lt;/p&gt;

&lt;p&gt;The Envoy is easy to miss, yet it may be the most futuristic object in the room. Unlike the SGI towers, which were powerful but established products, this was a preview of mobile messaging hardware that ordinary customers could not yet buy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Red Lights Belong To A Connection Machine
&lt;/h2&gt;

&lt;p&gt;The control room’s visual anchor is the wall of black cabinets filled with red LEDs. These are Thinking Machines CM-5 Connection Machine cabinets, chosen in place of the Cray supercomputer described in Michael Crichton’s novel.&lt;/p&gt;

&lt;p&gt;The CM-5 was a massively parallel system. A processing node combined a SPARC control processor with memory and, in accelerated configurations, four vector units. Nodes communicated through dedicated data and control networks, allowing installations to grow into serious scientific machines. MIT described its 128-processor CM-5, acquired in 1993, as the seventeenth most powerful computer in the world at the time.&lt;/p&gt;

&lt;p&gt;The lights were a status display only in the broadest theatrical sense. Their eye-catching patterns were not a readable visualization of the program running inside. They were designed to blink, and they made a machine built around parallelism immediately legible on camera.&lt;/p&gt;

&lt;p&gt;One recollection in the Hacker News thread supplies the best story about how the CM-5 got the part. The filmmakers reportedly approached Cray first because the novel named a Cray. When the company declined to provide a machine, Thinking Machines agreed. The production later screened the finished film for Thinking Machines employees in Cambridge, where the machine’s appearance and the line about recognizing UNIX received the biggest reactions.&lt;/p&gt;

&lt;p&gt;Whether or not every visible cabinet contained a complete working system, the choice was perfect. Jurassic Park’s central premise is an enormously complex operation concentrated into one control room. A machine made by connecting many processors together looks like the physical embodiment of that ambition.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Monitors Were A Production Problem
&lt;/h2&gt;

&lt;p&gt;Large CRTs dominate both desks. Several are 20-inch SuperMatch displays, premium Trinitron monitors that cost thousands of dollars. Ray’s SGI display appears to be a rebranded 19-inch Mitsubishi unit paired with SGI’s granite-colored keyboard.&lt;/p&gt;

&lt;p&gt;That keyboard has an elegant piece of industrial design: a mini-DIN connector on each side. The workstation cable can enter from whichever side is convenient, and the mouse plugs into the remaining port. A tiny detail like that says more about a purpose-built workstation than another screen full of fake hexadecimal ever could.&lt;/p&gt;

&lt;p&gt;Putting real CRTs on film introduced a technical problem. A camera and a monitor do not necessarily expose frames at the same rate, so an unsynchronized display produces rolling dark bands and flicker. The production used specialized synchronization equipment and staff to align the screens with the film camera. A commenter whose uncle worked on the movie recalled the wonderfully specific credit “24 Frame Computer Sync Engineer.”&lt;/p&gt;

&lt;p&gt;The clean screens in the finished movie were therefore not automatic evidence of digital compositing. They were the outcome of careful timing across a room full of physical displays.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Macs Handle Video, Code, And Sabotage
&lt;/h2&gt;

&lt;p&gt;Nedry’s desk contains two Macintosh Quadra 700 computers; Arnold has another. Introduced in 1991, the Quadra 700 used a 25 MHz Motorola 68040 processor and supported substantially more memory than a typical home computer. Its compact vertical case also left more room for the enormous displays and storage arrays.&lt;/p&gt;

&lt;p&gt;The Macs do several jobs in the film. One plays &lt;em&gt;Jaws&lt;/em&gt; in a window when Nedry is introduced. Another appears to carry a video call with his contact at the dock, but the visible QuickTime controls reveal that it is a prerecorded one-minute clip. The cursor is still sitting on the play control. In 1992, faking a desktop video conference with QuickTime was much easier than building the live connection implied by the scene.&lt;/p&gt;

&lt;p&gt;The sabotage interface also appears on a Mac. Nedry’s “white rabbit” operation disables the park’s systems, suppresses the audit trail, and leaves an animated version of his face repeating the magic-word taunt. The novel names the object &lt;code&gt;whte_rbt.obj&lt;/code&gt;; the movie turns it into a memorable graphical lockout.&lt;/p&gt;

&lt;p&gt;Elsewhere, the screens show source code from Macintosh Programmer’s Workshop, Apple’s development environment. Viewers in the HN thread identified Pascal example code for a HyperCard external command and scripts associated with Apple’s Projector source-control tooling. The text looks convincing because it is real development material, even if it was not the actual source of the fictional park-control system.&lt;/p&gt;

&lt;p&gt;One final prop completes the workstation: a copy of Anthony Meadow’s &lt;em&gt;System 7 Revealed&lt;/em&gt; sits on Nedry’s shelf. The programmers who built this room apparently needed documentation too.&lt;/p&gt;

&lt;h2&gt;
  
  
  “It’s A UNIX System” Was Basically True
&lt;/h2&gt;

&lt;p&gt;The most famous computer scene arrives when Lex Murphy sits at the SGI and recognizes the interface. The program is &lt;code&gt;fsn&lt;/code&gt;, the File System Navigator included with IRIX, Silicon Graphics’ UNIX operating system.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fsn&lt;/code&gt; represents folders and files as a navigable three-dimensional landscape. Lex opens &lt;code&gt;/usr&lt;/code&gt;, moves through the visualization, and finds the controls needed to restore the door locks. It is not how most administrators would choose to repair a failed production system, but it was not a Hollywood invention. SGI shipped the experimental browser as a demonstration of what its graphics hardware could render interactively.&lt;/p&gt;

&lt;p&gt;The workstation also runs &lt;code&gt;gr_osview&lt;/code&gt;, an IRIX performance monitor that displays processor, system, interrupt, and graphics activity. In at least one shot, its meters appear to react naturally to keyboard input. Small utilities like this make the scene convincing: a real machine is rarely occupied by one perfect full-screen application. It has terminals, monitors, diagnostics, and visual clutter.&lt;/p&gt;

&lt;p&gt;The park-wide interface is called Nedryland. It reports systems as they come back online after the reboot, using custom graphics prepared by Michael Backes and his team. Fans have since recreated both the IRIX and classic Mac environments in browsers, turning the fictional operations console into working software of its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Computers Explain The Failure
&lt;/h2&gt;

&lt;p&gt;Jurassic Park’s hardware is often remembered as a collection of delightful vintage props. It also supports the film’s argument.&lt;/p&gt;

&lt;p&gt;John Hammond says he spared no expense, and the control room proves it. The park has world-class graphics workstations, a massively parallel supercomputer, large professional displays, stacks of external storage, custom software, and even a prototype communicator. The machines are expensive, capable, and authentic.&lt;/p&gt;

&lt;p&gt;The failure is organizational. Too much knowledge and authority sit with one underpaid engineer. Critical operations depend on custom interfaces and undocumented behavior. The system can run the park with minimal staff, but that efficiency removes the people who might understand, challenge, or recover it. Buying better hardware does not repair the concentration of operational risk.&lt;/p&gt;

&lt;p&gt;That is why these machines remain more than nostalgia. The details make the fictional system believable, and the believable system makes the disaster legible. Jurassic Park did not fail because its computers were fake. It failed because its real-looking computers were asked to make an unsafe organization appear automated, controlled, and complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fabiensanglard.net/jurrasic_park_computers/index.html" rel="noopener noreferrer"&gt;Fabien Sanglard’s detailed computer inventory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=48915709" rel="noopener noreferrer"&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.therpf.com/forums/threads/jurassic-park-tablet-device-on-nedrys-desk.169883/" rel="noopener noreferrer"&gt;Account of the Envoy design mockup reaching the film&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.apple.com/en-ca/112153" rel="noopener noreferrer"&gt;Apple PowerBook 100 technical specifications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://archive.irixnet.org/sgistuff/funstuff/hollywood/jpark.html" rel="noopener noreferrer"&gt;Archived Silicon Graphics Jurassic Park feature and press release&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bitsavers.computerhistory.org/pdf/thinkingMachines/CM5/nov06/ConnectionMachineCM-5TechnicalSummary1991.pdf" rel="noopener noreferrer"&gt;Thinking Machines CM-5 technical summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.mit.edu/1997/lcs-0813" rel="noopener noreferrer"&gt;MIT’s account of retiring its CM-5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.computerhistory.org/brochures/t-z/thinking-machines-corporation-tmc/" rel="noopener noreferrer"&gt;Computer History Museum: Thinking Machines Corporation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jurassicsystems.com/about" rel="noopener noreferrer"&gt;Jurassic Systems browser recreation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>Build and Ship Apple Apps from the Command Line</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Tue, 14 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/build-and-ship-apple-apps-from-the-command-line-15ed</link>
      <guid>https://dev.to/0xgosu/build-and-ship-apple-apps-from-the-command-line-15ed</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6z0lf5dhnbxaf0b70iwa.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6z0lf5dhnbxaf0b70iwa.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apple development is often treated as inseparable from the Xcode interface. Create a project in a window, click a scheme, press a build button, open Organizer, choose an archive, and work through a signing wizard. That is the familiar path, but it is not the only path.&lt;/p&gt;

&lt;p&gt;Almost every important action underneath that interface already has a command-line form. Xcode still needs to be installed because it supplies the SDKs, compilers, simulators, device services, and distribution tools. After a small amount of account and certificate setup, however, the daily loop can live in a terminal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;define the project in a text file;&lt;/li&gt;
&lt;li&gt;regenerate the Xcode project when its structure changes;&lt;/li&gt;
&lt;li&gt;test and compile with &lt;code&gt;swift&lt;/code&gt; and &lt;code&gt;xcodebuild&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;archive, sign, and export a macOS app;&lt;/li&gt;
&lt;li&gt;submit it to Apple’s notary service and staple the returned ticket;&lt;/li&gt;
&lt;li&gt;install an iOS build on a connected device with &lt;code&gt;devicectl&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is useful for humans who prefer reproducible scripts. It is even more useful for coding agents, which are far more reliable when a repository exposes explicit commands instead of an undocumented sequence of clicks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Important Distinction: Xcode the App vs. Xcode the Toolchain
&lt;/h2&gt;

&lt;p&gt;There are two products hiding under one name.&lt;/p&gt;

&lt;p&gt;The first is the Xcode application: the editor, inspectors, project settings, visual debuggers, simulators, Organizer, and account screens. The second is the developer directory inside &lt;code&gt;Xcode.app&lt;/code&gt;, which contains the build system and platform tools.&lt;/p&gt;

&lt;p&gt;A complete Apple toolchain includes more than the standalone Command Line Tools package. The smaller package provides basics such as Clang and Git, but it does not contain the complete iOS SDK or every utility needed for device deployment and notarization. For native iPhone development and a full Mac distribution pipeline, install Xcode and select its developer directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcode-select &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;xcode-select &lt;span class="nt"&gt;--switch&lt;/span&gt; /Applications/Xcode.app/Contents/Developer
&lt;span class="nb"&gt;sudo &lt;/span&gt;xcodebuild &lt;span class="nt"&gt;-license&lt;/span&gt; accept
&lt;span class="nb"&gt;sudo &lt;/span&gt;xcodebuild &lt;span class="nt"&gt;-runFirstLaunch&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When Xcode uses its default name and location, the first command should eventually print &lt;code&gt;/Applications/Xcode.app/Contents/Developer&lt;/code&gt;. The second command selects that developer directory; the last two accept the license and install required components. Once that foundation is in place, &lt;code&gt;xcodebuild&lt;/code&gt;, &lt;code&gt;xcrun&lt;/code&gt;, &lt;code&gt;notarytool&lt;/code&gt;, &lt;code&gt;stapler&lt;/code&gt;, and &lt;code&gt;devicectl&lt;/code&gt; can run without launching the editor.&lt;/p&gt;

&lt;p&gt;Calling this a “no-Xcode” workflow would therefore be misleading. It is a no-Xcode-GUI workflow after initial setup. You still depend on Apple’s toolchain and must update it when new SDKs or platform requirements arrive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the Project Definition in Git
&lt;/h2&gt;

&lt;p&gt;An &lt;code&gt;.xcodeproj&lt;/code&gt; looks like a file in Finder, but it is a directory containing a large project description. Xcode modifies that description as files, targets, build settings, and schemes change. The format works, but it is not pleasant to edit by hand and can produce noisy merge conflicts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/yonaskolb/XcodeGen" rel="noopener noreferrer"&gt;XcodeGen&lt;/a&gt; moves the source of truth into a YAML or JSON specification. A &lt;code&gt;project.yml&lt;/code&gt; can declare targets, platforms, source directories, dependencies, build settings, schemes, entitlements, and configurations. Running one command recreates the generated project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;xcodegen
xcodegen generate

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That changes the maintenance model. Instead of asking a person or agent to manipulate an opaque project bundle, the repository keeps a readable specification and treats the &lt;code&gt;.xcodeproj&lt;/code&gt; as generated output. The project can be regenerated on every build, omitted from version control, or checked for drift in continuous integration.&lt;/p&gt;

&lt;p&gt;XcodeGen is a choice, not a law. Modern Xcode file-system-synchronized groups reduce some of the file-reference pain, while Tuist, Swift Package Manager, and Fastlane solve overlapping parts of the problem. Complex projects with extensions, multiple platforms, custom build phases, or legacy settings may prefer another tool or keep the project file committed. The principle is more important than the specific generator: make project structure deterministic and reviewable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate the Fast Loop from the Release Loop
&lt;/h2&gt;

&lt;p&gt;One command should not try to serve every purpose. A fast local check has different requirements from software that will be handed to another user.&lt;/p&gt;

&lt;p&gt;For code organized as a Swift package, the cheapest test loop may be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;swift &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A macOS target can be compiled without distribution signing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcodegen generate
xcodebuild &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-project&lt;/span&gt; Example.xcodeproj &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-scheme&lt;/span&gt; Example-macOS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-destination&lt;/span&gt; &lt;span class="s1"&gt;'platform=macOS'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;CODE_SIGNING_ALLOWED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NO &lt;span class="se"&gt;\&lt;/span&gt;
  build

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An iOS simulator build follows the same pattern with a simulator destination:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcodebuild &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-project&lt;/span&gt; Example.xcodeproj &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-scheme&lt;/span&gt; Example-iOS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-destination&lt;/span&gt; &lt;span class="s1"&gt;'generic/platform=iOS Simulator'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;CODE_SIGNING_ALLOWED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NO &lt;span class="se"&gt;\&lt;/span&gt;
  build

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands answer the quick questions: does the project generate, does the code compile, and do the unit tests pass? They avoid certificate and provisioning work that is unnecessary for a simulator or a continuous-integration sanity check.&lt;/p&gt;

&lt;p&gt;An unsigned or ad-hoc build is not a release. Gatekeeper will not treat it as a normally distributed Mac app, and capabilities whose entitlements depend on a real team identity may not work. The release loop must archive and export with the correct identity.&lt;/p&gt;

&lt;p&gt;Keeping these paths separate makes failures easier to understand. A compile failure belongs to the code or project. A later signing failure belongs to identities, profiles, entitlements, or export settings. Mixing them into one opaque command turns every problem into “Xcode failed.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Signing Starts with a Private Key
&lt;/h2&gt;

&lt;p&gt;The graphical signing screen can make code signing feel like remote Apple magic. The core mechanism is simpler: a private key in a keychain signs the product, and a certificate connects the corresponding public key to an Apple developer identity.&lt;/p&gt;

&lt;p&gt;For direct distribution of a Mac application outside the App Store, Apple documents the &lt;strong&gt;Developer ID Application&lt;/strong&gt; certificate. It is distinct from the &lt;strong&gt;Apple Development&lt;/strong&gt; certificate used for local development and device testing. Creating an identity from a certificate-signing request leaves the locally generated private key in the keychain. Moving that identity to another machine requires importing an exported identity such as a password-protected &lt;code&gt;.p12&lt;/code&gt;; importing Apple’s &lt;code&gt;.cer&lt;/code&gt; certificate by itself does not include the private key.&lt;/p&gt;

&lt;p&gt;That private key deserves the same care as any release credential. A certificate without the corresponding private key cannot sign with that identity. Back up the identity securely, limit access to the build environment, and do not place exported key material in the repository.&lt;/p&gt;

&lt;p&gt;Project-specific values such as the development team and bundle identifier prefix can live in a local configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt; &lt;span class="err"&gt;Local.xcconfig&lt;/span&gt;
&lt;span class="py"&gt;DEVELOPMENT_TEAM&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ABC1234567&lt;/span&gt;
&lt;span class="py"&gt;BUNDLE_PREFIX&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;com.example&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit a safe example, add the real &lt;code&gt;Local.xcconfig&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt;, and include it from the generated project settings. This gives each developer or build machine a clear setup point without baking personal identifiers into a reusable template.&lt;/p&gt;

&lt;p&gt;Signing secrets should remain outside Git as well. The login keychain can hold the signing key. &lt;code&gt;notarytool&lt;/code&gt; can keep its authentication profile in the keychain. A CI system can inject a temporary keychain and App Store Connect credentials at runtime. The repository needs names and commands, not raw secrets.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Mac Release Is a Pipeline, Not a Button
&lt;/h2&gt;

&lt;p&gt;For a directly distributed macOS app, a dependable release script should express each stage separately:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Regenerate the project.&lt;/li&gt;
&lt;li&gt;Archive a Release build.&lt;/li&gt;
&lt;li&gt;Export the archive using Developer ID signing.&lt;/li&gt;
&lt;li&gt;Package the signed app for notarization.&lt;/li&gt;
&lt;li&gt;Submit it to Apple’s notary service and wait for a result.&lt;/li&gt;
&lt;li&gt;Staple the notarization ticket to the app.&lt;/li&gt;
&lt;li&gt;Verify the signature, ticket, and Gatekeeper assessment.&lt;/li&gt;
&lt;li&gt;Copy the verified app to its final location or distribution package.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The archive and export stages are handled by &lt;code&gt;xcodebuild&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcodebuild &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-project&lt;/span&gt; Example.xcodeproj &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-scheme&lt;/span&gt; Example-macOS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-configuration&lt;/span&gt; Release &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-archivePath&lt;/span&gt; build/Example.xcarchive &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-allowProvisioningUpdates&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  archive

xcodebuild &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-exportArchive&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-archivePath&lt;/span&gt; build/Example.xcarchive &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-exportPath&lt;/span&gt; build/export &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-exportOptionsPlist&lt;/span&gt; ExportOptions.plist &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-allowProvisioningUpdates&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The export options identify the distribution method, team, and signing style. Keep that file in version control when it contains no secret data. Build it from a template when environments need different values.&lt;/p&gt;

&lt;p&gt;The script should use strict shell behavior such as &lt;code&gt;set -euo pipefail&lt;/code&gt;, validate prerequisites before a long archive, and fail at the first broken stage. It should also remove or isolate old build output so yesterday’s &lt;code&gt;.app&lt;/code&gt; cannot be mistaken for today’s successful export.&lt;/p&gt;

&lt;p&gt;This is where a short custom script can be better than a long checklist. The sequence becomes executable documentation. A developer, CI runner, or coding agent invokes the same entry point and receives the same checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notarization and Signing Solve Different Problems
&lt;/h2&gt;

&lt;p&gt;Signing establishes who produced an app and whether its contents changed after signing. Notarization sends the signed software to an automated Apple service that scans for malicious content and code-signing problems. On success, Apple issues a ticket. Stapling attaches that ticket to the deliverable so Gatekeeper can validate it even when it cannot retrieve the ticket online.&lt;/p&gt;

&lt;p&gt;Apple’s current command-line path uses &lt;code&gt;notarytool&lt;/code&gt;; the older &lt;code&gt;altool&lt;/code&gt; upload flow is no longer accepted. Store credentials once in a named keychain profile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcrun notarytool store-credentials ExampleNotary &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--apple-id&lt;/span&gt; &lt;span class="s2"&gt;"developer@example.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--team-id&lt;/span&gt; ABC1234567

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command prompts for an app-specific password. Avoid putting that password on a command line where it can leak into shell history or process listings.&lt;/p&gt;

&lt;p&gt;For the release itself, package the signed app, submit it, and staple the ticket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ditto &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="nt"&gt;--keepParent&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  build/export/Example.app &lt;span class="se"&gt;\&lt;/span&gt;
  build/Example-notarization.zip

xcrun notarytool submit &lt;span class="se"&gt;\&lt;/span&gt;
  build/Example-notarization.zip &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--keychain-profile&lt;/span&gt; ExampleNotary &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--wait&lt;/span&gt;

xcrun stapler staple build/export/Example.app

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not treat a successful submission as the final check. Validate the artifact that users will actually receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codesign &lt;span class="nt"&gt;--verify&lt;/span&gt; &lt;span class="nt"&gt;--deep&lt;/span&gt; &lt;span class="nt"&gt;--strict&lt;/span&gt; &lt;span class="nt"&gt;--verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 build/export/Example.app
xcrun stapler validate build/export/Example.app
spctl &lt;span class="nt"&gt;--assess&lt;/span&gt; &lt;span class="nt"&gt;--verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nt"&gt;--type&lt;/span&gt; execute build/export/Example.app

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apple’s notarization requirements also include a valid Developer ID signature, hardened runtime, a secure timestamp, and suitable entitlements. In particular, a shipping app should not accidentally retain the debugger-oriented &lt;code&gt;com.apple.security.get-task-allow&lt;/code&gt; entitlement. A headless pipeline does not remove these rules; it makes them visible and testable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing on a Real iPhone Without the Run Button
&lt;/h2&gt;

&lt;p&gt;iOS device deployment uses a different identity and does not use the Mac notarization service. A development build for a physical iPhone must be signed with an Apple Development identity and an appropriate provisioning profile.&lt;/p&gt;

&lt;p&gt;First archive for the device platform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcodebuild &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-project&lt;/span&gt; Example.xcodeproj &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-scheme&lt;/span&gt; Example-iOS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-destination&lt;/span&gt; &lt;span class="s1"&gt;'generic/platform=iOS'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-allowProvisioningUpdates&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-derivedDataPath&lt;/span&gt; build/ios &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-archivePath&lt;/span&gt; build/Example-iOS.xcarchive &lt;span class="se"&gt;\&lt;/span&gt;
  archive

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then list paired devices and install the built application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcrun devicectl list devices
xcrun devicectl device &lt;span class="nb"&gt;install &lt;/span&gt;app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--device&lt;/span&gt; DEVICE-UDID &lt;span class="se"&gt;\&lt;/span&gt;
  /path/to/Example.app

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a development and testing path, not an App Store release workflow. TestFlight and App Store distribution add App Store Connect records, distribution signing, metadata, review, and upload steps. Those can also be automated, often with Fastlane or an App Store Connect CLI, but they are a separate system and should not be implied by a local USB install.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give the Repository an Operator’s Manual
&lt;/h2&gt;

&lt;p&gt;Automation becomes much more valuable when the repository explains how to use it. A short &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;CLAUDE.md&lt;/code&gt;, or contributor guide should name the canonical commands and the boundaries between them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Validation&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Run &lt;span class="sb"&gt;`swift test`&lt;/span&gt; for package tests.
&lt;span class="p"&gt;-&lt;/span&gt; Run &lt;span class="sb"&gt;`xcodegen generate`&lt;/span&gt; after changing project structure.
&lt;span class="p"&gt;-&lt;/span&gt; Run &lt;span class="sb"&gt;`./scripts/build-macos.sh`&lt;/span&gt; for an unsigned compile check.
&lt;span class="p"&gt;-&lt;/span&gt; Run &lt;span class="sb"&gt;`./scripts/release-macos.sh`&lt;/span&gt; only for a signed, notarized release.

&lt;span class="gu"&gt;## Credentials&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Never commit &lt;span class="sb"&gt;`Local.xcconfig`&lt;/span&gt;, certificates, private keys, or passwords.
&lt;span class="p"&gt;-&lt;/span&gt; The release script expects the &lt;span class="sb"&gt;`ExampleNotary`&lt;/span&gt; keychain profile.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That file is not special because an agent reads it. It is useful because it captures the contract of the build system. A new teammate gets the same map. CI can invoke the same commands. Reviewers can see whether a change modifies the documented path or invents a parallel one.&lt;/p&gt;

&lt;p&gt;For agents, explicit commands reduce improvisation. Instead of asking a model to rediscover signing every session, tell it which cheap command verifies a change and which guarded command produces a release. Let the script own the sequence and let the agent respond to concrete failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the GUI Still Wins
&lt;/h2&gt;

&lt;p&gt;A terminal-first workflow should not become a purity contest. Xcode remains valuable for tasks that are naturally visual or interactive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stepping through code with the debugger;&lt;/li&gt;
&lt;li&gt;inspecting view hierarchies and performance instruments;&lt;/li&gt;
&lt;li&gt;configuring a new account or certificate when the CLI path is unclear;&lt;/li&gt;
&lt;li&gt;resolving a signing edge case by seeing Xcode’s interpretation of project settings;&lt;/li&gt;
&lt;li&gt;using previews, Interface Builder, simulators, or device logs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to forbid the application. The goal is to remove the GUI from the repeatable build and release contract.&lt;/p&gt;

&lt;p&gt;There are also legitimate objections to hand-written release scripts. Fastlane already packages mature mobile automation. Tuist may model a large project more comfortably than YAML. XcodeGen may be unnecessary for projects that benefit from synchronized groups. A complicated workspace may contain edge cases that a simple generator spec does not capture.&lt;/p&gt;

&lt;p&gt;Choose the smallest system that stays understandable. A 60-line release script can be excellent when it expresses eight stable commands. It becomes a liability when it quietly grows into a private build framework with no tests, ownership, or documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Payoff Is Reproducibility
&lt;/h2&gt;

&lt;p&gt;Avoiding Xcode windows is a convenience. The deeper improvement is that the software’s construction becomes inspectable.&lt;/p&gt;

&lt;p&gt;A button hides state: the selected scheme, active destination, signing identity, cached derived data, export choice, and account session. A command can name those inputs. A script can check them. CI can run it. An agent can repeat it. When it fails, the failing stage becomes evidence instead of a vague red badge in an organizer window.&lt;/p&gt;

&lt;p&gt;The result is a clean division of responsibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apple supplies the compiler, SDK, signing infrastructure, device service, and notary service.&lt;/li&gt;
&lt;li&gt;The project generator turns a reviewable specification into an Xcode project.&lt;/li&gt;
&lt;li&gt;Build scripts encode the fast and release paths.&lt;/li&gt;
&lt;li&gt;The keychain protects identities and credentials.&lt;/li&gt;
&lt;li&gt;Repository instructions tell humans and agents which path to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You still need judgment. You still need to test the app, protect signing keys, understand entitlements, inspect notarization failures, and decide when a generated project is appropriate. Automation does not make Apple distribution simple. It makes the complexity explicit, repeatable, and easier to operate.&lt;/p&gt;

&lt;p&gt;That is a much better foundation than teaching every new contributor—or every new coding-agent session—where to click.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://scottwillsey.com/building-and-shipping-mac-and-ios-apps-without-ever-opening-xcode/" rel="noopener noreferrer"&gt;Building and Shipping Mac and iOS Apps Without Ever Opening Xcode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=48896665" rel="noopener noreferrer"&gt;HN discussion: Building and shipping Mac and iOS apps without opening Xcode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/documentation/security/notarizing-macos-software-before-distribution" rel="noopener noreferrer"&gt;Apple: Notarizing macOS software before distribution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/help/account/certificates/create-developer-id-certificates/" rel="noopener noreferrer"&gt;Apple: Developer ID certificates&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.apple.com/documentation/security/resolving-common-notarization-issues" rel="noopener noreferrer"&gt;Apple: Resolving common notarization issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/yonaskolb/XcodeGen" rel="noopener noreferrer"&gt;XcodeGen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>PgBouncer Scaling Starts When One Core Stops Being Enough</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Sun, 12 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/pgbouncer-scaling-starts-when-one-core-stops-being-enough-9hj</link>
      <guid>https://dev.to/0xgosu/pgbouncer-scaling-starts-when-one-core-stops-being-enough-9hj</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7g2h4wx1i3bdtkcmhzjw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7g2h4wx1i3bdtkcmhzjw.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PgBouncer is usually introduced as a way to save Postgres from connection churn. Applications open fewer direct database connections, short-lived clients get pooled, and Postgres spends more time doing database work instead of process and session bookkeeping.&lt;/p&gt;

&lt;p&gt;That story is true, but it hides a second bottleneck.&lt;/p&gt;

&lt;p&gt;PgBouncer itself is single-threaded. One PgBouncer process can use one CPU core. Put it on a 16-vCPU instance and the operating system may report a large machine, but the pooler is still fundamentally one event loop doing one core’s worth of work. When concurrency rises, that single core can become the limit while most of the box sits idle.&lt;/p&gt;

&lt;p&gt;ClickHouse’s Managed Postgres team published a practical way around that ceiling: run multiple PgBouncer processes on the same host, let them all listen on the same port with &lt;code&gt;so_reuseport&lt;/code&gt;, and connect the processes with PgBouncer peering so cancellation requests still find the right session.&lt;/p&gt;

&lt;p&gt;The interesting part is not just the benchmark result, though the result is large. The interesting part is the shape of the fix. It is a reminder that “add a pooler” is not the end of the architecture. At scale, the pooler is another service with its own concurrency model, correctness traps, and capacity plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why One PgBouncer Process Leaves Hardware Idle
&lt;/h2&gt;

&lt;p&gt;Postgres connections are expensive enough that pooling is often worth adding well before the database is truly overloaded. PgBouncer accepts client connections, keeps a smaller set of server connections open to Postgres, and reuses them according to the configured pooling mode.&lt;/p&gt;

&lt;p&gt;In transaction pooling, a server connection is returned to the pool after a transaction commits. That makes PgBouncer especially effective for applications that perform many short transactions and do not need a stable backend session between transactions.&lt;/p&gt;

&lt;p&gt;But the pooler still has to accept connections, parse protocol messages, hand work to backend connections, track state, enforce limits, and move bytes. A single PgBouncer process does that work in a single thread.&lt;/p&gt;

&lt;p&gt;On small machines or low-concurrency workloads, that simplicity is part of the appeal. There is less coordination inside the process and fewer moving parts to reason about. On a larger box, the simplicity becomes a ceiling: the pooler can saturate one CPU while the instance still looks mostly empty in aggregate CPU metrics.&lt;/p&gt;

&lt;p&gt;That distinction matters operationally. If a 16-vCPU machine reports 8% or 10% CPU usage, it is easy to assume the pooler has headroom. For a single-threaded service, aggregate CPU can lie. One hot core is enough to cap throughput even when fifteen others are idle.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;so_reuseport&lt;/code&gt; Turns One Endpoint Into Many Processes
&lt;/h2&gt;

&lt;p&gt;The basic scaling move is straightforward: start a PgBouncer process per useful slice of CPU capacity, then make all of those processes bind the same address and port.&lt;/p&gt;

&lt;p&gt;Linux’s &lt;code&gt;SO_REUSEPORT&lt;/code&gt; socket option allows multiple processes to listen on the same port. The kernel distributes new incoming TCP connections across those listening sockets. From the client side, nothing changes. The application still connects to one host and one port. Behind that endpoint, different PgBouncer processes receive different client connections.&lt;/p&gt;

&lt;p&gt;That is exactly the kind of trick that fits PgBouncer well. You do not need to make PgBouncer internally multithreaded. You can scale horizontally inside one machine by running several independent single-threaded processes. Each process gets its own event loop and can land on its own core.&lt;/p&gt;

&lt;p&gt;PgBouncer’s documentation explicitly describes this pattern for a multi-core setup: enable &lt;code&gt;so_reuseport&lt;/code&gt;, run multiple instances with distinct per-process settings such as socket directories, and use peering when cancellation semantics matter.&lt;/p&gt;

&lt;p&gt;The result is simple from the outside and parallel on the inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[pgbouncer]&lt;/span&gt;
&lt;span class="py"&gt;listen_addr&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0&lt;/span&gt;
&lt;span class="py"&gt;listen_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;6432&lt;/span&gt;
&lt;span class="py"&gt;so_reuseport&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="py"&gt;peer_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a real deployment, each process also needs unique identity and local paths, and each peer must know how to reach the others. The important idea is that the port stays shared while process state stays separate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cancellation Trap
&lt;/h2&gt;

&lt;p&gt;Running a fleet of PgBouncer processes is not just a matter of launching &lt;code&gt;N&lt;/code&gt; copies and calling it done.&lt;/p&gt;

&lt;p&gt;Postgres query cancellation has an awkward property: the cancel request does not arrive on the same connection as the query being cancelled. It arrives on a new connection with a cancellation key. In a single PgBouncer process, that is manageable because the process has the state needed to match the key to the active query.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;so_reuseport&lt;/code&gt;, the kernel may route the cancellation connection to a different PgBouncer process than the one holding the client session. That second process has no local memory of the query. If nothing else is configured, the cancel request can land in the wrong place and fail to do the thing the user asked for.&lt;/p&gt;

&lt;p&gt;Peering is the fix. PgBouncer processes can be configured as peers so they can forward cancellation requests to the process that owns the session. The cancel connection can enter through any process, but the fleet cooperates to route it correctly.&lt;/p&gt;

&lt;p&gt;This is the part of the design that matters most for production. A connection pooler that is fast but loses cancellation is not transparent plumbing. It changes the behavior of the database path. Long-running queries become harder to stop, timeouts become less reliable, and operators lose an important escape hatch during incidents.&lt;/p&gt;

&lt;p&gt;Peering preserves the illusion that there is still one pooler endpoint, even though there are several processes behind it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capacity Is A Fleet Budget, Not A Process Budget
&lt;/h2&gt;

&lt;p&gt;Once PgBouncer becomes a process fleet, connection limits have to be treated as aggregate limits.&lt;/p&gt;

&lt;p&gt;If every process is given the old full &lt;code&gt;max_client_conn&lt;/code&gt; and &lt;code&gt;max_db_connections&lt;/code&gt; values, the fleet can accidentally multiply the pressure on Postgres. Sixteen processes each allowed to open the old budget is not a harmless refactor. It is a new capacity plan.&lt;/p&gt;

&lt;p&gt;ClickHouse’s setup divides the relevant budgets across the PgBouncer processes. Each process receives a fraction of the total, so the fleet as a whole remains within the intended envelope. That keeps the scale-out from turning into an oversubscription bug.&lt;/p&gt;

&lt;p&gt;This is a common failure mode in infrastructure work. A limit that was safe for one instance becomes unsafe when copied into a group. The name of the setting does not change, but the unit of planning does. The old question was “how many connections may this process allow?” The new question is “how many connections may this service endpoint allow across all workers?”&lt;/p&gt;

&lt;p&gt;The same thinking applies to observability. A single process metric is no longer enough. You want per-process visibility to catch skew, but you also want fleet-level totals to understand what clients and Postgres experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What The Benchmark Showed
&lt;/h2&gt;

&lt;p&gt;ClickHouse compared a single PgBouncer process with a 16-process fleet on identical hardware. The pooler ran on a 16-vCPU AWS &lt;code&gt;c7i.4xlarge&lt;/code&gt;; Postgres and the load generator were on separate machines. The workload used &lt;code&gt;pgbench&lt;/code&gt; in select-only mode with transaction pooling, and client concurrency was ramped from 8 to 256.&lt;/p&gt;

&lt;p&gt;At low concurrency, the single process was fine. With only 8 clients, there was little parallel work to distribute, and the overhead of the fleet did not help.&lt;/p&gt;

&lt;p&gt;The gap opened as concurrency increased.&lt;/p&gt;

&lt;p&gt;The single process reached about 86k transactions per second around 64 clients, then fell as load rose further. At 256 clients it was down around 77k transactions per second. That is the classic shape of a saturated single-threaded bottleneck: once the core is full, adding clients mostly adds contention and waiting.&lt;/p&gt;

&lt;p&gt;The fleet kept scaling much longer. It reached roughly 219k transactions per second at 64 clients, about 321k at 128 clients, and about 336k at 256 clients. In the measured setup, the multi-process configuration delivered about four times the throughput of the single process at the high-concurrency end.&lt;/p&gt;

&lt;p&gt;CPU measurements told the same story from another angle. The single process pinned about one core while the 16-vCPU box stayed mostly idle. The fleet used much more of the machine, climbing into several busy cores until Postgres and the load generator became the next limits.&lt;/p&gt;

&lt;p&gt;That last clause is important: the fleet does not remove all bottlenecks. It moves the pooler out of the way until another component becomes the limit. That is what good infrastructure plumbing should do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Better Than Just Adding Another Proxy Layer
&lt;/h2&gt;

&lt;p&gt;Another way to scale a single-threaded service is to put a load balancer in front of many instances. That can work, but it often creates another operational object to deploy, monitor, secure, and reason about.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;so_reuseport&lt;/code&gt; approach keeps the client-facing endpoint local and simple. The kernel distributes connections across local workers. PgBouncer handles the database-specific correctness issue through peering. The application does not need to know about process count, and Postgres still sees a controlled pool of backend connections.&lt;/p&gt;

&lt;p&gt;That does not make the pattern free. You still need per-process configuration, consistent versions, restart behavior, health checks, metrics, and a clear rollout plan. But the moving parts are close to the problem: PgBouncer processes, their shared port, and their peer relationships.&lt;/p&gt;

&lt;p&gt;For managed services, that is a reasonable trade. The platform can hide the fleet behind one endpoint and ship the multi-process design by default. Users get the capacity benefit without learning the mechanics on day one.&lt;/p&gt;

&lt;p&gt;For self-managed teams, it is a pattern worth understanding before the pooler becomes the mystery bottleneck during a traffic spike.&lt;/p&gt;

&lt;h2&gt;
  
  
  When A Single Process Is Still Fine
&lt;/h2&gt;

&lt;p&gt;The lesson is not “always run as many PgBouncer processes as cores.”&lt;/p&gt;

&lt;p&gt;If your application has modest concurrency, a single PgBouncer may be simpler and perfectly adequate. If Postgres is already the bottleneck, multiplying pooler processes will not make queries cheaper. If your workload relies on session semantics, transaction pooling may be the wrong mode. If your monitoring cannot distinguish per-process saturation from aggregate host CPU, adding more processes may make troubleshooting harder until observability catches up.&lt;/p&gt;

&lt;p&gt;There are also version and configuration details to respect. Peering support exists to preserve cancellation behavior in multi-process or load-balanced setups, but all peers need to be configured coherently. Mixed behavior across PgBouncer versions or inconsistent peer settings can turn a scaling change into a correctness problem.&lt;/p&gt;

&lt;p&gt;The practical threshold is straightforward: scale PgBouncer when the pooler is the bottleneck. Prove that with metrics. Look for one process saturating a core, rising wait time, throughput flattening while Postgres still has headroom, and client pressure increasing without corresponding database work.&lt;/p&gt;

&lt;p&gt;Then scale the pooler deliberately.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader Pattern
&lt;/h2&gt;

&lt;p&gt;This PgBouncer design is a small example of a larger infrastructure pattern: single-threaded components often survive longer than people expect because they are fast, simple, and reliable. Then one day they become the narrowest point in a system that has grown around them.&lt;/p&gt;

&lt;p&gt;The answer is not always to rewrite them. Sometimes the right answer is to keep the single-threaded unit and compose more of it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;give each worker a share of the machine,&lt;/li&gt;
&lt;li&gt;let the operating system distribute entry traffic,&lt;/li&gt;
&lt;li&gt;add just enough coordination for correctness,&lt;/li&gt;
&lt;li&gt;divide global limits across workers,&lt;/li&gt;
&lt;li&gt;observe both the worker and the fleet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a more conservative design than replacing the component outright. It keeps the mature behavior of PgBouncer while making better use of modern multi-core hosts.&lt;/p&gt;

&lt;p&gt;The ClickHouse numbers are useful because they make the hidden ceiling visible. A 16-vCPU box running one PgBouncer process is not really a 16-vCPU pooler. It is a one-core pooler on a 16-vCPU bill. A peered &lt;code&gt;so_reuseport&lt;/code&gt; fleet turns more of that bill into actual capacity.&lt;/p&gt;

&lt;p&gt;The cleanest version of this lesson is simple: connection pooling is not magic. It is software in the request path. Once it becomes important enough, it deserves the same capacity modeling and correctness review as everything else in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://clickhouse.com/blog/pgbouncer-clickhouse-managed-postgres" rel="noopener noreferrer"&gt;How we scale PgBouncer in ClickHouse Managed Postgres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pgbouncer.org/config.html" rel="noopener noreferrer"&gt;PgBouncer configuration documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pgbouncer.org/usage.html" rel="noopener noreferrer"&gt;PgBouncer usage documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>GPT-5.6 and GPT-Live: OpenAI Splits Intelligence from the Interface</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Fri, 10 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/gpt-56-and-gpt-live-openai-splits-intelligence-from-the-interface-18in</link>
      <guid>https://dev.to/0xgosu/gpt-56-and-gpt-live-openai-splits-intelligence-from-the-interface-18in</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2lejxhbiqzbqwfqpv8ij.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2lejxhbiqzbqwfqpv8ij.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OpenAI released two model families this week that look separate at first glance. &lt;strong&gt;GPT-5.6&lt;/strong&gt; is a new generation of frontier models built for coding, professional work, science, cybersecurity, and agents. &lt;strong&gt;GPT-Live&lt;/strong&gt; is a voice model built to listen and speak at the same time.&lt;/p&gt;

&lt;p&gt;The more interesting story is what happens when you put them together.&lt;/p&gt;

&lt;p&gt;OpenAI is separating the AI that interacts with you from the AI that does the hardest work. GPT-Live can manage a fluid, real-time conversation while delegating search and reasoning to a frontier model in the background. GPT-5.6, meanwhile, can coordinate tools, programs, and even multiple agents to finish complex tasks.&lt;/p&gt;

&lt;p&gt;This is not merely a pair of model upgrades. It is a blueprint for AI systems that remain responsive on the surface while becoming much more capable underneath.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPT-5.6 Is a Family, Not a Single Model
&lt;/h2&gt;

&lt;p&gt;The GPT-5.6 lineup has three durable capability tiers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Positioning&lt;/th&gt;
&lt;th&gt;Best fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPT-5.6 Sol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Flagship intelligence&lt;/td&gt;
&lt;td&gt;Difficult coding, research, professional work, and agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPT-5.6 Terra&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Balanced performance and cost&lt;/td&gt;
&lt;td&gt;Everyday production workloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GPT-5.6 Luna&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fastest and most affordable&lt;/td&gt;
&lt;td&gt;High-volume and latency-sensitive tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That structure matters. Model selection is becoming less about choosing one universal “best” model and more about matching intelligence to the work. A product can use Luna for routine interactions, Terra for the middle of the distribution, and Sol when failure is expensive or the task is unusually difficult.&lt;/p&gt;

&lt;p&gt;OpenAI’s headline claim for the family is &lt;strong&gt;more useful work per token&lt;/strong&gt;. Sol reaches state-of-the-art results across several coding, browsing, computer-use, cybersecurity, and professional-work evaluations. Terra and Luna are positioned to carry much of that capability into cheaper, faster workloads.&lt;/p&gt;

&lt;p&gt;The practical advantage is not simply a lower API bill. Token efficiency also affects latency, context pressure, and how long an agent can keep working before its history becomes unwieldy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sol Pushes Harder When the Task Justifies It
&lt;/h2&gt;

&lt;p&gt;GPT-5.6 adds two higher-compute modes for difficult problems.&lt;/p&gt;

&lt;p&gt;The first is &lt;strong&gt;&lt;code&gt;max&lt;/code&gt;&lt;/strong&gt; , which gives the model more time than &lt;code&gt;xhigh&lt;/code&gt; to explore alternatives, run checks, and revise its answer. The second is &lt;strong&gt;&lt;code&gt;ultra&lt;/code&gt;&lt;/strong&gt; , a mode that coordinates four agents in parallel by default. Instead of asking one model instance to work through every branch sequentially, ultra divides the work and synthesizes the results.&lt;/p&gt;

&lt;p&gt;This makes compute allocation more explicit. Routine requests should not pay the same cost as an ambiguous engineering problem, a deep research task, or a multi-stage financial analysis. The system can start efficiently and spend more only when the value of a better result justifies it.&lt;/p&gt;

&lt;p&gt;For developers, OpenAI says similar designs can be built through the multi-agent beta in the Responses API. That points toward a future where orchestration is not an application-specific workaround but a standard model capability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programmatic Tool Calling Changes the Agent Loop
&lt;/h2&gt;

&lt;p&gt;One of GPT-5.6’s most consequential features may be less visible than its benchmark scores.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Programmatic Tool Calling&lt;/strong&gt; , the model can write and run lightweight programs in memory to coordinate tools, filter intermediate results, monitor progress, and decide what to do next. A conventional tool-using agent sends every tool result back through the model. That creates extra round trips and can flood the context window with data that will never affect the final answer.&lt;/p&gt;

&lt;p&gt;GPT-5.6 can instead process intermediate information and retain what matters. OpenAI says this can reduce tokens, model turns, and the amount of guidance required for tool-heavy work.&lt;/p&gt;

&lt;p&gt;That is an architectural improvement, not just a smarter model. It moves part of the control loop closer to the model and lets an agent behave more like a small adaptive program than a rigid chain of prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowledge Work Finally Includes the Last Mile
&lt;/h2&gt;

&lt;p&gt;The GPT-5.6 announcement spends unusual attention on the quality of finished business artifacts. That is important because professional work rarely ends with a correct paragraph. The result has to fit a template, preserve a spreadsheet’s formulas, communicate through a coherent slide deck, or arrive as a document that another person can edit and share.&lt;/p&gt;

&lt;p&gt;OpenAI says GPT-5.6 is better at inferring the design system of a reference deck—including layouts, typography, spacing, colors, recurring patterns, and Slide Master rules—and applying it to new material. The same focus extends to documents and spreadsheets, where equations, financial models, hierarchy, and worksheet layout all matter.&lt;/p&gt;

&lt;p&gt;This changes the standard by which a model should be judged. A draft that contains the right facts but requires an hour of formatting is not the same product as a ready-to-use deliverable. The last mile is part of the task.&lt;/p&gt;

&lt;p&gt;The broader computer-use results reinforce that point. GPT-5.6 Sol reports 62.6% on OSWorld 2.0 and 90.4% on BrowseComp in its single-model configuration, with BrowseComp rising to 92.2% in ultra. Benchmarks are never the whole story, but these target the ability to navigate software and find difficult information rather than merely recall facts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding Is Becoming End-to-End Delivery
&lt;/h2&gt;

&lt;p&gt;OpenAI describes GPT-5.6 Sol as its best coding model yet. The release reports state-of-the-art results on the Artificial Analysis Coding Agent Index, Terminal-Bench 2.1, and DeepSWE.&lt;/p&gt;

&lt;p&gt;But the more meaningful shift is in the scope of the work. GPT-5.6 is designed to inspect live systems, use tools, change code, validate the result, and produce a finished artifact. Its stronger computer-use and design judgment also let it examine a rendered interface instead of stopping after it generates source code.&lt;/p&gt;

&lt;p&gt;That closes an important loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Interpret the product intent.&lt;/li&gt;
&lt;li&gt;Build the implementation.&lt;/li&gt;
&lt;li&gt;Run and inspect it.&lt;/li&gt;
&lt;li&gt;Notice visual or functional problems.&lt;/li&gt;
&lt;li&gt;Refine the result before handing it back.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For frontend development, the ability to judge the rendered output is as important as generating syntactically correct code. A component can compile and still have broken hierarchy, awkward spacing, poor mobile behavior, or an unusable interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cybersecurity and Science Raise the Stakes
&lt;/h2&gt;

&lt;p&gt;GPT-5.6 is also OpenAI’s strongest cybersecurity model so far. The reported gains are substantial: Sol scores 73.5% on ExploitBench 2 compared with GPT-5.5’s 47.9%, and 71.2% on SEC-Bench Pro compared with 45.8%. On ExploitGym 3, its two-hour pass rate rises from GPT-5.5’s 15.1% to 24.9%, reaching 33.7% when allowed six hours.&lt;/p&gt;

&lt;p&gt;Those abilities are dual-use. The same model that can reproduce a vulnerability can help a defender review code, validate a patch, model threats, or improve detection. OpenAI is reserving more sensitive defensive capabilities for verified users through its Trusted Access for Cyber program, with identity and account-security requirements attached.&lt;/p&gt;

&lt;p&gt;Scientific work is another major target. OpenAI reports improvements across genomics, quantitative biology, life-science research workflows, and medicinal chemistry. The company also says GPT-5.6 is being used internally to debug research systems, optimize kernels and training recipes, run experiments, and interpret results.&lt;/p&gt;

&lt;p&gt;These domains make reliability and oversight more important, not less. A higher benchmark score does not remove the need for authorization, domain expertise, reproducibility, and human review. It raises the ceiling of what a well-governed team can attempt—and the cost of deploying the system carelessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPT-Live Removes the Turn-Taking Tax
&lt;/h2&gt;

&lt;p&gt;While GPT-5.6 expands what AI can do, GPT-Live changes how it feels to use.&lt;/p&gt;

&lt;p&gt;Traditional voice assistants are usually built as a pipeline: speech becomes text, a language model generates a response, and text becomes speech again. More recent audio models reduced that delay, but they still tended to operate in discrete turns. The system waited for silence, assumed the user had finished, and then replied.&lt;/p&gt;

&lt;p&gt;GPT-Live uses a &lt;strong&gt;full-duplex architecture&lt;/strong&gt;. It continuously processes input while producing output, allowing it to decide many times per second whether to listen, speak, pause, interrupt, acknowledge the user, or call a tool.&lt;/p&gt;

&lt;p&gt;That enables small behaviors that matter enormously in conversation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Waiting when someone pauses to think&lt;/li&gt;
&lt;li&gt;Accepting an interruption without losing the thread&lt;/li&gt;
&lt;li&gt;Giving a brief acknowledgement without taking over the conversation&lt;/li&gt;
&lt;li&gt;Staying quiet when asked to listen&lt;/li&gt;
&lt;li&gt;Focusing on the speaker amid background noise&lt;/li&gt;
&lt;li&gt;Performing live translation with more natural timing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These details make voice feel less like submitting audio prompts and more like sharing a live conversational space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fast Conversation, Deep Work in the Background
&lt;/h2&gt;

&lt;p&gt;GPT-Live’s key design decision is to separate continuous interaction from deeper reasoning.&lt;/p&gt;

&lt;p&gt;When a request needs web search, extended reasoning, or agentic work, GPT-Live delegates it to a frontier model. At launch, GPT-Live-1 uses GPT-5.5 Instant for fast requests, while its Medium and High settings use GPT-5.5 Thinking. The background model can change as OpenAI releases newer frontier systems.&lt;/p&gt;

&lt;p&gt;Meanwhile, GPT-Live can keep the conversation moving.&lt;/p&gt;

&lt;p&gt;This solves a fundamental tension in voice AI. Human conversation expects immediate feedback, but hard problems need time. Making the conversational model perform every difficult task itself either weakens the answer or creates an uncomfortable silence. Delegation allows the interface to remain responsive while another model searches, reasons, or acts.&lt;/p&gt;

&lt;p&gt;It is easy to imagine GPT-5.6 and its successors filling that background role: Sol for the hardest requests, Terra for balanced everyday work, and Luna where speed and cost dominate.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPT-Live Is More Than Faster Speech
&lt;/h2&gt;

&lt;p&gt;The launch includes two versions: GPT-Live-1 and GPT-Live-1 mini. OpenAI’s human evaluations compare them with Advanced Voice Mode across conversations lasting five to ten minutes, measuring overall preference, turn-taking, interruptions, flow, and naturalness. The company reports a strong preference for both new models.&lt;/p&gt;

&lt;p&gt;Capability improved alongside conversational timing. GPT-Live-1 outperforms Advanced Voice Mode in OpenAI’s reported evaluations for expert scientific reasoning, agentic browsing, and realistic multi-turn telecom support. That combination matters because pleasant speech without useful answers is only a better voice skin; intelligence without conversational timing is still awkward to use.&lt;/p&gt;

&lt;p&gt;ChatGPT Voice also gains visual response cards for information such as weather, stocks, sports, and maps while the conversation continues. Search, memory, images, and file uploads remain available. Voice is therefore becoming one input and coordination surface inside a multimodal product, not an isolated audio mode.&lt;/p&gt;

&lt;p&gt;OpenAI says more than 150 million people use ChatGPT Voice and Dictation each week. At that scale, improvements to interruption, silence, accent coverage, and safety affect far more than a technical demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Releases, One Architecture
&lt;/h2&gt;

&lt;p&gt;Together, GPT-5.6 and GPT-Live suggest a layered design for the next generation of AI applications:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interaction model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Maintains timing, attention, tone, interruption, and conversational context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reasoning model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Handles analysis, search, planning, and difficult decisions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Coordinates tools, programs, computer use, and parallel workers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Safety system&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monitors the interaction and applies safeguards during execution&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The user does not need to see those boundaries. They can simply ask a question, continue talking, and receive the result when it is ready. Underneath, the system can route work to different models and spend different amounts of compute based on the task.&lt;/p&gt;

&lt;p&gt;This is closer to how effective human teams operate. The person in the conversation does not have to personally perform every analysis. They maintain context, delegate specialized work, and bring the answer back into the discussion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety Has to Operate in Real Time
&lt;/h2&gt;

&lt;p&gt;GPT-Live introduces risks that do not appear in the same way in text. A voice model speaks continuously, can influence an emotionally charged conversation through tone and timing, and may need to change direction before it finishes an unsafe response.&lt;/p&gt;

&lt;p&gt;OpenAI says it expanded testing with audio-native and synthetic evaluations covering self-harm, psychosis and mania, emotional reliance, violence, and sexual content. The system can intervene while speech is being generated: steering toward a safer response, presenting support resources, or ending a higher-risk voice conversation. Teen protections and parental controls are also part of the rollout.&lt;/p&gt;

&lt;p&gt;The model uses predefined ChatGPT voices and includes safeguards against impersonating a real person. OpenAI is also monitoring emotional reliance after launch, acknowledging that the social effects of a more natural voice system cannot be settled entirely in pre-release tests.&lt;/p&gt;

&lt;p&gt;GPT-5.6 uses its own layered safety system, combining model training, real-time checks, monitoring, and account-level enforcement. OpenAI reports roughly 700,000 A100-equivalent GPU hours of automated black-box red teaming before general availability. The company says the models do not cross its Critical capability threshold in either biology or cybersecurity, though Sol’s cyber safeguards intentionally begin more conservatively and may create friction for benign users.&lt;/p&gt;

&lt;p&gt;The common principle is that safeguards can no longer sit only at the input and output boundaries. When models speak, browse, write programs, use computers, and delegate work, safety has to observe the process while it unfolds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Availability and Cost
&lt;/h2&gt;

&lt;p&gt;GPT-5.6 is rolling out across ChatGPT, Codex, and the OpenAI API. API pricing per one million tokens is:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.6 Sol&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$30.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.6 Terra&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$15.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.6 Luna&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$6.00&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;GPT-Live is rolling out globally across ChatGPT on iOS, Android, and the web. GPT-Live-1 is becoming the default voice model for Go, Plus, and Pro users, while GPT-Live-1 mini is becoming the default for Free users. OpenAI says API access is planned, but it is not available at launch.&lt;/p&gt;

&lt;p&gt;There are also launch limitations. GPT-Live does not initially support voice conversations with video or screen sharing, and fluency may vary by language. Legacy voice modes remain available for features the new model does not yet support.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Developers Should Take Away
&lt;/h2&gt;

&lt;p&gt;The biggest lesson is not “always use the most powerful model.” It is to design products around &lt;strong&gt;routing and delegation&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a fast interaction layer to keep the experience responsive.&lt;/li&gt;
&lt;li&gt;Escalate difficult work to a stronger reasoning model.&lt;/li&gt;
&lt;li&gt;Use parallel agents only when the task benefits from the additional compute.&lt;/li&gt;
&lt;li&gt;Process noisy tool output before placing it back into model context.&lt;/li&gt;
&lt;li&gt;Validate artifacts in the environment where users will experience them.&lt;/li&gt;
&lt;li&gt;Treat latency, token use, and result quality as one optimization problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model is becoming one component in a larger intelligent system. The quality of that system increasingly depends on how well it decides who should do the work, how much effort to spend, and when to return control to the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;GPT-5.6 makes frontier intelligence more scalable across different budgets and levels of difficulty. GPT-Live makes access to that intelligence feel immediate and conversational. One advances the engine; the other redesigns the steering wheel.&lt;/p&gt;

&lt;p&gt;The combination points beyond chatbots that wait for a prompt and produce a single response. The emerging pattern is a continuously available interface backed by a dynamic team of models, tools, and agents—responsive enough for natural conversation and powerful enough for serious work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/gpt-5-6/" rel="noopener noreferrer"&gt;GPT-5.6: Frontier intelligence that scales with your ambition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openai.com/index/introducing-gpt-live/" rel="noopener noreferrer"&gt;Introducing GPT-Live&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>The Bash Script Hidden on a Uniqlo T-Shirt</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Thu, 09 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/the-bash-script-hidden-on-a-uniqlo-t-shirt-2l5a</link>
      <guid>https://dev.to/0xgosu/the-bash-script-hidden-on-a-uniqlo-t-shirt-2l5a</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgqomz43eb70bf952a33l.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgqomz43eb70bf952a33l.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A tan T-shirt, a heart inside curly braces, and hundreds of characters that look like encoded noise: it is an unusually effective way to make a programmer stop in the middle of a clothing store.&lt;/p&gt;

&lt;p&gt;The shirt comes from Akamai’s contribution to Uniqlo’s &lt;strong&gt;PEACE FOR ALL&lt;/strong&gt; collection. Its back is not merely decorated to resemble code. It carries a real Bash program, encoded as one long Base64 string and wrapped in a command that decodes and executes it. Recovering that program turns a piece of graphic design into a small reverse-engineering exercise.&lt;/p&gt;

&lt;p&gt;The result is harmless and cheerful. The route to that result, however, passes through several ideas worth understanding: recognizing shell syntax in an unfamiliar setting, reconstructing text when one wrong character can corrupt the payload, separating decoding from execution, and reading a terminal animation one primitive at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The clue at the top of the print
&lt;/h2&gt;

&lt;p&gt;The first useful detail is the beginning of the block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a &lt;strong&gt;shebang&lt;/strong&gt;. On an executable text file, it tells the operating system which interpreter should run the file. Seeing one printed above an opaque alphanumeric block changes the question from “is this decorative texture?” to “what program is this trying to run?”&lt;/p&gt;

&lt;p&gt;The wrapper around the long string contains three important pieces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;--decode&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read from the inside out:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt; is a Bash &lt;em&gt;here string&lt;/em&gt;. It sends the quoted text to a command through standard input.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;base64 --decode&lt;/code&gt; turns the printable Base64 data back into its original bytes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$(...)&lt;/code&gt; captures the decoded output.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;eval&lt;/code&gt; asks the current shell to parse that output as a command and execute it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The construction is compact, but it deserves suspicion. Base64 is an encoding, not encryption, and it says nothing about whether the hidden content is safe. An &lt;code&gt;eval&lt;/code&gt; wrapped around concealed text is common in installers, copy-pasted one-liners, and malicious payloads for the same reason: the reader cannot easily inspect the program before it runs.&lt;/p&gt;

&lt;p&gt;On the shirt, opacity is the puzzle. In a production terminal, opacity is a reason to stop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recovering the payload without trusting it
&lt;/h2&gt;

&lt;p&gt;For Tris Sherliker, who documented the decoding process, the hard part was not recognizing Base64. It was transcribing the print exactly.&lt;/p&gt;

&lt;p&gt;Base64 maps binary data into a restricted alphabet of letters, digits, &lt;code&gt;+&lt;/code&gt;, and &lt;code&gt;/&lt;/code&gt;, usually ending with &lt;code&gt;=&lt;/code&gt; padding. That makes it printable, but not resistant to transcription errors. A photograph adds fabric folds, lighting, perspective, and ink texture. The shirt also uses a dense type treatment in which characters such as &lt;code&gt;I&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;O&lt;/code&gt;, and &lt;code&gt;0&lt;/code&gt; are easy to confuse.&lt;/p&gt;

&lt;p&gt;Sherliker combined Android’s built-in OCR, Tesseract, and Claude. Generalized into a practical recovery method, the approach is redundancy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run more than one OCR engine.&lt;/li&gt;
&lt;li&gt;Keep the outputs separate.&lt;/li&gt;
&lt;li&gt;Diff them to find disagreement instead of trusting the most confident-looking result.&lt;/li&gt;
&lt;li&gt;Check the ambiguous characters against the image at high magnification.&lt;/li&gt;
&lt;li&gt;Decode to a file and inspect it as text.&lt;/li&gt;
&lt;li&gt;Never preserve the &lt;code&gt;eval&lt;/code&gt; step while investigating.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A safe first pass looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;--decode&lt;/span&gt; &amp;lt; payload.txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; decoded.sh

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then inspect &lt;code&gt;decoded.sh&lt;/code&gt; in an editor. If execution is eventually necessary, do it only after understanding the script and preferably in an isolated environment. For this artifact, execution is not required to learn what it does.&lt;/p&gt;

&lt;p&gt;Sherliker’s final transcription had useful structural clues. The Base64 padding was present, the shell wrapper was balanced, and a successful decode produced readable Bash rather than random bytes. Those checks do not prove that every character is right, but together they make accidental corruption much less likely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the decoded program contains
&lt;/h2&gt;

&lt;p&gt;Once decoded, the intimidating wall of characters becomes a commented Bash loop. Its message is repeated in English and Japanese, followed by the text it will animate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text="♥PEACE♥FOR♥ALL♥PEACE♥FOR♥ALL♥..."

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The program asks the terminal for its current dimensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;cols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;tput cols&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;tput lines&lt;span class="si"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;tput&lt;/code&gt; provides a portable interface to capabilities described by the terminal database. Rather than hard-coding a particular escape sequence or assuming an 80-column display, the script can query the active terminal and position output relative to its size.&lt;/p&gt;

&lt;p&gt;It then hides the cursor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tput civis

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Animations look cleaner without a cursor blinking through them. Hiding it creates another responsibility, though: the program must restore it before exiting. The script installs a signal handler for &lt;code&gt;Ctrl+C&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;"tput cnorm; exit"&lt;/span&gt; SIGINT

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the user interrupts the infinite loop, &lt;code&gt;tput cnorm&lt;/code&gt; makes the cursor visible again. This tiny cleanup detail is the difference between a playful demo and one that leaves the terminal in an annoying state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drawing a wave with shell arithmetic
&lt;/h2&gt;

&lt;p&gt;The animation advances a counter named &lt;code&gt;t&lt;/code&gt; forever. On each iteration it selects one character from the message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;char&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;text&lt;/span&gt;:t&lt;span class="p"&gt; % text_length&lt;/span&gt;:1&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The modulo operation wraps the index back to the beginning when it reaches the end, so the phrase repeats continuously.&lt;/p&gt;

&lt;p&gt;Next, the script turns the counter into an angle and asks &lt;code&gt;bc -l&lt;/code&gt; to calculate its sine. Bash only has integer arithmetic; &lt;code&gt;bc&lt;/code&gt; supplies the floating-point math:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;angle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"(&lt;/span&gt;&lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="s2"&gt;) * &lt;/span&gt;&lt;span class="nv"&gt;$freq&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | bc &lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;sine_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"s(&lt;/span&gt;&lt;span class="nv"&gt;$angle&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt; | bc &lt;span class="nt"&gt;-l&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sine value moves smoothly between &lt;code&gt;-1&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;. Scaling it by one quarter of the terminal width and adding half the width produces an &lt;code&gt;x&lt;/code&gt; coordinate centered on the screen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x = center + amplitude × sin(angle)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code rounds that position, clamps it to the terminal boundaries, and calls &lt;code&gt;tput cup&lt;/code&gt; to move the cursor to row &lt;code&gt;t&lt;/code&gt; and column &lt;code&gt;x&lt;/code&gt;. Each loop advances downward while the horizontal position oscillates, turning the repeated message into a sine wave.&lt;/p&gt;

&lt;p&gt;Color changes at the same time. The script cycles through values between cyan and orange in the terminal’s 256-color palette, emits one character, resets the color, and adds a line feed. The complete effect is a flowing ribbon of hearts and the phrase &lt;strong&gt;PEACE FOR ALL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is not the most efficient way to build terminal graphics. Each frame starts several processes—&lt;code&gt;echo&lt;/code&gt;, &lt;code&gt;bc&lt;/code&gt;, and &lt;code&gt;tput&lt;/code&gt;—and the row counter grows without reference to the current screen height. But efficiency is not the point. The program is short, readable after decoding, and assembled from commands likely to feel familiar to a Linux user.&lt;/p&gt;

&lt;h2&gt;
  
  
  The code is part of the design
&lt;/h2&gt;

&lt;p&gt;Akamai described the light tan color as a reference to the beige computers of the early internet. The heart on the front represents the internet used for good, while the code on the back connects the design to Linux and the open-source systems beneath online services.&lt;/p&gt;

&lt;p&gt;There is a technical imprecision in calling Linux a language—it is a kernel, while Bash is the language visible here—but the design works because it operates at several distances. Across a room, the code is texture. Up close, the shebang rewards recognition. With a camera and some patience, the encoded block becomes an executable message.&lt;/p&gt;

&lt;p&gt;That layered reveal is stronger than printing a plain slogan. The wearer carries the message, but the curious reader has to participate in uncovering it.&lt;/p&gt;

&lt;p&gt;The typography adds one final twist. The block uses Roboto Mono, yet spacing and optical treatment can make nominally monospaced characters difficult for OCR to segment. That is ideal for graphic texture and inconvenient for exact data recovery. It also explains why comparing multiple OCR results was more dependable than assuming a single modern vision model would produce a perfect transcription.&lt;/p&gt;

&lt;h2&gt;
  
  
  A useful rule for every encoded one-liner
&lt;/h2&gt;

&lt;p&gt;The shirt’s payload is benign. The wrapper is still a perfect example of a command that should not be executed on faith.&lt;/p&gt;

&lt;p&gt;When an unfamiliar one-liner decodes text and sends it directly into &lt;code&gt;eval&lt;/code&gt;, &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;sh&lt;/code&gt;, PowerShell, Python, or another interpreter, split the pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save the encoded input.&lt;/li&gt;
&lt;li&gt;Decode it without execution.&lt;/li&gt;
&lt;li&gt;Read the output.&lt;/li&gt;
&lt;li&gt;Identify network access, file writes, privilege changes, and persistence.&lt;/li&gt;
&lt;li&gt;Verify where it came from.&lt;/li&gt;
&lt;li&gt;Run it only if the behavior and environment are acceptable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That habit applies whether the code arrives in a shell prompt, an installation guide, a QR code, or on the back of a T-shirt.&lt;/p&gt;

&lt;p&gt;Here, careful inspection ends with a colored wave and a message of peace. More importantly, it demonstrates the right order of operations: curiosity first, execution last.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tris.sherliker.net/blog/obfuscated-self-evaluating-bash-script-by-cdn-akamai-being-supplied-to-consumers-via-retail-stores/" rel="noopener noreferrer"&gt;Tris Sherliker’s decoding and transcription&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ir.akamai.com/news-releases/news-release-details/uniqlo-adds-new-akamai-t-shirt-peace-all-collection" rel="noopener noreferrer"&gt;Akamai’s PEACE FOR ALL announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.uniqlo.com/us/en/products/E459561-000/00" rel="noopener noreferrer"&gt;Uniqlo’s Akamai PEACE FOR ALL product page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gnu.org/software/coreutils/manual/html_node/base64-invocation.html" rel="noopener noreferrer"&gt;GNU Coreutils documentation for &lt;code&gt;base64&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=48829312" rel="noopener noreferrer"&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
    <item>
      <title>StreetComplete Makes Map Editing Feel Like Field Work, Not Database Work</title>
      <dc:creator>Vincent Tran</dc:creator>
      <pubDate>Wed, 08 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/0xgosu/streetcomplete-makes-map-editing-feel-like-field-work-not-database-work-25</link>
      <guid>https://dev.to/0xgosu/streetcomplete-makes-map-editing-feel-like-field-work-not-database-work-25</guid>
      <description>&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqfdr79wrsv2f20ep9c1s.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqfdr79wrsv2f20ep9c1s.png" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OpenStreetMap has always had a strange product problem.&lt;/p&gt;

&lt;p&gt;The data is public, useful, and incomplete in exactly the places where local knowledge matters. A shop entrance moves. A bench appears. A crossing gets tactile paving. A road surface changes. A bike rack shows up outside a station. These facts are easy for a person standing there to verify, but they are awkward to add if the only tool you know is a general-purpose map editor.&lt;/p&gt;

&lt;p&gt;StreetComplete solves that problem by refusing to look like a general-purpose editor.&lt;/p&gt;

&lt;p&gt;It is an Android app for contributing to OpenStreetMap from the street. Instead of asking users to understand tags, relations, presets, geometry, changesets, validation rules, and community conventions, it asks small questions tied to nearby map objects. Is there a sidewalk here? What surface is this path? Does this crossing have tactile paving? What kind of bicycle parking is this? Is this shop still there?&lt;/p&gt;

&lt;p&gt;That sounds almost too modest. It is not.&lt;/p&gt;

&lt;p&gt;StreetComplete is interesting because it treats map maintenance as field work first and database editing second. The person with the phone answers a concrete question about the real world. The app turns that answer into the appropriate OpenStreetMap edit.&lt;/p&gt;

&lt;p&gt;That is the whole product insight.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Quest Model
&lt;/h2&gt;

&lt;p&gt;StreetComplete calls its tasks quests, and the word is doing useful work.&lt;/p&gt;

&lt;p&gt;A quest is not an open-ended request to improve a map. It is a constrained missing fact that can be answered on site. The app scans the surrounding OpenStreetMap data, finds objects where a survey would help, and places quest markers on the map. The user taps a marker, answers the question, and moves on.&lt;/p&gt;

&lt;p&gt;The constraint matters more than the game-like wrapper.&lt;/p&gt;

&lt;p&gt;Good quests are answerable without knowing OpenStreetMap’s tagging system. They should not require a user to infer mapper intent, repair complex geometry, settle a local classification debate, or choose between obscure schema options. They should ask for evidence that can be observed: the name on a sign, the material underfoot, the presence of a curb ramp, the kind of opening hours posted on a door.&lt;/p&gt;

&lt;p&gt;That keeps the app honest.&lt;/p&gt;

&lt;p&gt;A general map editor exposes the full power of OpenStreetMap. StreetComplete deliberately exposes less. It turns contribution into a sequence of bounded observations, then handles the translation from human answer to map data.&lt;/p&gt;

&lt;p&gt;For many contributors, that is the difference between helping and bouncing off the tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why OpenStreetMap Needs This Kind Of Editor
&lt;/h2&gt;

&lt;p&gt;OpenStreetMap is sometimes described as the Wikipedia of maps. The comparison is useful, but incomplete.&lt;/p&gt;

&lt;p&gt;Wikipedia is mostly edited from a chair. OpenStreetMap often needs someone to go outside.&lt;/p&gt;

&lt;p&gt;Aerial imagery can show buildings, roads, and paths. Imports can seed large datasets. Existing mappers can trace geometry and clean up topology. But many valuable map attributes are local, physical, and changing. Wheelchair access, surface quality, lighting, crossing details, address signs, shop status, public amenities, path barriers, opening hours, and bike infrastructure all benefit from human survey.&lt;/p&gt;

&lt;p&gt;The problem is not only collecting those facts. The problem is collecting them without requiring every contributor to become an OpenStreetMap specialist.&lt;/p&gt;

&lt;p&gt;Traditional editors such as JOSM, Vespucci, and the browser-based iD editor are powerful because they expose the map as a rich editable database. That is exactly why they can feel intimidating. OpenStreetMap is not just points and lines. It is a living schema made of tags, conventions, local practices, validation expectations, and social norms.&lt;/p&gt;

&lt;p&gt;StreetComplete chooses a different tradeoff. It does not try to be the tool for every edit. It tries to be the tool for the edits that can be made safe, obvious, and useful from a phone.&lt;/p&gt;

&lt;p&gt;That narrower ambition is why the design works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The App Hides The Schema Without Hiding The Work
&lt;/h2&gt;

&lt;p&gt;The best thing about StreetComplete is that it does not pretend mapping is magic.&lt;/p&gt;

&lt;p&gt;The user still has to be physically present. The user still has to look around. The user still has to answer carefully. If the app asks about a crossing, a surface, or an entrance, the quality of the edit depends on whether the person on site observes correctly.&lt;/p&gt;

&lt;p&gt;What the app removes is not responsibility. It removes schema friction.&lt;/p&gt;

&lt;p&gt;OpenStreetMap contributors eventually learn that tags matter. A bench, a bicycle parking stand, a segregated footway, a bus stop, and a shop all carry different tagging conventions. Even a simple answer can fan out into details: what key should be used, which value is accepted, whether a local community prefers one tagging style, whether an object already has related tags, whether a change belongs on a node, way, or relation.&lt;/p&gt;

&lt;p&gt;StreetComplete absorbs much of that machinery into quest definitions. The quest decides when to ask, how to phrase the question, which answers are valid, and how to convert the answer into an edit.&lt;/p&gt;

&lt;p&gt;That is product design as data modeling.&lt;/p&gt;

&lt;p&gt;The UI is simple because the hard choices moved into the quest system. Each quest is a small contract between the real-world observation and the OpenStreetMap data model. When that contract is good, a non-expert can contribute safely. When that contract is too vague or too clever, the quest becomes dangerous.&lt;/p&gt;

&lt;p&gt;This is why StreetComplete’s release notes often look like a stream of small quest adjustments. The June 2026 v63.2 release included fixes around map rendering, language behavior, form behavior, and many quest-level changes: not asking for winter roads in surface quests, avoiding opening-hours prompts for street vendors, refining lane answers, disabling a power-line attachment quest that was too complex in edge cases, and changing where tactile paving quests are enabled.&lt;/p&gt;

&lt;p&gt;Those are not cosmetic details. They are the maintenance work that keeps a simplified editor from becoming a simplified mistake generator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Offline, Local, And Built For Walking
&lt;/h2&gt;

&lt;p&gt;StreetComplete is also shaped by the fact that it is meant to be used outside.&lt;/p&gt;

&lt;p&gt;The repository describes the app as economical with data usage and usable offline during a survey. That is not a nice-to-have feature for this category. It is the difference between an app you can use while walking through a neighborhood and an app that only works when the network cooperates.&lt;/p&gt;

&lt;p&gt;Field tools need to respect interruption. The user may be in bright light, moving between intersections, low on battery, switching between map and camera, or checking a sign while trying not to block the sidewalk. A task that looks trivial at a desk becomes annoying if it takes twelve taps outside.&lt;/p&gt;

&lt;p&gt;That context explains the quest model again. A quest is small enough to complete in place. The app does not need to expose the whole database because the user does not need the whole database while standing beside a bike rack. They need the one question that matches the missing fact.&lt;/p&gt;

&lt;p&gt;This is the same lesson many developer tools eventually learn: the right interface is not the one that exposes the most capability. It is the one that matches the moment of use.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Community Boundary
&lt;/h2&gt;

&lt;p&gt;StreetComplete’s design also has to coexist with OpenStreetMap’s community norms.&lt;/p&gt;

&lt;p&gt;OpenStreetMap is not just a dataset. It is a project with local conventions, review habits, mapper expectations, and long-running debates about classification. An app that makes contribution easier can improve coverage, but it can also create low-quality edits at scale if the prompts are wrong.&lt;/p&gt;

&lt;p&gt;That is why bounded questions matter. A good StreetComplete quest does not ask a novice to decide something that experienced mappers would argue about. It asks for a fact that the person can observe and that the software can encode responsibly.&lt;/p&gt;

&lt;p&gt;There is still risk.&lt;/p&gt;

&lt;p&gt;Any mobile contribution workflow can encourage drive-by edits, duplicate data, mistaken answers, or local misunderstandings. The app must decide when not to ask. It must avoid objects that are already mapped in detail. It must handle private roads, heritage objects, seasonal cases, unusual infrastructure, locale-specific input, and values that look simple until they meet the real world.&lt;/p&gt;

&lt;p&gt;The interesting part is that StreetComplete appears to treat those edges as normal product work rather than as exceptions. The release history is full of small changes that narrow prompts, exclude bad cases, add missing answer options, and disable quests that do not behave well enough.&lt;/p&gt;

&lt;p&gt;That is what responsible simplification looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It Reached People Again
&lt;/h2&gt;

&lt;p&gt;StreetComplete has been around for years, and it has appeared on developer forums before. The reason it still catches attention is not novelty. It is clarity.&lt;/p&gt;

&lt;p&gt;Most civic data projects fail at the last meter. They have a good mission, a good data model, and a good community, but the path from “I noticed something outside” to “the shared dataset is better” is still too long for casual contributors.&lt;/p&gt;

&lt;p&gt;StreetComplete shortens that path.&lt;/p&gt;

&lt;p&gt;It says: you do not have to learn the whole map. You do not have to decide which editor is right. You do not have to search a tagging wiki while standing on a corner. You can answer this one question, here, now.&lt;/p&gt;

&lt;p&gt;That is a powerful contribution funnel.&lt;/p&gt;

&lt;p&gt;It is also a reminder that gamification works best when it is not decoration. The quest markers are useful because the underlying tasks are real. The satisfaction comes from making a public map slightly more accurate, not from collecting fake points in a closed system.&lt;/p&gt;

&lt;p&gt;The game layer is thin. The civic utility is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The iOS And Multiplatform Question
&lt;/h2&gt;

&lt;p&gt;One practical limitation remains obvious: StreetComplete is known primarily as an Android app.&lt;/p&gt;

&lt;p&gt;The project has active work toward a multiplatform future, including sponsor-backed efforts tied to iOS. That matters because field contribution benefits from broad device coverage. If the easiest survey tool is unavailable to a large share of pedestrians, the contributor pool is artificially smaller.&lt;/p&gt;

&lt;p&gt;Cross-platform work is not just a distribution checkbox, though. A survey app depends on maps, offline storage, location behavior, camera and sensor integration, background constraints, UI responsiveness, and careful power usage. Porting that experience without weakening it is real engineering.&lt;/p&gt;

&lt;p&gt;If StreetComplete reaches iOS with the same quest discipline, the bigger story will not be “now there is an app on another platform.” It will be that OpenStreetMap gains another low-friction path for local knowledge to become public infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Developers Can Learn From It
&lt;/h2&gt;

&lt;p&gt;StreetComplete is a useful case study even if you never edit OpenStreetMap.&lt;/p&gt;

&lt;p&gt;It shows how to build a contribution tool around bounded tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start from the user’s physical or operational context.&lt;/li&gt;
&lt;li&gt;Ask only questions the user can answer confidently.&lt;/li&gt;
&lt;li&gt;Hide internal schema details, but keep the user’s responsibility clear.&lt;/li&gt;
&lt;li&gt;Encode expert knowledge into task definitions.&lt;/li&gt;
&lt;li&gt;Treat edge cases as product quality work, not as cleanup.&lt;/li&gt;
&lt;li&gt;Avoid expanding scope until the simple path is reliable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That pattern applies far beyond maps.&lt;/p&gt;

&lt;p&gt;Bug triage, data labeling, knowledge-base cleanup, support macros, security inventory, accessibility audits, and internal tool maintenance all have versions of the same problem. Experts understand the schema. Non-experts see the real-world facts. The product opportunity is to connect those two groups without forcing everyone through the expert interface.&lt;/p&gt;

&lt;p&gt;The hard part is not making the UI friendly. The hard part is deciding which tasks are safe to simplify.&lt;/p&gt;

&lt;p&gt;StreetComplete works because it does not try to turn every mapping task into a quest. It picks tasks where the app can ask a narrow question, where the user can observe the answer, and where the resulting edit can be generated with confidence.&lt;/p&gt;

&lt;p&gt;That restraint is the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Lesson
&lt;/h2&gt;

&lt;p&gt;OpenStreetMap does not only need more data. It needs better ways for ordinary people to contribute the facts they already know because they live, walk, ride, shop, and wait for buses in real places.&lt;/p&gt;

&lt;p&gt;StreetComplete is one of the cleanest answers to that need.&lt;/p&gt;

&lt;p&gt;It does not replace full editors. It does not remove the need for experienced mappers. It does not solve every data-quality problem. What it does is turn a large, intimidating, globally shared map database into a set of small local observations.&lt;/p&gt;

&lt;p&gt;That is why it matters.&lt;/p&gt;

&lt;p&gt;Great contribution tools do not ask users to admire the complexity of the system. They find the smallest honest unit of useful work and make that work easy to do well.&lt;/p&gt;

&lt;p&gt;StreetComplete’s tiny quests are exactly that: small enough for a walk, structured enough for a database, and useful enough to make the map better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://streetcomplete.app/" rel="noopener noreferrer"&gt;StreetComplete website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/streetcomplete/StreetComplete" rel="noopener noreferrer"&gt;StreetComplete GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/streetcomplete/StreetComplete/releases/latest" rel="noopener noreferrer"&gt;StreetComplete latest release notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.openstreetmap.org/wiki/StreetComplete" rel="noopener noreferrer"&gt;StreetComplete on the OpenStreetMap Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.openstreetmap.org/wiki/StreetComplete/Quests" rel="noopener noreferrer"&gt;StreetComplete quest list&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=48816883" rel="noopener noreferrer"&gt;Hacker News discussion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>software</category>
    </item>
  </channel>
</rss>
