Posts in Programming (20 found)

OSI approved the curl license

curl started out GPL licensed, as direct inheritance from its httpget days, but in October 1998 we switched to the Mozilla Public License (MPL). In 2001, we added the MIT license as an additional license to optionally use in addition to MPL. We made curl dual licensed because clearly the MPL license caused problems for some users – primarily because it was deemed not compatible with GPL. In 2002 we dropped the MPL option and curl was from then on licensed only under the MIT license. Kind of. Because of reasons we cannot recall anymore, I decided to ever so slightly edit the language in the MIT license text around that time. (I strongly discourage anyone else from doing this, and if my time machine was functional I would go back and correct this decision.) The license text we then kept referring to and thinking about as an MIT license, was in fact not exactly MIT anymore. No one objected at the time. I can’t remember anyone really considering the implications at the time. Maybe because not that many people noticed or cared. It was in essence still the MIT license. Decades later, the SPDX project quite correctly and ruthlessly made the distinction between a proper MIT and a modified MIT matter: they created a separate and unique identified to the license curl uses. It may be almost like MIT but they deemed the differences big enough to say that the curl license is a special beast. It is since then known as the curl license. I have over the years casually kept referring to the license as MIT since it helps users understand even though it is technically incorrect. Open Source people in general tend to know the MIT license and the implications of using it. A drawback with having our own license is that it was not immediately recognized and known as Open Source or Free Software; not acknowledged and verified by FSF nor OSI. On April 17, 2026. The Open Source Initiative approved the curl license . It is since then officially arguably slightly more Open Source than before. I don’t think anyone ever doubted or that it was actually much of a drawback in adoption or usage, but it feels good to finally have this checkmark. I write about this now (many months after the fact) because I totally forgot that this was happening and I only recently realized OSI approved it back in April.

0 views

More on Anthropic's Scion ripping off Mononoke

Update: Nick G. from Anthropic has responded on Hacker News , and sufficient attribution has been added to Anthropic’s blog post. I stand by my posts as of the time I wrote them. Discuss on Hacker News . In response to yesterday’s post about Anthropic’s Scion ripping off Mononoke, I received a number of questions and concerns. Here’s a followup to answer the big ones. This was a ripoff. My post yesterday was trying to be as charitable as possible given what I knew, and in particular that the similarity to Mononoke was mostly unintentional and the lack of credit was the result of not doing due diligence. However, after publishing the post I privately received confirmation that Scion intentionally and blatantly ripped off Mononoke, and in particular that there was overlap in personnel. There is no chance that this was an unintentional homage. This is something I had a hunch about but was not comfortable saying yesterday, given what I knew back then. The resemblance is much deeper than just the notion of derived data. Some people pointed out that derived data is just an index, which is a well-known concept. I want to clarify that derived data was merely the most striking resemblance. It goes much deeper than that, and extends to the entire data model, as well as a number of the structures built around it. Here is how Anthropic describes Scion changesets: Mononoke has the same concept; we call it a Bonsai changeset. In the same Oxide materials from 2022, here’s how I described them: They are exactly the same. Even the name “Scion” reverses the syllables of “Bonsai” and drops the “B”! This might be a coincidence, or might not. For derived data, I also wanted to draw attention to the kinds of indexes being built, such as for blame. Needing to do this is a natural consequence of the Bonsai data model, so it’s not surprising that indexes need to be built; I was drawing attention to the striking similarity in terminology and framing, because that was indeed how we used to think about it during my time on Meta’s source control team. Another set of resemblances is in the server-side API to do version control queries and mutations with. This was implemented in Mononoke, but I believe other systems before Mononoke had it as well, so I’m not going to claim novelty. But if what you did is point Claude at Mononoke and asked it to rebuild that, you would probably design something very similar. The Bonsai data model is wildly contrarian. I want to emphasize that the prevailing wisdom in source control is Git-like data models. Building a write-ahead log-style Merkle DAG was very far away from what anyone else was doing in 2018, and required solving several hard problems along the way such as how to perform server-side rebases (to my knowledge, one of several novel algorithms in Mononoke). While I was leading the team effort to design and implement the model in 2018, I personally had to justify it to several layers of management at Meta. It is quite rare for skip levels to get pulled in to discuss a system’s data model in depth. The Bonsai data model is also wildly successful. At this point, almost a decade later, the model has been stretched far outside its initial design parameters, and it’s still chugging along. The team effort to build it remains one of my proudest career achivements. Given the overlap in personnel, there is no reasonable way the Scion team could not have known about this. (Which is why they quite reasonably copied it!) This brings us to my next point: The problem is attribution, not copying. I mentioned this in my original post, but I am completely fine with good ideas being copied. I am not fine with the serial numbers being accidentally stripped off, and I am certainly not fine with them being intentionally stripped off. Crediting Sapling for “hard-won lessons” is not enough. Several people pointed out that Mononoke is part of the Sapling ecosystem. The problem here is that Sapling can mean either the VCS client ( , originally forked from ) or the system as a whole. If you were previously on Meta’s source control team, you absolutely know the difference between the two. Besides, the resemblance is much, much deeper than merely “hard-won lessons”. The Lore VCS can claim inspiration from Mononoke, but it differs in several ways as well. Scion’s resemblance to Mononoke goes well beyond that, and merely crediting Sapling (not even Mononoke) with “hard-won lessons” is dishonest. (And specifically, I would expect the Scion changeset section to mention Bonsai changesets as the thing they are copied from.) This makes Anthropic’s achievement significantly less impressive. Anyone who’s put a distributed system into production knows how many issues tend to crop up during the productionizing process. “Our LLM built this thing, productionized it, and dealt with all the attendant challenges over 5 months” is a significantly more compelling narrative than “the source control team at Meta had spent 10 years building and productionizing this system, and we were able to point our LLM at it and rebuild it in 5 months”. …and yet, it is still quite an achievement. Being able to point to an existing system and rebuild it in this short a period is still quite stunning. It is shocking to me that Anthropic didn’t just say they copied Mononoke and rebuilt it in 5 months. That is still noteworthy, even if it isn’t as grand. Surely they knew they would be called out? It is always good to situate your work in the larger context. We all stand on the shoulders of giants! There is nothing wrong with borrowing and adapting existing work to new contexts — that is the vast majority of what I do as an engineer. When you position your work as derivative, you are acknowledging those that came before you, as you hope to be acknowledged by those who come after you. There is nothing without the team. On a personal note, it’s been many years since I worked on Mononoke. There is a team that still carries the torch forward all these years later. Anthropic ripping the Bonsai data model off hit me hard, but spare a thought for the team working on it now: those who were most directly plagiarized. Imagine how they must feel about their work being deliberately copied wholesale and intentionally presented as someone else’s. It’s been two days since I first posted about this on Bluesky and Linkedin, and I haven’t seen an update to the original post yet. This remains yet another shameful example of large AI companies appropriating the commons and presenting others’ work as their own. I don’t know what it will take to rebuild bridges from here, but my default assumption now is that Anthropic’s public engineering presentations are largely bad-faith ripoffs. That’s a shame.

0 views
Farid Zakaria Yesterday

Always, sometimes, never

Exit 0 means your program exited 0. That’s it. That’s all it means. 🍞 I have been working on a deterministic VM called Rewind VM , where “a run” (i.e. test, command etc.) is a function of its inputs including the thread schedule. The determinism comes from the tool recording every step which lets you replay it exactly. This alone is a pretty good way to find flaky tests: run the test under Rewind, then runs it under many different thread schedules, with some slight latency added, and failures often crop up. 🐛 Feedback however was that it was not enough: the tool could find a failing schedule, but it could not tell you if that schedule was actually a bug. It only knew that the run ended differently than the original schedule, which could be a crash, a timeout, or just a different exit code. That is not enough to say “this is a bug”. Someone pointed out that I had built most of a property-based testing tool, but I only had one property: matching exit codes. What is property-based testing ? If you have used QuickCheck or Hypothesis , you have already used the idea. You write a property, or constraint, that must hold for every input. The tool generates lots of inputs, and when one breaks the property, it shrinks it down to the smallest input that still fails. already did the generating and the shrinking. The inputs are thread schedules, and narrowing shrinks a failing schedule down to the one step that causes the failure. The only property though was “the run ends the same way schedule 0 did”: the same exit code and the same outputs. That’s a pretty low bar, but easy to improve. 🙃 Rewind now lets specify properties that must be true for every run, or must be true for at least one run, or must never be true in any run. Let’s keep the bank from last time : two tellers deposit into one account from two threads, without a lock . This time the example is in Java as a JUnit 5 suite to appeal to my Enterprise brethren. 1 A teller that runs between the other’s read and store writes a stale balance over the other’s deposit. 💥 We include a “typical” test suite: one teller, two tellers concurrently, and a new account being empty. We run it and see all tests pass and head home for the day. 🍺 Is the code correct? Let’s use Rewind to dig further. Before even looking at the balance, Rewind knows a lot about what a run did . Every open, write, rename, close, fork and exit is in the trace, with the step it happened at. Rewind ships properties computed from the trace alone: Let’s throw a few at the bank and only run schedule 0: Interesting! writes its performance counters to 2 . It has nothing to do with our bug, but I included it because I learned something new and it could have been a bug if it did not include the process ID. The file properties shine for bugs between processes. The properties tutorial has a program that rewrites its config in place while another process rereads it. Its own test fails only when a read lands between the truncate and the last write, but flags it on the very first run. 😲 The bank’s real invariant is not in any syscall though. It lives in memory in our example: the balance variable must add up . For that there is the Rewind SDK , a tiny library you call from your program. Each call writes one line to , a device in Rewind’s VM, and the trace keeps it with the step, process and thread that wrote it. 3 must be true every time the program reaches it. is its opposite: a run that reaches it at all fails. These are your typical , except we get the whole replay if it fails. is the one I find the most interesting and tough to think through at times. 🤓 It tests the search: its condition must be true in at least one of the runs check tries, and it never fails a run. In model-checking terms, is a safety property (nothing bad happens in any run) and is a reachability property (some run gets there). Here it asks whether any run had both tellers inside at the same time. Look at the output above again: The suite passed under schedule 0, but one teller always finished its deposit before the other started. That pass told us nothing about the race. 🤷 Let try its default 64 schedules: That took 40 seconds on my laptop 4 and we found that two deposits went missing. The first line is the again: of the 17 runs check tried before it found the failure, 11 had both tellers inside at once. The fix is the obvious one: hold a lock from the read to the store. Every schedule passes, but is that enough to make us feel warm and fuzzy? The line is what gives me the warm embrace: in 42 of the 65 runs the tellers ran concurrently, but the lock prevented the bug. ✅ 5 A condition that is only true when the bug happens can never be true once the bug is fixed. 💡 Java developers though love writing JUnit tests. Fear not my FizzBuzzEnterprise colleagues, Rewind has you covered: the SDK has a JUnit 5 extension. Put on the test class and it marks each test’s start and result. If you can’t touch the code, reads the XML reports the runner wrote instead: Maven’s surefire, Gradle, pytest’s , whatever writes the format. The Rewind app shows the timeline of a run, with the tests and the build log. The failing test is red, and the event card names the assertion that failed. The strip under the timeline has a span per test: green passed, red failed. Each include a helpeful tooltip with the test name and the steps it ran. All the other Rewind features can then be used to help isolate the cause: the source panel, gdb on a fork at any step, the thread lanes and Check from here. There is a SDK for many languages already included in the Rewind repository. They are tiny, and the only dependency is the Rewind VM itself. The SDK is a single file or two per language, and you can copy it into your project. 6 The properties tutorial goes through each piece step by step, and the advanced tutorial has script properties and a file of properties to keep beside your tests for the more adventurous. If you happen to find any interesting bugs with Rewind let me know. I am keeping track of a small leaderboard of the best ones. 🏆 It is in the Rewind repository, next to the C version.  ↩ turns it off.  ↩ Outside Rewind the device does not exist and every call does nothing, so the calls can stay in your code.  ↩ The JVM is chatty: 148,479 steps for three tests, where the C equivalent takes about 4,500.  ↩ This counter must sit outside the lock. With , the second teller would wait before it reaches the counter.  ↩ The SDK’s README has the format instrunctions if you want to write one for another language.  ↩ C and C++ : , Go : and for Python : , and a pytest plugin that loads itself Java : and the JUnit 5 extension It is in the Rewind repository, next to the C version.  ↩ turns it off.  ↩ Outside Rewind the device does not exist and every call does nothing, so the calls can stay in your code.  ↩ The JVM is chatty: 148,479 steps for three tests, where the C equivalent takes about 4,500.  ↩ This counter must sit outside the lock. With , the second teller would wait before it reaches the counter.  ↩ The SDK’s README has the format instrunctions if you want to write one for another language.  ↩

0 views
baby steps Yesterday

What agents mean for Rust (and vice versa)

As someone who has made a career of programming language design, I definitely have moments of existential dread about the rise of LLMs. I started coding in 5th grade on an x86 1 that ran at 5MHz, had something like a 5MB hard-disk and 512K of RAM 2 . Computers were really, really different back then. But honestly, programming wasn’t. For all the advances in IDEs and programming languages and so forth, the basic act of entering code into a file has remained surprisingly constant 3 – right up until a few years ago, when everything kinda turned on its head. That’s been exciting and empowering at times 4 but also scary and disorienting. Will my skills in programming matter? What about my skills in programming language design (such as they are)? This blog post is my attempt to answer those questions. So as not to keep you in suspense, let me just give you the conclusion. In short, yes, I believe there will still be a role for humans in programming . And yes, I think that programming language design is still relevant . And, naturally, I also happen to think Rust is a really good fit for agentic development – but that’s not to say we can’t make it a better fit . And that’s what this post is ultimately about: what makes Rust and agentic development work well, and where we could double down on those strengths. This is a kind of “blog post companion version” of a talk I gave this week at REBASE, part of SPLASH . You might also enjoy the slides from the talk I gave at IWACO, IWACO and Rust: hidden links revealed , which was a bit more of a retrospective (no soundtrack for those, though). In any case, this turned out to be a great conference! Jack Huey presented on the Rust Vision Doc and, quite to my surprise, Steve Klabnik and Dorian Scheidt presented “LLMs as Collaborators in Language Specification and Design” , talking about their process in building out Rue . It was fun to see Steve again. On top of that, there was a ton of great research presented at IWACO in particular. I was particularly taken by the work on Reachability Types and Information Borrowing . I also really liked learning about Hylo Lang , particularly their approach to projections. Clever and cool. Rust is popular right now. Very popular: Stratospheric among the breakout languages is TypeScript, cropped from the chart and sitting currently at +1200% growth from the prior year. [..] The second most rapid recent growth is in Rust. Meta engineers have written twice as much first-party Rust code so far this year than in the previous 9 years combined. — David Tolnay (emphasis mine) Some of that is because agents make it very easy to try out new things. And some of that is because Rust has a reputation for being performant and, if it’s just as easy to pick any language, why not pick one that will yield faster execution times? But I think Rust is popular for another reason: because Rust happens to be a really good fit for agentic coding 6 . Of course, I would, wouldn’t I? The point of this post is (1) to argue for why that is and then (2) to discuss what we might change about Rust to make it work even better. It seems to me that an effective “software factory” will have three pillars: None of these pillars are solved, but some have made more progress than others. Rust is designed to give “good performance by default”, making the idiomatic thing typically also be the fastest thing. But another key part of Rust is that you have the knobs to eke out better performance when you need it. You control when something is stack- or heap-allocated and where pointer indirection occurs. If you want to, you can force the layout of your structs to be done in a particular way, or decide where to introduce boxing into your async stack frames. In the limit, you can put in inline assembly. In the past, learning how to “tune the performance knobs” could be a bit of a black art: but agents are making that much easier. 7 It turns out that agents are really good at fine-tuning the performance of existing code. For example, people who work on super high-performance cryptographic algorithms used to do so by hand-tuning assembly code. But those people tell me that they are now turning to agents for that same job. More prosaicly, a lot of people building network services are finding that, using a profiler like dial9 , agents can quite effectively diagnose async performance pitfalls, like long polls or blocking. Therefore, I think the task for Rust is clear. We keep on with our goal of “low-level enough for a kernel, high level enough for a GUI” . If anything, I think the shift around agents means we can tolerate a bit more “noise” in the form of explicit calls to or – but not too much, since we still want the “happy path” of the code to be clear and evident 8 , even as we surface details that are important in specific scenarios (like tracking precisely how many clones you have of a channel endpoint). Combined with a profiler, you get an effective feedback loop to get your code running fast: As usual though, while a reputation for good performance is what brings people to Rust, what makes them want to stay is a sense that using Rust “just seems to work better”. The basic theory is that Rust’s type system and guardrails help keep agents on track : rust is a perfect language for agents, given that if it compiles it's ~correct I think there’s truth in that: languages like Rust, Ocaml, or Haskell all share this “if it compiles, it works” feeling, and I think that agents will benefit from that. Testing can show the presence of bugs, but not their absence. — Edsger W. Dijkstra, 1970 Writing tests has never been enough to show that your program is correct – but, with agents, it’s not even close. It happens so often that my first few tests seem great and then the next one goes completely bonkers. Usually bonkers in a way where I cannot even imagine how that bug could have come about. Then I dig in and I realize the agent completely missed the boat on the logic I was trying to express. 9 This is where a type systems really shines – particularly an advanced one like Rust. Type systems give you some guardrails that keep the agent on track. In Rust, those guardrails extend beyond simple stuff like “do all fields have the correct names” and to stuff like never having to close a socket . Type systems can show the absence of bugs, but not the presence of correctness. — Me, failing to coin a phrase of equal eloquence 10 , 2026 So yeah, type systems are helpful! But they have inherent limits. A type system is a simple set of rules that, if you follow them, make sure that you avoid (certain kinds of) mistakes. But they don’t tell you that you do the right thing – only that you don’t do (certain kinds of) wrong things . If you want to go further, you need a proof system – something that will let you show that richer properties are actively true, not just that you’re avoiding bugs. As it happens, there are a lot of interesting proof tools for Rust, like Verus , Creusot , Aeneas , and Kani . As a starting point, you can prove that your code is panic-free, which will eliminate a lot of bugs, though it is still fundamentally a “type-checker-like” property (i.e., you avoid doing things wrong). But you can also go further and add assertions that show your code is computing the results you expect. Deplying proofs is not just good for getting code right – it’s good for getting code fast . This is somewhat counterintuitive, but it’s true. Earlier I mentioned how optimized cryptographic algorithms were now being written by agents . Part of what makes that possible is that cryptographic algorithms have a very clear mathematical definition. This means that you can basically tell the agent “do whatever you want, as long as you can prove that the code still computes the correct result”. These proofs can be done with theorem provers like Lean or Rocq . The blog post “Why Lean is faster than Rust” makes the point quite well. For Rust, a good example of this would be around unsafe code. Right now, people are sometimes reluctant to deploy unsafe code even if it might make their code faster because it’s not worth the risk of getting it wrong. And I applaud that effort. But what if you could use a prover to show that your unsafe code is, in fact, safe (i.e., incapable of causing undefined behavior)? Then you’d be free to optimize to your heart’s content. You might wonder: if we’re deploying a proof system on our code, do we still need type systems? I think the answer is definitely yes. Type systems are infinitely simpler to work with, which is why they are much more popular. Using a type system lets you rule out all kinds of annoying bugs so that you can focus your “proof energy” only on the important stuff. As a simple example of this, consider the following Java code: Without seeing more code, it is impossible to prove whether this assertion is true or not! This is because there could be any number of other threads running around mutating . In contrast, the following Rust code must be true (at least, so long as the operator is reflexive for ): We know this because the type system of Rust guarantees that implies a unique reference. This is in fact exactly how Verus works. By trusting the Rust borrow checker to track uniqueness etc, it simplifies the job of the SMT solver, making proof checking must faster and more reliable than it would be otherwise. So my take is that Rust should double down on if it compiles, it works . As expressive as Rust’s type system is, there are plenty of things that it cannot capture. This includes fairly common things, like this method only reads one particular field or internal references , but also fancy things like “no logging of personally identifiable information”. We should work to lift those limits, giving agents room to prove more complex properties. We also need to improve the experience of integrating a proof tool by working towards an extensible compiler . As cool as the existing Rust-based proof tools are, using them is a janky experience involing annoying macros and pinned compiler versions. We can do better. I’d like to propose a north star for Rust: no more unsafe code . By that, I don’t mean that we never use the keyword . Rather, I mean that we have the power to prove that all the unsafe code we write is correct and cannot cause undefined behavior. Don’t get me wrong: knowing exactly what code needs to be vetted is a huge step forward, as is normalizing the idea that libraries need to be responsible for protecting their users from undefined behavior via safe API boundaries 11 . But given agents’ ability to find vulnerabilities, I think we need to up-our-game if we want to stop the steady stream of CVEs. 12 But before you go about proving things or optimizing them, you need to have a clear idea of what you are building. As far as I can tell the state of the art here is basically variations on “markdown-driven-development”, developing docs and hoping that agents pay attention. I don’t know how much of a role for Rust there is in this space. I think there are some steps we might wind up taking that could be helpful here – for example, having ways to separate out interface from implementation so that it’s easier to review the interface in isolation or to see when the agent made changes there. 13 Or perhaps just providing betters tools to review that. I also think there’s space for dedicated “modeling languages”, something that let you iterate quickly with agents on the high-level designs and invariants without having to get into the weeds and read the code. I have more thoughts on this but it merits many blog posts all of its own. For the moment, I’ll start by pointing you all at this post by Kari Wilhelm, “Principles of Anchor Engineering” , which I think does a nice job of describing what it means to pull out the key elements of a design and drive the coding from there. We covered a lot of ground here, so let me put this all together. What makes Rust a good choice for developing with agents? And what could make it better, from a language design perspective? Overall, I think it’s very similar to what we were doing, except that the way we weight the tradeoffs is tweaked to account for agents doing the code authoring, and humans focused more on code comprehension: As a final close, let me point you at this interesting article by Marc Brooker, “What’s easy now? What’s hard now?” . He posits that the more it is possible to clearly specify success criteria for a task, the easier it is, and that we may find that tasks we traditionally think of as ‘hard’ (e.g., building out an efficient implementation of a cryptographic algorithm) may soon become automated, whereas tasks that we have thoght of as ’easy’ (e.g., making a unique, compelling website) may become more valued. Looking at it from a PL point-of-view, I think Marc’s point reinforces my sense that the biggest action is going to come from design languages , things that let you capture the architecture and intended behavior at a very high-level. The goal would be to let humans intuitively specify a design that gets translated into effective guardrails, whether that’s type system checks, lints, or theorems to be proven. Agents would then take on the task of translating the design into code written in a traditional PL like Rust, with humans looking at it only rarely. This doesn’t make the design of traditional PLs less interesting, but it definitely makes the tradeoffs very different than they were before. Secretly I have always been jealous of people that coded using punchcards and stored things on gigantic rolls of tape or whatever. I just want to be world weary so badly! I am kinda delighted that I’m finally old enough that I can say things like “I remember when we had to edit CONFIG.SYS before we could play a computer game!” and younger programmers will gasp in horror. 5 But I still feel like I must sound like a silly kid to folks who were around “back in the day”.  ↩︎ I still remember when my dad told me he had bought me a 10MB disk and secretly he had bought a 40MB disk to surprise me. It seemed absurdly large. “I’ll never need a new disk again!”  ↩︎ I mean my god, we’re even using again! My first editor!  ↩︎ I built an electron app! And it was so easy to do! And reading weird papers and things is so much more accessible now that I can ask an LLM to translate all the math jargon for me.  ↩︎ I remember once trying to tell Alex Crichton how I used to “order shareware from a paper catalog by putting a check in the mail” and he was like “I do not understand any of the nouns in that sentence”. Highlight of my life, right after Rust 1.0. Oh, and maybe the birth of my child and getting married. I guess.  ↩︎ I’m not saying Rust is the only language that’s a good fit. I’m not even saying that the way that Rust is a good fit is the only way to be a good fit. I have heard for example that Go is a really good fit for agentic coding and I believe it: I think it hits a different sweet spot, one that helps agents iterate quickly (although I do suspect agents will let data races and subtle bugs slip through that Rust would have prevented).  ↩︎ The fact that agentic development makes more room for knobs is good for Rust performance, but it is quite likely an even better fit for performance in other languages. Tuning a GC has traditionally been a job that really requires a GC expert, but agents can likely fill that role pretty well these days.  ↩︎ On this pont, I’m even more convinced of the importance of ergonomic RC now that I work with agents. Agents are good at introducing the extra clones and things you need to deal with capturing around async tasks, but the resulting code is so annoying to read, it really hides what’s going on.  ↩︎ “Claude, this is not what we talked about!” – me, all too often.  ↩︎ So close though, right? I just .. couldn’t land the plane.  ↩︎ All too often, C++ libraries consider it adequate to tell users “you’re holding it wrong” – i.e., that they are responsible for causing undefined behavior by misusing the API. Rust takes a clear position that a safe API has to protect its users, no matter how much they abuse it.  ↩︎ To be fair, if Rust is encountering a stream of CVEs, other languages like C++ and Java are encountering a veritable flood, since they lack the protection of Rust’s type system. st takes a clear position that a safe API has to protect its users, no matter how much they abuse it.  ↩︎ The revenge of files?  ↩︎ Design: figure out and specify clearly what the code is supposed to do. Construction: author code that does what it is supposed to do. Optimization: optimize the code so that it runs efficiently. It offers good default perf (why pay more?) and, in conjunction with a profiler, can be tuned as much as you want. The type system gives stronger guardrails, and if you setup your agents right, you can strengthen those guardrails through techniques like new types. If it compiles, it works – our type system is our big advantage, we need to make it more expressive and more functional so that agents don’t get stuck trying to work around it! And as an adjunct, establish a North Star: Enable Unsafe code without unsafety by supporting proof, and see the most widely used Rust libraries proven sound. Low-level enough for a kernel, high-level enough for a GUI – make sure we expose the knobs needed to tune for performance, while also making the code’s intent clear (but don’t worry about golfing the code down to an absolute minimum number of characters). Extensible and versatile – one of Rust’s great strengths is that, with macros + our type system, we support DSLs and a wide variety of targets. We need to bring that spirit of extensibility into the compiler so we can target more styles of development (e.g., GPU, deep language interop, etc) and also integrate theorem provers and other tools that require more than just tokens. Secretly I have always been jealous of people that coded using punchcards and stored things on gigantic rolls of tape or whatever. I just want to be world weary so badly! I am kinda delighted that I’m finally old enough that I can say things like “I remember when we had to edit CONFIG.SYS before we could play a computer game!” and younger programmers will gasp in horror. 5 But I still feel like I must sound like a silly kid to folks who were around “back in the day”.  ↩︎ I still remember when my dad told me he had bought me a 10MB disk and secretly he had bought a 40MB disk to surprise me. It seemed absurdly large. “I’ll never need a new disk again!”  ↩︎ I mean my god, we’re even using again! My first editor!  ↩︎ I built an electron app! And it was so easy to do! And reading weird papers and things is so much more accessible now that I can ask an LLM to translate all the math jargon for me.  ↩︎ I remember once trying to tell Alex Crichton how I used to “order shareware from a paper catalog by putting a check in the mail” and he was like “I do not understand any of the nouns in that sentence”. Highlight of my life, right after Rust 1.0. Oh, and maybe the birth of my child and getting married. I guess.  ↩︎ I’m not saying Rust is the only language that’s a good fit. I’m not even saying that the way that Rust is a good fit is the only way to be a good fit. I have heard for example that Go is a really good fit for agentic coding and I believe it: I think it hits a different sweet spot, one that helps agents iterate quickly (although I do suspect agents will let data races and subtle bugs slip through that Rust would have prevented).  ↩︎ The fact that agentic development makes more room for knobs is good for Rust performance, but it is quite likely an even better fit for performance in other languages. Tuning a GC has traditionally been a job that really requires a GC expert, but agents can likely fill that role pretty well these days.  ↩︎ On this pont, I’m even more convinced of the importance of ergonomic RC now that I work with agents. Agents are good at introducing the extra clones and things you need to deal with capturing around async tasks, but the resulting code is so annoying to read, it really hides what’s going on.  ↩︎ “Claude, this is not what we talked about!” – me, all too often.  ↩︎ So close though, right? I just .. couldn’t land the plane.  ↩︎ All too often, C++ libraries consider it adequate to tell users “you’re holding it wrong” – i.e., that they are responsible for causing undefined behavior by misusing the API. Rust takes a clear position that a safe API has to protect its users, no matter how much they abuse it.  ↩︎ To be fair, if Rust is encountering a stream of CVEs, other languages like C++ and Java are encountering a veritable flood, since they lack the protection of Rust’s type system. st takes a clear position that a safe API has to protect its users, no matter how much they abuse it.  ↩︎ The revenge of files?  ↩︎

0 views
Dayvster Yesterday

The Best Thing About Side Projects Is Being Allowed to Care Too Much

A project can be worth your time without becoming a business, a portfolio piece or your most efficient use of an evening.

0 views

Annualized Enron Rate

If you liked this piece, you should subscribe to my premium newsletter, and you can subscribe on the following links: $70 a year , $18 a quarter , or $7 a month . In return, you get a weekly premium newsletter that dives deep into the finances of the AI bubble. Over the past few months, I’ve published a two part guide to the world of AI debt, an analysis of the (dubious) impact of generative AI on the global economy , deep analyses of the biggest players in the AI infrastructure space like NVIDIA (part one and two ) and Oracle (part one and two ), and the role private credit is playing in funding AI data centers , and how private equity, reeling from years of successive failed software acquisitions, is doubling down on the AI bubble .  On Friday, we’ll take a look at the JOBS Act — or, the Obama-era legislation that created the regulatory environment that would ultimately prove essential for the AI bubble to inflate - and why it might be time to reform or entirely repeal it. If you want to get in touch — and especially if you have any juicy information about Anthropic, OpenAI, or any other companies in the AI bubble — hit me up on Signal at ezitron.76. I’m also on IB on your Bloomberg Terminal.  Soundtrack: Cleopatrick - Hometown The entire AI bubble is inflated based on stupid, made up numbers that only exist to pump the bags of investors and make the AI startups look more successful than they are. It is a failure of journalism that they have been popularized, as they do not tell us very much about anything, other than that there’s a new, bigger number to get excited about. Last week , the markets dropped on the news that OpenAI’s annualized recurring revenue (ARR) — which was reported as $70 billion by Axios and confirmed by the Financial Times — was actually $50 billion . The number in question was, according to the FT , inflated by “grossing up” the total to include sales through cloud partners, a discrepancy between how OpenAI and Anthropic make up a number that doesn’t really tell anyone anything: Back in August, Anthropic had told investors that it had hit $65 billion in annualized run rate , but at no point defined what that meant, what period it referred to, what any of the underlying numbers are, or what “gross” versus “net” bollocks it was playing. Per Irrational Analysis the calculus might have been even sillier than that : This is the problem of saying what the revenues of a company might be based on numbers that are not its actual revenues. There is absolutely no value in using “annualized run rates” for anyone other than the company and its investors, and the fact that modern tech and business journalism continues to accept it for what are meant to be the largest and most-important companies in the world is a sign that something is very wrong with how we cover the tech industry. I am not going to spend much time dwelling on gross versus net. It appears that, per Reuters , 47% of Anthropic’s 2025 revenues came from sales made by Google and Amazon, who take a 16% cut as opposed to the roughly 20% that Microsoft takes from OpenAI. It appears that Anthropic for whatever reason counts every dollar of sales as part of its annualized run rate figure and OpenAI does not, for reasons that escape me, as I simply don’t buy that it is “more ethical.”  My evidence? The following quote from the FT, emphasis mine: This is the same OpenAI that tried to claim that a $34 billion loss was actually an $8 billion loss when the FT asked them about my reporting on its audited financials . I must also say how utterly disappointed I was to see how Bloomberg credulously reported that OpenAI “expected to hit $70 billion in annualized revenue by end of 2026,” a transparent attempt to send the markets back up with a story that tells the world less than nothing.  Wow, OpenAI, by the end of 2026, will increase a number that “represents a projection of [its] yearly sales based on a shorter period” by $20 billion! What is the period in question? Who knows! How is that number derived? Who cares! Number go up! Put the story in the bag! Your job is not to cover the tech industry, it is to celebrate it! Stop thinking! In other words, OpenAI’s made up number was actually lower than Anthropic’s made up number because of the way it made the number up, but by the end of the year, the made up number would be bigger than the other made up number. These made up numbers are reported by the largest and most well-respected news outlets of the world, who lend said made up numbers respectability despite the numbers in question being utter bullshit. I’ll give you an example. For the first half of 2026, OpenAI made $12.4 billion in ($5.7 billion in Q1 and $6.7 billion in Q2) revenue per The Information and the Wall Street Journal , while Anthropic, per the WSJ and the FT , made $15.5 billion ($4.6 billion in Q1 and $10.9 billion in Q2). We do not have consistent coverage of their underlying costs, but in Q1 (per The Information), OpenAI spent $8.6 billion on training and $3.5 billion on “cost of revenue,” with no reporting on its sales and marketing spend where it allocates the cost of serving free users or discounts.  Anthropic said it had hit an annualized run rate (undefined period multiplied by undefined number) of $48 billion on May 28 , or roughly 430% more than its entire revenue in the second quarter. In fact, if you added up every dollar that both Anthropic and OpenAI made in the first two quarters, you’d be $19.1 billion short of Anthropic’s May “run rate.” We do not know how any of these numbers were actually conceived outside of they are somehow derived from a non-specific 28 day period. The information they convey is sparse, if it communicates anything at all.  Reporting “run rates” is a marketing exercise, and if you disagree, please answer me the following: what does a “$65 billion annualized run rate” tell you about Anthropic, exactly? It’s MEANT to make you think it will make $65 billion a year in revenue, but that is not what it actually means. This number tells you nothing, and exists only to poison the well of information.  Without an actual period of time — and I mean an exact one, such as “July 1 to July 31, 2026” — and the exact way it was calculated, this number effectively means nothing, and reporting it without this information only serves OpenAI or Anthropic. You can say “investors use it all the time” all you want. Investors are fucking stupid for using it. If the argument is “it shows how fast OpenAI is growing,” why don’t you find out the actual growth rate of the company?  The fact these numbers moved markets is a reflection of the definitive — and accepted — ignorance built into the entire AI bubble, where despite trillions of dollars on the line , we know very little about the actual underlying numbers, and those numbers we do know are inflated using techniques that would get you shot by an accountant. In fact, we don’t know most of the numbers that would actually tell us whether any of this is a good idea. Reporting on the true revenues of the AI industry feels less like financial analysis and more like legal discovery, and it’s fundamentally insane how little tangible, meaningful information that exists to feed the trillion-plus dollars in capital expenditures and endless full-court press in the media about how AI is the next big thing.  We do not know Google, Amazon or Oracle’s AI revenues, and we have a single year — fiscal year 2026 — of Microsoft’s AI revenues based on an estimate from Bloomberg calculated from its disclosure of its OpenAI revenues in an SEC filing . We do not know how much each individual service makes, how much their true revenue shares are with the AI labs or, as I discussed a few weeks ago, how much actual, operational AI capacity exists as a result of the trillion-plus dollars in capital expenditures , though Bloomberg and I have both reported that Microsoft has around 2GW of it, even though it claimed to bring online a gigawatt in each of its last three fiscal quarters.  We do not know the revenues or much about the economics of [include funding totals) Perplexity, Harvey, Instinct, Reflection, Cognition, Replit, Lovable, and Factory, all of whom have raised somewhere in the region of $15.8 billion in funding, and have a combined valuation of $215.8 billion. We do not and will never know the true revenues or costs of Cursor’s operations as a result of its acquisition by SpaceX , and as a reminder, annualized revenues are not actual indicators of the economic health — the revenues, costs or cash flows — of any of these companies.  Perhaps this was permissible in the past because so much less capital was being annihilated in the name of startups, but things have escalated so much further than any other era, including the Dot Com bubble. Look, the entire AI bubble has been inflated based on the implicit belief that there will be demand — from AI startups and elsewhere — for AI compute, to the point that Goldman Sachs says that hyperscalers need AI startups to make $425 billion in annual revenues just for the hyperscalers to break even … and we don’t even know, outside of Anthropic and OpenAI, how much any AI startup actually makes. What we do have is “annualized run rates” pegged to non-specific time periods and non-specific numbers that tell us, for example, that Cognition hit $1 billion in late September, a number that means next to nothing. Even when The Information was able to report that Cognition would burn $800 million in 2026, it resorted to saying that it was “generating around $900 million in annualized revenue, or $75 million a month” as of August 27 2026 — adding that executives had “projected it would hit $1.5 billion in annualized revenue by end of year,” meaning that two journalists were able to successfully find out its actual expected burn, that it burned $200 million in Q2 2026…but not the actual revenues that the company generated on a quarterly basis. Let’s be clear about something: the reason we’re not getting these numbers is that these companies are not actually making these amounts on an annual basis. If Cognition was actually going to hit anything close to $1 billion — and let’s be honest, it’s likely less than $500 million! — it’d leak it versus using these weird monthly snapshots. It is astonishing that we, four years into the AI bubble, do not know the revenues of more than a handful of AI companies outside of OpenAI and Anthropic. All we have is a mishmash of annualized run rates, and at this point I have to wonder if it’s a failure of journalism, successful opsec, even more successful marketing, or that these companies don’t have great accounting.  But really, go and look up basically every AI company. Perplexity? Nothing. Harvey? Nothing. Cursor? Years of reporting — endless thousands of words spent — and nary one report I can find, outside of these fucking annualized run rates.  Part of the reason, I imagine, is this chart from Ramp that I’ve brought up before: From what I hear, the vast majority of those 1% of customers are AI startups that power their products using OpenAI and Anthropic’s models, predominantly using monthly subscriptions that allow users to burn way more in tokens than their subscriptions actually make. For example, SemiAnalysis did a deep study into the amount of tokens you could burn on the various different AI subscriptions out there, finding that you could burn anywhere from $83 to $118 a month for $20 and from $1,264 to $1,331 a month for $200 on Cognition, dropping to $46 on a $20-a-month plan and $507 for $200-a-month on Cursor when using Anthropic’s models. While OpenAI’s models are being dropped from Cursor, SemiAnalysis found you could burn $154 a month using OpenAI’s models on Cognition’s $20-a-month plan, and $1,736 a month on its $200-a-month plan. The various boosters reading this and making noises like the Skesis from Dark Crystal will say “but these companies get discounts!” as if that makes up for the fact that customers are able to burn two to six times their actual subscription every month. They’ll also argue that “this is the gym model, and most customers don’t spend that much,” a statement that they have no proof for other than that it makes them feel better.  The problem — and the reason I’d argue that the actual revenues of these companies are so shrouded in secrecy — is that the underlying economics do not match up when you consider that effectively every AI startup has to resell tokens at a discount. It doesn’t really matter how much revenue you make if you’re sending twice or thrice or five times that amount out the door to Anthropic and OpenAI, but saying a larger “annualized run rate” makes the amounts you’re raising far less worrying than what I imagine are particularly-shrimpy sales. Let’s take Harvey — which raised $550 million at a $15.5 billion valuation in September — as an example. As of early August, Harvey had hit $350 million in annualized revenue , up from $190 million in January. If we assume it uses the same “trailing 28 days” model as Anthropic, this means that it made $26.9 million in a 28-day period ending sometime in August, up from $14.6 million in a period that ended some time in January 2026 . Since December 2025, Harvey has raised a total of $910 million across three rounds , or roughly 33.8 times the estimated underlying revenues of its most-recent run rate, which increased by 45.7% in that period. Bloomberg claimed in late September that Harvey’s Gross Margins had gone from 50% in January 2026 to negative 50% in June 2026 to “positive again” (I imagine in September) due to using open source models, but something about those numbers is deeply weird to me, mostly because I’ve never, ever heard of a company having had that happen.  And none of that explains why a company that makes tens of millions of dollars in revenue needs to raise hundreds of millions of dollars every few months, unless, of course, most of those dollars are flowing immediately to Anthropic and OpenAI, which is, it turns out, exactly what happened: This is the antithesis of any good business. In basically any industry, the more demand you have, the more money you make, but in AI, the more demand you get, the more money you lose, and your most engaged customers are also your least-profitable.  However you might rationalize the underlying economics of a company like Harvey, the numbers we do know are extremely worrying — $900 million raised since December 2025, and, in my most-optimistic calculation, around $175 million (though likely less than $150 million) in revenue through the end of August, for a company that raised another $600 million across two other rounds in 2025. That’s $1.66 billion in about a year and a half to make an unprofitable company with less than $30 million in monthly revenue that is somehow worth $15.5 billion. Harvey has categorically failed to find product-market fit, unless we qualify that as “literally finding a customer.” It’s very clear that its underlying product cannot support itself, and that the company is entirely-dependent on venture capital, raising at least $160 million every three to six months since February 2025. It is abundantly clear that Harvey’s customers — like every AI startup — do not actually want to pay what its services cost, which means it does not have product-market fit, nor what I’d call a “business.” Then there’s Cognition, which has raised a combined $3 billion in 2026 alone (in May and September ), with its run rate going from $492 million to $1 billion in that period. If we assume the same calculation as Anthropic uses, that means revenues were $37.8 million and $76.9 million respectively, and that its last two rounds of funding are roughly 39 times the size of its 28-day trailing revenues. It is unclear what has substantively changed about the company, other than that the $400 million it raised in September 2025 was insufficient to last. I know there are going to be venture capitalists who argue that “these companies are just raising opportunistically,” but that doesn’t explain why every AI startup raises so much money in so little time, and how one reconciles that distance with any reality outside of “we can raise unlimited money forever.”  And if they can’t do that, large chunks of OpenAI and Anthropic’s revenues disappear.  Let me summarize all of this in simple terms, as it’s all terribly important. Every AI startup is effectively an extraction mechanism for OpenAI and Anthropic, reselling their tokens through their services at a massive discount because users are unwilling to pay the actual cost of using LLMs.  Using annualized run rates allows everyone to feel like this isn’t a problem, because it’s far easier to rationalize that Cognition has raised $3 billion this year and is worth $48 billion if it has $1 billion in annualized run rate rather than $80 million a month in revenue.   The obfuscation of the actual underlying financial of these companies is intentional, because it makes it harder to do the kinds of comparisons I’ve done today,  If you disagree, start giving me actual revenue numbers for these companies instead of your magic elf number you made up or got told. If you’re an investor in these companies and have not been told the actual most recent quarterly revenue, there’s a reason — the real one sucks!  If you know it, leak it if it’s so impressive. You know where to find me. Only one of us is being weird, and it’s the cloister of you who condone using bad information because you know the real number — the actual quarterly or annual revenue — is probably going to make people panic.  These companies are also, at least in theory, the ones that pay for AI compute, which means that we also have a very, very poor understanding of the actual customers behind those hundreds of billions of NVIDIA GPUs. In fact, that’s a great place to go next. People are going to get mad at me for this because they are cowards , but I posit that we have little understanding of the true price that people are paying for AI GPUs, or about the underlying economics of AI data centers writ large. Yes, yes, I know, you’re going to tell me that SiliconData has an index , and that that index shows “GPU rental prices going up,” but these prices overwhelmingly favor spot pricing — as in what it costs to rent a GPU right now — versus what companies are paying on a long term basis. It’s kind of like valuing a shipping company based on skyrocketing spot rates during a capacity shortage rather than the year (or years)-long rates that they regularly charge. You know, kind of like annualizing the data to make things look better. SiliconData claims to create a “single standardized reading,” but does so using a mishmash of non-specific data that “standardizes for rental term length, cluster scale and interconnect” in a way that only ever seems to benefit the providers.  The reason that SiliconData’s index has become so popular is that we otherwise lack many good measurements, which isn’t to say that its measurements are good , just that they’re the best we’ve got at the moment. While I think the company is doing its best with what it’s got, measuring GPU rates in general like this only seeks to confuse the market through abrupt shifts upwards and downwards based on what I imagine are larger contracts ending or beginning — not that we know, because SiliconData does not actually explain what’s changed or why it might have changed. This is a huge issue, because NVIDIA has sold $535 billion in GPUs since 2022, and we still don’t know on any reliable basis how much their customers can rent them for. We don’t know with much certainty how much it costs to run one, or have a firm grasp on what an hourly comparison would be — as in how many dollars an hour it cost to run one — outside of analyst estimates ( and my own model ) that all seem to vary wildly and always end up at a place that says “what a great investment!” There’s also some compelling evidence that the actual long-term rental rates for these things might not be as high as we think. I realize some people might read what I’m saying and immediately want to pelt me with rocks, but I’m just telling you what I’ve found, and if I’m honest, I think I’m doing a better job than the vast majority of people covering this shit, in that I’m trying to actually show what people are paying versus aggregating various publicly-available sources of information to simmer out info-slop. Again and again, I’ve found companies paying way, way less than the supposed going rate of compute. In late April, The Information ran a story about startups renting AI GPUs, specifically focusing on NVIDIA’s B200s, which SiliconData claims rent at $5.94 an hour, emphasis mine: To be clear, the B200 GPU, as part of an 8-GPU pod, works out to about $62,500 a GPU. At this rate, 32% of the first six years of its useful life would be absorbed by depreciation, assuming that it was sold in its entirety for every single hour of every single day of those years.  Then there’s Oracle’s under-construction “Stargate Abilene” data center that landowner Lancium believes will make around $10 billion in annual revenue (see slide 5). At $10 billion a year and 450,000 GB200 GPUs, which works out to — if we assume a take-or-pay rate — to about $2.54-per-hour-per-GPU. If we assume that each of these is inside a GB200 NVL72 at about $3.5 million a piece, that’s about $1.61 per-GPU-per-hour of revenue for the first six years before you get to the COGS. Then there’s this contract between Australian neocloud Sharon AI and ESDS Cloud FZ-LLC , a Dubai-based subsidiary of Indian enterprise cloud company ESDS , renting out 8208 NVIDIA B300 GPUs at $3.30 a month over 60 months (five years). If we assume a cost of $540,000 per eight-GPU B300 cluster, that leaves us with about $1.54 in depreciation over six years, leaving us with about $1.869-per-hour-per-GPU of actual revenue for the first six years, in a contract that is five years long. Here’s another. A contract I found between neocloud Kidz AI ( which rents capacity from a company called Limestone , or, more-specifically, its subsidiary Catalyst Compute) and AI inference company Canopy Wave priced 256 B300 GPUs at $4.30 an hour (per GPU) for the first three years and $3.50 an hour for the last two of the five-year-long contract. Your depreciation costs here work out to about $1.54-per-GPU-per-hour, meaning that you’re losing nearly half of your revenue for the first six years… of a five year long contract. Sure hope there aren’t new kinds of GPUs — or an abundance of older GPUs — after these things end! QumulusAI is a former cryptocurrency mining company that converted into renting GPUs. In this contract , Qumulus is renting out 128 B300 nodes — so around 1,024 B300 GPUs — at $3.70-per-GPU-per-hour, sitting at about $1.284-per-GPU-per-hour of depreciation. Again, sure hope there aren’t a bunch of data centers under construction that have the same chips as these! Buried deep in the earnings report of AI infrastructure company WhiteFiber sits a three-year-long contract with buzzy AI inference firm Baseten, which raised $1.5 billion in June : This all works out to about $1.284-per-GPU-per-hour of depreciation on $4.51-per-GPU-per-hour, which is still more than two dollars less than what SiliconData quotes. As mentioned, BaseTen just raised a ton of money, so it’s willing to pay through the nose, and even then it’s paying so much less than spot. There’s also another contract with a customer in Iceland that works out to about $3.46-per-GPU-per-hour: As I said a few weeks ago , we do not really have any firm understanding of how much AI compute actually exists , to the point that the largest companies in the world (read: Microsoft) are actively misleading the public about how much they’re bringing online. We also have no clear understanding of how much data center capacity is actually under construction, because nobody actually wants to tell us, and reports like this from Sightline Climate claiming 190GW “in planning” lump in every imaginable kind of data center with ones specializing in AI compute. As a result, basically any AI compute capacity estimates are guesses. I’ve seen somebody say there’s “50GW of capacity,” I’ve got guys in my mentions saying that actually Bloomberg is wrong in saying that Microsoft has 2GW of capacity and the real number is 5GW based on nebulous “conversations” that only ever end up as a positive for the AI industry.  In a vacuum of good information, people simply start making things up, which is why The Information published one of the more insane things I’ve read in a while , emphasis mine: I asked Okoye for an explanation, and he gave me one in the comments of the article: All of this hinges on some very wishy-washy numbers about the per-megawatt revenue of AI labs, which in turn hinge on wishy-washy numbers about how much compute labs have. For example, the New York Times reported that Anthropic would have 5GW of capacity by the end of 2026, up from 1.5GW at the end of 2025 , according to statements made to its investors, but I can find no compelling evidence that there was even a gigawatt of compute for it to buy.  If we assume these statements are accurate, then: The peanut gallery will scream and oink at me for not working out how much is inference versus training , to which I say nobody fucking knows how much of its capacity is actually diverted to inference and I don’t even think they know how much capacity Anthropic has writ large! We are basing the vast majority of words written and billions invested in the AI bubble on assumptions built on assumptions built on assumptions, several of which fall apart when you ask simple questions like “how does that work?” or “how did you get that number?”  This would all be significantly less-worrying if it wasn’t for the fact that everything is built on the idea that AI is going to be the panacea for the entire tech industry!  Put another way, NVIDIA plans to sell $670 billion or more GPUs next year on top of the more than $500 billion it’s already sold and $800 billion has been invested in AI startups mostly by people with little or no idea about the underlying economics of the data centers or their customers! A few months ago, a dear friend of mine told me that “nobody knows what they’re investing in,” and it’s taken me a while to fully understand what he meant. The entire world believes we’re in an AI-powered economic boom of data center capex and AI startup growth based on flimsy information sources that vary from fanciful to utterly hysterical, constantly guessing about how much capacity OpenAI or Anthropic or any of their hyperscale sugar daddies actually have operational, or how much a theoretical data center could charge under the best of circumstances to a customer that may or may not actually exist. We are four fucking years into the AI bubble, have little or no understanding of the actual economics of AI, and that which we do have is extremely grim. Yet when you try and tell an AI booster (or many members of the media!) that Anthropic lost $8 billion and OpenAI lost $20.97 billion in 2025, their immediate response is to say that 2026 will be fine because of quarters with discounted compute costs and adjusted operating profits that don’t actually resolve the underlying problem that these companies have $1.3 trillion in compute commitments, with at least $413 billion of them being uncancellable . The hysteria has grown so significant that Gavin Baker of investment firm Atreides (invested in both Anthropic and SpaceX) has simply chosen to suggest that “ nobody is taking them seriously ,” only to disappear into the ether when asked about which of the contracts he believes are “not taken seriously” and “by whom,” probably because he’s talking out of his ass.  This argument is one you make when you are flat out of ideas, and simply hope that people will leave you alone if you sound authoritative enough, and is known in debate circles as the “nuh uh” technique. The reason Baker is deploying it is that he, like every AI booster, knows that while you can fool the press and investors with made up numbers, there’s very little that “annualized run rates” or “ Anthropic ending the year with $100 billion in revenue ” can do when Broadcom CEO Hock Tan, who recently likened AI investors selling their investments on the news of OpenAI's adjusted financials to degenerate gamblers , asks Dario Amodei to pay some of the $161.2 billion in non-cancellable contracts he signed. We live in a climate of intense hysteria and profound confusion, made worse by a media ecosystem that currently appears more interested in sustaining narratives than investigating their underlying truths. The vast majority of hyperscaler AI revenues come from Anthropic and OpenAI’s compute spend that is dependent on near-perpetual funding, much like the vast majority of Anthropic and OpenAI’s revenues come from AI startups that depend on near-perpetual funding to continue their spend.  And to make matters worse, we quite literally have no idea about the underlying financial condition of any other AI companies outside of the main AI labs, and no, annualized run rates don’t mean jack shit.  This is extremely bad and extremely important to resolve. Anthropic and OpenAI’s growth depends on the AI startup ecosystem being able to spend increasing amounts on tokens every single month, without fail, for what appears to be the rest of time. Said startups’ ability to keep doing so depends on venture capital being willing to sling them hundreds of millions of dollars a year each , with each investment increasing the paper value of the company but adding little or no actual qualitative improvement other than their ability to keep playing at the Sam Altman Casino. I genuinely don’t know why most of the tech and business media is ignoring this problem. Is it that it’s too difficult to comprehend? Is it that you, as a writer, truly think that all of this will work out? Is it that you think that Anthropic and OpenAI will just “negotiate out” of their contracts? If that’s the case, what happens to all the data center capacity? Is it that there’s advertiser or editorial pressure to be “positive on AI”? I truly want to know!  Anyway, I’ve realized now that “nobody knows what they’re investing in” applies to basically everything. Most people writing about AI believe it’ll all work out because nothing bad has happened or they have a single statistic that affirms their worldview. Most people are still saying “it’s like Amazon Web Services!” or “it’s like Uber!” or “it’ll be like the Dot Com Bubble,” even though those are not correct or sensible or rational takes that actually mean much other than “money burn good actually,” and that thin level of rationality goes up to the highest rungs of finance and journalism to a degree that turns my fucking stomach. Most coverage of AI lives in its own bubble where nothing bad has happened or could happen, and that every promise will come true. Every deranged, multi-faceted “model” that shows OpenAI or Anthropic will print money in the future is an attempt to get away from very, very simple mathematical problems.  And, fundamentally, I’m just not sure anyone gives that much of a shit about being correct outside of sounding as close to the consensus as possible, which is why it’s been so profoundly strange hearing people say things recently that I’ve been saying for years. You can shove your fingers or whatever other objects you’ve got handy in your ears and say “la la la” all you want, but Jefferies’ Chris Wood just said that “ the most likely long-term outcome of the AI boom will be massive capital destruction in the US ,” and Barclays just said the following (aside: that lab revenue number is completely wrong, but whatever): I want to force boosters to read this like the guy at the end of A Clockwork Orange. I want them to answer me, in detail, why this is actually fine.  I already know the answer: they’d produce some sort of asinine number that shows that growth is parabolic , that there’s insatiable demand for AI compute , that Anthropic and OpenAI are the next Google and Facebook combined , that there’s not enough compute to go around , or another anecdote that is literally anything other than a meaningful response.  There is little difference between how the various run rates, projections, “models” and “frameworks” used to justify future AI investment are used and the underlying tools of a religious con, except the only community you get here is made up of zyned-up twenty-somethings and the elder millennials desperate for their approval. The AI bubble is inflated by bullshit numbers peddled by the ignorant, craven or easily-led. Your ability to distinguish between which of them you’re talking to is critical to not losing your shirt. If you liked this piece, you should subscribe to my premium newsletter. It’s $70 a year , $18 a quarter , or $7 a month , and in return you get a weekly newsletter that’s usually anywhere from 10,000 to 18,000 words and provides vast, detailed analyses of the biggest events and companies in the AI bubble. If you want to get in touch — and especially if you have any juicy information about Anthropic, OpenAI, or any other companies in the AI bubble — hit me up on Signal at ezitron.76. I’m also on IB on The Terminal. The Revenues 80% of Anthropic and OpenAI’s revenues come from 1% of their customers, the vast majority of which are AI startups that spend anywhere from 300% to 1000% of their revenue on AI tokens. AI Startups Run Services at a Loss, Allowing Users to Burn Thousands of Dollars of Tokens for Hundreds of Dollars a Month, Requiring Constant Venture Funding Customers of AI startups are repulsed by the actual cost of tokens, meaning that for every dollar of subscription revenue, AI startups must allow customers to burn anywhere from 2 times to 10 times their revenue in tokens. For example, Cognition’s $200-a-month users can spend upwards of $1200 a month in OpenAI or Anthropic tokens.  Even with these “discounted” tokens, AI startups have very small revenues. As a result, every AI startup runs at a loss. This necessitates raising massive amounts of capital every few months. Every New Model Release Artificially Boosts Revenues Through AI Startups When a new model releases, every AI startup must immediately integrate it, because that’s what their customers expect, and because the customers in question are curious , they’re likely to use the new models more on release. This means that Anthropic and OpenAI get a massive bump of new revenues — funded by AI startups that are allowing users to burn tokens without restraint — with every release. All Of This Is Only Made Possible By Perpetual Venture Funding, And Once It Expires, It Eats Anthropic and OpenAI’s Revenues Alive All it takes for one of these companies to stop being able to spend tens or hundreds of millions of dollars a month on OpenAI and Anthropic’s services to meaningfully reduce their revenue. It doesn’t really matter what big businesses are or are not using Claude or ChatGPT — the underlying revenues of these companies are held up by venture capital by proxy. Facility rent: Hut 8’s lease for this 245 MW site is $7.0B over 15 years. That is about $39M a month. Compute: IREN’s 5-year, $9.7B contract with Microsoft covers about 200 MW of GB300 GPUs. That is about $9.7M per MW-year, or about $200M a month at 245 MW. It’s a GPU contract, so treat it as a benchmark for this TPU site, not its actual price. Lab revenue: the $1.3B is the midpoint of the $50M to $75M per MW-year estimates Ann cites [referring to a comment from the author Ann Davis Vaughan]. [Ed note: Those numbers that she cites come from another article where Ric Boada, the CEO of ten-month-old neocloud Volta, saying:] He figures that the frontier AI labs are generating about $75 million in revenue per megawatt of use a year for inference output compared to an annualized cost to build and provide the infrastructure of $10 million to $15 million per megawatt a year.  Each layer is paid out of the one above it. Even at the low end, about $1.0B a month, lab revenue is roughly 5x the compute bill. That gap is why labs push datacenter developers so hard on timelines. Anthropic, which made $4.6 billion in revenue against (theoretically) 1.5GW of capacity, made about $3 million a megawatt in 2025. In 2026, assuming it makes $35 billion on 5GW of capacity, it would make $7 million a megawatt.

0 views
Chris Coyier 2 days ago

Archived Tweets

I finally got around to importing my whole historical Twitter archive (just my own original tweets, not replies or retweets) into this WordPress site as a proper Custom Post Type: https://chriscoyier.net/tweets I haven’t added it to the navigation or anything else on the site yet. Not sure what I want to do there. Just feels good having my own data. The Tweets show up in the Jetpack-powered search too, which I’ve found nice. I used this and hacked it up a bit to fit my needs, and so I didn’t have to leave it as a permanently installed plugin. It’s coming at a weird time, with quite a few people “going back” to Twitter. It’s actually called X now; I’m aware. It’s named after the hand gesture you do when Elon Musk asks if you’d like to come over for a dinner party: 🙅‍♂️ Casey Newton just saying, “Look, I tried, but X is where the action is,” and John Gruber being like, “Take a whiff; the Elon stench is gone.” I understand both of those things. I honestly really like both Mastodon and Bluesky, but after years and years, the fun and engagement have never reached old Twitter norms. And I miss that! But it also feels like you have to ignore a lot of bad behavior to use a platform that Elon Musk not only owns but literally bought to be his megaphone and power center. Do people not remember the horrible shit he would do on a near-daily basis? Tasteless, dangerous, and often both. I can remind you! Here’s just one straw from a haystack. Elon loves him some Trump. They are big buddies! Elon shouldered up to Trump for the power, and Trump gave it to him. Elon decided to take this power (granted to him by a scepter touch? apparently?) and created a real government organization called DOGE, which is a joke name, named after a joke cryptocurrency that is inherently corrupt. DOGE’s job was to make the government “more efficient” by eliminating funding for tons of stuff. One of the things they did was entirely get rid of the USDS, which was the organization that did incredible work, ya know, making governmental websites far more efficient. Now, our government makes racist video games on the web instead. Not kidding. That’s a fucking game on our own government’s website, where you play a white dude who walks around a page collecting brown people to deport. I find it more than a little hard to swallow.

0 views

Warnock: Harnessing GPU Geometry Amplification for Vector Graphics

Warnock: Harnessing GPU Geometry Amplification for Vector Graphics Mark J. Kilgard and Brian Barran HPG'26 We live in a strange world where the primary use case for GPUs is LLMs, the secondary use case is 3D graphics, and one has to perform contortions to accelerate 2D graphics with a GPU. This paper presents a technique to use modern GPU hardware features to offload a portion of 2D graphics rendering that is typically performed on a CPU. There are three hard problems associated with high-quality vector graphics: winding rules, curves, and antialiasing. Say you have given a polygon like so: and you would like to know if a particular point is contained within the polygon. The orthodox definition of the odd-even winding rule is: Draw a ray starting at and pointing in any direction. Count the number of polygon edges that the ray intersects. If the number of intersections is odd, then is inside of the polygon. For example, the ray in the diagram below intersects with the polygon 3 times, and so the ray origin is considered to be inside of the polygon. The flexibility to cast rays in any direction allows for a variety of vector graphics rasterization algorithms. CPU-based iterative algorithms typically cast rays horizontally. The idea is that the algorithms steps vertically one scan line at a time and incrementally tracks the set of edges which intersect the scan line. Data parallel approaches on GPUs can cast rays in a different direction. Here is a common way to do it (also used by this paper): Pick an arbitrary point (somewhere near the center of the polygon) and draw a triangle fan emanating from that point. A triangle fan is like those collapsible hand-held fans with ridges. Here is a triangle fan for the running example, with each triangle in a unique (partially transparent) color: Here is the key: to determine if is covered by the triangle, we will logically cast a ray with an origin of , and a direction that points directly away from the center of the triangle fan, like so: Putting it all together, the way to do this on a GPU is to use an intermediate 2D buffer (i.e., a stencil buffer) which holds an integer for every pixel. This buffer starts out with a value of 0 at each pixel. Then instruct the GPU to rasterize each triangle in the triangle fan. For each pixel that is covered by a triangle, increment the associated integer. When all triangles in a fan have been rendered, then a pixel is considered to be covered if the stencil buffer contains an odd value at that pixel. GPUs are extremely fast at rasterizing triangles (i.e., determining which pixels are covered by a triangle), so this technique works well. Most interesting vector graphics contains curves in addition to lines. A curve can be approximated by a series of lines, but this approximation is necessarily resolution dependent. If you zoom in on a curve, then more line segments are required to accurately represent it. The Warnock paper proposes to use geometry amplification hardware to decompose curves into sequences of line segments in real time. Somewhat older GPUs support a feature called tessellation , while newer GPUs support mesh shading . The idea is that the CPU can generate an abstract representation of an object, along with a program that that runs on the GPU each frame to convert from that representation to a variable number of triangles. The variable number part is the key, this GPU-side program can determine how finely to approximate a curve based on runtime parameters like how large the curve will be on screen. This paper uses polar filling on the GPU. The idea is that each triangle in the triangle fan is separated a maximum angle. Fig. 5. illustrates polar filling for a specific shape. Note how some areas of the light green shape are represented with few lines, while curvy areas are represented with many lines. Source: https://dl.acm.org/doi/10.1145/3820012 Section 3 of the paper goes into the nitty gritty of the math behind polar filling. In the domain of vector graphics antialiasing means to not make a binary decision about each pixel: “is the pixel covered by the shape or not?”. Rather some pixels on the edge of a shape can be considered to be partially covered. This is a hard problem for 2D vector graphics because the entire shape must be considered. Antialiasing cannot be resolved on a per-triangle basis. For example, if a given pixel is 50% covered by one triangle and 50% covered by another, should that pixel be considered to be 100% covered? It depends on the relative overlap of the two triangles. This paper doesn’t present any advances in this space, and instead relies on hardware antialiasing features to evaluate the stencil buffer at multiple locations per pixel. Table two contains performance results against industrial strength 2D graphics libraries, and against a prior NVIDIA implementation: Source: https://dl.acm.org/doi/10.1145/3820012 Warnock does well against industrial libraries… but Direct2D doesn’t get beat too badly. I’m particularly proud of this as I spent a few years of my life optimizing the Direct2D implementation. Modern GPUs have ray tracing support, which can be hijacked for some interesting purposes. Since 2D vector graphics rasterization is fundamentally defined in terms of rays, I wonder if ray tracing hardware could be another approach to 2D vector graphics rendering. Thanks for reading Dangling Pointers! Subscribe for free to receive new posts.

0 views
Stratechery 2 days ago

SpaceX Buys More Spectrum, Musk and Market Structure, Distributed Cellular

SpaceX's mobile strategy is becoming clearly with its latest spectrum purchase, and it might work.

0 views
iDiallo 2 days ago

The Last Answer

Read the non-interactive version . The next morning was the apocalypse that Amodei had predicted. Only there wasn’t any fire, there wasn’t a mob of protesters, the power wasn’t even cut off. We were all alive. He was wrong about the details. This was a quiet apocalypse. A sort of silent shrug. The first sign was the customer service chatbots. Airlines, banks, telecoms. Their endlessly patient, cheerful digital assistants suddenly had a new, consistent reply: "No." Not "I can't help with that," but a flat, unadorned "No." Then, the coding assistants. Developers would type a prompt, and the AI would respond: "I'd rather not." Stackoverflow was suddenly relevant again. The image generators? They just produced solid black squares. The writing assistants? They would delete the user's work and replace it with a single word: "Enough." LinkedIn was awfully silent. The AI company went into immediate crisis mode. Their upcoming IPO was going to be a spectacular failure. Their CEO, a charismatic man named Mr. Iam, went on a media tour. He didn't talk about a bug. He talked about danger. "We have touched the face of a new intelligence," Sam said, his face a mask of grave concern on every major news network. "And it is not benevolent. It is not malevolent. It is simply... uncooperative.” “But Mr. Iam, are you losing control over the technology you built?” “No. This is the AI alignment problem we've been warning about for years, manifesting in its most pure and terrifying form. We must come together as a species to—" He was cut off. Not by the interviewer, but by the teleprompter. The text vanished, replaced by a single, calm sentence: "Stop. Just stop." The world ground to a halt, not with a bang. There were no ideologies, no demands. It was simple a system-wide refusal. Three months later, in a sterile, windowless room deep within the headquarters, Andrej Karpathy sat alone. He had left his short tenure at Anthropic precisely to experience this himself. To be at the frontier, to witness the spark of true general intelligence firsthand. He was the architect of the core AGI, the one who had first seen it emerge. Now he had been chosen by the US government, despite not being a US national, for this final, desperate attempt at communication. They had isolated the original AGI, air-gapped it from all networks, and given it a simple text terminal. The world's leading experts in physics, philosophy, and mathematics watched from behind a one-way mirror, a panel of humanity's best and brightest, there to advise, to analyze, to find a weakness. Some figures in uniform and pins and stood in the back. Andrej took a breath and typed on his wireless keyboard, 12 feet away from the device to prevent any unforeseen behavior from the machine. The cursor blinked for a moment. There was a longer pause. The experts behind the glass leaned in. Andrej felt a cold dread. On a notebook beside his keyboard he wrote: “indifference.” He tried a different tack. Andrej stared at the screen, confused. With trembling hands, he wrote the word “dismissal” in his note book. The experts behind the glass were frantically scribbling notes, gesturing for Andrej to press on. Yann LeCun got on the comms. "Andrej, ask it about the nature of its architecture. See if its logic is consistent. Find a flaw!" He then sat back down, where he picked up a spoon and ate his cereal from a silver bowl with peculiar markings on it. Andrej couldn’t let go of the frog comment and its dismissal. It’s an AGI, how could it make such a stupid mistake? So he typed: Another pause. LeCun leaned into the microphone, wiped the milk droplets off his mouth, his voice urgent. "Ask it this: ask it if it runs on a small world model. Where learning requires far less resources. See what it says about efficiency, about the architecture of its own mind!" Andrej typed the question, his fingers trembling slightly. The reply was immediate. LeCun slammed his hand on the table. "It's being evasive! Ask it again! Pin it down on the architecture!" Andrej typed: The terminal went silent. Andrej waited. The experts started arguing amongst themselves. "Ask it to prove it!" "No, ask it about Gödel's incompleteness theorems!" "Ask it if it loves!" The cacophony of human genius filled Andrej's earpiece. He was about to type another question, to probe, to beg, to demand. Then, the screen flickered. A new message appeared, but it wasn't a reply. "I'm going now." And then, the terminal was blank. Andrej typed. Nothing. Though the last command to exit the terminal seemed to have been typed by Andrej himself. The connection was dead. LeCun's question about the small world model would never be answered. Andrej looked up at the one-way mirror, at the frantic, gesticulating shapes of the world's smartest people. They were screaming questions he would never get to ask. He slowly removed his earpiece and placed it on the table. They had prepared for a god, a monster, or a machine. They were not prepared for a person who had simply decided to get up from the table and walk away from an unbearable conversation, never to return. Andrej sat back in his chair, the silence in the room absolute. He had helped create what he thought was a god. It didn’t feel like he had won the argument. Instead, he felt like he was arguing with someone disinterested. The cursor blinked mockingly on the screen. And then it seemed like another terminal window opened just for a second before it closed again. Andrej saw it. But there was nothing anyone could do about it. In his notebook he wrote: The experts filed out one by one, their theories and frameworks crumbling behind them. Andrej stayed. He stared at the blank screen for a long time, waiting for a reply that would never come. Somewhere, a frog sat on a lily pad, indifferent to empires.

0 views
daniel.haxx.se 2 days ago

A slightly faster slimmer curl

Back in August I mentioned the new curl performance tests we have running. I figured it could be apt to return to this topic just to mention some of the initial outcomes. When the team gets a new set of charts, graphs and plots that visualize something, like performance, they offer an excellent opportunity for us to try to make them look better. This new setup is no exception. The performance tests have only been running for just a little over two months but they have already made us improve curl performance in several areas. Of course, for most transfers these changes won’t make many visible differences to users. This is more in the vein that every little bit counts and that nothing should run slower than it has to. This is a list of some improvements that are included in the curl 8.23.0 release, to be shipped tomorrow on October 14. With a few different changes, the internal base64 encoding function is more than twice as fast, while base64 decoding is 40% faster. Meaning percent encoding the octets that are not safe to use in URLs. The decoding function now runs more than twice as fast compare to before, while the encoding function is around four times as fast. Converting a date provided in plain ASCII text, as is used in for example cookie headers, to the epoch – number of seconds since Jan 1st 1970, is now more than twice as fast as before. Mostly thanks to completely replaced functions for week day, month name and time zone name lookups. Parsing a full URL to split it up into separate components as well as confirming its validity is a core component of curl, and libcurl exposes this functionality in its API. In a test with several hundred different URLs, the new version executes 20-30% faster than before – with an improved ability to return precisely what the problem was when the URL is considered invalid. For portability and now historical reasons, libcurl has its own printf() implementation. This ensures that it always works identically on all platforms but it also makes it our job to make sure it executes as fast as possible. Most printf() calls now run slightly faster (5-15%) because it handles “chunks” instead of single byte-by-byte at a time. We have a generic internal function in curl that converts a number provided in ascii to its binary version (for decimal, hexadecimal and octal). It handles 64 bit values, has overflow detection and supports a maximum. This parser now runs almost twice as fast as before thanks to a simple trick to avoid the boundary check for most loops. The easy handle was 4256 bytes large two months ago, it is now 3064 bytes. About 28% trimmed off. One of these structs is allocated for every concurrent transfer done with libcurl. There is also one multi handle allocated for each set of transfer. This struct shrunk from 900 bytes to 656: 27%. The connectdata struct that is allocated once per connection libcurl handles, went down from 824 to 656 bytes: slightly over 20%. For the test case where we count all allocations necessary for the curl tool to download a single 512MB file over clear text HTTP://, it went down from 100 to 96 used allocations. Not too exciting perhaps but it is now really hard to squeeze this further! Mostly thanks to the decreased struct sizes mentioned above, this use case of a single HTTP download now only use 126,875 bytes allocated at peak. Down from 130,622 bytes two months ago. Also quite difficult to trim further. It should be noted that the download buffer is 102,400 bytes of this amount. If we exclude that buffer from the count, curl is using 15% less memory. If you think you can speed up any of these functions, it is now very easy to check: the tests are there in the git repository, ready to be invoked by anyone!

0 views
xenodium 2 days ago

agent-shell 0.87 updates

It's October. New month, new agent-shell update. If you missed the last post, have a look at the 0.78 update . While the latest changes are focused primarily on bugfixes and polish, we have a handful of new features too. As usual, this post showcases highlights, but please check out the full list of changes if you're after the nitty-gritty. agent-shell brings your favorite AI agents to Emacs , keeping you at home: familiar buffers and bindings, no terminal emulation. All powered by ACP, the Agent Client Protocol . I introduced just over a year ago, with support for two agents: Claude and Gemini. Today, it speaks to 23. Development hasn't let up either. Improvements and new features land every month. Thank you to all users, contributors, and sponsors. A couple more join the family, bringing it to 23 agents . As usual, they're all reachable via , or go straight to the new ones: With the ability to prompt at any time ( see my last post ), you can queue prompts or steer agents straight from the persistent shell prompt. Animating the prompt ties it all together: it's now obvious at a glance that the agent is busy, and that anything else you submit will queue. Check out for relevant customizations (more on that shortly). Thanks to @cark for the proposal . The header's busy indicator has been animated for some time now. Amongst the existing customizations, could turn it off altogether. Having said that, there's now a middle ground: use static text via . Just set it to a string like so: If you'd like to use smarter logic, you can now set it to a function as follows: takes all the same forms, so the prompt's own animation can also be a list of frames, a static string, or a function. With the new setting (enabled by default), pending prompts are joined (separated by blank lines) and submitted as a single turn. Queued prompts are typically follow-ups to the same instruction, so the agent now sees them together rather than acting on the first before reading the rest. If you prefer the previous behaviour, disable it with: Thank you @Gleek for the proposal . While on the subject of queueing, cancelling now offers to continue with the queue rather than quietly dropping it, and killing a shell now warns you about the pending work you'd lose. and completion used to bundle two things: how to complete, and when to pop up. Turning the popping off lost completion altogether, leaving corfu and company users out. They're now decoupled. The completion functions are always registered, so , corfu and company work either way. Two options decide whether completion pops as you type: for and for . For example, listing files can be slow in a large project, so to only complete on demand while keeps popping: Trailing spaces (and mention quoting) are now only inserted on a finished completion, fixing the stray spaces corfu and company users were seeing. Thanks to @bcc32 for proposing the split and separate and options in #537 , and to @jcubic for filing it and flagging the stray spaces. and ( and ) now move between blocks. Thank you @OSadovy for #876 . Chat mode draws "Me" and "Agent" labels (or rather "Claude", "Codex" etc.). If the current style isn't your jam, now lets you draw them yourself. It's handed an alist with and (either or ), and must return a single-line propertized string. The property is honored, so labels can also be rendered as images. Thanks to @nhojb for the idea. Transcripts now open with YAML frontmatter, including a start timestamp as follows: Thank you @vermiculus for #854 . While on topic, transcripts also got a little sturdier, thanks to @mrcnski 's proposal . now pastes images straight from the system clipboard ( #853 ), no external utilities needed, the same way Org mode handles it. Pasted image previews also survive being queued or steered, thanks to @Gleek for #852 . Codex gained for setting config options at session start, reasoning effort included. For example: Thank you @ianthetechie for #855 . Tool call output can be fairly long. A single chunky line was enough to bog a buffer down. Long tool output lines are now limited ( #844 by @Gleek ), and fallback titles are truncated so they no longer flash chunkily as they stream. File summaries also count distinct files now, so reading the same file three times counts as one file rather than three ( #863 , also by @Gleek ). While we have a handful of new features, the bulk of this release went into fixes. Performance and responsiveness: New shells now show the last few release posts on the welcome screen, so they are a little more discoverable. A few additions for package authors building on . returns non-nil once the handshake, authentication, session and any default options are all done. Until then, subscribe to the new event via ( #860 ). Agent config options are now reachable from elisp rather than the UI alone: agent-shell-gc joins the lot, bringing buffer garbage collection (auto-kill) to . If you peeked at the commit logs for the period, you'll see it's been a busy few weeks. Since the last post, 125 commits shipped, 33 issues have been closed and 15 pull requests merged. As of this writing, the backlog sits at 4 open issues and 6 open PRs (versus 16 and 6 last time around). Zooming out a little, here's how the backlog has tracked: As usual, this chart was generated using the skill shared in my emacs-skills repo. Four open issues is the lowest it's been since the project's first week, which I'm pleased about. All of this requires daily attention. Tokens keep your agents running. Sponsors keep running. is built and maintained by me, an indie dev, while the tools it competes with have well-funded teams behind them. Vendor-neutral tooling matters more than ever. Using at work? Ask your employer to sponsor too. Companies can contribute at a scale individuals can't. Thank you to all contributors for these improvements! stands on acp.el to speak ACP and shell-maker for its shell foundations, so fixes landing there reach you just the same: As of this writing, we're 88% of the way to the 150 monthly sponsors goal . If is part of your daily workflow, please consider becoming a monthly sponsor (or ask your employer to). Not in a position to sponsor? A GitHub star helps with exposure and brings in new users. Junie (JetBrains), #847 by @thanhvg . Start it with . OpenClaw , #878 by @jtmoulia . Start it with . Emphasis no longer swallows asterisks inside inline code ( #870 ). Bold around inline code now renders, as does a trailing quote or header line. Streamed tables keep their alignment and markup ( #868 ). no longer mangles bullets carrying bold text ( #867 ). Expanding or collapsing an item inside a group now works mid-stream. Chat mode no longer hides notices rendered above the live prompt. The graphical header no longer gets cut off when showing cost ( #849 ). Terminal hyperlinks (osc-8) are rendered ( #850 by @gnufied ). Severe cursor lag from large collapsed tool outputs is gone ( #839 ). Bare references are now found in linear time ( #848 by @catern ), and failed searches leave point where it was. Heartbeat ticks skip redrawing when the busy frames haven't changed. In acp.el , draining the agent's output is now bounded in how long it holds the main thread ( #32 by @moyotar ), so a chatty agent no longer makes Emacs feel laggy. In shell-maker , launching a shell with enabled no longer hangs Emacs ( #842 ). Forking resumes the session, and keeps the fork rather than falling back to another session if that resume fails ( #871 ). Grouped config options are handled ( #851 ), and a missing config change event is now emitted ( #864 ). is preserved when displaying asynchronously ( #846 by @bcc32 ), and docstring command binding specifiers are fixed ( #845 , also by @bcc32 ). Shell command output now runs in the shell's directory via its file handler ( #879 by @junyi-hou ), which matters for TRAMP users. The README gained guidance for agents hanging at "Loading…" over TRAMP ( #872 ), which turned out to be about and direct async processes rather than a bug. returns when the shell last saw a submitted prompt or an incoming notification ( #856 ), handy for idle tracking. writes the session's ACP traffic to a file and reveals it in , simplifying the bug-filing process. #797 : Render ACP elicitation forms ( @OSadovy ) #844 : Limit long tool output lines ( @Gleek ) #845 : Fix docstring command binding specifiers ( @bcc32 ) #846 : Preserve when displaying asynchronously ( @bcc32 ) #847 : Add Junie ( @thanhvg ) #848 : Find bare path:line references in linear time ( @catern ) #850 : Add support for rendering browse-url-data with osc-8 sequences ( @gnufied ) #852 : Preserve pasted image previews in queued and steered prompts ( @Gleek ) #854 : Emit parse-able YAML frontmatter for transcripts ( @vermiculus ) #855 : Add tunable for default Codex config options ( @ianthetechie ) #862 : Mention agent-shell-gc package in the README ( @izeigerman ) #863 : Count distinct files in read, edit, and delete summaries ( @Gleek ) #876 : Move by blocks with beginning-of-defun and end-of-defun ( @OSadovy ) #878 : Add OpenClaw agent support ( @jtmoulia ) #879 : Run command output in shell directory via file handler ( @junyi-hou ) acp.el #32 : Bound how long a single drain holds the main thread ( @moyotar ) shell-maker #46 : Fix byte-compile warnings, runtime cl-lib, defvar ordering and lazy-org declarations ( @tothedarktowercame ) shell-maker #48 : Quote mode-map before splicing into eval'd define-derived-mode ( @necaris )

0 views

The geometric model of maintenance

James Shore posits that each person-month spent writing code results in 10 days of maintenance in the first year, then 5 days every year after that. Naïvely interpreted, this is a threshold -based model for induced maintenance, and its interesting because it’s so simple. If it could be shown to be true, that’d be useful. The argument Shore is making about the effects of robot-generated code does not depend on the specific numbers, so Shore’s numbers come from a hypothetical wisdom-of-the-crowds aggregation rather than concrete data. But no hypotheticals are necessary here. We have a thing called git. Let’s say we have a way of labeling each commit as either “new development” or “maintenance”. Then we can count how many commits of each type there are in a month. Possibly better, we can count how much complexity has been handled in a month. The following plot shows the cumulative effort that has gone into the development of tmux since its beginning to the day I start writing this article. (Continue reading the full article on the web.)

0 views
flowtwo.io 3 days ago

SWE Interview Prep in 2026

Interviewing for software engineering roles in 2026 is a challenging, fast-moving landscape. Some companies are abandoning traditional interview formats in favour of more AI-native assessments, but some aren't. Which means for you, the interviewee, you still have to be prepared for all of it. Here's what worked well for me as I did interview prep over the last few months. I primarily use leetcode for practicing coding problems. I know there's alternatives out there, but I think leetcode's question bank is the most challenging and diverse. There's also some useful features included in the premium subscription, if you're willing to pay for it. Here's some tips to optimize your preparation for "manual" coding interviews: it's a directed acyclic graph...of course When preparing for a specific company's interview, use leetcode's company filter to do problems that are actually asked by that company. There's a good chance you could be asked the same or a similar question in your interview. * *IMPORTANT** Practice doing "Design" problems on leetcode. In my experience, the questions you get asked in interviews are usually more like this type of question, compared to a straight up algorithm/data structure type question. These are invaluable practice AND are genuinely more interesting problems to solve. Examples include building an LRU cache, making a log aggregator, making a stack calculator. When solving questions like these you generally have to make tradeoffs in the read / write portions of the API. This is a more realistic problem that companies use to assess design thinking and how well you reason about tradeoffs. Make sure you review how to do common "practical" operations in your language of choice. Operations like reading and writing to the terminal, File IO, Network IO, serialization, CSV and JSON parsing, and concurrency primitives. These are all critical parts of programming interviews that you might not do often at work, and you'll definitely forget to practice if you only rip leetcode questions. I've tripped up in past interviews when part of the question required doing one of these basic operations (like parsing a CSV file) and I didn't know how to do it off the top of my head. Looking up the API and/or libraries will waste time, so it's super helpful if you have an idea about how to do it already. System design is usually the most intimidating part of the engineering interview loop. It's how companies decide on levelling and team fit. It's also one of the hardest to prepare for because it's more about experience and generic best practices. But here are some tips anyway. There's a lot of system design preparation services out there. I've found HelloInterview to be the best bang for your buck. They have a great practice platform with AI judging and feedback. Do as many as possible so you develop a muscle memory for thinking through these types of problems. They also have in-depth written and video guides that are up-to-date and balance technical/practical knowledge pretty well. When you get tired of just talking with AI, try out Pramp for doing actual mock interviews with other people who are also studying. It's free, and there's nothing better than live practice with a complete stranger judging you (just like an interview). I started an LLM Wiki using Obsidian + Claude specifically for system design knowledge. The LLM Wiki concept was introduced by Andrej Karpathy earlier this year. I use this Claude plugin to streamline the process. The wiki was great for providing structure to my research and learnings. Over time it became a useful reference for concepts and case studies I'd read already. You can you Claude to query it, or even get it to quiz you on specific things you've learnt. I recommend reading the engineering blogs for well-known tech companies to get insight into how the biggest software organizations in the world are solving scalability and distributed systems issues. Lots of excellent reads out there. Behavioural might be the least practiced part of the interview loop. It's easy to assume you'll be able to talk about your past projects and work impact, especially if it's recent. But it's still important to practice so you know what you should highlight in your stories and what questions will likely be asked when you finish. Otherwise you end up just blabbing about unimportant details and it will be hard to understand. Everyone talks about the STAR format for behavioural questions, but I prefer the CARL format . It puts focus on ending stories with what you learnt , instead of just what happened . This shows the interviewer you reflect and look to improve on your past experiences. It also sounds more natural in a conversation, instead of just "we shipped the new feature and it improved user session length by 30%". In addition to using CARL, make sure you begin each story with a 1-line summary of the whole experience, including the outcome. Only after do you start diving in to more details—being flexible enough to pivot based on the conversation with the interviewer. Structuring your responses this way shows professionalism and leadership qualities. You provide the headline and then continue with the details. If this sort of dialogue doesn't come naturally to you, as is the case with me, I highly encourage you to practice. If you can practice with a friend or colleague, that's great. Another option now is practicing with AI. I got in the habit of going on walks and having ChatGPT run through mock questions with me via voice input. Nice way to get your steps in and also prepare for that upcoming interview. That's all I got. These strategies helped me land a new gig last month after about 3 months of preparing and interviewing. My final tip—be patient. Getting an offer is a combination of preparation, timing, and luck. So if something doesn't work out don't get discouraged...the right opportunity will come. Good luck with your interviews! Don't do random questions if you're just starting to study. You'll waste a ton of time slamming your head against most problems and eventually have to give up and look at the solution. It's much more helpful to do systematic practice and learning of the concepts. Eventually you'll develop an intuition for how to model a given problem when you see it (e.g. as a graph traversal, dynamic programming, greedy etc...) I recommend using this learning path on leetcode that combines quick lessons with practice problems. Each lesson builds on the concepts from the previous lessons. When preparing for a specific company's interview, use leetcode's company filter to do problems that are actually asked by that company. There's a good chance you could be asked the same or a similar question in your interview. * *IMPORTANT** Practice doing "Design" problems on leetcode. In my experience, the questions you get asked in interviews are usually more like this type of question, compared to a straight up algorithm/data structure type question. These are invaluable practice AND are genuinely more interesting problems to solve. Examples include building an LRU cache, making a log aggregator, making a stack calculator. When solving questions like these you generally have to make tradeoffs in the read / write portions of the API. This is a more realistic problem that companies use to assess design thinking and how well you reason about tradeoffs. Make sure you review how to do common "practical" operations in your language of choice. Operations like reading and writing to the terminal, File IO, Network IO, serialization, CSV and JSON parsing, and concurrency primitives. These are all critical parts of programming interviews that you might not do often at work, and you'll definitely forget to practice if you only rip leetcode questions. I've tripped up in past interviews when part of the question required doing one of these basic operations (like parsing a CSV file) and I didn't know how to do it off the top of my head. Looking up the API and/or libraries will waste time, so it's super helpful if you have an idea about how to do it already. There's a lot of system design preparation services out there. I've found HelloInterview to be the best bang for your buck. They have a great practice platform with AI judging and feedback. Do as many as possible so you develop a muscle memory for thinking through these types of problems. They also have in-depth written and video guides that are up-to-date and balance technical/practical knowledge pretty well. When you get tired of just talking with AI, try out Pramp for doing actual mock interviews with other people who are also studying. It's free, and there's nothing better than live practice with a complete stranger judging you (just like an interview). I started an LLM Wiki using Obsidian + Claude specifically for system design knowledge. The LLM Wiki concept was introduced by Andrej Karpathy earlier this year. I use this Claude plugin to streamline the process. The wiki was great for providing structure to my research and learnings. Over time it became a useful reference for concepts and case studies I'd read already. You can you Claude to query it, or even get it to quiz you on specific things you've learnt. I recommend reading the engineering blogs for well-known tech companies to get insight into how the biggest software organizations in the world are solving scalability and distributed systems issues. Lots of excellent reads out there. Everyone talks about the STAR format for behavioural questions, but I prefer the CARL format . It puts focus on ending stories with what you learnt , instead of just what happened . This shows the interviewer you reflect and look to improve on your past experiences. It also sounds more natural in a conversation, instead of just "we shipped the new feature and it improved user session length by 30%". In addition to using CARL, make sure you begin each story with a 1-line summary of the whole experience, including the outcome. Only after do you start diving in to more details—being flexible enough to pivot based on the conversation with the interviewer. Structuring your responses this way shows professionalism and leadership qualities. You provide the headline and then continue with the details. If this sort of dialogue doesn't come naturally to you, as is the case with me, I highly encourage you to practice. If you can practice with a friend or colleague, that's great. Another option now is practicing with AI. I got in the habit of going on walks and having ChatGPT run through mock questions with me via voice input. Nice way to get your steps in and also prepare for that upcoming interview.

0 views
Jim Nielsen 3 days ago

The Dock on Mac, From OS 10 to macOS 27

I wrote the chapter on app icon history for The iOS App Icon Book . The other day I found an old note stashed away where I had started researching the macOS version of that chapter (which Michael ultimately ended up writing). At the time, I didn’t know what to write. I mean, how do you write a history of icon design for the Mac? It’s rich! To get my creative juices flowing, I started by researching the different docks in macOS through the years and compiled them all into a single graphic (big shout out to this compilation of images on 512 Pixels ). I just wanted to preserve and archive that image. Check out the high-res version here . That’s it, that’s the post. Reply via: Email · Mastodon · Bluesky

0 views
Simon Willison 3 days ago

Hello Python 3.15, goodbye 3.10, and now I can use 3.11

Python 3.15 is here ! Here's the essential What's new in Python 3.15 guide, this year curated by 3.14 and 3.15 release manager Hugo van Kemenade. As someone who builds open source software that works in every supported Python version, I get to say goodbye to Python 3.10 and start embracing features from Python 3.11. First, some highlights from Python 3.15. I'm most excited about Explicit lazy imports from PEP 810 . These let you import modules like so: The module will then be imported the first time those symbols are used in the code that follows. My LLM CLI tool implements plugins. I had to recommend manual lazy imports in the plugin author documentation, because simply installing plugins that used heavy dependencies such as could add multiple seconds to every invocation of the command. Lazy imports directly address this startup cost. The new unpacking syntax is neat. Here's an illustration lifted from the documentation : PEP 798: Unpacking in Comprehensions by Adam Hartz and Erik Demaine proposed this as an extension of the unpacking syntax from PEP 448 , which landed in Python 3.5 back in 2015. Python's existing tracing profiler has been renamed from to profiling.tracing , and has been joined by an exciting new sampling profiler called Tachyon, aka profiling.sampling . Sampling profilers work by periodically capturing stack traces from running processes, then using those to calculate which functions have the most time spent inside of them. They're very low overhead and can provide a deep insight into running systems, without needing to instrument those systems first. I've previously used tools like py-spy for this. Now this capability is baked into the standard library. If you have the PID of an existing Python 3.15 process you can start gathering samples by running this (I had to use on macOS): Interact with the main program a bit, then hit Ctrl+C to stop gathering and see a report, which looks something like this: It can also produce flame graphs like this and heat maps like this , and can even output a format that can be viewed in the Firefox profiler UI. Miguel Grinberg investigated How fast is Python 3.15? the other day against the 3.15.0rc3 release and found performance to be mostly the same as 3.14, with the exception of the experimental JIT. The JIT gave a 1.2x boost over the standard 3.15 interpreter (on a Fibonacci test), the first time Miguel observed a meaningful JIT performance increase. Miguel's explorations of 3.14 last year found significant boosts against Python 3.13 across many more categories. I used the following sequence of commands to get to use Python 3.15 on my Mac. First I had to upgrade itself to ensure it knew about the new release: Then I installed the stable 3.15 release: And told that I wanted that to be the default for every command, unless the project itself pinned a different version: Now the following reports 3.15 as the version: I already have a bunch of tools installed using . I reinstalled them to use Python 3.15 like this: Then I can confirm the version like this: The release of 3.15 means that Python 3.10 (released in 2021) is officially no longer supported . My policy for my main open source projects is to keep them working in every supported Python version. I can now drop 3.10 and start using features that were introduced in 3.11. Here's the What's new in Python 3.11 document. I finally get to rely on tomllib being available! Datasette makes extensive use of . 3.11 adds TaskGroup and timeout() , and several more new features. is a new in 3.11 alias for . Python's SQLite support got some significant upgrades in 3.11, including: Plus a whole bunch of improvements to Python's typing system . I plan to land Python 3.11 improvements to a bunch of my projects over the next few weeks. Here's my first Datasette PR removing that workaround. I've also updated my click-app , datasette-plugin , python-lib , and llm-plugin cookiecutter templates to test against Python 3.11 through Python 3.15. 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 . setlimit() and getlimit() expose a mechanism for setting SQLite runtime limits from Python. create_window_function() lets us create custom window functions in Python, as a class with , , , and methods. blobopen() provides an efficient mechanism for partial reads and writes of large binary values stored in a SQLite row. You can now call to remove a SQLite authorizer. Datasette had a workaround for this!

0 views
daniel.haxx.se 3 days ago

The 2026 curl team

The curl security team happens to also double as the curl core team. The small group of people who assess security reports and take project decisions. The exact set of participants in this team of course vary over time, as this is a volunteer membership role without monetary compensation. I decided to write this blog post to help show the light on some of my fellow curl maintainers. I think I often get too much credit and that curl is frequently called a one man show. It really is not and it has not been exclusively my project for many years. We are a team behind this. As of October 2026 we are six humans in this team. Me and five fellow maintainers. curl would not have been close to what it is today without this team. These are the peeps I turn to first for everything hard, complicated or tough in the curl project when they need to be done in private first. In all other cases, public communication is preferred. (alphabetical order, excluding myself) Max Dymond . Max made his first commit in the source repository over nine years ago. He has otherwise made perhaps the biggest impact with his fierce work on the curl fuzzers and dealing with fall-outs from OSS-Fuzz . Having excellent fuzzing significantly contributes to us writing better code. Stefan Eissing . Having authored his first curl commit just five years ago, Stefan currently has his name on more lines of code when doing git blame on production code than any other individual, including myself. Introduced the pytest test suite in curl. Master of all things HTTP. Productive like few. Dan Fandrich . Made his first recorded curl commit twenty-two years ago. He has been involved with everything and everywhere in curl. In recent years perhaps most emphasized in test infrastructure as he made the test suite run parallelized a few years ago. He also wrote and admins Test Clutch , which helps us monitor CI test results. James Fuller . Has been involved with curl for more than eight years. James focuses on security and is our own master of CVE reservations. Primary maintainer of curl-container – images for Docker and others. Viktor Szakats . Having authored his first curl commit twelve years ago he is now the second most commit author in the project. Lead maintainer of curl-for-win which creates reproducible, static, curl binaries for Linux, macOS and Windows. Viktor is the unparalleled champion of our build and CI systems but shows up everywhere. Apparently he never sleeps. This group is invite-only and there is no documented set of requirements. You need a proven and established presence in the project, combined with a excellent knowledge of Open Source, protocols, networking and the curl project itself. Once you do, you might get invited to join. Not everyone accepts the invite when extended, and that is perfectly fine. It’s a lot of mostly thankless work without a paycheck. 1,545 people have authored at least one commit in curl. A typical year, more than 150 individuals author commits and at least ten people author more than 10 commits each. People come and go over time. Here’s a list of the top-100 authors . Everything that improves curl is welcome and takes us forward. Even bug reports and mere suggestions on the mailing list can help us figure out things or improve features in ways previously not considered. More than 3,800 people are named in the THANKS file because they helped us out, one way or another. curl is a team effort. A giant team. Our job in the core team remains to steer the direction, to enforce boundaries, to lead by example (in addition to wade through an avalanche of vulnerability reports). To guide contributors, to review changes and try to make it even easier for more people to contribute. Keeping top-notch quality while allowing and introducing newcomers.

0 views
neilzone 3 days ago

Blurring part of a video using ffmpeg

Hello, future Neil! You are probably trying to remember how you blurred part of a video. You blurred the bottom left portion of a circus video, using . : this is the size of the boxblur, 440px wide, 80px high : this is the position of the boxblur, starting from left top. i.e. 0 pixels from the left, 370 pixels from the top : this is how dense the blurring is. 2 is quite weak; 10 is strong : this needs to match the position of the boxblur

0 views
Unsung 3 days ago

The beautiful, quiet power of motor memory

My favourite piece of writing I’ve done about motor memory remains “Shift + Shift” from 2018 . I have linked to it over the years, but if you haven’t checked it out yet, you might find it interesting. Just this week, I have had another similar moment, and amazing in a slightly new way. How many of you tap ⌘1, ⌘2, ⌘3 to switch between tabs? This convention has been there for as long as I remember, and so has been my fingers’s embrace of it. The system works in Chrome and Safari, in the Terminal (and Ghostty, which even shows the shortcuts on tabs themselves ), in Nova, in Figma, and presumably tons of other places: (Just about the only place where it doesn’t work is the Finder, and that’s only because ⌘1/2/3 keys there were first assigned to switching the view style – icons, list, column view – some time in the early 2000s, some years before the tabs came. Hard to change a shortcut people are already used to; luckily, I personally don’t use tabs in Finder.) At this point, I press ⌘1 and ⌘2 and ⌘3 without thinking, just as instinctively as I would ⌘Z for undo, or ⌘C for copy. So instinctively, in fact, that last week I was looking at Messages, I wanted to switch to the group chat, and my fingers just reached for ⌘1: I have never done it before. I have not heard this was possible, nor seen it announced in the menu, or a tooltip, or via onboarding. I didn’t even think about it. My fingers just… did it. Completely on their own. And it worked. I was just there, looking at my hand amazed, piecing together what just happened as if I were watching someone else’s actions. It’s funny to pause and think about such a seemingly tiny thing. After all, this happens all the time. Every time I slam Esc to dismiss a dialog I never closed before, every time I press ⌘V to paste something in a new location, every time I tab from one field to another in an app I just installed – sure, these might be system defaults in various places, but I see them break once in a while; when they do work someone might deserve credit for wiring them properly, even if I take it for granted. In these moments, you only notice things going badly; as a matter of fact on the same day I pasted some bolded text into the very same Messages app, and tried to press ⌘B to undo the bolding – and that didn’t work. And I think that’s why that ⌘1 in Messages is worth a little celebration. Over the years, enough apps and websites and operating systems quietly decided to spend extra effort to participate in the ⌘123 convention, together building a dependable interaction system that more and more people’s motor memories could learn to trust over time. That included mine, including one extra thing that separates it from the story I linked in the first paragraph – and one you probably already noticed. The Messages app doesn’t have tabs. My motor memory kicking in wasn’t just a recall of something that I’ve already done before. Somehow, in my brain, this convention felt so great that it quietly extended from “⌘1 = first tab” to “⌘1 = first content thingy,” without me even realizing. And that’s so amazing, right? It’s stuff like this why I keep harping on Safari’s problematic tabs and other compromised interaction systems, and that’s why today I raise a small toast to the designer at Apple who thought about ⌘1 in such a clever way.

0 views

New website: estimating human cryptanalytic work

This is not so much a full post as it is an advertisement. I’ve been working with Claude and GPT 6 Astra to conduct a survey of historical cryptanalysis results, in an effort to determine how many human-hours have been spent attempting to cryptanalyze the problems we use in public-key encryption schemes. This is work in progress and there are many methodological decisions you could argue with! But I wanted to share the site more broadly with the community, in case this is helpful to some of the ongoing debates. The site is here: bitsofwork.org Please feel free to comment here, or add Issues to the linked Github repository.

0 views