Shellsharks Blogroll - BlogFlock2026-04-27T16:09:36.647ZBlogFlockAdepts of 0xCC, destructured, fLaMEd, Trail of Bits Blog, Aaron Parecki, Westenberg, James' Coffee Blog, gynvael.coldwind//vx.log (pl), joelchrono, Evan Boehs, Kev Quirk, cool-as-heck, Posts feed, Sophie Koonin, <span>Songs</span> on the Security of Networks, cmdr-nova@internet:~$, Johnny.Decimal, Werd I/O, Robb Knight, Molly White, Hey, it's Jason!, Terence Eden’s BlogUpdate #2 on the Framework Saga - Kev Quirkhttps://kevquirk.com/update-2-on-the-framework-saga2026-04-27T13:41:00.000Z
<p>In case you hadn't heard (it's all I've been going on about for a couple weeks, so you probably have heard - sorry) <a href="https://kevquirk.com/i-may-have-killed-my-framework-13">I spilled coffee on my Framework 13</a>, then after lots of testing and cleaning, I confirmed that <a href="https://kevquirk.com/update-on-my-coffee-ridden-framework-13">the main board was dead</a>.</p>
<p>The new main board was delivered this morning, so I went ahead and got it fitted to the chassis. Problem is, I'd pissed about the partitions on the 2TB NVMe so I could dump my install on the 1TB NVMe in <a href="https://kevquirk.com/thinkpad-t480-initial-thoughts">my new ThinkPad T480</a>. I tried booting up and fixing the 2TB NVMe, but it was screwed, so I cut my losses and went for a re-install of Ubuntu 24.04 instead.</p>
<p class="notice">I'm aware that Ubuntu 26.04 LTS has been released, but I prefer to wait for the first point release before upgrading.</p>
<p>After 10 minutes or so, the plucky little Framework was alive!</p>
<p><img src="https://kevquirk.com/content/images/update-2-on-the-framework-saga/new.webp" alt="new install" /></p>
<p>So I spent most of the day (on my day off) configuring the fresh Ubuntu install back to how I had it before. Luckily the ThinkPad is working great, so I could use that as a reference to get everything pretty much exactly the same. After 3 or so hours work, we're back up and running with all my apps, data, and config restored.</p>
<p><img src="https://kevquirk.com/content/images/update-2-on-the-framework-saga/done.webp" alt="done" /></p>
<h2>Another issue</h2>
<p>While setting up the laptop, I noticed that there was an issue with the screen. At first I thought it was just some residue from coffee-gate, but on closer inspection it looks like the bottom corner has somehow de-laminated.</p>
<p><img src="https://kevquirk.com/content/images/update-2-on-the-framework-saga/screen.webp" alt="screen" /></p>
<p>I <em>know</em> this wasn't caused by the coffee spillage, as the stain would be brown. Plus the laptop would smell. I'm wondering if it's some isopropyl alcohol, or contact cleaner, from when I cleaned it out.</p>
<p>The only other explanation is that it has de-laminated due to the heat in the conservatory, but I doubt it. It doesn't get <em>that</em> hot in there, and it's only April.</p>
<p>This is the second problem I've had with screens on the Framework. The bottom of the screen de-laminated <a href="https://kevquirk.com/my-first-week-with-the-framework-13">just a week after I got the laptop</a>. I thought it was a fluke, and Framework support sent me a replacement immediately, but this has me thinking that the screens just aren't that good.</p>
<p>Can anyone else who has a Framework 13 confirm if they've had issues with the 2880x1920 display?</p>
<h2>Final thoughts</h2>
<p>Anyway, this is the last update in the saga. For all intents and purposes the Framework is now repaired. I'm waiting to hear back from Framework support to see if they have any recommendations, but if not, I'll probably have to buy a new screen too.</p>
<p>It's lovely to be back typing this post on the Framework. I've really missed this laptop, and the typing experience.</p>
<p>Geez this has been one expensive mistake! Take note, people - if you drink coffee around your computers, keep a lid on the cup!</p> <div class="email-hidden">
<hr />
<p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p>
<p>You can <a href="mailto:19gy@qrk.one?subject=Update%20%232%20on%20the%20Framework%20Saga">reply to this post by email</a>, or <a href="https://kevquirk.com/update-2-on-the-framework-saga#comments">leave a comment</a>.</p>
</div>
All You Fascists (Bound to Lose) - Werd I/O69ef661a825c3600019fc9592026-04-27T13:39:32.000Z<img src="https://storage.ghost.io/c/18/7c/187cc681-d3f3-49fc-87de-b01d06b76821/content/images/2026/04/Woody_Guthrie_2.jpg" alt="All You Fascists (Bound to Lose)"><p>I've had "All You Fascists (Bound to Lose)" in my song rotation for a little while – for, you know, <em>reasons</em>.</p><p>Bette Midler's getting some coverage for her cover, so I thought I'd round up some other versions I like very much.</p><p>To begin with, here's that Bette Midler cover:</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/uBj57ivPsxQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="ALL YOU FASCISTS (Bound to Lose) Music Video Bette Midler"></iframe></figure><p>This <a href="https://www.resistancerevivalchorus.com/?ref=werd.io" rel="noreferrer">Resistance Revival Chorus</a> with Rhiannon Giddens version is probably my favorite: upbeat and alive.</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/dWUa7aAIfLE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="Resistance Revival Chorus with Rhiannon Giddens "All You Fascists Bound To Lose""></iframe></figure><p>The <a href="https://www.billybragg.co.uk/?ref=werd.io" rel="noreferrer">Billy Bragg</a> version with <a href="https://wilcoworld.net/?ref=werd.io" rel="noreferrer">Wilco</a> is really strong too: </p><figure class="kg-card kg-embed-card"><iframe width="200" height="150" src="https://www.youtube.com/embed/SFPL97m2dsw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="All You Fascists"></iframe></figure><p><a href="https://www.yahoo.com/entertainment/music/articles/nina-hagen-live-forever-133000223.html?ref=werd.io" rel="noreferrer">Nina Hagen's</a> father Hans was a Holocaust survivor held at Moabit, and her paternal grandparents were murdered at Sachsenhausen. This is therefore a very personal cover:</p><figure class="kg-card kg-embed-card"><iframe width="200" height="150" src="https://www.youtube.com/embed/FMDgqMdpBMs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="All You Fascists Bound to Lose"></iframe></figure><p>Here's <a href="https://anidifranco.com/?ref=werd.io" rel="noreferrer">Ani DiFranco</a> with <a href="https://zeoboekbinder.com/?ref=werd.io" rel="noreferrer">Zoe Boekbinder</a>, <a href="https://www.gracieandrachel.com/?ref=werd.io" rel="noreferrer">Gracie and Rachel</a>, and <a href="https://www.dianepatterson.org/?ref=werd.io" rel="noreferrer">Diane Patterson</a> - all artists I love:</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/BbjCtIaMwBg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="Boundalose - Ani DiFranco w/ Zoe Boekbinder, Gracie and Rachel, and Diane Patterson live on the Mall"></iframe></figure><p>And finally, here's the great <a href="https://woodyguthrie.org/?ref=werd.io" rel="noreferrer">Woody Guthrie</a>, one of my heroes, singing the original:</p><figure class="kg-card kg-embed-card"><iframe width="200" height="150" src="https://www.youtube.com/embed/VwcKwGS7OSQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen title="Woody Guthrie~ All You Fascists Bound To Lose"></iframe></figure>Theatre Review: Hadestown ★★★★★ - Terence Eden’s Bloghttps://shkspr.mobi/blog/?p=706812026-04-27T11:34:27.000Z<p><img src="https://shkspr.mobi/blog/wp-content/uploads/2026/04/hadestown-poster.webp" alt="Poster for Hadestown featuring a hand holding a budding flower." width="256" class="alignleft size-full wp-image-70682"/>
Anaïs Mitchell has created something magical. I felt like giving a standing ovation after every song. Just pure theatrical joy delivered by a cast who know how to squeeze every drop of emotion from an audience.</p>
<p>Perhaps it was sitting right at the front of the stalls, but the opening of Hadestown feels like dinner theatre; almost cosy in its intimacy. The first act is so <em>busy</em> - there are a hundred-and-one things happening on stage that it occasionally becomes overwhelming. The second act is slightly more intimate, but no less dazzling.</p>
<p>Having the musicians on stage lends to the feel of being in a nightclub. The stereo separation makes it easier to pick out the various musical threads and brings a lovely texture to the songs. Also, who knew a trombone could steal a show?</p>
<p>Lots of the cast sing in their natural accents. A roaring northern Hades versus a Mancunian Orpheus makes for quite the thrilling combination. Having subsequently listened to the Broadway cast recording, it is amazing what a positive difference it makes.</p>
<p>And, yes, the obligatory revolve spins the performers on a near-constant merry-go-round. When I am King of the West End, the revolve will be banned for the laze cliché that it is!</p>
<p>A stunning show with a killer soundtrack and a delightful set of performers.</p>
<p>I've written before about how the <a href="https://shkspr.mobi/blog/2024/12/the-art-of-the-pre-show-and-post-show/">pre-show and post-show experience</a> shapes an event. The Lyric theatre is generously sized, so plenty of space to mill about before the show, rather than being crammed into a tiny bar. The toilets weren't in <em>too</em> bad a condition. Once again, no set dressing in the liminal spaces. Would it have been so hard to mock up some travel posters for the eponymous station? Or have something for people to take photos with?</p>
<p>The <a href="https://nimax-theatres.mytoggle.io/shop/hadestown-cocktails-at-the-lyric-theatre">themed cocktail menu was inventive</a> but shockingly expensive, even for London prices. The programme is only a fiver and, unlike other West End shows, is full of interesting information and not just an excuse to cram in adverts - excellent value for money.</p>
<p>After the curtain call, we get a few more minutes with the musicians, which was delightful. On the way out there was no leaflet offering a discount on return visits (unlike <a href="https://shkspr.mobi/blog/2026/04/theatre-review-avenue-q/">Avenue Q</a>). There is, apparently, a "Hadestown Passport" which you can get stamped every visit - although I didn't see any evidence of that.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70681&HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/>Why Is Everything Proprietary These Days? - Kev Quirkhttps://kevquirk.com/why-is-everything-proprietary-these-days2026-04-26T19:21:00.000Z
<p>After 10 years of loyal service, the motorbike jacket that I wear most often gave up the ghost recently and ripped. Being a piece of protective clothing, a rip isn't a good thing, so I've been shopping around for a replacement.</p>
<p>But you see, motorbike jackets are complex, heavy garments that are littered with protective pads. They used to come with back protectors too, but it was later decided that these were too expensive, so you had to buy one separately.</p>
<p>No problem, they're standardised so you buy a good one and it can last you decades. There's just a big void in the back of the jacket with a number of velcro patches that <em>any</em> back protector will cling to.</p>
<p>That's what I have in my old jacket, and I assumed it was still the same now.</p>
<p>So today I bought myself a new jacket. It cost me £380 (on sale!) but you can't put a price on safety, right? I also have protective trousers that zip to my jacket all the way around my waist.</p>
<p>But the zip on my new jacket isn't compatible with the zip on my old trousers (how the fuck can a ZIP be incompatible??) so I bought the matching trousers for the new jacket, costing another £300.</p>
<p>So now I'm £650 lighter in the bank, but I have good quality motorbike clothing that should last me another decade.</p>
<p>This evening I went to swap the back protector from my old jacket to the new, only to find that many manufacturers now have brand-specific pads for their clothing that sit in perfectly sculpted pockets.</p>
<p>The specific back protector (which is a bit of rubber with some holes in it) for my jacket is fifty fucking pounds. So now I'm at £700.</p>
<p><img src="https://kevquirk.com/content/images/why-is-everything-proprietary-these-days/back-protector.webp" alt="back protector" />
<em>Fifty quid's worth of rubber, apparently</em></p>
<p>Fuck that. I've bought a generic (but good quality) one, and I'll cut it to size.</p>
<h2>Vendor lock-in</h2>
<p>Whether it's phones, social networks, communication platforms, printer ink, laptop chargers, smart home systems, games consoles, coffee machines, electric toothbrush heads, camera batteries, or fucking motorbike jacket back protectors. Nothing is interchangeable.</p>
<p>It seems that every day another piece of standardisation is being washed away, and we as consumers need to make our choices, invest, and stick to a brand. You can switch, but it's gonna cost ya!</p>
<p>It's fucking ridiculous.</p>
<p>Over and over again we get shafted, and there's not a single thing we can do about it. I'm so tempted to take the jacket back for a refund, but what do I do then? I <em>need</em> a jacket for riding. I'd be screwed.</p>
<p>Fuck bike jacket manufacturers that do this. Fuck vendor lock-in. Fuck. This.</p>
<p><code></rant></code></p> <div class="email-hidden">
<hr />
<p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p>
<p>You can <a href="mailto:19gy@qrk.one?subject=Why%20Is%20Everything%20Proprietary%20These%20Days%3F">reply to this post by email</a>, or <a href="https://kevquirk.com/why-is-everything-proprietary-these-days#comments">leave a comment</a>.</p>
</div>
Sustaining innovation has failed us. It's time to think more radically - Werd I/O69ed2cad73f6b300016eb5952026-04-25T21:05:49.000Z<p>Link: <a href="https://www.linkedin.com/pulse/three-horizons-framework-government-reform-jennifer-pahlka-9bmdc/?ref=werd.io"><em>A Three Horizons Framework for Government Reform, by Jennifer Pahlka</em></a></p><p>Important analysis from <a href="https://www.recodingamerica.us/?ref=werd.io">Jennifer Pahlka</a>, founder of <a href="https://codeforamerica.org/?ref=werd.io">Code for America</a>, that is about government technology and services but could just as easily be about news and journalism.</p><p>She introduces the <a href="https://www.thinknpc.org/resource-hub/systems-practice-toolkit/the-three-horizons-framework/?ref=werd.io">Three Horizons framework</a> for thinking about change and building towards a shared vision of the future. Here, Horizon 1 is the status quo, Horizon 2 represents improvements to that system, and Horizon 3 represents an improved <em>system</em> rather than an optimized present.</p><p><a href="https://hbr.org/2017/06/the-4-types-of-innovation-and-the-problems-they-solve?ref=werd.io">There are four kinds of innovation</a>: research, sustaining, breakthrough, and disruptive. The first two don’t lead us anywhere new on their own; they might provide extra capacity and create more headroom, but they aren’t systemic change. Any fundamental problems with the status quo probably won’t go away. In contrast, breakthrough innovation brings in fresh ideas to solve problems in a new way, and disruptive innovation creates new systemic models that serve people in new ways.</p><p>Jennifer’s point is that a lot of government reform work — including Code for America — has been sustaining or incremental at best, which has relieved some pressure but hasn’t really changed anything. The same problems persist.</p><p>Philanthropic funding has compounded the problem by funding that kind of innovation instead of more radical solutions. This, for me, is the key sentence in her piece:</p><blockquote>“Funders need to ask not just whether an investment does good but whether it changes the conditions under which good can be done at scale.”</blockquote><p>And there’s a finite window for more aggressive change. This has been created by the AI shift, changes in the US government, the COVID-19 pandemic, and other changes that have highlighted how poorly our current system has adapted.</p><p>In government, that need has become rather obvious, but it’s true in news too — another key part of our civic framework. (And this is also true for social media!) These same factors apply, and philanthropic funding has been similarly risk-averse, aiming for sustaining innovation that builds capacity rather than changing how everything works to serve people better. The fundamentals aren’t changing and they <em>haven’t</em> been serving us. We need to think much more radically, and we need to <em>fund</em> much more radically.</p><p>In that framework, it’s incredibly important to articulate what the more radical futures we could work towards actually are. Jennifer points out that there are multiple, potentially contradictory, possible futures — the point is not to coalesce into one agreed-upon Horizon 3 end state, but to be able to describe where any current change might be leading to. Where is this taking us, and why?</p><p>Let’s allow ourselves to imagine something better. And then, let’s finally go there.</p>AI is not a magic wand and it won’t fix your problems - Werd I/O69ed0c2e73f6b300016eb5892026-04-25T18:47:10.000Z<p>Link: <a href="https://restofworld.org/2026/ai-social-good-humans/?ref=werd.io"><em>Why AI alone cannot fix social problems, by Deepak Varuvel Dennison and Aditya Vashistha in Rest of World</em></a></p><p>From the <em>AI is a tool for people and not a replacement for them</em> dept:</p><blockquote>“AI is often framed as a tool for efficiency, but efficiency alone does not strengthen public systems without the underlying capacity being improved. Even when tasks are completed faster, the deeper constraints of the system do not automatically disappear. In many cases, AI ends up addressing the symptoms of these problems rather than their causes.”</blockquote><p>If an institution — or an industry — is declining, adding AI won’t magically make it better. In the cases that these Cornell researchers highlight in this piece, there were only meaningful improvements when the underlying systems were working well and the human infrastructure around the software was well-developed.</p><p>Even beyond the lack of support for some regional needs (languages, dialects, accents) that created issues here, these systems worked best when the software was designed to support existing well-functioning human systems. If the human systems don’t work, if there isn’t human support, or if people are expected to adapt their processes to the needs of the software, the projects weren’t successful.</p><p>It isn’t a magic wand. There are important lessons here for news and other declining industries: adding software doesn’t absolve you of figuring out your underlying problems, and it will not solve them for you. It might even paper over them and make them worse.</p><p>It’s just another tool. Invest in your people.</p>The world is not a database - Werd I/O69ed086c73f6b300016eb5832026-04-25T18:31:08.000Z<p>Link: <a href="https://www.theverge.com/podcast/917029/software-brain-ai-backlash-databases-automation?ref=werd.io"><em>The People Do Not Yearn For Automation, by Nilay Patel in The Verge</em></a></p><p>This piece is important to internalize — particularly for the terminally AI-pilled and people who might want to force everyone into using LLMs to do work they were previously doing themselves.</p><p>AI is <em>incredibly</em> unpopular, and it’s not because it’s bad at marketing. These are multi billion dollar companies that have attracted some of the brightest talent from across Silicon Valley across all disciplines. AI vendors are not underdogs who just need to get their message across.</p><p>Indeed:</p><blockquote>“You can’t advertise people out of reacting to their own experiences. This is a fundamental disconnect between how tech people with software brains see the world and how regular people are living their lives.”</blockquote><p>“Software brain” is a fantastic name for a worldview that sees everything as databases that can be controlled, normalized, and optimized. As Nilay Patel puts it: “the idea that we can force the real world to act like a computer and then have AI issue that computer instructions.” This is not a new problem that has arrived with AI: we’ve been talking about people who were very good at making software who therefore thought they were geniuses who could take on any global challenge for a very long time.</p><p>Taking human experience, which is beautifully ambiguous and nuanced and nondeterministic, and trying to fit it into a database shape, is inherently extractive. Nilay points out that it flattens people, which is totally true, but it also transfers ownership of that experience from their subjective truth into a centralized database that someone else controls, sets the standards for, and profits from.</p><p>And yes: computers should support people. People shouldn’t support computers. The idea that we’ll all be left behind if we don’t pour our experiences, information, source material, communications, creativity, and all the rest of it into a computer system is absurd and offensive. By extracting that experience, flattening it, and changing ownership of it, it inherently devalues <em>us</em>, the humans who were its previous custodians. It certainly devalues labor, which is a problem in itself, but it also devalues all of the frictionful, living, breathing parts of being an actual human being.</p><p>The tools <em>are</em> useful. I think software development has probably changed forever. But they’re not useful for <em>everything</em>, and they’re not going to change <em>everything</em>. Everything isn’t a database. And if we think the world becomes better if we turn everything into one, we probably weren’t all that excited about humanity to begin with.</p>You can parse an .env file as an .ini with PHP - but there's a catch - Terence Eden’s Bloghttps://shkspr.mobi/blog/?p=686362026-04-25T11:34:15.000Z<p>The humble <code>.env</code> file is a useful and low-tech way of storing persistent environment variables. Drop the file on your server and let your PHP scripts consume it with glee.</p>
<p>But consume it <em>how</em>? There are lots of excellent parsing libraries for PHP. But isn't there a simpler way? Yes! You can use <a href="https://www.php.net/manual/en/function.parse-ini-file.php">PHP's <code>parse_ini_file()</code> function</a> and it works.</p>
<p>But…</p>
<p><code>.env</code> and <code>.ini</code> have subtly different behaviour which might cause you to swear at your computer.</p>
<p>Let's take this example:</p>
<pre><code class="language-env"># This is a comment
USERNAME="edent"
</code></pre>
<p>Run <code>$env = parse_ini_file( ".env" );</code> and you'll get back an array setting the USERNAME to be "edent". Hurrah! Works perfectly. Ship it!</p>
<p>But consider this:</p>
<pre><code class="language-env"># This is a comment
USERNAME="edent" # Don't use an @ symbol here.
</code></pre>
<p>It will happily tell you that the username is <code>"edent# Don"</code></p>
<p>WTAF?</p>
<p>Here's the thing. The comment character for <code>.ini</code> is <strong>not</strong> <code>#</code> - it's the semicolon <code>;</code></p>
<p>Let me give you some other examples of things which will fuck up your parsing:</p>
<pre><code class="language-env"># Documentation at https:/example.com/?doc=123
DOCUMENTATION=123
# Set the password
PASSWORD=qwerty;789
</code></pre>
<p>That gets us back this PHP array:</p>
<pre><code class="language-php">[
'# Documentation at https:/example.com/?doc' => '123',
'DOCUMENTATION' => '123',
'PASSWORD' => 'qwerty',
];
</code></pre>
<p>When the <code>.ini</code> is parsed, it ignores every line which <em>doesn't have an <code>=</code> sign</em>. It also treats literal semicolons as the start of a new comment until they're wrapped in quotes.</p>
<p>My code highlighter should show you how it is parsed:</p>
<pre><code class="language-ini"># Documentation at https:/example.com/?doc=123
DOCUMENTATION=123
# Set the password
PASSWORD=qwerty;789
</code></pre>
<p>It gets worse. Consider this:</p>
<pre><code class="language-env"># Set the "official" name
REALNAME="Arthur, King of the Britons"
</code></pre>
<p>That immediately fails with <code>PHP Warning: syntax error, unexpected '"' in envtest on line 1</code></p>
<p>You can use single quotes in pseudo-comments just fine, but if the ini parser sees a double quote without an equals then it throws a wobbly.</p>
<p>I'm sure there are several other gotchas as well. For example, there are <a href="https://www.w3schools.com/php/func_filesystem_parse_ini_file.asp">certain reserved words and symbols you can't used as a key</a>.</p>
<p>This will fail:</p>
<pre><code class="language-env"># Can we fix it? Yes we can!
FIX=true
</code></pre>
<p>It chokes on the exclamation point.</p>
<h2 id="how-to-solve-it-the-stupid-way"><a href="https://shkspr.mobi/blog/2026/04/you-can-parse-an-env-file-as-an-ini-with-php-but-theres-a-catch/#how-to-solve-it-the-stupid-way">How to solve it (the stupid way)</a></h2>
<p>The comments on an <code>.env</code> file start with a hash.</p>
<p>The comments on an <code>.ini</code> file start with a semicolon.</p>
<p>So, it is perfectly valid for a hybrid file to have its comments start with <code>#;</code></p>
<p>Look, if it's stupid but it works…</p>
<h2 id="what-have-we-learned-here-today"><a href="https://shkspr.mobi/blog/2026/04/you-can-parse-an-env-file-as-an-ini-with-php-but-theres-a-catch/#what-have-we-learned-here-today">What Have We Learned Here Today?</a></h2>
<ul>
<li>There's a right way and a wrong way to do <code>.env</code> parsing.</li>
<li>The wrong way works, up until the point it doesn't.</li>
<li>You should probably use a proper parser rather than hoping your <code>.env</code> looks enough like an <code>.ini</code> to pass muster.</li>
</ul>
<p>On next week's show - why you shouldn't store your passwords inside a JPEG!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=68636&HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/>ThinkPad T480 Initial Thoughts - Kev Quirkhttps://kevquirk.com/thinkpad-t480-initial-thoughts2026-04-25T10:48:00.000Z
<p>Since my Framework had a <a href="https://kevquirk.com/update-on-my-coffee-ridden-framework-13">coffee bath</a>, I've been using a ThinkPad T480 that I picked up from eBay for £285 ($385).</p>
<p>This has been my main laptop for a few days now, and I have some thoughts, so I thought I'd share them since I've read mixed reviews on these plucky little laptops - everything from:</p>
<blockquote>
<p>They're the best laptops in the world, EVARRRRR!</p>
</blockquote>
<p>To:</p>
<blockquote>
<p>They're overrated and overpriced - stop buying them!</p>
</blockquote>
<p>My opinion is that the T480 is somewhere in the middle of these 2 opinions. Let's just in...</p>
<h2>Price and condition</h2>
<p>Like I said, I paid £285 for this laptop, which was listed as <em>very good condition - refurbished"</em>. And I agree - the condition of the laptop is very good, especially considering it's been a corporate laptop and is 8 years old at this point.</p>
<p>It came with a 14" 1080p screen, 16GB RAM, a Core I5-8250U CPU (4 core, 8 thread @ 3.4GHz), a 256GB NVMe, and Windows 11 (which was promptly removed). I had a 1TB NVMe lying around, so I upgraded that first, and I've also bought a 32GB RAM upgrade costing an additional £70 ($95).</p>
<p>The RAM upgrade hasn't been delivered yet, so these thoughts are based on 16GB RAM.</p>
<p><img src="https://kevquirk.com/content/images/thinkpad-t480-initial-thoughts/t480.webp" alt="My T480" />
<em>My T480 (yes, those stickers needs to go)</em></p>
<h2>Design and functionality</h2>
<p>This laptop has <em>bezels for days</em> compared to my Framework, but that's to be expected. It's an old, utilitarian laptop - that didn't stop me getting a bit of a shock when I first cracked it open though. Now I've been using it a few days, the bezels don't bother me though.</p>
<p>I've always liked ThinkPad keyboards, and this is no exception. It works great, and has lots of travel on the keys, which I always appreciate. It's not as nice as the keyboard on my Framework, but I think that's the best keyboard I've ever used, Macbook included.</p>
<p>I'm not a fan of the textured finish that's all over this laptop though. It's on the case, on the keyboard, the trackpad, <em>everywhere</em>. It's like a slightly rubberised, gritty finish. It doesn't impact the functionality of the laptop, I'm just not a big fan of it.</p>
<p>The keyboard is backlit too, which I appreciate.</p>
<h2>Battery and performance</h2>
<p>Honestly, I was expecting the battery to be <em>crap</em> on the T480, being second-hand. But I was so wrong! It came with an extended battery fitted, and on checking it over, it's only had 2 charge cycles, so it brand new.</p>
<p>The battery will last all day, no problem at all. The other day I ran it for an entire working day, and at 15:00 it still had 61% charge left, with Ubuntu reporting another 6.5 hours of use remaining. That's incredible, in my opinion.</p>
<p>Ubuntu runs perfectly on this - all drivers were discovered fine, and I managed to get the fingerprint reader working with just a little bit of DuckDuckGo-fu.</p>
<p>Performance is good too. Everything feels snappy with no lag. Obviously it's not <em>instant</em> like on my Framework, but that thing is a powerhouse. Having said that, I could see myself using the T48 long-term without issue.</p>
<p>I'm currently running Firefox, Spotify, Obsidian, VSCodium, and a few other bits. Here's how the Ubuntu System Monitor looks:</p>
<p><img src="https://kevquirk.com/content/images/thinkpad-t480-initial-thoughts/system-monitor.webp" alt="system-monitor" /></p>
<p>So I'm using about half my RAM, and between 20-40% of the CPU. I don't <em>need</em> to upgrade the RAM, but it's nice to have the extra overhead in case I ever do need it.</p>
<p>I'm not much of a gamer, but the T480 will consistently run Minecraft at 40ish FPS, which is fine, and honestly better than I expected.</p>
<h2>Final thoughts</h2>
<p>Overall I think the T480 was good value for money. It's in really good condition, performs well, and is almost as repairable as my Framework. I think this laptop still has <em>years</em> of life left in it, so will it sit in a drawer once the Framework is repaired?</p>
<p>No, that would be a waste of both money, and a perfectly good laptop. My wife is currently using a 2014 X1 Carbon that I used for many years before <a href="https://kevquirk.com/three-years-with-my-m1-macbook-air">switching to the Macbook M1 Air</a>. The X1 is still going strong, but it's starting to struggle in its old age. Not to mention that my wife is still running Windows 10 on it!</p>
<p>So once the Framework is repaired, I'll be giving this laptop to my wife where it should continue to provide solid service for years to come, all while being a nice upgrade for her. The X1 will get the latest version of Ubuntu installed on it, and will be put out to pasture as the spare laptop for the household.</p>
<p>If you're on the fence about picking a T480 up, I'd say go for it. While they're no powerhouse, and won't win any beauty awards, they're a solid workhorse that still have <em>many</em> years of service left in them.</p>
<p>I'm very happy with my purchase.</p> <div class="email-hidden">
<hr />
<p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p>
<p>You can <a href="mailto:19gy@qrk.one?subject=ThinkPad%20T480%20Initial%20Thoughts">reply to this post by email</a>, or <a href="https://kevquirk.com/thinkpad-t480-initial-thoughts#comments">leave a comment</a>.</p>
</div>
Craft and Artistry - Hey, it's Jason!https://grepjason.sh/2026/craft-and-artistry2026-04-25T00:00:00.000ZThat time I went to a show in Japan by one of my favorite artists! 😱Notable links: April 24, 2026 - Werd I/O69eb6a29d2d9230001cfb88d2026-04-24T13:32:23.000Z<img src="https://images.unsplash.com/photo-1517281862878-d312fe477d71?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wxMTc3M3wwfDF8c2VhcmNofDIyfHxkYXRhJTIwY2VudGVyfGVufDB8fHx8MTc3NzAyNjE0NHww&ixlib=rb-4.1.0&q=80&w=2000" alt="Notable links: April 24, 2026"><p><em>Most Fridays, I share a handful of pieces that caught my eye at the intersection of technology, media, and society.</em></p><p><em>Did I miss something important? </em><a href="mailto:ben@werd.io" rel="noreferrer"><em>Send me an email</em></a><em> to let me know.</em></p><hr><h3 id="the-technological-republic-in-brief"><a href="https://twitter-thread.com/t/2045574398573453312?ref=werd.io" rel="noreferrer">The Technological Republic, in brief</a></h3><p>Palantir CEO Alex Karp wrote a book last year called the Technological Republic, but perhaps because it didn’t have the impact he hoped, the company posted a tweet thread (and <a href="https://www.linkedin.com/pulse/technological-republic-brief-palantir-technologies-ktdde/?ref=werd.io">LinkedIn post</a>, etc) that summarizes its core points. Which are, to be clear, an argument for hard-right nationalism — complete with remilitarization and implied cultural hierarchy — and fusing Silicon Valley with the national security state.</p><p>In Karp’s world, Silicon Valley innovators have an <em>obligation</em> to build weapons through a kind of moral debt to the country. He also wants to see Germany and Japan re-militarized, escalating tensions that will see his company make more money through those arms sales — particularly as his manifesto declares that AI weapons, exactly of the kind he happens to sell, are an inevitable future of military action.</p><p>He says we should be more tolerant of billionaires and scrutinize their private lives less, while being less tolerant of other cultures. He declares that no nation has advanced progressive values more than the US (a tough sell in itself), but then recites a litany of anti-progressive ideas. He takes time to defend Elon Musk by name.</p><p>He also furthers the idea that people who further progressive ideas are some kind of “elite”, instead of what they actually are: people from all slices of life, including working class unions, who want to have a more inclusive, more peaceful society.</p><p>Bellingcat founder Eliot Higgins has <a href="https://bsky.app/profile/eliothiggins.bsky.social/post/3mjtpunycuk2h?ref=werd.io">a great Bluesky thread</a> that lays out the issues plainly:</p><blockquote>“Point 21 is the giveaway, some cultures produce "wonders," others are "regressive and harmful." Once you accept that hierarchy, you've quietly been given permission to apply different standards of verification to different actors. The form of verification stays, but the democratic function doesn’t.<br><br>This is what verification looks like once national identity sits above method. Rigorous when it's pointed at adversaries, conveniently absent when it's pointed at us. Symmetric, evidence-led investigation of allied conduct, exactly what Bellingcat does, becomes the thing the worldview can't tolerate”</blockquote><p>In short, I find this offensive, often contradictory, and terrifying in equal measure. It makes clear that Palantir, its associates, and companies like it (Anduril, for example) are a threat to a democratic, peaceful, inclusive society. There’s no point in being cautious or pulling punches; it must be opposed.</p><hr><h3 id="%E2%80%9Cdata-embassies%E2%80%9D-and-safeguarding-digital-assets-during-wartime"><a href="https://restofworld.org/2026/gulf-war-data-center-risks/?ref=werd.io" rel="noreferrer">“Data embassies” and safeguarding digital assets during wartime</a></h3><p>Among the targets in the war between Iran and the US have been data centers. AWS was hit by drones, and Iran has threatened to target US tech. This piece makes the point that these buildings don’t just store vast amounts of civilian customer data: increasingly, they store military data, too. That make them an even more attractive target and makes the security consequences of an attack that much worse.</p><p>Meanwhile, data centers — including here in Pennsylvania, where I live, as well as Chile, India, and many other places around the world — have been the cause of significant objections from local populations. They push energy costs up, have a serious environmental footprint, <a href="https://www.cnn.com/2026/03/30/climate/data-centers-are-having-an-underrported?ref=werd.io">and can even change the local climate</a>.</p><p>So why have these giant megascale data centers at all?</p><blockquote>““It’s very possible that we see a move away from hyperscalers to small data centers for greater safety,” [Viktor Mayer-Schoenberger, professor of internet governance and regulation at the University of Oxford] said. “Lots of small data centers with randomly distributed backup copies of data are more resilient – but harder and more complex to build, more costly to maintain, and less effective, as data needs to be kept up to date not just in one or two centers, but in many.””</blockquote><p>The latter half of Mayer-Schoenberger’s claim is true if we cling to the same architectures. But if we embrace more decentralization on the architectural level as a founding premise, some of these inefficiencies become less of a problem. It could even be worth it to companies like AWS to build new underlying services that make decentralization easier: abstractions that allow data to be sharded across distributed data stores, and that make secure communication between distributed nodes easier.</p><p>That’s clearly necessary if we move to smaller data centers: a smaller venue can’t simply hold a copy of all the same data as the larger ones but in more places. It also opens up the possibility for mesh application layers rather than the monolithic mainframe-style architectures we’ve mostly seen on the cloud. Behind the scenes, cloud services are a sea of proprietary micro services and components; building more distributed architectures could more easily allow each component to be built, hosted, and supported by different entities.</p><p>Regardless, the change is an interesting thing to think about, and the cause for it is sobering. What <em>does</em> data infrastructure look like in an increasingly antagonistic world — one with more war, accelerated climate change, and authoritarian threats? Those considerations will need to be built into the internet at a backbone level, and into its applications from the ground up.</p><hr><h3 id="flare-before-you-focus"><a href="https://pointc.co/flare-before-you-focus/?ref=werd.io" rel="noreferrer">Flare Before You Focus</a></h3><p>Corey Ford’s advice on <a href="https://pointc.co/always-separate-flaring-and-focusing/?ref=werd.io">separating flaring and focusing</a> is something I draw on every workday: it prevents self-editing, allows more creative ideas to flourish, and helps enforce a more rigorous creative process. But as he points out here, to encourage curiosity on your team, you’ve got to model it yourself.</p><p>I have been in this meeting so many times:</p><blockquote>“Two people, both in Focus mode, talking across each other, each trying to prove they have the sharper analysis. Everyone in the room thinks they're having a robust debate. What they're actually having is two monologues masquerading as a conversation. […] They're asking themselves, How do I make sure everyone knows I'm smart?”</blockquote><p>The thing is, when everyone is coming into a brainstorm with genuine curiosity, and when everyone has the right to share and ideate without the outcome being predetermined, it’s genuinely more fun. It’s certainly more inclusive. And when it’s both of those things, you get more interesting ideas. If you “yes and” those ideas and model what it looks like to build with curiosity, you get more of them. It’s a virtuous circle.</p><p>Conversely, if you’re coming in with predetermined ideas, or you set the tone of a meeting to be evaluative rather than collaborative, people won’t speak up. The output becomes monocultural. Or, at its worst, you get the kind of posturing that Corey described above: a culture where people want to be recognized for being smart rather than helping to get to the best possible outcome.</p><p>It helps to be genuinely curious; playful; maybe risk being a little bit unserious. Then people start to loosen up, and that’s when the good stuff starts coming.</p><hr><h3 id="the-content-management-system-is-dead-long-live-the-context-management-system"><a href="https://www.hackshackers.com/cms-is-dead-long-live-the-context-management-system/?ref=werd.io" rel="noreferrer">The Content Management System Is Dead. Long Live the Context Management System.</a></h3><p>I thought this demo, by Hacks / Hackers founder Burt Herman, was pretty compelling. It’s obviously a proof of concept, but it points to some interesting places journalism could go, and it opens up some new platform questions in the process.</p><p>In Burt’s vision, the reader has a profile that expresses their interests, and then the newsroom curates material that is surfaced using that lens. His demo makes that more concrete: <a href="https://nyc-mayor-context-demo-2026.hackshackers.com/?ref=werd.io">here he’s pointed an engine at communications from New York City Mayor Mamdani’s office</a>, and set up personas like “renter in Bushwick” and “parent in Park Slope” that are served a briefing drawn from different information depending on that persona’s particular lens. A parent in Park Slope receives more information about schools in that neighborhood; a retiree in the West Village receives information about their neighborhood but also about services that pertain to them.</p><p>You can easily imagine how this might scale up to a newsroom. An engine like this doesn’t have to be limited to source material as in Burt’s demo: it could also be journalistic investigations, interviews, and net-new content created by skilled reporters. In some ways it’s a vision for a better homepage (often among the least-visited parts of a news website) more than a redefinition of journalism itself, except in the sense that surfacing more raw material is welcome.</p><p>There are so many interesting questions to consider — many of which dovetail with ideas that have been tackled outside news for years.</p><p>For example: if a reader creates a profile, where does that live? Is it on the news website, in which case they have to create a new profile every time they read another site? Or does it live in the browser, so that the user creates their profile once and consents to share it with the various sites they read? People have been working on browser-based identity, and now identity for agentic users, for a long time. It may make sense to apply that work here.</p><p>Where should the briefing live? Is it a news website’s homepage, as I’ve surmised above, or is it actually also at the browser or news reader level, drawing not just from <em>one</em> newsroom, but <em>all</em> the newsrooms a user reads? And if it’s the latter, how does the newsroom retain credit, get compensated, and build a first-party relationship with the reader?</p><p>I also think there’s an obvious business model here: when a user has created a profile <em>for themselves</em>, it’s just as easy to say that they’re in the market for a car, or that they enjoy single-origin coffee beans. Then you can serve useful sponsored content (like deals) to people who actually want to buy those things, which is both significantly more valuable to an advertiser and more consensual / less adversarial for a reader. It brings newsrooms very close to the <a href="https://customercommons.org/?ref=werd.io">Customer Commons</a> ideas that people like <a href="https://doc.searls.com/?ref=werd.io">Doc Searls</a> have been talking about for many years.</p><p>I agree with Burt’s warning here:</p><blockquote>“For publishers and journalists who ignore this: Don't be surprised when human readers stop coming to your websites and mobile apps. Not because the journalism is bad, but because it's more efficient to send an AI agent to gather what you've published, sift out what's truly relevant to the user's own context, and reassemble it in whatever format works best for them.”</blockquote><p>What might a version of this future that centers reader needs but does it in alignment with the newsroom’s needs and values look like? It’s a good time to start experimenting.</p><hr><h3 id="launching-xoxo-explore"><a href="https://xoxofest.com/blog/2026-launching-xoxo-explore/?ref=werd.io" rel="noreferrer">Launching XOXO Explore</a></h3><p>I freaking loved XOXO, the experimental festival for independent artists and creators from the internet. I attended <a href="https://xoxofest.com/2012/?ref=werd.io">the first one</a> during a fraught, stressful, often sad period of my life; I’d ripped my life up to move to the US to be nearer to my terminally ill mother. I thought I knew where my life was going, and then everything was uncertain.</p><p>And here was this joyful festival of people doing things on their own terms, in their own way. I attended with my partner at the time, who was visiting back from the UK, and we discovered Portland itself in the process. We played Johann Sebastian Joust with Dan Harmon. Ben Brown, who I had followed for years, silently sidled up at an arcade and played the 1990s <em>X-Men</em> cabinet game with me. We had a beer with MC Frontalot. And felt home in a way I desperately needed to.</p><p>Clearly, a ton of work went into this archive site, which contains almost every talk. (One in particular was too sensitive to record.) I’m grateful that this exists. I can <a href="https://xoxofest.com/2012/videos/maggie-vail-jesse-von-doom/?ref=werd.io">relive Maggie Vail and Jesse Von Doom’s CASH Music talk</a>; relive one of my childhood heroes, Tim Schafer, <a href="https://xoxofest.com/2013/videos/tim-schafer/?ref=werd.io">talking about his work</a>; and see talks from years I couldn’t attend by people I am in awe of like <a href="https://xoxofest.com/2024/videos/molly-white/?ref=werd.io">Molly White</a> and <a href="https://xoxofest.com/2024/videos/erin-kissane/?ref=werd.io">Erin Kissane</a>. It’s really worth plumbing the archive; it’s all good stuff.</p><p>It <em>can’t</em> show me the absolutely insane Q&A with the <a href="https://xoxofest.com/2024/videos/erin-kissane/?ref=werd.io">Don’t Hug Me I’m Scared</a> team ("...How?" "Because!"), or remind me or chatting with Cory Doctorow, or let me cuddle a baby goat again. But I can remember. And this is a lovely start.</p><p>Bonus link: <a href="https://werd.io/xoxo-crafty-makers-from-the-future/">here’s how I wrote about the first event at the time</a>.</p><hr><h3 id="copyright-and-dmca-best-practices-for-fediverse-operators"><a href="https://www.eff.org/deeplinks/2026/04/copyright-and-dmca-best-practices-fediverse-operators?ref=werd.io" rel="noreferrer">Copyright and DMCA Best Practices for Fediverse Operators</a></h3><p>A useful guide for anyone who is running their own community space — which includes folks running Mastodon instances, Bluesky hosts, RSS services, and so on. As the author explains in the preamble, there’s the potential for “massive, unpredictable financial liability”. It’s therefore really important to find ways to limit risk.</p><p>A lot of this is common sense:</p><blockquote>“Finally, make sure that nothing you post or advertise actively encourages copyright infringement. For example, don’t post examples of users uploading copyrighted music or video without permission, or insinuate that your server is a good place for infringing content.”</blockquote><p>Some of it is less obvious but still important. For example, responding promptly to DMCA notices — and not ignoring them regardless of technicalities — is one place where a less-savvy operator might fall over.</p><p>It’s easy to imagine compliance as a service for these kinds of operators, baked into the platforms themselves. So if you install a Mastodon instance and you could be subject to US law (which isn’t limited to instances operating in the US), there could be an easy way to set up with a service to handle all that for you. It could sit right alongside trust and safety services that are more aligned for community safety.</p>In wartime, megascale data centers may make way for distributed architectures - Werd I/O69eb702ed2d9230001cfb8ac2026-04-24T13:29:18.000Z<p>Link: <a href="https://restofworld.org/2026/gulf-war-data-center-risks/?ref=werd.io"><em>“Data embassies” and safeguarding digital assets during wartime, by Rina Chandran in Rest of World</em></a></p><p>Among the targets in the war between Iran and the US have been data centers. AWS was hit by drones, and Iran has threatened to target US tech. This piece makes the point that these buildings don’t just store vast amounts of civilian customer data: increasingly, they store military data, too. That make them an even more attractive target and makes the security consequences of an attack that much worse.</p><p>Meanwhile, data centers — including here in Pennsylvania, where I live, as well as Chile, India, and many other places around the world — have been the cause of significant objections from local populations. They push energy costs up, have a serious environmental footprint, <a href="https://www.cnn.com/2026/03/30/climate/data-centers-are-having-an-underrported?ref=werd.io">and can even change the local climate</a>.</p><p>So why have these giant megascale data centers at all?</p><blockquote>““It’s very possible that we see a move away from hyperscalers to small data centers for greater safety,” [Viktor Mayer-Schoenberger, professor of internet governance and regulation at the University of Oxford] said. “Lots of small data centers with randomly distributed backup copies of data are more resilient – but harder and more complex to build, more costly to maintain, and less effective, as data needs to be kept up to date not just in one or two centers, but in many.””</blockquote><p>The latter half of Mayer-Schoenberger’s claim is true if we cling to the same architectures. But if we embrace more decentralization on the architectural level as a founding premise, some of these inefficiencies become less of a problem. It could even be worth it to companies like AWS to build new underlying services that make decentralization easier: abstractions that allow data to be sharded across distributed data stores, and that make secure communication between distributed nodes easier.</p><p>That’s clearly necessary if we move to smaller data centers: a smaller venue can’t simply hold a copy of all the same data as the larger ones but in more places. It also opens up the possibility for mesh application layers rather than the monolithic mainframe-style architectures we’ve mostly seen on the cloud. Behind the scenes, cloud services are a sea of proprietary micro services and components; building more distributed architectures could more easily allow each component to be built, hosted, and supported by different entities.</p><p>Regardless, the change is an interesting thing to think about, and the cause for it is sobering. What <em>does</em> data infrastructure look like in an increasingly antagonistic world — one with more war, accelerated climate change, and authoritarian threats? Those considerations will need to be built into the internet at a backbone level, and into its applications from the ground up.</p>Does Mythos mean you need to shut down your Open Source repositories? - Terence Eden’s Bloghttps://shkspr.mobi/blog/?p=705992026-04-24T11:34:30.000Z<p>Much <i lang="de">Sturm und Drang</i> in the world of Open Source with the announcement that <a href="https://www.scientificamerican.com/article/what-is-mythos-and-why-are-experts-worried-about-anthropics-ai-model/">the "Mythos" AI is now the ultimate hacker</a> and is poised to unleash havoc on every code base.</p>
<p>So should you close all your Open Source projects to make them safe?</p>
<p>No.</p>
<p>Firstly, all your Open Source code has <em>already</em> been slurped up.</p>
<p>It was all ingested for "training purposes" years ago. If it was moderately interesting then it was backed-up by a digital hoarder. It has been archived by various digital libraries. Anyone who wants to do research on your code base can.</p>
<p>Closing now doesn't meaningfully protect you.</p>
<p>Secondly, most of the security holes in your systems are <em>probably</em> not in your code. Vulnerabilities exist throughout your supply chain. All the dependencies - your OS, libraries, and even hardware - are all richer targets for hackers. Finding a CVE in a popular library is almost certainly more worthwhile than investigating <em>your</em> Open Source code.</p>
<p>The bigger risk comes not from subtle logic bugs but from phishers, poor password hygiene, and insider threats. Securing your existing systems provides more protection than rushing to close-source your code.</p>
<p>Finally, closing the source of something doesn't protect you. These new AI models can easily investigate and your closed source systems and potentially penetrate them. It has always been possible to analyse websites and binaries. AI doesn't change that - although it might accelerate it.</p>
<p>Open Source does have risks but AI doesn't upend decades of evidence that closed-source is just as vulnerable to attackers.</p>
<p>In cases where the state creates code using public money, <a href="https://publiccode.eu/en/">it has a responsibly to share that code</a>. Automated threat analysis - even by hypercapabe AI - doesn't change that.</p>
<p>I would strongly recommend reading the UK's AI Safety Institute's <a href="https://www.aisi.gov.uk/blog/our-evaluation-of-claude-mythos-previews-cyber-capabilities">evaluation of Claude Mythos Preview’s cyber capabilities</a> and the <a href="https://www.ncsc.gov.uk/blogs/why-cyber-defenders-need-to-be-ready-for-frontier-ai">NCSC's advice</a>. Neither of them recommend closing down Open Source code.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=70599&HTTP_REFERER=Atom" alt="" width="1" height="1" loading="eager"/>XOXO Explore is fitting showcase for a brilliant experiment - Werd I/O69eacb03d2d9230001cfb87b2026-04-24T01:44:35.000Z<p>Link: <a href="https://xoxofest.com/blog/2026-launching-xoxo-explore/?ref=werd.io"><em>Launching XOXO Explore, by the Andys</em></a></p><p>I freaking loved XOXO, the experimental festival for independent artists and creators from the internet. I attended <a href="https://xoxofest.com/2012/?ref=werd.io">the first one</a> during a fraught, stressful, often sad period of my life; I’d ripped my life up to move to the US to be nearer to my terminally ill mother. I thought I knew where my life was going, and then everything was uncertain.</p><p>And here was this joyful festival of people doing things on their own terms, in their own way. I attended with my partner at the time, who was visiting back from the UK, and we discovered Portland itself in the process. We played Johann Sebastian Joust with Dan Harmon. Ben Brown, who I had followed for years, silently sidled up at an arcade and played the 1990s <em>X-Men</em> cabinet game with me. We had a beer with MC Frontalot. And felt home in a way I desperately needed to.</p><p>Clearly, a ton of work went into this archive site, which contains almost every talk. (One in particular was too sensitive to record.) I’m grateful that this exists. I can <a href="https://xoxofest.com/2012/videos/maggie-vail-jesse-von-doom/?ref=werd.io">relive Maggie Vail and Jesse Von Doom’s CASH Music talk</a>; relive one of my childhood heroes, Tim Schafer, <a href="https://xoxofest.com/2013/videos/tim-schafer/?ref=werd.io">talking about his work</a>; and see talks from years I couldn’t attend by people I am in awe of like <a href="https://xoxofest.com/2024/videos/molly-white/?ref=werd.io">Molly White</a> and <a href="https://xoxofest.com/2024/videos/erin-kissane/?ref=werd.io">Erin Kissane</a>. It’s really worth plumbing the archive; it’s all good stuff.</p><p>It <em>can’t</em> show me the absolutely insane Q&A with the <a href="https://xoxofest.com/2024/videos/erin-kissane/?ref=werd.io">Don’t Hug Me I’m Scared</a> team ("...How?" "Because!"), or remind me or chatting with Cory Doctorow, or let me cuddle a baby goat again. But I can remember. And this is a lovely start.</p><p>Bonus link: <a href="https://werd.io/xoxo-crafty-makers-from-the-future/">here’s how I wrote about it at the time</a>.</p>Budget friendly tech isn't what it used to be - Joel's Log Fileshttps://joelchrono.xyz/blog/budget-friendly-isn't-what-it-used-to-be2026-04-23T23:26:26.000Z<html><head><style>
.notice::before {
content: "IN REPLY TO:";
color: var(--bg);
background: var(--border);
width: 12rem;
display: inline-block;
text-align: center;
position: relative;
left: 1.5rem;
top: 1.5rem;
padding: 2px 10px;
font-weight: bold;
}
#notice{
border: none;
padding: 0;
font-style: normal;
margin: 0;
position: relative;
}
</style>
</head><body><blockquote id="notice">
<div class="notice">
<article class="post_embed">
<h2>Apple and affordability</h2>
<p><i>A €700 laptop is not cheap, a €700 phone is not cheap. My iPhone SE from 2022 cost €500 and it wasn't cheap either given what it had to offer. The price may be lower in comparison with other products from the brand and the prices of modern technology—which are madness. They may offer a good value for the money. That seems to be the case for this laptop. But it is not cheap.</i></p>
<p><a href="https://adrianperales.com/2026/04/apple-y-lo-barato/">Read the Full Post</a>
by <a href="https://masto.es/@aperalesf">Adrián Perales</a>
on <a href="https://adrianperales.com/">adrianperales.com</a></p>
</article>
</div>
</blockquote>
<p>I saw this post (originally in Spanish, title and quote translated by me) which dealt with something that I used to think a lot more, but sort of accepted given my current situation, but the more I thought about it, I kind of hate it.</p>
<p>Back in the day, I used to watch phone reviews that recommended budget friendly devices. Stuff like the Redmi 4A and 5A were the kings of low-budget gadgets, at a price around $100 bucks. That was the first phone I ever paid for, and 18-year-old me only had <em>half</em> of that money, my dad to paid the rest, and even that was too much for him. He wasn’t being greedy, but my previous phone still worked, so it was not a necessary purchase.</p>
<p>The flagship smartphones at the time? $500 bucks or so, the base iPhone 7? $650 USD, the one with 256 GB of storage? $969 USD. We both know storage wasn’t worth that much, but even then the Apple markup was acting up. The high tier was expensive, and it still is. Like Adrian, I am extremely surprised when I see people saying the Macbook Neo is “budget-friendly.”</p>
<p>I’ve said before how I am often disconnected <a href="https://joelchrono.xyz/blog/cultural-outsider/">from my own culture</a>, as a Latino who mostly interacts with American/English-speaking communities online and watches video reviews from people living there.</p>
<p>The people in my country who buy a Macbook Neo are either part of the upper class—or in debt. After all, owning an Apple device is a status symbol, for some reason, and even those who can’t afford it what those bragging rights.</p>
<p>The average person where I live has a two or three year old device that they got used from Facebook Marketplace, a chinese device from Oppo, Poco, Honor, Xiaomi or maybe Motorola. People will buy the flagship devices from these brands and think they are expensive and great quality. And yeah, they often have much better feature than Apple or Samsung products, even if riddled with tracking and advertising.</p>
<p>Alas, such brands are at a price people are actually willing to pay, as much as I don’t like it.</p>
<p>I’ve bought devices and things from China and chinese websites. Let’s talk the Miyoo Mini Plus, the Anbernic RG35XX SP, The Miyoo Mini Flip and the XTEINK X4, and all of them have been at under $70 USD. All of them are extremely affordable and found for even cheaper during sales.</p>
<p>Some of that price may be lowered because Chinese companies overwork people or do shady business practices, but reality is that the markup of most modern tech sold from more popular brands on this side of the globe are simply off the charts. A clear middle ground with a sensible approach can’t be that hardcan right? But no, just look at the “minimalist” devices out there, all above 300, 400, 600 bucks and they are hardly worth that much, the marketing is more expensive than the hardware itself, I suspect.</p>
<p>I guess most big tech review channels seem to just take this for granted, 700 bucks for an Apple laptop? Very cheap, sure.</p>
<p>The worst is that they barely mention actually cheap stuff. Personally, I think they realized that people who watch phone reviews for a living like to see expensive stuff—that they won’t buy—more than cheap stuff—that they won’t buy anyway, so they go and make that kind of content to appease the algorithm and get more revenue. Also cheap stuff has compromises which are often negative, so brands don’t like those to be brought up, even if at the price they are justified.</p>
<p>The people who genuinely look for reviews for actually budget devices are usually confined to content from smaller channels or from creators from India where those devices are more popular. Nothing wrong with that, of course, it’s a similar situation to Latin America, the concept of “budget friendly” is more akin to reality, and those reviews tend to be more honest anyway.</p>
<p>Right now I’m thankful for my current situation, which is rather privileged—single and without any debts—allowing me the purchasing power to consider expensive tech (as long as it isn’t Apple) among my options (although I would still probably go for whatever is cheaper or has better design). Still, I’d love if we recalibrated what “value for money” actually means, and what sort of hardware is actually enough, so we can stop allowing these companies to raise prices for no reason.</p>
<p>This is day 56 of <a href="https://100daystooffload.com">#100DaysToOffload</a></p>
<p>
<a href="mailto:me@joelchrono.xyz?subject=Budget friendly tech isn't what it used to be">Reply to this post via email</a> |
<a href="https://fosstodon.org/@joel/116456730959054822">Reply on Fediverse</a>
</p>Untitled - Posts feedhttps://www.coryd.dev/2026-04-23T17:16:51.000ZThe user-tailored newsroom - Werd I/O69ea2593d2d9230001cfb8682026-04-23T13:58:43.000Z<p>Link: <a href="https://www.hackshackers.com/cms-is-dead-long-live-the-context-management-system/?ref=werd.io"><em>The Content Management System Is Dead. Long Live the Context Management System., by Burt Herman at Hacks / Hackers</em></a></p><p>I thought this was a pretty compelling demo. It’s obviously a proof of concept, but it points to some interesting places journalism could go, and it opens up some new platform questions in the process.</p><p>In Burt’s vision, the reader has a profile that expresses their interests, and then the newsroom curates material that is surfaced using that lens. His demo makes that more concrete: <a href="https://nyc-mayor-context-demo-2026.hackshackers.com/?ref=werd.io">here he’s pointed an engine at communications from New York City Mayor Mamdani’s office</a>, and set up personas like “renter in Bushwick” and “parent in Park Slope” that are served a briefing drawn from different information depending on that persona’s particular lens. A parent in Park Slope receives more information about schools in that neighborhood; a retiree in the West Village receives information about their neighborhood but also about services that pertain to them.</p><p>You can easily imagine how this might scale up to a newsroom. An engine like this doesn’t have to be limited to source material as in Burt’s demo: it could also be journalistic investigations, interviews, and net-new content created by skilled reporters. In some ways it’s a vision for a better homepage (often among the least-visited parts of a news website) more than a redefinition of journalism itself, except in the sense that surfacing more raw material is welcome.</p><p>There are so many interesting questions to consider — many of which dovetail with ideas that have been tackled outside news for years.</p><p>For example: if a reader creates a profile, where does that live? Is it on the news website, in which case they have to create a new profile every time they read another site? Or does it live in the browser, so that the user creates their profile once and consents to share it with the various sites they read? People have been working on browser-based identity, and now identity for agentic users, for a long time. It may make sense to apply that work here.</p><p>Where should the briefing live? Is it a news website’s homepage, as I’ve surmised above, or is it actually also at the browser or news reader level, drawing not just from <em>one</em> newsroom, but <em>all</em> the newsrooms a user reads? And if it’s the latter, how does the newsroom retain credit, get compensated, and build a first-party relationship with the reader?</p><p>I also think there’s an obvious business model here: when a user has created a profile <em>for themselves</em>, it’s just as easy to say that they’re in the market for a car, or that they enjoy single-origin coffee beans. Then you can serve useful sponsored content (like deals) to people who actually want to buy those things, which is both significantly more valuable to an advertiser and more consensual / less adversarial for a reader. It brings newsrooms very close to the <a href="https://customercommons.org/?ref=werd.io">Customer Commons</a> ideas that people like <a href="https://doc.searls.com/?ref=werd.io">Doc Searls</a> have been talking about for many years.</p><p>I agree with Burt’s warning here:</p><blockquote>“For publishers and journalists who ignore this: Don't be surprised when human readers stop coming to your websites and mobile apps. Not because the journalism is bad, but because it's more efficient to send an AI agent to gather what you've published, sift out what's truly relevant to the user's own context, and reassemble it in whatever format works best for them.”</blockquote><p>What might a version of this future that centers reader needs but does it in alignment with the newsroom’s needs and values look like? It’s a good time to start experimenting.</p>Update on My Coffee Ridden Framework 13 - Kev Quirkhttps://kevquirk.com/update-on-my-coffee-ridden-framework-132026-04-23T13:43:00.000Z
<p>A week or so ago, I talked about how <a href="https://kevquirk.com/i-may-have-killed-my-framework-13">I might have killed my Framework 13</a> by dumping a full mug of coffee over it while it was running.</p>
<p>In that last post I explained how I'd stripped the laptop down and was waiting for some isopropyl alcohol (IPA) to be delivered so I could more thoroughly clean it. Well dear reader, the IPA turned up, I cleaned it as best I could, and left it for 24 hours to dry off.</p>
<p>The next day I came back to it, re-assembled it and hit the power button with a fair amount of trepidation.</p>
<p><strong>Nothing.</strong></p>
<p>I think it's dead, Jim. And I can't help thinking that turning the laptop on in haste, after the first clean is what completely screwed it. Oh well, we live and learn.</p>
<p>In my desperation, I contacted Framework support and explained the whole saga to see if there was anything I was missing.</p>
<p>There wasn't. They told me that the LED pattern I was seeing when powered on was indicative of a communication error with the board, so it's dead and needed to be replaced.</p>
<p>Problem is, a new board is £700 (~$950) and I didn't fancy shelling out that much money out of my own pocket, so I contacted my home insurance provider to make a claim, and to be fair they were great.</p>
<p>A case was logged and a couple of days later I had a payout that would cover the whole amount.</p>
<h2>The new board and a ThinkPad</h2>
<p>The payout from the insurance was more than the repair cost, so I decided to upgrade from my current Ryzen 7 7840, to an AI 300 series board instead - nice little upgrade!</p>
<p>The Framework site said it would be shipped in 5 days, and would probably be subject to delays of a further 7 days due to global freight disruptions. So I bought myself a ThinkPad T480 to see me through (which I'm typing this post on) as I couldn't bear to be on MacOS for another second.</p>
<p>Framework overachieved again and the board is due for delivery tomorrow (Friday 24th April 2026).</p>
<p>Nice!</p>
<p>Once the board is delivered and my beloved Framework is (hopefully) working again, this nice little ThinkPad will go to my wife as an upgrade from here 2014(!) Gen 2 X1 Carbon.</p>
<h2>How did it die?</h2>
<p>I've had a few people reach out telling me that they'd done something similar and their device's had survived. Unfortunately I wasn't as lucky, so what happened?</p>
<p>I <em>think</em> it's because I didn't spill the coffee <em>on</em> my laptop, but <em>next</em> to it. Then as the puddle of coffee made its way over my desk and inevitably under my laptop, the spinning fan must have sucked it up and perfectly spread the coffee all over the main board.</p>
<p>Thanks for that. Stupid fan. 🤣️</p>
<p>Had I spilled the coffee <em>on</em> my laptop, it would have had to make its way through the keyboard and chassis before it got to the board, by which point I would have had the laptop switched off and draining.</p>
<p>I can't say for sure, but that's my theory.</p>
<p>So anyway, wish my luck with the new board, folks!</p> <div class="email-hidden">
<hr />
<p>Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️</p>
<p>You can <a href="mailto:19gy@qrk.one?subject=Update%20on%20My%20Coffee%20Ridden%20Framework%2013">reply to this post by email</a>, or <a href="https://kevquirk.com/update-on-my-coffee-ridden-framework-13#comments">leave a comment</a>.</p>
</div>
It pays to reward curiosity more than looking smart - Werd I/O69ea1e7cd2d9230001cfb85c2026-04-23T13:28:28.000Z<p><em>Link: </em><a href="https://pointc.co/flare-before-you-focus/?ref=werd.io"><em>Flare Before You Focus, by Corey Ford at Point C</em></a></p><p>Corey’s advice on <a href="https://pointc.co/always-separate-flaring-and-focusing/?ref=werd.io">separating flaring and focusing</a> is something I draw on every workday: it prevents self-editing, allows more creative ideas to flourish, and helps enforce a more rigorous creative process. But as he points out here, to encourage curiosity on your team, you’ve got to model it yourself.</p><p>I have been in this meeting so many times:</p><blockquote>“Two people, both in Focus mode, talking across each other, each trying to prove they have the sharper analysis. Everyone in the room thinks they're having a robust debate. What they're actually having is two monologues masquerading as a conversation. […] They're asking themselves, How do I make sure everyone knows I'm smart?”</blockquote><p>The thing is, when everyone is coming into a brainstorm with genuine curiosity, and when everyone has the right to share and ideate without the outcome being predetermined, it’s genuinely more fun. It’s certainly more inclusive. And when it’s both of those things, you get more interesting ideas. If you “yes and” those ideas and model what it looks like to build with curiosity, you get more of them. It’s a virtuous circle.</p><p>Conversely, if you’re coming in with predetermined ideas, or you set the tone of a meeting to be evaluative rather than collaborative, people won’t speak up. The output becomes monocultural. Or, at its worst, you get the kind of posturing that Corey described above: a culture where people want to be recognized for being smart rather than helping to get to the best possible outcome.</p><p>It helps to be genuinely curious; playful; maybe risk being a little bit unserious. Then people start to loosen up, and that’s when the good stuff starts coming.</p><p>[<a href="https://pointc.co/flare-before-you-focus/?ref=werd.io">Link</a>]</p>Trailmark turns code into graphs - Trail of Bits Bloghttps://blog.trailofbits.com/2026/04/23/trailmark-turns-code-into-graphs/2026-04-23T12:00:00.000Z<p>We’re open-sourcing <a href="https://github.com/trailofbits/trailmark">Trailmark</a>, a library that parses source code into a queryable call graph of functions, classes, call relationships, and semantic metadata, then exposes that graph through a Python API that Claude skills can call directly. Install it now:</p>
<p><code>uv pip install trailmark</code></p>
<p>“Defenders think in lists. Attackers think in graphs. As long as this is true, attackers win.” John Lambert’s <a href="https://github.com/JohnLaTwC/Shared/blob/master/Defenders%20think%20in%20lists.%20Attackers%20think%20in%20graphs.%20As%20long%20as%20this%20is%20true%2C%20attackers%20win.md">widely cited observation</a> about network security applies just as well to AI-assisted software analysis.</p>
<p>When Claude reasons about a codebase, it reasons about lists: findings from static analyzers, surviving mutants from mutation testing, and line-by-line coverage reports. But the question that actually matters is a graph question: <em>can untrusted input reach this code, and what breaks if it’s wrong?</em></p>
<p>We built Trailmark to answer that question. It gives Claude a graph to think with instead of a list. We’re also releasing eight Claude Code skills we’ve built on top of it, designed for mutation triage, test vector generation, protocol diagramming, and more.</p>
<h2 id="when-lists-fall-short">When lists fall short</h2>
<p>Mutation testing is a great example of a method that benefits from graph-level reasoning. It’s one of the best ways to measure test quality. It makes small changes to your source code (e.g., swapping a <code><</code> for <code><=</code>, replacing <code>+</code> with <code>-</code>) and checks whether your tests catch the difference. Mutants that survive reveal gaps in your test suite that code coverage metrics might miss. The downside is that a mutation testing run on a real codebase can produce hundreds of surviving mutants of varying significance. This is very much a <em>list</em>.</p>
<p>Some surviving mutants are <em>equivalent</em>: the mutation doesn’t change the program’s behavior because of structural or mathematical constraints that the mutation testing tool can’t see. Some are in dead code; some are in error message formatting; some are in the finite field arithmetic that underpins every cryptographic operation in your library. A flat list of surviving mutants doesn’t tell you which is which.</p>
<p>We wanted to know whether Claude could use graph-level reasoning about a codebase to automatically triage surviving mutants by security relevance: which are reachable from untrusted input, which affect high-blast-radius functions, and which represent genuine gaps in security-critical code?</p>
<h2 id="how-trailmark-works">How Trailmark works</h2>
<p>Trailmark uses <a href="https://tree-sitter.github.io/">tree-sitter</a> for language-agnostic AST parsing and <a href="https://www.rustworkx.org/">rustworkx</a> for high-performance graph traversal. It operates in three phases:</p>
<ol>
<li><strong>Parse</strong>: Walk a directory, extract functions, classes, call edges, type annotations, cyclomatic complexity, and branch counts from source code.</li>
<li><strong>Index</strong>: Load the resulting graph into a rustworkx PyDiGraph with bidirectional ID/index mappings for fast traversal.</li>
<li><strong>Query</strong>: Answer questions: callers, callees, all paths between two nodes, attack surface enumeration, and complexity hotspots.</li>
</ol>
<p>It currently supports 17 languages, including C, Rust, Go, Python, PHP, JavaScript, Solidity, Circom, and Miden Assembly.</p>
<p>The graph is the substrate. The skills are where the analysis happens.</p>
<h2 id="the-skills">The skills</h2>
<p>The Trailmark plugin ships eight Claude Code skills that use the graph API as their backbone:</p>
<table>
<thead>
<tr>
<th>Skill</th>
<th>What it does</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>trailmark</code></td>
<td>Build and query a code graph with pre-analysis passes: blast radius, taint propagation, privilege boundaries, and entrypoint enumeration</td>
</tr>
<tr>
<td><code>diagram</code></td>
<td>Generate Mermaid diagrams from code graphs: call graphs, class hierarchies, complexity heatmaps, data flow</td>
</tr>
<tr>
<td><code>crypto-protocol-diagram</code></td>
<td>Extract protocol message flow from source code or specs (RFCs, ProVerif, Tamarin) into annotated sequence diagrams</td>
</tr>
<tr>
<td><code>genotoxic</code></td>
<td>Triage mutation testing results using graph analysis: classify surviving mutants as equivalent, missing test coverage, or fuzzing targets</td>
</tr>
<tr>
<td><code>vector-forge</code></td>
<td>Mutation-driven test vector generation: find coverage gaps via mutation testing, then generate Wycheproof-style vectors that close them</td>
</tr>
<tr>
<td><code>graph-evolution</code></td>
<td>Compare code graphs at two snapshots to surface security-relevant structural changes that text diffs miss</td>
</tr>
<tr>
<td><code>mermaid-to-proverif</code></td>
<td>Convert Mermaid sequence diagrams into ProVerif formal verification models</td>
</tr>
<tr>
<td><code>audit-augmentation</code></td>
<td>Project SARIF and weAudit findings onto code graph nodes as annotations, enabling cross-referencing of static analysis results with blast radius and taint data</td>
</tr>
</tbody>
</table>
<p>Each skill calls the Trailmark Python API directly. When <code>genotoxic</code> triages a surviving mutant, it queries <code>engine.paths_between</code> to check reachability from untrusted input. When <code>diagram</code> generates a complexity heatmap, it calls <code>engine.complexity_hotspots</code>. The graph is what makes those questions answerable in seconds rather than hours of manual tracing.</p>
<p>Trailmark also ingests SARIF output from static analyzers and <a href="https://blog.trailofbits.com/2024/03/19/read-code-like-a-pro-with-our-weaudit-vscode-extension/">weAudit</a> annotations, mapping external findings onto graph nodes by file and line range. This lets Claude layer static analysis results, audit notes, and mutation testing data onto a single unified graph, then query across all of them.</p>
<h2 id="what-claude-found">What Claude found</h2>
<p>We’ve been using these skills internally on several cryptographic libraries, combining graph analysis with language-appropriate mutation testing frameworks. Here’s what the graph let Claude see that flat lists couldn’t.</p>
<h3 id="equivalent-mutants-are-the-majority-in-well-tested-crypto">Equivalent mutants are the majority in well-tested crypto</h3>
<p>When we ran mutation testing against an Ed448 implementation in Go, 45 mutants survived out of 583 covered. A flat list of 45 surviving mutants looks like a serious test gap. But when Claude used the Trailmark call graph (332 nodes, 3,259 call edges) to triage via <code>genotoxic</code>, 33 of those 45 (73%) were equivalent mutants. The mutations were unobservable because the code’s mathematical structure constrained values more tightly than the explicit bounds checks that were mutated.</p>
<p>For example, nine surviving mutants modified boundary conditions in NAF (non-adjacent form) digit range checks. These look like real bugs in isolation. But the NAF digits are structurally bounded by the <code>nonAdjacentForm</code> algorithm itself: the values that would trigger the altered boundary can never appear. The graph confirmed these functions were called from specific contexts that made the mutations undetectable.</p>
<p>The 12 genuine gaps were concrete and actionable: a cross-package coverage gap where Go’s coverage profiling attributed execution to the calling package instead of the defining package, a 255-byte context string boundary condition that was never tested, and overflow carry paths in wide-integer parsing that required near-maximum input values that no existing test vector produced.</p>
<h3 id="architectural-bottlenecks-are-invisible-without-a-graph">Architectural bottlenecks are invisible without a graph</h3>
<p>When Claude built a Trailmark graph of <code>libhydrogen</code>, a compact C cryptographic library, the graph immediately highlighted something that wasn’t obvious from linearly reading the source files: the entire library funnels through a single permutation primitive, <code>gimli_core_u8</code>, which receives 37 direct calls. Every cryptographic operation (hashing, encryption, key exchange, signatures, and password hashing) depends on this one function.</p>
<p>This isn’t a bug. It’s a deliberate design choice common in lightweight crypto libraries. But it means the blast radius of a flaw in Gimli is total. The graph quantified this: a mutation in <code>gimli_core_u8</code> affects 100% of the library’s security-critical functionality. Gimli was also eliminated from the NIST Lightweight Cryptography competition. Together, these facts represent the kind of architectural risk that’s invisible in a line-by-line code review. The graph makes it obvious.</p>
<h3 id="mutation-testing-finds-what-kats-cant-cover">Mutation testing finds what KATs can’t cover</h3>
<p>For standardized algorithms like Ed25519 or ML-KEM, known-answer tests (KATs) and projects like <a href="https://github.com/google/wycheproof">Wycheproof</a> provide test vectors that exercise edge cases. But for novel constructions (libhydrogen’s combination of Gimli and Curve25519, for instance), independent KATs don’t exist. No one has published “if you give Gimli-based AEAD this input, you should get this output” vectors, because the construction is unique to this library.</p>
<p>This is where mutation testing fills the gap. It doesn’t need reference implementations or published test vectors. It tests whether <em>your</em> tests actually constrain <em>your</em> code’s behavior. The surviving mutants tell you exactly which aspects of the implementation aren’t pinned down by your test suite, regardless of whether anyone else has ever tested that specific construction.</p>
<p>In the RustCrypto/KEMs crates (ML-KEM, X-Wing), <code>vector-forge</code> found that seven surviving mutants targeted NTT multiplication (mutations like replacing <code>*</code> with <code>+</code> in polynomial dot products). These survived because the test suite only exercised NTT through full KEM round-trips. The algebraic properties of NTT were never tested directly. Existing Wycheproof vectors and NIST KATs caught most higher-level issues, but the internal algebraic invariants had no direct coverage.</p>
<h3 id="three-patterns-that-showed-up-everywhere">Three patterns that showed up everywhere</h3>
<p>Across multiple codebases analyzed with Trailmark, the same patterns emerged:</p>
<ul>
<li>
<p><strong>Blast radius concentrates in arithmetic modules.</strong> In libsodium (1,597 nodes, 9,574 call edges), the ed25519_ref10 module had the highest blast radius, underpinning Ed25519 signatures, Curve25519 key exchange, Ristretto255, and X-Wing KEM. In ML-KEM, the algebra module had a blast radius of 28; every polynomial and matrix operation depended on its Elem arithmetic. Graph analysis consistently identified these modules as the highest-priority targets for thorough testing.</p>
</li>
<li>
<p><strong>Codec parsers are high-value fuzzing targets that rarely get prioritized.</strong> Multiple analyses flagged hex/Base64 decoders and IP address parsers as high-complexity functions with external input exposure. libsodium’s <code>parse_ipv6</code> had a cyclomatic complexity of 18; libhydrogen’s <code>hydro_hex2bin</code> was the most complex function in the entire library, with a cyclomatic complexity of 11. These functions are natural targets for fuzzing, and the graph confirms they’re reachable from untrusted input.</p>
</li>
<li>
<p><strong>Property-based testing is sparse.</strong> Across the Rust cryptographic crates we examined, property-based testing was either absent or incomplete. The KEMs crates had zero property-based tests. Barrett reduction in ML-KEM was tested with only five points, even though exhaustive testing over all 11 million values of q = 3329 is computationally feasible. The graph’s blast radius analysis shows where property-based tests would have the greatest impact.</p>
</li>
</ul>
<h2 id="connecting-the-graph-to-everything-else">Connecting the graph to everything else</h2>
<p>The graph is most useful when it serves as the connective tissue between other analysis tools. When the constant-time analysis skill flags a function, Trailmark tells Claude its blast radius. When mutation testing produces survivors, Trailmark tells Claude which ones are reachable from untrusted input. When an auditor annotates a finding in weAudit, <code>audit-augmentation</code> shows what else in the graph is affected.</p>
<p>We use this internally to write targeted fuzzing harnesses. The graph identifies high-complexity functions reachable from external input; mutation testing identifies which of those functions have test gaps; the combination tells Claude exactly where a fuzzing harness will have the highest marginal value.</p>
<h2 id="start-querying-your-codebase">Start querying your codebase</h2>
<p>Trailmark is open source under <a href="https://github.com/trailofbits/trailmark">Apache-2.0</a>. The library is on PyPI; the skills plugin is in the same repository.</p>
<p><strong>Install the library</strong> (required by the skills):</p>
<figure class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">uv pip install trailmark</span></span></code></pre>
</figure>
<p><strong>Add the skills to Claude Code:</strong></p>
<figure class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">/plugin marketplace add trailofbits/skills</span></span></code></pre>
</figure>
<p>Then select the Trailmark plugin from the menu.</p>
<p>You can also explore the graph directly from the CLI:</p>
<figure class="highlight">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Full JSON graph</span>
</span></span><span class="line"><span class="cl">trailmark analyze path/to/project
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Analyze a specific language</span>
</span></span><span class="line"><span class="cl">trailmark analyze --language rust path/to/project
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Complexity hotspots</span>
</span></span><span class="line"><span class="cl">trailmark analyze --complexity <span class="m">10</span> path/to/project</span></span></code></pre>
</figure>
<p>Or call the Python API to build your own skills on top of the graph:</p>
<figure class="highlight">
<pre tabindex="0" class="chroma"><code class="language-py" data-lang="py"><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">trailmark.query.api</span> <span class="kn">import</span> <span class="n">QueryEngine</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">engine</span> <span class="o">=</span> <span class="n">QueryEngine</span><span class="o">.</span><span class="n">from_directory</span><span class="p">(</span><span class="s2">"path/to/project"</span><span class="p">,</span> <span class="n">language</span><span class="o">=</span><span class="s2">"c"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># What's reachable from this entrypoint?</span>
</span></span><span class="line"><span class="cl"><span class="n">engine</span><span class="o">.</span><span class="n">callees_of</span><span class="p">(</span><span class="s2">"handle_request"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Call paths from entrypoint to sensitive function</span>
</span></span><span class="line"><span class="cl"><span class="n">engine</span><span class="o">.</span><span class="n">paths_between</span><span class="p">(</span><span class="s2">"handle_request"</span><span class="p">,</span> <span class="s2">"crypto_verify"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Functions with cyclomatic complexity >= 10</span>
</span></span><span class="line"><span class="cl"><span class="n">engine</span><span class="o">.</span><span class="n">complexity_hotspots</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Run pre-analysis (blast radius, taint, privilege boundaries)</span>
</span></span><span class="line"><span class="cl"><span class="n">engine</span><span class="o">.</span><span class="n">preanalysis</span><span class="p">()</span></span></span></code></pre>
</figure>
<p>The graph API is designed to be called by skills, not just humans. If you’re building Claude Code skills for security analysis, code review, or test generation, Trailmark gives you the structural substrate to ask questions that lists can’t answer.</p>
<p>Seventeen languages. A graph, not a list. <a href="https://github.com/trailofbits/trailmark">The code is on GitHub</a>.</p>