termaid
I saw this post from Simon Willison about running mermaid.rs — a utility from Grok Build, xAI's newly open-sourced coding agent harness, as WebAssembly in the browser. The output looks really nice, the Rust code is very self-contained, and I thought it would be interesting to use an agent to convert it to OCaml. The outcome is termaid, a minimal-dependency OCaml library for rendering Mermaid diagrams.
Example
The package contains a minimal binary that renders a diagram from stdin, alongside the library itself, for use in other programs. Supported diagram types: flowchart/graph, stateDiagram, classDiagram, erDiagram, and sequenceDiagram.
$ termaid <<'EOF'
sequenceDiagram
A->>B: ping
B-->>A: pong
EOF
┌───┐ ┌───┐
│ A │ │ B │
└─┬─┘ └─┬─┘
│ │
│ ping │
├─────▶│
│ │
│ pong │
│◄╌╌╌╌╌┤
│ │
┌─┴─┐ ┌─┴─┐
│ A │ │ B │
└───┘ └───┘
Transformation Process
I focused on porting the Rust code to OCaml by settling on the top-level interface, then porting the unit tests, and creating a suite of "integration" tests matching my output against canonical output, before attempting to port the implementation. To generate those canonical outputs, I made a minimal Rust binary wrapper around the source mermaid.rs called the oracle. The gen_golden.sh script runs diagrams through the oracle to generate test cases into test/golden.
With the tests in place, the implementation followed. The agent had no trouble sticking to the plan. It chose to build the parser one diagram type at a time, running the tests after each one. In total it cost ~$50 of API usage to complete the port.
Opam Submission
I ran into a sharp edge of dune-release while preparing the PR submission to Opam. The oracle is ~500 lines of Rust code and Cargo configuration — probably a little rude to bundle into the source tarball everyone using the package has to download. Turns out dune-release doesn't let you configure tarball exclusions. I adjusted the release tarball to not include the oracle before dune-release uploaded it, but I think I'll try to submit a PR to make exclusions configurable.
Next Steps
I may cook up a performance test to see how the OCaml code compares with the Rust code, and pick off any low-hanging fruit.