원클릭으로
tuist
Manages Tuist configuration. Use when adding xcframeworks, configuring dependencies, or modifying Project.swift.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Manages Tuist configuration. Use when adding xcframeworks, configuring dependencies, or modifying Project.swift.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Swift 6 concurrency patterns. Use when working with async/await, actors, MainActor isolation, or Sendable conformance.
Creates Features for dependency injection. Use when creating features, exposing public entry points, or wiring up dependencies.
Creates Repositories that abstract data access. Use when creating repositories, transforming DTOs to domain models, or implementing local-first caching. Supports remote-only, local-only, and cached (remote + local) repositories with CachePolicy.
Creates a new feature module with minimal viable structure. Use when bootstrapping a new feature from scratch, scaffolding the Tuist module, Container, Feature entry point, DeepLinkHandler, and initial screen with placeholder Text view. Includes all unit tests, mocks, stubs, and app integration. For adding domain/data layers afterward, use /datasource, /repository, /usecase. For enhancing views, use /view, /viewmodel, /navigator.
Creates Navigator for navigation. Use when setting up navigation, adding navigation to ViewModels, or testing navigation behavior.
Creates ViewModels with state management. Use when creating ViewModels, implementing ViewState pattern, or adding state management for features. Delegates to /usecase for domain use cases and to /feature for Container/Feature wiring.
| name | tuist |
| description | Manages Tuist configuration. Use when adding xcframeworks, configuring dependencies, or modifying Project.swift. |
Skill for managing Tuist configuration in the project.
IMPORTANT: This project has a Tuist MCP server installed. Always use the MCP tools for Tuist operations instead of running bash commands directly.
The Tuist MCP server provides project graph information:
URI: tuist:///{project-path}
Resource: {AppName} graph
Type: application/json
Use ReadMcpResourceTool to read the project graph and understand:
// Read project graph
ReadMcpResourceTool(
server: "tuist",
uri: "tuist:///{project-path}"
)
Note: Use
ListMcpResourcesToolto see all available Tuist resources.
The root Project.swift delegates to mainApp.project (defined in ModuleKit/App.swift). The project structure adapts based on the active module strategy set in ModuleFactory.swift.
// Project.swift
let project = mainApp.project
// App.swift — generates the project with all module targets and schemes
Project(
name: name,
options: .options(
automaticSchemesOptions: .disabled, // Manual scheme generation
developmentRegion: "en",
disableBundleAccessors: true, // BundleAccessorGenerator handles this
disableSynthesizedResourceAccessors: true // No TuistAssets+*.swift
),
packages: packages, // Aggregated from modules (empty for FrameworkModule)
settings: .settings(
base: baseSettings.merging([...]) { _, new in new },
configurations: BuildConfiguration.all
),
targets: [appTarget, uiTestsTarget] + moduleTargets, // App + UI tests + module framework targets
schemes: allSchemes + [uiTestsScheme] + moduleSchemes // Environment schemes + tests + per-module
)
// Workspace.swift — coverage mode adapts to active strategy
let workspace = Workspace(
name: mainApp.name,
projects: ["."],
generationOptions: .options(
autogeneratedWorkspaceSchemes: .enabled(
codeCoverageMode: mainApp.coverageMode, // .targets() for Framework, .relevant for SPM
testingOptions: []
)
)
)
The Challenge (Dev) scheme aggregates all module test targets via ModuleAggregation, which dispatches on the active strategy:
.targets(...) with aggregated testableTargets and codeCoverageTargets from each module — no test plan file is generated..xctestplan via TestPlanGenerator and uses .testPlans(...), which is the only mechanism to aggregate test targets across SPM local packages.Focus mode: When TUIST_FOCUS_MODULES env var is set (via generate.sh --focus), ModuleAggregation filters testable and coverage targets to only include focused modules and their transitive dependents. Each FrameworkModule target is tagged with metadata: .metadata(tags: ["module:<ShortName>"]) for Tuist's tag-based generation filtering. The expansion is computed in generate.sh using tuist graph --format json to build the reverse dependency graph.
The test command is the same for both:
xcodebuild test \
-workspace Challenge.xcworkspace \
-scheme "Challenge (Dev)" \
-destination 'platform=iOS Simulator,name=iPhone 17 Pro,OS=26.1'
Tests run via xcodebuild test (not tuist test) because Tuist can't resolve SPM package test targets when using .testPlans().
| Option | Effect | Reason |
|---|---|---|
disableBundleAccessors | No Tuist Bundle+*.swift | BundleAccessorGenerator creates custom Bundle.module accessors |
disableSynthesizedResourceAccessors | No TuistAssets+*.swift | Not using generated asset accessors |
The app must declare supported languages in CFBundleLocalizations for iOS to load localizations from embedded frameworks:
// Project.swift
let appInfoPlist: [String: Plist.Value] = [
"CFBundleLocalizations": ["en", "es"],
// ... other settings ...
]
| Key | Value | Description |
|---|---|---|
CFBundleLocalizations | ["en", "es"] | Languages the app supports |
developmentRegion | "en" | Default/fallback language (in project options) |
Important: Without
CFBundleLocalizations, iOS ignores localizations in embedded frameworks (likeChallengeResources) and always shows the development language.
See /resources skill for adding new languages and managing localized strings.
To enable the app to receive external URLs (from Safari, other apps, push notifications), configure CFBundleURLTypes in the app's Info.plist:
// Project.swift
let appInfoPlist: [String: Plist.Value] = [
"UILaunchStoryboardName": "LaunchScreen",
// ... other settings ...
"CFBundleURLTypes": [
[
"CFBundleURLSchemes": ["challenge"],
"CFBundleURLName": "com.app.Challenge",
],
],
]
Configuration:
| Key | Value | Description |
|---|---|---|
CFBundleURLSchemes | ["challenge"] | URL scheme the app responds to |
CFBundleURLName | "com.app.Challenge" | Unique identifier for this URL type |
Usage:
After configuration, the app can receive URLs like:
challenge://character/listchallenge://character/detail/42Handle incoming URLs in RootContainerView with .onOpenURL:
.onOpenURL { url in
appContainer.handle(url: url, navigator: navigationCoordinator)
}
See /navigator skill for deep link implementation details.
Tuist generates files in the Derived/ folder:
Derived/
└── InfoPlists/
├── {AppName}-Info.plist
└── {AppName}UITests-Info.plist
Contents: Only Info.plist files for the app and UI tests targets. Module Info.plists are managed by their respective strategy (Tuist for Framework, SPM for SPM packages).
Git: The Derived/ folder is in .gitignore.
Place the .xcframework file in the Tuist/Dependencies/ directory:
{AppName}/
├── Tuist/
│ ├── Dependencies/
│ │ └── FrameworkName.xcframework
│ └── ProjectDescriptionHelpers/
├── Libraries/
├── App/
└── Project.swift
Note: The
Tuist/Dependencies/directory is ignored by git. Do not commit xcframeworks to the repository.
If it doesn't exist, create the file Tuist/ProjectDescriptionHelpers/Dependencies.swift:
import ProjectDescription
public enum XCFrameworks {
public static let frameworkName: TargetDependency = .xcframework(path: "Tuist/Dependencies/FrameworkName.xcframework")
}
In Project.swift, add the dependency to the target that needs it:
.target(
name: appName,
destinations: [.iPhone, .iPad],
product: .app,
bundleId: "com.app.\(appName)",
deploymentTargets: developmentTarget,
sources: ["App/Sources/**"],
resources: ["App/Sources/Resources/**"],
dependencies: [
XCFrameworks.frameworkName,
]
)
If the xcframework is a dependency of an internal framework in Libraries/, update Target+Framework.swift:
public extension Target {
static func createFramework(
name: String,
destinations: ProjectDescription.Destinations = [.iPhone, .iPad],
dependencies: [TargetDependency] = []
) -> Self {
let targetName = "\(appName)\(name)"
return .target(
name: targetName,
destinations: destinations,
product: .framework,
bundleId: "${PRODUCT_BUNDLE_IDENTIFIER}.\(targetName)",
sources: ["Libraries/\(name)/**"],
dependencies: dependencies
)
}
}
Then in Project.swift:
.createFramework(
name: "Features/UserFeature",
dependencies: [
XCFrameworks.frameworkName,
]
)
tuist generate