Xcode on steroids
Easy and fast
Bootstrap, maintain, and interact with
Xcode projects at any scale
GET STARTED
path = InfoPlistContentProvider.swift; sourceTree = "<group>"; }; OBJ_153 /* LinkGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkGenerator.swift; sourceTree = "<group>"; }; OBJ_154 /* ProjectFileElements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectFileElements.swift; sourceTree = "<group>"; }; OBJ_155 /* ProjectGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectGenerator.swift; sourceTree = "<group>"; }; OBJ_156 /* ProjectGroups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectGroups.swift; sourceTree = "<group>"; }; OBJ_157 /* SchemesGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchemesGenerator.swift; sourceTree = "<group>"; }; OBJ_158 /* TargetGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetGenerator.swift; sourceTree = "<group>"; }; OBJ_159 /* WorkspaceGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceGenerator.swift; sourceTree = "<group>"; }; , OBJ_1639 /* AEXML.framework in Frameworks */, OBJ_1640 /* PathKit.framework in Frameworks */, OBJ_1641 /* TuistSupport.framework in Frameworks */, OBJ_1642 /* SPMUtility.framework in Frameworks */, OBJ_1643 /* Basic.framework in Frameworks */, OBJ_1644 /* SPMLibc.framework in Frameworks */, OBJ_1645 /* clibc.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; };/* Begin PBXBuildFile section */ B90F3BFE238DB50A00102CB7 /* Manifest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90F3BFD238DB50A00102CB7 /* Manifest.swift */; }; OBJ_1007 /* Signals.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_544 /* Signals.swift */; }; OBJ_1014 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_545 /* Package.swift */; }; OBJ_1020 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_636 /* Package.swift */; }; OBJ_1026 /* CocoaPodsNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_43 /* CocoaPodsNode.swift */; }; OBJ_1027 /* FrameworkNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_44 /* FrameworkNode.swift */; }; B90F3B5C238DB48E00102CB7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = OBJ_1 /* Project object */; proxyType = 1; remoteGlobalIDString = "SwiftPM::Basic"; remoteInfo = Basic; }; B90F3B5D238DB48E00102CB7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = OBJ_1 /* Project object */; proxyType = 1; remoteGlobalIDString = "SwiftPM::SPMLibc"; remoteInfo = SPMLibc; }; B90F3B5E238DB48E00102CB7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = OBJ_1 /* Project object */; proxyType = 1; remoteGlobalIDString = "SwiftPM::clibc"; remoteInfo = clibc; }; OBJ_138 /* DotGraphNodeAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotGraphNodeAttribute.swift; sourceTree = "<group>"; }; OBJ_139 /* DotGraphType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotGraphType.swift; sourceTree = "<group>"; }; OBJ_14 /* FileElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileElement.swift; sourceTree = "<group>"; }; OBJ_140 /* GraphToDotGraphMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphToDotGraphMapper.swift; sourceTree = "<group>"; }; OBJ_142 /* AbsolutePath+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbsolutePath+Extras.swift"; sourceTree = "<group>"; }; OBJ_143 /* Array+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extras.swift"; sourceTree = "<group>"; }; OBJ_144 /* Xcodeproj+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Xcodeproj+Extras.swift"; sourceTree = "<group>"; }; OBJ_146 /* BuildPhaseGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildPhaseGenerator.swift; sourceTree = "<group>"; }; OBJ_147 /* ConfigGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigGenerator.swift; sourceTree = "<group>"; }; OBJ_148 /* DerivedFileGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DerivedFileGenerator.swift; sourceTree = "<group>"; }; OBJ_149 /* FileGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileGenerator.swift; sourceTree = "<group>"; }; OBJ_15 /* FileList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path =<<<<<<< HEAD:project.pbxproj = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileElement.swift; sourceTree = "<group>"; }; OBJ_140 /* GraphToDotGraphMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphToDotGraphMapper.swift; sourceTree = "<group>"; }; OBJ_142 /* AbsolutePath+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbsolutePath+Extras.swift"; sourceTree = "<group>"; }; OBJ_143 /* Array+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extras.swift"; sourceTree = "<group>"; }; OBJ_144 /* Xcodeproj+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Xcodeproj+Extras.swift"; sourceTree = "<group>"; }; OBJ_146 /* BuildPhaseGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildPhaseGenerator.swift; sourceTree = "<group>"; } ; OBJ_147 /* ConfigGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigGenerator.swift; sourceTree = "<group>"; }; OBJ_148 /* DerivedFileGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DerivedFileGenerator.swift; sourceTree = "<group>"; }; OBJ_149 /* FileGenerator.swift *=========== {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileGenerator.swift; sourceTree = "<group>"; }; OBJ_15 /* FileList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileList.swift; sourceTree = "<group>"; }; OBJ_150 /* GeneratedProject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift;>>>>>>> 77976da35a11db4580b80ae27e8d65caf5208086:project.pbxprojPBXBuildFile section */ B90F3BFE238DB50A00102CB7 /* Manifest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90F3BFD238DB50A00102CB7 /* Manifest.swift */; }; OBJ_1007 /* Signals.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_544 /* Signals.swift */; }; OBJ_1014 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_545 /* Package.swift */; }; OBJ_1020 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_636 /* Package.swift */; }; OBJ_1026 /* CocoaPodsNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_43 /* CocoaPodsNode.swift */; }; OBJ_1027 /* FrameworkNode.swift in Sources */ OBJ_16 /* Headers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Headers.swift; sourceTree = "<group>"; }; OBJ_1631 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 0; files = ( OBJ_1632 /* TuistSupportTesting.framework in Frameworks */, OBJ_1633 /* TuistKit.framework in Frameworks */, OBJ_1634 /* Signals.framework in Frameworks */, OBJ_1635 /* ProjectDescription.framework in Frameworks */, OBJ_1636 /* TuistGenerator.framework in Frameworks */, OBJ_1637 /* TuistCore.framework in Frameworks */, OBJ_1638 /* XcodeProj.framework in Frameworks */path = InfoPlistContentProvider.swift; sourceTree = "<group>"; }; OBJ_153 /* LinkGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkGenerator.swift; sourceTree = "<group>"; }; OBJ_154 /* ProjectFileElements.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectFileElements.swift; sourceTree = "<group>"; }; OBJ_155 /* ProjectGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectGenerator.swift; sourceTree = "<group>"; }; OBJ_156 /* ProjectGroups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectGroups.swift; sourceTree = "<group>"; }; OBJ_157 /* SchemesGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchemesGenerator.swift; sourceTree = "<group>"; }; OBJ_158 /* TargetGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetGenerator.swift; sourceTree = "<group>"; }; OBJ_159 /* WorkspaceGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkspaceGenerator.swift; sourceTree = "<group>"; }; , OBJ_1639 /* AEXML.framework in Frameworks */, OBJ_1640 /* PathKit.framework in Frameworks */, OBJ_1641 /* TuistSupport.framework in Frameworks */, OBJ_1642 /* SPMUtility.framework in Frameworks */, OBJ_1643 /* Basic.framework in Frameworks */, OBJ_1644 /* SPMLibc.framework in Frameworks */, OBJ_1645 /* clibc.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; };/* Begin PBXBuildFile section */ B90F3BFE238DB50A00102CB7 /* Manifest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B90F3BFD238DB50A00102CB7 /* Manifest.swift */; }; OBJ_1007 /* Signals.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_544 /* Signals.swift */; }; OBJ_1014 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_545 /* Package.swift */; }; OBJ_1020 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_636 /* Package.swift */; }; OBJ_1026 /* CocoaPodsNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_43 /* CocoaPodsNode.swift */; }; OBJ_1027 /* FrameworkNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_44 /* FrameworkNode.swift */; }; B90F3B5C238DB48E00102CB7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = OBJ_1 /* Project object */; proxyType = 1; remoteGlobalIDString = "SwiftPM::Basic"; remoteInfo = Basic; }; B90F3B5D238DB48E00102CB7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = OBJ_1 /* Project object */; proxyType = 1; remoteGlobalIDString = "SwiftPM::SPMLibc"; remoteInfo = SPMLibc; }; B90F3B5E238DB48E00102CB7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = OBJ_1 /* Project object */; proxyType = 1; remoteGlobalIDString = "SwiftPM::clibc"; remoteInfo = clibc; }; OBJ_138 /* DotGraphNodeAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotGraphNodeAttribute.swift; sourceTree = "<group>"; }; OBJ_139 /* DotGraphType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotGraphType.swift; sourceTree = "<group>"; }; OBJ_14 /* FileElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileElement.swift; sourceTree = "<group>"; }; OBJ_140 /* GraphToDotGraphMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphToDotGraphMapper.swift; sourceTree = "<group>"; }; OBJ_142 /* AbsolutePath+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AbsolutePath+Extras.swift"; sourceTree = "<group>"; }; OBJ_143 /* Array+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Extras.swift"; sourceTree = "<group>"; }; OBJ_144 /* Xcodeproj+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Xcodeproj+Extras.swift"; sourceTree = "<group>"; }; OBJ_146 /* BuildPhaseGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildPhaseGenerator.swift; sourceTree = "<group>"; }; OBJ_147 /* ConfigGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigGenerator.swift; sourceTree = "<group>"; }; OBJ_148 /* DerivedFileGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DerivedFileGenerator.swift; sourceTree = "<group>"; }; OBJ_149 /* FileGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileGenerator.swift; sourceTree = "<group>"; }; OBJ_15 /* FileList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path =
WORKSPACES
Describe & generate
Describe your apps and the frameworks they depend on. If they have unit or ui test targets you can define them too; even Swift package dependencies.
Project.swift
import ProjectDescription
import ProjectDescriptionHelpers
let project = Project.featureFramework(
name: "Home",
dependencies: [
.project(target: "Features", path: "../Features"),
.framework(path: "Carthage/Build/iOS/SnapKit.framework")
.package(product: "KeychainSwift")
]
)
DESIGN
Principles
Tuist is not a project generator, it’s a tool to empower you to build apps of any scale.
Plain and easy language
Describe your projects as you think about them. Build settings, phases and other intricacies become implementation details.
Reusability
Instead of maintaining multiple Xcode projects, describe your project once, and reuse it everywhere.
Focus
Generated projects are optimized for your focus and productivity. They contain just what you need for the task at hand.
Early errors
If we know your project won’t compile, we fail early. We don't want you *to* waste time waiting for the build system to bubble up errors.
Conventions
Be opinionated about the structure of the projects; define project factories that teams can use to create new projects.
Scale
Tuist is optimized to support projects at scale. Whether your project is 1 target, or 1000, it should make no diffference.
USERS
Reflections
Tuist is a project trusted and supported by developers that are already having fun working with Xcode
OLIVER ATKINSON
"It has really helped out the team and project by creating an environment where defining new modules is easy, modularity allows us to focus and become experts in our individual domains."
SENIOR IOS ENGINEER AT SKY
TYLER NEVELDINE
"Tuist centralizes our entire workspace’s configuration and describes it in a language that we all understand. This increases the readability and approachability of our project tenfold."
IOS LEAD AT DYNAMIC SIGNAL
ROMAIN BOULAY
"Tuist has delivered more than the SoundCloud iOS Collective expected! We aimed to make modularization more accessible and maintainable. We got this... and better build times!."
IOS LEAD AT SOUNDCLOUD
CONTRIBUTE
You can bring more fun to Xcode projects too
Tuist is a welcoming and open source project that is writen in Swift by and for the community
START CONTRIBUTING