Xcode and Swift project starter files
Choose what your project has and get three files you can drop into a new repository: a .gitignore for Xcode and Swift, a Package.swift for a new Swift package, and Shared, Debug and Release .xcconfig files. Every block has a one-line reason above it, so you can delete what you do not want. The files are built in your browser and nothing is uploaded.
Ignore patterns follow github/gitignore (CC0-1.0). Package.swift names follow Swift's PackageDescription for tools versions 5.7 to 6.4. Build setting names are from Apple's Build Settings reference. Checked 2026-11-01. Comments inside the files are in English.
Options
Ignoring a file is not the same as keeping a key safe. It only stops new commits: a file that was ever committed stays in the history, and a key in a public repository must be treated as leaked. Keep keys outside the project folder and revoke any key that was committed.
Preview
.gitignore
# .gitignore for Xcode and Swift projects
# Based on github/gitignore (Swift.gitignore, Global/Xcode.gitignore, Global/macOS.gitignore), licence CC0-1.0.
# Source: https://github.com/github/gitignore, checked 2026-11-01. Blocks marked "added" are not in those files.
# Your own window layout, breakpoints and open files. They differ on every Mac, so committing them only causes merge conflicts.
# xcuserdata/ is in Swift.gitignore; *.xcuserstate is added (older projects kept it outside xcuserdata).
xcuserdata/
*.xcuserstate
# Build output. Xcode keeps DerivedData outside the project unless you moved it; ignore it in case you did. Added.
DerivedData/
build/
# Archives and debug symbols you export for upload. Large, and rebuilt from the source. From Swift.gitignore.
*.ipa
*.dSYM.zip
*.dSYM
# Header maps and Playground scratch files that Xcode regenerates. From Swift.gitignore.
*.hmap
timeline.xctimeline
playground.xcworkspace
# .build/ is where swift build puts downloaded packages and build output. From Swift.gitignore.
# .swiftpm/ is local state that Xcode and SwiftPM write; Swift.gitignore lists it only as a comment, so this line is added.
.build/
.swiftpm/
# Package.resolved is not ignored on purpose. Commit it in an app so every build uses the same dependency versions.
# A library usually ignores it, because the apps that use the library choose their own versions.
# Finder folder settings that macOS drops into every folder. From Global/macOS.gitignore.
.DS_Store
# Keys and local settings: App Store Connect API keys (.p8), signing certificates (.p12), .env files. Added.
# Ignoring only stops new commits. A file that is already committed stays in the history, and anyone with the repository can read it.
# Keep keys out of the project folder, and revoke any key that was ever committed.
*.p8
*.p12
.env
.env.*
A file that Git already tracks stays tracked after you add it here. Run git rm -r --cached <path> once to stop tracking it.
How it works
- •.gitignore: tick what your project uses. The patterns follow GitHub's gitignore templates for Swift, Xcode and macOS (public domain, CC0-1.0); blocks that are not in those templates say "added". Package.resolved is your choice: commit it for apps, usually ignore it for libraries.
- •Package.swift: the first line is the swift-tools-version comment. Platform names such as .iOS(.v18) only exist from a given tools version, so the page only offers the versions that your chosen tools version knows, and it writes executableTarget, testTarget and product lines the way Swift's PackageDescription documents them. A dependency is a URL, a version for from:, and the product to import.
- •.xcconfig: Shared holds what every build uses; Debug and Release include it with #include and add their own settings. All setting names come from Apple's Build Settings reference through the same data as the build settings tool, and the finished files are run through its checker. A URL typed in the example field has every // written as /$()/ so Xcode does not read it as a comment.
What it does not do
- •It does not create an Xcode project or the folders and Swift files of a package; it lists the folders to make. For a full package skeleton, swift package init does that.
- •It does not know your project. A generated .gitignore is a starting point: read each block, and run git status to see what Git still tracks.
- •It does not check that a dependency URL or version exists, and it does not run swift build for you. Dependencies are written as from: versions only (not branches, exact versions or traits).
- •It does not keep secrets out of your repository. Ignore patterns only stop new commits; a key that was committed once stays in the history.
- •Comments inside the generated files are in English; setting and API names are never translated.
Questions
- Should I commit Package.resolved?
- For an app, yes: it pins every dependency to the exact version you tested, so teammates and build servers get the same code. For a library, usually no: the app that uses your library resolves its own versions, so your file would not be used. The .gitignore tab lets you pick either.
- I added a file to .gitignore but Git still shows changes. Why?
- Ignore rules only apply to files Git is not tracking yet. Run git rm -r --cached path/to/file once, commit, and the file stays on your disk but leaves the repository. It remains in older commits; if it held a secret, treat the secret as leaked and replace it.
- Which swift-tools-version should I pick?
- The oldest one that has everything you use, because it is the oldest Swift that can open the package. Platform names such as .iOS(.v18) or .macOS(.v26) only exist from tools 6.0 and 6.2, and the list on this page only offers names your chosen tools version knows. Tools 6.0 and later also compile in the Swift 6 language mode unless you keep Swift 5 mode.
- Swift Testing or XCTest for a new package?
- Swift Testing (import Testing, @Test) is the newer choice for unit tests and needs a Swift 6 toolchain. XCTest is still needed for UI tests and performance tests, and both can live in the same test target. The manifest line is the same .testTarget either way; only the test files differ.
- How do I put a URL in an .xcconfig file?
- // starts a comment anywhere in a line, so API_URL = https://example.com is read as https:. Write API_URL = https:/$()/example.com: the empty $() keeps the two slashes apart in the file and Xcode reads https://example.com. The .xcconfig tab on this page writes it that way for you.
- How do I use the .xcconfig files in Xcode?
- Add the three files to the project folder, select the project (not a target), open the Info tab and, under Configurations, choose Debug.xcconfig for Debug and Release.xcconfig for Release. A value typed in a target's Build Settings tab beats the file, so clear it there to let the file win.