<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://marginalutility.dev/blog</id>
    <title>Marginal Utility Blog</title>
    <updated>2026-10-12T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://marginalutility.dev/blog"/>
    <subtitle>Marginal Utility Blog</subtitle>
    <icon>https://marginalutility.dev/img/favicon.ico</icon>
    <rights>Copyright © 2026 Marginal Utility</rights>
    <entry>
        <title type="html"><![CDATA[Turnstile, a gate for agent builds]]></title>
        <id>https://marginalutility.dev/blog/turnstile</id>
        <link href="https://marginalutility.dev/blog/turnstile"/>
        <updated>2026-10-12T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Run several coding agents on one Mac without them swapping it into the ground. Turnstile queues heavy builds and tests for memory, machine-wide.]]></summary>
        <content type="html"><![CDATA[<p>I run three or four coding agents at once, each in its own worktree. Each one is sensible on its own. Together they'd start three <code>swift test</code>s, two <code>npm run build</code>s, and a Playwright suite in the same minute, and my Mac would swap until the cursor stuttered.</p>
<p>Turnstile is the fix. It's a free, open source CLI that queues heavy builds and tests for a slot and for free memory, across every terminal and agent on the machine.</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="what-it-looks-like">What it looks like<a href="https://marginalutility.dev/blog/turnstile#what-it-looks-like" class="hash-link" aria-label="Direct link to What it looks like" title="Direct link to What it looks like" translate="no">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">$ swift test</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">turnstile: waiting for memory, needs ~4 GB, ~1.2 GB spare (running: api swift test, ~3 GB; web npm run build, ~2 GB)</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">turnstile: starting after 41s</span><br></div></code></pre></div></div>
<p>That's it. The command runs in place once there's room, with the same output, exit code, environment, and Ctrl-C. Quick commands like <code>npm install</code> or <code>swift --version</code> pass straight through.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="why-underneath-the-shell">Why underneath the shell<a href="https://marginalutility.dev/blog/turnstile#why-underneath-the-shell" class="hash-link" aria-label="Direct link to Why underneath the shell" title="Direct link to Why underneath the shell" translate="no">​</a></h2>
<p>Every agent harness has its own idea of concurrency, and none of them know about each other. Telling each one to behave doesn't scale, and it doesn't cover the build you start yourself, or the <code>prepublishOnly</code> hook that quietly runs a compile.</p>
<p>So turnstile puts shims named <code>swift</code>, <code>cargo</code>, <code>npm</code>, <code>xcodebuild</code>, and friends first on PATH. A small daemon decides who runs. It works the same for Claude Code, Codex, Gemini, Cursor, Aider, and you, with no per-project setup.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="the-parts-i-like-most">The parts I like most<a href="https://marginalutility.dev/blog/turnstile#the-parts-i-like-most" class="hash-link" aria-label="Direct link to The parts I like most" title="Direct link to The parts I like most" translate="no">​</a></h2>
<ul>
<li class=""><strong>It learns.</strong> Each command's memory peak and run time are learned from recent runs in that project, so admission is based on what the build costs, not a guess.</li>
<li class=""><strong>People go first.</strong> Agent commands run at background priority and queue behind the ones you type.</li>
<li class=""><strong>Duplicate runs merge.</strong> Two agents running the same test on the same tree share one run.</li>
<li class=""><strong>It backs off under pressure.</strong> When memory runs low it lowers each tool's parallelism, then pauses the newest agent compile if things get critical.</li>
<li class=""><strong>It fails open.</strong> If the daemon is missing or broken, commands run ungated rather than failing.</li>
</ul>
<p>There's also a menu bar app for watching the queue, and the same gate makes it safe to run a self-hosted CI runner on the Mac you're working on.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="try-it">Try it<a href="https://marginalutility.dev/blog/turnstile#try-it" class="hash-link" aria-label="Direct link to Try it" title="Direct link to Try it" translate="no">​</a></h2>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token plain">brew install mcclowes/turnstile/turnstile</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">turnstile init</span><br></div></code></pre></div></div>
<p>Open a new shell and run <code>turnstile doctor</code>. It needs macOS 26 or later. Everything stays on your machine.</p>
<p>The <a href="https://turnstile.marginalutility.dev/" target="_blank" rel="noopener noreferrer" class="">docs</a> cover how scheduling and memory pressure work, and how it compares to containers, cloud agents, and build tools. The code is on <a href="https://github.com/mcclowes/turnstile" target="_blank" rel="noopener noreferrer" class="">GitHub</a>. If it misbehaves on your setup, I'd like to hear about it.</p>]]></content>
        <author>
            <name>Max Clayton Clowes</name>
            <uri>https://mcclowes.com</uri>
        </author>
        <category label="turnstile" term="turnstile"/>
        <category label="launch" term="launch"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Welcome to the workshop]]></title>
        <id>https://marginalutility.dev/blog/welcome-to-the-workshop</id>
        <link href="https://marginalutility.dev/blog/welcome-to-the-workshop"/>
        <updated>2026-09-08T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[A home for notes on building small, focused tools with care.]]></summary>
        <content type="html"><![CDATA[<p>Marginal Utility now has a place for writing.</p>
<p>This blog will hold product updates, design decisions, and the lessons that come from building small tools. Some posts will explain what changed. Others will look at why a tool works the way it does, including the choices that didn't survive contact with the real thing.</p>
<!-- -->
<p>The studio's philosophy is simple: software should earn the space it takes up. That means focused products, clear interfaces, and care for the details people encounter every day.</p>
<p>Expect occasional notes from the workshop. No content calendar, no filler.</p>]]></content>
        <author>
            <name>Max Clayton Clowes</name>
            <uri>https://mcclowes.com</uri>
        </author>
        <category label="studio" term="studio"/>
    </entry>
</feed>