<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Posts Tagged "ocaml" on Alex Leighton's Blog</title>
  <id>https://alexleighton.com/posts/tags/ocaml-tag-feed.xml</id>
  <link href="https://alexleighton.com/posts/tags/ocaml-tag-feed.xml" rel="self" />
  <link href="https://alexleighton.com/posts/tags/ocaml.html" />
  <updated>2026-03-11T13:36:28.055135011Z</updated>
  <author>
    <name>Alex Leighton</name>
    <uri>https://alexleighton.com/</uri>
  </author>
  <icon>https://alexleighton.com/static/icon-dino.png</icon>
  <logo>https://alexleighton.com/static/icon-dino.png</logo>
  
  <entry>
    <title>Use Your Preferred Technology</title>
    <id>https://alexleighton.com/posts/2026-03-11-use-your-preferred-technology.html</id>
    <link href="https://alexleighton.com/posts/2026-03-11-use-your-preferred-technology.html" />
    <published>2026-03-11T13:30:00Z</published>
    <updated>2026-03-11T13:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Re: Perhaps not Boring Technology after all</p><p>Published on <span title="2026-03-11T13:30:00Z">2026-03-11</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Re: Perhaps not Boring Technology after all</h3><p>Published on <span title="2026-03-11T13:30:00Z">2026-03-11</span><br>Tags: commentary, llm, ocaml, software-eng</p><blockquote>
<p><a href="https://simonwillison.net/2026/Mar/9/not-so-boring/"><strong>Simon Willison</strong> on 2026-03-09</a>:</p><p>Drop a coding agent into any existing codebase that uses libraries and tools that are too private or too new to feature in the training data and my experience is that it works just fine—the agent will consult enough of the existing examples to understand patterns, then iterate and test its own output to fill in the gaps.</p></blockquote>
<p>This is my experience as well. Two years ago (gpt-4o, sonnet-3.5), there was a noticeable difference in the "smoothness" of the OCaml code generated by agents, when compared to generated Python code. The Python code was simpler, more clever, more easily involved various libraries, while the OCaml code had complicated compound expressions, unfortunate nesting (all helper functions defined inside the current function via let-binding instead of deduplicating into the file or across files), and sometimes simply failed to be written in complex situations involving <a href="https://ocaml.org/docs/functors">Functors</a> or circular module definitions or using popular libraries (without handing the agent interface files).</p><p>...<br><a href="https://alexleighton.com/posts/2026-03-11-use-your-preferred-technology.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Fast Forward</title>
    <id>https://alexleighton.com/posts/2026-02-28-kbs-fast-forward.html</id>
    <link href="https://alexleighton.com/posts/2026-02-28-kbs-fast-forward.html" />
    <published>2026-03-01T03:45:00Z</published>
    <updated>2026-03-01T03:45:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Code generation on cruise control.</p><p>Published on <span title="2026-03-01T03:45:00Z">2026-03-01</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Code generation on cruise control.</h3><p>Published on <span title="2026-03-01T03:45:00Z">2026-03-01</span><br>Tags: article, llm, ocaml, python, software-eng, software-eng-auto</p><p>On today's episode: a lot of code. The previous work prepared the project codebase to guide agents in generating good quality code, which is what we did.</p>
<h2>Update, Resolve, Archive Commands</h2>
<p>After the <code>Kb_service</code> module was broken apart, the coding agent easily generated full verticals for update, resolve, and archive commands. The process I'm following:</p>
<ul>
<li>Work with the agent to peel off a chunk of functionality from <a href="https://github.com/alexleighton/knowledge-bases/blob/0eb55844acc47bb847f6d8063a9bc1b4c7689e4b/docs/product-requirements.md"><code>docs/product-requirements.md</code></a>.</li>
<li>Then write a <a href="https://github.com/alexleighton/knowledge-bases/blob/0eb55844acc47bb847f6d8063a9bc1b4c7689e4b/prompts/activities/implementation-plan.md"><code>prompts/activities/implementation-plan.md</code></a> for building the functionality.</li>
<li>After the code is generated, I review the code, as well as the agent (<a href="https://github.com/alexleighton/knowledge-bases/blob/0eb55844acc47bb847f6d8063a9bc1b4c7689e4b/prompts/activities/code-review.md"><code>prompts/activities/code-review.md</code></a>), and apply changes for all issues.</li>
</ul>
<p>Related commit: <a href="https://github.com/alexleighton/knowledge-bases/commit/0eb55844acc47bb847f6d8063a9bc1b4c7689e4b"><code>0eb5584</code></a> — feat: add update, resolve, and archive commands</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-28-kbs-fast-forward.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: List and Show</title>
    <id>https://alexleighton.com/posts/2026-02-25-kbs-list-and-show.html</id>
    <link href="https://alexleighton.com/posts/2026-02-25-kbs-list-and-show.html" />
    <published>2026-02-26T05:00:00Z</published>
    <updated>2026-02-26T05:00:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Code generation picks up speed.</p><p>Published on <span title="2026-02-26T05:00:00Z">2026-02-26</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Code generation picks up speed.</h3><p>Published on <span title="2026-02-26T05:00:00Z">2026-02-26</span><br>Tags: article, llm, ocaml, software-eng, software-eng-auto</p><p>Today's log consists mostly of code generation. We've laid enough foundation that new functionality is easily produced.</p>
<h2>List Functionality</h2>
<p>The functionality for <code>bs list</code> is well defined after the work for the <a href="../../../posts/2026-02-24-kbs-nesting-and-ideation.html">previous dev log</a>. I think the experiment of directing the agents from the requirements document rather than my own intuition of what to tackle was successful, though perhaps only at the scale of a project like Knowledge Bases. The coding agent was able to select a reasonable chunk of functionality to peel off and turn into an implementation plan, with a different agent generating the implementation.</p>
<h2>"Flaky" Tests</h2><p>...<br><a href="https://alexleighton.com/posts/2026-02-25-kbs-list-and-show.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Nesting and Ideation</title>
    <id>https://alexleighton.com/posts/2026-02-24-kbs-nesting-and-ideation.html</id>
    <link href="https://alexleighton.com/posts/2026-02-24-kbs-nesting-and-ideation.html" />
    <published>2026-02-24T14:30:00Z</published>
    <updated>2026-02-24T14:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>More scaffolding before future work.</p><p>Published on <span title="2026-02-24T14:30:00Z">2026-02-24</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>More scaffolding before future work.</h3><p>Published on <span title="2026-02-24T14:30:00Z">2026-02-24</span><br>Tags: article, llm, ocaml, software-eng, software-eng-auto</p><p>Today's changes follow on from the previous post's "next steps": nesting and ideation.</p>
<h2>Nesting</h2>
<p>I worked with the agent to find code with deep nesting, decide how to flatten it, and generalize the approach into suggestions for a <a href="https://github.com/alexleighton/knowledge-bases/blob/faf049e4a4fecaf8a04552e505a178ed29c2299f/docs/lib/principles.md#3-low-nesting-depth">nesting principle</a>. We then applied that principle across the codebase, and I think we were successful as the diff in <a href="https://github.com/alexleighton/knowledge-bases/commit/a05f2ea7eaa69805e88e395082dbfe57d29198d2">the refactor commit</a> is noticeably flatter.</p>
<blockquote>
<p><strong>4. Nesting Depth</strong></p>
<p>Keep expressions nested at most two or three levels deep. Deeply nested code
is hard to follow because the reader must hold every enclosing context in their
head at once. When nesting grows, treat it as a signal that the code should be
restructured.</p>
<p>Approaches for reducing nesting:</p>
<ul>
<li>Use monadic result operators (<code>let*</code>, <code>let+</code>). ...</li>
<li>Extract resource-management wrappers. ...</li>
<li>Consolidate error mapping into named functions. ...</li>
<li>Factor repeated control-flow shapes into helpers. ...</li>
</ul>
</blockquote><p>...<br><a href="https://alexleighton.com/posts/2026-02-24-kbs-nesting-and-ideation.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Adding Todos</title>
    <id>https://alexleighton.com/posts/2026-02-19-kbs-adding-todos.html</id>
    <link href="https://alexleighton.com/posts/2026-02-19-kbs-adding-todos.html" />
    <published>2026-02-20T03:45:00Z</published>
    <updated>2026-02-20T03:45:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>More guidance, and thoughts on automatic review.</p><p>Published on <span title="2026-02-20T03:45:00Z">2026-02-20</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>More guidance, and thoughts on automatic review.</h3><p>Published on <span title="2026-02-20T03:45:00Z">2026-02-20</span><br>Tags: article, code-review, llm, ocaml, software-eng, software-eng-auto</p><p>Today's changes build on the previous commit's unpacking of <code>Todo</code>, making a repository for <code>Todo</code>s, and hooking it up to the command line to provide <code>bs add todo ...</code>.</p>
<h2>More Guidance</h2>
<p>The implementation plan forgot to add a task for integration tests, which resulted in a <a href="https://github.com/alexleighton/knowledge-bases/blob/412117ae6940be69a6122a8a1d048f73ba0fa8de/docs/bin/principles.md?plain=1#L17-L40"><code>bin</code> principle</a> saying changes to <code>bin</code>, where we're only keeping command-line parsing and top-level orchestration, should always be accompanied by an integration test. I also had the agent put together an <a href="https://github.com/alexleighton/knowledge-bases/blob/412117ae6940be69a6122a8a1d048f73ba0fa8de/docs/test-integration/architecture.md">architecture document</a> guiding the structure of integration tests and their purpose.</p>
<p>In the hopes of keeping file sizes down, I added a line length principle to <a href="https://github.com/alexleighton/knowledge-bases/blob/412117ae6940be69a6122a8a1d048f73ba0fa8de/docs/bin/principles.md?plain=1#L52-L57"><code>bin</code></a> and <a href="https://github.com/alexleighton/knowledge-bases/blob/412117ae6940be69a6122a8a1d048f73ba0fa8de/docs/lib/principles.md?plain=1#L41-L46"><code>lib</code></a>. I'm not sure about these principles, because I think this can be automated as a lint. I will keep these in mind and improve the linting situation when I get another structural/syntactic principle that can be automated.</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-19-kbs-adding-todos.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Unpacking Todo</title>
    <id>https://alexleighton.com/posts/2026-02-18-kbs-unpacking-todo.html</id>
    <link href="https://alexleighton.com/posts/2026-02-18-kbs-unpacking-todo.html" />
    <published>2026-02-19T04:15:00Z</published>
    <updated>2026-02-19T04:15:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Guidance, prompts, and TDD.</p><p>Published on <span title="2026-02-19T04:15:00Z">2026-02-19</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Guidance, prompts, and TDD.</h3><p>Published on <span title="2026-02-19T04:15:00Z">2026-02-19</span><br>Tags: article, code-review, llm, ocaml, software-eng, software-eng-auto</p><p>Today's change to Knowledge Bases is addressing my unhappiness at the beginning of the month: <a href="../../../posts/2026-02-01-storage-for-knowledge-bases.html">"Data modeling"</a>. I've returned to the work of <a href="https://github.com/alexleighton/knowledge-bases/blob/d5fcf06481d710a6ecf35a0b874474e96d016dc5/lib/data/todo.ml#L19-L25">unpacking <code>Note</code> into <code>Todo</code></a>, to make it easier to control the TypeID prefix, and prepare for making a <code>Todo</code> repository.</p>
<h2>Revisiting Guidance Docs</h2>
<p>A handy thing about coding agents: they can make such a wide-ranging change with minimal effort (see the number of changed files in the commit). Additionally, the coding principles guidance doc paid for itself — agent code review noted the duplicated validation logic for title and content now in both <code>Note</code> and <code>Todo</code> and recommended deduplication. I redirected it to encapsulate the validation into new types, a favorite software engineering technique of mine (see <a href="../../../posts/2025-10-24-note-identifiers-and-tests.html">"Aside: Correct Construction"</a>), as well as <a href="https://github.com/alexleighton/knowledge-bases/blob/d5fcf06481d710a6ecf35a0b874474e96d016dc5/docs/lib/principles.md?plain=1#L15-L26">adjusted the guidance</a>.</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-18-kbs-unpacking-todo.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Going Automatic</title>
    <id>https://alexleighton.com/posts/2026-02-17-kbs-going-automatic.html</id>
    <link href="https://alexleighton.com/posts/2026-02-17-kbs-going-automatic.html" />
    <published>2026-02-18T05:30:00Z</published>
    <updated>2026-02-18T05:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Exploring a hands-off agent-driven workflow.</p><p>Published on <span title="2026-02-18T05:30:00Z">2026-02-18</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Exploring a hands-off agent-driven workflow.</h3><p>Published on <span title="2026-02-18T05:30:00Z">2026-02-18</span><br>Tags: article, git, llm, ocaml, software-eng, software-eng-auto</p><p>I've decided to use this project as a testbed for automatic development, to explore the kinds of techniques described in recent results [<a href="../../../posts/2026-02-12-new-software-engineering-modes.html">1</a>] [<a href="../../../posts/2026-02-14-more-software-engineering-research.html">2</a>], and to speed up development. I'll be making the vast majority of changes to the codebase via coding agents, exploring what controls are needed to stay hands-off yet maintain code quality.</p>
<h2>Short AGENTS.md</h2>
<p>I've played around with longer <code>AGENTS.md</code> and not seen much value. Agents would ignore pieces, and after a while it felt like simply a waste of context space. I'm keeping <a href="https://github.com/alexleighton/knowledge-bases/blob/223c4ece2550fb1196cec770d97762a66823fcda/AGENTS.md?plain=1"><code>AGENTS.md</code> short</a> this time around, "linking" to where more information can be retrieved, with the hope that brevity keeps the content important.</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-17-kbs-going-automatic.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Storage for Knowledge Bases</title>
    <id>https://alexleighton.com/posts/2026-02-01-storage-for-knowledge-bases.html</id>
    <link href="https://alexleighton.com/posts/2026-02-01-storage-for-knowledge-bases.html" />
    <published>2026-02-03T05:30:00Z</published>
    <updated>2026-02-03T05:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Progress, regrets, and motivation working with SQLite.</p><p>Published on <span title="2026-02-03T05:30:00Z">2026-02-03</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Progress, regrets, and motivation working with SQLite.</h3><p>Published on <span title="2026-02-03T05:30:00Z">2026-02-03</span><br>Tags: article, database, git, ocaml, software-eng</p><p>Today's update is brought to you by my lack of motivation 😆. I decided to work on building out a storage layer for Knowledge Bases objects, and then got burned by lack of interest.</p>
<p>Restating our storage requirements: we need notes, todos, etc to be persisted to disk in a way where git's diff will capably show edits, additions, and deletions, and which allows for easily querying these objects by identifier or by their relation to each other (we want to support parent-child, related-to, etc). To meet those requirements I intend to persist data in two ways. First, in an appropriately-sorted JSON or YAML file, to solve for the git-diff requirement. Second, in a <a href="https://en.wikipedia.org/wiki/SQLite">SQLite</a> database to make it easy to add/edit/delete/query. The program will mirror the SQLite database onto the JSON file unless it's determined to be out of date (i.e. when the git branch is changed), in which case we'll rebuild the database from the JSON file. For now I'm starting with the SQLite db, as that can be useful for purely local todo storage, and we'll bolt-on the ability to synchronize them over git later.</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-01-storage-for-knowledge-bases.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Year in Review: 2025</title>
    <id>https://alexleighton.com/posts/2025-12-31-year-in-review-2025.html</id>
    <link href="https://alexleighton.com/posts/2025-12-31-year-in-review-2025.html" />
    <published>2026-01-01T06:15:00Z</published>
    <updated>2026-01-01T06:15:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Building and blogging on this site the past year.</p><p>Published on <span title="2026-01-01T06:15:00Z">2026-01-01</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Building and blogging on this site the past year.</h3><p>Published on <span title="2026-01-01T06:15:00Z">2026-01-01</span><br>Tags: article, git, meta, ocaml, static-site</p><p>For 2024's New Year's resolution I decided I'd finally build and publish a personal website. That I'd write up my thoughts on the articles I was reading and post them instead of dumping them on friends 😆. In review, I'm happy to say I succeeded.</p>
<p>I wrote and published 164 blog posts over the past year, not counting this post. September was my most prolific month. I initialized the OCaml project that became the static site generator in late January, writing a <a href="../../../posts/2025-02-02-listening-to-the-resonance-between.html">test post</a> at the beginning of February to work out frontmatter parsing, markdown generation, and my custom templating language. The first "real" post came at the end of June, a few days after I bought the domain name.</p><p>...<br><a href="https://alexleighton.com/posts/2025-12-31-year-in-review-2025.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Changelog: Individual Image Pages</title>
    <id>https://alexleighton.com/posts/2025-12-01-changelog-individual-image-pages.html</id>
    <link href="https://alexleighton.com/posts/2025-12-01-changelog-individual-image-pages.html" />
    <published>2025-12-02T05:45:00Z</published>
    <updated>2025-12-02T05:45:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Images now link to a page featuring the image.</p><p>Published on <span title="2025-12-02T05:45:00Z">2025-12-02</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Images now link to a page featuring the image.</h3><p>Published on <span title="2025-12-02T05:45:00Z">2025-12-02</span><br>Tags: changelog, ocaml, static-site</p><p>I've created individual image pages. Now all images will link to their own image page, which makes it easier to see the alt text and variant images. For example, <a href="../../../img/img_o_01k80xvwggfn1s20cv98d75bee.html">this page for the picture of my dog on Rialto Beach</a>.</p>
<p>Implementing this was pretty straightforward. My static site generator makes a distinction between "normal" pages, ones where the <code>Page</code> structure is constructible solely from the contents of a file (HTML or Markdown body with all the necessary metadata in a <a href="https://jekyllrb.com/docs/front-matter/">YAML frontmatter</a>), and "synthetic" pages, where the <code>Page</code> structure is constructed in OCaml code inside the generator. These image pages are synthetic: the generator constructs one for each image original used on the site, generated alongside other synthetic pages like the tag pages or blog post archive pages.</p><p>...<br><a href="https://alexleighton.com/posts/2025-12-01-changelog-individual-image-pages.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>TypeIDs for Knowledge Bases</title>
    <id>https://alexleighton.com/posts/2025-11-29-typeids-for-knowledge-bases.html</id>
    <link href="https://alexleighton.com/posts/2025-11-29-typeids-for-knowledge-bases.html" />
    <published>2025-11-30T04:00:00Z</published>
    <updated>2025-11-30T04:00:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Data consistency and the primary identifier for content.</p><p>Published on <span title="2025-11-30T04:00:00Z">2025-11-30</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Data consistency and the primary identifier for content.</h3><p>Published on <span title="2025-11-30T04:00:00Z">2025-11-30</span><br>Tags: article, git, ocaml, software-eng</p><h2>TypeID</h2>
<p><a href="https://github.com/jetify-com/typeid">TypeID</a> is a micro-standard combining a number of well-thought-out decisions.</p>
<blockquote>
<p>TypeIDs are a modern, type-safe extension of UUIDv7. Inspired by a similar use of prefixes in Stripe's APIs.</p>
<p>TypeIDs are canonically encoded as lowercase strings consisting of three parts:</p>
<ol>
<li>A type prefix (at most 63 characters in all lowercase snake_case ASCII <code>[a-z_]</code>).</li>
<li>An underscore '_' separator</li>
<li>A 128-bit UUIDv7 encoded as a 26-character string using a modified base32 encoding.</li>
</ol>
</blockquote>
<pre><code class="language-plain">user_2x4y6z8a0b1c2d3e4f5g6h7j8k
└──┘ └────────────────────────┘
type    uuid suffix (base32)
</code></pre>
<p>Most identifiers, barring a specialized context, should include a "type" for the identifier. Interconnected computer systems are always passing around identifiers — for someone holding an identifier in their database it is really valuable to know who that identifier belongs to as well as what the identifier is for. For example in a financial institution handling investments, <code>md_quote_2x4y6z8a0b1c2d3e4f5g6h7j8k</code> can tell the receiver that they're holding a reference to a stock price quote, owned by the market data (<code>md</code>) system. Identifier types give engineers metadata, which can be especially useful when there's a bug in the system — no need to stress whether the integer identifier you're currently holding came from the <code>user</code> table or <code>news</code> table.</p><p>...<br><a href="https://alexleighton.com/posts/2025-11-29-typeids-for-knowledge-bases.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Notes and Todos</title>
    <id>https://alexleighton.com/posts/2025-10-31-notes-and-todos.html</id>
    <link href="https://alexleighton.com/posts/2025-10-31-notes-and-todos.html" />
    <published>2025-11-01T00:00:00Z</published>
    <updated>2025-11-01T00:00:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Small Knowledge Bases update.</p><p>Published on <span title="2025-11-01T00:00:00Z">2025-11-01</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Small Knowledge Bases update.</h3><p>Published on <span title="2025-11-01T00:00:00Z">2025-11-01</span><br>Tags: article, ocaml</p><p>Short update today — the definitions of <code>note</code> and <code>todo</code> types and their basic operations.</p>
<p>My intention is to represent arbitrary content as a <code>note</code>, and represent things to be done with <code>todo</code>. Notes are just an identifier, a title, and some content, while Todos also have a status and eventually relationships. I've left relationships between notes and todos for later. I'm not sure if I want them represented separately or as part of the structures.</p>
<h2>Note</h2>
<pre><code class="language-ocaml">(** Note type and operations.

    A note bundles an [Identifier.t] with a title and content.
*)

(** Abstract type of notes. *)
type t

(** [pp fmt t] prints the note [t] using the formatter [fmt]. *)
val pp : Format.formatter -&gt; t -&gt; unit

(** [show t] returns the same string that {!pp} would print. *)
val show : t -&gt; string

(** [make identifier title content] constructs a note after validating inputs.

    - [title] must be non-empty and at most 100 characters.
    - [content] must be non-empty and at most 10000 characters.

    @raise Invalid_argument if validation fails. *)
val make : Identifier.t -&gt; string -&gt; string -&gt; t

(** [id t] returns the note identifier. *)
val id : t -&gt; Identifier.t

(** [title t] returns the title of the note. *)
val title : t -&gt; string

(** [content t] returns the content of the note. *)
val content : t -&gt; string
</code></pre><p>...<br><a href="https://alexleighton.com/posts/2025-10-31-notes-and-todos.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Note Identifiers and Tests</title>
    <id>https://alexleighton.com/posts/2025-10-24-note-identifiers-and-tests.html</id>
    <link href="https://alexleighton.com/posts/2025-10-24-note-identifiers-and-tests.html" />
    <published>2025-10-25T00:45:00Z</published>
    <updated>2025-10-25T00:45:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Extended discussion on data representation.</p><p>Published on <span title="2025-10-25T00:45:00Z">2025-10-25</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Extended discussion on data representation.</h3><p>Published on <span title="2025-10-25T00:45:00Z">2025-10-25</span><br>Tags: article, llm, ocaml</p><p>My inclination, after getting the hello world project set up in place, is to start defining the major data representations of the domain we're working in. Since I'm documenting the process, and I want to discuss decisions, I'm going to start out pretty slowly — today's update is basically just a type for representing identifiers for "notes" (whatever it is we decide to call the basic content building block).</p>
<h2>Basic Definition and Data Access</h2>
<p>The plan here is to expose an opaque type <code>t</code> for our identifier values (<code>Identifier.t</code>), and be explicit and deliberate about what data is exposed to the rest of the program. I liked how Beads stuck with an identifier format that's human readable, and likely prevalent in LLM training data, so we'll use the same format for our identifier: <code>[a-z]{1,5}-[0-9]+</code> (e.g. <code>kbase-12345</code>). Decomposing that identifier gets us a <code>namespace</code> and <code>raw_id</code>.</p><p>...<br><a href="https://alexleighton.com/posts/2025-10-24-note-identifiers-and-tests.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Starting Knowledge Bases</title>
    <id>https://alexleighton.com/posts/2025-10-22-starting-knowledge-bases.html</id>
    <link href="https://alexleighton.com/posts/2025-10-22-starting-knowledge-bases.html" />
    <published>2025-10-22T13:30:00Z</published>
    <updated>2025-10-22T13:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Writing a coding agent tool in OCaml.</p><p>Published on <span title="2025-10-22T13:30:00Z">2025-10-22</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Writing a coding agent tool in OCaml.</h3><p>Published on <span title="2025-10-22T13:30:00Z">2025-10-22</span><br>Tags: article, git, llm, ocaml</p><p>A couple days ago, <a href="https://en.wikipedia.org/wiki/Steve_Yegge">Steve Yegge</a> <a href="https://steve-yegge.medium.com/beads-for-blobfish-80c7a2977ffa">wrote about a coding agent tool</a> he's been developing called <a href="https://github.com/steveyegge/beads">Beads</a>.</p>
<blockquote>
<p>Beads is a lightweight memory system for coding agents, using a graph-based issue tracker. Four kinds of dependencies work to chain your issues together like beads, making them easy for agents to follow for long distances, and reliably perform complex task streams in the right order.</p>
</blockquote>
<p>I haven't had an opportunity to see if it works well or not, but the feature set seems straightforward to implement and I've been looking for a project to work on which will involve OCaml and publishing to opam. I'll be documenting the development process here 😁.</p><p>...<br><a href="https://alexleighton.com/posts/2025-10-22-starting-knowledge-bases.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Randomart</title>
    <id>https://alexleighton.com/posts/2025-09-05-randomart.html</id>
    <link href="https://alexleighton.com/posts/2025-09-05-randomart.html" />
    <published>2025-09-06T05:15:00Z</published>
    <updated>2025-09-06T05:15:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>SSH key visualization.</p><p>Published on <span title="2025-09-06T05:15:00Z">2025-09-06</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>SSH key visualization.</h3><p>Published on <span title="2025-09-06T05:15:00Z">2025-09-06</span><br>Tags: article, ocaml, security, software-eng</p><p>When using <a href="https://en.wikipedia.org/wiki/OpenSSH">OpenSSH</a>, you may see ASCII art from time to time, like:</p>
<pre><code>+--[ED25519 256]--+
|                 |
|     .           |
|      o          |
|     o o o  .    |
|     .B S oo     |
|     =+^ =...    |
|    oo#o@.o.     |
|    E+.&amp;.=o      |
|    ooo.X=.      |
+----[SHA256]-----+
</code></pre>
<p>This is output<sup><a href="#fn-1" id="ref-1-fn-1" role="doc-noteref" class="fn-label">[1]</a></sup> of the randomart SSH Key visualization algorithm, intended to leverage the user's visual pattern matching to quickly recognize (or not) a remote host key. It's known as the <a href="https://www.jfurness.uk/the-drunken-bishop-algorithm/">Drunken Bishop's algorithm</a>, contributed to the OpenSSH codebase by <a href="https://undeadly.org/cgi?action=article&amp;sid=20080615022750">Alexander von Gernler in 2008</a>.</p>
<blockquote>
<p><a href="https://marc.info/?l=openbsd-cvs&amp;m=121321826818823&amp;w=2"><strong>Alexander von Gernler</strong> on 2008-06-11</a>:</p><p>Introduc[ing] SSH Fingerprint ASCII Visualization, a technique inspired by the graphical hash visualization schemes known as "random art", and by Dan Kaminsky's musings on the subject during a BlackOp talk at the 23C3 in Berlin.</p>
<p>Scientific publication (original paper): "Hash Visualization: a New Technique to improve Real-World Security", Perrig A. and Song D., 1999, International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)</p></blockquote><p>...<br><a href="https://alexleighton.com/posts/2025-09-05-randomart.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Re: Your MCP Doesn’t Need 30 Tools: It Needs Code</title>
    <id>https://alexleighton.com/posts/2025-08-18-re-your-mcp-doesnt-need-30-tools-it-needs-code.html</id>
    <link href="https://alexleighton.com/posts/2025-08-18-re-your-mcp-doesnt-need-30-tools-it-needs-code.html" />
    <published>2025-08-18T20:58:17Z</published>
    <updated>2025-08-18T20:58:17Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Thoughts related to Armin's post.</p><p>Published on <span title="2025-08-18T20:58:17Z">2025-08-18</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Thoughts related to Armin's post.</h3><p>Published on <span title="2025-08-18T20:58:17Z">2025-08-18</span><br>Tags: commentary, llm, ocaml, plt, protocol, software-eng</p><blockquote>
<p><a href="https://lucumr.pocoo.org/2025/8/18/code-mcps/"><strong>Armin Ronacher</strong> on 2025-08-18</a>:</p><p>A general challenge with MCP today is that the more tools you have, the more you’re contributing to context rot. You’re also limited to rather low amounts of input. On the other hand, if you have an MCP that exposes a programming language, it also indirectly exposes a lot of functionality that it knows from its training.</p></blockquote>
<p>I've been thinking about how one could design a programming language, knowing that a language model would be used in the crafting of programs in said programming language. Models have trouble generating nested "language", e.g. outputting <a href="https://aider.chat/2024/08/14/code-in-json.html">code inside of JSON</a> (and failing to make the code syntactically correct), or as Armin documents their poor ability at using MCP (data and semantics embedded in JSON).</p><p>...<br><a href="https://alexleighton.com/posts/2025-08-18-re-your-mcp-doesnt-need-30-tools-it-needs-code.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Building Search for this Site</title>
    <id>https://alexleighton.com/posts/2025-08-09-building-search-for-this-site.html</id>
    <link href="https://alexleighton.com/posts/2025-08-09-building-search-for-this-site.html" />
    <published>2025-08-10T05:10:37Z</published>
    <updated>2025-08-10T05:10:37Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Search on a static site.</p><p>Published on <span title="2025-08-10T05:10:37Z">2025-08-10</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Search on a static site.</h3><p>Published on <span title="2025-08-10T05:10:37Z">2025-08-10</span><br>Tags: article, java, javascript, ocaml, static-site</p><p>I like the idea of having search for my blog, to help readers find anything related to a specific topic, or something they'd read in the past. How do I make something as dynamic as search, but statically generated?</p>
<h2>Requirements</h2>
<ul>
<li><strong>The solution has to be small</strong> — part of my purpose in statically generating the site is to make it fast to download, fast to view. Whatever is chosen needs to maintain that vision.</li>
<li><strong>The solution can't introduce too many dependencies</strong> — I really like OCaml as a language, and I used building my personal site as an excuse to work in it. Introducing non-OCaml dependencies has to be done with care, as I don't want to maintain a Rube Goldberg machine for my website.</li>
</ul><p>...<br><a href="https://alexleighton.com/posts/2025-08-09-building-search-for-this-site.html">Read the full post →</a></p>]]></content>
  </entry>
  
</feed>
