Thursday, September 17, 2026

Xcode’s New .xcproj Files Are JSON

Apple:

Xcode now supports a JSON-based project format (.xcproj) that’s more readable, merge-friendly, and easier for coding agents to edit. Enable it in the file inspector. Projects using .xcproj also open in earlier versions of Xcode 27. Learn more in Updating your Xcode project configuration file format.

Fatbobman:

[The] new project.xcproj caught my eye. What it replaces is project.pbxproj, the build graph inside the .xcodeproj bundle, not the bundle itself.

[…]

In the age of agents, the drawbacks of pbxproj are amplified further. A great many IDs carry both object identity and cross-references, so an agent modifying a project usually has to locate the right object in a flat table, then update several mutually referencing places in step, all while trying to keep the serialized output faithful to Xcode’s conventions.

[…]

From a flat ID table to a tree that mirrors the UI: instead of dumping everything into objects, it unfolds into structures like files / targets / build-settings, so diffs look closer to the operations you actually performed in the interface;

The direction of relationships is reversed: a file can declare which targets it belongs to via target-membership, so adding a file no longer means editing several mutually referencing places at once;

Simon B. Støvring:

Developers have been screaming for a friendlier Xcode project format for years. I’m one of them.

Tony Arnold:

I’ve been waiting for something like this for most of my career! 🎉

Rob Napier:

It does feel like another case of “we’ve quickly done a thing to help AI that we’ve been unwilling to do for years to help humans.” I’m seeing that happen across the industry.

It is very welcome and appreciated, and lots of thanks to the teams involved. It’s also frustrating that it took “it can help AI” to make it happen.

Apple:

xcode-project-format is a Swift library for reading, writing, and manipulating Xcode’s JSON-based project.xcproj format. It models the format as a rich set of value types nested under a single namespace, XCSchema, so consumers get precise, typed access to a project’s structure instead of hand-parsing JSON.

The goal is to give the ecosystem a shared, accurate model of the Xcode project format — so tools like generators, linters, verifiers, and validators don’t each have to reverse-engineer the format from scratch.

Helge Heß:

Didn’t most people switch to local SPM projects anyways? Those are the new xcproj that have to be replaced with sth sensible 🙃

Fatbobman:

What the community has actually been waiting years for is a project manifest along the lines of Package.swift: something written by people, read by people, and reviewed by people, rather than a more modern encoding of the IDE’s internal database.

Previously:

Update (2026-09-23): John Gruber:

The old .pbxproj project format was not XML; it was an old NeXT-style “ASCII” property list — a file format that is surprisingly JSON-like considering that it predates not only JSON, but JavaScript (JSON = JavaScript Object Notation).

14 Comments RSS · Twitter · Mastodon


> It does feel like another case of “we’ve quickly done a thing to help AI that we’ve been unwilling to do for years to help humans.” I’m seeing that happen across the industry.

They should do the same thing for XIBs and Storyboards...for AI of course. Then SwiftUI would be cooked and they know it.


And the absurdity is that modern day agents are quite capable or parsing and modifying the existing projects and workspaces. Or Storyboards, for that matter.


> And the absurdity is that modern day agents are quite capable or parsing and modifying the existing projects and workspaces. Or Storyboards, for that matter.

Yea I was calling for it to be open for this part:

> The goal is to give the ecosystem a shared, accurate model of the Xcode project format — so tools like generators, linters, verifiers, and validators don’t each have to reverse-engineer the format from scratch.

I don't think they have to change the format from XML to JSON or anything like that - but lots of people don't want to build tools around a moving target.


xcodegen already exists, if you are looking to deal with a yml instead of xml or json.


If I may be excused for a brief "old man shakes fist at cloud" moment… apologies, but…
It saddens me to see Apple so cavalierly embrace Filename Extensions in *2026*. We have lost SOOO much, it almost makes me cry.


ObjC4Life said: "I don't think they have to change the format from XML to JSON or anything like that - but lots of people don't want to build tools around a moving target."

Agreed! The answer to this is proper documentation, not a new file format.

I don't even see documentation of the format. There's just a Swift library for it. They say one of the goals is "Make the file easily readable by humans", but if you aren't using their library, you still have to guess how it works.

It's crazy that they're finally admitting that such attributes as "Reduce merge conflicts in project files, and make them feel justified when they occur" are worthwhile, and they've just been ignoring them for the past 20+ years.

I wonder if Apple will someday admit that people want to read and write Numbers and Pages files, too, and if they will solve that by documenting the file format, or inventing yet another file format and publishing a Swift library for it.


There's documentation for the format within the library, and the generated form of the documentation is online. It explains what all the types are and how they relate, and what the constraints should be.

> It's crazy that they're finally admitting that such attributes as
> "Reduce merge conflicts in project files, and make them feel
> justified when they occur" are worthwhile, and they've just
> been ignoring them for the past 20+ years.

It's incorrect to say that Apple has just been ignoring them. For a portion of that time, I was responsible for the project file format, and reducing merge conflicts was always something we were working towards. I worked on an earlier version of the JSON format before I retired in 2024, and the last thing I did on the format was the Xcode 16.3 format, which also reduced overhead and made things clearer and less risky to merge by eyeballing. (I don't know if the shipped JSON format is based on my work or is new work, or a bit of both.) And a couple other people did substantial work to implement the Xcode 16 "Folders" feature to remove a lot of unnecessary overhead from project files in cases where the filesystem structure and project structure were intended to match.

The pbxproj format, as it stood, was actually designed to *reduce* the occurrence of merge conflicts by structuring the global IDs of objects created on different systems so they'd appear in different places. The main sources of merge conflicts in general were when multiple people would add the same type of thing at the same time, or add things to the same place in the same container at the same time (e.g. at the end). The problem was that nobody seemed to be able to wrap their head around the contents of the project file because it didn't look like the visual structure in the IDE, so people just threw their hands up and said "can't merge, treat it as binary" even though they didn't have to.

I wrote an explanation of the pbxproj format, how the objects relate to each other, and how merge conflicts arise and should be dealt with on the old Xcode-users mailing list many years ago. Unfortunately Apple's archive no longer seems to be up. The post is from September 28, 2012 in the thread "git rebase corrupts Xcode projects" if anyone happens to know of an archive of the posts.



Oh, and I can assure everyone that when I was working on this stuff, making anything easier to use with LLM-based tooling was not one of my considerations.


That Gruber update sure reads a lot like a rehash of things Fatbobman had already said but Gruber didn't link to.


Feels like when we ASP.NET developers moved from web.config to appsettings.json.

Would not want to go back, tbh.


"The pbxproj format, as it stood, was actually designed to *reduce* the occurrence of merge conflicts by structuring the global IDs of objects created on different systems so they'd appear in different places."

Waitaminute...so all this time, I was supposed to be merging my pbxproj files by manually tracking 24-digit hex IDs? And the IDE was intentionally putting them in seemingly random places for my benefit? And this was described in an email (now gone) on a mailing list (now gone) back in 2012?

"We thought this was the right solution" somehow seems even worse to me than "We hadn't gotten around to it yet".


>Feels like when we ASP.NET developers moved from web.config to appsettings.json.

Or from the old-style .csproj with lots of explicit file names and GUIDs. Or especially the old .sln (tons and tons of GUIDs) vs. the modern .slnx (look ma, I can actually understand at a glance what it _means_!).

The key goal should be to have _less_ code, fewer lines, fewer obscure IDs. This makes it easier for developers to hand-edit the files, which, even when you're _usually_ not going to do that makes merge conflicts so much easier to understand as well as resolve.

The new format seems better, but still a far cry from e.g. XcodeGen.


The main issue I have with Xcode projects is that when using folders (instead of groups) if I move a file it will forget which targets other files are excluded from. For example, today I moved a source file to a different folder and my project stopped compiling because 10 test classes got “added” to the non-test target.

Leave a Comment