Skip to main content
Tuist uses Swift-based manifest files to describe your projects, workspaces, and configuration. This guide explains each manifest type and how to use them effectively.

Manifest Types

Tuist supports three main manifest files:

Project.swift

Defines a single Xcode project with targets, schemes, and settings

Workspace.swift

Groups multiple projects into an Xcode workspace

Tuist.swift

Global configuration and shared settings (formerly Config.swift)

Project.swift

The Project.swift manifest defines an Xcode project and its targets.

Basic Structure

import ProjectDescription

let project = Project(
    name: "MyApp",
    targets: [
        .target(
            name: "MyApp",
            destinations: .iOS,
            product: .app,
            bundleId: "com.example.myapp",
            sources: ["Sources/**"],
            resources: ["Resources/**"]
        )
    ]
)

Key Components

Targets define buildable components:
.target(
    name: "FeatureProfile",
    destinations: .iOS,
    product: .framework,
    bundleId: "com.example.profile",
    deploymentTargets: .iOS("15.0"),
    sources: ["Profile/Sources/**"],
    resources: ["Profile/Resources/**"],
    dependencies: [
        .target(name: "Core"),
        .external(name: "Kingfisher")
    ]
)
Product types:
  • .app - Application
  • .framework - Dynamic framework
  • .staticFramework - Static framework
  • .staticLibrary - Static library
  • .unitTests - Unit test bundle
  • .uiTests - UI test bundle
  • .appExtension - App extension
  • .watch2App - watchOS app

Advanced Features

Add custom build phases:
scripts: [
    // Pre-build script
    .pre(
        script: """
        if which swiftlint >/dev/null; then
            swiftlint
        else
            echo "warning: SwiftLint not installed"
        fi
        """,
        name: "SwiftLint",
        basedOnDependencyAnalysis: false
    ),
    
    // Post-build script
    .post(
        path: "Scripts/upload-symbols.sh",
        name: "Upload Debug Symbols",
        inputPaths: ["$DWARF_DSYM_FOLDER_PATH"],
        outputPaths: []
    )
]
Wrap non-Xcode build systems (KMP, Rust, etc.):
.foreignBuild(
    name: "SharedKMP",
    destinations: .iOS,
    script: """
    eval "$($HOME/.local/bin/mise activate bash --shims)"
    cd $SRCROOT/SharedKMP
    gradle assembleSharedKMPReleaseXCFramework
    """,
    inputs: [
        .folder("SharedKMP/src"),
        .file("SharedKMP/build.gradle.kts")
    ],
    output: .xcframework(
        path: "SharedKMP/build/XCFrameworks/release/SharedKMP.xcframework",
        linking: .dynamic
    )
)
Generate code for resources:
resourceSynthesizers: [
    .strings(),
    .assets(),
    .fonts(),
    .plists(),
    .custom(
        name: "JSONAssets",
        parser: .json,
        extensions: ["json"]
    )
]
Access generated code:
// Strings
let title = MyAppStrings.profileTitle

// Assets
let icon = MyAppAssets.profileIcon.image

// Fonts
let font = MyAppFonts.custom(name: "CustomFont", size: 14)

Workspace.swift

The Workspace.swift manifest groups multiple projects into an Xcode workspace.
import ProjectDescription

let workspace = Workspace(
    name: "MyWorkspace",
    projects: [
        "App",
        "Framework",
        "Packages/**"
    ]
)
Use Workspace.swift when you need to:
  • Group multiple independent projects
  • Share schemes across projects
  • Organize a large codebase into modules
  • Include documentation or non-project files
If you only have one Project.swift, Tuist automatically generates a workspace - you don’t need Workspace.swift

Tuist.swift (Config)

The Tuist.swift manifest (formerly Config.swift) provides global configuration that applies to all projects in your workspace.
import ProjectDescription

let tuist = Tuist(
    project: .tuist(
        generationOptions: .options(
            enableCaching: true
        )
    )
)

Configuration Options

Control how projects are generated:
generationOptions: .options(
    // Enable Tuist Cloud caching
    enableCaching: true,
    
    // Custom Xcode project name
    xcodeProjectName: "MyApp",
    
    // Allow manifest execution without auth
    optionalAuthentication: true,
    
    // Disable sandboxing (dev only)
    disableSandbox: false,
    
    // Additional SPM arguments
    additionalPackageResolutionArguments: [
        "--replace-scm-with-registry"
    ]
)

Project Helpers

Create reusable manifest helpers in Tuist/ProjectDescriptionHelpers/:
import ProjectDescription

public extension Target {
    static func feature(
        name: String,
        dependencies: [TargetDependency] = []
    ) -> Target {
        return .target(
            name: name,
            destinations: .iOS,
            product: .framework,
            bundleId: "com.example.\(name.lowercased())",
            deploymentTargets: .iOS("15.0"),
            sources: ["\(name)/Sources/**"],
            resources: ["\(name)/Resources/**"],
            dependencies: dependencies + [.target(name: "Core")]
        )
    }
    
    static func featureTests(for feature: String) -> Target {
        return .target(
            name: "\(feature)Tests",
            destinations: .iOS,
            product: .unitTests,
            bundleId: "com.example.\(feature.lowercased()).tests",
            sources: ["\(feature)/Tests/**"],
            dependencies: [
                .target(name: feature)
            ]
        )
    }
}

Best Practices

Split large apps into focused projects:
/MyApp
├── App/Project.swift           # Main app
├── Features/
   ├── Profile/Project.swift   # Profile feature
   └── Settings/Project.swift  # Settings feature
└── Core/Project.swift          # Shared utilities
Leverage Swift’s type system:
enum BundleIdentifiers {
    static let app = "com.example.app"
    static let framework = "com.example.framework"
}

.target(
    bundleId: BundleIdentifiers.app
)
Use environment variables for sensitive data:
settings: .settings(
    base: [
        "DEVELOPMENT_TEAM": Environment.developmentTeam.getString(default: "")
    ]
)
.env
TUIST_DEVELOPMENT_TEAM=ABCDEF1234

Next Steps

Generated Projects

Learn how manifests become Xcode projects

Workspaces

Organize multi-project workspaces

Architecture

Understand Tuist’s architecture

API Reference

Complete manifest API documentation