AoAH Day 9: Adding a Bonsai terminal UI to Sortal / Dec 2025

After building a reasonably complete Sortal contacts manager, I decided to try to do a proper job of a terminal user interface. The first option for a modern UI is something that Yaron Minsky announced last week: bonsai_term, which also gives me a chance to dip into the OxCaml ecosystem with my agentic hacking!

Approach to using OxCaml

I did dip my toes into this a couple of weeks ago very quickly
I did dip my toes into this a couple of weeks ago very quickly

Switching to the OxCaml compiler is a relatively straightforward process by following the installation instructions. There is a custom oxcaml/opam-repository remote that contains all the bleeding edge packages required.

However, stepping outside of the Jane Street OxCaml package universe and interfacing with bleeding edge upstream OCaml packages does require a minor act of god to succeed. Luckily, David Allsopp is one such OCaml god that's been helping me work through a bunch of constraints to get a consistent package universe. This is a topic for a future note, but I just wanted to warn the casual reader that this aspect of OxCaml isn't quite ready for casual use yet: if you want to play with it, then stick with the Jane Street package set for now and you'll make fine progress.

Making Eio and Async play nicely

I however, thought I'd go in the deep end and make Bonsai work with Sortal, including the Romeo-and-Juliet-esque blending of Bonsai's use of Async with Sortal's Eio. This is complex because they each have their own run queues that don't compose cleanly -- one of the motivating problems we wrote about in early OCaml effects work back in 2017.

There have been attempts since then; Thomas Leonard built an async_eio bridge and even a lwt/async/eio chimera that could run all three in one process!

I gave this a quick shot, but there has been a lot of bitrot and code movement in the intervening years since these prototypes, especially as OxCaml has zoomed off with all of its extensions. So after my morning espresso I decided to instruct the coding agent to instead use JSON-RPC to communicate between a Sortal server (that it spawns) and a Bonsai terminal client. After all, we've got really good jsont codecs so JSON-RPC shouldn't be too difficult.

Setting up the agentic environment

The only environment that really worked here was giving the agent a monorepo with all the relevant Jane Street packages checked out with the OxCaml switch configured, and my eio OxCaml patched packages.

I then had to build the application in two phases:

  • first get a client/server JSON-RPC working with test cases to check that there is a useful information flow
  • then, with reference to the bonsai_term_examples build the user interface.

The agent went through a fairly complex TODO list to do the client/server split
The agent went through a fairly complex TODO list to do the client/server split

Results

There was some drama, but I did end up with a working terminal UI here, although perhaps one that requires a lot more iteration before I consider it sound. The most obvious result is that I have no idea how to code review this, as I need to spend more time learnings the basics of Bonsai and then get to terminal coding and then apply it my specific Sortal usecase. But, as the only user of this thing, the artefact that came out after an hour's agentic coding isn't completely bad.

I was only confident enough to push this to a branch and not main until I do more experimentation, but I did learn a few fun things.

How does a coding agent debug a UI?

One big drawback with coding agents is that they don't have a spatial sense of how UI elements can be laid out. There are workaround for browsers such as using headless Chrome, but often the results of a bad web layout just need repeated iteration.

However, Sadiq Jaffer pointed out to me that Claude Code also supports multimodal images as part of its prompts, which could be fed into it to debug the UI! It's as simple as dragging and dropping images into the Claude Code prompt.

For example, look at the two screenshots below that represent before and after triggering a bug:

Before I triggered a UI corruption bug
Before I triggered a UI corruption bug

After the bug, the contents are all over the place
After the bug, the contents are all over the place

Simply dragging these two images allowed the agent to figure out (visually) that there was a layout problem, and then apply it to a reasonable looking code fix that refactored the component layout logic.

The result of the before/after image prompting
The result of the before/after image prompting

It seems really worthwhile to build a proper Claude Skill that wraps this process up. I could imagine taking your favourite terminal recording library and hooking it up to an interactive Pty to automate this prompting process of UI layout.

Bonsai itself seems to have a lot of power

The other fun thing was experimenting with Bonsai terminal components, since there are some incredibly nice ones present. These range from TUI bar charts to full blown text editor components (with vi bindings!) to tree views.

Check out some of the example gifs in the main repo like the weighted tree one below.

So I think working through the constraint problems are well worth it in order to use so many cool components. The text editor especially is extremely usable out of the box as a replace for ed or nvi, which is incredible! There are also pager replacement components which remove the need for less/more, but with the same bindings.

Reflections

I call today a "negative but worthwhile result". The Bonsai-term architecture is too complex with the client-server split, although agentic coding made it possible to try it out really quickly. I think in the future it's worth investing in Eio and Async interoperability properly so that everything can run in one process, which dramatically simplifies a TUI. Thomas Leonard has already done the groundwork here, so it's a matter of putting time in the integration and keeping it working.

Bonsai itself shows how powerful TUIs can be, and in the Day 10 I'll look at yet another new TUI library just announced a few days ago!

# 9th Dec 2025agents, ai, aoah, llms, ocaml, oxcaml

Loading recent items...