One of the advantages of defining your projects in Swift is that we can leverage Xcode and the Swift compiler to safely edit the projects with syntax auto-completion and documentation.

Editing your projects is easy; position yourself in a directory where there’s a project defined and run the following command:

tuist edit
Copy the content

It will open a temporary Xcode project with the manifests and the project description helpers. After making changes you can run the target from Xcode and it will call tuist generate for you.

The project is deleted automatically once you are done with editing. If you wish to generate and keep the project in the current directory, you can run the command passing the --permanent argument:

tuist edit --permanent
Copy the content

That will generate a Manifest.xcodeproj project that you can open manually.


In projects with an established architecture, developers might want to bootstrap new components or features that are consistent with the project. With scaffold you can define your own templates and also templates that Tuist provides to generate a basic structure of your module!

To define templates, you can run tuist edit and then create a directory under Tuist/Templates that represents your template. Templates need a manifest file, Template.swift that describes the template:

import ProjectDescription
let nameAttribute: Template.Attribute = .required("name")
let template = Template(
description: "Custom template",
attributes: [
.optional("platform", default: "ios"),
files: [
.string(path: "Project.swift",
contents: "My template contents of name \(nameAttribute)"),
.file(path: "generated/Up.swift",
templatePath: "generate.stencil"),
Copy the content

This template would then be called like this:

tuist scaffold name_of_template --name Name --platform macos
Copy the content

Since platform is an optional argument, we can also call the command without the --platform macos argument.

If .string and .files don’t provide enough flexibility, you can leverage the Stencil templating language via the .file case.

Templates can import project description helpers. Just add import ProjectDescriptionHelpers at the top, and extract reusable logic into the helpers.


One of the benefits of making the definition of projects explicit, is that we can run checks on them and uncover configuration issues that otherwise would be bubbled up by the build system later on. Tuist follows the principle of the sooner we detect the errors, the less time developers will have to spend. For that reason, we provide a command that developers can run either locally or on CI to ensure their projects have a valid configuration:

tuist lint
Copy the content

Please note that there are checks that only the compiler and the build system can do. In other words, those will only be uncover by compiling the app with Xcode or xcodebuild.


When projects grow, it becomes hard to visualize the dependencies between all the targets that are part of the project. Fortunately, Tuist provides a command, tuist graph, that loads your project dependencies graph and exports it in a representable format.

Being in a directory that contains a workspace or project manifest, run the following command:

tuist graph
Copy the content

The command will output a human-readable file, graph.dot that describes the dependencies graph using the DOT description language.

A visual representation of the graph

Graphviz is a command line tool that take the .dot graph and convert it into an image.

brew install graphviz
dot -Tpng graph.dot > graph.png
Copy the content

Alternatively, you can use online services like this one that renders your graph on a website.


Xcode projects often have dependencies with system tools like SwiftLint, Carthage, or Sourcery. Those are dependencies that need to be installed/pulled and properly configured in the developer environment for the project to run.

Most projects include a list of steps in the README file for developers to follow:

1. Clone the repository.
2. Install Carthage if it's not already installed.
3. Install `brew install swiftlint`.
4. Run `carthage update`.
5. Open the project.
Copy the content

It’s a tedious process that can break without you noticing it. Moreover, each project usually has its own set of non-standard steps, which makes inconvenient jumping from one project to another.

The good news is that Tuist offers a command, tuist up that helps you define your project dependencies and then takes care of the configuration process for you.

To define your project dependencies, we need to create a new Setup.swift manifest file:

import ProjectDescription
let setup = Setup([
.homebrew(packages: ["swiftlint"]),
.carthage(platforms: [.iOS])
Copy the content

We have turned the markdown steps that we saw before into up commands in the setup manifest. When you run tuist up, Tuist translates those declarations into actual commands that are executed in your system.

Moreover, it assesses whether those dependencies are already met in the environment, and if they are, it skips them. For instance, if the Carthage dependencies exist and are up to date, it doesn’t run the Carthage update command.

tuist up
Copy the content

Available commands

Tuist offers the following set of commands.

Homebrew packages

.homebrew(packages: [“swiftlint”])
Copy the content

It installs the given Homebrew packages if they don’t exist in the system.

Homebrew tap

.homebrewTap(repositories: ["peripheryapp/periphery"])
Copy the content

Configures Homebrew tap repositories. It also installs Homebrew if it’s not available in the system.

Carthage dependencies

.carthage(platforms: [.macOS])
Copy the content

It runs Carthage dependencies for those dependencies that don’t exist or that are outdated.

Mint packages

Copy the content

It installs all the packages in a Mintfile if they don’t exist in the system.


.custom(name: "Name", meet: ["./install.sh"], isMet: ["test", "mytool"])
Copy the content

Besides the built-in commands, you can define yours using the custom option. It takes the following arguments:

  • Name: Name of the command
  • Meet: Command to run in the system to configure the environment.
  • Met: Command to run in the system to verify whether the environment is already configure. A 0 exit code means that the environment is already configured.

If you have ideas of other built-in commands that Tuist could offer, don’t hesitate to open an issue with your ideas.

Tuist's logotype



Getting startedManifest specificationDependenciesContributors
Tuist © Copyright 2019. All rights reserved. Crafted with ♥ by Pedro Piñera & the contributors.


Tuist © Copyright 2019. All rights reserved. Crafted with ♥ by Pedro Piñera & the contributors.