Skip to content
Install

Move to synchronized folders

Convert a group-based project to Xcode 16's folder format, verified by building it before and after.

Xcode 16 introduced synchronized folders. Instead of listing every file in the project, a target points at a folder and picks up whatever is inside it. That gives you fewer merge conflicts in project.pbxproj, and new files show up without being added by hand.

Older projects use groups. sochi migrate converts them, and sochi needs the new format before it can add targets.

Terminal window
sochi migrate --dry-run

sochi lists each folder it would convert and which targets use it. It also lists groups it would leave alone, with the reason.

Terminal window
sochi migrate

Each group that matches a real folder on disk becomes a synchronized folder. sochi keeps every target building exactly what it built before:

  • Files a target didn’t use are listed as exceptions for that target. A file that sits in the folder but wasn’t in the project stays out of the app.
  • Per-file compiler flags carry over.
  • .xcconfig files inside a converted folder stay attached to their configurations.

Before writing anything, sochi builds the project twice, once as it is and once converted. Both builds use the device SDK without signing. If the compiled sources or the files bundled into any product differ, sochi stops, lists the differences, and changes nothing.

✓ builds identically (148 compiled sources, 37 bundled files across 3 products)
✓ converted 6 folders · the project now needs Xcode 16 or later

Running migrate again changes nothing.

sochi leaves a group as it is when a folder can’t express it exactly. The reasons include:

  • It isn’t backed by a folder (a virtual group).
  • Its folder doesn’t exist.
  • A file is in a Copy Files or other build phase besides Sources and Resources.
  • A file has per-file attributes, such as a public header setting.
  • A subgroup doesn’t match a folder inside it.
  • A file lives outside the folder, is missing on disk, or is referenced twice.
  • It contains a folder reference.

Groups made only of SDK frameworks or build products aren’t reported. The Products group is never touched.

Terminal window
sochi migrate --move-files --dry-run
sochi migrate --move-files

--move-files first gives each virtual or mismatched group a real folder, named after the group, inside its parent’s folder. It moves the group’s files there and updates build settings that point at them. Then it converts as usual and verifies the build. If anything differs, it moves every file back.

sochi won’t move a group when:

  • The destination folder already exists.
  • A file is missing, outside the project, or referenced twice.
  • A file’s path is used in an .xcconfig, a scheme or a build-phase script, which sochi won’t rewrite.
  • The group’s name can’t be used as a folder name.

Review the moves with git status afterwards.

Option Effect
--project <path> A folder or .xcodeproj. Defaults to the current folder.
--dry-run Show what would change without writing. With --move-files, lists the files per folder.
--no-verify Skip the two builds. The checks that don’t need a build still run.
--force Convert a project that looks generated by XcodeGen or Tuist.
--move-files Give virtual groups real folders by moving their files.

If the project doesn’t build as it is, sochi can’t compare the builds. Fix the build first, or pass --no-verify to rely on the other checks only.