# XcodeGen: Generate an Xcode Project From a YAML Spec

> XcodeGen builds .xcodeproj files from a project.yml spec and your folder structure, so the project file can stay out of git. Here is how it installs, what the spec actually controls, and where it stops being the right tool.

**yonaskolb/XcodeGen** — A Swift command line tool for generating your Xcode project

- Repository: https://github.com/yonaskolb/XcodeGen
- Stars: 8,810 · Forks: 910
- Language: Swift
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/yonaskolb-xcodegen

## What XcodeGen replaces, and who it is for

The file an Xcode project is stored in, project.pbxproj, is a generated-looking blob that developers edit constantly and version control handles badly. Two branches that add files or targets to the same project tend to conflict in ways that are tedious to resolve by hand. XcodeGen's answer is to stop treating that file as source. The README states the tool generates your Xcode project using your folder structure and a project spec, and that the spec is a YAML or JSON file defining targets, configurations, schemes and custom build settings. Because source directories are parsed automatically, the project file becomes an artifact you can regenerate rather than a document you edit.

The audience is iOS and macOS teams that already keep their sources in a predictable directory layout. The README lists the payoff directly: remove your .xcodeproj from git, which means no more merge conflicts, and groups and files in Xcode are always synced to your directories on disk. If your team's pain is a project file that only one person understands, this is aimed at you. If your team rarely touches the project file, the spec is one more thing to maintain for little return.

## How the spec, the folder scan and the generated project fit together

The mechanism is a one-way pipeline. You write a spec, XcodeGen resolves it, scans the directories the spec points at, and writes a new .xcodeproj. The README gives an example spec with a name, an include of base_spec.yml, an options block with bundleIdPrefix, a packages block resolving Yams from a URL and version, and two targets. The MyApp target declares type: application, platform: iOS, deploymentTarget: "10.0", sources: [MyApp], per-configuration settings, and a dependencies list mixing target, carthage, framework, sdk and package entries. MyFramework is declared separately as a framework target, and MyApp depends on it by target name.

Two properties of that design matter. First, sources are directories, not file lists. You point at MyApp and the folder contents are picked up, which is why adding a file means adding it to disk rather than to a project editor. Second, the spec is composable: include pulls in base_spec.yml, and the README notes that distributing the spec across multiple files is supported for sharing and overriding. The dependency entries also show that XcodeGen does not resolve your dependencies itself. It records that a Carthage framework or a Swift package should be linked; fetching it is still Carthage's or Swift Package Manager's job. The README's claim that Carthage frameworks integrate without any work refers to the project wiring, not to building them.

## Install XcodeGen on macOS and generate a first project

The README says to make sure the latest stable, non-beta version of Xcode is installed first. Four install paths are documented: Mint, Make, Homebrew, and Swift Package Manager. Homebrew is the shortest.

```bash
brew install xcodegen
```

After that, xcodegen should be on your PATH. If the shell reports xcodegen: command not found, the install did not land in a directory your PATH includes, and the Make route lets you see where the binary goes: it copies the executable to /usr/local/bin/xcodegen and the SettingPresets folder to /usr/local/share/xcodegen/SettingPresets.

```bash
git clone https://github.com/yonaskolb/XcodeGen.git
cd XcodeGen
make install
```

The Makefile builds with swift build --disable-sandbox -c release --arch arm64 --arch x86_64, so it produces a universal release binary. Mint is the third documented option:

```bash
mint install yonaskolb/xcodegen
```

For a first run, create project.yml in the directory that holds your sources, then generate. The README states that xcodegen generate looks for a project spec in the current directory called project.yml and writes a project named after the spec.

```bash
xcodegen generate
```

The README also documents xcodegen dump, which outputs the resolved spec in several formats or writes it to a file. That command is the fastest way to confirm what XcodeGen actually understood after includes and overrides have been applied, and it is worth running before you commit a spec you have just restructured.

## The flags that matter once the project is in CI

The README documents four generate options. --spec takes a path to a .yml or .json spec and defaults to project.yml; the README notes that multiple spec files can be linked by comma separating them, with all other flags applying to each. --project sets the output directory and defaults to the directory the spec lives in. --quiet suppresses informational and success messages. --use-cache prevents unnecessary generation: a cache file is written when a project is generated, and if the spec and every file it contains are unchanged on a later run, the project is not regenerated. --cache-path overrides the cache location, which the README says defaults to ~/.xcodegen/cache/{PROJECT_SPEC_PATH_HASH}.

The cache is the one flag with a real failure mode. It compares the spec and the files it contains, so a build that depends on something outside that set, such as a generated source file produced by an earlier build step, can be skipped when you expected a fresh project. On a clean CI machine the cache is empty and the flag buys nothing; locally it saves time on repeated runs. If generated output looks stale, deleting the cache file at the documented default path is the direct test.

## Where XcodeGen is the wrong choice

The spec is the source of truth, and that cuts both ways. Any setting changed inside Xcode and not written back into project.yml disappears the next time you generate. Teams that treat the project file as a place to experiment will find their changes overwritten, and the README does not describe a merge or import path from an existing .xcodeproj back to a spec. Adopting XcodeGen on a large existing project therefore means transcribing that project's configuration by hand.

Version drift is the second constraint. The generated output depends on the XcodeGen release that produced it, and the release notes show a steady stream of versions, with 2.46.0, 2.45.4 and 2.45.3 in 2026 alone. If one developer runs a Homebrew-installed build and CI runs a different one, you can get diffs in generated files that have nothing to do with your code. Pinning the version everywhere is not optional in practice.

Finally, the tool only emits Xcode projects. The repository topics include xcode and xcodeproj, and nothing in the README suggests output for another build system. A team that also ships an Android app will keep a separate build definition for it, and queries like xcodegen android have no answer here.

## XcodeGen compared with Tuist

The README lists Tuist, Xcake and struct as alternatives, so the project is explicit that it is not the only option. The meaningful difference with Tuist is where the project definition lives. XcodeGen's spec is a declarative YAML or JSON document that the tool reads and turns into a project file. Tuist describes projects in Swift, which means the manifest is compiled code that can compute values, call functions and share logic across targets. If your configuration is mostly static and you want the shortest path from a readable file to a project, XcodeGen's approach is simpler to review in a pull request, because a YAML diff is a diff of data. If your project definition needs branching logic or generated target sets, a Swift manifest expresses that without templating tricks.

Xcake and struct are also named in the README as alternatives, and the attributions section credits XcodeProj, Yams, PathKit and SwiftCLI as the libraries XcodeGen is built on. That matters for evaluation: XcodeGen's project-writing layer is the same one Tuist maintains, so the difference between them is the manifest language and the surrounding tooling, not the file format being written.

## Licence, upgrades and what maintenance costs

XcodeGen is MIT licensed, and the LICENSE file is at the repository root. MIT is permissive: it allows use, modification and redistribution with the licence and copyright notice retained. That is a statement about the licence text, not legal advice for your situation; if you redistribute the binary or embed XcodeGenKit, have your own counsel read the terms.

The last push to the repository was on 2026-09-13, and the most recent release is 2.46.0 from 2026-07-16. The Makefile pins VERSION = 2.46.0, and the release target rewrites the version string in Sources/XcodeGen/main.swift and the dependency example in README.md before committing, which tells you the version is maintained in more than one place and that a release touches source, docs and the Makefile together. Upgrading is a binary swap for Homebrew and Mint users, but the version constant also appears in the README's Swift Package Manager snippet, so a project consuming XcodeGenKit as a dependency tracks the same numbering.

The upgrade cost is mostly in the spec, not the binary. The README points to Docs/ProjectSpec.md for all available properties, and that document, not the README, is where you check whether a key you rely on has changed. The repository also carries SettingPresets/, which the Makefile installs alongside the binary; those presets supply defaults for build settings, so a release that changes them can alter generated output even when your spec is untouched. Diffing the generated project after an upgrade is the practical check.

## Conclusion

Adopt XcodeGen if your team keeps hitting merge conflicts in project.pbxproj, or if you want a project that can be regenerated on CI from a spec plus the files on disk. Do not adopt it if you rely on hand-edited Xcode settings that never make it back into the spec, or if you need Gradle-style Android builds, since it only emits Xcode projects. Before committing, verify three things: that your project.yml produces the targets and schemes you expect, that everyone on the team installs the same XcodeGen release so generated output stays identical, and that nothing you currently change inside Xcode is missing from the spec. The acceptance test is simple: delete the .xcodeproj, run xcodegen generate, and see whether the project still builds.

## FAQ

### What does XcodeGen do?

It is a Swift command line tool that generates an Xcode project from a YAML or JSON project spec plus your folder structure. The README states that source directories are parsed automatically and referenced appropriately, so groups and files in Xcode stay synced to what is on disk.

### How do I install XcodeGen?

The README documents Mint, Make, Homebrew and Swift Package Manager. Homebrew is a single command, brew install xcodegen, and the Make route clones the repository and runs make install, which places the binary at /usr/local/bin/xcodegen.

### How do I install XcodeGen on a Mac?

The README says to make sure the latest stable, non-beta version of Xcode is installed first, then install with Homebrew, Mint, Make or Swift Package Manager. The Makefile builds a universal release binary for arm64 and x86_64.

### How do I use XcodeGen?

Write a project.yml spec in your project directory, then run xcodegen generate. The README states it looks for project.yml in the current directory and generates a project with the name defined in the spec; xcodegen dump prints the resolved spec if you want to check what was understood.

### What is XcodeGen?

It is a command line tool written in Swift that generates your Xcode project using your folder structure and a project spec, which the README describes as a YAML or JSON file defining targets, configurations, schemes and custom build settings.

### How does XcodeGen compare with other project generators?

The README names Tuist, Xcake and struct as alternatives, and credits XcodeProj, Yams, PathKit and SwiftCLI as the libraries it is built on. The main difference from Tuist is that XcodeGen reads a declarative YAML or JSON spec rather than a Swift manifest.

## Sources

- [Issues](https://github.com/yonaskolb/XcodeGen/issues)
- [License: MIT](https://github.com/yonaskolb/XcodeGen/blob/master/LICENSE)
- [README](https://github.com/yonaskolb/XcodeGen/blob/master/README.md)
- [Releases](https://github.com/yonaskolb/XcodeGen/releases)
- [yonaskolb/XcodeGen on GitHub](https://github.com/yonaskolb/XcodeGen)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/yonaskolb-xcodegen
