<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Developer from Another World</title>
    <description>The latest articles on DEV Community by Developer from Another World (@isekai_kara_no_dev).</description>
    <link>https://dev.to/isekai_kara_no_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4025160%2F2b0218fd-b22a-4f87-a60d-71cb922b106d.png</url>
      <title>DEV Community: Developer from Another World</title>
      <link>https://dev.to/isekai_kara_no_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/isekai_kara_no_dev"/>
    <language>en</language>
    <item>
      <title>Use Xcode MCP Instead of xcodebuild to Save Disk Space and Time in Agentic iOS Development</title>
      <dc:creator>Developer from Another World</dc:creator>
      <pubDate>Sat, 11 Jul 2026 14:28:46 +0000</pubDate>
      <link>https://dev.to/isekai_kara_no_dev/-use-xcode-mcp-instead-of-xcodebuild-to-save-disk-space-and-time-in-agentic-ios-development-2m4j</link>
      <guid>https://dev.to/isekai_kara_no_dev/-use-xcode-mcp-instead-of-xcodebuild-to-save-disk-space-and-time-in-agentic-ios-development-2m4j</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; - When setting up an AI agent for iOS development, the default approach is to have the agent run headless &lt;code&gt;xcodebuild&lt;/code&gt; commands. To save disk space and time, you might point the agent at your active Xcode &lt;code&gt;DerivedData&lt;/code&gt; folder. &lt;strong&gt;I found that this doesn't work.&lt;/strong&gt; While they write to the same directory, &lt;code&gt;xcodebuild&lt;/code&gt; and Xcode.app do not actually share their incremental build state. Instead, they overwrite each other's intermediate files, forcing rebuilds. To fix this, drive headless builds using the Xcode MCP bridge (&lt;code&gt;xcrun mcpbridge&lt;/code&gt;). This allows your agent to use Xcode.app's internal build engine, safely sharing a single &lt;code&gt;DerivedData&lt;/code&gt; folder, drastically reducing disk usage, and preserving fast incremental builds when switching between xcode and agent (terminal).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Agentic Development Disk Space Trap
&lt;/h2&gt;

&lt;p&gt;When doing AI driven iOS development, one of the most common approach is to have our agent operates via the command line (&lt;code&gt;xcodebuild&lt;/code&gt;), while you might be doing some debugging / UI verification in the GUI (&lt;code&gt;Xcode.app&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Because DerivedData folders frequently exceed 10GB–20GB for modern apps, maintaining separate build directories for the human and the agent wastes massive amounts of SSD space. It also wastes time, as the agent cannot benefit from the compilation work you just completed in Xcode.&lt;/p&gt;

&lt;p&gt;It is tempting to pass &lt;code&gt;-derivedDataPath&lt;/code&gt; to your agent's &lt;code&gt;xcodebuild&lt;/code&gt; commands, pointing it exactly at your live Xcode workspace's DerivedData. The goal is to have the agent "pick up where you left off."&lt;/p&gt;

&lt;p&gt;I found that sharing the directory destroys the incremental state for both tools instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Showing that it fails
&lt;/h2&gt;

&lt;p&gt;You can run a targeted test on any active project to see the time penalty yourself.&lt;/p&gt;

&lt;p&gt;Set your project variables:&lt;/p&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/repo/iOS
&lt;span class="nv"&gt;WORKSPACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;GoodNotes.xcworkspace
&lt;span class="nv"&gt;SCHEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;GoodNotes

&lt;span class="c"&gt;# A booted/available simulator UDID - adjust as needed:&lt;/span&gt;
&lt;span class="nv"&gt;SIM_UDID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xcrun simctl list devices available | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-oE&lt;/span&gt; &lt;span class="s1"&gt;'[0-9A-F-]{36}'&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Your Xcode's DerivedData folder location&lt;/span&gt;
&lt;span class="nv"&gt;DD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/DerivedData
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable build durations in Xcode to accurately read the GUI's timings:&lt;/p&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;defaults write com.apple.dt.Xcode ShowBuildOperationDuration &lt;span class="nt"&gt;-bool&lt;/span&gt; YES
&lt;span class="c"&gt;# Restart Xcode after running this&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1 — Build in Xcode (⌘B), then build again.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The second build is a fast, no-op incremental build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — Run &lt;code&gt;xcodebuild&lt;/code&gt; against the same DerivedData.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the exact same scheme, destination, and DerivedData path with no source changes:&lt;/p&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xcodebuild build &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-workspace&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKSPACE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-scheme&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SCHEME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-destination&lt;/span&gt; &lt;span class="s2"&gt;"platform=iOS Simulator,id=&lt;/span&gt;&lt;span class="nv"&gt;$SIM_UDID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-derivedDataPath&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-skipMacroValidation&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-skipPackagePluginValidation&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-skipPackageUpdates&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Despite no code changing, the CLI executes a &lt;strong&gt;full rebuild&lt;/strong&gt;. It recompiles, relinks, and re-signs the application instead of acting incrementally relative to Xcode's previous build.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Build in Xcode again (⌘B).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The build becomes slow again. The CLI run overwrote the shared object files and &lt;code&gt;.swiftmodule&lt;/code&gt;s on disk. Because the intermediate files were modified by a different build driver, Xcode is forced to rebuild a massive portion of the graph.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Verified Time Penalty
&lt;/h2&gt;

&lt;p&gt;Here is the exact performance penalty measured on the app I'm working on. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Build&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Driver&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Time (% of Clean Build)&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Incremental, no changes&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Xcode.app&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;22.7 s (~2.3%)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same tree, immediately after&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;xcodebuild&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;863.0 s (~86.3%)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Incremental, immediately after CLI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Xcode.app&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;300.8 s (~30.1%)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By forcing &lt;code&gt;xcodebuild&lt;/code&gt; into Xcode's DerivedData, the CLI build ran slower than a clean build, and it dragged Xcode's subsequent incremental build from 22.7 seconds up to 300.8 seconds (a ~13× slowdown).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Drive Xcode via MCP
&lt;/h2&gt;

&lt;p&gt;Using xcode MCP, I was able to save SSD space by using a single DerivedData directory, and maintain fast incremental build times.&lt;br&gt;
To accomplish this, use the Xcode MCP bridge (&lt;code&gt;xcrun mcpbridge&lt;/code&gt;), introduced in Xcode 26.&lt;/p&gt;

&lt;p&gt;When your agent uses &lt;code&gt;xcrun mcpbridge&lt;/code&gt; to trigger a build:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;BuildProject&lt;/code&gt; tool calls Xcode.app's internal build system.&lt;/li&gt;
&lt;li&gt;The build executes entirely incrementally, relying exactly on the state you just generated in the GUI.&lt;/li&gt;
&lt;li&gt;Disk space is strictly limited to one DerivedData folder per project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Look at &lt;a href="https://developer.apple.com/documentation/xcode/giving-external-agents-access-to-xcode" rel="noopener noreferrer"&gt;this page&lt;/a&gt; from Apple to see how to enable this for Claude / Codex. In my experience, after running &lt;code&gt;mcp add&lt;/code&gt; command, you can simply ask the agent to use xcode MCP and it knows what to do.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>mobile</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
