fifthrevision

  • Essays
  • Blog
  • Projects
  • Bookshelf
  • About

Blog

From my head to yours, no filter.

  • October 2026
  • September 2026
  • August 2026
  • July 2026
  • June 2026
  • January 2026
  • November 2025
  • June 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025

dtg 0.4

This release has three main changes:

  1. A much improved onboarding experience. Better readme, more sensible vocabulary, and dtg init writes a working definition with the option to start with the Material or Tailwind examples.
  2. UI and UX improvements to the editor. Yes, it’s just called the editor now (invoked with dtg edit). Particular attention was paid to how the color picker behaves and functions.
  3. An important under-the-hood change: colors are now stored as unbounded OKLab values and each algorithm decides which math space to compute in. Previously, dtg guessed a color space from how the inputs were written and converted everything to it before computing. That could clip wide-gamut colors, and colors written in different notation could produce different results. Gamut now only matters on output.
Posted Oct 26, 2026

dtg 0.3

Version 0.3 of dtg is out. Check it out on GitHub!

This is a substantial release. By the end of 0.2, I knew that the next version would entail major changes. I didn’t appreciate their extent until the work was underway:

  • A new top-level palette keyword in the definition file. Palettes collect colors into a set for viewing and manipulating. They are for an earlier, more exploratory stage of color work, where designers puts colors side by side and adjust them until they work well together. Palettes also serve as inputs to roles and systems, and replace the use of constants today.
  • System addressing now uses method parameters instead of paths. Use sky(3 tint) instead of sky/3/tint. Dot notation is still used for traversal, e.g., warm-wash.red(6). This syntax makes it easier to distinguish what’s being used from what’s being configured, while more closely resembling CSS color functions.
  • A simpler set of out-of-the-box algorithms. ink-ramp became tint, oklch-scale became scale and blend was removed by a group of tint systems. The algorithms are also more focused, with simpler interfaces and fewer responsibilities. Definitions are more concise, and output is now explicitly controlled by the definition file rather than the algorithms.
  • Modes support color-scheme and inheritance. Modes can now be associated with light or dark color schemes, and they can inherit from other declared modes as well. This makes it easier to build related themes, including high-contrast variants or themes that differ by only a handful of colors.
  • Edit the definition file through the bundled web editor. As much as I like the syntax, color work is fundamentally visual. In 0.2, the web editor let you preview colors and how they are used. In 0.3, it supports editing and saving directly. I’ve paid particular attention to the color picker, making it easy to adjust colors, especially when working with dtg dev --build. A few things are still missing before it is possible to author a definition file from scratch, but we’re getting there.
  • Quality of life updates to the web editor. Systems can now be simulated without requiring a reference. Color scales are displayed more clearly, and hovering over any swatch reveals its color information.
  • And tons of changes to smooth out the rough edges while using dtg:
    • The config file dtg.yaml is renamed to dtg.config.yaml so that it’s both more differentiated from the definition file, and closer to other config files inside a codebase.
    • There is no longer a default path for definition files. Specify them in the config file.
    • dtg emit becomes dtg build and the --live flag got renamed to --watch to align the verbs to other tools.

The CLI can also generate static pages for publishing (dtg docs --out <dir>). Here are the colors that fifthrevision uses, along with a preview of Mosaic’s (my design system) colors and component library.

Truthfully, we’re still in the early stages of the project, where many of the building blocks are still being reconsidered and refined. Version 0.2 demonstrated the value of a color tool that captures how colors are derived. Version 0.3 focused on making the idea practical, with a coherent foundation and usable interface. The basic shape should now be largely stable, with fewer breaking changes going forward. The focus for the next release will be on from-scratch authoring and extension points, as well as support for gradients.

This tool has been invaluable to me and my coding agents as we iterate on Mosaic, and hopefully it will be for you as well.

Posted Oct 19, 2026

Axle release 0.33 and 0.34

I should make a habit of writing about releases when they come out. The weekly cadence means announcements sometimes get bunched up.

0.33 and 0.34 are substantive Axle and CLI releases that let me acheive a personal milestone: I have a agent doing financial research on a schedule and sending me a text message with recommendations.

On the CLI side, 0.33 added scheduling to Axle CLI on macOS via launchd. Tasks can now run on interval or schedule through the axle schedule subcommand, and can be retrieved using session and resumed as other Axle sessions. To make this useful, every CLI recipe gets a tool set unless specified.

0.34 completes the scenario above by adding Skills. CLI now supports the Agent Skills spec. Drop a skill in your local .axle/skills or .agent/skills folder and Axle will pick it up. Then, there are a lot of other changes under the hood to make sure the shape and ergonomics are right.

On Axle core itself, 0.33.0 and 0.34.0 bring in a grab bag of improvements. Skill support as a first class Agent concept. Pending Turns show up on Transcript, making it simple to render queued messages. New lifecycle hooks (async onSettled and onIdle) on the Agent object enable better lifecycle interactions. The static model registry got replaced with a dynamic one backed by models.dev so that consumers can look up real-time model info and pricing. There are tons of work under the hood as well: stability, robustness, protocol improvements, as well as a few breaking changes coming from implementing better mental models. Building a library is a process of understanding the problem, and then understanding the problem over and over again*.

And oh, TypeSafe’s decision API is in Core as experimental. I’m looking forward to integrating it as a first-class citizen for classification into Agent – more on that soon.

Full release notes can be found here.

Posted Oct 11, 2026

Goodbye Jekyll, hello Astro

The first commit of this version of the website happened in February 2017 (169e91e7). It went from a set of handcrafted HTML and CSS files (edit: I was wrong, it was a Wordpress site!) to a site statically generated with Jekyll.

Jekyll gave me the vocabulary and the confidence to do bigger things. The loose collection of pages turned into a coherent set of essays and portfolio entries. Then, a reading list and reviews I would write of them (that ended up being a tough thing to keep up on). Later, a microblog.

In the last few years, I’ve noticed creakiness in the Jekyll ecosystem. Once, I upgraded the Ruby version and the build broke. Plugins stopped getting maintained (I’m looking at you, jekyll-paginate-v2). Liquid 4.x is limited in what it can express (5.x looks like it’ll never get supported). Lastly, I’m not a Ruby person and I don’t want to maintain custom extensions.

Recently, I’ve used Astro for a few content-heavy static sites and I liked what I saw. Well, first and foremost, I’m a TypeScript person. My requirements for this site remain the same: static-site generation primary, JavaScript as an enhancement layer, and building on top of a variety of content types. Back then, I flirted with the idea of porting the site to Astro, but the idea of undoing years of technical debt felt daunting so I never took the next step.

Yesterday, I bit the bullet and ran the migration using Claude Code. It was done in a few hours with Fable 5.1 driving Opus 5.5 subagents and the entire process went as smoothly as one can hope. Layouts went from Liquid to Astro components. The content folders became more sane; it’s interesting how many Jekyll conventions can quickly become limitations once the use cases outgrow what they were designed for. I took the opportunity to convert SCSS to plain old CSS — CSS is mostly at parity these days with a few features in the pipe. The codebase reads better, runs better (no more fumbling with bundler, why no run scripts?), and the generated output is basically byte-identical.

Then, I shipped my first site change in years, a revamped projects list. Which is to say, fifthrevision is now officially on Astro. So far so good! I’m sure I’ve traded one set of constraints for another. Time will tell.

For nearly a decade, you served me well. Thank you, Jekyll.

Posted Oct 06, 2026

Anti-social social technology

The first question we ask of a new technology is what can this product do for me. It’s a useful lens for evaluation, and AI is right in the middle of answering that: do my work, read my emails, write my docs, achieve my dreams, yada yada.

The question seldom asked is what can this product do for the other. How do we make it easier for the other person to understand us? How do we take the burden off other people that we work with? How do we help other people? Much of what we use today don’t arrive at this stage of questioning.

AI is poised to be the most transformative technology in my lifetime. It is also, so far, a Randian ideal: it accentuates differences and reinforces individual preferences. However, we are social creatures who rise and fall together. So the imperative question we should all be asking at the moment, designer or not, is what can this technology do for us.

Posted Sep 30, 2026

This week: Axle 0.31, 0.32

I haven’t posted an update in a while because I took a vacation and had to work for money! That said, Axle shipped a few minor versions:

  • Axle 0.31.0 shipped a major CLI revamp. This update took everything I’ve learned building apps with Axle and put it into a modern, usable TUI. In addition to the new UI, Axle CLI now supports follow up interactions and resumable sessions, as well as more sensible configuration and setup.
  • Axle 0.32.0 reworked the thinking Turn and stream objects. It’s a minor but breaking change to the format. The implementation of thinking has always been a little janky, and the recent release of Muse Spark 1.3 gave me a chance to revisit it so that it’s a little cleaner.

I’m personally pretty pleased with the CLI updates. This resolved a few longstanding issues I had with the previous implementation, including the fact that it was just really ugly. With the open weight models being quite cheap and good these days – I’m really liking GLM 5.3 Flash – I’m harboring a few automation fantasies on my life. Not quite there yet, a few more gaps to close, but I’m hoping to have some updates soon.

Posted Sep 15, 2026

Intelligence and behavior

There has been constant fighting with the latest crop of AI models.

A few things I’ve noticed: AI models are much more eager to jump in and do instead of understand what you want. When they write, the output is jargon-filled and convoluted. Worst of all, the recent Opus 5 just flat out make things up; over the last few weeks, I’ve had multiple incidents where after I push on a specific point in a plan, the model tells me that it made a mistake and acquiesces.

While none of this is indicative of intelligence per se, these behaviors make the model unpleasant to use. It feels as if they don’t understand my goals, try to paper over subpar decisions, and the most egregious of all, lie. I know I’m using people words here, ascribing intentionality to floating point numbers computed across arrays of special-purpose silicon. However, language is inherently anthropomorphizing; it is what we use to express and communicate with each other, and now with computers.

The thing is, none of this is inherent to the mathematical properties that create artificial intelligence. This is all trained behavior. My guess is that the pursuit of AI models that perform well on benchmarks and long-horizon tasks that leads to choosing verifiable rewards over human feedback creates behaviors that look like this. Inattentive and dismissive.

I’ve long thought that intelligence is not a linear measure. I had a conversation recently with a friend about this where I argued that preferences–for example in language and art–are not something that can be captured by scaling laws. He disagrees. I was arguing that there are different dimensions to intelligence and maxxximizing one will diminish others. A better way to frame it would be to separate what it can do versus how it behaves.

Perhaps soon, people will start talking about IQ vs EQ again. Perhaps one day AI model makers will find the right balance between the know-it-all and the we-get-you. But I’m not holding my breath.

Posted Aug 26, 2026

This week: dtg and company

I spent a good part of this week working on a color system to token tool called dtg. It’s a somewhat niche tool that solves a long standing problem that I have. I’ll have more to say about it shortly, but suffice to say, I’m real stoked about it.

Axle got a 0.30.2 bump. Bug fix and a refinement to the prompt compactor API. It feels pretty good now. I’ve been test driving axle-code on the new stealth model on open router, ox alpha, and I’m overall really happy with how rock solid Axle is. Occasionally, I wished that I can compile typescript down to binary (yes I know about scriptc) just to really get access to real multithreading, but as it stands everything is fast enough.

Speaking of ox alpha, rumor has that it’s a GLM or GLM-based fine tune. It definitely has some Claude-isms in the text it emits (and less so GPT-isms). After running it for a bit, I’ll pin it at around a below Sonnet, above Haiku level of intelligence. In my subjective measure, coding ability is be inversely proportional to the amount of frustration I feel while using it. This new model often runs itself into a quagmire and needs me or a better model to bail it out; this is the first time I’ve had to revert my git history while using an AI agent.

I’m making little progress on the eval work that I’ve been mulling on. The approach that I’m taking — a test harness vocabulary built on knobs on LLM as a judge – feels like a dead end. It all still feels like syntactic sugar and not a meaningful step forward. Part of it is that it’s really hard to know what correct means over a long horizon, the other is that even if I do, I don’t know if I could trust it without seeing it.

Posted Aug 23, 2026

This week: Axle 0.30, new docs; Sunnyday gains skills

Axle 0.30 is a big milestone in a few ways:

  1. It marks the 30th release since I’ve started publishing the library consistently since June of last year. I typically release when I need to integrate changes into my core projects, and minor releases are when I make significant additions or breaking changes. That’s quite a pace, if I may say so myself.
  2. More importantly, the compaction API has arrived at a good place. 0.30 solved a design conundrum I’ve been facing for a while, that is, what is the role of History — the dual objects of Messages and Turns — when it can be modified by an external actor. The answer is by removing Turn, the presentation layer, out of the Agent, and reduce the surface area of data that Agents work with. Now, the data model is coherent with a bit of conceptual tradeoff which we can bridge with built-in functions.

To celebrate, and to make sure I’m explaining the conceptual model well, the documentation site got a content revamp.


Sunnyday shipped skills. It’s something I’ve been wanting to do for a while, and having a concrete use case finally gave me a reason to built it.

The implementation went through a couple of cycles. The starting point was simple enough: it walks like a file and quacks like a file. But it soon became apparent that skills do indeed have a special status in an agent platform. I’ve settled on treating skills as files in the UI while handling them differently on the backend, which let’s me keep the UI and entry points simple. Though I doubt this is the last time I’ll have to think about it.

Posted Aug 16, 2026

This week: Sunnyday Sandbox resume, Assistant; next Axle CLI?

On the Sunnyday side:

  • Agent sandboxes per session are fully resumable now, up to a maximum of 30 days. This sets up each agent up to take follow up commands, which will open up new avenues of interacting and correcting remote agents
  • Assistant is now in beta. You can now prototype, create, and update Agents using the Assistant. This is something I’ve been mulling on for a while; as much as I think the UI is remarkably intuitive, the blank screen problem is still tricky to design around. This provides a way to turn sketches into infrastructure builds really quickly.

Because the work was based on Axle (we shipped an update for this around the internal ontology — 0.29.0), and most of the work took advantage of features in Axle recently, it was quick to come together. For me, this sets up some further thinking around conversations as the primary UI that I’ve been mulling about, and I believe will make some of the deeper cutting features, such as self-serve custom evals, possible. AI Agents are very good at pulling existing snippets together.

I’ve been thinking about the next iteration of axle-cli. I’ve been building axle-code for fun on the side, and it has been illuminating to see what features require more work (harness) and what works “out of the box”. Spoiler alert: frontier AI models are coding models by default. I am going to need a more sophisticated CLI soon: it’s going to look a bit like Cowork but with the conveniences of task runners. More to come!

Posted Aug 09, 2026
  • Older
© 2009–2026I speak to computers, telling them about dreams that humans dream.