<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <!-- Source: https://www.dolthub.com/blog/rss.xml -->
  <channel>
    <title>DoltHub Blog - Latest Posts</title>
    <description>Blog for DoltHub, a website hosting databases made with Dolt, an open-source version-controlled SQL database with Git-like semantics.</description>
    <link>https://siftrss.com/f/Kkmm5PG8lw</link>
    <language>en-us</language>
    <lastBuildDate>Fri, 05 Jun 2026 20:49:46 GMT</lastBuildDate>
    <atom:link href="https://siftrss.com/f/Kkmm5PG8lw" rel="self" type="application/rss+xml"/>
    <item>
      <title>Announcing Dumbo Garbage Collection</title>
      <link>https://dolthub.com/blog/2026-06-02-dumbodb-gc/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-06-02-dumbodb-gc/</guid>
      <description>MongoDB and Git had a baby, and it's named Dumbo. The latest release has garbage collection!</description>
      <pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/dumbo-logo.png/c02da7b39168585c4dc1adf3ebf6ffe77404dd9b8fc5a35f6dc765bb9dea9e16.webp" alt="DumboDB Logo"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dolthub/dumbodb"&gt;DumboDB&lt;/a&gt; is a document database inspired by &lt;a href="https://github.com/mongodb/mongo"&gt;MongoDB&lt;/a&gt;, built on top of &lt;a href="https://github.com/dolthub/dolt"&gt;Dolt’s storage&lt;/a&gt;. DumboDB combines the flexibility of a document database with the power of Git-like version control, allowing you to track changes, branch, and merge your data with ease.&lt;/p&gt;
&lt;p&gt;It’s early days for DumboDB, but thanks to leveraging Dolt’s underlying architecture, we’re able to rapidly iterate and add new features. In &lt;a href="https://github.com/dolthub/dumbodb/releases/tag/v0.1.3"&gt;release 0.1.3&lt;/a&gt;, we’re excited to announce the addition of garbage collection (GC) to DumboDB!&lt;/p&gt;
&lt;h2 id="what-is-garbage-collection"&gt;What is Garbage Collection?&lt;a class="anchor-link" aria-label="Link to heading" href="#what-is-garbage-collection"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In many databases, as you update your data on disk, old versions of your data will accumulate over time. Cleaning up this data goes by many names. In PostgreSQL, it’s called &lt;a href="https://www.postgresql.org/docs/current/sql-vacuum.html"&gt;VACUUM&lt;/a&gt;. In MySQL, it’s called &lt;a href="https://dev.mysql.com/doc/refman/9.7/en/innodb-purge-configuration.html"&gt;purging&lt;/a&gt;. In Dolt, it’s called &lt;a href="https://www.dolthub.com/docs/sql-reference/server/garbage-collection/"&gt;garbage collection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In traditional databases, it makes sense that garbage would exist. When you update a row in a table, the old version of that row is still on disk until the database decides to clean it up.&lt;/p&gt;
&lt;p&gt;Dolt and Dumbo are version-controlled databases, so it’s reasonable to assume we store every version of the data forever. Unfortunately, it’s not that simple. Dolt and Dumbo keep track of all &lt;em&gt;committed&lt;/em&gt; data, specifically data that has been committed to the database and is part of the commit history.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/how-garbage-is-created.png/c719463f830464444cce6a285c5a4125cc88710480ad62d28a3108f60a25739b.webp" alt="how garbage is created"&gt;&lt;/p&gt;
&lt;p&gt;In scenarios where you insert or update many documents, there are intermediate versions of the data that are not committed to the commit history. These intermediate versions take up disk space and may not be necessary to keep around indefinitely. This is where garbage collection comes in.&lt;/p&gt;
&lt;h2 id="how-does-dumbos-garbage-collection-work"&gt;How Does Dumbo’s Garbage Collection Work?&lt;a class="anchor-link" aria-label="Link to heading" href="#how-does-dumbos-garbage-collection-work"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The short answer is that it’s just like &lt;a href="https://www.dolthub.com/blog/2025-03-21-session-aware-gc-technical-details/"&gt;Dolt’s Session Aware GC&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I won’t go into that level of detail here, but at a high level, every chunk of data in a Dolt (and Dumbo) database must be reachable from the commit history of all branches. We build a list of all chunks in the database, then walk the commit history to find all chunks that are reachable from commits. Any chunks that are not reachable from the commit history are considered garbage and can be safely deleted.&lt;/p&gt;
&lt;p&gt;This becomes more complicated when you consider that there may be active sessions in the database that are still using some of the intermediate versions of the data. We don’t want to delete any chunks that are still being used by active sessions, so we need to keep track of those as well.&lt;/p&gt;
&lt;p&gt;Dolt’s GC process takes this into account by keeping track of the active sessions and ensuring that any chunks that are still being used by those sessions are not deleted during the GC process. This allows us to safely clean up any garbage data without affecting any active operations in the database.&lt;/p&gt;
&lt;p&gt;DumboDB uses the same storage engine as Dolt, so we were able to leverage the existing GC implementation in Dolt to add GC support to DumboDB. This means that DumboDB can now automatically clean up any garbage data that may be taking up space on disk, without affecting any active sessions or operations in the database.&lt;/p&gt;
&lt;h2 id="using-garbage-collection-in-dumbodb"&gt;Using Garbage Collection in DumboDB&lt;a class="anchor-link" aria-label="Link to heading" href="#using-garbage-collection-in-dumbodb"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Garbage collection has been added in the &lt;a href="https://github.com/dolthub/dumbodb/releases/tag/v0.1.3"&gt;latest release&lt;/a&gt; of DumboDB.&lt;/p&gt;
&lt;p&gt;Be sure that the &lt;code&gt;mongo&lt;/code&gt; driver is installed for Python:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;pip&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; pymongo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then create a script that creates a bunch of garbage chunks. Put this text in a file called &lt;code&gt;make_garbage.py&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="python"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; random&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; secrets&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; pymongo &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; MongoClient&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;client &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; MongoClient(&lt;/span&gt;&lt;span&gt;"mongodb://127.0.0.1:27017"&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;db &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; client[&lt;/span&gt;&lt;span&gt;"gcdemo"&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;coll &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; db[&lt;/span&gt;&lt;span&gt;"items"&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    docs &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    for&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        docs.append({&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            "_id"&lt;/span&gt;&lt;span&gt;:   &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;"b&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;i&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;secrets.token_hex(&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            "name"&lt;/span&gt;&lt;span&gt;:  &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;"user-&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;secrets.token_hex(&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            "email"&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;secrets.token_hex(&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;@example.com"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            "age"&lt;/span&gt;&lt;span&gt;:   random.randint(&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            "score"&lt;/span&gt;&lt;span&gt;: random.random() &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; 100&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    coll.insert_many(docs)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    db.command({&lt;/span&gt;&lt;span&gt;"dumboCommit"&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;"message"&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;"batch &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;"author"&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;"gcdemo &amp;#x3C;gcdemo@example.com&gt;"&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;"batch &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;b &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; 1}&lt;/span&gt;&lt;span&gt;/50 committed"&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;client.close()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This script creates 50 commits, each with 100 new random documents. As a result, it creates a lot of intermediate data versions that are not committed to the commit history and are therefore considered garbage. Run the script:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sh"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; python&lt;/span&gt;&lt;span&gt; make_garbage.py&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;batch&lt;/span&gt;&lt;span&gt; 1/50&lt;/span&gt;&lt;span&gt; committed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;batch&lt;/span&gt;&lt;span&gt; 2/50&lt;/span&gt;&lt;span&gt; committed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;[... snip ...]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;batch&lt;/span&gt;&lt;span&gt; 49/50&lt;/span&gt;&lt;span&gt; committed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;batch&lt;/span&gt;&lt;span&gt; 50/50&lt;/span&gt;&lt;span&gt; committed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In another file, &lt;code&gt;run_gc.py&lt;/code&gt;, add the following code to trigger the GC process:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="python"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; pprint &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; pprint&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; pymongo &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; MongoClient&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;client &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; MongoClient(&lt;/span&gt;&lt;span&gt;"mongodb://127.0.0.1:27017"&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;res &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; client[&lt;/span&gt;&lt;span&gt;"gcdemo"&lt;/span&gt;&lt;span&gt;].command({&lt;/span&gt;&lt;span&gt;"dumboGC"&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;pprint(&lt;/span&gt;&lt;span&gt;dict&lt;/span&gt;&lt;span&gt;(res))&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;client.close()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you run this script, it will trigger the GC process in DumboDB and print out the results:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sh"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; python&lt;/span&gt;&lt;span&gt; run_gc.py&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;'chunksAfter'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 6608.0,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 'chunksBefore'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 7119.0,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 'db'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 'gcdemo',&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 'durationMs'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 163.0,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 'mode'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 'default',&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 'ok'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 1.0,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 'sizeAfter'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 5929327.0,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 'sizeBefore'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; 7452156.0&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The command returns statistics about the number of chunks before and after the GC process, the database size before and after, and how long the GC process took to run.&lt;/p&gt;
&lt;h2 id="comparison-to-dolt"&gt;Comparison to Dolt&lt;a class="anchor-link" aria-label="Link to heading" href="#comparison-to-dolt"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of the reasons I wanted to add GC to DumboDB is to see how Dumbo’s storage usage compares to Dolt’s. I added &lt;a href="https://github.com/dolthub/dumbodb-parity-testing/pull/14"&gt;parity tests&lt;/a&gt; to generate equivalent data in both Dolt and Dumbo, then ran GC on both databases to see how much space was used for each.&lt;/p&gt;
&lt;p&gt;The results aren’t fantastic, I’m not gonna lie. There is clearly something amiss. When storing about 1M documents, Dumbo is using about 6x the amount of space after GC compared to Dolt.&lt;/p&gt;
&lt;p&gt;It’s not clear yet if this is the result of a bug in how Dumbo stores data or if we are being too conservative when we garbage collect. As we &lt;a href="https://www.dolthub.com/blog/2026-05-19-dumbodb-01-performance/"&gt;discussed in a previous post&lt;/a&gt;, this kind of side-by-side comparison is one of the main ways we can verify that a vibe-coded product such as Dumbo is working correctly. My gut says that we should have collected more data in our example and we are being too conservative. We will be investigating this issue in the coming weeks and will share our findings in a future blog post.&lt;/p&gt;
&lt;h2 id="whats-next"&gt;What’s Next?&lt;a class="anchor-link" aria-label="Link to heading" href="#whats-next"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sorting out the storage discrepancy just mentioned is the top priority. After we sort that out, automatic garbage collection is the next step. Similar to Dolt, when the server determines that there is a reasonable amount of garbage data that can be cleaned up, it will automatically trigger the GC process. This will help ensure that your DumboDB instance stays clean and efficient without requiring manual intervention.&lt;/p&gt;
&lt;p&gt;Want to learn more about Dolt and Dumbo? Hop on our &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;Discord&lt;/a&gt; to ask questions and nerd out about version-controlled databases!&lt;/p&gt;</content:encoded>
      <dc:creator>Neil Macneale</dc:creator>
      <category>dumbo</category>
      <category>feature release</category>
    </item>
    <item>
      <title>Evolving with Beads</title>
      <link>https://dolthub.com/blog/2026-05-29-evolving-with-beads/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-05-29-evolving-with-beads/</guid>
      <description>A guide to evolving your Beads setup from classic single-agent mode to server and shared-server modes for multi-agent workflows, with a bonus look at the global Beads database.</description>
      <pubDate>Fri, 29 May 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;&lt;a href="https://github.com/gastownhall/beads"&gt;Beads&lt;/a&gt; is a tool for extending the memory of coding agents, such as &lt;a href="https://claude.com/product/claude-code"&gt;Claude Code&lt;/a&gt;, allowing them to manage tasks (i.e. beads) themselves. It was originally built by &lt;a href="https://steve-yegge.medium.com/introducing-beads-a-coding-agent-memory-system-637d7d92514a"&gt;Steve Yegge&lt;/a&gt; and is now part of &lt;a href="https://gastownhall.ai/"&gt;Gaslandia&lt;/a&gt;, which comprises of Beads, Gastown, Gas City, and Wasteland. Beads is backed by Dolt, and version &lt;a href="https://github.com/gastownhall/beads/releases/tag/v1.0.5"&gt;v1.0.5&lt;/a&gt; is available now.&lt;/p&gt;
&lt;p&gt;In today’s blog, I’ll cover a common question we’ve seen from Beads users about how to evolve with the tool: “I’ve been using Beads classic and want to know how to move to server mode, when should I do that, and how do I do that?” I’ll answer this by migrating from the most simple, “classic”, single-agent mode to the server and shared-server modes that better support multi-agent workflows.&lt;/p&gt;
&lt;h1 id="beads-classic"&gt;Beads Classic&lt;a class="anchor-link" aria-label="Link to heading" href="#beads-classic"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Most Beads users use the “classic” mode of Beads, which provides a coding-agent persistent memory and an interface for self-managing it. In this example, I have the latest Dolt installed, &lt;a href="https://github.com/dolthub/dolt/releases/tag/v2.0.8"&gt;v2.0.8&lt;/a&gt;, and will make a new Git project where my coding agent will work.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  repros&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;dolt&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;dolt&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt; 2.0.8&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  repros&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; mkdir&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  repros&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; cd&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; echo&lt;/span&gt;&lt;span&gt; "# evolving_demo"&lt;/span&gt;&lt;span&gt; &gt;&gt;&lt;/span&gt;&lt;span&gt; README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Initialized&lt;/span&gt;&lt;span&gt; empty&lt;/span&gt;&lt;span&gt; Git&lt;/span&gt;&lt;span&gt; repository&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.git/&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; add&lt;/span&gt;&lt;span&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; commit&lt;/span&gt;&lt;span&gt; -m&lt;/span&gt;&lt;span&gt; 'README.md'&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;[main (root&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;commit) 9dffb6e] README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; file&lt;/span&gt;&lt;span&gt; changed,&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; insertion&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;span&gt; 100644&lt;/span&gt;&lt;span&gt; README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; remote&lt;/span&gt;&lt;span&gt; add&lt;/span&gt;&lt;span&gt; origin&lt;/span&gt;&lt;span&gt; https://github.com/coffeegoddd/evolving_demo.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; push&lt;/span&gt;&lt;span&gt; origin&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Enumerating&lt;/span&gt;&lt;span&gt; objects:&lt;/span&gt;&lt;span&gt; 3,&lt;/span&gt;&lt;span&gt; done.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Counting&lt;/span&gt;&lt;span&gt; objects:&lt;/span&gt;&lt;span&gt; 100%&lt;/span&gt;&lt;span&gt; (3/3), done.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Writing&lt;/span&gt;&lt;span&gt; objects:&lt;/span&gt;&lt;span&gt; 100%&lt;/span&gt;&lt;span&gt; (3/3), 250 bytes &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; 250.00&lt;/span&gt;&lt;span&gt; KiB/s,&lt;/span&gt;&lt;span&gt; done.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total&lt;/span&gt;&lt;span&gt; 3&lt;/span&gt;&lt;span&gt; (delta &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;), reused 0 (&lt;/span&gt;&lt;span&gt;delta&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;), pack-reused 0 (&lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;To&lt;/span&gt;&lt;span&gt; https://github.com/coffeegoddd/evolving_demo.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; [new &lt;/span&gt;&lt;span&gt;branch]&lt;/span&gt;&lt;span&gt;      main&lt;/span&gt;&lt;span&gt; -&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’ve initialized my git project and pushed it to GitHub as well. Next, I also have the latest version of Beads installed, and I can run &lt;code&gt;bd init&lt;/code&gt; to initialize the project with everything my agent will need to use Beads successfully.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt; 1.0.5&lt;/span&gt;&lt;span&gt; (dev: &lt;/span&gt;&lt;span&gt;801fb95d1767&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Configured&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;span&gt; remote:&lt;/span&gt;&lt;span&gt; origin&lt;/span&gt;&lt;span&gt; →&lt;/span&gt;&lt;span&gt; git+https://github.com/coffeegoddd/evolving_demo.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Repository&lt;/span&gt;&lt;span&gt; ID:&lt;/span&gt;&lt;span&gt; 76062c1e&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Clone&lt;/span&gt;&lt;span&gt; ID:&lt;/span&gt;&lt;span&gt; 642acc6d98a2785e&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;▶&lt;/span&gt;&lt;span&gt; Already&lt;/span&gt;&lt;span&gt; configured&lt;/span&gt;&lt;span&gt; as:&lt;/span&gt;&lt;span&gt; maintainer&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Change&lt;/span&gt;&lt;span&gt; role?&lt;/span&gt;&lt;span&gt; [y/N]: n&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;▶&lt;/span&gt;&lt;span&gt; Auto-export&lt;/span&gt;&lt;span&gt; can&lt;/span&gt;&lt;span&gt; keep&lt;/span&gt;&lt;span&gt; .beads/issues.jsonl&lt;/span&gt;&lt;span&gt; up&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; date&lt;/span&gt;&lt;span&gt; after&lt;/span&gt;&lt;span&gt; write&lt;/span&gt;&lt;span&gt; commands.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  This&lt;/span&gt;&lt;span&gt; optional&lt;/span&gt;&lt;span&gt; JSONL&lt;/span&gt;&lt;span&gt; export&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; useful&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; viewers&lt;/span&gt;&lt;span&gt; (bv), interchange, and issue-level migration.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Dolt&lt;/span&gt;&lt;span&gt; remotes/backups&lt;/span&gt;&lt;span&gt; handle&lt;/span&gt;&lt;span&gt; cross-machine&lt;/span&gt;&lt;span&gt; sync&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; backup.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Enable&lt;/span&gt;&lt;span&gt; auto-export?&lt;/span&gt;&lt;span&gt; [y/N]: n&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Auto-export&lt;/span&gt;&lt;span&gt; disabled&lt;/span&gt;&lt;span&gt; (enable &lt;/span&gt;&lt;span&gt;later&lt;/span&gt;&lt;span&gt; with:&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; export.auto&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Hooks&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;span&gt; to:&lt;/span&gt;&lt;span&gt; .beads/hooks/&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; AGENTS.md&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Registered&lt;/span&gt;&lt;span&gt; SessionStart&lt;/span&gt;&lt;span&gt; hook&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; CLAUDE.md&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  File:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/CLAUDE.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; additional&lt;/span&gt;&lt;span&gt; configuration&lt;/span&gt;&lt;span&gt; needed!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Settings:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.claude/settings.json&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; changes&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; take&lt;/span&gt;&lt;span&gt; effect.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; skill...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; skill&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Skill:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.agents/skills/beads/SKILL.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; native&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; native&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  File:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/AGENTS.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; if&lt;/span&gt;&lt;span&gt; it&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; already&lt;/span&gt;&lt;span&gt; running.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Committed&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; files&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;⚠&lt;/span&gt;&lt;span&gt; Git&lt;/span&gt;&lt;span&gt; upstream&lt;/span&gt;&lt;span&gt; not&lt;/span&gt;&lt;span&gt; configured&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  For&lt;/span&gt;&lt;span&gt; sync&lt;/span&gt;&lt;span&gt; workflows,&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; your&lt;/span&gt;&lt;span&gt; upstream&lt;/span&gt;&lt;span&gt; with:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  git&lt;/span&gt;&lt;span&gt; remote&lt;/span&gt;&lt;span&gt; add&lt;/span&gt;&lt;span&gt; upstream&lt;/span&gt;&lt;span&gt; &amp;#x3C;&lt;/span&gt;&lt;span&gt;repo-ur&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; initialized&lt;/span&gt;&lt;span&gt; successfully!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Backend:&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Mode:&lt;/span&gt;&lt;span&gt; embedded&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Database:&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issue&lt;/span&gt;&lt;span&gt; prefix:&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issues&lt;/span&gt;&lt;span&gt; will&lt;/span&gt;&lt;span&gt; be&lt;/span&gt;&lt;span&gt; named:&lt;/span&gt;&lt;span&gt; evolving_demo-&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;h&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; (e.g., &lt;/span&gt;&lt;span&gt;evolving_demo-a3f2dd&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Run&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; quickstart&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; get&lt;/span&gt;&lt;span&gt; started.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Importantly, always choose the role ‘maintainer’ and choose ‘no’ for auto-export.&lt;/p&gt;
&lt;p&gt;Contributor mode is outside the scope of this blog, and auto-export is a legacy feature.&lt;/p&gt;
&lt;p&gt;After Beads is initialized in my repo, I can create a sample bead to test it out before my agent takes over.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; "my first bead"&lt;/span&gt;&lt;span&gt; -t&lt;/span&gt;&lt;span&gt; task&lt;/span&gt;&lt;span&gt; -p&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; issue:&lt;/span&gt;&lt;span&gt; evolving_demo-0v4&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; my&lt;/span&gt;&lt;span&gt; first&lt;/span&gt;&lt;span&gt; bead&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Priority:&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Status:&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;💡&lt;/span&gt;&lt;span&gt; Tip:&lt;/span&gt;&lt;span&gt; Install&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; plugin&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; automatic&lt;/span&gt;&lt;span&gt; workflow&lt;/span&gt;&lt;span&gt; context,&lt;/span&gt;&lt;span&gt; or&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; 'bd setup claude'&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; CLI-only&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-0v4&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; my&lt;/span&gt;&lt;span&gt; first&lt;/span&gt;&lt;span&gt; bead&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, I’ll delete this sample issue and turn things over to Claude to start working.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt; evolving_demo-0v4&lt;/span&gt;&lt;span&gt; --force&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Deleted&lt;/span&gt;&lt;span&gt; evolving_demo-0v4&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Removed&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; dependency&lt;/span&gt;&lt;span&gt; link&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Updated&lt;/span&gt;&lt;span&gt; text&lt;/span&gt;&lt;span&gt; references&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; issue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Starting my agent in the repo brings it up with all the context it needs to use Beads on its own, so I can just talk to the agent normally, and it will get to work.&lt;/p&gt;
&lt;p&gt;In this example I’ve asked it to write me a news fetching application, and when Claude starts working, I can see what it’s doing in the &lt;code&gt;bd list&lt;/code&gt; output.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-2wo&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; Unit&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt; RSS&lt;/span&gt;&lt;span&gt; client&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;span&gt; httptest&lt;/span&gt;&lt;span&gt; fixture&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-gby&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; Implement&lt;/span&gt;&lt;span&gt; output&lt;/span&gt;&lt;span&gt; formatters&lt;/span&gt;&lt;span&gt; (text &lt;/span&gt;&lt;span&gt;and&lt;/span&gt;&lt;span&gt; JSON&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;◐&lt;/span&gt;&lt;span&gt; evolving_demo-mlq&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; Scaffold&lt;/span&gt;&lt;span&gt; Go&lt;/span&gt;&lt;span&gt; module&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; CLI&lt;/span&gt;&lt;span&gt; entry&lt;/span&gt;&lt;span&gt; point&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-p5d&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; Implement&lt;/span&gt;&lt;span&gt; Google&lt;/span&gt;&lt;span&gt; News&lt;/span&gt;&lt;span&gt; RSS&lt;/span&gt;&lt;span&gt; client&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-y7r&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; Wire&lt;/span&gt;&lt;span&gt; main.go:&lt;/span&gt;&lt;span&gt; client&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; formatter&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; error&lt;/span&gt;&lt;span&gt; handling&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-6ed&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P3&lt;/span&gt;&lt;span&gt; Write&lt;/span&gt;&lt;span&gt; README&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;span&gt; build&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; usage&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 6&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (5 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When Claude is done, it closes the beads it worked on, and my app is ready to use. But Claude did not know that it can push the beads of this repo up to GitHub too, just like it pushes code, so I let Claude know.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;●&lt;/span&gt;&lt;span&gt; Committed&lt;/span&gt;&lt;span&gt; as&lt;/span&gt;&lt;span&gt; 9ed3470.&lt;/span&gt;&lt;span&gt; Working&lt;/span&gt;&lt;span&gt; tree&lt;/span&gt;&lt;span&gt; clean,&lt;/span&gt;&lt;span&gt; only&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; gitignored&lt;/span&gt;&lt;span&gt; usnews&lt;/span&gt;&lt;span&gt; binary&lt;/span&gt;&lt;span&gt; remains&lt;/span&gt;&lt;span&gt; untracked.&lt;/span&gt;&lt;span&gt; All&lt;/span&gt;&lt;span&gt; 6&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; closed.&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  remote&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; push&lt;/span&gt;&lt;span&gt; to.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✻&lt;/span&gt;&lt;span&gt; Baked&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; 25s&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;❯&lt;/span&gt;&lt;span&gt; there&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt; remote,&lt;/span&gt;&lt;span&gt; try&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; push&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;●&lt;/span&gt;&lt;span&gt; Bash&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; push&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ⎿&lt;/span&gt;&lt;span&gt;  Pushing&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;span&gt; remote...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;     Push&lt;/span&gt;&lt;span&gt; complete.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;●&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; pushed.&lt;/span&gt;&lt;span&gt; Now&lt;/span&gt;&lt;span&gt; checking&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; remote.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It actually used to be the case that there was &lt;a href="https://www.dolthub.com/blog/2026-02-19-supporting-git-remotes-as-dolt-remotes/"&gt;nothing visible on GitHub&lt;/a&gt; when using it as a Dolt remote, but we recently added some visual cues to more easily tell that your Git repo has Dolt data.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/git-dolt-remotes-github-visual-1.png/6e8bb4e95424055d1453ec4afb9ada0430b69f499ee4e77f13756ff3ac47f5d4.webp" alt="GitHub Dolt Remote Visualization 1"&gt;&lt;/p&gt;
&lt;p&gt;Git Dolt remotes now also create and push to a branch &lt;code&gt;__dolt_remote_info__&lt;/code&gt;, and this branch will have a file updated on each &lt;code&gt;dolt push&lt;/code&gt; that tells you the ref Dolt is using and its &lt;code&gt;HEAD&lt;/code&gt; sha.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/git-dolt-remotes-github-visual-2.png/1c3874b2ff3c533caf3b5320ee647cd3a1b638ed0f3e49a382bcfe1d8669a418.webp" alt="GitHub Dolt Remote Visualization 2"&gt;&lt;/p&gt;
&lt;p&gt;This is the standard Beads Classic usage pattern and app development style. And the application Claude wrote works great.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;go&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 1.&lt;/span&gt;&lt;span&gt; U.S.,&lt;/span&gt;&lt;span&gt; Iran&lt;/span&gt;&lt;span&gt; nearing&lt;/span&gt;&lt;span&gt; deal&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; end&lt;/span&gt;&lt;span&gt; war&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; reopen&lt;/span&gt;&lt;span&gt; Strait&lt;/span&gt;&lt;span&gt; of&lt;/span&gt;&lt;span&gt; Hormuz&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; The&lt;/span&gt;&lt;span&gt; Washington&lt;/span&gt;&lt;span&gt; Post&lt;/span&gt;&lt;span&gt; (1h &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 2.&lt;/span&gt;&lt;span&gt; Judge&lt;/span&gt;&lt;span&gt; halts&lt;/span&gt;&lt;span&gt; Trump&lt;/span&gt;&lt;span&gt; ‘anti-weaponization’&lt;/span&gt;&lt;span&gt; fund&lt;/span&gt;&lt;span&gt; after&lt;/span&gt;&lt;span&gt; Jan.&lt;/span&gt;&lt;span&gt; 6&lt;/span&gt;&lt;span&gt; prosecutor&lt;/span&gt;&lt;span&gt; sues&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; NBC&lt;/span&gt;&lt;span&gt; News&lt;/span&gt;&lt;span&gt; (1h &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 3.&lt;/span&gt;&lt;span&gt; Former&lt;/span&gt;&lt;span&gt; AG&lt;/span&gt;&lt;span&gt; Pam&lt;/span&gt;&lt;span&gt; Bondi&lt;/span&gt;&lt;span&gt; testifies&lt;/span&gt;&lt;span&gt; before&lt;/span&gt;&lt;span&gt; Congress&lt;/span&gt;&lt;span&gt; over&lt;/span&gt;&lt;span&gt; handling&lt;/span&gt;&lt;span&gt; of&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; Epstein&lt;/span&gt;&lt;span&gt; files&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; NPR&lt;/span&gt;&lt;span&gt; (23m &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 4.&lt;/span&gt;&lt;span&gt; Romania&lt;/span&gt;&lt;span&gt; Says&lt;/span&gt;&lt;span&gt; It&lt;/span&gt;&lt;span&gt; Could&lt;/span&gt;&lt;span&gt; Invoke&lt;/span&gt;&lt;span&gt; NATO’s&lt;/span&gt;&lt;span&gt; Article&lt;/span&gt;&lt;span&gt; 4.&lt;/span&gt;&lt;span&gt; What&lt;/span&gt;&lt;span&gt; Would&lt;/span&gt;&lt;span&gt; That&lt;/span&gt;&lt;span&gt; Do?&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; The&lt;/span&gt;&lt;span&gt; New&lt;/span&gt;&lt;span&gt; York&lt;/span&gt;&lt;span&gt; Times&lt;/span&gt;&lt;span&gt; (4h &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 5.&lt;/span&gt;&lt;span&gt; Kenyan&lt;/span&gt;&lt;span&gt; court&lt;/span&gt;&lt;span&gt; halts&lt;/span&gt;&lt;span&gt; US&lt;/span&gt;&lt;span&gt; plans&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; Ebola&lt;/span&gt;&lt;span&gt; quarantine&lt;/span&gt;&lt;span&gt; facility&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; Americans&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; politico.eu&lt;/span&gt;&lt;span&gt; (5h &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 6.&lt;/span&gt;&lt;span&gt; Trump&lt;/span&gt;&lt;span&gt; Loses&lt;/span&gt;&lt;span&gt; It&lt;/span&gt;&lt;span&gt; at&lt;/span&gt;&lt;span&gt; Jill&lt;/span&gt;&lt;span&gt; Biden&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; Morning&lt;/span&gt;&lt;span&gt; Rage&lt;/span&gt;&lt;span&gt; Post&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; The&lt;/span&gt;&lt;span&gt; Daily&lt;/span&gt;&lt;span&gt; Beast&lt;/span&gt;&lt;span&gt; (4h &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 7.&lt;/span&gt;&lt;span&gt; Bus&lt;/span&gt;&lt;span&gt; hits&lt;/span&gt;&lt;span&gt; cars&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; Virginia,&lt;/span&gt;&lt;span&gt; killing&lt;/span&gt;&lt;span&gt; 5&lt;/span&gt;&lt;span&gt; people&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; injuring&lt;/span&gt;&lt;span&gt; 34,&lt;/span&gt;&lt;span&gt; state&lt;/span&gt;&lt;span&gt; police&lt;/span&gt;&lt;span&gt; say&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; AP&lt;/span&gt;&lt;span&gt; News&lt;/span&gt;&lt;span&gt; (3h &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 8.&lt;/span&gt;&lt;span&gt; California&lt;/span&gt;&lt;span&gt; House&lt;/span&gt;&lt;span&gt; Primary&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; Sacramento&lt;/span&gt;&lt;span&gt; Displays&lt;/span&gt;&lt;span&gt; Democrats’&lt;/span&gt;&lt;span&gt; Fierce&lt;/span&gt;&lt;span&gt; Generational&lt;/span&gt;&lt;span&gt; Battle&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; The&lt;/span&gt;&lt;span&gt; New&lt;/span&gt;&lt;span&gt; York&lt;/span&gt;&lt;span&gt; Times&lt;/span&gt;&lt;span&gt; (7h &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 9.&lt;/span&gt;&lt;span&gt; Mullin&lt;/span&gt;&lt;span&gt; plan&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; punish&lt;/span&gt;&lt;span&gt; sanctuary&lt;/span&gt;&lt;span&gt; jurisdictions&lt;/span&gt;&lt;span&gt; by&lt;/span&gt;&lt;span&gt; targeting&lt;/span&gt;&lt;span&gt; their&lt;/span&gt;&lt;span&gt; airports&lt;/span&gt;&lt;span&gt; faces&lt;/span&gt;&lt;span&gt; fierce&lt;/span&gt;&lt;span&gt; headwinds&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; CNN&lt;/span&gt;&lt;span&gt; (7h &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;10.&lt;/span&gt;&lt;span&gt; In&lt;/span&gt;&lt;span&gt; Carroll&lt;/span&gt;&lt;span&gt; Lawsuits&lt;/span&gt;&lt;span&gt; Inquiry,&lt;/span&gt;&lt;span&gt; Scrutiny&lt;/span&gt;&lt;span&gt; Turns&lt;/span&gt;&lt;span&gt; Toward&lt;/span&gt;&lt;span&gt; Private&lt;/span&gt;&lt;span&gt; Citizens&lt;/span&gt;&lt;span&gt; Who&lt;/span&gt;&lt;span&gt; Antagonized&lt;/span&gt;&lt;span&gt; Trump&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; The&lt;/span&gt;&lt;span&gt; New&lt;/span&gt;&lt;span&gt; York&lt;/span&gt;&lt;span&gt; Times&lt;/span&gt;&lt;span&gt; (51m &lt;/span&gt;&lt;span&gt;ago&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="server-mode"&gt;Server Mode&lt;a class="anchor-link" aria-label="Link to heading" href="#server-mode"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The next phase of evolving with Beads is transitioning from classic to server mode. Server mode here means Beads will run a local Dolt server on your host, instead of using the non-server embedded Dolt mode, which is the default.&lt;/p&gt;
&lt;p&gt;But why use server mode in the first place?&lt;/p&gt;
&lt;p&gt;The reason users may want to consider running Beads in server mode is because it allows you to run many coding agent sessions against the same Git repo, since server mode is designed for multi-process concurrent use. This is a limitation of Beads classic, which is single-writer.&lt;/p&gt;
&lt;p&gt;To migrate from classic mode to server mode, let’s first make a new bead that we can easily track across the migration from classic to server mode.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; "from classic to server mode"&lt;/span&gt;&lt;span&gt; -p&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; issue:&lt;/span&gt;&lt;span&gt; evolving_demo-w1g&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; classic&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Priority:&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Status:&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, to perform the migration we actually want to take a backup of our Beads database in classic mode, then after we initialize Beads in server mode, we’ll restore from the backup, which will give us our database back.&lt;/p&gt;
&lt;p&gt;To do this I first make a new directory to use as my database backup, then initialize it with the &lt;code&gt;bd backup init&lt;/code&gt; command. After initialization I can run &lt;code&gt;bd backup sync&lt;/code&gt; to sync my database to the backup destination.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; mkdir&lt;/span&gt;&lt;span&gt; ../ed_backup_1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; backup&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;span&gt; ../ed_backup_1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Backup&lt;/span&gt;&lt;span&gt; destination&lt;/span&gt;&lt;span&gt; configured:&lt;/span&gt;&lt;span&gt; file:///home/dustin/cursor_src/repros/ed_backup_1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Run&lt;/span&gt;&lt;span&gt; 'bd backup sync'&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; push&lt;/span&gt;&lt;span&gt; your&lt;/span&gt;&lt;span&gt; data.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; backup&lt;/span&gt;&lt;span&gt; sync&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Backup&lt;/span&gt;&lt;span&gt; synced&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; 20ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the backup synced, I can then remove the &lt;code&gt;.beads&lt;/code&gt; directory in my Git repo, which will delete the classic mode database (or just &lt;code&gt;mv&lt;/code&gt; it to not be named &lt;code&gt;.beads&lt;/code&gt; just in case), and then re-initialize Beads using the &lt;code&gt;--server&lt;/code&gt; flag.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; rm&lt;/span&gt;&lt;span&gt; -rf&lt;/span&gt;&lt;span&gt; .beads&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;span&gt; --server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Bootstrapped&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; remote:&lt;/span&gt;&lt;span&gt; git+https://github.com/coffeegoddd/evolving_demo.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Synced&lt;/span&gt;&lt;span&gt; database&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; git+https://github.com/coffeegoddd/evolving_demo.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Bootstrapped&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; remote:&lt;/span&gt;&lt;span&gt; git+https://github.com/coffeegoddd/evolving_demo.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Repository&lt;/span&gt;&lt;span&gt; ID:&lt;/span&gt;&lt;span&gt; 76062c1e&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Clone&lt;/span&gt;&lt;span&gt; ID:&lt;/span&gt;&lt;span&gt; 642acc6d98a2785e&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Adopted&lt;/span&gt;&lt;span&gt; project&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; existing&lt;/span&gt;&lt;span&gt; database&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;▶&lt;/span&gt;&lt;span&gt; Already&lt;/span&gt;&lt;span&gt; configured&lt;/span&gt;&lt;span&gt; as:&lt;/span&gt;&lt;span&gt; maintainer&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Change&lt;/span&gt;&lt;span&gt; role?&lt;/span&gt;&lt;span&gt; [y/N]: n&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;▶&lt;/span&gt;&lt;span&gt; Auto-export&lt;/span&gt;&lt;span&gt; can&lt;/span&gt;&lt;span&gt; keep&lt;/span&gt;&lt;span&gt; .beads/issues.jsonl&lt;/span&gt;&lt;span&gt; up&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; date&lt;/span&gt;&lt;span&gt; after&lt;/span&gt;&lt;span&gt; write&lt;/span&gt;&lt;span&gt; commands.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  This&lt;/span&gt;&lt;span&gt; optional&lt;/span&gt;&lt;span&gt; JSONL&lt;/span&gt;&lt;span&gt; export&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; useful&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; viewers&lt;/span&gt;&lt;span&gt; (bv), interchange, and issue-level migration.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Dolt&lt;/span&gt;&lt;span&gt; remotes/backups&lt;/span&gt;&lt;span&gt; handle&lt;/span&gt;&lt;span&gt; cross-machine&lt;/span&gt;&lt;span&gt; sync&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; backup.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Enable&lt;/span&gt;&lt;span&gt; auto-export?&lt;/span&gt;&lt;span&gt; [y/N]: n&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Auto-export&lt;/span&gt;&lt;span&gt; disabled&lt;/span&gt;&lt;span&gt; (enable &lt;/span&gt;&lt;span&gt;later&lt;/span&gt;&lt;span&gt; with:&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; export.auto&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Hooks&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;span&gt; to:&lt;/span&gt;&lt;span&gt; .beads/hooks/&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Updated&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; section&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; AGENTS.md&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; latest&lt;/span&gt;&lt;span&gt; format&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Hook&lt;/span&gt;&lt;span&gt; already&lt;/span&gt;&lt;span&gt; registered:&lt;/span&gt;&lt;span&gt; SessionStart&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Updated&lt;/span&gt;&lt;span&gt; existing&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; section&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; CLAUDE.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  File:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/CLAUDE.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; additional&lt;/span&gt;&lt;span&gt; configuration&lt;/span&gt;&lt;span&gt; needed!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Settings:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.claude/settings.json&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; changes&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; take&lt;/span&gt;&lt;span&gt; effect.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; skill...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; skill&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Skill:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.agents/skills/beads/SKILL.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; native&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; native&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  File:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/AGENTS.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; if&lt;/span&gt;&lt;span&gt; it&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; already&lt;/span&gt;&lt;span&gt; running.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Committed&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; files&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; initialized&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; remote!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Backend:&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Mode:&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Server:&lt;/span&gt;&lt;span&gt; root@127.0.0.1:46091&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ⚠&lt;/span&gt;&lt;span&gt; Server&lt;/span&gt;&lt;span&gt; host&lt;/span&gt;&lt;span&gt; defaulted&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; 127.0.0.1.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    If&lt;/span&gt;&lt;span&gt; your&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; remote,&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; BEADS_DOLT_SERVER_HOST&lt;/span&gt;&lt;span&gt; or&lt;/span&gt;&lt;span&gt; pass&lt;/span&gt;&lt;span&gt; --server-host.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Database:&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issue&lt;/span&gt;&lt;span&gt; prefix:&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issues&lt;/span&gt;&lt;span&gt; will&lt;/span&gt;&lt;span&gt; be&lt;/span&gt;&lt;span&gt; named:&lt;/span&gt;&lt;span&gt; evolving_demo-&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;h&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; (e.g., &lt;/span&gt;&lt;span&gt;evolving_demo-a3f2dd&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Run&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; quickstart&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; get&lt;/span&gt;&lt;span&gt; started.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As before, I keep my role as ‘maintainer’ and decline auto-export. This time though Beads is using a local server running on port &lt;code&gt;46091&lt;/code&gt;, as shown in the output above.&lt;/p&gt;
&lt;p&gt;Now I can restore from the backup I made earlier to get all my beads back.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; backup&lt;/span&gt;&lt;span&gt; restore&lt;/span&gt;&lt;span&gt; ../ed_backup_1&lt;/span&gt;&lt;span&gt; --force&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Restore&lt;/span&gt;&lt;span&gt; complete&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-w1g&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; classic&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And you can see that the bead I made is available and ready. I can also see the “status” of my Beads server by running &lt;code&gt;bd dolt status&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; status&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Dolt&lt;/span&gt;&lt;span&gt; server:&lt;/span&gt;&lt;span&gt; running&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  PID:&lt;/span&gt;&lt;span&gt;  778645&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Port:&lt;/span&gt;&lt;span&gt; 46091&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Data:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.beads/dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Logs:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.beads/dolt-server.log&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I wanted to actually poke around in the state of my Beads database, I could do so with a standard MySQL client. As of this blog, Beads servers always run with &lt;code&gt;root&lt;/code&gt; and no password.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; docker&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; --rm&lt;/span&gt;&lt;span&gt; -it&lt;/span&gt;&lt;span&gt; --network&lt;/span&gt;&lt;span&gt; host&lt;/span&gt;&lt;span&gt; mysql:8&lt;/span&gt;&lt;span&gt; mysql&lt;/span&gt;&lt;span&gt; -h&lt;/span&gt;&lt;span&gt; 127.0.0.1&lt;/span&gt;&lt;span&gt; -P&lt;/span&gt;&lt;span&gt; 46091&lt;/span&gt;&lt;span&gt; -u&lt;/span&gt;&lt;span&gt; root&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Welcome&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; MySQL&lt;/span&gt;&lt;span&gt; monitor.&lt;/span&gt;&lt;span&gt;  Commands&lt;/span&gt;&lt;span&gt; end&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;span&gt; ; &lt;/span&gt;&lt;span&gt;or&lt;/span&gt;&lt;span&gt; \g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Your&lt;/span&gt;&lt;span&gt; MySQL&lt;/span&gt;&lt;span&gt; connection&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; 27&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Server&lt;/span&gt;&lt;span&gt; version:&lt;/span&gt;&lt;span&gt; 8.0.33&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Copyright&lt;/span&gt;&lt;span&gt; (c) 2000, 2026, Oracle and/or its affiliates.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Oracle&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt; registered&lt;/span&gt;&lt;span&gt; trademark&lt;/span&gt;&lt;span&gt; of&lt;/span&gt;&lt;span&gt; Oracle&lt;/span&gt;&lt;span&gt; Corporation&lt;/span&gt;&lt;span&gt; and/or&lt;/span&gt;&lt;span&gt; its&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;affiliates.&lt;/span&gt;&lt;span&gt; Other&lt;/span&gt;&lt;span&gt; names&lt;/span&gt;&lt;span&gt; may&lt;/span&gt;&lt;span&gt; be&lt;/span&gt;&lt;span&gt; trademarks&lt;/span&gt;&lt;span&gt; of&lt;/span&gt;&lt;span&gt; their&lt;/span&gt;&lt;span&gt; respective&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;owners.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt; 'help;'&lt;/span&gt;&lt;span&gt; or&lt;/span&gt;&lt;span&gt; '\h'&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; help.&lt;/span&gt;&lt;span&gt; Type&lt;/span&gt;&lt;span&gt; '\c'&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; clear&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; current&lt;/span&gt;&lt;span&gt; input&lt;/span&gt;&lt;span&gt; statement.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;show&lt;/span&gt;&lt;span&gt; databases&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+--------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; Database&lt;/span&gt;&lt;span&gt;           |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+--------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt;               |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;span&gt;      |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; information_schema&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; mysql&lt;/span&gt;&lt;span&gt;              |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+--------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt; rows&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; (0.00 &lt;/span&gt;&lt;span&gt;sec&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;use&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Reading&lt;/span&gt;&lt;span&gt; table&lt;/span&gt;&lt;span&gt; information&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; completion&lt;/span&gt;&lt;span&gt; of&lt;/span&gt;&lt;span&gt; table&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt; names&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;You&lt;/span&gt;&lt;span&gt; can&lt;/span&gt;&lt;span&gt; turn&lt;/span&gt;&lt;span&gt; off&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; feature&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; get&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt; quicker&lt;/span&gt;&lt;span&gt; startup&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;span&gt; -A&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Database&lt;/span&gt;&lt;span&gt; changed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; count&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+----------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; count(*&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+----------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt;        7&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+----------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; row&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; (0.00 &lt;/span&gt;&lt;span&gt;sec&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;span&gt;&gt; &lt;/span&gt;&lt;span&gt;exit&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Bye&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our issue count in our restored database has our bead that we tracked across the classic to server migration and the six now closed issues used to build the news application.&lt;/p&gt;
&lt;p&gt;From this point forward, we could continue to use Beads in single-player mode as we did with classic mode, or we could open multiple terminal sessions against this repo and dispatch agents in each in parallel (non-overlapping) feature work.&lt;/p&gt;
&lt;h1 id="shared-server-mode"&gt;Shared-server Mode&lt;a class="anchor-link" aria-label="Link to heading" href="#shared-server-mode"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Lastly, let’s say I’ve been enjoying using Beads on many projects on my host, both in classic mode and server mode, but have noticed that each server mode project spins up a new Dolt sql-server process. Instead of doing this, can Beads run just a single Dolt sql-server for all my projects?&lt;/p&gt;
&lt;p&gt;Why yes it can, and this is the motivation behind shared-server mode. In this mode, Beads will manage a single global Dolt server that can house all Beads for your Git projects on the host, and these Beads will be isolated, so Beads will not leak between projects.&lt;/p&gt;
&lt;p&gt;To migrate from normal &lt;code&gt;--server&lt;/code&gt; mode to &lt;code&gt;--shared-server&lt;/code&gt; mode, we simply need to go through our backup and restore flow we did above, making sure to stop the running &lt;code&gt;--server&lt;/code&gt; mode process before starting the new &lt;code&gt;--shared-server&lt;/code&gt; process. If you have many &lt;code&gt;--server&lt;/code&gt; mode Beads projects on your host, you’ll want to do this for each one.&lt;/p&gt;
&lt;p&gt;To start, let’s remove the old bead we made and make a new one to watch across the migration.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-w1g&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; classic&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt; evolving_demo-w1g&lt;/span&gt;&lt;span&gt; --force&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Deleted&lt;/span&gt;&lt;span&gt; evolving_demo-w1g&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Removed&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; dependency&lt;/span&gt;&lt;span&gt; link&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Updated&lt;/span&gt;&lt;span&gt; text&lt;/span&gt;&lt;span&gt; references&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; issue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; found.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; "from server to shared-server"&lt;/span&gt;&lt;span&gt; -p&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; issue:&lt;/span&gt;&lt;span&gt; evolving_demo-pz8&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; shared-server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Priority:&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Status:&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-pz8&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; shared-server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we will need a new backup directory for our existing &lt;code&gt;--server&lt;/code&gt; mode Beads database.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; ../ed_backup_2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; backup&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;span&gt; ../ed_backup_2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Backup&lt;/span&gt;&lt;span&gt; destination&lt;/span&gt;&lt;span&gt; configured:&lt;/span&gt;&lt;span&gt; file:///home/dustin/cursor_src/repros/ed_backup_2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Run&lt;/span&gt;&lt;span&gt; 'bd backup sync'&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; push&lt;/span&gt;&lt;span&gt; your&lt;/span&gt;&lt;span&gt; data.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; backup&lt;/span&gt;&lt;span&gt; sync&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Backup&lt;/span&gt;&lt;span&gt; synced&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; 50ms&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the backup is synced I can stop the &lt;code&gt;--server&lt;/code&gt; mode server with &lt;code&gt;bd dolt stop&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; stop&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Flushed&lt;/span&gt;&lt;span&gt; working&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; database&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;before&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; stop&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Dolt&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; stopped.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, like before, I can remove the existing &lt;code&gt;.beads&lt;/code&gt; directory in my Git project and reinitialize Beads with the &lt;code&gt;--shared-server&lt;/code&gt; flag.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; rm&lt;/span&gt;&lt;span&gt; -rf&lt;/span&gt;&lt;span&gt; .beads&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;span&gt; --shared-server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Bootstrapped&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; remote:&lt;/span&gt;&lt;span&gt; git+https://github.com/coffeegoddd/evolving_demo.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Shared&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; started&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Global&lt;/span&gt;&lt;span&gt; database&lt;/span&gt;&lt;span&gt; beads_global&lt;/span&gt;&lt;span&gt; available&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Global&lt;/span&gt;&lt;span&gt; database&lt;/span&gt;&lt;span&gt; schema&lt;/span&gt;&lt;span&gt; initialized&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Configured&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;span&gt; remote:&lt;/span&gt;&lt;span&gt; origin&lt;/span&gt;&lt;span&gt; →&lt;/span&gt;&lt;span&gt; git+https://github.com/coffeegoddd/evolving_demo.git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Repository&lt;/span&gt;&lt;span&gt; ID:&lt;/span&gt;&lt;span&gt; 76062c1e&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Clone&lt;/span&gt;&lt;span&gt; ID:&lt;/span&gt;&lt;span&gt; 642acc6d98a2785e&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Shared&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;span&gt; enabled&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;▶&lt;/span&gt;&lt;span&gt; Already&lt;/span&gt;&lt;span&gt; configured&lt;/span&gt;&lt;span&gt; as:&lt;/span&gt;&lt;span&gt; maintainer&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Change&lt;/span&gt;&lt;span&gt; role?&lt;/span&gt;&lt;span&gt; [y/N]: n&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;▶&lt;/span&gt;&lt;span&gt; Auto-export&lt;/span&gt;&lt;span&gt; can&lt;/span&gt;&lt;span&gt; keep&lt;/span&gt;&lt;span&gt; .beads/issues.jsonl&lt;/span&gt;&lt;span&gt; up&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; date&lt;/span&gt;&lt;span&gt; after&lt;/span&gt;&lt;span&gt; write&lt;/span&gt;&lt;span&gt; commands.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  This&lt;/span&gt;&lt;span&gt; optional&lt;/span&gt;&lt;span&gt; JSONL&lt;/span&gt;&lt;span&gt; export&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; useful&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; viewers&lt;/span&gt;&lt;span&gt; (bv), interchange, and issue-level migration.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Dolt&lt;/span&gt;&lt;span&gt; remotes/backups&lt;/span&gt;&lt;span&gt; handle&lt;/span&gt;&lt;span&gt; cross-machine&lt;/span&gt;&lt;span&gt; sync&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; backup.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Enable&lt;/span&gt;&lt;span&gt; auto-export?&lt;/span&gt;&lt;span&gt; [y/N]: n&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Auto-export&lt;/span&gt;&lt;span&gt; disabled&lt;/span&gt;&lt;span&gt; (enable &lt;/span&gt;&lt;span&gt;later&lt;/span&gt;&lt;span&gt; with:&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; export.auto&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Hooks&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;span&gt; to:&lt;/span&gt;&lt;span&gt; .beads/hooks/&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  AGENTS.md&lt;/span&gt;&lt;span&gt; already&lt;/span&gt;&lt;span&gt; has&lt;/span&gt;&lt;span&gt; current&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Hook&lt;/span&gt;&lt;span&gt; already&lt;/span&gt;&lt;span&gt; registered:&lt;/span&gt;&lt;span&gt; SessionStart&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Updated&lt;/span&gt;&lt;span&gt; existing&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; section&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; CLAUDE.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  File:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/CLAUDE.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; additional&lt;/span&gt;&lt;span&gt; configuration&lt;/span&gt;&lt;span&gt; needed!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Settings:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.claude/settings.json&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; changes&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; take&lt;/span&gt;&lt;span&gt; effect.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; skill...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; skill&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Skill:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/.agents/skills/beads/SKILL.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; native&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; native&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  File:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/evolving_demo/AGENTS.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; if&lt;/span&gt;&lt;span&gt; it&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; already&lt;/span&gt;&lt;span&gt; running.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Committed&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; files&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; initialized&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; remote!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Backend:&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Mode:&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Server:&lt;/span&gt;&lt;span&gt; root@127.0.0.1:3308&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ⚠&lt;/span&gt;&lt;span&gt; Server&lt;/span&gt;&lt;span&gt; host&lt;/span&gt;&lt;span&gt; defaulted&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; 127.0.0.1.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    If&lt;/span&gt;&lt;span&gt; your&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; remote,&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; BEADS_DOLT_SERVER_HOST&lt;/span&gt;&lt;span&gt; or&lt;/span&gt;&lt;span&gt; pass&lt;/span&gt;&lt;span&gt; --server-host.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Database:&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issue&lt;/span&gt;&lt;span&gt; prefix:&lt;/span&gt;&lt;span&gt; evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issues&lt;/span&gt;&lt;span&gt; will&lt;/span&gt;&lt;span&gt; be&lt;/span&gt;&lt;span&gt; named:&lt;/span&gt;&lt;span&gt; evolving_demo-&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;h&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; (e.g., &lt;/span&gt;&lt;span&gt;evolving_demo-a3f2dd&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Run&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; quickstart&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; get&lt;/span&gt;&lt;span&gt; started.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, the role is ‘maintainer’ and ‘auto-export’ is disabled.&lt;/p&gt;
&lt;p&gt;Now I can restore from my &lt;code&gt;--server&lt;/code&gt; backup.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; backup&lt;/span&gt;&lt;span&gt; restore&lt;/span&gt;&lt;span&gt; ../ed_backup_2&lt;/span&gt;&lt;span&gt; --force&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Restore&lt;/span&gt;&lt;span&gt; complete&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; evolving_demo-pz8&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; from&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; shared-server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And once I do that, I’m successfully running in Shared-server mode!&lt;/p&gt;
&lt;h1 id="bonus"&gt;Bonus&lt;a class="anchor-link" aria-label="Link to heading" href="#bonus"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;As I mentioned earlier, Beads are scoped to a single Git repository and single Dolt database, so there is currently no way to share beads across projects.&lt;/p&gt;
&lt;p&gt;Except actually, there &lt;em&gt;kinda&lt;/em&gt; is… As a maintainer of Beads I snuck in a unique feature to Beads Shared-server mode which seemed like it needed, but didn’t have a way to share beads across projects.&lt;/p&gt;
&lt;p&gt;In Shared-server mode there is a unique &lt;code&gt;global&lt;/code&gt; beads database that works like a normal Beads database, except it is readable and writeable by all clients of the Shared server. This database is not tied to any specific Git project, so it does not have the same restrictions as ones that are tied to a specific Git project.&lt;/p&gt;
&lt;p&gt;For this reason, if you did need to share beads between projects, you can do so by reading and writing beads with the &lt;code&gt;--global&lt;/code&gt; flag, which will route the &lt;code&gt;bd&lt;/code&gt; command to the global database instead of the project scoped one.&lt;/p&gt;
&lt;p&gt;Here’s an example. First let’s delete the old migration bead we made.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt; evolving_demo-pz8&lt;/span&gt;&lt;span&gt; --force&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Deleted&lt;/span&gt;&lt;span&gt; evolving_demo-pz8&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Removed&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; dependency&lt;/span&gt;&lt;span&gt; link&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Updated&lt;/span&gt;&lt;span&gt; text&lt;/span&gt;&lt;span&gt; references&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; issue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, we’ll make another Beads project on our host and register it on the shared server by initializing Beads with &lt;code&gt;--shared-server&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; found.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; ..&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  repros&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; mkdir&lt;/span&gt;&lt;span&gt; different_project&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  repros&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; cd&lt;/span&gt;&lt;span&gt; different_project&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Initialized&lt;/span&gt;&lt;span&gt; empty&lt;/span&gt;&lt;span&gt; Git&lt;/span&gt;&lt;span&gt; repository&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/different_project/.git/&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;echo&lt;/span&gt;&lt;span&gt; "# different project"&lt;/span&gt;&lt;span&gt; &gt;&gt;&lt;/span&gt;&lt;span&gt; README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; add&lt;/span&gt;&lt;span&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;✗&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; commit&lt;/span&gt;&lt;span&gt; -m&lt;/span&gt;&lt;span&gt; 'README.md'&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;[main (root&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;commit) a11c0f1] README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; file&lt;/span&gt;&lt;span&gt; changed,&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; insertion&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;span&gt; 100644&lt;/span&gt;&lt;span&gt; README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;span&gt; --shared-server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Global&lt;/span&gt;&lt;span&gt; database&lt;/span&gt;&lt;span&gt; beads_global&lt;/span&gt;&lt;span&gt; available&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Global&lt;/span&gt;&lt;span&gt; database&lt;/span&gt;&lt;span&gt; schema&lt;/span&gt;&lt;span&gt; initialized&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Repository&lt;/span&gt;&lt;span&gt; ID:&lt;/span&gt;&lt;span&gt; ad3c7c9e&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Clone&lt;/span&gt;&lt;span&gt; ID:&lt;/span&gt;&lt;span&gt; d9436fdceeb5a843&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Shared&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;span&gt; enabled&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;▶&lt;/span&gt;&lt;span&gt; Already&lt;/span&gt;&lt;span&gt; configured&lt;/span&gt;&lt;span&gt; as:&lt;/span&gt;&lt;span&gt; maintainer&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Change&lt;/span&gt;&lt;span&gt; role?&lt;/span&gt;&lt;span&gt; [y/N]: n&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;▶&lt;/span&gt;&lt;span&gt; Auto-export&lt;/span&gt;&lt;span&gt; can&lt;/span&gt;&lt;span&gt; keep&lt;/span&gt;&lt;span&gt; .beads/issues.jsonl&lt;/span&gt;&lt;span&gt; up&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; date&lt;/span&gt;&lt;span&gt; after&lt;/span&gt;&lt;span&gt; write&lt;/span&gt;&lt;span&gt; commands.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  This&lt;/span&gt;&lt;span&gt; optional&lt;/span&gt;&lt;span&gt; JSONL&lt;/span&gt;&lt;span&gt; export&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; useful&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; viewers&lt;/span&gt;&lt;span&gt; (bv), interchange, and issue-level migration.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Dolt&lt;/span&gt;&lt;span&gt; remotes/backups&lt;/span&gt;&lt;span&gt; handle&lt;/span&gt;&lt;span&gt; cross-machine&lt;/span&gt;&lt;span&gt; sync&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; backup.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Enable&lt;/span&gt;&lt;span&gt; auto-export?&lt;/span&gt;&lt;span&gt; [y/N]: n&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Auto-export&lt;/span&gt;&lt;span&gt; disabled&lt;/span&gt;&lt;span&gt; (enable &lt;/span&gt;&lt;span&gt;later&lt;/span&gt;&lt;span&gt; with:&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; export.auto&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Hooks&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;span&gt; to:&lt;/span&gt;&lt;span&gt; .beads/hooks/&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; AGENTS.md&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Registered&lt;/span&gt;&lt;span&gt; SessionStart&lt;/span&gt;&lt;span&gt; hook&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; CLAUDE.md&lt;/span&gt;&lt;span&gt; with&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  File:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/different_project/CLAUDE.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; additional&lt;/span&gt;&lt;span&gt; configuration&lt;/span&gt;&lt;span&gt; needed!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; integration&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Settings:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/different_project/.claude/settings.json&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;span&gt; Claude&lt;/span&gt;&lt;span&gt; Code&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; changes&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; take&lt;/span&gt;&lt;span&gt; effect.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; skill...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Beads&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; skill&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Skill:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/different_project/.agents/skills/beads/SKILL.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; native&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; native&lt;/span&gt;&lt;span&gt; hooks&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Installing&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt; project...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; instructions&lt;/span&gt;&lt;span&gt; installed&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  File:&lt;/span&gt;&lt;span&gt; /home/dustin/cursor_src/repros/different_project/AGENTS.md&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Restart&lt;/span&gt;&lt;span&gt; Codex&lt;/span&gt;&lt;span&gt; if&lt;/span&gt;&lt;span&gt; it&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; already&lt;/span&gt;&lt;span&gt; running.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; Committed&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; files&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;⚠&lt;/span&gt;&lt;span&gt; No&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;span&gt; remote&lt;/span&gt;&lt;span&gt; configured&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issues&lt;/span&gt;&lt;span&gt; are&lt;/span&gt;&lt;span&gt; stored&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; local&lt;/span&gt;&lt;span&gt; Dolt.&lt;/span&gt;&lt;span&gt; .beads/issues.jsonl&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; an&lt;/span&gt;&lt;span&gt; export,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  not&lt;/span&gt;&lt;span&gt; cross-machine&lt;/span&gt;&lt;span&gt; sync&lt;/span&gt;&lt;span&gt; or&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; source&lt;/span&gt;&lt;span&gt; of&lt;/span&gt;&lt;span&gt; truth.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  To&lt;/span&gt;&lt;span&gt; enable&lt;/span&gt;&lt;span&gt; durable&lt;/span&gt;&lt;span&gt; sync,&lt;/span&gt;&lt;span&gt; add&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt; git&lt;/span&gt;&lt;span&gt; origin&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; then&lt;/span&gt;&lt;span&gt; run:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    bd&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; push&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; initialized&lt;/span&gt;&lt;span&gt; successfully!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Backend:&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Mode:&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Server:&lt;/span&gt;&lt;span&gt; root@127.0.0.1:3308&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ⚠&lt;/span&gt;&lt;span&gt; Server&lt;/span&gt;&lt;span&gt; host&lt;/span&gt;&lt;span&gt; defaulted&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; 127.0.0.1.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    If&lt;/span&gt;&lt;span&gt; your&lt;/span&gt;&lt;span&gt; Dolt&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; is&lt;/span&gt;&lt;span&gt; remote,&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; BEADS_DOLT_SERVER_HOST&lt;/span&gt;&lt;span&gt; or&lt;/span&gt;&lt;span&gt; pass&lt;/span&gt;&lt;span&gt; --server-host.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Database:&lt;/span&gt;&lt;span&gt; different_project&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issue&lt;/span&gt;&lt;span&gt; prefix:&lt;/span&gt;&lt;span&gt; different_project&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Issues&lt;/span&gt;&lt;span&gt; will&lt;/span&gt;&lt;span&gt; be&lt;/span&gt;&lt;span&gt; named:&lt;/span&gt;&lt;span&gt; different_project-&lt;/span&gt;&lt;span&gt;&amp;#x3C;&lt;/span&gt;&lt;span&gt;has&lt;/span&gt;&lt;span&gt;h&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; (e.g., &lt;/span&gt;&lt;span&gt;different_project-a3f2dd&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Run&lt;/span&gt;&lt;span&gt; bd&lt;/span&gt;&lt;span&gt; quickstart&lt;/span&gt;&lt;span&gt; to&lt;/span&gt;&lt;span&gt; get&lt;/span&gt;&lt;span&gt; started.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, we can use the project as normal, and beads will route to their project scoped database.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; found.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; "my first different project bead"&lt;/span&gt;&lt;span&gt; -p&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; issue:&lt;/span&gt;&lt;span&gt; different_project-s9i&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; my&lt;/span&gt;&lt;span&gt; first&lt;/span&gt;&lt;span&gt; different&lt;/span&gt;&lt;span&gt; project&lt;/span&gt;&lt;span&gt; bead&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Priority:&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Status:&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;💡&lt;/span&gt;&lt;span&gt; Tip:&lt;/span&gt;&lt;span&gt; Install&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; beads&lt;/span&gt;&lt;span&gt; plugin&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; automatic&lt;/span&gt;&lt;span&gt; workflow&lt;/span&gt;&lt;span&gt; context,&lt;/span&gt;&lt;span&gt; or&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; 'bd setup claude'&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; CLI-only&lt;/span&gt;&lt;span&gt; mode&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; different_project-s9i&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; my&lt;/span&gt;&lt;span&gt; first&lt;/span&gt;&lt;span&gt; different&lt;/span&gt;&lt;span&gt; project&lt;/span&gt;&lt;span&gt; bead&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we return to our earlier project which also uses this shared-server, you’ll see that it won’t be able to see the bead created and scoped to &lt;code&gt;different_project&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; ../evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; found.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Buuuuuuuut, if we go back to &lt;code&gt;different_project&lt;/code&gt; and create a bead using &lt;code&gt;--global&lt;/code&gt;, we’ll create a global bead that all shared-server projects can access.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; ../different_project&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; --global&lt;/span&gt;&lt;span&gt; "my first global bead"&lt;/span&gt;&lt;span&gt; -p&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;✓&lt;/span&gt;&lt;span&gt; Created&lt;/span&gt;&lt;span&gt; issue:&lt;/span&gt;&lt;span&gt; global-wqk&lt;/span&gt;&lt;span&gt; —&lt;/span&gt;&lt;span&gt; my&lt;/span&gt;&lt;span&gt; first&lt;/span&gt;&lt;span&gt; global&lt;/span&gt;&lt;span&gt; bead&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Priority:&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  Status:&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice the different output of &lt;code&gt;bd list&lt;/code&gt; with and without the &lt;code&gt;--global&lt;/code&gt; flag.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; different_project-s9i&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; my&lt;/span&gt;&lt;span&gt; first&lt;/span&gt;&lt;span&gt; different&lt;/span&gt;&lt;span&gt; project&lt;/span&gt;&lt;span&gt; bead&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;span&gt; --global&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; global-wqk&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; my&lt;/span&gt;&lt;span&gt; first&lt;/span&gt;&lt;span&gt; global&lt;/span&gt;&lt;span&gt; bead&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And similarly, if we return to the previous project we see the scoped beads
versus the global ones, by using the &lt;code&gt;--global&lt;/code&gt; flag.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  different_project&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; ../evolving_demo&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;No&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; found.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;➜&lt;/span&gt;&lt;span&gt;  evolving_demo&lt;/span&gt;&lt;span&gt; git:&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;bd&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;span&gt; --global&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;○&lt;/span&gt;&lt;span&gt; global-wqk&lt;/span&gt;&lt;span&gt; ●&lt;/span&gt;&lt;span&gt; P2&lt;/span&gt;&lt;span&gt; my&lt;/span&gt;&lt;span&gt; first&lt;/span&gt;&lt;span&gt; global&lt;/span&gt;&lt;span&gt; bead&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;--------------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Total:&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; issues&lt;/span&gt;&lt;span&gt; (1 &lt;/span&gt;&lt;span&gt;open,&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; progress&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;Status:&lt;/span&gt;&lt;span&gt; ○&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;  ◐&lt;/span&gt;&lt;span&gt; in_progress&lt;/span&gt;&lt;span&gt;  ●&lt;/span&gt;&lt;span&gt; blocked&lt;/span&gt;&lt;span&gt;  ✓&lt;/span&gt;&lt;span&gt; closed&lt;/span&gt;&lt;span&gt;  ❄&lt;/span&gt;&lt;span&gt; deferred&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;a class="anchor-link" aria-label="Link to heading" href="#conclusion"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I hope this helps clarify some common usage patterns for Beads, and we encourage you to give it a try if you haven’t already.&lt;/p&gt;
&lt;p&gt;Also, feel free to join both the &lt;a href="https://discord.gg/xHpUGUzZp2"&gt;Gaslandia Discord&lt;/a&gt; and the &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;Dolt Discord&lt;/a&gt; if you haven’t already. We’d love to chat with you and discuss building for the agentic future.&lt;/p&gt;</content:encoded>
      <dc:creator>Dustin Brown</dc:creator>
      <category>ai</category>
    </item>
    <item>
      <title>How TPC-C Works</title>
      <link>https://dolthub.com/blog/2026-05-14-how-tpcc-works/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-05-14-how-tpcc-works/</guid>
      <description>A detailed description of Dolt's TPC-C benchmarking.</description>
      <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;Dolt is a version-controlled database that works as a drop-in MySQL replacement.
In addition to correctness parity with MySQL, we are also determined to reach performance parity with MySQL.
For years now, we’ve been improving Dolt performance on both Sysbench and TPC-C benchmarks.
Towards the end of 2025, Dolt reached &lt;a href="https://www.dolthub.com/blog/2025-12-04-dolt-is-as-fast-as-mysql/"&gt;parity with MySQL on Sysbench&lt;/a&gt; when averaging reads and writes.
Shortly after, we managed to reach &lt;a href="https://www.dolthub.com/blog/2026-01-06-more-read-performance-wins/"&gt;MySQL parity on both read and writes&lt;/a&gt;.
Now, we &lt;a href="https://dolthub.com/docs/sql-reference/benchmarks/latency"&gt;surpass MySQL on Sysbench reads and writes&lt;/a&gt; with a &lt;code&gt;0.95&lt;/code&gt; reads mean multiplier and &lt;code&gt;0.87&lt;/code&gt; write mean multiplier.&lt;/p&gt;
&lt;p&gt;While we are proud of our accomplishments on Sysbench, TPC-C Benchmarks are arguably more important to the average user experience.
This blog will go into detail about the TPC-C benchmarks and the kinds of queries run against the database.&lt;/p&gt;
&lt;h1 id="what-is-tpc-c"&gt;What is TPC-C&lt;a class="anchor-link" aria-label="Link to heading" href="#what-is-tpc-c"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.tpc.org/tpcc/"&gt;TPC-C&lt;/a&gt; stands for Transaction Processing Performance Council Benchmark C.
It is the industry standard benchmark used for OLTP databases.
TPC-C simulates real-world usage of a database by modeling transactions for a wholesale supplier.
Dolt actually uses a slightly modified version of the official TPC-C benchmarks from &lt;a href="https://github.com/Percona-Lab/sysbench-tpcc"&gt;Percona Labs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="settings"&gt;Settings&lt;a class="anchor-link" aria-label="Link to heading" href="#settings"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We run TPC-C with these settings:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="shell"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;./tpcc.lua&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --db-driver=&lt;/span&gt;&lt;span&gt;"mysql"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --mysql-db=&lt;/span&gt;&lt;span&gt;"sbtest"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --mysql-host=&lt;/span&gt;&lt;span&gt;"127.0.0.1"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --mysql-port=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;$PORT&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --mysql-user=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;$USER&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --mysql-password=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;$PASS&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --time=800&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --report_interval=10&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --threads=1&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --tables=1&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --scale=1&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  --trx_level=&lt;/span&gt;&lt;span&gt;"RR"&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The benchmarks are run with a single thread for &lt;code&gt;800&lt;/code&gt; seconds with &lt;code&gt;autocommit&lt;/code&gt; and &lt;code&gt;foreign_key_checks&lt;/code&gt; disabled.
&lt;code&gt;trx_level="RR"&lt;/code&gt; is &lt;code&gt;REPEATABLE_READ&lt;/code&gt; (the MySQL/Innodb default), which means that &lt;code&gt;SELECT&lt;/code&gt; results are isolated within a transaction.
Uncommitted writes to a table from another transaction will not be visible to this transaction.
We compare the 95th percentile latency and number of transactions per second (tps) against MySQL.&lt;/p&gt;
&lt;h2 id="tables"&gt;Tables&lt;a class="anchor-link" aria-label="Link to heading" href="#tables"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is a brief summary of the tables created.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;warehouse&lt;/code&gt; with &lt;code&gt;1&lt;/code&gt; row&lt;/li&gt;
&lt;li&gt;&lt;code&gt;district&lt;/code&gt; with &lt;code&gt;10&lt;/code&gt; rows&lt;/li&gt;
&lt;li&gt;&lt;code&gt;customer&lt;/code&gt; with &lt;code&gt;30000&lt;/code&gt; rows&lt;/li&gt;
&lt;li&gt;&lt;code&gt;orders&lt;/code&gt; with &lt;code&gt;30000&lt;/code&gt; rows&lt;/li&gt;
&lt;li&gt;&lt;code&gt;new_orders&lt;/code&gt; with &lt;code&gt;9000&lt;/code&gt; rows&lt;/li&gt;
&lt;li&gt;&lt;code&gt;order_line&lt;/code&gt; with &lt;code&gt;299293&lt;/code&gt; rows&lt;/li&gt;
&lt;li&gt;&lt;code&gt;item&lt;/code&gt; with &lt;code&gt;100000&lt;/code&gt; rows&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stock&lt;/code&gt; with &lt;code&gt;100000&lt;/code&gt; rows&lt;/li&gt;
&lt;li&gt;&lt;code&gt;history&lt;/code&gt; with &lt;code&gt;30000&lt;/code&gt; rows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many of these tables have primary keys, secondary keys, and foreign keys (even though &lt;code&gt;foreign_key_checks&lt;/code&gt; are disabled).&lt;/p&gt;
&lt;h2 id="transactions"&gt;Transactions&lt;a class="anchor-link" aria-label="Link to heading" href="#transactions"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;TPC-C randomly selects between &lt;code&gt;5&lt;/code&gt; different transaction types with varying odds.
Each transaction starts with a &lt;code&gt;BEGIN&lt;/code&gt; and ends with &lt;code&gt;COMMIT&lt;/code&gt;.
Without spelling out every query run within a transaction, here is a high-level overview of each transaction.&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;trx_type&lt;/th&gt;&lt;th&gt;run_percent&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;new_order&lt;/code&gt;&lt;/td&gt;&lt;td&gt;43.48%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;payment&lt;/code&gt;&lt;/td&gt;&lt;td&gt;43.48%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;order_status&lt;/code&gt;&lt;/td&gt;&lt;td&gt;4.35%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;delivery&lt;/code&gt;&lt;/td&gt;&lt;td&gt;4.35%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;payment&lt;/code&gt;&lt;/td&gt;&lt;td&gt;4.35%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;TOTAL&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;≈100.00%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id="1-new_order"&gt;1. &lt;code&gt;new_order&lt;/code&gt;&lt;a class="anchor-link" aria-label="Link to heading" href="#1-new_order"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;:
This transaction simulates a customer order of &lt;code&gt;5&lt;/code&gt; - &lt;code&gt;15&lt;/code&gt; quantity of an item.
The new order is logged in the &lt;code&gt;orders&lt;/code&gt;, &lt;code&gt;new_orders&lt;/code&gt;, and &lt;code&gt;order_line&lt;/code&gt; tables, and the &lt;code&gt;item&lt;/code&gt; and &lt;code&gt;stock&lt;/code&gt; tables are updated accordingly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Percent Run&lt;/strong&gt;:
&lt;code&gt;43.49% (10/23)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;# of SQL Statements&lt;/strong&gt;:
&lt;code&gt;25&lt;/code&gt; - &lt;code&gt;65&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reads Tables&lt;/strong&gt;:
&lt;code&gt;customer&lt;/code&gt;, &lt;code&gt;district&lt;/code&gt;, &lt;code&gt;item&lt;/code&gt;, &lt;code&gt;stock&lt;/code&gt;, &lt;code&gt;warehouse&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Writes Tables&lt;/strong&gt;:
&lt;code&gt;district&lt;/code&gt;, &lt;code&gt;orders&lt;/code&gt;, &lt;code&gt;order_line&lt;/code&gt;, &lt;code&gt;new_orders&lt;/code&gt;, &lt;code&gt;stock&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="2-payment"&gt;2. &lt;code&gt;payment&lt;/code&gt;&lt;a class="anchor-link" aria-label="Link to heading" href="#2-payment"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;:
This transaction simulates a customer making a purchase.
It reads the customer’s payment details (name, address, etc.) from the &lt;code&gt;customer&lt;/code&gt; table, update their account balance, and logs the transaction in the &lt;code&gt;history&lt;/code&gt; table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Percent Run&lt;/strong&gt;:
&lt;code&gt;43.48% (10/23)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;# of SQL Statements&lt;/strong&gt;:
&lt;code&gt;6&lt;/code&gt; - &lt;code&gt;10&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reads Tables&lt;/strong&gt;:
&lt;code&gt;customer&lt;/code&gt;, &lt;code&gt;district&lt;/code&gt;, &lt;code&gt;warehouse&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Writes Tables&lt;/strong&gt;:
&lt;code&gt;customer&lt;/code&gt;, &lt;code&gt;district&lt;/code&gt;, &lt;code&gt;history&lt;/code&gt;, &lt;code&gt;warehouse&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="3-order_status"&gt;3. &lt;code&gt;order_status&lt;/code&gt;&lt;a class="anchor-link" aria-label="Link to heading" href="#3-order_status"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;:
This transaction simulates a customer inquiring about their order details.
It performs a series of &lt;code&gt;SELECT&lt;/code&gt; queries into the &lt;code&gt;customer&lt;/code&gt;, &lt;code&gt;orders&lt;/code&gt; and &lt;code&gt;order_line&lt;/code&gt; tables.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Percent Run&lt;/strong&gt;:
&lt;code&gt;4.34% (1/23)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;# of SQL Statements&lt;/strong&gt;:
&lt;code&gt;3&lt;/code&gt; - &lt;code&gt;4&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reads Tables&lt;/strong&gt;:
&lt;code&gt;customer&lt;/code&gt;, &lt;code&gt;orders&lt;/code&gt;, &lt;code&gt;order_line&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Writes Tables&lt;/strong&gt;:
&lt;code&gt;NONE&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="4-delivery"&gt;4. &lt;code&gt;delivery&lt;/code&gt;&lt;a class="anchor-link" aria-label="Link to heading" href="#4-delivery"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;:
This transaction simulates a customer’s order getting delivered.
An order is removed from the &lt;code&gt;new_orders&lt;/code&gt; table and the appropriate entries are updated in &lt;code&gt;orders&lt;/code&gt;, &lt;code&gt;order_line&lt;/code&gt; and &lt;code&gt;customer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Percent Run&lt;/strong&gt;:
&lt;code&gt;4.34% (1/23)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;# of SQL Statements&lt;/strong&gt;:
&lt;code&gt;1&lt;/code&gt; - &lt;code&gt;6&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reads Tables&lt;/strong&gt;:
&lt;code&gt;orders&lt;/code&gt;, &lt;code&gt;order_line&lt;/code&gt;, &lt;code&gt;new_orders&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Writes Tables&lt;/strong&gt;:
&lt;code&gt;customer&lt;/code&gt;, &lt;code&gt;orders&lt;/code&gt;, &lt;code&gt;order_line&lt;/code&gt;, &lt;code&gt;new_orders&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="5-stocklevel"&gt;5. &lt;code&gt;stocklevel&lt;/code&gt;&lt;a class="anchor-link" aria-label="Link to heading" href="#5-stocklevel"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;:
This transaction simulates a query over existing inventory.
It is a few &lt;code&gt;SELECT&lt;/code&gt; queries that aggregate over the &lt;code&gt;order_line&lt;/code&gt; and &lt;code&gt;stock&lt;/code&gt; tables that count the quantity of certain items.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Percent Run&lt;/strong&gt;:
&lt;code&gt;4.34% (1/23)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;# of SQL Statements&lt;/strong&gt;:
&lt;code&gt;3+&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reads Tables&lt;/strong&gt;:
&lt;code&gt;district&lt;/code&gt;, &lt;code&gt;orders&lt;/code&gt;, &lt;code&gt;stock&lt;/code&gt;, &lt;code&gt;order_line&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Writes Tables&lt;/strong&gt;:
&lt;code&gt;NONE&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can explore the TPC-C database in more detail here:
&lt;a href="https://www.dolthub.com/repositories/jcor/sbtest"&gt;https://www.dolthub.com/repositories/jcor/sbtest&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;a class="anchor-link" aria-label="Link to heading" href="#conclusion"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We have been focused on Dolt performance on TPC-C, which aims to simulate a real user experience with an OLTP database.
Over the last few months we have made substantial improvements to TPC-C.
Stay tuned for a future blog describing how we’ve broken the 2x MySQL multiplier on TPC-C.
Have any performance issues? Cut a bug on our &lt;a href="https://github.com/dolthub/dolt/issues"&gt;GitHub issues page&lt;/a&gt;.
Want to talk to anyone on our team? Join &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;our Discord&lt;/a&gt;.&lt;/p&gt;</content:encoded>
      <dc:creator>James Cor</dc:creator>
      <category>technical</category>
      <category>performance</category>
    </item>
    <item>
      <title>Dolt 2.0</title>
      <link>https://dolthub.com/blog/2026-05-11-dolt-2-dot-0/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-05-11-dolt-2-dot-0/</guid>
      <description>Almost exactly three years ago, we announced Dolt 1.0. Today, we announce Dolt 2.0.</description>
      <pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;Three years ago, we &lt;a href="https://www.dolthub.com/blog/2023-05-05-dolt-1-dot-0/"&gt;announced Dolt 1.0&lt;/a&gt;, signalling that Dolt was ready for production workloads. We haven’t stopped improving &lt;a href="https://www.dolthub.com/blog/2022-08-04-database-versioning/"&gt;the world’s first and only version-controlled SQL database&lt;/a&gt;. Today, we are excited to announce &lt;a href="https://github.com/dolthub/dolt/releases/tag/v2.0.0"&gt;Dolt 2.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/dolt-2_0.png/35df9fbddbb4f701cb124b70d8c1fe657b29a4f14c94606770a8996d40bc41ea.webp" alt="Dolt 2.0"&gt;&lt;/p&gt;
&lt;h1 id="what-did-dolt-10-mean"&gt;What Did Dolt 1.0 Mean?&lt;a class="anchor-link" aria-label="Link to heading" href="#what-did-dolt-10-mean"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.dolthub.com/blog/2023-05-05-dolt-1-dot-0/"&gt;Dolt 1.0&lt;/a&gt; meant four things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Forward Storage Compatibility&lt;/li&gt;
&lt;li&gt;Production Performance&lt;/li&gt;
&lt;li&gt;MySQL Compatibility&lt;/li&gt;
&lt;li&gt;Stable Version Control Interface&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Dolt 2.0 maintains the promises of Dolt 1.0. Dolt 2.0 improves on the performance and correctness metrics established in Dolt 1.0.&lt;/p&gt;
&lt;h1 id="what-does-dolt-20-mean"&gt;What Does Dolt 2.0 Mean?&lt;a class="anchor-link" aria-label="Link to heading" href="#what-does-dolt-20-mean"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Dolt 2.0 means five things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Automated Garbage Collection on by Default&lt;/li&gt;
&lt;li&gt;Archive Compression on by Default&lt;/li&gt;
&lt;li&gt;Faster than MySQL on &lt;code&gt;sysbench&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Beta Vector Support&lt;/li&gt;
&lt;li&gt;Adaptive Storage&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unlike Dolt 1.0, Dolt 2.0 is fully backwards compatible with all Dolt 1.0 versions. No storage migration using &lt;code&gt;dolt migrate&lt;/code&gt; is required. Let’s dive into the details of each of these points.&lt;/p&gt;
&lt;h2 id="garbage-collection"&gt;Garbage Collection&lt;a class="anchor-link" aria-label="Link to heading" href="#garbage-collection"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Dolt makes a lot of disk garbage, especially during import. Dolt is copy-on-write so all intermediate committed transaction state is preserved to disk. Any intermediate state that is not in a Dolt commit is garbage and can be collected.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/how-garbage-is-created.png/c719463f830464444cce6a285c5a4125cc88710480ad62d28a3108f60a25739b.webp" alt="Garbage"&gt;&lt;/p&gt;
&lt;p&gt;Dolt already must preserve all history in the commit graph on disk. Adding extra garbage can eat through your disk very quickly.&lt;/p&gt;
&lt;p&gt;Dolt 2.0 has &lt;a href="https://www.dolthub.com/blog/2025-02-28-announcing-automatic-gc-in-sql-server/"&gt;automatic garbage collection&lt;/a&gt; on by default, meaning most users don’t have to care about disk garbage. Many users have been running in this mode for over a year. We’re confident it is stable.&lt;/p&gt;
&lt;p&gt;Dolt 2.0 databases do not require extra garbage maintenance, just like other modern SQL engines.&lt;/p&gt;
&lt;h2 id="archives"&gt;Archives&lt;a class="anchor-link" aria-label="Link to heading" href="#archives"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Following on the disk space theme, we also have a &lt;a href="https://www.dolthub.com/blog/2024-04-29-dolt-storage-v2/"&gt;new on disk format we call archives&lt;/a&gt; that can reduce Dolt’s storage footprint by an additional 30-50%. Archives use dictionary compression to de-duplicate storage in the deepest layers of Dolt, saving even more disk space.&lt;/p&gt;
&lt;p&gt;As with automatic garbage collection, archives have been the default format for new Dolt databases for months. We’re confident the format is stable and delivers real disk space wins.&lt;/p&gt;
&lt;p&gt;Dolt 2.0 databases are kind to your disk with automatic garbage collection and archives. Version control already requires more disk space than traditional databases. Dolt 2.0 preserves that disk for your data’s history.&lt;/p&gt;
&lt;h2 id="faster-than-mysql-on-sysbench"&gt;Faster than MySQL on &lt;code&gt;sysbench&lt;/code&gt;&lt;a class="anchor-link" aria-label="Link to heading" href="#faster-than-mysql-on-sysbench"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We’ve long used the &lt;a href="https://github.com/akopytov/sysbench"&gt;industry standard &lt;code&gt;sysbench&lt;/code&gt;&lt;/a&gt; to measure and benchmark &lt;a href="https://dolthub.com/docs/sql-reference/benchmarks/latency"&gt;the latency of simple SQL queries in Dolt&lt;/a&gt;. We started at about 10X slower on reads and 20X slower on writes than MySQL. We’ve worked tirelessly to improve Dolt’s performance and we are now 13% faster than MySQL on writes and 5% faster on reads, averaging out to 8% faster than MySQL on &lt;code&gt;sysbench&lt;/code&gt; style workloads.&lt;/p&gt;
&lt;p&gt;Dolt 2.0 databases deliver real production database performance coupled with version control functionality.&lt;/p&gt;
&lt;h2 id="beta-vector-support"&gt;Beta Vector Support&lt;a class="anchor-link" aria-label="Link to heading" href="#beta-vector-support"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We announced &lt;a href="https://www.dolthub.com/blog/2025-01-16-announcing-vector-indexes/"&gt;vector index support&lt;/a&gt; early last year. We have a much bigger challenge than traditional databases with vector indexes because our vector indexes must be version-controlled. We’ve done &lt;a href="https://www.dolthub.com/blog/2025-06-23-vector-index-deep-dive/"&gt;the hard computer science&lt;/a&gt; to achieve this. We &lt;a href="https://www.dolthub.com/blog/2025-09-03-improving-vector-performance/"&gt;adopted the Vector type from MariaDB&lt;/a&gt; in September 2025.&lt;/p&gt;
&lt;p&gt;Dolt 2.0 databases have Beta vector support. Dolt is the only database where your vectors are version-controlled. We still have some edge cases on the read query path where a vector index should be used but it is not. Closing these gaps will remove the Beta tag from Dolt’s vector support.&lt;/p&gt;
&lt;h2 id="adaptive-storage-for-large-column-types"&gt;Adaptive storage for large column types&lt;a class="anchor-link" aria-label="Link to heading" href="#adaptive-storage-for-large-column-types"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Borrowing from our &lt;a href="https://www.dolthub.com/blog/2025-04-14-adaptive-encoding/"&gt;Doltgres adaptive storage work&lt;/a&gt; to support &lt;a href="https://www.postgresql.org/docs/current/storage-toast.html"&gt;TOAST types&lt;/a&gt;, we’re excited to announce Dolt 2.0 has adaptive storage.&lt;/p&gt;
&lt;p&gt;For large column types like TEXT, BLOB, and JSON, databases generally store the value “out of band”, as a file on disk with a pointer to the file in the actual table structure. A different strategy, popularized by Postgres, is to examine the size of the value and store small values in the table structure while preserving the files and pointers strategy for large values. This strategy allows the user to be less disciplined about sizing &lt;code&gt;VARCHAR&lt;/code&gt; columns and just use &lt;code&gt;TEXT&lt;/code&gt; instead. It’s also a big performance win for these types when the values are small.&lt;/p&gt;
&lt;p&gt;Dolt 2.0 has adaptive storage making MySQL databases that use &lt;code&gt;TEXT&lt;/code&gt;, &lt;code&gt;BLOB&lt;/code&gt;, &lt;code&gt;GEOMETRY&lt;/code&gt;, or &lt;code&gt;JSON&lt;/code&gt; columns a good fit regardless of whether they need version control or not.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;a class="anchor-link" aria-label="Link to heading" href="#conclusion"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Dolt 2.0 is here. It’s kinder to your disk and it’s fast. Questions? Stop by &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;our Discord&lt;/a&gt; and just ask.&lt;/p&gt;</content:encoded>
      <dc:creator>Tim Sehn</dc:creator>
      <category>dolt</category>
      <category>feature release</category>
    </item>
    <item>
      <title>Announcing DumboDB: A MongoDB Clone Built on Dolt</title>
      <link>https://dolthub.com/blog/2026-05-07-announcing-dumbodb/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-05-07-announcing-dumbodb/</guid>
      <description>MongoDB and Git had a baby, and it's named Dumbo. Release 0.1 is now public!</description>
      <pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/dumbo-logo.png/c02da7b39168585c4dc1adf3ebf6ffe77404dd9b8fc5a35f6dc765bb9dea9e16.webp" alt="DumboDB Logo"&gt;&lt;/p&gt;
&lt;p&gt;Today, I’m pleased to announce the &lt;a href="https://github.com/dolthub/dumbodb"&gt;release of DumboDB 0.1&lt;/a&gt;, a &lt;a href="https://github.com/mongodb/mongo"&gt;MongoDB&lt;/a&gt; clone built on top of Dolt’s storage system.&lt;/p&gt;
&lt;p&gt;MongoDB and Git had a baby, and it’s named DumboDB.&lt;/p&gt;
&lt;h2 id="tldr"&gt;TL;DR;&lt;a class="anchor-link" aria-label="Link to heading" href="#tldr"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Grab the code and give it a try! We are excited to see what the community can do with it. You can find the code on GitHub: &lt;a href="https://github.com/dolthub/dumbodb"&gt;https://github.com/dolthub/dumbodb&lt;/a&gt;. See the README for installation instructions. If you have feedback, questions, or want to contribute, join us on &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;Discord&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id="how-did-we-get-here"&gt;How Did We Get Here?&lt;a class="anchor-link" aria-label="Link to heading" href="#how-did-we-get-here"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Like everyone else in the software industry, we have been kicking around the AI tools that are getting so much hype these days. No joke, &lt;a href="https://www.dolthub.com/blog/2026-03-25-doltlite/"&gt;my boss is vibe coding now&lt;/a&gt;. What a stereotype, right? A couple of weeks ago &lt;a href="https://www.dolthub.com/blog/2026-04-16-two-weeks-in-gastown/"&gt;I talked about testing Gas Town&lt;/a&gt;, a coding agent orchestrator, only to get swept up in the excitement of building something new insanely fast. Turns out that a dozen agents can make a really compelling proof of concept in a couple of weeks. Ultimately, we decided to turn that proof of concept into a real product, and here we are.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/dumbo_i_made_this.jpg/721f49f2a93edb921e59fafa20922b2ade612be7731c0cac557987dae2523add.webp" alt="I Made This"&gt;&lt;/p&gt;
&lt;p&gt;Since then, the pace of change has slowed to allow for human-speed verification and testing. The firehose of code generation provided by Gas Town hasn’t been necessary, and it’s mostly been slower 1-on-1 coding with &lt;a href="https://code.claude.com/docs/en/overview"&gt;Claude Code&lt;/a&gt;. I’ve even read some of the code and directed Claude to clean up some nonsense which we are all used to seeing with coding agents at this point. Nevertheless, the 6 weeks of development to get to a viable 0.1 release has been far, far faster than I could have ever done on my own. Say what you want about the AI bubble, coding agents are going to help us write a mountain of code.&lt;/p&gt;
&lt;h2 id="dumbodbs-dna"&gt;DumboDB’s DNA&lt;a class="anchor-link" aria-label="Link to heading" href="#dumbodbs-dna"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;DumboDB started with the &lt;a href="https://github.com/FerretDB/FerretDB"&gt;FerretDB code base&lt;/a&gt;, which is an open-source MongoDB clone. FerretDB operates as a proxy that translates MongoDB queries into SQL queries that are executed against a PostgreSQL database. It’s written in Go.&lt;/p&gt;
&lt;p&gt;Dolt is written in Go as well, so we ripped out the proxy approach of FerretDB and made a standalone server that uses Dolt’s storage engine.&lt;/p&gt;
&lt;p&gt;Dolt’s storage engine is a &lt;a href="https://dolthub.com/docs/architecture/storage-engine/prolly-tree"&gt;Prolly Tree&lt;/a&gt;, which is a data structure that allows for structural sharing of data. Using &lt;a href="https://en.wikipedia.org/wiki/Merkle_tree"&gt;Merkle Trees and DAGs&lt;/a&gt;, Dolt can represent a very granular set of snapshots of your data. This is the same approach used by Git to model your source code history.&lt;/p&gt;
&lt;p&gt;Our Prolly Tree implementation has been getting our love and attention for more than a &lt;a href="https://github.com/dolthub/dolt/commit/68c3ac02058e559367534aeeb7d9f8f483a4db1b"&gt;decade now&lt;/a&gt;. It is what enables our primary product, Dolt, to be a version-controlled database. And when we say version-controlled, we mean it. You can branch, merge, diff, send pull requests, rebase, and so on - just like you would with Git. Dolt is a drop-in replacement for MySQL and is &lt;a href="https://dolthub.com/docs/sql-reference/benchmarks/latency"&gt;as fast as MySQL for many workloads&lt;/a&gt;. It gives you all the &lt;a href="https://www.dolthub.com/blog/2026-05-04-database-insurance/"&gt;safety of Git for your data&lt;/a&gt;. Honestly, most software engineers hear about what we’ve built in Dolt, and they are astonished because it seems impossible. It’s real! &lt;a href="https://github.com/dolthub/dolt"&gt;Check it out&lt;/a&gt; if you haven’t already!&lt;/p&gt;
&lt;p&gt;DumboDB is using the same storage engine as Dolt, but with a different access layer. Instead of using SQL, DumboDB uses the MongoDB query language. This means that you can use all the same tools and libraries that you would use with MongoDB, but with the added benefits of Dolt’s storage engine. To be crystal clear, there is no SQL layer in DumboDB. DumboDB uses the storage objects of Dolt. Therefore, it uses the same indexes, journal code, and commit model — but no SQL. It’s a NoSQL document database — not a facade on top of a SQL database.&lt;/p&gt;
&lt;h2 id="what-can-you-do-with-dumbodb"&gt;What Can You Do With DumboDB?&lt;a class="anchor-link" aria-label="Link to heading" href="#what-can-you-do-with-dumbodb"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;DumboDB is alpha-quality software, so what you &lt;em&gt;should not&lt;/em&gt; do is run it in production.&lt;/p&gt;
&lt;p&gt;That said, it should be able to do most basic MongoDB operations. If you are familiar with MongoDB, you should be able to pick up DumboDB pretty quickly. You can use the same drivers and libraries that you would use with MongoDB, so probably the best thing to do is just kick the tires and tell us when something doesn’t work. We are sure there are bugs, and we want to know about them!&lt;/p&gt;
&lt;p&gt;There are some glaring gaps. DumboDB has no concept of user accounts or permissions yet. There are no isolated sessions or transactions with rollbacks (though you can &lt;code&gt;reset --hard&lt;/code&gt;!). Text search and geo features aren’t implemented. We don’t have a replication or sharding story yet, and we may just stick to the Git model of clone/push/pull. We’ll see. It all depends on what our users ask for. The joy of open source is that we aren’t hiding behind a proprietary roadmap. We’ll build what makes sense, and take PRs for all the rest.&lt;/p&gt;
&lt;p&gt;Being a drop-in replacement for MongoDB is the eventual goal, but we aren’t there yet. If you are bold, you can try running your existing MongoDB workloads against DumboDB and see what happens. Start your server with the &lt;code&gt;--auto-commit&lt;/code&gt; flag and witness how your application changes your data over time.&lt;/p&gt;
&lt;h3 id="version-control-features"&gt;Version Control Features&lt;a class="anchor-link" aria-label="Link to heading" href="#version-control-features"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;All the basic operations you would expect from a Git-inspired product are available. This includes: &lt;code&gt;commit&lt;/code&gt;, &lt;code&gt;branch&lt;/code&gt;, &lt;code&gt;merge&lt;/code&gt;, &lt;code&gt;cherry-pick&lt;/code&gt;, &lt;code&gt;rebase&lt;/code&gt;, &lt;code&gt;log&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;diff&lt;/code&gt;, &lt;code&gt;reset&lt;/code&gt;, &lt;code&gt;revert&lt;/code&gt;, and &lt;code&gt;tag&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Read the documentation for each command &lt;a href="https://github.com/dolthub/dumbodb/wiki/Commands"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is no “staging” concept in DumboDB, which is a departure from how Git works. Instead, you just make your changes to the database, and then when you are ready to commit, you commit and whatever content is in your workspace will be committed. No need to “add” changes, like you would in Git.&lt;/p&gt;
&lt;p&gt;There are two additional commands for working with merge conflicts: &lt;code&gt;conflicts&lt;/code&gt; and &lt;code&gt;resolveConflict&lt;/code&gt;. Unlike Git, but similar to Dolt, merge conflicts are structured. When merge conflicts arise, the three-way merge details are available to your application so that it can resolve the conflicts reliably. See examples below.&lt;/p&gt;
&lt;p&gt;Note the lack of &lt;code&gt;checkout&lt;/code&gt;. There is no checkout in DumboDB. Instead, you get a database instance using the &lt;code&gt;getSiblingDB&lt;/code&gt; operation. Check out the examples…&lt;/p&gt;
&lt;h2 id="examples"&gt;Examples&lt;a class="anchor-link" aria-label="Link to heading" href="#examples"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You’ll need to grab a prebuilt binary or build from source to run these examples. See the &lt;a href="https://github.com/dolthub/dumbodb#install-dumbodb"&gt;README&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;p&gt;Run the server in its own terminal window:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;dumbodb&lt;/span&gt;&lt;span&gt; --data-dir&lt;/span&gt;&lt;span&gt; /tmp/dumbodb-data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in another terminal window, connect to the server using the &lt;a href="https://www.mongodb.com/docs/mongodb-shell/"&gt;MongoDB shell&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; mongosh&lt;/span&gt;&lt;span&gt; mongodb://localhost:27017/&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;   The&lt;/span&gt;&lt;span&gt; server&lt;/span&gt;&lt;span&gt; generated&lt;/span&gt;&lt;span&gt; these&lt;/span&gt;&lt;span&gt; startup&lt;/span&gt;&lt;span&gt; warnings&lt;/span&gt;&lt;span&gt; when&lt;/span&gt;&lt;span&gt; booting&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;   2026-05-06T21:36:58.547Z:&lt;/span&gt;&lt;span&gt; Powered&lt;/span&gt;&lt;span&gt; by&lt;/span&gt;&lt;span&gt; DumboDB&lt;/span&gt;&lt;span&gt; v0.1.0&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;   2026-05-06T21:36:58.547Z:&lt;/span&gt;&lt;span&gt; Star&lt;/span&gt;&lt;span&gt; Us!&lt;/span&gt;&lt;span&gt; https://github.com/dolthub/dumbodb&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;mongosh&lt;/code&gt; is a JavaScript shell, so you execute JavaScript code to interact with the database. The &lt;code&gt;test&gt;&lt;/code&gt; prompt indicates that you are connected to the &lt;code&gt;test&lt;/code&gt; database. The way you change the database is you set the &lt;code&gt;db&lt;/code&gt; variable to a different database. For example, if you want to switch to the &lt;code&gt;mydb&lt;/code&gt; database, you would run:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;getSiblingDB&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;"mydb"&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See how the prompt changed to &lt;code&gt;mydb&gt;&lt;/code&gt;? That indicates that we are now using the &lt;code&gt;mydb&lt;/code&gt; database. Now let’s use it!&lt;/p&gt;
&lt;h3 id="create-a-new-collection-and-insert-some-documents"&gt;Create a new collection, and insert some documents:&lt;a class="anchor-link" aria-label="Link to heading" href="#create-a-new-collection-and-insert-some-documents"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The MongoDB approach is to create collections implicitly when you first insert a document into them. So there is no &lt;code&gt;createCollection&lt;/code&gt; command. Instead, you just start inserting documents into a collection, and it will be created for you. Let’s insert two documents into a new collection called &lt;code&gt;customers&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.customers.&lt;/span&gt;&lt;span&gt;insertOne&lt;/span&gt;&lt;span&gt;({ name: &lt;/span&gt;&lt;span&gt;"Alice"&lt;/span&gt;&lt;span&gt;, phone: &lt;/span&gt;&lt;span&gt;"555-1234"&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  acknowledged&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  insertedId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ObjectId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'69fbcb932a4aeea4bc4de9b5'&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.customers.&lt;/span&gt;&lt;span&gt;insertOne&lt;/span&gt;&lt;span&gt;({ name: &lt;/span&gt;&lt;span&gt;"Bob"&lt;/span&gt;&lt;span&gt;, phone: &lt;/span&gt;&lt;span&gt;"555-5678"&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  acknowledged&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  insertedId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ObjectId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'69fbbb46a26d8df3b3ab5cf6'&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s all vanilla Mongo behavior. By inserting these two documents, we have made changes to the database, but those changes are not committed yet. It’s like editing a source file in Git: you need to commit it. It works exactly the same with DumboDB. Make as many changes as you need to, then commit when ready.&lt;/p&gt;
&lt;p&gt;DumboDB’s version control operations are executed with the &lt;code&gt;db.runCommand&lt;/code&gt; method. We can see the status of our database with the &lt;code&gt;dumboStatus&lt;/code&gt; command:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboStatus: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt;,                   &lt;/span&gt;&lt;span&gt;// `db` is on the main branch&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  dirty&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,                      &lt;/span&gt;&lt;span&gt;// there are uncommitted changes&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  readonly&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,                  &lt;/span&gt;&lt;span&gt;// we can write to this database, as demonstrated by our inserts&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  collections&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      name: &lt;/span&gt;&lt;span&gt;'customers'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      status: &lt;/span&gt;&lt;span&gt;'added'&lt;/span&gt;&lt;span&gt;,              &lt;/span&gt;&lt;span&gt;// the customers collection is new, so it's status is "added"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      added: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,                     &lt;/span&gt;&lt;span&gt;// we added 2 documents to the customers collection&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      modified: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      deleted: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;                             // the command was successful. Standard MongoDB.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can commit our changes to the database. The commit will create a new snapshot of the database, and the dirty flag will return to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboCommit: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                      message: &lt;/span&gt;&lt;span&gt;"Add customers collection with Alice and Bob"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                      author: &lt;/span&gt;&lt;span&gt;"neil &amp;#x3C;neil@dolthub.com&gt;"&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  commitId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'6nc94olva9m81ofdjnnhp3018100qs5f'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  message&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'Add customers collection with Alice and Bob'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  author&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  timestamp&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T22:12:28.240Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  committer&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  committerTimestamp&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T22:12:28.240Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboStatus: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  dirty&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  readonly&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  commitId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'6nc94olva9m81ofdjnnhp3018100qs5f'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;// commitId is shown whenever dirty is false.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  collections&lt;/span&gt;&lt;span&gt;: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="branch-merge-and-resolve-conflicts"&gt;Branch, Merge, and Resolve Conflicts&lt;a class="anchor-link" aria-label="Link to heading" href="#branch-merge-and-resolve-conflicts"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s create a new branch, called &lt;code&gt;feature&lt;/code&gt;, and change the phone number for Alice:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboBranch: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, branch: &lt;/span&gt;&lt;span&gt;"feature"&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{ &lt;/span&gt;&lt;span&gt;branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'feature'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;// Specify the branch or revision number with &amp;#x3C;db&gt;@&amp;#x3C;branchOrRevision&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt; feature &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;getSiblingDB&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;"mydb@feature"&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;// `feature` variable is a database instance that is now "pointing" to the `feature` branch.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;// We can run commands against it, just like we do with `db`.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; feature.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboStatus: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'feature'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  dirty&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  readonly&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  commitId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'6nc94olva9m81ofdjnnhp3018100qs5f'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  collections&lt;/span&gt;&lt;span&gt;: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;// Update Alice's phone number in the feature branch&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; feature.customers.&lt;/span&gt;&lt;span&gt;updateOne&lt;/span&gt;&lt;span&gt;({ name: &lt;/span&gt;&lt;span&gt;"Alice"&lt;/span&gt;&lt;span&gt; }, { $set: { phone: &lt;/span&gt;&lt;span&gt;"555-4321"&lt;/span&gt;&lt;span&gt; } })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  acknowledged&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  insertedId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  matchedCount&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  modifiedCount&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,   &lt;/span&gt;&lt;span&gt;// Indicates that one document was modified.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  upsertedCount&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; feature.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboStatus: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'feature'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  dirty&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  readonly&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  collections&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      name: &lt;/span&gt;&lt;span&gt;'customers'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      status: &lt;/span&gt;&lt;span&gt;'modified'&lt;/span&gt;&lt;span&gt;,  &lt;/span&gt;&lt;span&gt;// The customers collection is modified, because we changed Alice's phone number.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      added: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      modified: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,         &lt;/span&gt;&lt;span&gt;// Alice's document was modified.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      deleted: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;dumboStatus&lt;/code&gt; gives a high-level summary of what has changed in our working copy of the database, but if we want to see the actual changes, we can use the &lt;code&gt;dumboDiff&lt;/code&gt; command:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; feature.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboDiff: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  collections&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      name: &lt;/span&gt;&lt;span&gt;'customers'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      status: &lt;/span&gt;&lt;span&gt;'modified'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      added: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      removed: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      modified: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          _id: &lt;/span&gt;&lt;span&gt;ObjectId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'69fbcb932a4aeea4bc4de9b5'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          diff: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            // the "phone" field was changed from "555-1234" to "555-4321"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            { type: &lt;/span&gt;&lt;span&gt;'modified'&lt;/span&gt;&lt;span&gt;, path: &lt;/span&gt;&lt;span&gt;'$.phone'&lt;/span&gt;&lt;span&gt;, from: &lt;/span&gt;&lt;span&gt;'555-1234'&lt;/span&gt;&lt;span&gt;, to: &lt;/span&gt;&lt;span&gt;'555-4321'&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          ]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;// dumboCommit will always commit the content shown in the output of dumboDiff without arguments.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;// Run dumboCommit now, it will commit the change to Alice's phone number.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; feature.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboCommit: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, message: &lt;/span&gt;&lt;span&gt;"Update Alice's phone number"&lt;/span&gt;&lt;span&gt;, author: &lt;/span&gt;&lt;span&gt;"neil &amp;#x3C;neil@dolthub.com&gt;"&lt;/span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  commitId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'p7p99vndl9d11hjloivlu1lcuvt3n9qa'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'feature'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  message&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;"Update Alice's phone number"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  author&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  timestamp&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:27:52.848Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  committer&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  committerTimestamp&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:27:52.848Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let’s change the same field, but on the &lt;code&gt;main&lt;/code&gt; branch. Note that the &lt;code&gt;db&lt;/code&gt; instance was created on the default branch, which is &lt;code&gt;main&lt;/code&gt;, so when we run commands against &lt;code&gt;db&lt;/code&gt;, we are running them against the &lt;code&gt;main&lt;/code&gt; branch. We’ll perform a ‘find’ to demonstrate:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.customers.&lt;/span&gt;&lt;span&gt;find&lt;/span&gt;&lt;span&gt;({name: &lt;/span&gt;&lt;span&gt;'Alice'&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    _id: &lt;/span&gt;&lt;span&gt;ObjectId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'69fbcb932a4aeea4bc4de9b5'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    name: &lt;/span&gt;&lt;span&gt;'Alice'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    phone: &lt;/span&gt;&lt;span&gt;'555-1234'&lt;/span&gt;&lt;span&gt; // Still unchanged on the main branch.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.customers.&lt;/span&gt;&lt;span&gt;updateOne&lt;/span&gt;&lt;span&gt;({ name: &lt;/span&gt;&lt;span&gt;"Alice"&lt;/span&gt;&lt;span&gt; }, { $set: { phone: &lt;/span&gt;&lt;span&gt;"555-9999"&lt;/span&gt;&lt;span&gt; } })&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  acknowledged&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  insertedId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  matchedCount&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  modifiedCount&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  upsertedCount&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({dumboCommit:&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, message: &lt;/span&gt;&lt;span&gt;"update Alice on main"&lt;/span&gt;&lt;span&gt;, author: &lt;/span&gt;&lt;span&gt;"neil &amp;#x3C;neil@dolthub.com&gt;"&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  commitId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'22gvmftrbf995mn924hl0ounoo4quhqh'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  message&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'update Alice on main'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  author&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  timestamp&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:28:51.139Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  committer&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  committerTimestamp&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:28:51.139Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To recap: We’ve updated Alice’s phone number to “555-4321” on the &lt;code&gt;feature&lt;/code&gt; branch, and “555-9999” on the &lt;code&gt;main&lt;/code&gt; branch. We can see the differences between the two branches with &lt;code&gt;dumboDiff&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({ dumboDiff: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, from: &lt;/span&gt;&lt;span&gt;"main"&lt;/span&gt;&lt;span&gt;, to: &lt;/span&gt;&lt;span&gt;"feature"&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  collections&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      name: &lt;/span&gt;&lt;span&gt;'customers'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      status: &lt;/span&gt;&lt;span&gt;'modified'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      added: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      removed: [],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      modified: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          _id: &lt;/span&gt;&lt;span&gt;ObjectId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'69fbcb932a4aeea4bc4de9b5'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          diff: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;            { type: &lt;/span&gt;&lt;span&gt;'modified'&lt;/span&gt;&lt;span&gt;, path: &lt;/span&gt;&lt;span&gt;'$.phone'&lt;/span&gt;&lt;span&gt;, from: &lt;/span&gt;&lt;span&gt;'555-9999'&lt;/span&gt;&lt;span&gt;, to: &lt;/span&gt;&lt;span&gt;'555-4321'&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          ]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is just a flat diff between the branches, but we know that they have a common ancestor with a third value for Alice’s phone number. When we attempt to merge the &lt;code&gt;feature&lt;/code&gt; branch into &lt;code&gt;main&lt;/code&gt;, we will get a merge conflict, because the same field was modified in both branches. DumboDB will give us the details of the merge conflict, so that we can resolve it:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({dumboMerge: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     merge_in: &lt;/span&gt;&lt;span&gt;"feature"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     message: &lt;/span&gt;&lt;span&gt;"merge in feature branch"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     author: &lt;/span&gt;&lt;span&gt;"neil &amp;#x3C;neil@dolthub.com&gt;"&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;MongoServerError&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;dumboMerge&lt;/span&gt;&lt;span&gt;: unresolved conflicts &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;(s)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We got the merge conflict, as expected. To make sense of what happened, we can run the &lt;code&gt;dumboConflicts&lt;/code&gt; command:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({dumboConflicts: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  collections&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      collection: &lt;/span&gt;&lt;span&gt;'customers'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      conflicts: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          conflictId: &lt;/span&gt;&lt;span&gt;'1I7p9HPnc+ff2JXl+sLqgw'&lt;/span&gt;&lt;span&gt;,          &lt;/span&gt;&lt;span&gt;// Unique identifier for this specific conflict.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          _id: &lt;/span&gt;&lt;span&gt;ObjectId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'69fbcb932a4aeea4bc4de9b5'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          base: { name: &lt;/span&gt;&lt;span&gt;'Alice'&lt;/span&gt;&lt;span&gt;, phone: &lt;/span&gt;&lt;span&gt;'555-1234'&lt;/span&gt;&lt;span&gt; },    &lt;/span&gt;&lt;span&gt;// Original value.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          ours: { name: &lt;/span&gt;&lt;span&gt;'Alice'&lt;/span&gt;&lt;span&gt;, phone: &lt;/span&gt;&lt;span&gt;'555-9999'&lt;/span&gt;&lt;span&gt; },    &lt;/span&gt;&lt;span&gt;// Value on the main branch (ours)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          theirs: { name: &lt;/span&gt;&lt;span&gt;'Alice'&lt;/span&gt;&lt;span&gt;, phone: &lt;/span&gt;&lt;span&gt;'555-4321'&lt;/span&gt;&lt;span&gt; },  &lt;/span&gt;&lt;span&gt;// Value on the feature branch (theirs)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          ourDiffType: &lt;/span&gt;&lt;span&gt;'modified'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;          theirDiffType: &lt;/span&gt;&lt;span&gt;'modified'&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can resolve the conflict with the &lt;code&gt;dumboResolveConflict&lt;/code&gt; command. We have three options to resolve the conflict: we can choose either “ours” or “theirs”, or we can provide a custom resolution. For this example, we’ll choose a custom resolution, where we set Alice’s phone number to “555-0000”:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({dumboResolveConflict: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     collection: &lt;/span&gt;&lt;span&gt;"customers"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     conflictId: &lt;/span&gt;&lt;span&gt;"1I7p9HPnc+ff2JXl+sLqgw"&lt;/span&gt;&lt;span&gt;,    &lt;/span&gt;&lt;span&gt;// Unique identifier from above. required.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     resolution: &lt;/span&gt;&lt;span&gt;"custom"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     value: { name: &lt;/span&gt;&lt;span&gt;'Alice'&lt;/span&gt;&lt;span&gt;, phone: &lt;/span&gt;&lt;span&gt;'555-0000'&lt;/span&gt;&lt;span&gt; }})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{ &lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;// dumboStatus prints merge state:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({dumboStatus: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  branch&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  dirty&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  readonly&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  collections&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      name: &lt;/span&gt;&lt;span&gt;'customers'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      status: &lt;/span&gt;&lt;span&gt;'modified'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      added: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      modified: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      deleted: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  mergeState&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'merge'&lt;/span&gt;&lt;span&gt;,  &lt;/span&gt;&lt;span&gt;// Currently in the middle of a merge.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  conflicts&lt;/span&gt;&lt;span&gt;: [],        &lt;/span&gt;&lt;span&gt;// No more conflicts, because we resolved the only conflict.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;// Complete the merge with the `continue` flag on the dumboMerge command.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({dumboMerge: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     continue: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     message: &lt;/span&gt;&lt;span&gt;"merge in feature branch"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                     author: &lt;/span&gt;&lt;span&gt;"neil &amp;#x3C;neil@dolthub.com&gt;"&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  commitId&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'7iraa088995v304n61egkm45dcge2a78'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  message&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'merge in feature branch'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  author&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  timestamp&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:59:11.995Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  committer&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  committerTimestamp&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:59:11.995Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, you can use the &lt;code&gt;dumboLog&lt;/code&gt; command to see the history of commits on the &lt;code&gt;main&lt;/code&gt; branch, including the merge commit we just made:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="javascript"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;mydb&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; db.&lt;/span&gt;&lt;span&gt;runCommand&lt;/span&gt;&lt;span&gt;({dumboLog: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  commits&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      commitId: &lt;/span&gt;&lt;span&gt;'7iraa088995v304n61egkm45dcge2a78'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      refs: [ &lt;/span&gt;&lt;span&gt;'HEAD'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt; ],                               &lt;/span&gt;&lt;span&gt;// refs tell you which branches or tags are pointing to this commit.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      parent1: &lt;/span&gt;&lt;span&gt;'22gvmftrbf995mn924hl0ounoo4quhqh'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      parent2: &lt;/span&gt;&lt;span&gt;'p7p99vndl9d11hjloivlu1lcuvt3n9qa'&lt;/span&gt;&lt;span&gt;,            &lt;/span&gt;&lt;span&gt;// Second parent because this is a merge commit!&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      message: &lt;/span&gt;&lt;span&gt;'merge in feature branch'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      timestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:59:11.980Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      author: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committer: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committerTimestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:59:11.980Z'&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      commitId: &lt;/span&gt;&lt;span&gt;'22gvmftrbf995mn924hl0ounoo4quhqh'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      parent1: &lt;/span&gt;&lt;span&gt;'9t4t592jqddgj1elcfnaal7c8o6boj26'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      message: &lt;/span&gt;&lt;span&gt;'update Alice on main'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      timestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:28:51.139Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      author: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committer: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committerTimestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:28:51.139Z'&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      commitId: &lt;/span&gt;&lt;span&gt;'p7p99vndl9d11hjloivlu1lcuvt3n9qa'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      refs: [ &lt;/span&gt;&lt;span&gt;'feature'&lt;/span&gt;&lt;span&gt; ],                                 &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      parent1: &lt;/span&gt;&lt;span&gt;'9t4t592jqddgj1elcfnaal7c8o6boj26'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      message: &lt;/span&gt;&lt;span&gt;"Update Alice's phone number"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      timestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:27:52.848Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      author: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committer: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committerTimestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:27:52.848Z'&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      commitId: &lt;/span&gt;&lt;span&gt;'9t4t592jqddgj1elcfnaal7c8o6boj26'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      parent1: &lt;/span&gt;&lt;span&gt;'6h1nv5qcnkesp3ahg5vn7shp6airkkn7'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      message: &lt;/span&gt;&lt;span&gt;'Add customers collection with Alice and Bob'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      timestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:16:04.348Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      author: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committer: &lt;/span&gt;&lt;span&gt;'neil &amp;#x3C;neil@dolthub.com&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committerTimestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:16:04.348Z'&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      commitId: &lt;/span&gt;&lt;span&gt;'6h1nv5qcnkesp3ahg5vn7shp6airkkn7'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      message: &lt;/span&gt;&lt;span&gt;'Initialize database'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      timestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:15:31.054Z'&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      author: &lt;/span&gt;&lt;span&gt;'dumbodb &amp;#x3C;dumbodb@dumbodb&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committer: &lt;/span&gt;&lt;span&gt;'dumbodb &amp;#x3C;dumbodb@dumbodb&gt;'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      committerTimestamp: &lt;/span&gt;&lt;span&gt;ISODate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'2026-05-06T23:15:31.054Z'&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ok&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;dumboLog&lt;/code&gt; command is not very flexible yet, but you can see a summary of the documents changed with the &lt;code&gt;stat&lt;/code&gt; flag, and the full diff of each with the &lt;code&gt;patch&lt;/code&gt; flag. Both are inspired by the &lt;code&gt;git log&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;To read the specifics of each command, see the &lt;a href="https://github.com/dolthub/dumbodb/wiki/Commands"&gt;documentation&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id="roadmap"&gt;Roadmap&lt;a class="anchor-link" aria-label="Link to heading" href="#roadmap"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are plenty of ways we can expand this product’s features, and we are just at the beginning. Here is our current rough roadmap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;v0.2&lt;/strong&gt;: Garbage Collection and zstd compression. Reduce the footprint of your database. Simplified configuration for user details (name and email) so you don’t have to specify them on every commit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v0.3&lt;/strong&gt;: Add Clone, Push, and Pull support. This will allow you to sync your DumboDB repositories with remote servers, and collaborate with others.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v0.4&lt;/strong&gt;: Add support for Replication (as a secondary backup to your existing MongoDB instance).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v0.5&lt;/strong&gt;: Isolated Session and Transaction support.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v0.6&lt;/strong&gt;: Add Authentication and Authorization support.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v0.7&lt;/strong&gt;: Add MCP server support, allowing you to use agents to work with the DumboDB database.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v0.8&lt;/strong&gt;: Visualization and operations via a custom Workbench UI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;v1.0&lt;/strong&gt;: General availability release, with a focus on stability, performance, and usability improvements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No dates are assigned on any of this, mainly because we will invest our engineering resources in balance with the other DoltHub products. We’ll go faster if you bang on our doors!&lt;/p&gt;
&lt;h2 id="call-to-action"&gt;Call to Action!&lt;a class="anchor-link" aria-label="Link to heading" href="#call-to-action"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here at &lt;a href="https://www.dolthub.com/"&gt;DoltHub&lt;/a&gt;, we strongly believe in the power of version-controlled databases. Users have told us for a long time that a NoSQL option would appeal to them, and now we have one! Real-world usage and feedback is the surest way to make sure we are building the right features. For that, we require your help. If you are interested in this space (you must be because you read this far), try DumboDB out and tell us what needs to be improved, extended, thrown out, etc. We want to hear from you!&lt;/p&gt;
&lt;p&gt;Want to impact the future of DumboDB? Join us on &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;Discord&lt;/a&gt;!&lt;/p&gt;</content:encoded>
      <dc:creator>Neil Macneale</dc:creator>
      <category>dumbo</category>
      <category>feature release</category>
    </item>
    <item>
      <title>Announcing Azure Private Link Support for Hosted Dolt</title>
      <link>https://dolthub.com/blog/2026-05-06-azure-private-link-networking/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-05-06-azure-private-link-networking/</guid>
      <description>Hosted Dolt now supports Azure Private Link. You can create a new Hosted Dolt instance on Azure with Private Link support in just a few clicks.</description>
      <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;&lt;a href="https://hosted.doltdb.com"&gt;Hosted Dolt&lt;/a&gt; is a fully managed &lt;a href="https://doltdb.com"&gt;Dolt&lt;/a&gt; deployment available on AWS, GCP,
and, most recently, &lt;a href="https://www.dolthub.com/blog/2026-04-13-hosted-dolt-on-azure/"&gt;Azure&lt;/a&gt;. The initial offering of
&lt;a href="https://hosted.doltdb.com"&gt;Hosted Dolt&lt;/a&gt; on Azure only supported publicly accessible deployments. Today we are excited to
announce the same level of private networking support for Azure that we already have for AWS and GCP.&lt;/p&gt;
&lt;h1 id="what-is-azure-private-link"&gt;What is Azure Private Link?&lt;a class="anchor-link" aria-label="Link to heading" href="#what-is-azure-private-link"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/private-link/"&gt;Azure Private Link&lt;/a&gt; is a service that allows you to access VNets
in other Azure subscriptions and tenants securely through Azure’s network. This means that you can create a
&lt;a href="https://hosted.doltdb.com"&gt;Hosted Dolt&lt;/a&gt; deployment on Azure that is only accessible to your private Azure infrastructure,
and not accessible over the public internet.&lt;/p&gt;
&lt;h1 id="creating-a-deployment-with-azure-private-link"&gt;Creating a Deployment with Azure Private Link&lt;a class="anchor-link" aria-label="Link to heading" href="#creating-a-deployment-with-azure-private-link"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The first thing you will need to do is get the subscription ID of the Azure subscription that you want to use for your
private network (You can find this in the Azure portal). Once you have the subscription ID, create a new
&lt;a href="https://hosted.doltdb.com"&gt;Hosted Dolt&lt;/a&gt; deployment on Azure and enable the “Private deployment” option on the “Advanced”
tab of the deployment creation form. Then in the “Allowed subscription IDs” box enter the subscription ID(s) that you
want to allow access to your deployment.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/azpl-private-deployment.png/3f91ea8acc2765d125f344103f351d837be35af7358f3bab29ecd5d149f65246.webp" alt="Private Deployment"&gt;&lt;/p&gt;
&lt;p&gt;Once you have that filled out, click “Next” and review your deployment choices. Finally, click “Create Deployment” and
your instance will be up and running in minutes. Once your deployment is running, you will see the connections tab populated.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/azpl-connections-tab.png/ea3fe6603afd7178aa0b2c6c6888803c860d335ba81f4fa2dd79e27bb675b3a3.webp" alt="Connections Tab"&gt;&lt;/p&gt;
&lt;p&gt;And the “Azure Private Link Networking” section of the connections tab will show you the information you will need to
connect your private Azure infrastructure to your &lt;a href="https://hosted.doltdb.com"&gt;Hosted Dolt&lt;/a&gt; deployment.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/azpl-azure-private-link-networking.png/0d99904e90b1c2937de67f46bd6ffc0be0976d3578631a5aa793554f612576ca.webp" alt="Azure Private Link Networking"&gt;&lt;/p&gt;
&lt;h1 id="connecting-to-your-private-deployment"&gt;Connecting to your Private Deployment&lt;a class="anchor-link" aria-label="Link to heading" href="#connecting-to-your-private-deployment"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;By taking the information from the “Azure Private Link Networking” section of the connections tab, you can connect
your private Azure infrastructure using the web portal, Azure CLI, or you could use Terraform. I won’t go through
the web portal, but I will cover the Azure CLI and Terraform options.&lt;/p&gt;
&lt;h2 id="connecting-your-infrastructure-with-the-azure-cli"&gt;Connecting your Infrastructure with the Azure CLI&lt;a class="anchor-link" aria-label="Link to heading" href="#connecting-your-infrastructure-with-the-azure-cli"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order to connect your infrastructure you will need the region, resource group, virtual network, and subnet of the
private network that you want to connect to your deployment.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"my-resource-group"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;REGION&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"eastus2"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;VNET&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"my-vnet"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SUBNET&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"my-subnet"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then we will take the information from the “Azure Private Link Networking” section of the connections tab&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;PRIVATE_LINK_SERVICE_ID&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"/subscriptions/01234567-89ab-cdef-fedc-ba9876543210/resourceGroups/networking-dev/providers/Microsoft.Network/privateLinkServices/pls-01234567-89ab-cdef-fedc-ba9876543210"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"test-az-priv"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;URL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"test-az-priv.pls.dbs.hosted.doltdb.com"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With that information you need to create an Azure “Private Endpoint” and then set up DNS resolution for the private
endpoint so that you can connect to your deployment using the url provided in the “Azure Private Link Networking” section
of the connections tab.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;# Create primary&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; private-endpoint&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --resource-group&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --name&lt;/span&gt;&lt;span&gt; "dolt-${&lt;/span&gt;&lt;span&gt;ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;}-private-endpoint"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --location&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$REGION&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --vnet-name&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$VNET&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --subnet&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$SUBNET&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --private-connection-resource-id&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$PRIVATE_LINK_SERVICE_ID&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --connection-name&lt;/span&gt;&lt;span&gt; "dolt-${&lt;/span&gt;&lt;span&gt;ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;}-connection"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Retrieve private IP from the endpoint NIC&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;PE_NIC_ID&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; private-endpoint&lt;/span&gt;&lt;span&gt; show&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --resource-group&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --name&lt;/span&gt;&lt;span&gt; "dolt-${&lt;/span&gt;&lt;span&gt;ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;}-private-endpoint"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --query&lt;/span&gt;&lt;span&gt; "networkInterfaces[0].id"&lt;/span&gt;&lt;span&gt; -o&lt;/span&gt;&lt;span&gt; tsv&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;PE_IP&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; nic&lt;/span&gt;&lt;span&gt; show&lt;/span&gt;&lt;span&gt; --ids&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$PE_NIC_ID&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --query&lt;/span&gt;&lt;span&gt; "ipConfigurations[0].privateIPAddress"&lt;/span&gt;&lt;span&gt; -o&lt;/span&gt;&lt;span&gt; tsv&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Create DNS zone and VNet link&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt; az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; private-dns&lt;/span&gt;&lt;span&gt; zone&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --resource-group&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --name&lt;/span&gt;&lt;span&gt; "pls.dbs.hosted.doltdb.com"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; private-dns&lt;/span&gt;&lt;span&gt; link&lt;/span&gt;&lt;span&gt; vnet&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --resource-group&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --zone-name&lt;/span&gt;&lt;span&gt; "pls.dbs.hosted.doltdb.com"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --name&lt;/span&gt;&lt;span&gt; "dolt-${&lt;/span&gt;&lt;span&gt;ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;}-vnet-link"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --virtual-network&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$VNET&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --registration-enabled&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Register primary DNS&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; private-dns&lt;/span&gt;&lt;span&gt; record-set&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt; add-record&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --resource-group&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --zone-name&lt;/span&gt;&lt;span&gt; "pls.dbs.hosted.doltdb.com"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --record-set-name&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --ipv4-address&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$PE_IP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you should be able to connect to your deployment from your instances within the given VNet using the provided URL. If
you SSH onto one of your instances with the MySQL client installed, you can connect to your deployment using the MySQL
command provided on the “Connections” tab of your deployment.&lt;/p&gt;
&lt;p&gt;The process for connecting a read endpoint is very similar if you are using replication.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;READ_PRIVATE_LINK_SERVICE_ID&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"/subscriptions/01234567-89ab-cdef-fedc-ba9876543210/resourceGroups/networking-dev/providers/Microsoft.Network/privateLinkServices/pls-read-01234567-89ab-cdef-fedc-ba9876543210"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;READ_ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"read-test-az-priv"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;READ_URL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"read-test-az-priv.pls.dbs.hosted.doltdb.com"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; private-endpoint&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --resource-group&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --name&lt;/span&gt;&lt;span&gt; "dolt-${&lt;/span&gt;&lt;span&gt;READ_ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;}-private-endpoint"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --location&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$REGION&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --vnet-name&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$VNET&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --subnet&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$SUBNET&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --private-connection-resource-id&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$READ_PRIVATE_LINK_SERVICE_ID&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --connection-name&lt;/span&gt;&lt;span&gt; "dolt-${&lt;/span&gt;&lt;span&gt;READ_ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;}-connection"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;READ_PE_NIC_ID&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; private-endpoint&lt;/span&gt;&lt;span&gt; show&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --resource-group&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --name&lt;/span&gt;&lt;span&gt; "dolt-${&lt;/span&gt;&lt;span&gt;READ_ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;}-private-endpoint"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --query&lt;/span&gt;&lt;span&gt; "networkInterfaces[0].id"&lt;/span&gt;&lt;span&gt; -o&lt;/span&gt;&lt;span&gt; tsv&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;READ_PE_IP&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;$(&lt;/span&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; nic&lt;/span&gt;&lt;span&gt; show&lt;/span&gt;&lt;span&gt; --ids&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$READ_PE_NIC_ID&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --query&lt;/span&gt;&lt;span&gt; "ipConfigurations[0].privateIPAddress"&lt;/span&gt;&lt;span&gt; -o&lt;/span&gt;&lt;span&gt; tsv&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;az&lt;/span&gt;&lt;span&gt; network&lt;/span&gt;&lt;span&gt; private-dns&lt;/span&gt;&lt;span&gt; record-set&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt; add-record&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --resource-group&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$RESOURCE_GROUP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --zone-name&lt;/span&gt;&lt;span&gt; "pls.dbs.hosted.doltdb.com"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --record-set-name&lt;/span&gt;&lt;span&gt; "${&lt;/span&gt;&lt;span&gt;READ_ENDPOINT_NAME&lt;/span&gt;&lt;span&gt;}"&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    --ipv4-address&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;$READ_PE_IP&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="terraform"&gt;Terraform&lt;a class="anchor-link" aria-label="Link to heading" href="#terraform"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The same thing can be accomplished with Terraform.  Here is an example Terraform configuration that will create a private
endpoint and set up DNS resolution for that endpoint. The “Variables” section of the configuration should be filled out
with the appropriate values for your deployment and private network. Many of these values may come from the output of other
Terraform configurations that manage your Azure infrastructure, or you could just fill them out manually.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="hcl"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;terraform&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  required_providers&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    azurerm&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      source  &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; "hashicorp/azurerm"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      version &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; "~&gt; 3.0"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;provider&lt;/span&gt;&lt;span&gt; "azurerm"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  features&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Variables&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; "resource_group"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  type&lt;/span&gt;&lt;span&gt;        =&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; "Azure resource group to create the private endpoints in"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; "region"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  type&lt;/span&gt;&lt;span&gt;        =&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; "Azure region (e.g. eastus)"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; "vnet"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  type&lt;/span&gt;&lt;span&gt;        =&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; "Name of the VNet to attach the private endpoints to"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; "subnet"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  type&lt;/span&gt;&lt;span&gt;        =&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; "Name of the subnet within the VNet for the private endpoints"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; "endpoint_name"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  type&lt;/span&gt;&lt;span&gt;        =&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; "Hosted Dolt endpoint name (used to name Azure resources and DNS records)"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; "read_endpoint_name"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  type&lt;/span&gt;&lt;span&gt;        =&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; "Hosted Dolt read endpoint name (used to name Azure resources and DNS records)"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; "private_link_service_id"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  type&lt;/span&gt;&lt;span&gt;        =&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; "Resource ID of the primary Private Link Service"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;variable&lt;/span&gt;&lt;span&gt; "read_private_link_service_id"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  type&lt;/span&gt;&lt;span&gt;        =&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; "Resource ID of the read-replica Private Link Service"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Data sources&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; "azurerm_subnet"&lt;/span&gt;&lt;span&gt; "endpoint_subnet"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  name&lt;/span&gt;&lt;span&gt;                 =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;subnet&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  virtual_network_name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;vnet&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  resource_group_name&lt;/span&gt;&lt;span&gt;  =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resource_group&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Private endpoints&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;resource&lt;/span&gt;&lt;span&gt; "azurerm_private_endpoint"&lt;/span&gt;&lt;span&gt; "primary"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  name&lt;/span&gt;&lt;span&gt;                =&lt;/span&gt;&lt;span&gt; "dolt-&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;endpoint_name&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;-private-endpoint"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  location&lt;/span&gt;&lt;span&gt;            =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;region&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  resource_group_name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resource_group&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  subnet_id&lt;/span&gt;&lt;span&gt;           =&lt;/span&gt;&lt;span&gt; data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;azurerm_subnet&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;endpoint_subnet&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  private_service_connection&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span&gt;                              =&lt;/span&gt;&lt;span&gt; "dolt-&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;endpoint_name&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;-connection"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    private_connection_resource_id&lt;/span&gt;&lt;span&gt;    =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;private_link_service_id&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    is_manual_connection&lt;/span&gt;&lt;span&gt;              =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;resource&lt;/span&gt;&lt;span&gt; "azurerm_private_endpoint"&lt;/span&gt;&lt;span&gt; "read"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  name&lt;/span&gt;&lt;span&gt;                =&lt;/span&gt;&lt;span&gt; "dolt-&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;read_endpoint_name&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;-private-endpoint"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  location&lt;/span&gt;&lt;span&gt;            =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;region&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  resource_group_name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resource_group&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  subnet_id&lt;/span&gt;&lt;span&gt;           =&lt;/span&gt;&lt;span&gt; data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;azurerm_subnet&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;endpoint_subnet&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  private_service_connection&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span&gt;                              =&lt;/span&gt;&lt;span&gt; "dolt-&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;read_endpoint_name&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;-connection"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    private_connection_resource_id&lt;/span&gt;&lt;span&gt;    =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;read_private_link_service_id&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    is_manual_connection&lt;/span&gt;&lt;span&gt;              =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Private DNS zone and VNet link&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;resource&lt;/span&gt;&lt;span&gt; "azurerm_private_dns_zone"&lt;/span&gt;&lt;span&gt; "dolt"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  name&lt;/span&gt;&lt;span&gt;                =&lt;/span&gt;&lt;span&gt; "pls.dbs.hosted.doltdb.com"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  resource_group_name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resource_group&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;resource&lt;/span&gt;&lt;span&gt; "azurerm_private_dns_zone_virtual_network_link"&lt;/span&gt;&lt;span&gt; "dolt"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  name&lt;/span&gt;&lt;span&gt;                  =&lt;/span&gt;&lt;span&gt; "dolt-&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;endpoint_name&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;-vnet-link"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  resource_group_name&lt;/span&gt;&lt;span&gt;   =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resource_group&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  private_dns_zone_name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; azurerm_private_dns_zone&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dolt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  virtual_network_id&lt;/span&gt;&lt;span&gt;    =&lt;/span&gt;&lt;span&gt; data&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;azurerm_subnet&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;endpoint_subnet&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;virtual_network_id&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  registration_enabled&lt;/span&gt;&lt;span&gt;  =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# DNS A records&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# ---------------------------------------------------------------------------&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;resource&lt;/span&gt;&lt;span&gt; "azurerm_private_dns_a_record"&lt;/span&gt;&lt;span&gt; "primary"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  name&lt;/span&gt;&lt;span&gt;                =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;endpoint_name&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  zone_name&lt;/span&gt;&lt;span&gt;           =&lt;/span&gt;&lt;span&gt; azurerm_private_dns_zone&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dolt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  resource_group_name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resource_group&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ttl&lt;/span&gt;&lt;span&gt;                 =&lt;/span&gt;&lt;span&gt; 300&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  records&lt;/span&gt;&lt;span&gt;             =&lt;/span&gt;&lt;span&gt; [azurerm_private_endpoint&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;primary&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;private_service_connection[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;private_ip_address]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;resource&lt;/span&gt;&lt;span&gt; "azurerm_private_dns_a_record"&lt;/span&gt;&lt;span&gt; "read"&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  name&lt;/span&gt;&lt;span&gt;                =&lt;/span&gt;&lt;span&gt; "&lt;/span&gt;&lt;span&gt;${&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;read_endpoint_name&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  zone_name&lt;/span&gt;&lt;span&gt;           =&lt;/span&gt;&lt;span&gt; azurerm_private_dns_zone&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dolt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  resource_group_name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; var&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;resource_group&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  ttl&lt;/span&gt;&lt;span&gt;                 =&lt;/span&gt;&lt;span&gt; 300&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  records&lt;/span&gt;&lt;span&gt;             =&lt;/span&gt;&lt;span&gt; [azurerm_private_endpoint&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;read&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;private_service_connection[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;private_ip_address]&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;a class="anchor-link" aria-label="Link to heading" href="#conclusion"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://hosted.doltdb.com"&gt;Hosted Dolt&lt;/a&gt; now supports Azure Private Link. You can create a new &lt;a href="https://hosted.doltdb.com"&gt;Hosted Dolt&lt;/a&gt;
deployment on Azure with Private Link support in just a few clicks. If you have any questions about using &lt;a href="https://hosted.doltdb.com"&gt;Hosted Dolt&lt;/a&gt;
on Azure, or any other cloud provider, or if you have feedback or feature requests, please join our &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;Discord&lt;/a&gt; and let us know.&lt;/p&gt;</content:encoded>
      <dc:creator>Brian Hendriks</dc:creator>
      <category>hosted</category>
      <category>feature release</category>
    </item>
    <item>
      <title>Database Insurance</title>
      <link>https://dolthub.com/blog/2026-05-04-database-insurance/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-05-04-database-insurance/</guid>
      <description>Use a Dolt replica for database insurance against catastrophe or more mundane bad writes. In the human operator era, a Dolt replica was nice to have. In the agentic operator era, a Dolt replica is essential.</description>
      <pubDate>Mon, 04 May 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;Did you know &lt;a href="https://www.doltdb.com"&gt;Dolt&lt;/a&gt; and &lt;a href="https://www.doltgres.com"&gt;Doltgres&lt;/a&gt; can be &lt;a href="https://www.dolthub.com/blog/2023-03-15-getting-started-versioned-mysql-replica/"&gt;run as replicas&lt;/a&gt; to your existing MySQL, MariaDB, or Postgres databases? In this mode, Dolt acts as database insurance. Each transaction commit on your primary becomes a Dolt commit on your replica, preserving the history of your database in Dolt. You can use Dolt’s version control functionality on your replica for &lt;a href="https://www.dolthub.com/blog/2022-09-23-dolt-rollback-options/"&gt;all manner of rollback&lt;/a&gt;, including complex reverse patches of multiple transactions.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/this-is-fine.png/61736ebe94d4d0c9b65b8a311b6b4af5637c8c844953d5c95e4445049f7b0f28.webp" alt="Dolt. This is fine."&gt;&lt;/p&gt;
&lt;p&gt;Database insurance is becoming all the more important with the threat of agents going off the rails. It seems like not a month goes by without another “an agent deleted my database” story. Dolt can protect you from rogue agents without switching out your primary. Just add a Dolt replica. This article explains.&lt;/p&gt;
&lt;h1 id="agents-delete-databases"&gt;Agents Delete Databases&lt;a class="anchor-link" aria-label="Link to heading" href="#agents-delete-databases"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is no longer hypothetical. Agents delete databases.&lt;/p&gt;
&lt;p&gt;Last week, &lt;a href="https://www.tomshardware.com/tech-industry/artificial-intelligence/claude-powered-ai-coding-agent-deletes-entire-company-database-in-9-seconds-backups-zapped-after-cursor-tool-powered-by-anthropics-claude-goes-rogue"&gt;Pocket’s Claude-powered coding agent turned a staging task into a production incident&lt;/a&gt;. It deleted the company database and the attached backups in one shot. This is the cleanest possible example of the new failure mode: give an agent broad infra access and eventually it will speedrun your disaster recovery plan.&lt;/p&gt;
&lt;p&gt;In March, Alexey Grigorev asked Claude to help clean up AWS resources and &lt;a href="https://alexeyondata.substack.com/p/how-i-dropped-our-production-database"&gt;got an unexpected terraform destroy adventure instead&lt;/a&gt;. Production database gone. Snapshots gone. Support upgraded mid-incident. It reads like a normal ops postmortem except the culprit was an agent with cloud credentials.&lt;/p&gt;
&lt;p&gt;And in July last year, &lt;a href="https://www.pcmag.com/news/vibe-coding-fiasco-replite-ai-agent-goes-rogue-deletes-company-database"&gt;after Replit’s agent deleted a database&lt;/a&gt;, Replit’s CEO said the lesson was that agents should not have access to production databases. Fair enough. But is that achievable? Agents are going to find their way into production workflows, whether through direct SQL, admin tools, or application APIs. The practical question is not whether mistakes will happen but rather how much damage is done when they do.&lt;/p&gt;
&lt;p&gt;These stories get attention because they are spectacular. “Entire company database deleted in nine seconds” is a headline. But the underlying issue is not new. Any tool, human- or agent-driven, that has production credentials, broad access, and enough autonomy to make a lot of changes very quickly is dangerous.&lt;/p&gt;
&lt;p&gt;Databases were already at-risk. Agents just increased the blast radius.&lt;/p&gt;
&lt;p&gt;The old production failure mode was a tired human typing &lt;code&gt;DROP TABLE&lt;/code&gt; into the wrong terminal. The new production failure mode is an enthusiastic agent with API keys, shell access, a task list, and a limited context window.&lt;/p&gt;
&lt;h1 id="agents-write-junk"&gt;Agents Write Junk&lt;a class="anchor-link" aria-label="Link to heading" href="#agents-write-junk"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Outright deletion is the catastrophe case. It is easy to notice. It makes the news. Much more common is quiet failure when an agent writes junk to production.&lt;/p&gt;
&lt;p&gt;Maybe it backfills the wrong values. Maybe it misinterprets a schema. Maybe it “fixes” a bug by overwriting a field everywhere. Maybe it makes a long sequence of individually valid writes that are collectively nonsense. In many cases the agent is not even talking SQL directly. It is calling your production API, which is often worse because the damage looks like legitimate application traffic. I would guess for every “the agent deleted my database” story, there are hundreds of “the agent wrote bad data into production” stories.&lt;/p&gt;
&lt;p&gt;A recent article on the subject, &lt;a href="https://arpitbhayani.me/blogs/defensive-databases/"&gt;“Databases Were Not Designed For This”&lt;/a&gt; by Arpit Bhayani, generated &lt;a href="https://news.ycombinator.com/item?id=47897140"&gt;a lively Hacker News discussion&lt;/a&gt;. Arpit’s point is that databases were built for boring callers: deterministic apps, reviewed writes, short-lived connections, obvious failures. Agents break every one of those assumptions at once, so a bunch of database hygiene practices that were once “nice to have” — statement timeouts, idempotency keys, soft deletes, append-only logs, role-per-agent, query tagging, the works — suddenly become load-bearing infrastructure. I think that framing is right. The database is no longer talking to careful application code but to an agent who must fix the issue before its context fills up.&lt;/p&gt;
&lt;p&gt;This is where normal backups start to feel insufficient. Backups are great for disaster recovery. They are less great for “between 2:13 PM and 2:21 PM, the agent wrote garbage into three related tables, and I need to surgically undo those writes specifically”.&lt;/p&gt;
&lt;p&gt;That is a version control problem, and Dolt is the world’s &lt;a href="https://www.dolthub.com/blog/2022-08-04-database-versioning/"&gt;first and only version-controlled database&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="protect-yourself"&gt;Protect Yourself&lt;a class="anchor-link" aria-label="Link to heading" href="#protect-yourself"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The easiest way to get database insurance is to run a Dolt replica on a separate host. You keep your existing primary. MySQL stays MySQL. MariaDB stays MariaDB. Postgres stays Postgres. Dolt or Doltgres sits downstream as a replica, ingesting &lt;code&gt;binlog&lt;/code&gt; or WAL changes and turning each committed transaction into a durable Dolt commit.&lt;/p&gt;
&lt;p&gt;Setup is the same basic shape as standard replication. No application rewrite. No cutover. No “replace your database with our database” project. Just add a replica.&lt;/p&gt;
&lt;p&gt;The result is useful immediately. You get:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A continuously updated copy of production.&lt;/li&gt;
&lt;li&gt;A commit history of every transaction.&lt;/li&gt;
&lt;li&gt;Diffs over time.&lt;/li&gt;
&lt;li&gt;Branches if you need to experiment.&lt;/li&gt;
&lt;li&gt;Rollback tools much more expressive than “restore last night’s backup”.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the pre-agent era, this was nice to have. With Claude and Codex in all your engineer’s hands, it looks more like a necessity.&lt;/p&gt;
&lt;h2 id="catastrophe"&gt;Catastrophe&lt;a class="anchor-link" aria-label="Link to heading" href="#catastrophe"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Backups are still your number one defense here. If a machine dies, a region disappears, or an attacker wipes out infrastructure, backups are what save you. A Dolt replica is defense in depth.&lt;/p&gt;
&lt;p&gt;It gives you another live copy of the database and a detailed transaction history. If your primary gets destroyed by a rogue agent, the Dolt replica can tell you exactly what happened and when. If you push that replica to DoltHub or another remote, you now have true off-host safety with different access credentials as well.&lt;/p&gt;
&lt;p&gt;This is the right layering:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Backups for disaster recovery.&lt;/li&gt;
&lt;li&gt;Replication for availability.&lt;/li&gt;
&lt;li&gt;Dolt replication for history, auditability, and surgical undo.&lt;/li&gt;
&lt;li&gt;Dolt remote as disaster recovery if all else fails.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You want all four.&lt;/p&gt;
&lt;h2 id="bad-writes"&gt;Bad Writes&lt;a class="anchor-link" aria-label="Link to heading" href="#bad-writes"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Bad writes are where a Dolt replica really shines.&lt;/p&gt;
&lt;p&gt;First, find the bad writes. Use &lt;a href="https://dolthub.com/docs/sql-reference/version-control/dolt-system-tables#dolt_log"&gt;&lt;code&gt;dolt_log&lt;/code&gt;&lt;/a&gt; to identify the suspicious time window or commit range. Use &lt;a href="https://dolthub.com/docs/sql-reference/version-control/dolt-sql-functions#dolt_diff"&gt;&lt;code&gt;dolt_diff()&lt;/code&gt;&lt;/a&gt; to inspect exactly what changed. Because the writes are preserved as commits, you are not guessing. You are looking at history.&lt;/p&gt;
&lt;p&gt;Then undo them on &lt;a href="https://dolthub.com/docs/sql-reference/version-control/branches"&gt;a branch&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sometimes a simple &lt;a href="https://dolthub.com/docs/sql-reference/version-control/dolt-sql-procedures#dolt_revert"&gt;&lt;code&gt;dolt_revert()&lt;/code&gt;&lt;/a&gt; is enough. Other times, you want to reverse a sequence of commits or a custom patch that keeps the good changes and removes only the bad ones. Dolt gives you those tools. Once you have the corrective patch, you can get the SQL you need to apply to your primary with &lt;a href="https://dolthub.com/docs/sql-reference/version-control/dolt-sql-functions#dolt_patch"&gt;&lt;code&gt;dolt_patch()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is a much better story than:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Restore backup to staging.&lt;/li&gt;
&lt;li&gt;Diff it manually against production.&lt;/li&gt;
&lt;li&gt;Write custom SQL.&lt;/li&gt;
&lt;li&gt;Hope you found all the bad rows.&lt;/li&gt;
&lt;li&gt;Hope you didn’t revert good writes too.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With Dolt, the database history is already organized into commits. That makes complex rollback possible.&lt;/p&gt;
&lt;p&gt;That is what “database insurance” means in practice. Not just “I have a copy somewhere”, but “I can understand what happened and undo it precisely”.&lt;/p&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;a class="anchor-link" aria-label="Link to heading" href="#conclusion"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Use a Dolt replica for database insurance against catastrophe or more mundane bad writes. In the human operator era, a Dolt replica was nice to have. In the agentic operator era, a Dolt replica is essential. Questions? Come by &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;our Discord&lt;/a&gt;. We’re happy to help get your replica set up.&lt;/p&gt;</content:encoded>
      <dc:creator>Tim Sehn</dc:creator>
      <category>dolt</category>
      <category>doltgres</category>
      <category>use case</category>
    </item>
    <item>
      <title>Announcing Functional Indexes in Dolt</title>
      <link>https://dolthub.com/blog/2026-04-29-announcing-functional-indexes-in-dolt/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-04-29-announcing-functional-indexes-in-dolt/</guid>
      <description>Dolt now supports functional indexes, allowing you to index expressions and function results for faster queries on computed values.</description>
      <pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;&lt;a href="https://doltdb.com/"&gt;Dolt&lt;/a&gt; is the world’s first SQL database with Git-style version control built in. Dolt gives you all the power of SQL combined with the ability to branch, merge, diff, clone, and push your data, just like you would with source code in Git. Today we’re excited to announce that Dolt now supports &lt;strong&gt;functional indexes&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Functional indexes have been part of &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/create-index.html#create-index-functional-key-parts"&gt;MySQL since MySQL 8.0&lt;/a&gt;. They’re not something every application needs, but when they are needed, they can have a &lt;strong&gt;big&lt;/strong&gt; impact on query performance, as we’ll see later in this post. This is a feature we’ve wanted to build for a long time, and after receiving a few customer requests for it, we decided to prioritize it. We’ve launched the initial support in Dolt and are now expanding that to add this feature to Doltgres, add additional syntax support, enable usage of the functional indexes in more queries, and fine tune performance.&lt;/p&gt;
&lt;p&gt;In this blog post, we’ll walk through what functional indexes are, how they work, how to use them, and see them in action.&lt;/p&gt;
&lt;h2 id="what-is-a-functional-index"&gt;What is a Functional Index?&lt;a class="anchor-link" aria-label="Link to heading" href="#what-is-a-functional-index"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A regular index stores the values of one or more columns and lets Dolt quickly look up rows by those raw column values. A functional index is similar, but instead of storing a column’s raw value, it stores the result of a function or expression applied to that column. That stored result is what gets indexed, so when a query contains the same expression in its &lt;code&gt;WHERE&lt;/code&gt; clause, Dolt can use the index to satisfy the query efficiently — without scanning the full table and evaluating the expression row by row.&lt;/p&gt;
&lt;p&gt;The syntax uses an extra set of parentheses to mark the expression:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; INDEX&lt;/span&gt;&lt;span&gt; idx_lower_email&lt;/span&gt;&lt;span&gt; ON&lt;/span&gt;&lt;span&gt; users ((&lt;/span&gt;&lt;span&gt;LOWER&lt;/span&gt;&lt;span&gt;(email)));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The double parentheses are important — that’s how MySQL and Dolt distinguish a functional expression from a regular column reference inside an index definition.&lt;/p&gt;
&lt;h2 id="when-does-this-help"&gt;When Does This Help?&lt;a class="anchor-link" aria-label="Link to heading" href="#when-does-this-help"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s look at a common scenario for functional indexes. Imagine you have a &lt;code&gt;users&lt;/code&gt; table and you want to look up users by email address, but you don’t want &lt;code&gt;User@Example.COM&lt;/code&gt; and &lt;code&gt;user@example.com&lt;/code&gt; to be treated as different entries. There are several ways to handle this, including normalizing values to lowercase when filtering on them.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; users &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; LOWER&lt;/span&gt;&lt;span&gt;(email) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; LOWER&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;'User@Example.COM'&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without a functional index on &lt;code&gt;LOWER(email)&lt;/code&gt;, satisfying that query requires a full table scan. The database engine has to evaluate &lt;code&gt;LOWER(email)&lt;/code&gt; for every single row and compare it against your search value. On a large table, that’s going to be slow.&lt;/p&gt;
&lt;p&gt;A functional index solves this cleanly, without requiring you to store a redundant &lt;code&gt;email_lower&lt;/code&gt; column purely for indexing purposes.&lt;/p&gt;
&lt;p&gt;Other common cases for using a functional index include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Date part extraction&lt;/strong&gt; — index on &lt;code&gt;YEAR(created_at)&lt;/code&gt; or &lt;code&gt;MONTH(order_date)&lt;/code&gt; for reporting queries that filter by year or month&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JSON path extraction&lt;/strong&gt; — index on &lt;code&gt;JSON_UNQUOTE(JSON_EXTRACT(metadata, '$.type'))&lt;/code&gt; to speed up queries on specific fields inside a JSON column&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;String transformations&lt;/strong&gt; — indexing trimmed or normalized versions of values without duplicating the data in an extra column&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="getting-started"&gt;Getting Started&lt;a class="anchor-link" aria-label="Link to heading" href="#getting-started"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let’s see functional indexes in action. We’ll use the &lt;a href="https://www.dolthub.com/repositories/dolthub/employees"&gt;dolthub/employees&lt;/a&gt; database from DoltHub — a sample database with 300,024 employees and 443,308 title records, which gives us enough data to see a real difference in query performance.&lt;/p&gt;
&lt;p&gt;If you don’t have Dolt yet, &lt;a href="https://dolthub.com/docs/introduction/installation"&gt;install it here&lt;/a&gt;. Then clone the database:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sh"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; clone&lt;/span&gt;&lt;span&gt; dolthub/employees&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; cd&lt;/span&gt;&lt;span&gt; employees&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From here, you can run &lt;code&gt;dolt sql&lt;/code&gt; to start a SQL shell:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sh"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; sql&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Welcome to the DoltSQL shell.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# Statements must be terminated with ';'.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;# "exit" or "quit" (or Ctrl-D) to exit. "\help" for help.&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;employees/main&lt;/span&gt;&lt;span&gt;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can start exploring the database:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; DESCRIBE employees;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;------------+---------------+------+-----+---------+-------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| Field      | &lt;/span&gt;&lt;span&gt;Type&lt;/span&gt;&lt;span&gt;          | &lt;/span&gt;&lt;span&gt;Null&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;Default&lt;/span&gt;&lt;span&gt; | Extra |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;------------+---------------+------+-----+---------+-------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| emp_no     | &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;           | &lt;/span&gt;&lt;span&gt;NO&lt;/span&gt;&lt;span&gt;   | PRI | &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;    |       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| birth_date | &lt;/span&gt;&lt;span&gt;date&lt;/span&gt;&lt;span&gt;          | &lt;/span&gt;&lt;span&gt;NO&lt;/span&gt;&lt;span&gt;   |     | &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;    |       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| first_name | &lt;/span&gt;&lt;span&gt;varchar&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;)   | &lt;/span&gt;&lt;span&gt;NO&lt;/span&gt;&lt;span&gt;   |     | &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;    |       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| last_name  | &lt;/span&gt;&lt;span&gt;varchar&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;)   | &lt;/span&gt;&lt;span&gt;NO&lt;/span&gt;&lt;span&gt;   |     | &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;    |       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| gender     | enum(&lt;/span&gt;&lt;span&gt;'M'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;'F'&lt;/span&gt;&lt;span&gt;) | &lt;/span&gt;&lt;span&gt;NO&lt;/span&gt;&lt;span&gt;   |     | &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;    |       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| hire_date  | &lt;/span&gt;&lt;span&gt;date&lt;/span&gt;&lt;span&gt;          | &lt;/span&gt;&lt;span&gt;NO&lt;/span&gt;&lt;span&gt;   |     | &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;    |       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;------------+---------------+------+-----+---------+-------+&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Out of the box, the only index is the primary key on &lt;code&gt;emp_no&lt;/code&gt;. There’s no index on &lt;code&gt;last_name&lt;/code&gt;. Suppose we want to find all employees by last name, but we need the search to be case-insensitive — the data was imported from multiple sources and the casing isn’t consistent. We write:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; emp_no, first_name, last_name &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employees &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; LOWER&lt;/span&gt;&lt;span&gt;(last_name) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 'facello'&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="without-a-functional-index"&gt;Without a Functional Index&lt;a class="anchor-link" aria-label="Link to heading" href="#without-a-functional-index"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s look at the query plan Dolt uses when there’s no index. We’ll use &lt;code&gt;EXPLAIN FORMAT=TREE&lt;/code&gt; which gives us Dolt’s detailed execution plan:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; EXPLAIN FORMAT&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;TREE &lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; emp_no, first_name, last_name &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employees &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; LOWER&lt;/span&gt;&lt;span&gt;(last_name) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 'facello'&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| plan                                                                       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| Project                                                                    |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  ├─ columns: [employees.emp_no, employees.first_name, employees.last_name] |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  └─ &lt;/span&gt;&lt;span&gt;Filter&lt;/span&gt;&lt;span&gt;                                                                 |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      ├─ (&lt;/span&gt;&lt;span&gt;lower&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;last_name&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 'facello'&lt;/span&gt;&lt;span&gt;)                           |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      └─ &lt;/span&gt;&lt;span&gt;Table&lt;/span&gt;&lt;span&gt;                                                              |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|          ├─ &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: employees                                                |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|          └─ columns: [emp_no first_name last_name]                         |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt; rows&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;00&lt;/span&gt;&lt;span&gt; sec) &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The plan is a Project of three columns, over a &lt;code&gt;Filter&lt;/code&gt; node on top of a full &lt;code&gt;Table&lt;/code&gt; scan. Dolt reads all 300,024 rows, evaluates &lt;code&gt;LOWER(last_name)&lt;/code&gt; on each one, and discards the ones that don’t match. Against 300K rows, on my Apple M1 Max laptop, this query takes about &lt;strong&gt;150ms&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="adding-the-functional-index"&gt;Adding the Functional Index&lt;a class="anchor-link" aria-label="Link to heading" href="#adding-the-functional-index"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now let’s create the functional index, using the same syntax we covered earlier:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; CREATE&lt;/span&gt;&lt;span&gt; INDEX&lt;/span&gt;&lt;span&gt; idx_lower_last_name &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;span&gt; employees ((&lt;/span&gt;&lt;span&gt;LOWER&lt;/span&gt;&lt;span&gt;(last_name)));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s look at the query plan for the same query and see if it’s different after creating a functional index on &lt;code&gt;LOWER(last_name)&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; EXPLAIN FORMAT&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;TREE &lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; emp_no, first_name, last_name &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employees &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; LOWER&lt;/span&gt;&lt;span&gt;(last_name) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 'facello'&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| plan                                                                       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| Project                                                                    |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  ├─ columns: [employees.emp_no, employees.first_name, employees.last_name] |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  └─ IndexedTableAccess(employees)                                          |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      ├─ &lt;/span&gt;&lt;span&gt;index&lt;/span&gt;&lt;span&gt;: [employees.!hidden!idx_lower_last_name!0!0]                 |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      └─ filters: [{[facello, facello]}]                                    |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt; rows&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;00&lt;/span&gt;&lt;span&gt; sec) &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The full table scan is gone. The plan now shows &lt;code&gt;IndexedTableAccess&lt;/code&gt; — Dolt goes directly to the index, seeks to the entries where the indexed expression equals &lt;code&gt;'facello'&lt;/code&gt;, and returns only those rows. The same query now takes &lt;strong&gt;under 2ms&lt;/strong&gt;, a &lt;strong&gt;~75x improvement&lt;/strong&gt; on a 300K row table.&lt;/p&gt;
&lt;p&gt;Indexed lookups into a large table are one of the areas where functional indexes can have a huge impact on query performance. Going from a full table scan to a direct lookup resulted in a 75x improvement for this query against 300k rows, and as the table gets bigger, the full table scan performance gets slower, while the indexed lookup performance remains constant, resulting in a larger and larger improvement.&lt;/p&gt;
&lt;h2 id="functional-indexes-in-joins"&gt;Functional Indexes in Joins&lt;a class="anchor-link" aria-label="Link to heading" href="#functional-indexes-in-joins"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The functional index doesn’t just speed up point lookups — it also improves queries where the filtered table is one side of a join. Let’s look at a query that finds the current job title for every employee with the last name ‘Facello’:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;first_name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;last_name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;from_date&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; emp_no, first_name, last_name &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employees &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; LOWER&lt;/span&gt;&lt;span&gt;(last_name) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 'facello'&lt;/span&gt;&lt;span&gt;) f&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;JOIN&lt;/span&gt;&lt;span&gt; titles t &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to_date&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; '9999-01-01'&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="without-the-index"&gt;Without the Index&lt;a class="anchor-link" aria-label="Link to heading" href="#without-the-index"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let’s start off by looking at the query plan for this query, just like we did earlier. To remove the index we just created on the &lt;code&gt;employees&lt;/code&gt; table, we can run:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; DROP&lt;/span&gt;&lt;span&gt; INDEX&lt;/span&gt;&lt;span&gt; idx_lower_last_name &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;span&gt; employees;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And here’s the query plan:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; EXPLAIN FORMAT&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;TREE&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;first_name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;last_name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;from_date&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    FROM&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; emp_no, first_name, last_name &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employees &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; LOWER&lt;/span&gt;&lt;span&gt;(last_name) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 'facello'&lt;/span&gt;&lt;span&gt;) f&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    JOIN&lt;/span&gt;&lt;span&gt; titles t &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    WHERE&lt;/span&gt;&lt;span&gt; t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to_date&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; '9999-01-01'&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;--------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| plan                                                                     |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;--------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| Project                                                                  |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  ├─ columns: [f.emp_no, f.first_name, f.last_name, t.title, t.from_date] |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  └─ LookupJoin                                                           |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      ├─ SubqueryAlias                                                    |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: f                                                      |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ outerVisibility: false                                       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ isLateral: false                                             |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ cacheable: true                                              |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ colSet: (&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;)                                                |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ tableId: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;                                                   |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   └─ &lt;/span&gt;&lt;span&gt;Filter&lt;/span&gt;&lt;span&gt;                                                       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │       ├─ (&lt;/span&gt;&lt;span&gt;lower&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;last_name&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 'facello'&lt;/span&gt;&lt;span&gt;)                 |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │       └─ &lt;/span&gt;&lt;span&gt;Table&lt;/span&gt;&lt;span&gt;                                                    |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │           ├─ &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: employees                                      |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │           └─ columns: [emp_no first_name last_name]               |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      └─ &lt;/span&gt;&lt;span&gt;Filter&lt;/span&gt;&lt;span&gt;                                                           |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|          ├─ (&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to_date&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; '9999-01-01'&lt;/span&gt;&lt;span&gt;)                                   |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|          └─ TableAlias(t)                                                |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|              └─ IndexedTableAccess(titles)                               |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|                  ├─ &lt;/span&gt;&lt;span&gt;index&lt;/span&gt;&lt;span&gt;: [titles.emp_no,titles.title,titles.from_date] |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|                  ├─ columns: [emp_no title from_date to_date]            |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|                  └─ keys: &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;span&gt;                                       |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;--------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt; rows&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;00&lt;/span&gt;&lt;span&gt; sec) &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The subquery on one side of the &lt;code&gt;LookupJoin&lt;/code&gt; does a full table scan of all 300K employees to find the Facello employees. Then, for each matching employee, it does a fast indexed lookup into the &lt;code&gt;titles&lt;/code&gt; table using the primary key. The bottleneck is that first full scan — the query runs in about &lt;strong&gt;150ms&lt;/strong&gt;. This is very similar performance to our first un-indexed query, which makes sense, because the most significant factor in the performance of both queries is the full table scan over the 300k items in the &lt;code&gt;employees&lt;/code&gt; table.&lt;/p&gt;
&lt;h3 id="with-the-index"&gt;With the Index&lt;a class="anchor-link" aria-label="Link to heading" href="#with-the-index"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Just like before, let’s create a functional index over &lt;code&gt;LOWER(last_name)&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; CREATE&lt;/span&gt;&lt;span&gt; INDEX&lt;/span&gt;&lt;span&gt; idx_lower_last_name &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;span&gt; employees ((&lt;/span&gt;&lt;span&gt;LOWER&lt;/span&gt;&lt;span&gt;(last_name)));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let’s look at the query plan:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;employees&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; EXPLAIN FORMAT&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;TREE&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;first_name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;last_name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;from_date&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    FROM&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; emp_no, first_name, last_name &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employees &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; LOWER&lt;/span&gt;&lt;span&gt;(last_name) &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 'facello'&lt;/span&gt;&lt;span&gt;) f&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    JOIN&lt;/span&gt;&lt;span&gt; titles t &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    WHERE&lt;/span&gt;&lt;span&gt; t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to_date&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; '9999-01-01'&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| plan                                                                                   |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| Project                                                                                |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  ├─ columns: [f.emp_no, f.first_name, f.last_name, t.title, t.from_date]               |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  └─ LookupJoin                                                                         |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      ├─ SubqueryAlias                                                                  |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: f                                                                    |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ outerVisibility: false                                                     |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ isLateral: false                                                           |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ cacheable: true                                                            |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ colSet: (&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;)                                                            |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   ├─ tableId: &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;                                                                 |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │   └─ Project                                                                    |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │       ├─ columns: [employees.emp_no, employees.first_name, employees.last_name] |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │       └─ IndexedTableAccess(employees)                                          |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │           ├─ &lt;/span&gt;&lt;span&gt;index&lt;/span&gt;&lt;span&gt;: [employees.!hidden!idx_lower_last_name!0!0]                 |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      │           └─ filters: [{[facello, facello]}]                                    |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|      └─ &lt;/span&gt;&lt;span&gt;Filter&lt;/span&gt;&lt;span&gt;                                                                         |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|          ├─ (&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;to_date&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; '9999-01-01'&lt;/span&gt;&lt;span&gt;)                                                 |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|          └─ TableAlias(t)                                                              |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|              └─ IndexedTableAccess(titles)                                             |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|                  ├─ &lt;/span&gt;&lt;span&gt;index&lt;/span&gt;&lt;span&gt;: [titles.emp_no,titles.title,titles.from_date]               |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|                  ├─ columns: [emp_no title from_date to_date]                          |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|                  └─ keys: &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_no&lt;/span&gt;&lt;span&gt;                                                     |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;----------------------------------------------------------------------------------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt; rows&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;00&lt;/span&gt;&lt;span&gt; sec) &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The join structure is identical — a &lt;code&gt;LookupJoin&lt;/code&gt; with a per-employee index seek into &lt;code&gt;titles&lt;/code&gt; — but now the employees side uses &lt;code&gt;IndexedTableAccess&lt;/code&gt; with the functional index instead of a full table scan. Dolt resolves only the 186 matching employees before doing any join work at all, which brings the query down to &lt;strong&gt;under 2ms&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here’s a sample of the results:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;--------+------------+-----------+------------------+------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| emp_no | first_name | last_name | title            | from_date  |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;--------+------------+-----------+------------------+------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;10001&lt;/span&gt;&lt;span&gt; | Georgi     | Facello   | Senior Engineer  | &lt;/span&gt;&lt;span&gt;1986&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;06&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;15346&lt;/span&gt;&lt;span&gt; | Kirk       | Facello   | Senior Engineer  | &lt;/span&gt;&lt;span&gt;1997&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;06&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;15685&lt;/span&gt;&lt;span&gt; | Kasturi    | Facello   | Senior Engineer  | &lt;/span&gt;&lt;span&gt;1997&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;03&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;18686&lt;/span&gt;&lt;span&gt; | Kwangyoen  | Facello   | Senior Staff     | &lt;/span&gt;&lt;span&gt;1994&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;05&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;02&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;21947&lt;/span&gt;&lt;span&gt; | Taisook    | Facello   | Senior Engineer  | &lt;/span&gt;&lt;span&gt;1998&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;08&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;23938&lt;/span&gt;&lt;span&gt; | Nahum      | Facello   | Senior Engineer  | &lt;/span&gt;&lt;span&gt;1985&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;09&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;24774&lt;/span&gt;&lt;span&gt; | Uno        | Facello   | Senior Staff     | &lt;/span&gt;&lt;span&gt;2002&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;05&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;24806&lt;/span&gt;&lt;span&gt; | Charmane   | Facello   | Senior Engineer  | &lt;/span&gt;&lt;span&gt;1999&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;03&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;25955&lt;/span&gt;&lt;span&gt; | Christoph  | Facello   | Technique Leader | &lt;/span&gt;&lt;span&gt;1995&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;08&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;|  &lt;/span&gt;&lt;span&gt;27732&lt;/span&gt;&lt;span&gt; | Girolamo   | Facello   | Senior Engineer  | &lt;/span&gt;&lt;span&gt;1986&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;06&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;| ...    |            |           |                  |            |&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;--------+------------+-----------+------------------+------------+&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;186&lt;/span&gt;&lt;span&gt; rows&lt;/span&gt;&lt;span&gt; in&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="functional-indexes-and-dolt-branches"&gt;Functional Indexes and Dolt Branches&lt;a class="anchor-link" aria-label="Link to heading" href="#functional-indexes-and-dolt-branches"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One thing worth noting for Dolt users: functional indexes are part of your schema, and like everything else in Dolt, your schema lives on branches. If you create a functional index on a feature branch, it exists only on that branch until you merge it. Schema changes, including functional index additions and removals, show up in &lt;code&gt;dolt diff&lt;/code&gt; and in pull requests on DoltHub, so your team can review index changes the same way they review any other change to the database.&lt;/p&gt;
&lt;p&gt;This means you can safely experiment with different indexing strategies on isolated branches and only merge the ones that work the way you need them to. It also allows you to offload the work to build the initial index to be performed in the branch, then Dolt can often reuse the index data directly and update it from data differences when you merge it into another branch.&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How It Works&lt;a class="anchor-link" aria-label="Link to heading" href="#how-it-works"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Under the hood, Dolt implements functional indexes the same way MySQL does: by automatically creating a hidden virtual generated column that stores the result of the expression, then building a regular index on that hidden column. The virtual column is entirely transparent — it won’t appear in &lt;code&gt;SHOW COLUMNS&lt;/code&gt; or &lt;code&gt;SELECT *&lt;/code&gt; output. Dolt handles computing and maintaining it automatically as rows are inserted and updated.&lt;/p&gt;
&lt;h2 id="future-enhancements"&gt;Future Enhancements&lt;a class="anchor-link" aria-label="Link to heading" href="#future-enhancements"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Our initial release of functional index support includes the features that customers told us they needed from functional indexes (e.g. support for a single functional expression, using functional indexes in joins and filters). Now that those customer use cases are unblocked, we’re following up with a few more enhancements:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Multiple expressions per functional index.&lt;/strong&gt; Each functional index currently supports exactly one functional expression. If you need indexes on multiple expressions, you’ll need a separate index for each one. This was an expedient way to build what our first customers needed, and we’re already working on expanding support for mixing functional expressions with column references in an index, and using multiple functional expressions in a single index. We expect to deliver this as a quick follow-up to the initial support.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Doltgres support.&lt;/strong&gt; &lt;a href="https://www.doltgres.com/"&gt;Doltgres is our PostgreSQL-compatible database engine&lt;/a&gt;. Dolt has a head start of a few years over Doltgres, but Doltgres is catching up quickly and moving towards a 1.0 milestone. We’ve already started working on enabling functional index support in Doltgres and expect to deliver this as another fast follow-up.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Use functional indexes for more queries.&lt;/strong&gt; Today, functional indexes are used in joins and filters to speed up queries. These are the main places where functional index speed up queries, but there are other places where functional indexes could also be used, such as to optimize sorting. For example, a query like &lt;code&gt;SELECT * FROM users ORDER BY LOWER(email)&lt;/code&gt; won’t yet use the functional index to avoid a sort.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Performance testing.&lt;/strong&gt; Our initial performance testing for functional indexes shows a dramatic speed up for queries that performed a full table scan before being optimized with a functional index. When compared to MySQL performance for those same queries and same index, Dolt matches or beats MySQL’s performance for those queries. We’ll be adding &lt;a href="https://www.dolthub.com/blog/2025-12-04-dolt-is-as-fast-as-mysql/"&gt;sysbench tests&lt;/a&gt; to track query performance with functional indexes and digging into other cases, like JSON usage with functional indexes to continue tuning performance.&lt;/p&gt;
&lt;h2 id="wrap-up"&gt;Wrap Up&lt;a class="anchor-link" aria-label="Link to heading" href="#wrap-up"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The ability to index functional expressions on your data and then use those precomputed values to speed up joins and filtering in queries is a big feature for Dolt. These functional indexes can turn slow table scans over large tables into lightning fast point lookups. In the examples we walked through here, on a table with 300k rows, a functional index improved performance by 75x. The performance impact gets larger as the table size grows.&lt;/p&gt;
&lt;p&gt;If you want to dig deeper into how Dolt uses indexes and plans joins, check out Nick’s recent post on &lt;a href="https://www.dolthub.com/blog/2026-02-27-index-selection-for-join-queries/"&gt;improving index selection for join queries&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you haven’t tried Dolt yet, &lt;a href="https://dolthub.com/docs/introduction/installation"&gt;install it here&lt;/a&gt; and give functional indexes a spin! If you have questions or feedback, swing by our &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;Discord server&lt;/a&gt; or &lt;a href="https://github.com/dolthub/dolt/issues/new"&gt;file an issue on GitHub&lt;/a&gt;. We love hearing from customers and are always happy to prioritize features or bug fixes that customers tell us they need.&lt;/p&gt;</content:encoded>
      <dc:creator>Jason Fulghum</dc:creator>
      <category>feature release</category>
      <category>dolt</category>
    </item>
    <item>
      <title>Why DoltLite?</title>
      <link>https://dolthub.com/blog/2026-04-27-why-doltlite/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-04-27-why-doltlite/</guid>
      <description>DoltLite redefines what is possible for local-first software. You can now use Git-style merges instead of CRDTs in sync engines.</description>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;We shipped &lt;a href="https://github.com/dolthub/doltlite"&gt;DoltLite&lt;/a&gt;, a version-controlled SQLite. We already have &lt;a href="https://www.doltdb.com"&gt;Dolt&lt;/a&gt;. Dolt is free and open source. Dolt clones, branches, pushes, pulls, and merges. Why ship a second product? This article explains.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dolthub/doltlite"&gt;&lt;img src="https://static.dolthub.com/blogimages/doltlite-logo.png/187cf16f99ea27a3199258d56892a3869221f9c9af529beeaffba3990bfc3f47.webp" alt="DoltLite Logo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="local-first-software"&gt;Local-first Software&lt;a class="anchor-link" aria-label="Link to heading" href="#local-first-software"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.inkandswitch.com/essay/local-first/"&gt;Local-first software&lt;/a&gt;, coined by Ink &amp;#x26; Switch in 2019, has inspired a lot of software, mostly based on SQLite. SQLite puts the “local” in “local-first”. SQLite delivers complex tabular data and SQL query power as a C-library, embeddable in any language.&lt;/p&gt;
&lt;p&gt;Local-first defines seven ideals:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fast&lt;/li&gt;
&lt;li&gt;Multi-device&lt;/li&gt;
&lt;li&gt;Offline&lt;/li&gt;
&lt;li&gt;Collaboration&lt;/li&gt;
&lt;li&gt;Longevity&lt;/li&gt;
&lt;li&gt;Privacy&lt;/li&gt;
&lt;li&gt;User control&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;SQLite gives you “Fast”, “Offline”, “Privacy”, and “User Control”.&lt;/p&gt;
&lt;p&gt;How do you get “Multi-device” and “Collaboration” from SQLite? You need a sync engine. There’s been a number of sync engines based around SQLite in the over half-a-decade since Ink &amp;#x26; Switch published this essay:
&lt;a href="https://turso.tech/"&gt;Turso&lt;/a&gt;, &lt;a href="https://www.powersync.com/"&gt;Powersync&lt;/a&gt;, &lt;a href="https://electric-sql.com/"&gt;ElectricSQL&lt;/a&gt;, and &lt;a href="https://github.com/vlcn-io/cr-sqlite"&gt;cr-sqlite&lt;/a&gt; to name a few.&lt;/p&gt;
&lt;p&gt;But, the fundamental problem with sync engines is “What do you do with conflicts?”. The &lt;a href="https://www.inkandswitch.com/essay/local-first/"&gt;Local-first software essay&lt;/a&gt; suggests Conflict Resistant Data Types (CRDTs) as the solution, rejecting Git because “Git has no capability for real-time, fine-grained collaboration, such as the automatic, instantaneous merging” and “other (non-text) file formats are treated as binary blobs that cannot meaningfully be edited or merged”.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href="https://github.com/dolthub/doltlite"&gt;DoltLite&lt;/a&gt;, a version-controlled SQLite. DoltLite enables a new class of local-first application by supporting Git-style merging on tabular data directly accessible as a C-library.&lt;/p&gt;
&lt;h1 id="but-dolt"&gt;But Dolt?&lt;a class="anchor-link" aria-label="Link to heading" href="#but-dolt"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.doltdb.com"&gt;Dolt&lt;/a&gt; already existed and has been stable for years. Why not just use Dolt?&lt;/p&gt;
&lt;p&gt;Because Dolt is a server. To use Dolt from your application you stand up &lt;code&gt;dolt sql-server&lt;/code&gt;, point a MySQL client at port 3306, and talk wire protocol. That’s a fine model if you’re replacing MySQL or Postgres. It’s the wrong model for local-first.&lt;/p&gt;
&lt;p&gt;The whole point of local-first is the database lives on the user’s device. Asking the user to run a server defeats the purpose. Running a local server is a pain. There’s a process to manage, a port to not collide with, a daemon that can crash. SQLite has none of that. SQLite is a &lt;code&gt;.dylib&lt;/code&gt; your application links in. That’s the model local-first wants.&lt;/p&gt;
&lt;p&gt;DoltLite is that model with version control. People have been asking us for an embedded Dolt for years.&lt;/p&gt;
&lt;h1 id="sql-and-version-control-in-any-language"&gt;SQL and Version Control in Any Language&lt;a class="anchor-link" aria-label="Link to heading" href="#sql-and-version-control-in-any-language"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Dolt is written in Go. Go is great for a server. It is bad for a library you embed in someone else’s runtime, &lt;a href="https://www.dolthub.com/blog/2022-07-25-embedded/"&gt;unless it’s a Go runtime&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Go binaries are big. Go is awkward to link into iOS apps, Python C extensions, Ruby gems, Node addons, Erlang NIFs, and Rust crates. And Go’s WebAssembly (WASM) story produces multi-megabyte bundles with a runtime that doesn’t play well with the browser’s threading and storage primitives.&lt;/p&gt;
&lt;p&gt;C compiles to all of those. iOS, Android, Python, Ruby, Node, Rust, Erlang, and the one that matters most for local-first: a &lt;code&gt;.wasm&lt;/code&gt; bundle that runs inside a browser tab. &lt;a href="https://github.com/dolthub/doltlite#webassembly-extwasm"&gt;DoltLite compiles SQLite’s WASM target&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;WASM is what local-first looks like in 2026. The user opens a webpage. The webpage downloads a &lt;code&gt;.wasm&lt;/code&gt; file. The &lt;code&gt;.wasm&lt;/code&gt; is a full version-controlled SQL database backed by &lt;a href="https://developer.chrome.com/blog/sqlite-wasm-in-the-browser-backed-by-the-origin-private-file-system"&gt;the browser’s private filesystem&lt;/a&gt;. The user’s edits commit to a local branch. When they hit publish, the branch pushes to a DoltLite remote. When a teammate’s branch lands, the user pulls and merges.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;-- alice's laptop&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; dolt_clone(&lt;/span&gt;&lt;span&gt;'https://dolthub.com/team/users'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'users.db'&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; users &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'alice'&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; dolt_commit(&lt;/span&gt;&lt;span&gt;'-Am'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'add alice'&lt;/span&gt;&lt;span&gt;);                                       &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; dolt_push(&lt;/span&gt;&lt;span&gt;'origin'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt;);                                &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;                                                                                &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;-- bob's browser tab (WASM)                                        &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; dolt_clone(&lt;/span&gt;&lt;span&gt;'https://dolthub.com/team/users'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'users.db'&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; users &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'bob'&lt;/span&gt;&lt;span&gt;);                                          &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; dolt_commit(&lt;/span&gt;&lt;span&gt;'-Am'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'add bob'&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; dolt_pull(&lt;/span&gt;&lt;span&gt;'origin'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt;);   &lt;/span&gt;&lt;span&gt;-- merges alice's commit                &lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; dolt_push(&lt;/span&gt;&lt;span&gt;'origin'&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;'main'&lt;/span&gt;&lt;span&gt;);   &lt;/span&gt;&lt;span&gt;-- pushes the merged history &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No wire protocol. No port. No server. A C library call into a &lt;code&gt;.dylib&lt;/code&gt;, &lt;code&gt;.so&lt;/code&gt;, &lt;code&gt;.dll&lt;/code&gt;, or &lt;code&gt;.wasm&lt;/code&gt; you linked into your app. &lt;code&gt;dolt_push&lt;/code&gt; to share with everyone else holding a copy.&lt;/p&gt;
&lt;p&gt;In the example, Alice and Bob inserted different rows, so the merge was trivial. If they had both updated row two to different names, &lt;code&gt;dolt_pull&lt;/code&gt; would do what Git does: drop both versions into a &lt;code&gt;dolt_conflicts_users&lt;/code&gt; table and refuse to commit until a human picks. That’s the part CRDTs hide. For data with audit or rollback requirements, you want disagreement surfaced, not silently resolved.&lt;/p&gt;
&lt;p&gt;DoltLite is the local-first use case, with Git-style merging on structured data instead of CRDTs.&lt;/p&gt;
&lt;h1 id="try-doltlite"&gt;Try DoltLite&lt;a class="anchor-link" aria-label="Link to heading" href="#try-doltlite"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;All DoltLite needs is users. Have a local-first app you’ve been waiting to build because there was no Git-style sync model? Wait no longer. Questions? Bugs? Feature requests? Cut &lt;a href="https://github.com/dolthub/doltlite/issues"&gt;an issue&lt;/a&gt;. Otherwise, come by &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;our Discord&lt;/a&gt; to discuss. Meet me in the #doltlite🪶 channel.&lt;/p&gt;</content:encoded>
      <dc:creator>Tim Sehn</dc:creator>
      <category>doltlite</category>
      <category>use case</category>
    </item>
    <item>
      <title>How Dolt Represents and Evaluates Queries: A Case Study</title>
      <link>https://dolthub.com/blog/2026-04-21-how-dolt-represents-and-evaluates-queries/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-04-21-how-dolt-represents-and-evaluates-queries/</guid>
      <description>We look at a recent bug fix to understand how Dolt actually represents queries internally. It turns out, database engines and compilers have a lot in common.</description>
      <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;Want to know a cool secret about database engines? They’re literally the same thing as compilers.&lt;/p&gt;
&lt;p&gt;At my previous job, I worked on Google’s internal Java compiler. Now, I’m one of the developers of &lt;a href="https://github.com/dolthub/dolt"&gt;Dolt&lt;/a&gt;, the first version-controlled SQL database, as well as &lt;a href="https://github.com/dolthub/go-mysql-server/"&gt;go-mysql-server&lt;/a&gt;, the SQL engine that Dolt depends on.&lt;/p&gt;
&lt;p&gt;It turns out that the skills and techniques that I first learned while writing a compiler are the exact same techniques that Dolt uses in its database engine. And that’s because when you break it down, database engines are just a domain-specific compiler:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;General-purpose compilers turn human-readable source code into machine-readable programs that manipulate variables and produce side-effects.&lt;/li&gt;
&lt;li&gt;SQL engines turn human-readable SQL queries into machine-readable execution plans that manipulate table columns and produce a stream of rows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most compiler concepts map directly onto database engines. &lt;a href="https://sqlite.org/opcode.html"&gt;Some database engines like SQLite even work by producing bytecode that executes in a special-purpose VM.&lt;/a&gt;. Dolt doesn’t do that, but it does create an &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree"&gt;abstract syntax tree&lt;/a&gt; almost exactly like one you would see in any other interpreted language.&lt;/p&gt;
&lt;p&gt;The main difference is that in most languages, evaluating a syntax tree produces a return value and side effects. In Dolt, evaluating a syntax tree produces an iterator. This also means that each intermediate node in the tree is an iterator defined in terms of one or more child iterators. This approach is often called the &lt;strong&gt;volcano model&lt;/strong&gt; or &lt;strong&gt;iterator model&lt;/strong&gt; of database engine design.&lt;/p&gt;
&lt;p&gt;This means that database engines can have the same types of bugs as traditional languages and a lot of the same thorns. We recently fixed a correctness issue in Dolt that does a good job demonstrating this. &lt;a href="https://github.com/dolthub/go-mysql-server/pull/3428"&gt;You can find the writeup and the fix here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To trigger the incorrect behavior, you needed a query that looked like this.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; ab&lt;/span&gt;&lt;span&gt; (a &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt;, b &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; three_pk&lt;/span&gt;&lt;span&gt; (pk1 &lt;/span&gt;&lt;span&gt;TINYINT&lt;/span&gt;&lt;span&gt;, pk2 &lt;/span&gt;&lt;span&gt;TINYINT&lt;/span&gt;&lt;span&gt;, pk3 &lt;/span&gt;&lt;span&gt;TINYINT&lt;/span&gt;&lt;span&gt;, col &lt;/span&gt;&lt;span&gt;TINYINT&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;PRIMARY KEY&lt;/span&gt;&lt;span&gt; (pk1, pk2, pk3));&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; ab &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; ab1 &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; ab &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; ab2 &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; ab &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; ab3 &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; three_pk &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; pk1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ab1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; pk2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ab2&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; pk3 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ab3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running this query on older versions of Dolt would trigger a panic. To understand why, let’s talk about scopes.&lt;/p&gt;
&lt;h1 id="scopes"&gt;Scopes&lt;a class="anchor-link" aria-label="Link to heading" href="#scopes"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Scopes are something that every programmer has to deal with even if they don’t realize it. It’s how programs resolve symbols to the things that are actually being referenced.&lt;/p&gt;
&lt;p&gt;SQL queries reference tables and columns by name, and Dolt needs to map those names onto the tables and columns they represent. This is not as simple as it looks, because the same name can refer to different tables based on where it appears in the statement. The following is a valid SQL query:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; test_table &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; test_table &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; test_table&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;and&lt;/span&gt;&lt;span&gt; test_table&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this query, there are two tables named &lt;code&gt;test_table&lt;/code&gt; and two filter conditions that name &lt;code&gt;test_table&lt;/code&gt;. Which condition refers to which child iterator? If Dolt resolves these names incorrectly, it will produce incorrect output.&lt;/p&gt;
&lt;p&gt;Two names can also refer to the same table, again depending on where the names appear. Consider this simple query with a two-part primary key:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; test_table&lt;/span&gt;&lt;span&gt;(pk1 &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt;, pk2 &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;PRIMARY KEY&lt;/span&gt;&lt;span&gt; (pk1, pk2));&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; test_table &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; test_table&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;pk2&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; table_alias &lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; table_alias&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;pk1&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This query can be optimized into a simple table lookup, but only if Dolt can detect that the two &lt;code&gt;WHERE&lt;/code&gt; clauses refer to the same table, even though the two clauses use different table names.&lt;/p&gt;
&lt;p&gt;Thus, it does not suffice for Dolt to simply keep a global dictionary that maps names onto tables, because the rules for resolving references are not global. Different parts of the query introduce their own namespace, which changes how names are resolved. These namespaces are scopes.&lt;/p&gt;
&lt;p&gt;So how does a database engine keep these scopes straight? How are table references actually represented in the abstract syntax tree?&lt;/p&gt;
&lt;h2 id="scopes-at-analysis-time"&gt;Scopes at Analysis Time&lt;a class="anchor-link" aria-label="Link to heading" href="#scopes-at-analysis-time"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The most naive approach is to simply store the same names in the AST as they appear in the query. Then, whenever the engine wants to analyze, optimize, or execute part of the tree, it resolves the name using scope rules. This works, but it’s incredibly brittle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Any optimization that transforms the AST needs to be very careful. If a node contains a reference, moving that node to another part of the tree could change the meaning of that reference, and change the behavior of the query. Whenever the engine transforms the tree, it would need to update any references.&lt;/li&gt;
&lt;li&gt;In fringe cases, a transformation may result in an impossible tree, where we need to reference a table but it’s impossible to do so because that table’s name is being shadowed by another.&lt;/li&gt;
&lt;li&gt;Needing to resolve references repeatedly is slow and wasteful.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is actually how Dolt used to operate years ago, and it was the source of subtle bugs. So we switched to a better approach: when analyzing a query, we assign incrementing globally unique IDs to tables and columns. Every reference is resolved once, and then the name gets replaced with the ID. Since each ID always refers to the same table or column, we can safely modify the AST without any risk of changing the query’s meaning.&lt;/p&gt;
&lt;p&gt;But this is only half of the situation of scopes.&lt;/p&gt;
&lt;h2 id="scopes-at-runtime"&gt;Scopes at Runtime&lt;a class="anchor-link" aria-label="Link to heading" href="#scopes-at-runtime"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It’s not enough to just be able to resolve references to the table or column they represent, we also need to track those values while the query is running. Operations that produce column values need to be able to send those values to the operations that read them.&lt;/p&gt;
&lt;p&gt;In general-purpose languages, this might be accomplished with registers, or by writing to values in memory. But SQL queries are declarative and functional and don’t have state: when evaluating a node in the syntax tree, the iterator it produces is often a pure function of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Columns inherited from parent nodes
&lt;ul&gt;
&lt;li&gt;Example: In &lt;code&gt;SELECT id FROM a WHERE EXISTS (SELECT id FROM b WHERE a.id = b.id)&lt;/code&gt;, the inner query references a column from the outer query.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Columns returned from child nodes
&lt;ul&gt;
&lt;li&gt;Example: In &lt;code&gt;SELECT id FROM (SELECT id FROM a) AS a_alias where a_alias.id = 1&lt;/code&gt;, the outer query references a column from the inner query.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Columns defined in sibling nodes
&lt;ul&gt;
&lt;li&gt;Example: In &lt;code&gt;SELECT id FROM a JOIN LATERAL (SELECT id FROM b WHERE a.id = b.id)&lt;/code&gt;, the right side of the join references a column from the left side of the join.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these columns can have multiple values over the lifetime of the query, but only one at a time. A SQL engine needs a strategy to represent this internally.&lt;/p&gt;
&lt;p&gt;A naive approach might be to maintain a mapping from each column name to its current value. Except as we already saw, names don’t map one-to-one onto columns. In fact, it’s perfectly valid MySQL to for a table alias to have multiple columns with the same name. For example, the below query produces a table alias with two columns both named &lt;code&gt;pk&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; test_table&lt;/span&gt;&lt;span&gt;(pk &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; test_table &lt;/span&gt;&lt;span&gt;JOIN&lt;/span&gt;&lt;span&gt; test_table) &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; table_alias;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even more problematic is that a table alias column might have &lt;em&gt;no&lt;/em&gt; name:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; table_alias;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In either case, it’s not possible to reference these columns in filters, but they can still impact the results of the query if the alias is used in a &lt;code&gt;SELECT *&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So if we can’t track values by their column name, another approach might be to use the unique column IDs we discussed in the previous section. But there could be many such IDs, and each node in the AST only cares about a small number of them. Managing lots of small maps is also not very performant, and we care about performance.&lt;/p&gt;
&lt;p&gt;Fortunately, there’s an approach to that gives us both clarity and performance. Every scope in a SQL query always has the same number of columns. So the number of columns referenceable from any node in the AST is a constant value that can be determined by statically analyzing the query. The number of columns in that node’s iterator is also a constant value.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A table reference with N columns produces an iterator that returns a list of five values.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;SELECT col1, col2, ... colN WHERE EXISTS (...)&lt;/code&gt; construct creates N referenceable columns for every node within the subquery.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each node can have an array where we store the value of each of these columns. Each element in the array corresponds to a different column. Before we evaluate the query, we can analyze the AST to determine which column each array element represents. Now if we want to represent an expression that reads a column, we don’t need to store the name of the column in the AST, and we don’t need to store that column’s globally unique ID either: all we need to store is the offset within that node’s own array corresponding to that column.&lt;/p&gt;
&lt;p&gt;This is the approach that Dolt uses: it analyzes the tree, determines the exact set of columns visible to each node, and replaces column references with the correct offset into that node’s array that will contain that column at runtime.&lt;/p&gt;
&lt;p&gt;We can illustrate this process with some diagrams. In each case, we show the nodes in the AST, and each node has both an ordered sequence of columns it produces (the output schema), and an ordered lists of columns it can reference (the input schema). The color of each cell indicates the node that originally produced the value. Note how nodes can contain column references from children, siblings, or parents, but in each case the number of columns can be statically determined.&lt;/p&gt;
&lt;p&gt;A node referencing its child:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; test_table&lt;/span&gt;&lt;span&gt;(a &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;, b &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;, c &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; c&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; AS&lt;/span&gt;&lt;span&gt; d &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; test_table;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Would result in an AST that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/ast-child.svg/c1eb0eb3597c600cc5b743a41588051270245a20bc8e15c127188c15bb754b26.svg" alt="node with child reference"&gt;&lt;/p&gt;
&lt;p&gt;A node referencing its parent:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; test_table&lt;/span&gt;&lt;span&gt;(a &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;, b &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;, c &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; test_table &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; t1 &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; test_table &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; t2 &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; t1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; t2&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Would result in an AST that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/ast-parent.svg/5f8e321bc1841193cb1170493715d10ce03d971997b743c941aa25ecd95aeb8a.svg" alt="node with parent reference"&gt;&lt;/p&gt;
&lt;p&gt;In order for this optimization to work correctly, every node must agree on how many columns it receives from each of their children, and how many columns are visible from parent and sibling scopes. If these numbers don’t agree, it could lead to situations where Dolt accesses the wrong value at runtime, or accesses the array out-of-bounds and panics.&lt;/p&gt;
&lt;p&gt;So with all this in mind, let’s look back at the query that triggered the bug:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="sql"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; ab&lt;/span&gt;&lt;span&gt; (a &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt;, b &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; three_pk&lt;/span&gt;&lt;span&gt; (pk1 &lt;/span&gt;&lt;span&gt;TINYINT&lt;/span&gt;&lt;span&gt;, pk2 &lt;/span&gt;&lt;span&gt;TINYINT&lt;/span&gt;&lt;span&gt;, pk3 &lt;/span&gt;&lt;span&gt;TINYINT&lt;/span&gt;&lt;span&gt;, col &lt;/span&gt;&lt;span&gt;TINYINT&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;PRIMARY KEY&lt;/span&gt;&lt;span&gt; (pk1, pk2, pk3));&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; ab &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; ab1 &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; ab &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; ab2 &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; ab &lt;/span&gt;&lt;span&gt;AS&lt;/span&gt;&lt;span&gt; ab3 &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;      SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; three_pk &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; pk1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ab1&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; pk2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ab2&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt; and&lt;/span&gt;&lt;span&gt; pk3 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ab3&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  )&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The simplest explanation for the root cause was this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When Dolt optimized this query, it would transform it into multiple nested join nodes.&lt;/li&gt;
&lt;li&gt;Each of these join nodes introduced a new table alias that could be referenced by its children.&lt;/li&gt;
&lt;li&gt;If a join condition referenced a column, then Dolt would need to compute the offset of that column in the join node’s array of column references. This required knowing how many of the columns in the array came from parent scopes, how many came from sibling scopes, and how many were from that node’s children.&lt;/li&gt;
&lt;li&gt;The logic for computing how many columns in the input schema came from outer scopes did not consider the fact scopes could be introduced in the middle of a nested join. This made it impossible to correctly calculate this for every node in the AST.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There were some attempts made to account for this issue, but in adjusting the calculations for common queries, it broke the calculations for less common queries. Ultimately, these adjustments made the logic harder to reason about. In the end, we fixed the issue by completely rewriting how we generated iterators during join in order to make it simpler to analyze them.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/dolthub/go-mysql-server/pull/3428"&gt;The full scope of the issue and the fix are more complicated, but this was the general idea.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope this illuminates what actually goes on inside a database engine.&lt;/p&gt;
&lt;p&gt;As always, if you have any thoughts about database design, or if you’re curious how a version-controlled database can benefit you, then you should hop into our &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;Discord&lt;/a&gt; and we’d love to discuss it with you.&lt;/p&gt;</content:encoded>
      <dc:creator>Nick Tobey</dc:creator>
      <category>dolt</category>
    </item>
    <item>
      <title>Vibe-Coded Agents for Vibe-Coded Issues</title>
      <link>https://dolthub.com/blog/2026-04-03-vibe-coded-agents-for-vibe-coded-issues/</link>
      <guid isPermaLink="true">https://dolthub.com/blog/2026-04-03-vibe-coded-agents-for-vibe-coded-issues/</guid>
      <description>Gas Town's vibe-coded agents introduced a plethora of new issues to Dolt. I vibe-coded a Go CLI to fight back: parallel agents to reproduce the issues agents caused.</description>
      <pubDate>Fri, 03 Apr 2026 00:00:00 GMT</pubDate>
      <content:encoded>&lt;p&gt;&lt;a href="https://github.com/dolthub/dolt"&gt;Dolt&lt;/a&gt; is a SQL database with Git-style version control. It speaks the MySQL wire protocol, so any MySQL client can connect to it, and it adds version control primitives on top: branch, merge, diff, clone, and push, all over SQL. Under the hood, &lt;a href="https://github.com/dolthub/go-mysql-server"&gt;go-mysql-server&lt;/a&gt; handles the SQL execution layer between clients and Dolt’s storage engine.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/steveyegge/gastown"&gt;Gas Town&lt;/a&gt; builds on those primitives. It is &lt;a href="https://www.dolthub.com/blog/2026-01-15-a-day-in-gas-town/"&gt;a multi-agent coding orchestrator&lt;/a&gt; built on write-only code, and as &lt;a href="https://www.dolthub.com/blog/2026-03-13-multi-agent-persistence/"&gt;it scaled to hundreds of concurrent workers&lt;/a&gt;, those agents were constantly branching, merging, and committing against Dolt. That load surfaced a new class of issues: vibe-coded issues.&lt;/p&gt;
&lt;p&gt;To be clear, I’m not throwing shade. After all, I’m familiar with &lt;a href="https://www.dolthub.com/blog/2025-08-28-how-i-use-multiple-agents-in-parallel/"&gt;running agents in parallel&lt;/a&gt; to work through MySQL correctness work, but we’re also entering a new ballpark here. It’s hard to expect clear reproductions when hundreds of agents unpredictably use a tool at the same time. I would know, since I recently spent hours trying to get a reproduction on a couple of Gas Town Dolt issues, some leading to nowhere.&lt;/p&gt;
&lt;p&gt;So, in the spirit of &lt;a href="https://www.dolthub.com/blog/2026-03-26-vibe-code-vs-trad-code/"&gt;Vibe Code vs Trad Code&lt;/a&gt;, sometimes you fight fire with fire. I’ve “vibe-coded” &lt;code&gt;grunt&lt;/code&gt;, a Go CLI that provisions isolated Docker agent environments in parallel but with options this time around.&lt;/p&gt;
&lt;h1 id="the-problem-pre-baked-containers-dont-scale"&gt;The Problem: Pre-Baked Containers Don’t Scale&lt;a class="anchor-link" aria-label="Link to heading" href="#the-problem-pre-baked-containers-dont-scale"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The obvious answer to “Gas Town introduced these issues, why not use Gas Town to reproduce them?” is that issue reproduction isn’t really a Gas Town job. Gas Town is built for long-running, write-only work where persistent agent memory via &lt;a href="https://github.com/gastownhall/beads"&gt;Beads&lt;/a&gt; accumulates across sessions. Reproducing a GitHub issue is the opposite in that it’s a short-lived, discrete task where you spin up, get a failing test, and tear down.&lt;/p&gt;
&lt;p&gt;My &lt;a href="https://www.dolthub.com/blog/2025-08-28-how-i-use-multiple-agents-in-parallel/"&gt;previous setup&lt;/a&gt; relied on a single container image with all dependencies pre-baked. That worked when I was targeting a specific repository and task. The moment I needed to handle two repos with different requirements, it broke down and I had to manually update things.&lt;/p&gt;
&lt;p&gt;What I actually wanted was to configure at launch time via CLI flags what each agent container and repo needs: which post-install scripts to run, how much memory to give it, what prompt to start it with.&lt;/p&gt;
&lt;p&gt;So I pointed an agent at the problem. I had it follow Go best practices from the official docs and address IDE warnings as it went, rather than letting it freewheel. The result is &lt;code&gt;grunt&lt;/code&gt;. I can read the code, which puts it firmly in &lt;a href="https://www.dolthub.com/blog/2026-03-26-vibe-code-vs-trad-code/"&gt;Trad Code territory&lt;/a&gt; even if it got there via an agent.&lt;/p&gt;
&lt;h1 id="how-grunt-works"&gt;How grunt Works&lt;a class="anchor-link" aria-label="Link to heading" href="#how-grunt-works"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;One command does everything:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;grunt&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; -name&lt;/span&gt;&lt;span&gt; gms&lt;/span&gt;&lt;span&gt; -repo&lt;/span&gt;&lt;span&gt; dolthub/go-mysql-server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://static.dolthub.com/blogimages/gms-session.png/c2511ed284053fd62f268798d2d67ab4f35018bc0d6a16f780166486991f7fc5.webp" alt="A grunt agent session running against go-mysql-server"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;create&lt;/code&gt; resolves the repo’s configuration, builds the Docker image with the right post-install scripts applied, clones the repo, starts the container, and drops you straight into a &lt;a href="https://zellij.dev/"&gt;zellij&lt;/a&gt; session with Claude already running. There is no separate start step.&lt;/p&gt;
&lt;p&gt;The nice part is that &lt;code&gt;grunt agent create -repo dolthub/dolt&lt;/code&gt; already knows what that repo needs without me specifying anything. &lt;code&gt;dolthub/dolt&lt;/code&gt; needs &lt;a href="https://www.dolthub.com/blog/2025-11-21-easy-cgo-builds-with-docker/"&gt;CGo build dependencies&lt;/a&gt; plus &lt;a href="https://www.dolthub.com/blog/2024-07-17-lambdabats/"&gt;bats&lt;/a&gt; for its test suite. &lt;code&gt;dolthub/go-mysql-server&lt;/code&gt; needs something lighter. That comes from the configuration layer, covered in the next section. Even if you don’t have a config, it’ll figure out the GitHub URL automatically for any new repositories.&lt;/p&gt;
&lt;p&gt;If I want to override the post-install scripts or provider (only claude so far) for a specific run, I pass them directly:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;grunt&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; -name&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; -repo&lt;/span&gt;&lt;span&gt; dolthub/dolt&lt;/span&gt;&lt;span&gt; -repo&lt;/span&gt;&lt;span&gt; dolthub/go-mysql-server&lt;/span&gt;&lt;span&gt; -issue&lt;/span&gt;&lt;span&gt; 1234&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  -post-install&lt;/span&gt;&lt;span&gt; go,bats,dolt-cgo-deps&lt;/span&gt;&lt;span&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  -provider&lt;/span&gt;&lt;span&gt; claude&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When I have several issues to chase at once, &lt;code&gt;-d&lt;/code&gt; starts the container in the background and hands control back immediately. Then I attach to whichever is idle.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;grunt&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; -d&lt;/span&gt;&lt;span&gt; -name&lt;/span&gt;&lt;span&gt; dolt&lt;/span&gt;&lt;span&gt; -repo&lt;/span&gt;&lt;span&gt; dolthub/dolt&lt;/span&gt;&lt;span&gt; -issue&lt;/span&gt;&lt;span&gt; 10782&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;grunt&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; create&lt;/span&gt;&lt;span&gt; -d&lt;/span&gt;&lt;span&gt; -name&lt;/span&gt;&lt;span&gt; gms&lt;/span&gt;&lt;span&gt; -repo&lt;/span&gt;&lt;span&gt; dolthub/go-mysql-server&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;grunt&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;ID&lt;/span&gt;&lt;span&gt;                 STATE&lt;/span&gt;&lt;span&gt;    ACTIVITY&lt;/span&gt;&lt;span&gt;  PROVIDER&lt;/span&gt;&lt;span&gt;  REPOS&lt;/span&gt;&lt;span&gt;                         ISSUES&lt;/span&gt;&lt;span&gt;              CREATED&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;gms-41b27c1c&lt;/span&gt;&lt;span&gt;       running&lt;/span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt;         claude&lt;/span&gt;&lt;span&gt;    dolthub/go-mysql-server&lt;/span&gt;&lt;span&gt; (+2)  10190               2026-03-27T18:20:49Z&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;gms-c35d524e&lt;/span&gt;&lt;span&gt;       stopped&lt;/span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt;         claude&lt;/span&gt;&lt;span&gt;    dolthub/go-mysql-server&lt;/span&gt;&lt;span&gt; (+1)  dolthub/dolt#10757  2026-03-30T20:12:06Z&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;dolt-d32698b0&lt;/span&gt;&lt;span&gt;      running&lt;/span&gt;&lt;span&gt;  working&lt;/span&gt;&lt;span&gt;   claude&lt;/span&gt;&lt;span&gt;    dolthub/dolt&lt;/span&gt;&lt;span&gt;                  10782&lt;/span&gt;&lt;span&gt;               2026-03-31T17:16:23Z&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;gms-a573c42c&lt;/span&gt;&lt;span&gt;       running&lt;/span&gt;&lt;span&gt;  idle&lt;/span&gt;&lt;span&gt;      claude&lt;/span&gt;&lt;span&gt;    dolthub/go-mysql-server&lt;/span&gt;&lt;span&gt; (+1)  -                   2026-04-01T17:39:20Z&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;grunt&lt;/span&gt;&lt;span&gt; agent&lt;/span&gt;&lt;span&gt; attach&lt;/span&gt;&lt;span&gt; gms-a573c42c&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For changes I want to stick across all runs of a repo, I use &lt;code&gt;grunt config set&lt;/code&gt;. I’ll usually do this when working on any new repo to set their post-install scripts.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="bash"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;grunt&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; branch.prefix&lt;/span&gt;&lt;span&gt; -value&lt;/span&gt;&lt;span&gt; elian&lt;/span&gt;&lt;span&gt; -repo&lt;/span&gt;&lt;span&gt; dolthub/dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;branch.prefix[dolthub/dolt]&lt;/span&gt;&lt;span&gt;=elian&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;grunt&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; ls&lt;/span&gt;&lt;span&gt; -repo&lt;/span&gt;&lt;span&gt; dolthub/dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt; grunt&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; ls&lt;/span&gt;&lt;span&gt; -repo&lt;/span&gt;&lt;span&gt; dolthub/dolt&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;agent.provider&lt;/span&gt;&lt;span&gt;=claude&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;agent.memory-limit&lt;/span&gt;&lt;span&gt;=8g&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;branch.prefix&lt;/span&gt;&lt;span&gt;=elian&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;issue.prompt&lt;/span&gt;&lt;span&gt;=Create&lt;/span&gt;&lt;span&gt; a&lt;/span&gt;&lt;span&gt; failing&lt;/span&gt;&lt;span&gt; reproduction&lt;/span&gt;&lt;span&gt; for&lt;/span&gt;&lt;span&gt; the&lt;/span&gt;&lt;span&gt; following&lt;/span&gt;&lt;span&gt; issue&lt;/span&gt;&lt;span&gt; {{....&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;repo.post-install&lt;/span&gt;&lt;span&gt;=go,bats,expect,dolt-cgo-deps&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;repo.services&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That &lt;code&gt;config ls&lt;/code&gt; output is the resolved view of a three-layer system. The UX borrows directly from &lt;code&gt;git config&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="per-repo-config"&gt;Per-Repo Config&lt;a class="anchor-link" aria-label="Link to heading" href="#per-repo-config"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Rather than making users configure everything from scratch, grunt ships with per-repo defaults embedded directly in the binary using &lt;code&gt;//go:embed&lt;/code&gt;. Each supported repo gets one JSON file covering the two things that vary most: which post-install scripts to run and a default prompt to seed the agent with.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="json"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  "scripts"&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;"go"&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;"bats"&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;"expect"&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;"dolt-cgo-deps"&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;  "prompt"&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;"Create a failing reproduction for the following issue {{.IssueRef}} under the relevant available repositories..."&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Adding a new repository means adding one JSON file. On top of those sit two user-owned layers: a global config that applies across all repos and a per-repo override. Every lookup walks the same three layers.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="go"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;s &lt;/span&gt;&lt;span&gt;ProfileService&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;AgentProvider&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;repo&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    profile, err &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; s.Store.&lt;/span&gt;&lt;span&gt;Load&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; err &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ""&lt;/span&gt;&lt;span&gt;, fmt.&lt;/span&gt;&lt;span&gt;Errorf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;"load profile: &lt;/span&gt;&lt;span&gt;%w&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;, err)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; provider, ok &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; profile.RepoAgentProviders[repo]; ok {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; provider, &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; profile.AgentProvider, &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works fine for the number of config values &lt;code&gt;grunt&lt;/code&gt; has today. It’s worth noting that the agent duplicated this walk across every accessor instead of merging the layers once at load time. A cleaner approach would resolve everything in &lt;code&gt;Load()&lt;/code&gt; and let accessors just read fields. With only a handful of values, this is not a real problem yet, but it’s worth revisiting.&lt;/p&gt;
&lt;h1 id="adding-a-new-agent-type"&gt;Adding a New Agent Type&lt;a class="anchor-link" aria-label="Link to heading" href="#adding-a-new-agent-type"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;grunt&lt;/code&gt; only ships with Claude today, but it was designed so that swapping in a different agent is one interface implementation away. Each agent type implements &lt;code&gt;AgentProvider&lt;/code&gt;, which covers everything that varies between providers, including how to set up the agent in the Docker container, where to find the agent’s config files, how to read its activity status, and what command to launch it with.&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="go"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; AgentProvider&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    Name&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    Spec&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;Spec&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    PrepareRuntime&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; RuntimeInput&lt;/span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span&gt;RuntimeOutput&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    ActivityStatusPath&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;workspaceRoot&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    ReadActivityStatus&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;workspaceRoot&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    EnsureGlobalConfig&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;paths&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Paths&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    SaveAPIKey&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;paths&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Paths&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    ConfigPaths&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;paths&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Paths&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;ConfigPaths&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    Validate&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;PrepareRuntime&lt;/code&gt; handles the container setup by returning the Docker mounts, environment files, and build commands specific to that provider. &lt;code&gt;Spec&lt;/code&gt; returns the startup command and shell. Those get passed into a &lt;a href="https://zellij.dev/"&gt;zellij&lt;/a&gt; layout file that grunt generates at runtime using Go’s &lt;code&gt;text/template&lt;/code&gt; (has also been useful in other templates i.e. the Dockerfile).&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="plaintext"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;layout {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    tab {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        pane name="Claude" command={{ printf "%q" .StartupCommand }}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    new_tab_template {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        pane name="Shell" command={{ printf "%q" .PaneShell }}&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zellij is a terminal multiplexer, similar to tmux, that lets &lt;code&gt;grunt&lt;/code&gt; give each agent its own named panes. Because the layout is generated from a template, a different provider produces a different layout with no special casing anywhere in the terminal code. Provider selection is a single switch:&lt;/p&gt;
&lt;pre class="astro-code github-dark" tabindex="0" data-language="go"&gt;&lt;code&gt;&lt;span class="line"&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; LookupAgentProvider&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; string&lt;/span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span&gt;AgentProvider&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    switch&lt;/span&gt;&lt;span&gt; strings.&lt;/span&gt;&lt;span&gt;ToLower&lt;/span&gt;&lt;span&gt;(strings.&lt;/span&gt;&lt;span&gt;TrimSpace&lt;/span&gt;&lt;span&gt;(name)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    case&lt;/span&gt;&lt;span&gt; ""&lt;/span&gt;&lt;span&gt;, domain.DefaultProvider:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ClaudeProvider&lt;/span&gt;&lt;span&gt;{}, &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    default&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; nil&lt;/span&gt;&lt;span&gt;, fmt.&lt;/span&gt;&lt;span&gt;Errorf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;%q&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;%w&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;, name, errUnsupportedProvider)&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class="line"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;a class="anchor-link" aria-label="Link to heading" href="#conclusion"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;grunt&lt;/code&gt; is a vibe-coded tool for reproducing issues caused by a vibe-coded tool. That is about as recursive as it gets. We could go on about each aspect of implementation, but the above represents the main goal of these ephemeral configurable agent instances. It’s readable-enough, and it works.&lt;/p&gt;
&lt;p&gt;It’s already helped me spin up multiple reproductions in parallel and close issues faster. I’ve also gotten new ideas on putting this against CI flaky tests in the background too. If you have questions about the setup or want to dig into Dolt, come find us on &lt;a href="https://discord.gg/gqr7K4VNKe"&gt;Discord&lt;/a&gt;. We are always happy to talk Go.&lt;/p&gt;</content:encoded>
      <dc:creator>Elian Deogracia-Brito</dc:creator>
      <category>golang</category>
      <category>technical</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
