[idea:26w33]2026-08-16Week 33

Contents

It was a productive week back at the office (my apartment living room). I’m writing on a Monday again, which is becoming the more reasonable day on which to publish my weeknote, so I’ll stop apologizing for it. The sections are in reverse order this week, as some hacking I did over the weekend has resulted in the new skin you see here for these weeknotes, and it’s very much top of mind. The tooling that enables this structure is something I’ve been wanting to build since I started writing weeknotes, and a lot of the work I’m planning to do in the coming months will build on it as a basis.

This website now runs on a new Rheo/Typst package called rookery. I spent the weekend developing this package and doing my best to explain its concepts and how it works in that documentation site, and so I direct the reader there for a proper explanation. Here I’ll just talk a little about its motivation and the research that I hope it will jumpstart.

When I was an undergraduate freshman, my parents bought me a Macbook Pro to use for my studies. I remember opening it in California when I arrived in the US on August 10th, 2013. My high school hadn’t offered any classes in computing except a summer course on touch typing, taught by the headmaster’s wife, but I had taught myself Python using Coursera and EdX, the MOOC platforms of the moment.

For reasons I don’t remember, I used the indy software Growly Notes for all my work. In a particularly memorable course as a freshman (taught by Daniel Heller-Roazen), I remember deciding to take notes in a different way each lecture, ranging from structured bullets on Growly to writing a single stream-of-thought line that spiralled from the outer edges of an A4 piece of paper to its center.1

Growly stuck with me for four years. In my junior or senior year, a PhD student in German whom I had become friends with, William Stewart, clued me in to another indy Mac software, DEVONThink. Over several years as a recent graduate working at Forensic Architecture in London, I came to a way of using DEVONthink as what I called an associative archive. This wasn’t a note-taking philosophy so much as it was a kind of nascent theory of how to bring the best of Unix to digital archiving in general, and personal research databases in particular.

As I moved through the early years of my dissertation, I eventually managed to cleanse myself of any strong dependency on Apple software. Though I haven’t yet managed to recreate a richly featured associative archiving system on Linux, much of my recent software work with the FCL is essentially in search of this vision.

In 2023 or so, I adopted Org-mode more seriously at Zac Ioannidis’ suggestion. Org-mode completely transformed my way of thinking about note-taking, partly because I hacked together a way (with LaTeX and Pandoc) to export documents to both HTML and PDF, and partly because of its inbuilt TODO system.

At the end of 2025, I started looking into Typst after conversations with Will Crichton. This led me to develop Rheo and to publish a paper with Will about its possible use in augmented reading research alongside bene, an EPUB reading system. As I started doing all my writing in Typst, I came to realise that I wanted to use it as the basis of not only an associative archive, but also both a proper academic authoring toolchain and my (increasingly constant) communication with LLMs.

Rookery lets you create intellectual junkyards in Typst, and it is the next step in this line of my research thinking about better foundations for documents and knowledge systems. It draws most of its concepts from Jon Sterling’s forester, which I wrote about as inspiration for why I started writing weeknotes, and again in the rookery FAQ.

I recognise, however, that often tools in this ‘deep note taking’ space can come across as unapproachable and opaque—at least, this is my experience of how tools like Roam Research and even Obsidian tend to signify. Notion is the most mainstream tool that draws aspects of its architecture from this research space, but it very much follows Apple’s example in cultivating walled gardens and prioritizing enterprise use cases.

Rookery is my first real contribution to this space (other than Rheo, which arguably doesn’t play in quite the same sandpit), and I can’t wait to rebuild and extend several of the sites I maintain with it this coming week. This site is the first that I’ve ported—it took all of five minutes with the help of Claude Code—so watch this space for many more rookery examples.

The development of rookery and its documentation took only one weekend (15-16 August), though with full 10+ hour days hacking, and it stands on the shoulders of much prior work in Rheo. It is almost entirely vibe-engineered, and only currently tested anecdotally in my own examples. Rookery is personal software for the time being, and like Rheo it is likely to undergo relatively dramatic changes in the next few months as I work out how I best work with it. That said, if this kind of tooling excites you, you’re brave enough to want to use rookery for something, or you just have some feedback, please do reach out.

Footnotes

  1. ^ Appropriately, I believe that these were my notes for the lecture on Dante’s Inferno.

Earlier in the week, I posted a new blog post, Birdkeeping. I wrote this post two weeks ago, actually, as I started hacking on a tool in the same family as rookery, and it represents my latest thinking about how to use LLMs effectively in software maintenance and research. I decided that I want to develop this tool in Lean, an exciting new programming language that is getting a lot of play in software news at the moment in relation to the waves AI is making in mathematical research.

Grant Sanderson has some good thoughts about how to use LLMs to learn, and I’m doing something similar in order to learn Lean. I have a prototype for this tool in Rust—which is the programming language I’m most comfortable thinking with right now—and so I asked Opus 5 to devise a tutorial covering core concepts and features in Lean that reconstruct the same tool. This has so far been a productive exercise, as I know exactly what I’m building and why I’d want to build it: I just get a contextualized tour of Lean along the way. After an hour or two building the prototype back up in Lean, I realised that I still needed to refine some of the concepts in the tool themselves, so I went back to Rust for a bit where I can iterate faster. But this is the general workflow that I intend to continue. More on this tool when it’s more mature in my own thinking!

In order to enable parts of rookery, I cut a 0.5.2 release of Rheo this week. It only adds one feature, which is to enable both end users and Rheo packages to specify marrow. I haven’t fully thought through the consequences of this feature in Rheo yet, so I’m leaving it undocumented for now.

A bigger rewrite also got underway factoring out parts of Rheo’s engine to custom Typst packages. Rheo is intended as a kind of wrapping compiler around Typst, and so it only wants features that are impossible to achieve or otherwise not performant in pure Typst. The way that Rheo creates rheo-context, for example, is currently hacky given that it could be implemented as a Typst package. In Rheo 0.6.0, I hope to strip away some of the unnecessary features in Rheo’s core and compartmentalize them instead as packages.

I also shipped a blogfeed 0.1.1, which enables the nice colours you can now see in the filters on my main blog.

I spent a day at the very beginning of the week—which feels like a long time ago now—setting up a local instance of listmonk so that I can send out emails easily every time I have a new post here or on my main blog. This was a bit more finicky than I had hoped, as listmonk doesn’t provide a built-in way to treat Atom feeds like the one for this site as a source of truth for email campaigns, which is what I want. It was so frustrating, in fact, that I went searching for a different framework halfway through. Buttondown looks usable, but I wanted to self-host it, and it’s not open source. So I resisted the urge to develop my own emailing software from scratch, and stuck through configuring listmonk.

I ended up developing a custom Python CLI / NixOS module that both provisions a fresh instance of listmonk in the way that I want, and also runs a daemon that polls Atom feeds and creates new campaigns when there is new content. After a forgettable afternoon fighting with listmonk’s misshapen API, I got it working reasonably enough. When my Framework Desktop is turned on, it polls my sites’ Atom feeds, and prompts me if there are new campaigns (emails for new posts) to send out. I can adapt the template for the email, i.e. how much of the content it previews in the email itself, and send emails etc. in the listmonk frontend interface, which is… fine.

The other major hitch is that, in order to provide an endpoint through which users can automatically subscribe and unsubscribe, the service running on my machine would need an external IP address. The deeper problem is that I intentionally don’t leave my desktop on at all times, and so the service isn’t always available. I have plans to solve this deeper part with (yet another) system I’m building; but given it doesn’t exist yet, there’s no point right now in taking the trouble to expose my listmonk server to the broader Internet. My workaround at the moment is just to manually maintain the list, which means that ‘subscribing’ and ‘unsubscribing’ just amount to sending me an email. Thankfully, the readership for both this site and my blog is minuscule, and given its technical consistency many if not most of my readers know how Atom feeds work. For those who don’t, you can get on the email list by sending an email with subscribe weeknotes.ohrg.org in the header to hi [the symbol in emails] ohrg [dot] org.

[idea:26w32]2026-08-09Week 32

Contents

It is the day after again, the day after the official end of a frazzled week of suffering to think in the European heat. Much of the work I snuck in during it was on a new project related to the blog post I wrote two weeks ago regarding my beads/jj/agent setup. One part of this that I am willing to share at this stage is the coding-agent extension set soroban, which I released on Thursday last week. Soroban operationalizes the workflow I outlined in the blog post through a set of agent skills, or a real extension if you use pi. Due to token constraints, I am still mostly using soroban from inside Claude Code via the skill interface, which works just fine.

Besides releasing soroban, this week I rethought the broader frame of my dissertation (Dissertation), did more course development (Course development), and hacked through a full stack application deployment on Digital Ocean (Digital Theory Lab). In extra-academic and likely more exciting news, we bike-packed some of the way to Switzerland to catch the opening weekend of the Locarno Film Festival (et alia).

[idea:26w32-diss]

Dissertation

Up until this point, my dissertation has been conceived as a theoretical undertaking which will result in a monograph, as is the fashion in the North American humanities. 1 This may yet be the case; but I have decided that I would be remiss not to incorporate the software work and maintenance that is increasingly a core aspect of my labour and headspace. Thus I did some work remapping the structure of my dissertation this week. The first three chapters will still proffer a conceptual and critical history of the relation between computer science and capital, the topic on which I settled several years ago. I now intend to also add three more chapters to the dissertation as a whole which frame and reflect on three software systems I have built throughout my PhD.

These three projects will likely be: Rheo, Karaji, and the new project that I refer to in the intro above. Each of these systems will be something that I intend to use daily, as I currently use Rheo for all my writing, website maintenance, and slide decks. Each of these systems will also, I hope, be a serious open source software used by a non-trivial number of people, although maximizing the raw headcount of users is not their driving force. What I hope these systems will collectively demonstrate is a style of software that tugs against capital’s capricious nature, and therefore materializes in a different way the thrust of the theoretical argument I will make against a culture of computing that does not attend to how the value it produces in the world is disfigured by capital’s unconsciously installed drives, desires, and motive forces.

Footnotes

  1. ^ For those unfamiliar, the humanities PhD dissertation in the U.S. system is something like a first-pass draft at your first book, which you are expected to publish after substantial revisions in the first few years after your PhD, i.e as a postdoc or junior professor.
[idea:26w32-coursedev]

Course development

I both continued development on an advanced agentic studio and also started thinking about resuscitating a course that has unfortunately fallen off Brown CS’s regular roster, CS3.

When I was an undergrad at Princeton, Brian Kernighan taught a roughly analogous course called Computers in our World. Because computer science departments are the academic authority on how computers work and what it means to code, there are a lot of students searching for a general introduction to computing. The problem is that CS largely conceives of itself as an engineering discipline and therefore (often) places a premium on rigour. ‘Introduction to computer science’ courses are sometimes styled as grueling undertakings for new students, implicitly or explicitly becoming a forcing function to winnow down from the mass of potential CS majors to a select few.

At least, this was the case at Princeton, and seems also to be the case at Brown. The ‘real’ introduction to computer science course is difficult by design, making it inhospitable for students who just want to get a feel for understanding computers and code rather than majoring in CS. I’m actually not against this philosophy of difficult introductions per se. There is some truth to the idea that CS in practice largely consists of reading the tea leaves of arcane error messages to parlay with intransigent machines. I also have some sympathy for the very real logistical difficulties when too many students want to major in the same subject, even if it seems absurd to complain about from the point of view of humanities departments that are increasingly marginalized in the academic edifice.

But it does raise an important question. How can we best offer introductions to computing for all students, not just those who are committed to majoring in CS, and therefore are willing to commit the time and hard work that a rigorous introduction sequence requires?

One aspect of this is a change in what is sometimes referred to as the ‘culture’ of CS departments. The propensity for rigour can give misogyny an easy footing, as the systematic exclusion of certain kinds of people can be written off as an unfortunate but necessary outcome of technical meritocracy, when it is really the consequence of a contingent and therefore changeable cultural atmosphere that makes many feel very unwelcome. Brian Kernighan’s Computers in our World course was colloquially known amongst undergrads as “Emails for Females”, presumably in contrast to the implicitly masculine COS 126, the ‘real’ introductory course for CS majors. Though there have been many initiatives around women in STEM and CS in these spaces in the past decade, most CS departments are still in my view accurately described as having programmed inequality. It is impossible to redress the trenchant misogyny in CS without seriously tracing how it stitches together the couture of technical rigour in the discipline as a whole.

But this thought needs proper fleshing out elsewhere. My hope in reviving CS3 is that it can function as an alternative introduction to computing and computer science at Brown for students who want to understand how computers are a part of the fabric of our everyday world, but who don’t necessarily plan to be able to do advanced algorithmic theory in the immediate future. More particularly, I am renovating the syllabus with LLMs and agential harnesses in the rearview mirror, as these dramatically change the scope of what it’s plausible to do with computers with little or no programming knowledge.

[idea:26w32-dtl]

Digital Theory Lab

After a bit of hacking to make it more pretty and properly functional, I spent some time struggling to deploy our O(x)Caml viewer (which consists of both a backend server and a frontend) to Digital Ocean. I tried a deployment workflow using NixOS in production, as I run NixOS on all of the hardware that I use on a day-to-day basis and would love to also make use of it on remote servers. Digital Ocean doesn’t offer a NixOS image by default, and so I tried a deployment workflow using nixos-anywhere to transform a Debian droplet into a NixOS installation. For reasons that I didn’t dig too deeply into, the computer was saying no no no when I tried to deploy the system, so I eventually decided to switch the CD to Docker containers orchestrated with Compose, as I’ve used these technologies extensively in the past. The Docker-adapted OpenTofu deployment process is running as I write, so I hope not to have to weed around in this domain too much more this week. The next step is to get a few researchers using the site internally to work up some insights and feedback.

Last but not least, we went to Locarno last Friday to catch some of the film festival (and to approximately celebrate our wedding anniversary). The festival was, in characteristic Swiss fashion, immaculately organized. (We learned while there that the non-profit which organizes the festival has an 18mil CHF annual budget and more than 30 full-time employees.)

We were only there Friday evening and Saturday, and the midnight screenings were too much for us, needing to travel 1.5hr back to our accommodation. We thus saw three feature-length films: Ich ist ein Anderer, Violence du corps l’autre, and The Invite, in response to which I thought (respectively): you’d have a better time reading the wikipedia page than watching it; it was an auteur’s masterpiece; and it was at last a rom-com worth watching.

We cycled 60km or so up Lago Maggiore from Verbania to Bellinzona on the way in, and over a beautiful mountain pass another 60km or so from Bellinzona to Chiasso on the way out. I recommend the bike-packing: I’m not sure that we’ll be going back to the film festival on a regular basis, as although the lakeside setting is gorgeous, I can’t quite diff the prices with the food quality in Switzerland when comparing with Italy.

[idea:26w31]2026-08-02Week 31

Contents

First, I apologise to the abstractions or gods that hold me accountable to weeknotes, as I am writing this on Monday morning (“the morning after”) on account of a Sunday riveted to another digital undertaking, about which more soon. I took a breather from Rheo development this week to participate in the second week of an online interpretability intensive at the Digital Theory Lab run by Tyler Shoemaker. I have been collaborating with Tyler for a year or so now on research that is nearing publication readiness, and it was great to see him in his element: namely, a Jupyter notebook.

I also got set up with OBS so that I can livestream some research work later this month. I played around with some livestreams this time last year, and despite their resplendent inconspicuousness in the world of views and likes, I nevertheless found the exercise very helpful. (The phrasing ‘even though… I nevertheless’ seems to be something of a pattern in evaluations of my publicly posted research.) So I will take to the binary skies again in the coming weeks, likely with passengers like Rheo and an agential harness in tow.

[idea:26w31-dtl]

Digital Theory Lab

Tyler’s summer school was designed to bootstrap the technical knowledge necessary for interpretability work for language models. Practically speaking, this means a whirlwind tour of Python and an exhibition of how one can use it in a Jupyter environment to do the archaeology of language models that is now generally called interpretability research.

Tyler’s course is a practical introduction to thinking differently about large language models. The Digital Theory Lab was founded by Leif Weatherby, who wrote about the conceptual stakes of the ‘science’ of language models in his 2025 book, Language Machines: Cultural AI and the End of Remainder Humanism. (For a gentler and less thoughtfully argued introduction to the Lab’s position, I gave a short presentation (with slides) earlier this year problematizing the rhetorics of objectivity in interpretability research. Though there are aspects of my argument that could be more precise, it paints an accurate picture of the thrust of my early thinking about the misunderstandings that traffic in the interpretability mainstream.)

As Director of the Lab, Tyler now leads the small but serious research effort we have going towards the different kind of language model interpretation that Leif calls for in his book. I thought I would listen in to remind myself of what I’m supposed to already know, but—as often happens in ‘introductions’—I learned I need to firm up my sense of a whole lot of things in the space. I went back and started working through the sessions in Tyler’s 2024 course, as even though this 2026 one was supposed to be standalone, I personally find that it works much better as a follow-on from that earlier edition. The 2024 course gives shape to language models as an abstraction by first introducing an n-gram model that doesn’t involve any machine learning, just statistical sampling; whereas the 2026 edition throws you right in the deep end of transformers and tokenization.

I felt like I first got a real grasp on machine learning after working through the fast.ai course Practical Deep Learning back in 2019 or so. Two of the tidbits that have stuck with me from this course are:

  1. The best way to grok what’s going on in machine learning is by inspecting and fiddling with the tensors in a notebook at every phase of transformation.
  2. Reading ML literature gets a lot easier if you learn how to pronounce the Greek letters in formulae, so that you can talk through them when you encounter them.

As I listened to Tyler fluently talking through various statistical terms and operations, I realized quite quickly that I would need to port these and other aspects of the fast.ai pedagogy to really understand the notebooks in the course. To that end, after struggling to follow through the first few seminars, I set up a local dev environment with all the data in marimo notebooks, as I feel that they have both better UX and functionality than Jupyter notebooks. I have now started rewriting some of these tutorials in that environment, using more descriptive variables (as I have never been comfortable with the Pythonic proclivity for C-like variable abbreviations; I always forget what they’re supposed to mean) and adding markdown cells to explain the operational motive better where I struggled to follow.

I’m now considering streaming some of the content from this ‘literate programming’ translation of the combined 2024 and 2026 courses. But at the very least I intend to make the notebooks available as a supplement for those who similarly have difficulty following mathematical formulae and stylishly terse Python.

A big DTL section this week; as I also did some more work on the OxCaml/Bonsai viewer for the set of experiments in the aforementioned paper. Because it deals with gigabytes of data on disk, I’ve set up a backend server for it as well, and will deploy it this week to a Digital Ocean droplet. This gives me a nice opportunity to try out some of the patterns for NixOS in Production, which has been on my want-to-dos for a while.

I built out the basic structure of the syllabus for this course (described in last week’s weeknotes). It is split between several weeks on the LLM engine component of an agential harness, which comprises the hardware-intensive substrate of running next-token generation with an LLM somewhere, and the harness architecture, which covers the agentic loop, tool use, session context, and the other aspects that make next-token generation practicable as a software development assistant in tools like Claude Code. I found this post a helpful jumping-off point, and also discovered the pi coding agent through my research.

Pi is a fantastically minimal yet extensible coding harness, which reads with respect to Claude Code or Codex as (Neo)vim does to Visual Studio Code. As of yesterday, I’ve now switched over to pi for all my agential programming. Critically, pi’s minimalism makes it practicable for me to swap out Anthropic’s engine for local models running on ollama. (I recognize that there are likely ways to optimize a local LLM engine, but ollama with ROCm has been sufficient for me to get started seriously using open weights models locally.) I’ve been playing around with qwen3.6:35b, a model that generates tokens remarkably promptly on my Framework Desktop. I haven’t leaned in on it yet, but I expect that Qwen 3.6′s performance and capability will be sufficient to work on features and bugs filed by more capable models, a plan-implement workflow that I currently manage with beads and jj.

Open models are an increasingly exciting space, both for interpretability and agential harness research. I highly recommend the latest Oxide and Friends podcast with Simon Willison on open weights models and the recent Anthropic/Hugging Face incident. If you’re not already jazzed about open weights, I expect you will be after listening.

I went on a bike ride and a few runs this week, but the August heat is really starting to dig in its heels. In an attempt to quarrel with it, I’ve been experimenting with artificially creating various airflows around my apartment by positioning fans near windows and our air conditioner, which unfortunately combats the 30-degree-plus norm only in its direct proximity, rather than across all of our home. (Our roof is old and doesn’t insulate as well as it should.)

I also renamed my main blog to ‘one long token soup’ after reading this scrumptious phrase in an interesting new paper from ICML. I apologise if this refreshes or otherwise upsets your RSS reader!

[idea:26w30]2026-07-26Week 30

Contents

I spent the better part of the week in Bucharest, Romania, visiting friends and attending Kraftwerk in concert—and so there’s not quite as much to report on. I did still manage to ship some features in Rheo, and also did some further thinking about an undergraduate course I hope to teach next Spring.

As I wrote last week, I decided to ship this next set of features as 0.5.1 rather than 0.6.0, given that 0.5.0 was released last week, and 0.4.0 was released just three weeks ago. There are technically two breaking changes in 0.5.1: 1) namely removing the rheo-context variable in favour of a rheo-context() function, and 2) resetting footnote numbers by default across vertebrae. The other changes in the release gravitate around fluffing the rheo-context().spine data structure up with the information configured using #set document statements in each Typst vertebra. This makes a lot more context regarding Rheo’s spine available, which also means that it can be abstracted away in packages like blogfeed (newly created this week), which now powers this site’s homepage.

Currently, the content in rheo-context() is powered by a ‘second’ shallow parse of the Typst files in Rheo, rather than in Typst’s compilation itself. This is probably unnecessary, as I’m pretty sure that different documents in a Typst bundle can introspect each other’s metadata. So the better solution would be a Typst-native construction, which would also avoid the three-way type transliteration (Typst types represented in Rust for Rheo, which then casts them back to Typst types again) that we’re doing currently. But the preliminary shape of what rheo-context() provides is now in place, which means that I can experiment with building out a Zettelkasten-like package that makes use of it, something that I’ve been meaning to do since I started writing weeknotes almost two months ago, now.

Among the other changes that landed was an adjustment to the way Rheo’s default stylesheet gets injected. It now shows up in the build through the Rheo asset system, which means as an external CSS file linked in the HTML header, rather than being inlined in the HTML as it was previously (for relatively arbitrary, historical reasons). This resulted in a glorious PR to rheo-tests removing some 14k lines of repeated code, as we store full HTML references in the test harness.

If you follow these weeknotes regularly, you’ll know that I started building an agential harness from scratch a few weeks ago. I decided this week to build a seminar/studio course in tandem with the development, as I believe that building a tool analogous to Claude Code from scratch could both disillusion young engineers of the trending idea that there may soon be nothing left in software to work on, and give a good hands-on introduction to how to work effectively with LLMs, whether local or accessed via API.

This is a space that is changing rapidly, both as frontier labs release new models and as we discover how to most effectively work with the jagged intelligence they avail to us (mere mortal humans). I expect the sketch that I have now of the topics we will cover in each week of the course to change by the time I actually offer it, as the earliest I might teach it is in Spring 2027.

Because the course will involve graded assignments, I’ve taken the konrad codebase down from the public domain, moving it from tangled to GitHub, as I haven’t yet had the time to set up a self-hosted source forge and—as far as I can tell—tangled doesn’t offer private repos.

The Kraftwerk concert in Bucharest was the highlight of my week away. To my shame, I haven’t listened too extensively to them up until now. I particularly enjoyed their rendition of Tour de France given its present resonance. Autobahn also always hits the spot. (This number I have heard many times before, as it was a major staple in a playlist I was listening to when I was taking a course titled ‘Histories of Infrastructure’ with Arunabh Ghosh in the first semester of my PhD.)
[idea:26w29]2026-07-19Week 29

Contents

It was a relatively good week work-wise, despite the IQ-diminishing heat sweeping Europe. On Friday I wrote and published a blog post detailing my current agentic coding workflow. It was spectacularly unpopular on Bluesky, squeaked out a few likes on LinkedIn, and garnered no attention on HackerNews. (I think I forgot to enable comments or upvotes when I posted? I can’t find any sort of link to it, now.) It was nonetheless time well spent, as putting to paper these thoughts about how LLMs are changing my personal experience of software engineering helped to clarify my thinking about the subject. If you’re curious about how I use my computer to write code these days (which includes the way I write the prose, although I use LLMs only for editing grammar and spelling in personal writing like this), check it out.

I also updated both this site and that main blog site to use the Rheo justify package, which should produce much better word spacing in all of my personal writing. When I viewed a post on mobile (I have a very small screen on my device), it looked a bit messy; so I reverted mobile to regular left-alignment.

[idea:26w29-diss]

Dissertation

I stacked up a small but significant (virtual) pile of papers about Marx and mathematics, and made further progress on the 2021 edited collection Karl Marx and Mathematics. Slowly I am building up a clearer sense of how this literature might all come together in a chapter.

For reasons I explained in last week’s notes, I cut another major release, 0.5.0, of Rheo this week. Probably most significant in this release is a change in how spines are specified in rheo.toml. A spine is the main conceptual extension that Rheo gives over Typst proper. It functions as a project management primitive, allowing you to split Typst across multiple files and then have the Rheo CLI automatically collect them together. If you’ve been following the latest features in Typst, you’ll know that this is fairly trivial to set up natively using a combination of the experimental bundle target and module system, which is more or less how Rheo compiles spines under the hood. Spines offer an abstract way to think about which files (‘vertebrae’) should be packaged into each format.

In 0.5.0, spines are inferred from the file system hierarchy of the content directory by default. I realized that this is usually what I want in my Rheo projects, and that this ‘spine inference’ gives Rheo more concrete utility over Typst; as maintaining spines explicitly translates the burden of tracking vertebrae into a different idiom (as was basically necessary in Rheo <0.5.0), rather than actually alleviating it. If you want to use the native Typst CLI to compile multiple Typst source files into a website with a corresponding number of pages, you need to set up a basic bundle/module template to import them appropriately. Using Rheo >=0.5.0, you can just run rheo watch . and get going.

I also added the rheo-context variable, which is the first step to comparably removing the need to explicitly set up a harness for tables of contents / sitemaps in sidebars and index pages. After a discussion with Will Crichton about this, I decided that I need to change the API in another breaking way this week, moving the data structure behind a rheo-context() function boundary. This is breaking for a variable that was only introduced in 0.5.0, though, and so I am considering subverting strict semver and batching the changes into an 0.5.1 release. Otherwise I might give the impression that a major version every week is Rheo’s standard development velocity, which is certainly not the case.

[idea:26w29-dtl]

Digital Theory Lab

I sunk my teeth back into this project on Tuesday and Wednesday, and I’m hopeful that we’ll soon have some public updates. The code changes did include one public PR to treetok, a Python library that gives an indication of the research’s general domain, i.e. LLM interpretability at the level of token variation. Here’s a sneak peek of some data visualization from the project:

This is a screenshot of a viewer that I wrote this week with Bonsai, a frontend framework developed at Jane Street that incorporates concepts from Elm, React, and other functional UX libraries and packages them through OCaml. Though I wrote recently about my drift away from web development, it was the topic of my most serious technical thinking as an undergraduate, and visualization is inseparable from programming, despite the fetish of some backend/systems engineering cultures that isolate the two from each other. I do like the idea of having a more powerful type system for frontend work (in Bonsai you write code in OCaml with effectively inlined HTML and CSS, and it compiles to HTML/CSS/Javascript).

Last but not least, I started a new project this week in the distributed systems space. I’ve decided to wait and see what comes of working on it for a few weeks before I say too much more, but I’m quite excited about it. My last serious job before grad school was at Halter working out the best way to build a feature store as an application running on Apache Flink, and throughout my PhD I’ve cast around in the streaming execution engine and vector database space for something that would stick. Part of the problem I had in this search, I realize now in retrospect, is that Flink and similar distributed systems are typically built out for the purpose of large-scale, industrial data processing, where data is processed as soon as possible after ingested (in ‘real time’).

Karaji—the name I’m giving to this new system—is something I’ve started building to address a personal use case, not a hypothetical business one. I started writing Rheo for the same reason—to do something with my computers that I hadn’t worked out how to do with existing software in a way that worked for me. It seems obvious to say (and this advice is widely circulated in engineering communities): but personal software is the most inspiring software to write, as there’s no better motivation for making something work well than wanting to use it yourself.

[idea:26w28]2026-07-12Week 28

Contents

[idea:26w28-diss]

Dissertation

First and foremost, my dissertation, for which a full draft of the second chapter is (informally) due as Fall falls. I have a skeletal but solid idea of what this chapter will contain/argue. But, as ever, there are books-and-books to read to flesh it all out in the open space of scholarly discussion. I found some (possibly) important texts that make arguments adjacent to the one I would like to pen regarding Marx’s mathematical manuscripts, and so I lined many of these up on my reMarkables to chew through in the coming weeks.

Some of this is reading in recent Marxist criticism (such as this); but much of it is more general education in the history and philosophy of mathematics, as this is not a domain that I have ever systematically studied. It is unfortunate for me that the “history and philosophy of mathematics” is such a sweeping body of literature that is often dense and particular. I have been reckoning with this wily character of the domain since at least 2024, when we started the Math(s), Philosophy, History reading group, which is roughly also when I started to think seriously about the history and philosophy of mathematics as an important lens for computationally inflected critical theory. The modern academic-historical sensibility—which still struggles under the weight of that ghastly postmodern apothegm; that everything has (nothing if it does not have) a specific time and place—often bristles at the conceptual scope of mathematical undertaking. The context for a proof sometimes swings from a seventeenth century insight (Leibniz, say), through progress made in the twentieth century, only to arrive promptly back in the present wherein some uncharted graduate student has unearthed a new way of looking at dots and lines. It is the broad-shouldered historicity of mathematical culture that makes it such a curious body of work to study in postmodern times: mathematical ideas seem to shrug off contextual particularity like water off a duck’s back.

Zeroing in on the mathematical developments that matter for my argument is the tall order on which I am currently at work. The overall aim is to link Marx’s critique of capital to the origins of computer science in the mid-twentieth century: hence my dissertation’s current working title, Mathematical Materialism: Capital, Calculus, and the Cradle of Computer Science.

In Rheo dev news, I have started preparing a 0.5.0 release, despite just last week releasing 0.4.0. This is another major version bump because it changes (in a breaking way) how spines work and how they are exposed to source Typst files.

This set of changes stemmed from my first serious attempt to build a zettelkasten-style linking system with Rheo, a project I’ve had planned since I started writing weeknotes. I thus set out to extend Rheo’s spine abstraction so that it included some notion of ‘blocks’, i.e. sections of text within a file. A spine in Rheo currently is essentially just a list of vertebrae, which have a one-to-one mapping with the files in a Rheo content directory. Typst documents, of course, are often broken up by headings, such as the one under which this text sits. The text that follows from each heading can therefore serve as a block, where a block essentially captures a select portion of continuous content in a Typst source file.

Following the pattern I have been using in these weeknotes, my first attempt was to get Rheo to track all labelled headings and to synthesize unique block IDs by concatenating the heading label with the spine vertebra handle. If the label <a> was attached to a heading in an ‘intro.typ’ file, Rheo would thus create the block ID <intro:a>, essentially extending the relative linking pattern to include blocks within files in the spine.

There isn’t a hard mechanical reason this couldn’t work, I don’t believe. But as I built out the implementation, the abstraction began to feel clunky and leaky. In order to synthesize such labels in Typst files in particular, Rheo would essentially have to edit the Typst source provided by the user, either replacing existing labels or inserting extra ones. Though there might be future features where it makes sense to do this, I realized that tracking blocks in this way is a feature that is somewhat specific to this zettelkasten use case, rather than a functionality that is likely to be used by other formats at this stage.

I therefore changed tack and worked out what would be necessary in order to do block synthesis downstream in a Rheo package, rather than in the core Rheo compiler. The required feature is one I’ve been meaning to add for some time, which is exposing spine information in Typst at compile-time. The way I decided to do this is to inject a rheo-context variable into every spine vertebra, where rheo-context is a dictionary that contains both a handle indicating the current file’s location in the spine, as well as a map of the whole spine. This latter map will enable an improved sidebar package, which will now be able to infer what to include rather than needing an explicit data structure, as well as for other code and packages that need a sitemap.

I also decided to incorporate the Rheo target info as part of rheo-context to limit the namespace that Rheo effectively reserves to just one variable. This means deprecating rheo-context, which is a breaking change, which is technically what is triggering the major version bump to 0.5.0. I don’t think Rheo has very many serious users other than me currently, so I’m not getting hung up about consistently staging releases or keeping backwards compatibility at this stage of development. I also started working on a more structured way to specify spines, which will amount to another breaking change, so jumping straight to 0.5.0 on the next release (sometime next week) will certainly be warranted.

Lastly, I added a justify package which operationalizes a demo Andy Matuschak sent us showing how you can get better Knuth-Plass spacing variance in the browser using pretext.

My wife and I went to our first condominium meeting this week, which was somewhat titillating. Though the stakes are small, all things considered, the seriousness and energy our neighbours brought to the table was invigorating. We hope to propose a more organized rubbish system (which includes horticultural accoutrements) for the common space at the upcoming meeting in September:

Figure 2: This image is AI-enhanced. Currently the rubbish bins sit exposed in their naked plasticity where you see the beautiful garden plants in the image above.

We also found a free, air-conditioned, and ambiently quiet workspace a stone’s throw from our apartment in (of course) the foyer of a bank. It’s nice to have this somewhere to go when home becomes that little bit too overwhelmingly regular.

I visited the Archivio Tipografico, and went to see an exhibition on the archaeology of Palestine at the Fondazione Merz. I also got caught in a small summer storm at the tail end of a gravel ride, causing a slide-out on a downhill from which I sustained minor injuries (scrapes on my right thigh and elbow):

[idea:26w27]2026-07-05Week 27

Contents

Back at home this week, I spent a lot of time with my new Framework Desktop. Over the course of my PhD, I’ve been slowly but surely transitioning from coffee-shop worker to a seated homebody. 1

I cut a new release of Rheo this week, 0.4.0. This version both upgrades Rheo to Typst 0.15.0 as its Typst compilation engine, and also uses the new bundle compilation target as the primary mechanism for compiling Rheo spines. The former engine upgrade means that Rheo 0.4.0 compiles Typst math syntax to MathML in HTML, and the latter spine implementation detail means that Rheo now supports Typst-native labels for relative linking in projects.

I also massaged out an early design decision that had been turning into something of a leaky abstraction, namely a global merge attribute on all implementations of FormatPlugin. My original thinking was that, by toggling merge as true/false, a user could determine whether they wanted a spine to ‘reticulate’ (compile) into one document (as a single PDF, say), or into N documents (where N is the number of vertebrae in the spine). Now that I’ve been using Rheo for all my writing for a few months, I’ve decided that this optionality stuffs more complexity into Rheo’s API than it’s worth. The formats we currently care about—PDF, HTML, and EPUB—have a baked-in notion of whether they should produce 1 or N files ("pdf" = 1, "html" = N, "epub" = 1. EPUB is actually something of a hybrid, as we produce N XHTML files, but then package them as 1 file.)

Besides not really being useful to me in practice, the global merge attributed added complexity to the lifecycle of FormatPlugin implementations. When merge was true, compile would only be called once, as all of the spine vertebrae would be assembled into a single virtual file that would then be passed off to the Typst compiler. When merge was false, however, compile was called once per vertebra, which led to poor performance, as Rheo would essentially have to run a typst compile command for every vertebra independently. Because Typst 0.15.0 makes it possible to produce multiple (N) output files from a single typst compile invocation, in 0.4.0, Rheo’s compile function is only ever called once, regardless of whether it produces 1 or N files. The merge attribute doesn’t exist any longer, although it could be added back as a format-specific option in the pdf crate if there is a need.

Because I now have  10 sites that I maintain with Rheo, I also added a rheo migrate command. This makes a best-effort attempt at modifying a Rheo project so that its syntax and configuration matches the most recent version of Rheo. In the simplest case, this just requires setting the version in rheo.toml to the latest, i.e. 0.4.0 at time of writing. But because the relative linking syntax has also changed, this command will also attempt to rewrite links from the old syntax (#link("./index.typ")[Home]) to the new one (#link(<index>)[Home]).

I also added documentation for the slides plugin (one of the important use cases of Rheo for me that has been difficult to manage in Typst natively) and consolidated the configuration around Atom feed support.

I’m quite happy with Rheo’s shape now. I use it daily (for all my writing, documentation, and slides), and it seems that there are at least a couple of other people using it. It’s getting close to 200 stars on GitHub, but I only know of 2-3 others who have actively reported using it. This could, of course, simply be because many others have used it and found nothing to complain about—but I somehow doubt this. Crates.io does show around 300 downloads, and I don’t think that includes cargo binstall (?), which is the recommended way of installing Rheo on the docs and README, so that’s promising.

[idea:26w27-typst]

Typst Limited Forms Application

I heard back this morning (Monday 6th July) that I wasn’t selected to implement the limited project this summer adding support for forms at Typst. I thought the interview (on Wednesday 1st July) had gone relatively well, as I had identified a number of issues with my take-home assignment in advance, and thought that I had demonstrated a reasonable ability to refine and improve the design in the 1-hour interview. In any case, it was nice to receive some written feedback about why I wasn’t selected:

The section of your take home about type mappings in the API was well thought-out and matches Typst design spirit. Groups and fieldsets were one of the focal areas you chose for the take home and we zeroed in on them during our interview. We felt like at the end of the interview, we still did not achieve clarity about the rationale, use, or implementation of groups and did not manage to sufficiently differentiate them from field sets. During our interview, we also noticed that having the editor open at times did more harm than good as it took focus away from the conversation. Nevertheless, both your presentation of Rheo and the take home were approachable and showed that you did your research.

All in all, this seems a fair assessment, and suggests to me that the main reason I wasn’t selected is because another candidate was a better fit / performed more impressively in the take-home and interview. There were some unresolved issues with groups/fieldsets from the interview, and though I personally felt that I made good progress on smoothing them out over the course of the interview, it’s possible that there are deeper contours of the PDF/HTML spec that I hadn’t considered that render my design fundamentally weak or otherwise inappropriate. The feedback about having my editor open is interesting, too. I personally felt that we were able to specify and resolve several issues precisely because we were looking at concrete examples. But it’s useful to know that this was most likely a solipsistic experience, rather than a feeling shared by my interviewers, and I will certainly keep this comment in mind during future interviews / pair-programming sessions.

I’ll of course be curious to track the implementation of forms as it does happen over the course of this summer; and to learn more about Typst from the design that bested my proposal! Though I’m naturally a little disappointed that I didn’t get this gig, it does free me up a little to focus on my dissertation and other projects that are beginning to get into flight this summer (see Konrad below, for example). So the disappointment at least hit this morning with a slight touch of relief.

I spent a good portion of Thursday and some 10 hours on Friday putting the finishing touches to this frontend platform, about which I wrote a couple of weeks ago. The platform will hopefully be released publicly soon, and despite my deepening alienation from frontend development, I’m quite proud of the platform from both a design and investigative perspective. I wasn’t responsible for any of the investigative work, really; but I do think it documents important aspects of the changing nature of migrant pushbacks on the Mediterranean. Besides a few tweaks and touches in design review, I don’t expect to be sinking much more time into development of this platform, which is also something of a relief. At this stage, it’s been more than a year since I decided to get involved with the project. As is often the case with investigative platforms of this nature, we spent a lot more time refining the design and waiting on collaborators than anticipated, and so the project has been drawn out beyond its original context.

I was inspired to start a new project this week building an agential harness from scratch. This is partly a pedagogical exercise so that I can better understand the mechanics of tools like Claude Code, which is now an essential component of my coding workflow, prompted by reading about Anil Madhavapeddy’s own experiments with bootstrapping an agential harness in OCaml. But I also think building agential harnesses that use local models effectively (as opposed to models hosted by frontier labs or compatible APIs) might be a space in which genuine research/hacking needs to be done.

After a bit of jockeying with Kagi Assistant (my LLM research platform of choice), I settled on the name konrad; following the naming inspiration of Anthropic’s ‘claude’, but with reference to the first name of a different computing luminary known for his autodidactical elan. I’m developing the codebase on tangled:

The idea is first to build an implementation in Rust, as this is the language with which I’m most familiar, and which seems most appropriate to the task at hand given that it will need to interface with relatively low-level code to run local models as close to the metal as possible. If that goes well, then I have in mind to see how successively I might develop alternative implementations in either/both OxCaml and Lean, two languages about which I’d like to learn more, from a language-independent spec that I’ll try to build alongside the initial Rust impl. This experiment is spirited by the idea that, given how well LLMs can now produce code, there might be newfound gravity in a software’s specification and test suite independent of any canonical implementation.

[idea:26w27-diss]

Dissertation

Dissertation work slipped a little under the radar this week. But I did wake up in the middle of one night and finish an essay or two that I’ve been meaning to digest. And I took Jensen Suther’s True Materialism up again. I should focus more here this coming week.

I discovered a glorious new climb on my road bike one evening:

The route out wasn’t particularly inspiring in the 5-6PM traffic, but the salita over the lake was well worth the moto scoppio. Next time I’ll consider taking the train out the first 10km, as it would make the ride both more pleasant and easier to fit into the day.

Those who follow professional cycling will know that the Tour de France started this weekend. The best way to watch cycling is to be cycling yourself on an indoor trainer: and so I’ve set up my Zwift in the cellar (where I keep my real bikes) and augmented it with an extra screen so that I can run both the Tour and Zwift concurrently:

When it was set up in my previous residence’s turreted office, this Zwift station was aptly dubbed the ‘Power Tower’. I like this real rhyme much better than the ‘pain cave’ (common and colloquial nickname for an indoor cycling setup these days), even if the latter is inarguably the more appropriate to my new setup’s elevation and aesthetic. So the Power Tower it remains! I will be pushing watts (paltry compared to the pros) on this thing for many hours over the next three weeks while I watch Tadej Pogacar make winning races look like child’s play, despite all the world’s other best riders being in the bunch.

Footnotes

  1. ^ This transition has been helped along by the fact that I now drink coffee almost exclusively at home in search of quality. Perhaps I’ll update the desiring world on the particulars of my coffee-making setup in a post on my main blog sometime soon.
[idea:26w26]2026-06-28Week 26

Contents

This was essentially a holiday week, spent based in Morciano di Leuca, a small town at the heel of the Italian boot. This turned out to be a reasonably effective way to temper the heatwave sweeping Europe (with the ocean breeze and salt water), though it wasn’t directly planned this way. I mostly managed to wrap up some reading projects, bulk up my running volume a bit, and experiment with how LLMs have improved the text-to-speech landscape. I did also manage to make a little progress on Rheo on the 9-hour train back up on Friday (from Lecce to Reggio Emilia).

[idea:26w26-diss]

Dissertation

I wrapped up note-taking for Karatani’s Transcritique (about which I wrote a little last week). Suffice it to say that this book has firmed up many convictions that were already starting to form about Marx and his critique in Capital, but for which I didn’t yet have external anchors. I now need to cast a net out to find what has been written in Karatani’s wake (in English), as the book is almost thirty-five years old at this stage (originally published as essays in 1993, translated into English in 2003).

I also read the first half or so of Erich Fromm’s The Art of Loving—although the copy I have is in Italian, and therefore is titled L’arte d’amare. I packed this book after finding it in my wife’s parents’ bookshelf as a precaution, as I don’t like taking my reMarkables to the beach, and ended up flipping through the first 50 or 60 pages. I don’t imagine that this book will be essential to my next chapter, but it broadly sits in the literature I’m treating (Marxism, psychoanalysis; and therefore the Frankfurt School), and I may yet finish it and/or return to it.

I only spent one decent session coding, but did manage to update the Typst version that Rheo vendors to the latest 0.15.0 release. Crucially—for my dissertation, among other projects—this Typst release compiles math expressions to MathML, a markup language for math that browsers support. The workaround up until this point has been to wrap every math expression in a frame element, which converts the expression to an inline SVG; which often leads to styling anomalies, as CSS can’t target SVG in the same way it can DOM elements. I’m yet to really confirm how the new version feels as part of Rheo.

I also started working on a PR to make use of Typst 0.15.0′s experimental bundle target as the mechanism through which Rheo compiles spines. This will change a few things about Rheo’s compilation, but most importantly it should allow us to finally shed the way of doing relative linking that’s existed since 0.1.0 (using #link("./file.typ)[]) in favor of a variation on the native @ref syntax. The current #link syntax is brittle in a number of ways: I just hadn’t yet got around to scoping/implementing a more native reference syntax. I’m hopeful that the bundle target will allow us to provide this syntax essentially for free, i.e. without having to implement much in the way of an additional parsing phase.

I re-read the Typst tutorial, and also spent an afternoon (once back from Puglia) studying improvements to my take-home assignment from a few weeks ago with Claude. This was a super effective review/study technique, and I think furnished me with the beginnings of a more intuitive perspective on Typst’s API design, as well as the specs for PDF and HTML forms.

[idea:26w26-tts]

Text-to-speech

I took the holiday opportunity to experiment with these. I originally tried ElevenReader (at an LLM’s suggestion). After an hour of two listening, however, I got frustrated with how it would get stuck in footnotes or citational paraphernalia, as the parser for the PDFs I uploaded didn’t do a particularly good job of navigating the page structure.

At another LLM’s suggestion, I switched to Paper2Audio, which I am finding much more congenial. I had originally wanted to listen to Tommaso Astarita’s Between Salt Water and Holy Water: A History of Southern Italy: but the free version of Paper2Audio puts a limit on the number of pages in the PDF you can transcribe to audio, so I settled on Joseph Weizenbaum’s Computer Power and Human Reason.

I’ve been meaning to read Weizenbaum in full for a while, but I’ve never quite found the time. Because I have a heap of dense and theoretical reading to do for my PhD, I usually prioritize this when I’m with my reMarkables. The attention required for audiobooks is of a different nature, however, and it turned out that Weizenbaum’s style of writing is just about right for what I can cognize via audio at the moment. I listened through about 50% of the book, mostly while running.

[idea:26w25]2026-06-21Week 25

Contents

I am in Santa Maria di Leuca, Puglia, at the very southern tip of Italy currently, and as such only reading is on my agenda for the coming week. I’ll finish Karatani (more on progress in Dissertation), and restart Jensen Suther’s True Materialism, a book I’ve been meaning to discuss with Carson Welch for a few months now—and as the summer heat really sets in, we’ve slapped a date on it.

[idea:26w25-diss]

Dissertation

I worked more through Karatani’s Transcritique this week and am a few hours away from having detailed notes across all of its chapters. I’ll preview my organised thoughts about it here, as next week I’ll flesh them out some more, perhaps in a blog post on my main blog.

As far as I can tell, Karatani is a critic on pretty low volume in the English-speaking world, given that he is a figure apparently as great in stature in Japan as Fredric Jameson is in America. Architecture as Metaphor and Transcritique were translated by Sabu Koshu and published with MIT Press in 1995 and 2005 respectively. Columbia University Press published History and Repetition in 2011 ; but it was not until the publication of The Structure of World History with Duke University Press in 2014 that the Anglophone Marx studies world seems to start really discussing his work.1 Duke then published Isonomia and the Origins of Philosophy in 2017, Oxford University Press Nation and Aesthetics also in 2017, and two more translations of Karatani’s work have been published by Verso in 2020 and 2026.

There may be other translations into English that I’ve missed, as Karatani has written and published more than 20 books in Japanese over the course of a career that runs from 1980 to present. But despite this good number of translations, I am now surprised that I have heard so little of his work having read Transcritique. The book argues that transcritique is the common methodological thread that ties Marx to Kant, and in turn re-reads Marx’s Capital as a transcritical reading of political economy. For the uninitiated, this is heterodox essentially because it has been much more common to tie Marx tightly to Hegel, rather than Kant, both because Marx explicitly positioned Capital as a counterpoint to Hegel’s dialectical method, and because his intellectual biography has much more obvious ties to him. Whether it matters or not for our reading of Capital and Marx is the table stakes of the debate. (Whether reading Capital and Marx in the 21st century matters is the topic of my dissertation. Spoiler: I argue that it does, and that we have few better philosophical resources for thinking about the social architecture and politics of computer science.)

I’m hung up on Karatani at the moment because he argues in Transcritique that Capital is “a Kantian critique of the ill-contained drive of capital to self-realize beyond its limit” [2, p.9]. Karatani divulges to the reader a wealth of good thinking about these terms—critique, drive, self-realization, limit—in a number of respects; but the fundamental aspect of Marx’s work that his argument’s vocabulary opens up for me is its mathematical nature. If Marx is a student of Kant, then he is a student of formalization and the ways in which we can (and can’t, or shouldn’t) claim its intricacies bear a relation to reality. As noted, I intend to digest Karatani’s Transcritique more directly somewhere soon, so that’s all I’ll say for now. What reading Transcritique has confirmed for me is that I need to read Karatani’s other work, especially his writing on Marx (Marx: Towards the Centre of Possibility and The Structure of World History), and learn more about 20th century Japanese Marxist thinkers such as Uno Kōzō.

Footnotes

  1. ^ I haven’t yet done the legwork to properly reconstruct this discussion and its stakes, but Elena Lange—a scholar currently at Zurich who seems active in value theory debates about figures like Alfred Sohn-Rethel—seems to be one of the key nodes; as does the Verso translator Gavin Walker.
[idea:26w25-dtl]

Digital Theory Lab

At the beginning of the week, I wrote a full first draft of a section for a paper formalizing the kinds of experiments that we’re running. It needs a bit of work—I run the risk of overformalizing aspects of our experimentation, and we also need to do some more literature review to understand whether or not aspects of our approach go by other names in other fields of machine learning—but it was a useful start.

I also got the codebase running on my new Framework Desktop with a PR adapting CUDA (Nvidia) hardware acceleration to ROCM, the analogous software that allows GPUs to process machine learning tasks on AMD. This was pleasantly straightforward, as hardware acceleration in Python has come a long way since I was last messing with it in 2018/19. I’m really excited about this project, as I hope it will be a real contribution to machine learning interpretation from a more humanistically-centered place.

No direct progress on Rheo this week, besides tracking a few issues following from the Typst 0.15.0 release. As per the intro above, likely nothing substantive this coming week either. I am, however, reviewing the Typst documentation and reference for an upcoming interview for a limited project.

Most of my week was sunk into developing a new feature for a platform for a forthcoming investigation about migrant pushbacks on the Mediterranean. I made a false start at rewriting the whole thing in bonsai a couple of weeks ago, but deadlines have demanded that I fall back into React.

The technical details of the platform are, alas, no longer very interesting to me. There was a time when I was excited to learn about the browser, WebAssembly, and other infrastructures of frontend development, but several years at grad school have shifted my perspective pretty substantially. One of the most difficult things about frontend engineering, I think, is that it almost always means you are interfacing with designers and/or clients who don’t have substantial software knowledge directly. This is essential and necessary work in so many domains; but it’s densely difficult, and requires good communication across many channels, which means meetings, changes, backtracking.

Frontend engineering is sometimes colloquially treated as less technically requiring than backend engineering or systems programming. To me this stems from a misunderstanding about what is hard about building software, about what it means to be ‘technical’. It’s easy, relatively speaking, to identify a problem in a domain with people who all speak your language, who all generally speaking approach the problem in the same way. It’s much harder to work effectively in the squishy channels of human-to-human communication, parsing and formalizing desires as features, and doing so with a bedside manner that allows everyone to feel like they’re getting what they want. Frontend engineering is almost definitionally on the frontlines of this kind of work, the most difficult aspect of engineering, because the browser is one of the most common places where software systems get exposed to users with vastly different understandings of computation.

Grad school has been a haven for me in which I have been allowed to work without guardrails towards aims largely of my own choosing. 1 I have chosen to work almost exclusively in Rust, a programming language at the other end of the spectrum: by design/definition, Rustaceans (those who work in Rust) get to work with colleagues who have a shared understanding of computation and how to handle it. An absolutely banal yet absolutely accurate observation: there is a cooperative joy to sharing a community with others who share your basic understanding of what work is! If given the choice, I can’t help but think that I would rather not do the hard, labyrinthine, and mercurial labor of translating between computational dialects, as good frontend engineers must do. Let me work in a terminal and modal text editor on a NixOS machine, so that the only people I have to explain my work to are those who already understand the vocabulary in the first half of this sentence.

Despite the above disavowal of frontend engineering, I have enjoyed learning the level of abstraction at which one needs to prompt models like Anthropic’s Opus 4.7 to get meaningful results in frontend development. It’s often not enough to say something like “make the red square clickable”, as an LLM is much more effective if you gesture using the language of HTML and CSS (“make div.nav-bar-button clickable”). Thinking clearly about data structures and how they will support the functionality in your application is also work worth doing, as Claude will not (in my experience) do it for you.

Footnotes

  1. ^ Not all PhDs have this latitude: but my program does, and I’m very grateful for it.

On the long train to Puglia (from Reggio Emilia, 8ish hours) I downloaded ElevenReader and started listening to some PDFs and EPUBs I’ve been meaning to read as a rest from my reMarkable. This was surprisingly successful, and I will experiment more with this synesthesia while on the beach. (Though it has no problem with the sun given its e-ink, I’ve never quite managed to read successfully on my reMarkable at the beach given the sand, sweat, and heat.)

Bibliography

  • [2] K. Karatani, Transcritique: On Kant and Marx. Mit Press, 2005.
[idea:26w24]2026-06-14Week 24

Contents

This week was one of the first that I have spent almost entirely uninterrupted in Torino. Though we formally moved here in January of this year, it seems as though there has been something to flit to almost every week, either in another part of Italy/Europe, or overseas. (For almost all of April I was in the US, as I organized two conferences which ran on back-to-back weeks in Providence.) This summer should be a welcome period of respite from becoming a journeyman academic (although we have a holiday planned in Puglia the week after next.)

[idea:26w24-diss]

Dissertation

I only managed a few hours continuing to work through Karatani’s Transcritique this week, but they were an important few hours. I’m 200 pages in (out of some 320), but something is really starting to churn. I am purposefully moving slowly in order to more surely cover the important details in my notes (which I hand-write on a second reMarkable), as I suspect that Karatani’s argument about the isomorphic relation between Kant and Marx will be what shores up some of the conceptual turns in the last section of my dissertation’s first chapter, which is an exposition of Marx’s theory of the commodity in relation to Kant and the philosophy of cause.

I don’t yet know a lot about Karatani’s reception in Anglophone Marx studies1, but at first glance it seems to me that Transcritique illuminates a wealth of possible developments in discussions being had currently around capitalism and its discontents. My aim for the next week is to work through the last 100 pages.

I also gave an internal presentation (on Zoom) about my dissertation in the Machine Visual Culture group based at the Bibliotheca Hertziana Max Planck Institute for Art History in Rome. I’ll be starting a predoctoral fellowship with this group in September 2026, and so this was a nice opportunity to communicate to others who are active in the group what I’m working on while there. I am now happily using the Rheo slides package to annotate my dissertation repo directly with slides as ‘inserts’ in the prose. This means that I can annotate excerpts from the introduction with visuals in talks such as this one, and then more easily fold edits and augmentations back into the body of my dissertation. The preparation for this talk meant that I built out slides that run parallel to the entire first section of my introduction.

Footnotes

  1. ^ ‘Anglophone Marx studies’ is the moniker I use to avoid referring to ‘Western Marxism’ given the critique that some such as Domenico Losurdo have made of that formulation. I refer to ‘Anglophone Marx studies’ as a sort of next-generation Western Marxism (in the academy) that is astute to the criticisms leveled at its paternal concept; but which also takes issue with some such criticisms when stated too crudely, such as the claim that many 20th century European Marxist philosophers abandoned class struggle in favor of bourgeois comfortability.

Much of my week was dedicated to Rheo or Rheo-adjacent work. I added Atom feed generation to the html crate, and in the process did some refactoring to improve the quality of the codebase. I also minted a v0.3.1 release so that I could integrate this feature into the build process for my main blog and weeknotes, both of which now have Atom feeds!

Though Atom/RSS feeds are a run-of-the-mill feature for any static site generator (which is part of what Rheo is) and are not really complicated or interesting in themselves, the Atom feed implementation in Rheo highlights how it is architected as an extensible compilation toolchain for Typst.

In Rheo-adjacent news, I spent much of Wednesday writing a job application for a limited project adding PDF Forms to the Typst compiler, a freelance project that the Typst core team recently put up as a 3-month gig over the summer. I applied as, though I’ve made a few minor contributions to the open source project, it would be helpful to get some structured experience contributing. This summer is an especially good time for me to take up something like this, as I’ve just effectively extended my PhD by a year by receiving back-to-back predoctoral fellowships for the upcoming Fall and Spring.

The take-home project was an interesting exercise. It involved reading the PDF and HTML specs for interactive forms, and then designing a Typst API that integrates the two in a unified interface. As this is essentially the task of the limited project (three months of work), it quickly became clear that I wasn’t going to be able to smooth all of the sharp edges in the divergence between the two formats, so I just did my best in (the vicinity of) the 4-hour time limit. Here is the take-home assignment I submitted for the role, which is naturally typeset with Typst/Rheo. I expect to hear back about whether I’ll move to the interview stage this coming week.

[idea:26w24-dtl]

Digital Theory Lab

As I now have a machine that has enough RAM to run some serious local models (see Framework Desktop), I ran some preliminary experiments using a codebase that Tyler Shoemaker and I have been working on to test the limits of open source LLMs such as the qwen family of models. (I have been trying to find hardware to run these on for a while, and thought I had SSH access to a machine with enough RAM at one stage a few weeks ago: but then it turned out something was off with my login credentials, or possibly the VPN I use to access the network.) More next week on this front, I hope.
I took some small steps to further configure the Bonsai rewrite I started last week; but was largely blocked on significant progress in this project due to the excitement I talk about next in Framework Desktop
[idea:26w24-framework]

Framework Desktop

The absolute biggest news this week in relation to my research is that my new Framework Desktop arrived. I’ve known that I wanted this thing ever since it was announced in February 2025, as I have been the happy user of a Framework Laptop for a couple of years now. The old Dell laptop that I’ve been using as a substitute desktop neglected to turn on one morning, and so I greedily pulled the trigger and ordered one. This purchase took a serious chunk out of my savings: but life is short!

I’ve always wanted to be more savvy about the hardware aspect of computers since I got a bit of professional exposure to hardware and firmware as a backend engineer at Halter in 2021, but I remain embarrassingly dilettantish with respect to the knowledge domain. I know the basics that any software engineer worth their salt does—which is to say, I have a very abstract but functional understanding of how CPUs, RAM, GPUs, and hardware devices like disk and NVMe storage work, when it comes to writing performant software that runs on them—but there’s an enormity more to learn. Assembling a Framework is like the Ikea of assembling a computer: you do almost nothing because they’ve put all the ingredients in the right place for you and made it hard to screw up. But Apple and other hardware titans like Dell have made even the thought of fiddling with a RAM chip or replacing a fan all but unthinkable.

It took me less than an hour to set up my Framework Desktop, and now it’s sitting on my desk and running like the little monster that it is:

I run NixOS on all of my machines, and it’s effortless to run this operating system on a Framework machine, as all of the steps in the official NixOS install guide just work out of the box. Because this Framework Desktop is more powerful than my laptop, I also spent a few hours messing with ollama and configuring some local LLMs, which I intend to play with more seriously in the coming weeks. I follow Simon Willison’s work on llms, and I want to follow in his footsteps and play a bit more seriously with local models now that I have the beefy hardware to do so.

[idea:26w23]2026-06-07Week 23

Contents

As this is my first entry of weeknotes, before writing out these actual notes, I wrote a general introductory post and posted it to my blog site.

[idea:26w23-diss]

Dissertation

Early this week I received a desk rejection for a paper that I had submitted a few months ago to a top journal. I wrote the paper several years ago now, and I no longer feel that it represents my best work. But I still broadly think that it contributes something to the discourse (about AI and capitalism), and had hoped to place it in this journal on account of the fact that last year I had had a paper rejected from the same venue, but with encouraging comments. The peer review timelines in the humanities are punishing, unfortunately, and so I now have on my hands a paper that I’m beginning to feel less excited about (it has been rejected from two journals now), but which I feel that I should still peddle, especially given my early career stage as an academic.

Part of my feeling divided about the academic mercantilism of pushing to publish papers in prestigious venues is that, in the very early years of my PhD, I ‘open sourced’ a paper after another paper came out that (I felt) stole the (almost inaudible) thunder of the point I wanted to make. Though I don’t feel at all that this paper was my best work, I do hear every now and then from folks who have found it on my website and find the writing useful or interesting one way or another. Had I published it in the non open-access venue for which it was written, I very much doubt it would have been read as much. Of course, releasing papers as ‘preprints’ on my website abandons the benefits of peer review, which are non-trivial when the process is done right. But I increasingly am beginning to feel as though the time-cycle of peer review in the humanities (6-12 months, sometimes more) also prevents a lot of good work from coming out in a timely fashion. Whether or not the essay that I have just had rejected is a part of that ‘good work’ is, of course, a question that I am not best positioned to answer, as the paper’s sole author and therefore someone with an emotional attachment to the piece that makes me want to see it as such.

On the reading front, I am still working my way through Kojin Karatani’s Kantian Marxian treatise Transcritique, a book whose argument will help structure the transition from Chapter 1 to Chapter 2 of my dissertation. (I currently have a full draft of Chapter 1, and need to complete a full draft of Chapter 2 before the summer is out.) I also churned through a number of the articles in the most recent edition of the LRB (having just purchased a subscription), and finally opened George Eliot’s Middlemarch, having purchased a hard copy of the novel last Christmas.

[idea:26w23-dtl]

Digital Theory Lab

I spent 3-4 hours drafting an introduction and reviewing PRs for a paper I’m working on with colleagues at the Digital Theory Lab that we hope to place in a machine learning interpretability venue later this year. (The outlines of the idea are in this presentation by Leif Weatherby and Tyler Shoemaker from a few months ago.) I need to present a full draft of this paper to my DTL colleagues early next week.

I refactored the Typst template from two Rheo sites (https://rheo.ohrg.org and https://book.cftw.ohrg.org/) into a sidebar component in the rheo-packages registry. (Previously, this was very similar code duplicated across both repos, as the packages feature in Rheo only landed three weeks ago, which enabled this factoring out.)

I also created a rheo-author Claude skill so that Claude Code can do a better job at working within Rheo projects without me having to provide a lot of context in every prompt.

I spent one morning in the library firming up a Turing test entry, which was then discussed by members of the project in our weekly working group. (More information on the LOLM project, which I run with Ryan Healey, is available here.)

In the coming weeks I need to finish up a frontend project for LIMINAL Lab. Several months ago, I (vibe-)coded a prototype of the application using React and zustand. There is an interactive table component in this application that has been fragile since I spun up the prototype; and I am almost unconquerably unmotivated to delve into the particulars of react-window to work out why the styling keeps going out of whack.

In an attempt to motivate myself to get steaming on the project again, I spent an evening (vibe-)porting the basics of the application to Jane Street’s Bonsai framework. Almost a decade ago now, I explored the tradeoffs between Elm and React as an undergraduate project, and in all of the serious frontend work done since I have longed for a framework that feels better than React, for a way to write web applications with more express use of types.1

The OCaml tooling setup (opam, dune, etc.) took an hour or two to get used to, as it’s not quite as smooth-surfaced as the modern bundling tooling for JS (pnpm, vite, etc.). But I now have a basic copy of the single-page-application prototype I had in React, and am much more excited to rewrite the interactive table component while refining my OCaml and Bonsai. This will be the thrust of what I work on in this coming week.

Footnotes

  1. ^ React with TypeScript has been the gold standard for a few years now, in my opinion. But TypeScript has always been the layering of more structured types over the chaotically typed underbelly of JavaScript, a more robust and better supported version of Facebook’s flow project.

Kohei Saito, the Japanese eco-Marxist who came to fame through his book on Marx and the Anthropocene (and the youngest ever winner of the Deutscher Prize, apparently), was in Torino for a film festival! I moved to Torino at the beginning of this year with my partner, and we are still ‘integrating’ and learning about the sociality and activities that take place here; so it was nice to feel as though a part of my academic world (anglophone ‘Marx people’) was here, if only briefly. We fangirled after the interview and got a picture with him: