Skip to main content
Tuist is a modular CLI tool built in Swift that helps you generate, build, and maintain Xcode projects at scale. Understanding its architecture will help you make the most of Tuist’s capabilities.

High-Level Architecture

Tuist follows a layered architecture that separates concerns and enables extensibility:
Tuist is organized into distinct modules, each with specific responsibilities:
  • CLI Layer - Command parsing and execution (entry point)
  • Manifest Layer - Project description types and DSL
  • Loader Layer - Manifest loading and validation
  • Graph Layer - Dependency resolution and graph modeling
  • Generator Layer - Xcode project generation
  • Integration Layer - Server, cache, and external services

Module Structure

Tuist’s codebase is divided into focused modules under cli/Sources/:

Core Modules

ProjectDescription

Public manifest DSL types (Project, Target, Scheme)

TuistCore

Domain models, analytics, and shared abstractions

TuistLoader

Manifest loading, evaluation, and caching

XcodeGraph

Graph models for dependencies and targets

Feature Modules

TuistGenerator transforms manifests into Xcode projects:
// Simplified generation flow
Manifest  Graph  ProjectDescriptor  .xcodeproj
  • Loads Project.swift manifests
  • Builds dependency graph
  • Generates Xcode project files
  • Creates schemes and build phases

Data Flow

Here’s how data flows through Tuist when you run tuist generate:
1

Discover Manifests

Tuist traverses the directory tree to find Project.swift, Workspace.swift, and Tuist.swift files.
/MyApp
├── Tuist.swift          # Global config
├── Workspace.swift      # Workspace definition
└── Project.swift        # Project manifest
2

Load & Parse

The TuistLoader module:
  • Compiles manifest files as Swift code
  • Executes them in a sandboxed environment
  • Decodes JSON output into ProjectDescription types
// From Project.swift manifest
let project = Project(
    name: "MyApp",
    targets: [
        .target(
            name: "App",
            destinations: .iOS,
            product: .app,
            bundleId: "com.example.app"
        )
    ]
)
3

Build Graph

XcodeGraph creates a complete dependency graph:
  • Resolves target dependencies
  • Validates circular dependencies
  • Links external packages
  • Determines build order
4

Generate Projects

TuistGenerator creates Xcode project files:
  • Transforms graph into ProjectDescriptor
  • Writes .xcodeproj packages
  • Generates schemes and configurations
  • Applies build settings

Key Design Principles

Manifests are written in Swift, providing:
  • Type safety and compile-time validation
  • Code reuse through helpers and functions
  • IDE autocomplete and refactoring support
  • Version control friendly
// Example: Reusable helper function
func debugSettings() -> SettingsDictionary {
    var settings: SettingsDictionary = [:]
    settings["ENABLE_TESTABILITY"] = "YES"
    settings["DEBUG_INFORMATION_FORMAT"] = "dwarf"
    return settings
}
Xcode projects are generated, not manually maintained:
  • Single source of truth (manifests)
  • Reproducible builds across teams
  • Eliminates merge conflicts in .pbxproj
  • Easy to regenerate or clean
Clear separation of concerns:
  • ProjectDescription has no dependencies (manifest DSL)
  • TuistLoader bridges manifests to models
  • TuistCore provides shared domain logic
  • Feature modules depend on core, not each other
Caching uses content hashing:
  • Deterministic fingerprints for targets
  • Cache invalidation based on content changes
  • Shared caches across teams
  • Supports selective testing

Extension Points

Tuist provides several extension mechanisms:

Plugins

// In ProjectDescriptionHelpers
import ProjectDescription

public extension Project {
    static func app(
        name: String,
        destinations: Destinations,
        dependencies: [TargetDependency] = []
    ) -> Project {
        return Project(
            name: name,
            targets: [
                .target(
                    name: name,
                    destinations: destinations,
                    product: .app,
                    bundleId: "com.company.\(name)",
                    dependencies: dependencies
                )
            ]
        )
    }
}

Target Scripts

Custom build phases can be added to targets:
.target(
    name: "App",
    // ...
    scripts: [
        .pre(
            script: """
            echo "Running SwiftLint..."
            swiftlint
            """,
            name: "SwiftLint",
            basedOnDependencyAnalysis: false
        )
    ]
)

Resource Synthesizers

Automatic code generation for resources:
let project = Project(
    name: "MyApp",
    resourceSynthesizers: [
        .strings(),
        .assets(),
        .fonts(),
        .plists(),
        .custom(
            name: "CustomAssets",
            parser: .json,
            extensions: ["custom"]
        )
    ],
    targets: [...]
)

Server Architecture

While the CLI is written in Swift, the Tuist Server is built with Elixir/Phoenix to handle web services, caching, and analytics at scale.
Swift-based command-line tool:
  • Fast local execution
  • Direct Xcode integration
  • File system operations
  • Build orchestration

Integration Flow

When using Tuist Cloud features:
import ProjectDescription

let tuist = Tuist(
    fullHandle: "myorg/myproject",
    project: .tuist(
        generationOptions: .options(
            enableCaching: true
        )
    )
)

Next Steps

Generated Projects

Learn how Tuist generates Xcode projects

Manifests

Understand Project.swift and other manifest files

Workspaces

Explore workspace organization

API Reference

Complete manifest API documentation