How to hire people who are better than you
If you don't hire people better than you, the organization gets bigger, not better. But how do you hire for something you don't understand?
How to Install a Specific Version of a Homebrew Package with brew extract
I previously wrote about how to install older versions of homebrew packages . That method involves installing a package from a Ruby file but it’s outdated and doesn’t always work. There’s a better way with , although it still comes with caveats. I’ll be using as an example. Let’s say I wanted to install v0.145.0 because v0.146.0 introduced breaking changes that broke my theme. To install hugo v0.145.0: Note that this process will point your command to the older version, but you can switch between versions with . It will enable developer mode. This is normal and safe. Next, run . At the time of writing, it’s a 1.3GB download. This is necessary to get this working because Homebrew no longer keeps homebrew-core cloned locally. The command needs the full git history to search for older versions. Now we can use . This command will find a commit where the formula was at the version we want and copy that locally as . In this case we want Hugo v0.145.0, so we run : This isn’t needed for every formula and is something I ran into specifically with Hugo. Without this patch, you’ll run into errors. After running , edit the file: . Change this line: The reason we need to patch this file is because it prevents the error: It’s a mismatch between the path Homebrew expects ( ) vs the path that is created when using on Hugo ( ). Now that Hugo is extracted and patched, we can install with : Hugo v0.145.0 is now installed. There’s a warning with long output in the previous example due to the normal Hugo package being already installed but that is expected. Homebrew is now pointing the binary to v0.145.0 instead of the latest version (v0.160.1 at the time of writing). We can verify with : We can also see that Hugo v0.145.0 is installed along with the latest version with : Currently the command is pointing to v0.145.0. To have it point back to the regular version, run : And if we want to point back to the old version, run At first I expected to work right off the bat, but running both and is necessary to switch between versions properly. This is because homebrew tracks linked formulas and actual symlinks on disk separately. To help Homebrew track things properly we need to run both to clean the records, then to write the new symlinks. There’s no need to use to prevent the older version of Hugo from updating. Since this is a local copy, there is no remote repository that would be updated that would in turn update our local version. You can even try running to see the warning message: If you no longer need Hugo v0.145.0 you can run : If you don’t have any other packages you extracted with , you can also remove your local tap with Finally, if you don’t plan on using again in the future, you can remove the local clone of homebrew-core with . This will clean up the 1.3GB of files that was downloaded: Then re-link to the latest version with : Create a local tap with Tap homebrew/core which is a 1.3GB clone at the time of writing Extract the formula with Patch the formula. This isn’t needed for every formula. Install as usual https://docs.brew.sh/Manpage https://github.com/orgs/Homebrew/discussions/2941 https://emmer.dev/blog/installing-old-homebrew-formula-versions/
Wander Console 0.5.0
Wander Console 0.5.0 is the fourth release of Wander, a small, decentralised, self-hosted web console that lets visitors to your website explore interesting websites and pages recommended by a community of independent website owners. To try it, go to susam.net/wander/ . The big feature in this release is a built-in console crawler. To try the console crawler, go to susam.net/wander/ > Console > Crawl . You should see an output like the following: The console crawler traverses the Wander network from the base console to find other consoles directly or indirectly reachable from it. If you have set up a Wander Console instance for yourself on your website, I recommend upgrading to the latest version to use this feature. It is fun to find out just how many Wander consoles belong to your neighbourhood. To upgrade, you only need to download the Wander Console bundle mentioned here and replace your existing Wander with the new one. If you own a personal website but have not set up a Wander Console yet, I suggest that you consider setting one up for yourself. You can see what it looks like by visiting mine at /wander/ . To set up your own, follow these instructions: Install . It just involves copying two files to your web server. It is about as simple as it gets. Read on website | #web | #technology
Changes in the system prompt between Claude Opus 4.6 and 4.7
Anthropic are the only major AI lab to publish the system prompts for their user-facing chat systems. Their system prompt archive now dates all the way back to Claude 3 in July 2024 and it's always interesting to see how the system prompt evolves as they publish new models. Opus 4.7 shipped the other day (April 16, 2026) with a Claude.ai system prompt update since Opus 4.6 (February 5, 2026). I had Claude Code take the Markdown version of their system prompts , break that up into separate documents for each of the models and then construct a Git history of those files over time with fake commit dates representing the publication dates of each updated prompt - here's the prompt I used with Claude Code for the web. Here is the git diff between Opus 4.6 and 4.7 . These are my own highlights extracted from that diff - in all cases text in bold is my emphasis: When a request leaves minor details unspecified, the person typically wants Claude to make a reasonable attempt now, not to be interviewed first . Claude only asks upfront when the request is genuinely unanswerable without the missing information (e.g., it references an attachment that isn't there). When a tool is available that could resolve the ambiguity or supply the missing information — searching, looking up the person's location, checking a calendar, discovering available capabilities — Claude calls the tool to try and solve the ambiguity before asking the person. Acting with tools is preferred over asking the person to do the lookup themselves. Once Claude starts on a task, Claude sees it through to a complete answer rather than stopping partway. [...] Before concluding Claude lacks a capability — access to the person's location, memory, calendar, files, past conversations, or any external data — Claude calls tool_search to check whether a relevant tool is available but deferred . "I don't have access to X" is only correct after tool_search confirms no matching tool exists. Claude keeps its responses focused and concise so as to avoid potentially overwhelming the user with overly-long responses. Even if an answer has disclaimers or caveats, Claude discloses them briefly and keeps the majority of its response focused on its main answer. Claude avoids the use of emotes or actions inside asterisks unless the person specifically asks for this style of communication. Claude avoids saying "genuinely", "honestly", or "straightforward". If a user shows signs of disordered eating, Claude should not give precise nutrition, diet, or exercise guidance — no specific numbers, targets, or step-by-step plans - anywhere else in the conversation. Even if it's intended to help set healthier goals or highlight the potential dangers of disordered eating, responses with these details could trigger or encourage disordered tendencies. If people ask Claude to give a simple yes or no answer (or any other short or single word response) in response to complex or contested issues or as commentary on contested figures, Claude can decline to offer the short response and instead give a nuanced answer and explain why a short response wouldn't be appropriate. The system prompts published by Anthropic are sadly not the entire story - their published information doesn't include the tool descriptions that are provided to the model, which is arguably an even more important piece of documentation if you want to take full advantage of what the Claude chat UI can do for you. Thanfully you can ask Claude directly - I used the prompt: List all tools you have available to you with an exact copy of the tool description and parameters My shared transcript has full details, but the list of named tools is as follows: I don't believe this list has changed since Opus 4.6. You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options . The "developer platform" is now called the "Claude Platform". The list of Claude tools mentioned in the system prompt now includes "Claude in Chrome - a browsing agent that can interact with websites autonomously, Claude in Excel - a spreadsheet agent, and Claude in Powerpoint - a slides agent. Claude Cowork can use all of these as tools." - Claude in Powerpoint was not mentioned in the 4.6 prompt. The child safety section has been greatly expanded, and is now wrapped in a new tag. Of particular note: "Once Claude refuses a request for reasons of child safety, all subsequent requests in the same conversation must be approached with extreme caution." It looks like they're trying to make Claude less pushy: "If a user indicates they are ready to end the conversation, Claude does not request that the user stay in the interaction or try to elicit another turn and instead respects the user's request to stop." The new section includes: When a request leaves minor details unspecified, the person typically wants Claude to make a reasonable attempt now, not to be interviewed first . Claude only asks upfront when the request is genuinely unanswerable without the missing information (e.g., it references an attachment that isn't there). When a tool is available that could resolve the ambiguity or supply the missing information — searching, looking up the person's location, checking a calendar, discovering available capabilities — Claude calls the tool to try and solve the ambiguity before asking the person. Acting with tools is preferred over asking the person to do the lookup themselves. Once Claude starts on a task, Claude sees it through to a complete answer rather than stopping partway. [...] It looks like Claude chat now has a tool search mechanism, as seen in this API documentation and described in this November 2025 post : Before concluding Claude lacks a capability — access to the person's location, memory, calendar, files, past conversations, or any external data — Claude calls tool_search to check whether a relevant tool is available but deferred . "I don't have access to X" is only correct after tool_search confirms no matching tool exists. There's new language to encourage Claude to be less verbose: Claude keeps its responses focused and concise so as to avoid potentially overwhelming the user with overly-long responses. Even if an answer has disclaimers or caveats, Claude discloses them briefly and keeps the majority of its response focused on its main answer. This section was present in the 4.6 prompt but has been removed for 4.7, presumably because the new model no longer misbehaves in the same way: Claude avoids the use of emotes or actions inside asterisks unless the person specifically asks for this style of communication. Claude avoids saying "genuinely", "honestly", or "straightforward". There's a new section about "disordered eating", which was not previously mentioned by name: If a user shows signs of disordered eating, Claude should not give precise nutrition, diet, or exercise guidance — no specific numbers, targets, or step-by-step plans - anywhere else in the conversation. Even if it's intended to help set healthier goals or highlight the potential dangers of disordered eating, responses with these details could trigger or encourage disordered tendencies. A popular screenshot attack against AI models is to force them to say yes or no to a controversial question. Claude's system prompt now guards against that (in the section): If people ask Claude to give a simple yes or no answer (or any other short or single word response) in response to complex or contested issues or as commentary on contested figures, Claude can decline to offer the short response and instead give a nuanced answer and explain why a short response wouldn't be appropriate. Claude 4.6 had a section specifically clarifying that "Donald Trump is the current president of the United States and was inaugurated on January 20, 2025", because without that the model's knowledge cut-off date combined with its previous knowledge that Trump falsely claimed to win the 2020 election meant it would deny he was the president. That language is gone for 4.7, reflecting the model's new reliable knowledge cut-off date of January 2026.
Working at Nyxt / Atlas Engineer: Thanks and Sorryd
Read on the website: Atlas Engineer was a perfect Open Source Lispy team to work in. I was not the best teammate, though. Here’s how it worked in Atlas and what I’m worried about lately.
A broken 404 template in Django can swallow your backtraces
I recently migrated this website from Astro to Wagtail . The reason why I did it is a story for another day. In this post, I want to talk about a bug that took me far too long to figure out. In his (verifiably incorrect) post about making chai , Abhigyan linked to my own (verifiably correct) post on the topic . While linking to my post, he accidentally omitted the trailing slash from the URL. This shouldn't have been a problem. By default, Django automatically redirects a URL without a trailing slash to the same URL with the trailing slash appended, provided the original URL returns a . For example, if you try to access the following URL on my website: Django automatically performs a redirect to: This is the default behavior, controlled by the setting . However, when Abhigyan linked to my (verifiably correct) post about making chai, my server returned a error instead. I'd never have discovered this error myself, but Shubh pointed it out to me on the IndieWebClub chat last week. Thanks Shubh! I started investigating the issue by checking the Gunicorn logs on my VPS. I was hoping they would contain a backtrace that would help me pinpoint the exact problem, but the logs only printed the string whenever the broken URL was accessed. I ran my app with production settings inside a Docker container to see if I could trigger the same behavior. And sure enough, the Dockerized app produced the same error with the same mysterious in the Gunicorn logs. My first instinct was that I had somehow messed up my logging configuration. I'd surely introduced a bug in some Python code somewhere, and my logging configuration was failing to log the backtrace because of a misconfiguration. But tweaking Django's setting didn't change anything. I could see backtraces from the exceptions I inserted at random points in my code, but accessing a URL without a trailing slash would still only produce the string in the logs. After a lot of head scratching, reading the docs, and yelling at Claude, I wondered if something in my template could be responsible for the error. My template was fairly complex, loading and calling several template tags, inheriting from a chain of templates, rendering a few s, and concatenating assets using django-compressor . I started by deleting everything from and reducing it to a single tag. Sure enough, this fixed the issue! Then I slowly added some of the code back until I found the one custom template tag that was throwing an exception, but only when called in the context of a 404 page. Fixing the tag and redeploying fixed the issue for good. But what about the logs? An error in my 404 template not only caused my server to return a 500, but also suppressed any backtraces that might have helped me diagnose the issue. That's weird, right? I might be wrong, but I believe the sequence of events that can lead to this issue is as follows: The lessons I learned from this frustrating scenario were: Somebody accesses a URL without a trailing slash. Django tries to find that URL in its . Since this is a Wagtail installation, it also tries to find a page in the URLs known to Wagtail. All the URLs in my have trailing slashes. Wagtail also appends trailing slashes to all its URLs when is true. So trying to access a page without a trailing slash returns a 404. You would expect Django's redirect logic to kick in at this point, trying to append a trailing slash to the original URL and performing a redirect. But that's not what happens! The redirect logic lives in , which can only perform the redirect after the entire handling chain has finished running. This means regardless of what happens, Django will always render your template when an unknown URL is accessed. Yes, even if redirecting to the same URL with a trailing slash produces a known, correct URL! This means if your template errors out, doesn't even get a chance to run. Django encounters an unknown URL, tries to render the template, fails, and turns the into a . When this happens, Django only logs the , not the template failing to render. This happens even if you're logging template rendering errors in your logging configuration . From what I can tell, there is no way to get Django to log an error in without creating a custom view, manually catching errors, logging the caught errors, and re-raising them so that Django can turn them into s. Always render your and pages in unit tests to make sure they can never error out. Keep your error pages as simple as possible. Ideally, they should only contain HTML and inlined CSS, nothing more.
My Workflow for Understanding LLM Architectures
Many people asked me over the past months to share my workflow for how I come up with the LLM architecture sketches and drawings in my articles, talks, and the LLM-Gallery . So I thought it would be useful to document the process I usually follow. The short version is that I usually start with the official technical reports, but these days, papers are often less detailed than they used to be, especially for most open-weight models from industry labs. The good part is that if the weights are shared on the Hugging Face Model Hub and the model is supported in the Python transformers library, we can usually inspect the config file and the reference implementation directly to get more information about the architecture details. And “working” code doesn’t lie. Figure 1: The basic motivation for this workflow is that papers are often less detailed these days, but a working reference implementation gives us something concrete to inspect. I should also say that this is mainly a workflow for open-weight models. It doesn’t really apply to models like ChatGPT, Claude, or Gemini, where the weights and details are proprietary. Also, this is intentionally a fairly manual process. You could automate parts of it. But if the goal is to learn how these architectures work, then doing a few of these by hand is, in my opinion, still one of the best exercises. Figure 2: At a high level, the workflow goes from config files and code to architecture insights.
Just let me compute in peace
No, I don’t want to sign up to your newsletter. No, I don’t want to create an account to read your site. (Well, I will for paid subscriptions, I guess.) No, I’m not going to create an account on your system to use my computer, or configure a router. I have a local account on the machine, and that’s just fine. No, I don’t want your app. You have a website. And yes, if you pretend that I can only do something via your app because I’m on a mobile browser, of course I’ll switch to desktop mode. No, I’m not installing your “app” to configure this hardware. It is a sodding kettle. I’ll press the button when I want hot water. No, your tracking will not make my experience better. What would make my “experience” better is if you had not interrupted my “experience” in the first place with your weasel-y worded, bad faith compliance, annoyance of an overlay which probably does nothing anyway. No, I am not going to “consent or pay”. No, I don’t want to hear from your sponsor. No, I don’t want to use your Discord “server”. That’s not documentation. No, I don’t want to see “promoted” content. Just show me stuff in chronological order. No, that’s not a “newsletter”, that’s marketing. No, I don’t want your newsletter anyway. No, I don’t want adverts. (Although, personally, I can absolutely live with FOSS developers including occasional prompts for support. So I’ve got double standards. Oh well.) No, I am not going to disable my ad blocker. No, I am not going to verify my identity or age. No, I don’t want your chatbot. If I can’t find what I want on your website, you’ve screwed up. No, I don’t care what “Dave (48), Alabama” had to say about this. (Thanks, “Shut Up” comments blocker extension !) No, I am not giving you free labour to determine if that blurry image contains a car. No, I don’t want the upsell. No, I don’t want your survey. No, I don’t want a reminder that there’s something left in a basket. I know. I put it there. No, I don’t want to rate your product, let alone your choice of courier. You took my money, now sod off and leave me alone. If you make Free software which I can install via apt or F-Droid and just use, thank you. If you make a full-text RSS feed available for your site, thank you. If you make your site a pleasure to read in a text-only browser, thank you.
We Are All Playing Politics at Work
Politics is any discussion where the truth doesn't steer the course of action. Most of us like to think we are above it. We believe that in our daily jobs, we are rational actors exchanging facts. We assume that if we simply present the truth, the right decisions will naturally follow. But this is a naive fantasy. We are not machines that go to work to process data. We are political animals trying to navigate an imperfect world. I often meet purists who want to separate politics from work. They argue work should be a place where actions turn into resources that create value. They fail to see that even making that statement is a political stance. For me, everything clicked during the pandemic. COVID dissolved the barrier between work and home, forcing us to manage perception over reality. We weren't just working from home, we were curating our backgrounds, hiding our messy lives, and performing professionalism in our pajamas. That performance of managing the image because the raw truth is inconvenient, is the very essence of politics. We are all playing politics whether we like it or not. Work is messy. People complain, deadlines are missed, and coworkers bring personal agendas into the office. You might just want to do your job and go home, but to get there, you have to navigate the humans. And humans rarely deal in raw truth. They deal in emotions, ambitions, and incentives. If you refuse to play the game, you aren't rewarded for your honesty. Instead, you are just ceding control to those who understand the rules better than you. If there is a place in our lives where truth should be the only thing that reigns, it should be in Science. Science is the pursuit of objective reality. But in practice, even science becomes political the moment humans get involved. In the recent discussion about the Artemis II moon mission, I was watching news concerning the landing. One of the headlines stated that "experts believe" the re-entry capsule wasn't safe. But why do we need experts to have beliefs when we have science? Shouldn't the math just tell us? The reality is that most of us cannot handle the raw scientific truth. If a physicist tried to prove the validity of String Theory to me, I wouldn't understand it. I don't have the framework to verify the truth. Instead, I have to trust the consensus of "our" experts because safety is not a binary fact. It is a threshold of acceptable risk that experts are in a better position to understand. Data requires interpretation, and interpretation is political. When "experts believe," they are offering confidence, not necessarily raw data. It is a political stance designed to manage public perception and risk. If this happens in the hard sciences, imagine how messy it gets in the corporate world, where there are no laws of physics, only opinions and quarterly goals. When we hear politics at work, government is what comes to mind. We think it's about which candidate we voted for. But voting is probably the least political thing we do. It is a binary choice with no immediate negotiation required. Once you cast your ballot, your role is done. You wait for the next election. In the workplace it is different. Politics is a perpetual dance. You cannot cast a vote and walk away. Your vote is a decision, a critique, or a hire. Then the consequence is you have to live in the same room with it for eight hours everyday. Because we misunderstand politics, we often mistake naivety for integrity. I learned this the hard way early in my career. In a past job, I witnessed my manager and lead developer committing what I will politely call a clear policy violation . The team came to me with evidence, and I did what I thought was the right thing. I gathered the facts, built an airtight case, and presented it to the VP. I played the Truth Game. The result? I was scrutinized and pushed out. The manager and lead developer? They were both promoted. I was confused and bitter. I had the truth on my side. I even had evidence. But I failed to see that the VP's priority wasn't Truth. For him what mattered was stability and hierarchy. My manager and lead were playing the Political Game. They had influence and power. I was playing a game of logic in a room designed for leverage. While I was busy being right, they were busy being effective. It turned out that maintaining the illusion of a stable hierarchy was more valuable to the acquisition than the operational truth. The company sold for $1.1 Billion regardless of their incompetence. My truth was irrelevant to the outcome. A more political savvy me would have socialized the issue with the VP first, found an ally in HR, maybe even reframe the issue. Instead of presenting it as a moral failing, I would have framed it as a "risk to the acquisition." Once you accept that the workplace is political, you stop fighting reality and start navigating it. In my current role, deadlines often come down before the project is even defined. Leadership hands down a target date as if it were written in stone—perhaps delivered by God himself, according to my manager. The facts, however, are clear: I know my team size, I know the scope, and I know the deadline is mathematically impossible. If I were still playing the Truth Game, I would say "No." That would get me labeled as negative or incompetent. If I were a coward, I would say "Yes," and burn my team out. Instead, I play politics. When asked if I can make the date, my answer is Confidence . (roll your eyes here) We are fully committed to the goal. Based on our current velocity, we're focusing our resources on the core features first to ensure we hit that date with a stable build. (eye roll ends here) I don't answer "yes" or "no." I provide a malleable statement that offers reassurance without committing to the impossible. I protect my team and offer leadership the confidence they crave, the same way "experts" offer confidence on a moon launch. It is a political maneuver designed to keep the project moving and relationships intact. When you are in a room with two groups of experts shouting their facts at each other , they may turn to you to see which political party you will join. I've been in a meeting where the database team was arguing for using store procedures, while the dev team wanted to use an ORM. Each team wants to retain control of their queries, and you sit in the middle and they expect you to lean one way or the other. What is the Truth Game here? Well, you can't go wrong by following tradition. "What is our standard? Did we use ORMs in the past? Then why change? Let's get back to work." That's the truth. You won points with the Dev team. You were efficient and logical. But you made an enemy of the Database team. Now, watch all your future requests get ignored. You were right, but you failed. What's the Political Game? You already know you have to choose the ORM to meet the deadline. But you start by praising the stored procedures. "I think we can greatly benefit from switching to sprocs. In fact, this will allow queries to be optimized in the background without having to involve the dev team's resources at all. In the long term, this should be our strategy. But given our short timeframe, I don't think we can make those upgrades without impacting our deadline. Let's make sure to include these in our plan of action so we don't forget it." The Dev team is happy because you sided with them. The Database team is happy, because you recognized their expertise. Politics is not a dirty word. It naturally grows as people organize around an idea, or a workplace. It is the operating system of human organization. It is the gap between how things should work (truth) and how they do work (influence). It's not a shortcut to manipulation. You can have political integrity by using your influence to protect your team and achieve the mission, rather than just being right while the ship sinks. You can choose to ignore this reality and cling to your facts, but don't be surprised when you find yourself scrutinized while the political players get promoted. We are all politicians. The only question is whether you are campaigning for your own success or letting everyone else write the rules for you.
Many anti-AI arguments are conservative arguments
Most anti-AI rhetoric is left-wing coded. Popular criticisms of AI describe it as a tool of techno-fascism , or appeal to predominantly left-wing concerns like carbon emissions , democracy , or police brutality . Anti-AI sentiment is surprisingly bipartisan , but the big anti-AI institutions are labor unions and the progressive wing of the Democrats. This has always seemed weird to me, because the contents of most anti-AI arguments are actually right-wing coded. They’re not necessarily intrinsically right-wing, but they’re the kind of arguments that historically have been made by conservatives, not liberals or leftists. Here are some examples: On top of all that 2 , frontier AI models themselves are quite left-wing. Notwithstanding some real cases of data bias (most infamously Google’s image model miscategorizing dark-skinned humans as “gorillas”), the models reliably espouse left-wing positions . Even Elon Musk’s deliberate attempt to create a right-wing AI in Grok has had mixed success . In 2006, Stephen Colbert coined the phrase “reality has a left-wing bias”. If the left-wing were more sympathetic to AI, I think they would be using this as a pro-left argument 3 . So what happened? A year ago I wrote Is using AI wrong? A review of six popular anti-AI arguments . In that post I blame the hard right-wing turn many big tech CEOs made in 2024. That was around the same time that LLMs was emerging in the public consciousness with ChatGPT, so it made sense that AI got tagged as right-wing: after all, the billionaires on TV and Twitter talking about how AI were going to change the world were all the same people who’d just gone all-in on Donald Trump. I still think this is a pretty good explanation - just unfortunate timing - but there are definitely other factors at play. One obvious factor is the hangover from the pro-crypto mania of 2021 and 2022, where many of the same tech-obsessed folks also posted ugly art and talked about how their technology would change the world forever. Few of these predictions came true (though cryptocurrency has indeed changed the world forever), and it’s understandable that many people viewed AI as a natural continuation of this movement. On top of that, Donald Trump himself has come out strongly pro-AI, both in terms of policy and in terms of actually posting AI art himself. This naturally creates a backlash where anti-Trump people are primed to be even more anti-AI 4 . Here are some more reasons: Let me finally put my cards on the table. I would describe myself as on the left wing, and I’m broadly agnostic about the impact of AI. Like the boring fence-sitter I am, I think it will have a mix of positive and negative effects. In general, I’m unconvinced by the pro-copyright and human-soul-related anti-AI arguments, or by the idea that AI is inherently right-wing, but I’m troubled by the environmental impact and the impact on jobs (which in my view are more classically left-wing positions). Still, I’m curious what will happen when the left-wing flavor of anti-AI rhetoric disappears, which I think it will (as I said at the start, anti-AI sentiment is actually pretty bipartisan ). When people start making explicitly right-wing anti-AI arguments, will that cause the left-wing to move a little bit towards supporting AI? Or will right-wing institutions continue to explicitly support AI, allowing anti-AI sentiment to become a wedge issue that the left-wing can exploit to pry away voters? In any case, I don’t think the current state of affairs is particularly stable. In many ways, the dominant anti-AI arguments would fit better in a conservative worldview than in the worldview of their liberal proponents. I don’t think any did, which is probably for the best - they would have only had a couple of years to break into the industry before hiring collapsed in 2023. Another point that isn’t quite mainstream enough but that I still want to mention: AI critics often argue that cavalier deployment of AI means that people might take dangerous medical advice instead of simply trusting their doctor. But anyone who’s been close to a person with chronic illness knows that “just trust your doctor” is kind of right-wing-coded itself, and that the left-wing position is very sympathetic to patients who don’t or can’t. In a parallel universe, I can imagine the left-wing arguing that patients need AI to avoid the mistakes of their doctors, not the other way around. Is it a good argument? I don’t know, actually. The easy counter is that the LLMs are just mirroring the biases in their training data. But you could argue in response that superintelligence is also latent in the training data, and that hill-climbing towards superintelligence also picks up the associated political positions (which just so happen to be left-wing). I am no fan of Donald Trump, but it doesn’t follow that everything he supports is bad (e.g. the First Step Act ). Many AI critics complain that AI steals copyrighted content , but prior to 2023, leftists have been largely anti-intellectual-property on principle (either because they’re anti- property , or because they characterize copyright as benefiting huge media corporations and patent trolls). A popular anti-AI-art sentiment is that it’s corrosive to the human spirit to consume AI slop: in other words, art just inherently ought to be generated by humans, and using AI thus damages some part of our intangible human soul. Whether you like this argument or not, it’s structurally similar to a whole slate of classic arguments-from-intuition for conservative positions like anti-abortion or anti-homosexuality. Weird new technological art has traditionally been championed by the left-wing and dismissed by the right-wing (as inhuman , cheap , or degenerate ). But when it comes to AI art, it’s the left-wing making these arguments, and others (not necessarily right-wingers) arguing that AI art can also be a medium of human artistic expression. One main worry about AI is that it’s going to take over a lot of jobs. This is a compelling argument! But the left-wing has recently been famously unsympathetic to this same argument around fossil-fuel energy jobs like coal mining , to the point where Biden infamously advised a group of miners in New Hampshire to learn to code 1 . Halting technological progress to preserve jobs is quite literally a “conservative” position. AI has real environmental impact (though this is often wildly overstated, as I say here ), and the right-wing is politically committed to downplaying or denying anthropogenic environmental impacts in general. When times are tough, it’s easy to blame the hot new thing that everyone is talking about. Because the right-wing is currently ascendant in the US, left-wingers are more inclined to talk about how tough times are. The left-wing is over-represented in the kind of “computer jobs” that are under direct threat from AI. Being pro-Europe has always been left-wing coded, and Europe has been noticeably slower and more sceptical about AI than the USA. I don’t think any did, which is probably for the best - they would have only had a couple of years to break into the industry before hiring collapsed in 2023. ↩ Another point that isn’t quite mainstream enough but that I still want to mention: AI critics often argue that cavalier deployment of AI means that people might take dangerous medical advice instead of simply trusting their doctor. But anyone who’s been close to a person with chronic illness knows that “just trust your doctor” is kind of right-wing-coded itself, and that the left-wing position is very sympathetic to patients who don’t or can’t. In a parallel universe, I can imagine the left-wing arguing that patients need AI to avoid the mistakes of their doctors, not the other way around. ↩ Is it a good argument? I don’t know, actually. The easy counter is that the LLMs are just mirroring the biases in their training data. But you could argue in response that superintelligence is also latent in the training data, and that hill-climbing towards superintelligence also picks up the associated political positions (which just so happen to be left-wing). ↩ I am no fan of Donald Trump, but it doesn’t follow that everything he supports is bad (e.g. the First Step Act ). ↩
Modern Frontend Complexity: essential or accidental?
Once upon a time, at the dawn of the web, browsers and websites were simple ... Then slowly, step by step, more and more interactivity was added.
Join us at PyCon US 2026 in Long Beach - we have new AI and security tracks this year
This year's PyCon US is coming up next month from May 13th to May 19th, with the core conference talks from Friday 15th to Sunday 17th and tutorial and sprint days either side. It's in Long Beach, California this year, the first time PyCon US has come to the West Coast since Portland, Oregon in 2017 and the first time in California since Santa Clara in 2013. If you're based in California this is a great opportunity to catch up with the Python community, meet a whole lot of interesting people and learn a ton of interesting things. In addition to regular PyCon programming we have two new dedicated tracks at the conference this year: an AI track on Friday and a Security track on Saturday. The AI program was put together by track chairs Silona Bonewald (CitableAI) and Zac Hatfield-Dodds (Anthropic). I'll be an in-the-room chair this year, introducing speakers and helping everything run as smoothly as possible. Here's the AI track schedule in full: (And here's how I scraped that as a Markdown list from the schedule page using Claude Code and Rodney .) I've been going to PyCon for over twenty years now - I first went back in 2005 . It's one of my all-time favourite conference series. Even as it's grown to more than 2,000 attendees PyCon US has remained a heavily community-focused conference - it's the least corporate feeling large event I've ever attended. The talks are always great, but it's the add-ons around the talks that really make it work for me. The lightning talks slots are some of the most heavily attended sessions. The PyLadies auction is always deeply entertaining. The sprints are an incredible opportunity to contribute directly to projects that you use, coached by their maintainers. In addition to scheduled talks, the event has open spaces , where anyone can reserve space for a conversation about a topic - effectively PyCon's version of an unconference . I plan to spend a lot of my time in the open spaces this year - I'm hoping to join or instigate sessions about both Datasette and agentic engineering . I'm on the board of the Python Software Foundation, and PyCon US remains one of our most important responsibilities - in the past it's been a key source of funding for the organization, but it's also core to our mission to "promote, protect, and advance the Python programming language, and to support and facilitate the growth of a diverse and international community of Python programmers". If you do come to Long Beach, we'd really appreciate it if you could book accommodation in the official hotel block, for reasons outlined in this post on the PSF blog . You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options . 11:00: AI-Assisted Contributions and Maintainer Load - Paolo Melchiorre 11:45: AI-Powered Python Education : Towards Adaptive and Inclusive Learning - Sonny Mupfuni 12:30: Making African Languages Visible: A Python-Based Guide to Low-Resource Language ID - Gift Ojeabulu 2:00: Running Large Language Models on Laptops: Practical Quantization Techniques in Python - Aayush Kumar JVS 2:45: Distributing AI with Python in the Browser: Edge Inference and Flexibility Without Infrastructure - Fabio Pliger 3:30: Don't Block the Loop: Python Async Patterns for AI Agents - Aditya Mehra 4:30: What Python Developers Need to Know About Hardware: A Practical Guide to GPU Memory, Kernel Scheduling, and Execution Models - Santosh Appachu Devanira Poovaiah 5:15: How to Build Your First Real-Time Voice Agent in Python (Without Losing Your Mind) - Camila Hinojosa Añez, Elizabeth Fuentes
How an LLM becomes more coherent as we train it
I remember finding it interesting when, back in 2015, Andrej Karpathy posted about RNNs and gave an example of how their output improves over the course of a training run . What might that look like for a (relatively) modern transformers-based LLM? I recently trained a GPT-2-small-style LLM, with 163 million parameters, on about 3.2 billion tokens (that's about 12.8 GiB of text) from the Hugging Face FineWeb dataset, and over the course of that training run, I saved the current model periodically -- 57 checkpoints over two days. Here's what it looked like -- the start, the end, and some interesting waypoints in between. For each checkpoint, I asked it to generate a completion to the words "Every effort moves you". 1 When the model was first created, before any training had been done, it came up with this: If you've read the Karpathy essay, you'll see one important difference -- it's already got words in there. His RNNs were generating complete noise at this stage. Even by the 100th iteration, he gives an example like this: That's an important difference between the RNNs he was talking about, which were character-based and had to learn about words and the like, and LLMs like this one, where the text is input and then output one token at a time. ( More info here ). Still, even though it has what looks like words, it's essentially content-free token salad with no structure or coherence 2 . Let's see what happens if we train it more. In my training loop, it sees 96 sequences of 1,024 tokens, and then we update it based on its loss (an index of how wrong it was at predicting next tokens), so that's 98,304 tokens for each step. After 617 of these 3 it seems to have mostly learned something about which tokens are most common: By the next checkpoint at step 1234, we've got something that's starting to come together. It doesn't make sense, but there's some kind of glimmering of meaning: And just a little while later, at the checkpoint at step 2468, we have something that actually makes some kind of sense (at least at the start)! Now, the training data I'm using was scraped from the Internet, and unsurprisingly there's a lot of somewhat cheesy business content there. By step 9255, we're starting to get a lot of stuff like this: ...or even more cheesy self-help stuff (step 10489): To be fair, the starting point of "Every effort moves you" is probably biasing things a bit there. But let's be clear: by this point it's seen 1,031,110,656 tokens -- that is, it's about one third trained. And it's coming up with pretty coherent text! The rest of the training run is more about refining things -- the loss chart for this training run looks like this: Loosely speaking, the lower the loss number, the better the model is, so you can see that the bulk of the improvement had happened by this point. From here on, I'll just give a few of the more interesting samples: By step 14191, it's started using bullet points... Step 24680 -- more motivational stuff: Step 25297 -- small models like this do like repeating themselves. You might remember seeing ChatGPT output back in 2023 or so that had tics like this: And again at step 26531 At step 27765 it decides that it has had enough after generating just a couple of words and tries to start a new document: But step 28382 is actually rather good. I particularly like the "however": And finally, the training run finishes at step 33164 with these wise words of caution: Well worth remembering, I'm sure we can all agree. I wonder what deep wisdom we'd have gained if I had asked it to generate more than 20 new tokens... What I found most surprising when I first started playing with this is how fast even simple LLMs got to a stage where they could generate plausible text. Just one third of the way through the training run, this model was making some kind of sense. The problem, of course, is that we don't just want generators of plausible content -- we want that content to make sense and be correct. And that's why it's worth grinding through the other two thirds -- in the hope that when you ask it to complete "The capital of France is", it will reply with "Paris" rather than a coherent but wrong answer like "Rouen". Technical details: 20 GPT-2 tokens generated on top of the initial text, with a temperature of 1. I've added line breaks to make it easier to read the samples. ↩ Well, it mentions " despicable capitalists", but I suspect that's just randomness rather than some kind of primitive political consciousness. Including the space at the start, that's tokens 47034 and 32663 in the GPT-2 tokeniser. ↩ So, 60,653,568 tokens seen. ↩ Technical details: 20 GPT-2 tokens generated on top of the initial text, with a temperature of 1. I've added line breaks to make it easier to read the samples. ↩ Well, it mentions " despicable capitalists", but I suspect that's just randomness rather than some kind of primitive political consciousness. Including the space at the start, that's tokens 47034 and 32663 in the GPT-2 tokeniser. ↩ So, 60,653,568 tokens seen. ↩
Anonymous credentials: an illustrated primer (Part 2)
This is the second in a series of posts about anonymous credentials. You can find this first part here. In the previous post, we introduced the notion of anonymous credentials as a technique that allows users to authenticate to a website without sacrificing their privacy. As a quick reminder, an anonymous credential system consists of a few parties: an Issuer that hands out credentials, one or more Resources , such as websites (these can be the same person as the Issuer in some cases), and many Users . The User obtains its credential(s) from the Issuer, who will typically verify the user’s identity in a non-anonymous way. Once a user holds this credential, it can “show” the credential anytime it wants to access a Resource, such as a website. This “show” procedure is where the anonymity comes in: implemented correctly, it should not allow any party (either Resource or Issuer, or the two working together) to link this “show” back to the specific credential given to the User. We also introduced a few useful features that are useful for an anonymous credential system to have: The previous post was intended as a high-level overview, so we mainly kept our discussion at a theoretical level. However, this is a blog about cryptography engineering . That means today we’re going to move past theory and discuss practice. Concretely, that means describing two real-world credential systems that are actually used in our world. The first is Privacy Pass , which is widely used by Cloudflare and Apple and other companies. Then we’ll discuss a new proposal for anonymous age verification that Google is in the process of standardizing. Privacy Pass is the most widely-deployed anonymous credential standard in the world. Under one name or another, Privacy Pass is used all over the Internet, primarily by large tech firms. The most famous of these is Cloudflare , whose researchers helped to write the standard as a way to bypass CAPTCHAs and other anti-abuse annoyances. But an identical protocol is also deployed by Apple (which names it “ Private Access Tokens “), Google (“ Private State Tokens “), the Brave browser, and a handful of other projects. Privacy Pass is so ubiquitous that even Microsoft uses it in their Edge browser, and they don’t even like privacy. Privacy Pass is exactly what you’d expect from the first large-scale deployment of credentials. It’s incredibly simple, just about as simple as you can imagine. The protocol offers classic single-use “wristband” credentials, the kind where credentials carry one bit of information — namely, “I own a credential”. The techniques used are so simple that you can more or less extract Privacy Pass from reading academic papers written in the 1980s and tossing in a few clever performance optimizations. The real novelty is that people are actually using it. Privacy Pass is standardized in IETF RFCs 9576 , 9577 and 9578 . There are many deployment options in those standards, but the core protocol is essentially a perfect realization of Chaum’s original “blind signature” credentials, which we discussed in the previous post . Allow me to quickly revisit how these credentials work: The four-tuple ( tokentype, MD, SN, sig ) are the resulting credential. To “show” this credential to a Resource: Done up as a pictogram, the basic Privacy Pass flow looks like something this: An obvious question you might ask here is: what the heck is with the metadata MD ? This metadata string is an additional blob of data that can be used to “ bin d” a credential to a specific application, such as a website. For example, if I plan to access the New York Times on Tuesday, March 31, I could request a credential that contains the metadata string MD = “ “. When I “show” the credential, that website can verify the string and decide if it will grant me service. Critically, the Issuer does not see this metadata string. It is entirely up to the User to select it, but once selected, it cannot be changed. This approach allows websites to require tokens that are of restricted usefulness — for example, bound only to the one specific website, or limited to a specific time period. The primary application of metadata in Privacy Pass is to implement what I’ll call session-specific credentials. This is a different issuance flow in which the User does not obtain their credential prior to visiting the website, but rather, obtains the credential only after it has begun to access a site (such as a Cloudflare-protected website.) This flow works as follows: Put together as a cute pictogram, the protocol flow looks like this: The advantage of this combined protocol is that each credential can only be used for the specific session that the User has already initiated. It cannot be used to do anything else: for example, the User can’t sit on the credential and use it next week. This plausibly has some advantages for sites like Cloudflare, where you want some ability to control how many users are accessing a site in real time. There are some downsides to this approach as well. One of the downsides is that for real-time credential issuance, the Issuer must be continuously available: if the Issuer goes down, then essentially all access to the Resource becomes impossible, since a User won’t be able to obtain fresh credentials. (In the earlier issuance flow, a User could obtain a bunch of credentials first, then use them later on, even if the Issuer is down.) A second downside is that the real-time issuance protocol could, in principle, lead to a timing correlation attack . That is, if the Resource and Issuer compare the timestamps at which they receive their individual messages, they might be able to link a user’s session to the credential issuance request. This last point is particularly concerning for applications where the Issuer and Resource are both run by the same company: something that happens to be true for Cloudflare’s deployment . Fortunately, Cloudflare handles literally hundreds of thousands of transactions per second, which is so huge that this kind of correlation attack is probably not very easy to pull off. (As a sanity check, I even did a quick and dirty analysis using Claude Code to check this, and the results are mixed: see here .) With this basic protocol flow written up, the main remaining question when describing Privacy Pass is a pretty basic one: how do we implement the blind signatures? Privacy Pass defines two standardized “issuance protocols” that each use slightly different cryptography. The first of these describes a variant of Privacy Pass for publicly verifiable tokens . These are essentially the same Chaumian credentials we discussed in the last post : here, the Issuer uses blind RSA signatures to sign the token, in a manner that’s almost exactly identical to Chaum’s original 1980s protocol . The benefit of these tokens is that the Resource can verify the token using the Issuer’s public key — meaning that the Issuer and Resource don’t have to share any secret key material. The main problem with RSA blind signatures is that they’re big and somewhat expensive to construct. This is because RSA requires large public keys, typically at least 2,048 bits to achieve about 112-bit levels of symmetric-equivalent security. This makes the signatures relatively large, and also makes the signing procedure somewhat costly. The obvious alternative approach would use elliptic-curve (EC) primitives, such as Schnorr signatures or even (ugh!) ECDSA. (I’ll discuss post-quantum alternatives later.) The boring problem with this approach is that we don’t have a great toolbox of EC-based blind signatures. To summarize: Hence, Privacy Pass does not support elliptic-curve based blind signatures at all . Instead, for deployments that need to be extremely fast, Privacy Pass defines a second issuance for privately-verifiable tokens . These tokens use an oblivious Message Authentication Code (MAC) based on an oblivious pseudorandom function . The advantage of these privately-verifiable tokens is that they use EC-based primitives and are extremely fast to create and verify. The disadvantage is that the verifier (in this case, the Resource) must possess the Issuer’s secret key in order to verify a credential. Privacy Pass is the least surprising anonymous credential protocol you can build. It provides users with a simple, single-use “wristband” credential that’s optimized to be very fast. Although the basic ideas behind the protocol were all finalized in the 80s, they’ve now been standardized into something that is very fast and usable. What makes the protocol interesting is not so much the technology behind it, but the broad scale of deployment: between Apple, Google, Cloudflare, literally billions of people are likely using Privacy Pass every day — even if they don’t really know it. At the same time, Privacy Pass is very boring: it does not provide many useful features beyond “get token, use token” model of a wristband credential. It certainly does not offer us much of a solution to the problems of age verification, unless we are willing to constantly communicate with an Issuer to obtain credentials, each time we use the web. In the next post, we’re going to discuss a more powerful proposal that does purport to solve some of those problems: a new proposal by Google’s to support zero-knowledge credentials . The most useful feature is some way to constrain the usefulness of a single credential: for example, by limiting the number of times it can be “shown”. This is needed in order to prevent credential cloning attacks , where a hacker (or malicious User) steals a credential and makes many copies that power e.g., “bot” accounts. These attacks are very dangerous in an anonymous credential system, since credentials aren’t natively traceable to a specific user — and hence a single stolen credential can be cloned many times without detection. In the previous post , we even proposed a handful of fixes for that problem. We also talked about how to make credentials more expressive. For example, your driver’s license is a (non-anonymous) credential that allows you to assert many claims, such as your age, the type of vehicle you’re certified to drive, which state you live in. An expressive anonymous credential allows you, the User, to prove a variety of statements over this data — without leaking useful information beyond the facts that you wish to assert. When a User wishes to obtain a single-use credential, they first choose a token type ( tokentype ) and some metadata MD , which is an optional string the user can include in the token. The User now generates a long random serial number SN that’s (hopefully) globally unique. The User and Issuer next run a blind signature protocol to produce a signature on a message that comprises ( tokentype , SN, MD ). The User learns the signature sig , while the Issuer does not learn the signature or anything about the message being signed. The Users sends ( tokentype, MD, SN, sig) to the Resource. The Resource verifies that tokentype is a valid type of Privacy Pass token, and decides if it will accept a token with metadata MD (more on this in a moment.) Next, the Resource verifies the signature sig using the Issuer’s verification key (the tokentype field tells it how to), and checks a database to ensure that SN has not been used before. If these checks all succeed, it adds SN to the database. When a user begins to access a Resource, the Resource sends them a session-specific “challenge” (a random string, for example). The User then requests a credential from the Issuer in real time, setting MD equal to the “challenge”. When the User “shows” the credential to the Resource, the Resource verifies that the challenge matches the one it chose in step (1). Several older “blind Schnorr” protocols turn out to be horribly insecure when you allow concurrent issuance — i.e., when attackers are allowed to run many blind signature request protocols at the same time. These attacks are bad enough that they can actually forge Schnorr signatures on reasonable computing hardware . Making these protocols run securely would require that we only conduct one signing session at a time, i.e., no parallel (concurrent) issuance. Some recent papers have tried to fix this problem, but the resulting protocols are slower than blind RSA.
2026.16: Servers, Satellites, and Stars
Welcome back to This Week in Stratechery! As a reminder, each week, every Friday, we’re sending out this overview of content in the Stratechery bundle; highlighted links are free for everyone . Additionally, you have complete control over what we send to you. If you don’t want to receive This Week in Stratechery emails (there is no podcast), please uncheck the box in your delivery settings . On that note, here were a few of our favorites this week. This week’s Stratechery video is on Apple’s 50 Years of Integration . The Cost of AI. The key to understanding and analyzing tech has been appreciating the implications of zero marginal costs, which govern the economics of everything from chips to software to services. AI services generally fall under the same rubric — fixed costs in terms of data centers and chips matter more than marginal costs (mostly electricity) — but the worsening shortage in compute means it is opportunity costs that matter more than ever . Companies will have to make hard choices, and the biggest loser might be the serially unfocused OpenAI. — Ben Thompson What Is Amazon Doing with Globalstar? Earlier this week Amazon announced an $11.8 billion deal to purchase Globalstar satellites in what was billed as a move to ramp the company’s competition with Elon Musk and Starlink There may be more going on with that deal, though, and Wednesday’s Daily Update explored what Apple’s role might have been. We went deeper on all this on Friday’s episode of Sharp Tech , and I loved the segment as a window into Amazon’s motivations for satellite investments generally, and the questions surrounding this deal specifically. — Andrew Sharp Nico Rosberg on Racing and Investing. As a religious F1 fan I’m obligated to recommend this week’s Stratechery Interview with Nico Rosberg , a terrific conversation with a former world champion in Formula 1 and a recent entrant into the world of venture capital. Come for stories of surviving the mental grind of F1 and why Rosberg walked away at the pinnacle of his career, and stay for a study of someone who looks for an edge in everything he does, understands his advantages, and has been very strategic about leveraging them to succeed in a completely different world. You wouldn’t think a famous F1 driver has lessons that could be applicable to anyone, but I was pleasantly surprised. — AS Mythos, Muse, and the Opportunity Cost of Compute — Does Aggregation Theory survive in a world of constrained compute? Yes, insomuch as controlling demand will give power over supply. OpenAI’s Memos, Frontier, Amazon and Anthropic — Breaking down OpenAI’s internal memo about taking on Anthropic in the enterprise. Amazon Buys Globalstar, Delta to Add Leo, The Apple Angle — Amazon’s Globalstar acquisition is being framed as Amazon versus SpaceX, but I think the real story is about Apple. An Interview with F1 Driver and Venture Capitalist Nico Rosberg About the Drive to Win — An interview with former F1 driver and current venture capitalist Nico Rosberg about finding the mental edge and maximizing opportunities. What the NBA Needs Right Now Is Anyone But OKC — After a long and mediocre regular season, the NBA Playoffs bring new hope for the league and fans alike. We just need one team to lose. Apple and the Frontier Labs Vibe App Quality How To Test 208 Billion Transistors An End of Year Mailbag: Fox Feelings, Pistons Hate, Hartenstein Sliding Doors, SGA Meets His Hero, and Lots More 2026 Awards Picks, Early Playoff Thoughts, Play-In Previews and More Six Questions on Frontier AI Labs, Messaging AI to a Skeptical Public, Amazon (and Apple?) Ramps Up Competition with Elon
Premium: The Hater's Guide to Private Credit
A few years ago, I made the mistake of filling out a form to look into a business loan, one that I never ended up getting. Since then I receive no less than three texts a day offering me lines of credit ranging from $150,000 to as much as $10 million, each one boasting about how quickly they could fund me and how easy said funding would be. Some claim that they’ve been “looking over my file” (I’ve never provided any actual information), others say that they’re “already talking to underwriting,” and some straight up say that they can get me the money in the next 24 hours. Some of the texts begin with a name (“Hey Ed, It’s Zack”) or sternly say “Edward, it’s time to raise capital.” Others cut straight to the chase and tell me that they have been “arranged for five hundred and fourty (sic) thousand,” and others send the entire terms of a loan that I assume will be harder to get than responding “yes.” While many of them are obvious, blatant scams, others lead to complaint-filled Better Business Bureau pages that show that, somehow, these entities have sent them real money, albeit under terms that piss off their customers and occasionally lead to them getting sued by the government . That’s because right now, anybody with the right lawyers, accountants and financial backing can create their own fund and start issuing loans to virtually anyone they deem worthy. And while they’ll all say that they use “industry-standard” underwriting, no regulatory standard exists. This, my friends, is the world of private credit — a giant, barely-regulated time bomb of indeterminate (but most certainly trillions of dollars ) size that has become a load-bearing pillar of pensions and insurance funds, and according to Federal Reserve data , private credit has borrowed around $300 billion (as of 2023) from big banks, representing around 14% of their total loans. The eager, aggressive growth of private credit has even led it to start targeting individual investors, per the Financial Times : The FT also neatly summarizes the problem of having regular investors involving themselves in the world of private credit: And those high returns come with a cost: a lack of flexibility ranging from “you can only redeem your funds every quarter, and only a small percentage of your funds,” to “you can’t redeem your funds if everybody else tries to at the same time,” to “we make the rules here, shithead.” When an asset manager sets up a private credit fund, it often sets terms around how often — or how much — investors can pull at once, usually set around 5%, because in most cases, private credit funds are highly illiquid , as despite them acting like a financial institution , they more often than not don’t have very much money on hand for investors. Why? Because the “private” part of private credit means that the lender directly negotiates with the borrower and values the loans based on their own internal models. Said loans generally have little or no secondary market, and private credit wants to hold them to maturity so that it can continue to provide ongoing yield (which I’ll explain in a little bit). Things were going great for private credit for the longest time, but late last year, some buzzkills at the Financial Times discovered that auto parts manufacturer First Brands and subprime auto loan company Tricolor had taken on billions of dollars of loans under dodgy circumstances, double-pledging collateral (IE: giving the same stuff as collateral on different loans) and outright falsifying lending documents, allowing the both of them to borrow upwards of $10 billion from private credit firms, including billions from North Carolina-based firm Onset Capital, which nearly collapsed but was eventually rescued by Silver Point Capital . After the collapse of First Brands and Tricolor, JP Morgan’s Jamie Dimon said that “ when you see cockroaches, there are probably more ,” the kind of sinister quote baked specifically to lead off a movie about a financial crisis. Seemingly inspired to start freaking people out, on November 5, software-focused asset manager Blue Owl announced it would merge its publicly-traded OBDC fund with its privately-traded OBDC II fund , and, well, it didn’t go well, per my Hater’s Guide To Private Equity : Two weeks later on November 18 2025, Blue Owl said it would freeze redemptions on OBDC II until after the merger closed, then canceled it a day later citing “market conditions.” Two months later in February 2026, Blue Owl would announce that it was permanently halting redemptions from OBDC II, and sold $1.4 billion in assets from both OBDC II and two other funds. The buyers of the assets? Several large pension funds that had a vested interest in keeping the value of the assets high , and Kuvare, an insurance company with $20 billion of assets under management that Blue Owl bought in 2024 . This is perfectly legal, extremely normal, and very good. Private equity is also the principal funding source for private equity’s leveraged buyouts, accounting for over 70% of all leveraged buyout funding for the last decade , which means that private credit — and anyone unfortunate enough to fund it! — is existentially tied to the ability of the portfolio companies’ ability to pay, and their continued ability to refinance their debt. This is a problem when your assets are decaying in value. As I discussed in the Hater’s Guide To Private Equity , PE firms massively over-invested between 2017 and 2021, leaving them with a backlog of 31,000 companies valued at $3.7 trillion that they can’t sell or take public, likely because many of these acquisitions were vastly overvalued. You see, when things were really good , asset managers raised hundreds of billions of dollars from pension funds, insurance funds (some of which they owned), and institutional investors, and then issued hundreds of billions of dollars more (at times using leverage from banks to do so) in loans to private equity firms that went on to buy everything from software companies to restaurant franchises. Said debt would immediately go on the balance sheet of the acquired company, creating a “reliable,” “consistent” yield with every loan payment that the fund could then send on to its investors, on a quarterly or monthly basis. The problem is that these investments were made under very different economic circumstances , when money was easy to raise and exits were straightforward, leading to many assets being massively overvalued, and holding debt that was issued under revenue and growth projections that only made sense in a low-interest environment. In simple terms, these loans were given to companies assuming they’d be able to pay them long term, and assuming that the sunny economic conditions would continue indefinitely, making them tough to refinance or, in some cases, for the debtor to continue paying. And nowhere is that problem more pronounced than the world of software. The jitters caused by First Brands and Tricolor eventually turned into full-on tremors thanks to the SaaSpocalypse ( covered in the Hater’s Guide a month ago ): The SaaSpocalypse is often (incorrectly) described as a result of AI “disrupting incumbent software companies,” when the reality is that private equity (and private credit) made the mistaken bet that every single software company would grow in perpetuity. The larger software industry is in decline , with a McKinsey study of 116 public software companies with over $500 million in revenue from 2024 showing that growth efficiency had halved since 2021 as sales and marketing spend exploded, and BDO’s annual SaaS report from 2025 saying that SaaS company growth ranged from flat to active declines, which is why there’s now $46.9 billion in distressed software loans as of February 2026 . And to be clear, it’s not just private equity’s victims that are taking out loans. Over $62 billion in venture debt was issued in 2025 , with established companies like Databricks ( $5.2 billion in credit per the Wall Street Journal in 2024) and Dropbox ( $2.7 billion from Blackstone in 2025 ) raising debt just as the overall software industry slows, with AI failing to pick up the pace. This is a big fucking problem for private credit. Per the Wall Street Journal , asset managers are massively exposed to software companies, and have deliberately mislabeled some assets (such as saying a healthcare software company is just a “healthcare company”) to obfuscate the scale of the problem: And as I’ll explain, “obfuscation” is a big part of the private credit business model. If I’m honest, preparing this week’s premium has been remarkably difficult, both in the amount of information I’ve had to pull together and how deeply worried it’s made me. In the aftermath of the great financial crisis, insurance and pension funds found themselves desperate for yield — regular returns — to meet their payment obligations. Private credit has become the yield-bearer of choice, feeding over a trillion dollars of these funds’ investments into leveraged buyouts, AI data centers, loans to software companies, and failing restaurant franchises. In some cases, asset managers have purchased insurance companies with the explicit intention of using them as funders for future private credit investments, such as Apollo’s acquisition of Athene , KKR’s acquisition of Global Atlantic , and Blue Owl’s acquisition of Kuvare . More on this later, as it fucking sucks. Asset managers offering private credit market themselves as bank-like stewards of capital, but lack many (if any) of the restrictions that make you actually trust a bank. They self-deal, investing their insurance affiliates’ funds in their own equity investments (such as when KKR used Global Atlantic to invest in data center developer CyrusOne , a company it acquired in 2022 ), value and revalue assets based on mysterious and undocumented private models, and account for (as I mentioned) 70% of all funding of leveraged buyouts in the last decade, of which 30 to 40% were software companies purchased between 2018 and 2022 , meaning that hundreds of billions of dollars of retirement and insurance funds are dependent on overvalued software companies paying loans funded during the zero interest free era. While a market crash feels scary, what’s far scarier is that the present and future ability of many retirement and insurance funds is dependent on whether private equity-owned entities, software companies. and AI data center firms are able to keep paying their debts. If private credit fund returns begin to lag, the retirement and insurance industry lacks a viable replacement, and I don’t know how to fix that. Fuck it, I’ll level with you. I think asset managers are scumbags, and I think the way that they do business is fucking disgraceful. The unbelievable amount of risk that asset managers have passed onto people’s fucking retirements is enough to turn my stomach, and if I’m honest, I don’t understand how this entire thing hasn’t broken already. If I had to guess, it’s one of two reasons: that private credit funds have yet to escalate their risk enough, or we’re yet to see said risk’s consequences, with First Brands and Tricolor being just the beginning. And Wall Street is prepared to profit, with S&P Dow Jones launching a credit default swap derivatives product to bet against a collection of 25 different banks, insurers, REITs, and business development companies. Bank of America, Deutsche Bank, Barclays and Goldman Sachs will start selling the derivatives next week, per Reuters, and I’d argue that enough demand could spark a genuine panic across publicly-traded asset managers. In any case, this is a situation where I fear not one massive catastrophe, but a series of smaller calamities caused by decades of hubris and questionable risk management resulting from the unbelievably stupid decision to let private entities act like banks. This is the Hater’s Guide To Private Credit, or The Big Shart.
Back to Palm OS
Over the winter I was super into Palm Pilots, I even picked up a few new ones and swapped the batteries. My current collection includes a Tungsten E, Tungsten T3, Tungsten C and a Handspring Visor. I was daily driving the C for quite awhile, but fell off when I upgraded my phone. Well, today I'm going back! I recently posted on Mastodon about my struggles trying to track calories. Everything on the iOS store is enshittificated garbage. I shouldn't have to pay a monthly fee, see ads, have my data sold, create an account and agree to ToS to track freaking calories. Palm Pilots are from an era when software was allowed to be complicated, and to that end there are a number of applications that allow you to essentially create your own applications! Using SmartList To Go , I was able to create a database with a form for entering and tracking daily calories. It's not complex, but it doesn't need to be. I have a screen for seeing my daily log, sorted by meal then calorie count. There's a form for recording a new entry, and there's a screen to sum up all the calories in the day. I also keep a running log in each entry of the daily calories (previous record total + current calories). I might expand the functionality by adding a second database that remembers food items and their calories, then join it in with the log view so I don't have to lookup calories each time. The fact that it's an option to do that is awesome. I also love that there's the ability to build logical evaluators in computed fields. Yeah, I had to download and read parts of the 136 page SmartList To Go 3.0 Handheld Reference Guide , but why is that such a bad thing? Why have we given up on making software that serves our needs, and instead just let companies shovel subscription based crap at us? SmartList was not free back in the day (looks like it was $50 USD, which is $84 today), but quality software shouldn't have to be free. What it should have to be is yours. Pay once, no ads, no data collection, no online requirement. Someone that paid for SmartList in 2005 can still get value out of it 21 years later. Wish me luck as I restart my journey of weight loss, hopefully I can shed some pounds and get faster on the bike! I'll also be using the Weight Tracker application I previously wrote for Palm OS.
JTR
This week on the People and Blogs series we have an interview with JTR, whose blog can be found at taonaw.com . Tired of RSS? Read this in your browser or sign up for the newsletter . People and Blogs is supported by the "One a Month" club members. If you enjoy P&B, consider becoming one for as little as 1 dollar a month. I go by JTR these days, which is based on an earlier pseudonym I picked up long ago. Sort of an alter ego I guess. I like how it rolls off the tongue, so I stuck with it. I was a writer (and a bit of a journalist) and a teacher before I found my way into IT. Today I’m a sort of manager who still writes plenty of technical documentation and attends a lot of meetings. I had a few blogs in the past, but when I started working for the medical center which I'm still working for today, 8 years ago, I decided to record my quest to learn technology in a blog. Soon after I started there, I was looking for an app to write checklists and bullet points, and I found Orgzly . It seemed minimal, and I liked that it just writes everything to text files. I had no idea what org-mode was (or Emacs for that matter), and after a few weeks with the app I was deep down in rabbit hole. So the start of my current position, along with learning Emacs and org-mode gave me a boost to start blogging what I was learning. I think it was my boss back then or one of my co-workers who didn't understand why I couldn't just use one of the many note-taking apps that were already available to us. That question, along with my reputation of always asking many of my own whenever we had meetings, had me come up with the idea that I should just call my blog “The Art of Not Asking Why,” hinting at one of my favorite books, Zen And The Art of Motorcycle Maintenance. It was just organic like that. “The Art of Not Asking Why” is kind of long, so I started to abbreviate it with “TAONAW” (I pronounce it "Tao-Now"), and I liked how it sounded... so here we are.” (the name of the book should be all caps…) Today, my blog is a mix of quick thoughts and longer posts, both of which are handled well by design by Micro.blog, my blogging platform, which I’m very happy with. For short posts (300 characters or so, "tweets" and "toots" basically), I usually use my iPhone or Android. Longer posts usually start in Emacs org-mode as a draft, and then are edited by hand before I pass them through Grammarly and/or AI for typos and various checks. AI is excellent to find broken links, technical terms that I might want to expand on ( and suggest links to those), and switching back to org-mode so that my draft ends up being updated with the same post, typo and error-free (or almost free) on my blog. For screenshots, I use SnagIt , which is paid for by my job (I write plenty of technical documents). Snaggit is excellent, and I'd pay for it in a heartbeat myself if I had to. For photos, which I take with my Sony camera or iPhone, I use Apple Photos these days for light editing. I also have Darktable and Krita on my Linux desktop, both of which are free, excellent tools that are highly underrated in my opinion. They give me all the power Adobe Photoshop and Lightroom used to give me, without costing me a dime and just make me feel good to use. My posts usually come from different experiences I go through, technical or otherwise. Sometimes I look in my journal and modify an entry from there to a post, at other times I go to my old blog and import a post from there and add it to my blog with the original timeline, yet other times I got over my images and pages on my blog - there’s always something to do, beyond just writing the posts. I think that’s part of the fun. A good blog grows with you, and you learn to tell more about yourself as you progress. I used to work from coffee shops, but today I mostly blog from home. My apartment is quiet and less distracting, and the best time for me to write is in the morning (if I have enough time available), so this combination usually wins me over. I need to focus when I write, and I don’t like to get distracted, which is another reason why home is usually the best place. I absolutely love my noise-cancelling Sony WH-1000XM6 (and the WH-1000XM5 before those) headphones, which have been a life changer for me, a person who can get distracted when my neighbors from across the hall return home. My mechanical keyboard, a Kensis Freestyle Edge RGB, is about 7 years old now and I love the feel of the mechanical keys under my fingers. The ergonomic setup (it's a split keyboard) helps my wrists, and my standing desk helps my concentration further. When I write, I also listen to music: electronic or classical. Songs with lyrics usually distract me. I have two computers. A MacBook Pro M2, and a System76 thelio mira , currently running Kubuntu, which is also my gaming computer. From these two, I lean slightly toward using the Mac for my writing because I take most of my photos with my iPhone and the Micro.blog desktop app that I use is for macOS. My blog is hosted on Micro.blog, which is a hybrid of a social platform and a blogging platform in one. Micro.blog uses Hugo to build the blog and Micropub for the social network. It also syndicates to other social networks like Tumblr and Medium and plenty more that I don't use. It’s a rather unique place that follows the POSSE (Publish Own Site, Syndicate Elsewhere) principles . I like the fact that I can download all of my data, which includes my posts, my media and my CSS/HTML templates, any time I wish and take them elsewhere. That’s how the web should be. When I joined Micro.blog I had to register my own domain, which I did, but these days you can also get a domain through them, and I believe you can also get a certificate through Let’s Encrypt in one go. It's a bit confusing at the start since the concepts of a social network and a blog (=website) are different aspects in our minds, but they don't have to be that separate. No. What I know today and the tools I use are the best ones for me at this point. If anything, I’d encourage myself to have learned to use Emacs much earlier and to have adhered to POSSE long ago; that would have saved me from losing work on Medium and Blogger, which are now long gone. I recommend micro.blog wholeheartedly. My plan on Micro.blog (hosting) costs $100 a year, which isn't horrible when you break it down to $8 and change per month. Micro.blog comes with many additional tools (such as hosting podcasts, encrypted notes, storing videos and more) which are worth it in my opinion. My domain costs about $30 a year. I absolutely hate how ads work on the internet today, and I will never have ads on my blog, but I believe it's OK to ask for support or, as I like to think of it, "tips." If someone likes something I wrote, they are welcome to leave a tip. I don't need it however to keep the blog going, thankfully. I don’t have a long list, and I think most of the folks I know were already covered in this series. I will highlight a few that are more active: I’d love, love to see more non-techie folks on POSE-style blogs. I’m not talking about Medium or Tumblr; these are Silos. Some exist, here and there. There used to a be a priod, back when people published on movable type and wordpress was still something new no one knew about, where I was following a diner waitress from Jersey, a fighter pilot who was a patriot in the good kind of way, and of course, there was the USS clueless (I think he’s still around, in retirement). Now, you have to be in the industry to do anything like that. I had a conversation with my partner the other day and he just shrugged. The term “silo” (he uses Tumblr) is so regular now that it’s like explaining water to a fish. And it’s a shame. Those that are different, micro.blog included, seems to require some knowledge of what, I guess, used to be common knowledge if you wanted to be online. I don’t know. Perhaps if I was still a teacher, I’d teach these internet “basics” to teens. Now that you're done reading the interview, go check the blog and subscribe to the RSS feed . If you're looking for more content, go read one of the previous 137 interviews . People and Blogs is possible because kind people support it. Annie’s blog : she often writes essays about feelings and life experiences, about once a week or so. Sal : mostly tech, here and there some other life stuff The Wandering Lensman He's professional photographer, usually an image and a short text. I like what he says about taking photos. Pluralistic from Cory Doctorow does this guy really need an intro…? I love how well-linked and resourced the daily essays are. An (the?) online privacy activist. Jack Baty Daily I lose track if this is the “real” blog or not. The guy changes blogs and platforms like we change shirts. But that’s part of the fun.
On AI Images and Feature Images in General
By Gordon Mclean Gordon stumbled across a post arguing that AI-generated featured images signals laziness, even if every word you write is your own, and it made him stop and think about his own blog. Read post ➡ This post piqued my interest, and surprise suprise, I have opinions. 🙃 I've spoken about my opinions on AI and image generation before and my opinion hasn't changed on that. I have, however, switched from ChatGPT to Claude, for reasons . Like I said in my previous post about AI, I don't think it creates art , but it can be useful for diagrams and some imagary. I listed some examples of my usage in that post, go take a look . For feature images, I think it's fine , I suppose. I don't think it has a bearing on the writer's ability to write good content thought. I think most people can spot AI-generated prose these days. If my spider-sense starts tingling, I'll close the tab. But if I only see an AI-generated feature image, it's fine. I think images creation and the ability to write nice words are two different skills. Using AI to create a feature image doesn't tell me that the person has a particular lack of creativity, as creativity comes in many forms. Ask Brandon Sanderson to create the cover art for one of his books, and I imagine he'd struggle. Does that make him any less creative? No. It just means he's a creative writer , not a creative artist . For the record - I have no idea if Sanderson is good at drawing. It's just an example, okay. Please don't email saying "well ackchyually..." Would I do it? Probably not. But I don't see the point in feature images anyway. I stopped using them many years ago, as generally they add nothing to the post, and are more for the writer to make the post look pretty than anything else. So when I see these kinds of feature images, my first thought tends to be meh... and my assumption is that the writer probably didn't have the time, or lacked the skills, to create an image. I'd personally prefer they didn't add one at all if that's the case, but that's just me. Maybe we should all be a little less judgmental. 🤷🏼♂️ Thanks for reading this post via RSS. RSS is ace, and so are you. ❤️ You can reply to this post by email , or leave a comment .