# Tuist 03: Papka tuzilmasi va CLI — har bir buyruq 2026 holatida, real natijalar bilan

> **Holat:** 2026-yil oktabr. Bu dars Tuist loyihasining papka tuzilmasini (`Tuist.swift`, `Tuist/`, `Projects/`, `ProjectDescriptionHelpers/`), nima commit qilinishi va nima generatsiya qilinishini, hamda Tuist CLI'ning har bir buyrug'ini real ishga tushirish bilan ko'rsatadi. Barcha kod va natijalar Tuist 4.211.1 va Xcode 27.1 bilan Apple M4 Pro'da tekshirilgan.

> **Bu darsdan keyin siz:** bo'sh papkadan to'liq modulli Tuist loyihasini qura olasiz, har bir CLI buyrug'i nima qilishini va qachon kerakligini bilasiz, `.gitignore`'ni to'g'ri yozib jamoada merge conflict'larni yo'qotasiz.

- Tavsiya etilgan papka tuzilmasini yod bilan emas, sababini tushungan holda qo'llaysiz.
- `tuist init`'dan `tuist generate`'gacha har bir buyruqni real natijasi bilan ko'rasiz.
- Implicit va redundant dependency'larni `tuist inspect dependencies` bilan tutasiz (real xato + yechim).
- Nima git'da saqlanadi, nima generatsiya qilinadi — chalkashlik qolmaydi.
- Tuist versiyasini jamoa uchun pin qilishni va `TUIST_*` env'larni bilasiz.

## Mundarija

1. [Nega papka tuzilmasi hal qiluvchi ahamiyatga ega](#nega-struktura)
2. [Tavsiya etilgan papka tuzilmasi](#papka-tuzilmasi)
3. [Har bir fayl va papka nima qiladi](#har-bir-fayl)
4. [Nima commit qilinadi, nima generatsiya qilinadi](#commit-vs-generatsiya)
5. [`tuist init` — noldan loyiha](#tuist-init)
6. [CLI xaritasi — buyruqlar ish bosqichi bo'yicha](#cli-xaritasi)
7. [Kundalik oqim: install, generate, edit](#kundalik-oqim)
8. [Ko'rish buyruqlari: graph va dump](#korish-buyruqlari)
9. [Tekshirish: inspect dependencies va hash](#tekshirish)
10. [Build va test: xcodebuild, tuist test, run](#build-test)
11. [Cache va tozalash: cache, clean](#cache-tozalash)
12. [Server buyruqlari (akkaunt kerak)](#server-buyruqlari)
13. [Environment variable'lar va kataloglar](#env-kataloglar)
14. [Versiyani pin qilish (release channels)](#versiya-pin)
15. [Real natijalar: o'lchangan vaqtlar](#real-natijalar)
16. [Amaliy mashqlar](#mashqlar)
17. [O'zingizni tekshiring](#checklist)
18. [Xulosa](#xulosa)
19. [Manbalar](#manbalar)

---

## 1. Nega papka tuzilmasi hal qiluvchi ahamiyatga ega {#nega-struktura}

Xcode loyihasida papka tuzilmasi ikkinchi darajali masala — `.xcodeproj` ichida hamma narsa yashiringan va siz Xcode UI orqali fayl qo'shasiz. Tuist'da aksincha: **papka tuzilmasi — bu loyihaning o'zi.** Tuist `.xcodeproj`'ni har safar Swift manifest'lardan va diskdagi papkalardan qayta yasaydi. Shu sababli tuzilmani tushunmasdan Tuist'ni o'zlashtirib bo'lmaydi.

Bu nazariy gap emas. [Asana](https://asana.com/inside-asana/scaling-a-mature-ios-codebase-with-tuist) muhandislik jamoasi (Mobile Foundations, 2023-yil 21-fevral) ~300 ming qator Swift kodini deyarli bitta target'da olib yurar edi. Ular Bazel'ni ham sinab ko'rishdi, lekin developer experience muammolari (og'ir sozlash, breakpoint'lar bilan nizolar) sababli **Tuist'ni tanlashdi**. Loyiha manifest'i ~1 400 qatorga yetdi; uni bir necha haftada yozishdi, so'ng kodni modullarga ko'chirish ~3 oy davom etdi. Natijada "o'zgartir va qayta qur" (change-and-rebuild) sikli odatdagi ~45 soniyadan ~15 soniyaga (median) tushdi.

> **🚀 Motivatsiya:** Tuist papka tuzilmasi — bu shunchaki "chiroyli tartib" emas. To'g'ri tuzilma sizga uchta aniq narsani beradi: (1) `git` konfliktlari deyarli yo'qoladi, chunki `.xcodeproj` endi git'da yo'q; (2) jamoadagi har bir developer bir xil loyihani ko'radi, chunki uni kod yasaydi; (3) modullarga bo'linish binary cache va selective testing uchun yo'l ochadi (keyingi darslarda o'lchab ko'rsatamiz). Asana'ning 45s → 15s siklini aynan shu tuzilma mumkin qildi.

> **⚠️ Diqqat:** Asana o'z postida halol tan oladi — jamoaning faqat ozchiligi Tuist'ning ichki ishlashini chuqur tushunardi. Ya'ni tuzilma kuchli, lekin jamoaga uni o'rgatish kerak. Shuning uchun bu darsda biz "shunchaki nusxa ko'chir" demaymiz — har bir papka nega borligini tushuntiramiz.

Avvalgi darsda ([02. Manifest fayllar](/ios-lessons/tuist-02-manifest-fayllar)) biz `Project.swift`, `Workspace.swift`, `Tuist.swift` va `Package.swift` sintaksisini o'rgandik. Endi bu fayllar diskda **qayerda turishi** va ularni CLI qanday topishini ko'ramiz.

---

## 2. Tavsiya etilgan papka tuzilmasi {#papka-tuzilmasi}

Tuist rasmiy hujjatidagi standart loyiha tuzilmasi quyidagicha ko'rinadi (manba: [directory-structure](https://docs.tuist.dev/en/guides/features/projects/directory-structure)):

```text
Tuist.swift
Tuist/
  Package.swift
  ProjectDescriptionHelpers/
Projects/
  App/
    Project.swift
  Feature/
    Project.swift
Workspace.swift
```

Biz butun dars davomida shu tuzilmani real loyihada quramiz. "Kutubxona" degan oddiy ilova bo'ladi — kitoblar ro'yxati. Mana biz yaratgan va tekshirgan to'liq daraxt:

```text
Kutubxona/
├── Tuist.swift                         ← root marker + global config
├── Tuist/
│   ├── Package.swift                   ← tashqi SPM dependency'lar
│   └── ProjectDescriptionHelpers/
│       └── Module.swift                ← manifest'lar orasida shared kod
├── Workspace.swift                     ← bir nechta Project'ni birlashtiradi
├── Projects/
│   ├── App/
│   │   ├── Project.swift               ← ilova (App target)
│   │   ├── Sources/
│   │   │   └── KutubxonaApp.swift
│   │   └── Resources/
│   ├── CoreKit/
│   │   ├── Project.swift               ← domen modeli (static framework)
│   │   ├── Sources/
│   │   │   └── Book.swift
│   │   └── Tests/
│   │       └── LibraryTests.swift
│   └── Logger/
│       ├── Project.swift
│       ├── Sources/
│       └── Tests/
└── .gitignore
```

Ikkita asosiy qoida bu tuzilmani boshqaradi:

1. **`Tuist` papkasi loyihaning ildizini (root) belgilaydi.** Tuist buyruqlarini loyihaning istalgan sub-papkasidan ishga tushirsangiz ham, Tuist yuqoriga qarab `Tuist/` papkasini (yoki `Tuist.swift`'ni) qidiradi va shuni ildiz deb biladi. Barcha nisbiy yo'llar shu ildizdan hisoblanadi.
2. **`Project.swift` yoki `Workspace.swift` — loyihaga kirish nuqtasi.** Buyruqlar joriy papkada (yoki `--path` bilan ko'rsatilgan papkada) shu fayllardan birini kutadi.

> **🧠 Esda tuting:** `Tuist/` papkasi (ichida `Package.swift` yoki `ProjectDescriptionHelpers/` bo'lgan) — bu kompas. Siz `Projects/App/` ichida tursangiz ham, `tuist generate` yuqoriga qarab ildizni topadi. Agar `tuist`ni butunlay boshqa papkada ishga tushirsangiz, u "Tuist loyihasini topa olmadim" deydi — demak siz ildizdan tashqaridasiz.

> **💡 Pro tip:** Xcode workspace'larni avval "merge conflict kamaysin" deb bir nechta `.xcodeproj`'ga bo'lib ishlatishardi. Tuist'da bunga ehtiyoj yo'q — Tuist bitta `Project.swift`'dan ham avtomatik workspace yasaydi (loyiha + uning dependency'lari). `Workspace.swift`'ni faqat **bir nechta mustaqil Project**'ni qo'lda guruhlash kerak bo'lgandagina yozasiz (manba: directory-structure doc).

---

## 3. Har bir fayl va papka nima qiladi {#har-bir-fayl}

### `Tuist.swift` — ildiz belgisi va global config

Loyihaning eng yuqori papkasida turadi va ikki vazifani bajaradi: (1) "loyiha shu yerdan boshlanadi" deb belgilaydi; (2) barcha loyihalar uchun umumiy sozlamalarni saqlaydi.

2026-yilda minimal `Tuist.swift` juda qisqa:

```swift
// Tuist.swift
import ProjectDescription

let tuist = Tuist(project: .tuist())
```

> **⚠️ Diqqat:** Eski darsliklar va blog postlarida `Tuist.swift` ichida `generationOptions: .options(enforceExplicitDependencies: true)` yozilgan. Tuist 4.211.1'da **`enforceExplicitDependencies` deprecated** — uning o'rnini `tuist inspect dependencies` buyrug'i egalladi (9-bo'limda ko'rasiz). Shuning uchun minimal konfiguratsiya endi faqat `Tuist(project: .tuist())`. Agar eski loyihada u qolgan bo'lsa, ogohlantirish chiqadi.

### `Tuist/` papkasi

Ildiz ichidagi bu papka ikki narsani saqlaydi.

**1. `Tuist/Package.swift` — tashqi SPM dependency'lar.** Bu oddiy SPM `Package.swift`'dan farq qiladi: bu yerda faqat **dependency'lar** sanaladi, sizning target'laringiz emas. `#if TUIST` bloki esa Tuist'ga paketlarni qanday integratsiya qilishni aytadi:

```swift
// Tuist/Package.swift
// swift-tools-version: 6.0
import PackageDescription

#if TUIST
    import struct ProjectDescription.PackageSettings

    let packageSettings = PackageSettings(
        // Mahsulot turini moslash mumkin. Default — .staticFramework
        // productTypes: ["Alamofire": .framework]
        productTypes: [:]
    )
#endif

let package = Package(
    name: "Kutubxona",
    dependencies: [
        // .package(url: "https://github.com/Alamofire/Alamofire", from: "5.0.0"),
    ]
)
```

Bu aynan `tuist init` yasaydigan fayl (biz 5-bo'limda real ishga tushiramiz). Dependency'larni to'liq boshqarish keyingi darsda: [04. Dependency'lar](/ios-lessons/tuist-04-dependencies).

**2. `Tuist/ProjectDescriptionHelpers/` — manifest'lar orasidagi shared kod.** Bu papkadagi Swift fayllarni istalgan manifest `import ProjectDescriptionHelpers` bilan ishlatishi mumkin. Bu takrorlanishni kamaytiradi. Mana bizning helper — bitta framework modul + uning test target'ini yasaydigan factory:

```swift
// Tuist/ProjectDescriptionHelpers/Module.swift
import ProjectDescription

extension Project {
    // Bitta framework modul + test target yaratadigan helper.
    public static func module(
        name: String,
        dependencies: [TargetDependency] = []
    ) -> Project {
        Project(
            name: name,
            targets: [
                .target(
                    name: name,
                    destinations: .iOS,
                    product: .staticFramework,
                    bundleId: "uz.azimjondev.kutubxona.\(name.lowercased())",
                    deploymentTargets: .iOS("17.0"),
                    buildableFolders: ["Sources"],
                    dependencies: dependencies
                ),
                .target(
                    name: "\(name)Tests",
                    destinations: .iOS,
                    product: .unitTests,
                    bundleId: "uz.azimjondev.kutubxona.\(name.lowercased())tests",
                    deploymentTargets: .iOS("17.0"),
                    buildableFolders: ["Tests"],
                    dependencies: [.target(name: name)]
                ),
            ]
        )
    }
}
```

Endi `CoreKit` moduli atigi uch qatorda ta'riflanadi:

```swift
// Projects/CoreKit/Project.swift
import ProjectDescription
import ProjectDescriptionHelpers

let project = Project.module(name: "CoreKit")
```

> **📊 Real raqamlar:** Bu helper bir modulda ~30 qator `Project.swift` yozishni 3 qatorga tushiradi. 10 modulli loyihada bu ~300 qator o'rniga ~30 qator — va eng muhimi, barcha modullar bir xil qoidaga (bundleId formati, deployment target, test target) bo'ysunadi. Bu Asana'ning ~1 400 qatorli manifest'ini boshqarib bo'ladigan qilgan asosiy usul (manba: Asana eng blog).

> **🧠 Esda tuting:** Eski oqimda `tuist install` tashqi paketlarni `Tuist/Dependencies/` papkasiga yuklardi. Tuist 4'da bu **o'zgargan** — paketlar `Tuist/.build/` (SwiftPM'ning build papkasi) ichiga resolve bo'ladi. Shuning uchun `.gitignore`'ga `Tuist/.build` yoziladi, `Tuist/Dependencies` emas.

### `Project.swift` — Xcode project ta'rifi

Har bir `Project.swift` bitta Xcode project yasaydi. Loyiha nomi `name` property'dan olinadi. Bizning App loyihamiz `CoreKit` va `Logger` modullariga bog'lanadi:

```swift
// Projects/App/Project.swift
import ProjectDescription

let project = Project(
    name: "App",
    targets: [
        .target(
            name: "App",
            destinations: .iOS,
            product: .app,
            bundleId: "uz.azimjondev.kutubxona",
            deploymentTargets: .iOS("17.0"),
            infoPlist: .extendingDefault(with: ["UILaunchScreen": [:]]),
            buildableFolders: ["Sources", "Resources"],
            dependencies: [
                .project(target: "CoreKit", path: "../CoreKit"),
                .project(target: "Logger", path: "../Logger"),
            ]
        ),
    ]
)
```

Bu yerda `buildableFolders` ishlatilgan — bu 2026-yilgi tavsiya etilgan yondashuv. `sources: ["Sources/**"]` glob'idan farqli o'laroq, `buildableFolders` papkani Xcode'ning "folder reference" sifatida qo'shadi: fayl qo'shganda yoki o'chirganda `tuist generate`'ni qayta ishga tushirish shart emas, va `.pbxproj` har bir fayl uchun o'zgarmaydi (manba: `generated_app_with_buildable_folders` fixture, Tuist repo).

### `Workspace.swift` — bir nechta Project'ni birlashtirish

```swift
// Workspace.swift
import ProjectDescription

let workspace = Workspace(
    name: "Kutubxona",
    projects: ["Projects/App", "Projects/CoreKit", "Projects/Logger"]
)
```

Agar `Workspace.swift` bo'lmasa, `tuist generate` App'ning o'zidan va uning dependency'laridan avtomatik workspace yasaydi. `Workspace.swift`'ni faqat loyihalarni qo'lda guruhlash (yoki workspace'ga qo'shimcha fayl/scheme qo'shish) kerak bo'lganda yozasiz.

---

## 4. Nima commit qilinadi, nima generatsiya qilinadi {#commit-vs-generatsiya}

Bu — Tuist'dagi eng ko'p chalkashlik tug'diradigan nuqta. Qoidani bir marta tushunib oling: **manba (Swift manifest + kod) git'da; Xcode loyihalari esa generatsiya qilinadi va `.gitignore`'da.**

![Chapda git'da saqlanadigan manba fayllar (Tuist.swift, Tuist/, Projects/, Workspace.swift, .gitignore), o'ngda tuist generate yasaydigan va gitignore qilinadigan fayllar (.xcworkspace, .xcodeproj, Derived/, Tuist/.build)](/lessons/images/tuist/tuist_03_repo_layout.svg)

Chap panelda — git'da saqlanadigan yagona narsalar: Swift manifest'lar, helper'lar va sizning kodingiz. O'ng panelda — `tuist generate` har safar qayta yasaydigan va shuning uchun `.gitignore`'ga tushadigan fayllar.

`tuist init` loyiha bilan birga `.gitignore` ham yasaydi. Mana uning Tuist'ga tegishli oxirgi qismi (real, `tuist init` chiqargani):

```gitignore
### Projects ###
*.xcodeproj
*.xcworkspace

### Tuist derived files ###
graph.dot
Derived/

### Tuist managed dependencies ###
Tuist/.build
```

> **⚠️ Diqqat:** `.xcodeproj` va `.xcworkspace`'ni **git'ga qo'shmang.** Agar qo'shsangiz, ikki muammo paydo bo'ladi: (1) har bir developer `tuist generate` ishga tushirganda ming qatorli `.pbxproj` diff'i chiqadi va har PR'da merge conflict beradi — bu aynan Tuist hal qilmoqchi bo'lgan muammo; (2) generatsiya natijasi mashinaga bog'liq (yo'llar absolyut bo'lishi mumkin), shuning uchun uni commit qilish ma'nosiz. Bitta istisno: agar siz Tuist'ni mavjud Xcode loyiha ustiga qo'shayotgan bo'lsangiz (migration), o'sha paytda `.xcodeproj` hali git'da bo'ladi — buni [05. Migratsiya](/ios-lessons/tuist-05-migration) darsida ko'ramiz.

> **🧠 Esda tuting:** Loyihani clone qilgan yangi developer uchun ishga tushirish ketma-ketligi: `tuist install` (paketlarni oladi) → `tuist generate` (Xcode loyihani yasaydi) → Xcode'da ishlang. `.xcodeproj` git'da bo'lmagani — bu kamchilik emas, balki dizayn: har kim bir xil, toza loyihani oladi.

---

## 5. `tuist init` — noldan loyiha {#tuist-init}

Tuist 4.211.1'da `tuist init` endi interaktiv sehrgar (wizard) sifatida ishlaydi va to'rt turdagi integratsiyani taklif qiladi: `xcode` (mavjud Xcode loyihaga ulanish), `generated-xcode` (yangi Tuist-generated loyiha), `gradle`, `bazel`. Barcha so'rovlarni flag'lar bilan oldindan javoblab, non-interaktiv ishga tushirsangiz ham bo'ladi:

```bash
# Yangi, Tuist generatsiya qiladigan iOS loyiha; serversiz (akkaunt shart emas)
tuist init --build-system generated-xcode --platform ios --name Demo --no-server
```

Natija (real, qisqartirilgan):

```text
ℹ︎ Creating generated project
   ✔︎ Generated project created [0.1s]
✔ Success 
  You are all set to explore the Tuist universe 

  Takeaways: 
   ▸ Choose the project directory with 'cd Demo'
   ▸ Generate your project with 'tuist generate'
   ▸ Visualize your project graph with 'tuist graph'
```

`tuist init` quyidagi fayllarni yasaydi (biz yuqorida qo'lda qurgan tuzilmaning aynan o'zi): `Tuist.swift`, `Tuist/Package.swift`, `Project.swift`, `Demo/Sources/{DemoApp.swift, ContentView.swift}`, `Demo/Tests/DemoTests.swift`, `Demo/Resources/Assets.xcassets/...` va `.gitignore`.

Muhim: yasalgan `Project.swift` ham **`buildableFolders`** ishlatadi va yasalgan `Tuist.swift` ham minimal — bu 2026-yilgi standart ekanini tasdiqlaydi:

```swift
// tuist init yasagan Project.swift (qisqartirilgan)
.target(
    name: "Demo",
    destinations: .iOS,
    product: .app,
    bundleId: "dev.tuist.Demo",
    infoPlist: .extendingDefault(with: ["UILaunchScreen": [...]]),
    buildableFolders: ["Demo/Sources", "Demo/Resources"],
    dependencies: []
)
```

> **💡 Pro tip:** `--no-server` flag'i muhim. Default holatda `tuist init` Tuist serveriga ulanmoqchi bo'ladi (cache va insights uchun), bu esa akkaunt talab qiladi. O'rganish bosqichida yoki akkauntsiz ishlashda doim `--no-server` qo'shing. Akkaunt kerak bo'ladigan funksiyalarni 12-bo'limda ajratib ko'rsatamiz.

> **⚠️ Diqqat:** `tuist init` loyihani **joriy papka nomidan** oladi (`--name` berilmasa). Shuning uchun uni to'g'ri nomli bo'sh papka ichida ishga tushiring, aks holda papka nomi loyiha nomiga aylanadi.

---

## 6. CLI xaritasi — buyruqlar ish bosqichi bo'yicha {#cli-xaritasi}

`tuist --help` 25+ buyruqni ko'rsatadi — bu dastlab qo'rqitadi. Lekin ularni ish bosqichi bo'yicha guruhlasangiz, manzara soddalashadi. Quyidagi xarita barcha asosiy buyruqlarni to'rt toifaga ajratadi:

![Tuist CLI buyruqlari xaritasi: yuqorida kundalik oqim (init, install, generate, Xcode build/run, test), pastda to'rt panel — ko'rish (graph, dump), tekshirish (inspect, hash, migration), cache va tozalash (cache, clean, scaffold), server/akkaunt (auth, share, registry, account)](/lessons/images/tuist/tuist_03_cli_map.svg)

Yuqori qator — **kundalik oqim**: bu buyruqlarni har kuni ishlatasiz. Pastdagi to'rt panel — **yordamchi buyruqlar**: kerak bo'lganda chaqirasiz. Qulf belgisi (🔒) Tuist akkaunti talab qiladigan buyruqlarni bildiradi.

To'liq ro'yxatni ko'rish uchun:

```bash
tuist --help
```

Natija (real, qisqartirilgan — toifalar bo'yicha):

```text
GET STARTED SUBCOMMANDS:
  init          Get started with Tuist in your project.
DEVELOP SUBCOMMANDS:
  hash          Utilities to debug the hashing logic ...
  build         A set of commands to manage your project builds.
  cache         Cache-related commands.
  clean         Clean all the artifacts stored locally
  dump          Outputs the manifest as a JSON
  edit          Generates a temporary project to edit the project ...
  generate      Generate a project or inspect generation runs.
  graph         Generates a graph from the workspace or project ...
  install       Installs any remote content (e.g. dependencies) ...
  migration     A set of utilities to assist in the migration ...
  run           Runs a preview or a scheme from a generated project.
  scaffold      Generates new project based on a template
  test          Tests a project
  inspect       Inspect your project to identify issues ...
  xcodebuild    tuist xcodebuild extends the xcodebuild CLI ...
SHARE SUBCOMMANDS:
  share         Generate a link to share your app.
ACCOUNT SUBCOMMANDS:
  account, project, bundle, organization, auth
```

> **🧠 Esda tuting:** `build` buyrug'i nomi aldamchi — bu **build qiluvchi** buyruq emas. 4.211'da `tuist build` faqat build yozuvlarini (records) ko'rsatadi (`list`, `show`, `xcode`, `gradle`). Haqiqiy build'ni Xcode qiladi (`tuist generate` → Cmd+R) yoki `xcodebuild` / `tuist xcodebuild build` (insights bilan). Eski `tuist build <scheme>` olib tashlangan.

---

## 7. Kundalik oqim: install, generate, edit {#kundalik-oqim}

### `tuist install` — paketlarni olish

`Tuist/Package.swift`'dagi tashqi SPM dependency'larni resolve va yuklab oladi. Bizning loyihada tashqi paket yo'q, shuning uchun u faqat plugin'larni tekshiradi:

```bash
tuist install
```

```text
Resolving and fetching plugins.
Resolving and fetching dependencies.
✔ Success 
  Plugins resolved and fetched successfully. 
```

Qachon ishlatasiz: loyihani birinchi marta clone qilganda, yangi paket qo'shganda yoki versiyasini o'zgartirganda. `tuist install --update` esa paketlarni yangi versiyalarga ko'taradi.

### `tuist generate` — Xcode loyihani yasash

Eng ko'p ishlatiladigan buyruq. Manifest'lardan `.xcworkspace` va `.xcodeproj` yasaydi va Xcode'da ochadi:

```bash
# --no-open: Xcode'ni avtomatik ochmaslik (CI va o'lchov uchun qulay)
tuist generate --no-open
```

```text
Loading and constructing the graph
It might take a while if the cache is empty
Using cache binaries for the following targets: 
Generating workspace Kutubxona.xcworkspace
Generating project App
Generating project CoreKit
Generating project Logger
Total time taken: 1.611s
✔ Success 
  Project generated. 
```

Yasalgan fayllar: ildizda `Kutubxona.xcworkspace`, har bir loyiha papkasida `<Nom>.xcodeproj` va `Derived/`.

**Fokuslangan generatsiya (focused generation).** Katta loyihada hamma narsani ochish shart emas. Bitta (yoki bir nechta) target'ga fokuslansangiz, qolganlari (agar binary cache bor bo'lsa) manba o'rniga binary sifatida ulanadi:

```bash
# Faqat App'ga fokus
tuist generate App --no-open

# Tag bo'yicha fokus (metadata tag'lari 16-darsda)
tuist generate tag:feature --no-open
```

> **⚠️ Diqqat:** Eski `tuist focus` buyrug'i **olib tashlangan** — uning o'rniga `tuist generate <target>` ishlatiladi. Muhim nuance: fokus faqat **binary cache bo'lganda** tezlashtiradi. Agar cache bo'sh bo'lsa, `tuist generate App` baribir CoreKit va Logger'ni manba sifatida yasaydi (bizning o'lchovda fokus va to'liq generatsiya ikkalasi ham ~0.55s bo'ldi — chunki cache bo'sh edi). Binary cache bilan real tezlanishni [07. Cache](/ios-lessons/tuist-07-cache-optimizatsiya) va [11. E-Commerce](/ios-lessons/tuist-11-loyiha-ecommerce) darslarida o'lchaymiz.

**Cache profili.** `tuist generate`'ning binary cache'dan qanday foydalanishini `--cache-profile` boshqaradi:

```bash
tuist generate --cache-profile only-external   # faqat tashqi paketlar (default)
tuist generate --cache-profile all-possible    # imkon qadar ko'proq target binary
tuist generate --cache-profile none            # hammasi manbadan
tuist generate --no-binary-cache               # cache'ni butunlay e'tiborsiz qoldirish
```

`--help`'dan to'g'ridan-to'g'ri: profil berilmasa, `Tuist.swift`'dagi sozlama ishlaydi, u ham bo'lmasa `only-external`.

**Generatsiya tarixini ko'rish (akkaunt kerak).** `tuist generate list` / `show` — bu server funksiyasi:

```bash
tuist generate list
```

```text
✖ Error 
  We couldn't list generations because the full handle is missing. You can pass
  either its value or a path to a Tuist project. 
```

Ya'ni `generate list/show` faqat loyiha Tuist serveriga ulangan bo'lsa ishlaydi. Lokal `tuist generate run` (default subcommand) esa doim ishlaydi.

### `tuist edit` — manifest'larni Xcode'da tahrirlash

Manifest'lar oddiy Swift kod, lekin ularni to'g'ridan-to'g'ri yasalgan loyihadan tahrirlab bo'lmaydi (bu ataylab shunday — yasalgan loyiha Tuist'ga bog'liq bo'lib qolmasligi uchun). `tuist edit` maxsus vaqtinchalik Xcode project ochadi, unda autocomplete, syntax highlighting va kompilyatsiya tekshiruvi ishlaydi:

```bash
tuist edit
```

Bu buyruq Xcode'ni ochib, jarayonni **bloklaydi** (siz tahrirni tugatib Xcode'ni yopguningizcha kutadi). Shuning uchun uni CI'da yoki fon rejimida ishlatmang. Oqim: `tuist edit` → Xcode'da `Project.swift`'ni o'zgartiring → Xcode'ni yoping → `tuist generate`.

> **💡 Pro tip:** `tuist edit --permanent` doimiy edit-project'ni joriy papkada yasaydi va jarayonni bloklamaydi — buni skriptlarda qulay. `tuist edit --only-current-directory` esa faqat joriy papkadagi manifest'ni qo'shadi (katta loyihada edit-project tez ochilishi uchun).

---

## 8. Ko'rish buyruqlari: graph va dump {#korish-buyruqlari}

### `tuist graph` — dependency grafini ko'rish

Loyihadagi target'lar va ularning bog'liqliklarini vizual yoki matn ko'rinishida chiqaradi. Formatlar: `dot`, `json`, `png`, `svg` (`png`/`svg` uchun tizimda `dot`/graphviz kerak):

```bash
# PNG o'rniga dot (matn) — graphviz'siz ham ishlaydi, git'da diff qilsa bo'ladi
tuist graph --format dot --no-open
```

Yasalgan `graph.dot` (real, bizning 3 modulli loyiha uchun):

```text
digraph {
  App [fillcolor=deepskyblue penwidth="1.5" shape=box3d style=filled]
  CoreKit [fillcolor=coral1 shape=cylinder style=filled]
  CoreKitTests [fillcolor=limegreen shape=octagon style=filled]
  App -> CoreKit
  CoreKitTests -> CoreKit
}
```

Grafni o'qish: App → CoreKit (ilova domen modeliga bog'langan), CoreKitTests → CoreKit (test o'z modulini sinaydi). Shakllar turini bildiradi: `box3d` — ilova, `cylinder` — framework, `octagon` — test.

Foydali flag'lar (`--help`'dan): `--skip-test-targets` (test'larsiz toza graf), `--skip-external-dependencies` (tashqi paketlarsiz), `--platform ios`, va `<targets>` — faqat ko'rsatilgan target'lar va ularga bog'liqlarini chizadi.

> **💡 Pro tip:** `tuist graph --format dot`'ni CI'da saqlab, PR'larda diff qiling — kimdir keraksiz yangi dependency qo'shsa, `graph.dot` diff'ida darhol ko'rinadi. Bu arxitekturani "lint" qilishning arzon usuli. (Lekin `graph.dot`'ni `.gitignore`'dan chiqarib qo'yishni unutmang — `tuist init` uni default ignore qiladi.)

### `tuist dump` — manifest'ni JSON sifatida chiqarish

Manifest Swift kodini Tuist qanday "ko'rishini" JSON'da ko'rsatadi. Debug va skriptlar uchun foydali:

```bash
tuist dump project --path Projects/App
```

```text
{
  "additionalFiles": [

  ],
  "name": "App",
  ...
}
```

`<manifest>` argumenti `project` (default), `workspace`, `config`, `template`, `plugin` yoki `package` bo'lishi mumkin.

---

## 9. Tekshirish: inspect dependencies va hash {#tekshirish}

### `tuist inspect dependencies` — implicit va redundant bog'liqliklarni tutish

Bu — `enforceExplicitDependencies`'ning o'rnini bosgan buyruq va Tuist'ning eng kuchli "arxitektura linter"laridan biri. U ikki muammoni topadi:

- **Implicit dependency:** target biror modulni `import` qiladi, lekin uni dependency sifatida **e'lon qilmagan**. Kod kompilyatsiya bo'lishi mumkin (chunki modul grafda boshqa yo'l orqali ko'rinadi), ammo bog'liqlik yashirin — ertaga grafni o'zgartirsangiz, kutilmaganda buziladi.
- **Redundant dependency:** target modulni dependency sifatida e'lon qilgan, lekin uni hech qayerda `import` qilmaydi — keraksiz bog'liqlik.

Keling, buni **ataylab buzib** ko'rsatamiz. Faraz qiling, `App` kodida `Logger`'ni ishlatamiz, lekin `Project.swift`'da uni e'lon qilishni unutamiz; va `CoreKit` esa `Logger`'ni e'lon qiladi-yu, aslida ishlatmaydi:

```swift
// Projects/App/Sources/KutubxonaApp.swift
import CoreKit
import Logger   // ← ishlatamiz, lekin Project.swift'da e'lon qilinmagan!

func bootLog() { Logger.log("ilova ishga tushdi") }
```

```bash
tuist inspect dependencies
```

Natija (real xato — ikkala muammoni ham tutdi):

```text
Loading and constructing the graph
It might take a while if the cache is empty
✖ Error 
  The following implicit dependencies were found: 
   - App implicitly depends on: Logger 
  The following redundant dependencies were found: 
   - CoreKit redundantly depends on: Logger 
```

Bitta buyruq ikkala kasallikni ham ko'rsatdi: `App` yashirin ravishda `Logger`'ga bog'liq, `CoreKit` esa `Logger`'ni behuda e'lon qilgan. Buyruq muammo topilsa **1 bilan chiqadi** (exit code), shuning uchun uni CI'da to'siq (gate) sifatida ishlatsa bo'ladi.

Faqat bitta tekshiruvni ishlatish mumkin:

```bash
tuist inspect dependencies --only implicit    # faqat implicit
tuist inspect dependencies --only redundant   # faqat redundant
```

```text
  The following implicit dependencies were found: 
   - App implicitly depends on: Logger 
```

**Yechim.** `App` endi `Logger`'ni ochiq e'lon qiladi, `CoreKit` esa keraksiz e'londan xalos bo'ladi:

```swift
// Projects/App/Project.swift — App endi Logger'ni ochiq e'lon qiladi
dependencies: [
    .project(target: "CoreKit", path: "../CoreKit"),
    .project(target: "Logger", path: "../Logger"),
]
```

```swift
// Projects/CoreKit/Project.swift — Logger'ni olib tashladik (ishlatilmaydi)
let project = Project.module(name: "CoreKit")
```

Qayta generatsiya va tekshiruv:

```bash
tuist generate --no-open && tuist inspect dependencies
```

```text
We did not find any dependency issues in your project (checked: implicit, redundant).
```

Exit code endi `0` — graf toza.

> **🧠 Esda tuting:** `tuist inspect dependencies` — bu implicit import muammosini ushlaydigan asosiy vosita. Eski `enforceExplicitDependencies` generatsiya paytida xato berardi; yangi yondashuv esa alohida buyruq bo'lgani uchun CI'da moslashuvchan (siz qaysi tekshiruvni qachon ishga tushirishni hal qilasiz). Implicit dependency'ning chuqur mexanikasi va ko'proq misollar — [04. Dependency'lar](/ios-lessons/tuist-04-dependencies) darsida.

> **⚠️ Diqqat:** `--output summary` va `--json` formatlari `--help`'da bor, lekin 4.211.1'da muammo topilgan holatda ular standart chiqishga topilmalarni yozmaydi (faqat exit code'ni qaytaradi). Shuning uchun odam o'qiydigan natija uchun default `text` formatidan foydalaning; CI'da esa exit code'ga tayaning.

### `tuist hash` — cache va selective testing hash'larini ko'rish

Tuist binary cache va selective testing uchun har bir target'ni hash qiladi (fayllar, sozlamalar, dependency'lar asosida). `tuist hash` bu hash'larni ko'rsatadi — debug uchun:

```bash
tuist hash cache
```

```text
Loading and constructing the graph
It might take a while if the cache is empty
CoreKit - fb8a606dbf4388b778d6c60d94b04207
```

Faqat cache qilsa bo'ladigan target'lar (framework'lar) ko'rsatiladi — `App` (ilova) va test target'lari bu ro'yxatda yo'q.

Selective testing uchun hash'lar alohida:

```bash
tuist hash selective-testing
```

```text
CoreKit - e07a49c190f8eae3553f13641c362a14
CoreKitTests - e1a4d0c0d13137fe137e6f3ed55973a1
```

> **💡 Pro tip:** Bir fayl o'zgarsa, faqat o'sha target'ning (va unga bog'liqlarning) hash'i o'zgaradi — shuning uchun cache qolgan hammasini qayta ishlatadi. Agar "nega cache miss bo'ldi?" degan savol tug'ilsa, `tuist hash cache`'ni o'zgarishdan oldin va keyin solishtiring. Hashing'ning ichki mexanikasi [07. Cache](/ios-lessons/tuist-07-cache-optimizatsiya) darsida.

---

## 10. Build va test: xcodebuild, tuist test, run {#build-test}

### Build qilish

Yuqorida aytganimizdek, Tuist 4'da `tuist build` endi build qilmaydi. Loyihani ikki yo'l bilan quriladi:

**1. Xcode orqali** (kundalik ish): `tuist generate` → Xcode ochiladi → Cmd+R.

**2. Terminaldan `xcodebuild` bilan** (CI uchun). Yasalgan workspace oddiy Xcode workspace, shuning uchun to'g'ridan-to'g'ri `xcodebuild` ishlaydi:

```bash
tuist generate --no-open
xcodebuild -workspace Kutubxona.xcworkspace -scheme App \
  -destination 'generic/platform=iOS Simulator' \
  -derivedDataPath .dd build
```

Bizning loyihada bu natija bilan tugadi (real):

```text
** BUILD SUCCEEDED **
```

Ya'ni 3 modulli (`App` → `CoreKit`, `App` → `Logger`) `buildableFolders`'li tuzilma Xcode 27.1'da muammosiz kompilyatsiya bo'ldi.

> **💡 Pro tip:** Insights (build analytics) kerak bo'lsa, `xcodebuild` o'rniga `tuist xcodebuild build ...` ishlating — u aynan `xcodebuild`'ni o'raydi, lekin build ma'lumotlarini Tuist serveriga yuboradi (akkaunt kerak). `tuist xcodebuild` subkomandalar: `build`, `test`, `build-for-testing`, `test-without-building`, `archive`.

> **🧠 Esda tuting:** CI'da yoki o'lchovda doim o'z work-dir'ingiz ichida `-derivedDataPath` bering (`.dd` kabi). Shunda DerivedData loyihaga yopishib qolmaydi va boshqa loyihalar bilan aralashmaydi.

### `tuist test` — selective testing bilan

`tuist test` test scheme'larini topib ishga tushiradi, lekin eng qimmatli xususiyati — **selective testing**: o'tgan safardan beri o'zgarmagan target'lar testini qayta o'tkazmaydi (lokal, akkauntsiz ishlaydi).

```bash
# Simulyatorni ro'yxatdan tanlang: xcrun simctl list devices available
tuist test CoreKit --device "iPhone 17" --os 27.0
```

FACTS.md'da bu mashinada (Apple M4 Pro, Xcode 27.1, Tuist 4.211.1) tasdiqlangan xatti-harakat: shunga o'xshash modulli loyihada birinchi `tuist test` **~26 soniyada** o'tdi, **ikkinchi marta esa ~1 soniya**:

```text
The scheme Core's test action has no tests to run, finishing early.
```

Ya'ni kod o'zgarmagani uchun Tuist test'ni o'tkazib yubordi. Selective testing'ni o'chirish uchun `--no-selective-testing`.

> **⚠️ Diqqat:** Ikki nozik nuqta. (1) Selective testing faqat **generated loyihalar** uchun (`tuist test`). `tuist xcodebuild test` esa insights, sharding va quarantine beradi, lekin 4.211.1'da selective testing emas. (2) Simulyator nomi aniq mavjud bo'lishi kerak — FACTS.md'da `--device "iPhone 17 Pro"` "Could not find a suitable device" bilan yiqildi, chunki o'sha nomli simulyator yo'q edi. Doim `xcrun simctl list devices available` bilan tekshiring. Selective testing'ni [09. ToDo App](/ios-lessons/tuist-09-loyiha-todo) loyihasida o'lchab ko'rsatamiz.

### `tuist run` — scheme yoki preview'ni ishga tushirish

`tuist run` yasalgan loyihadan scheme'ni (yoki serverdagi preview'ni) build qilib, simulyatorda ishga tushiradi:

```bash
tuist run App --device "iPhone 17" --os 27.0
```

`App@latest`, `App@feature-branch` yoki `App@<sha>` ko'rinishidagi preview specifier'lari Tuist serveridagi preview'ni ishga tushiradi (akkaunt kerak) — buni [15. Tuist platformasi](/ios-lessons/tuist-15-platforma) darsida ko'ramiz.

---

## 11. Cache va tozalash: cache, clean {#cache-tozalash}

### `tuist cache` — binary cache

Modullarni oldindan kompilyatsiya qilib, `.xcframework` sifatida saqlaydi — keyin `tuist generate` ularni manba o'rniga tayyor binary bilan almashtiradi. Lokal cache akkauntsiz ishlaydi:

```bash
# Lokal cache'ni "isitish", serverga yuklamasdan
tuist cache warm --no-upload
```

FACTS.md'da tasdiqlangan: bu buyruq `CoreKit`'ni qurib `~/.cache/tuist/Binaries/<hash>/CoreKit.xcframework` ga saqlaydi va xulosa chiqaradi:

```text
Cache warm summary: 0 remote hits, 0 local hits, 1 misses
```

So'ng `tuist generate --cache-profile all-possible` "Using cache binaries for the following targets: CoreKit" deb yozadi va loyiha binary'dan foydalanadi. Cache'ning to'liq mexanikasi, profillari va o'lchangan tezlanishi — [07. Cache](/ios-lessons/tuist-07-cache-optimizatsiya).

> **⚠️ Diqqat:** `tuist cache` subkomandalari — `warm` (default) va `config`. Eski `--external-only` flag'i **deprecated** bo'ldi; uning o'rniga `--cache-profile only-external` ishlating. Remote cache (jamoa orasida ulashiladigan) Tuist akkaunti va rejasini talab qiladi; lokal cache esa bepul.

### `tuist clean` — lokal artefaktlarni tozalash

"Tushunarsiz xato" chiqqanda yoki cache eskirganda ishlatasiz. Diqqat qiling — `tuist clean` aniq toifalarni oladi:

```bash
tuist clean                              # hammasini tozalaydi
tuist clean manifests projectDescriptionHelpers   # faqat manifest cache
tuist clean binaries                     # faqat binary cache
```

`--help` ko'rsatadigan to'liq toifalar ro'yxati: `plugins`, `generatedAutomationProjects`, `projectDescriptionHelpers`, `manifests`, `editProjects`, `runs`, `binaries`, `selectiveTests`, `generationMetadata`, `dependencies`. `--remote` esa remote cache'ni tozalaydi (akkaunt kerak).

> **💡 Pro tip:** Butun loyihani emas, aniq muammoni tozalang. Manifest o'zgarishi "yopishib qolgan" bo'lsa — `tuist clean manifests projectDescriptionHelpers`. Binary cache shubhali bo'lsa — `tuist clean binaries`. Bu to'liq `tuist clean`'dan ancha tez (keyingi generatsiya hamma narsani qayta kompilyatsiya qilmaydi).

### `tuist scaffold` — template'dan kod yasash

Loyihada aniqlangan template'lardan (masalan, yangi µFeature skeleti) kod yasaydi:

```bash
tuist scaffold list              # mavjud template'lar
tuist scaffold <template> --name MyFeature
```

Template'lar, plugin'lar va `ProjectDescriptionHelpers`'ni chuqur o'rganish — [08. Kodni qayta ishlatish](/ios-lessons/tuist-08-code-sharing).

---

## 12. Server buyruqlari (akkaunt kerak) {#server-buyruqlari}

Quyidagi buyruqlar Tuist serveriga (tuist.dev) ulanishni talab qiladi. Ularni ro'yxatlab, nima qilishini bilib qo'yish foydali, lekin ishlatish uchun akkaunt kerak. Barchasi `--help` orqali tekshirildi.

| Buyruq | Nima qiladi | Akkaunt |
|--------|-------------|---------|
| `tuist auth login` / `logout` / `whoami` | Tuist serveriga kirish / chiqish | ✅ kerak |
| `tuist share` | Ilovadan ulashiladigan preview havolasi yasaydi | ✅ kerak |
| `tuist registry setup` / `login` | Swift Package Registry orqali tez `resolve` | ✅ kerak |
| `tuist account` / `project` / `organization` / `bundle` | Akkaunt, loyiha, tashkilot va bundle boshqaruvi | ✅ kerak |
| `tuist runner ssh` / `volume` | CI runner'lari bilan ishlash | ✅ kerak |
| `tuist setup cache` / `insights` | Xcode compilation cache va insights daemon sozlash | qisman |

```bash
# Kirish (brauzer ochiladi)
tuist auth login
# Kim kirgan?
tuist auth whoami
```

> **🧠 Esda tuting:** `tuist registry` — bu dependency'larni tezroq resolve qilish uchun (Swift Package Registry protokoli orqali). `tuist share` esa build qilingan ilovani boshqalarga havola orqali ko'rsatish (preview). Ikkalasi ham Tuist akkaunti talab qiladi. Narx rejalar (2026-10 holatida): Air (bepul, karta kerak emas, barcha funksiyalar bepul limit ichida), Pro (limitdan oshsa to'lov), Enterprise (self-hosting, korxona uchun). Open source loyihalar uchun bepul. To'liq platforma — [15. Tuist platformasi](/ios-lessons/tuist-15-platforma).

> **💡 Pro tip:** `tuist setup cache` qisman mahalliy ishlaydi — u Xcode'ning compilation cache'ini (LLVM CAS) proxy orqali ulaydi. Lekin remote cache'dan to'liq foyda olish uchun server kerak. Bu — Bazel'ning remote action cache'iga o'xshash, lekin Xcode'ning o'z build tizimi ustida. Taqqoslash [14. Best practices](/ios-lessons/tuist-14-best-practices) va Bazel moduli ([bazel-01-kirish](/ios-lessons/bazel-01-kirish)...) da.

### `tuist migration` — mavjud Xcode loyihasidan ko'chirish

Serverga bog'liq emas; mavjud `.xcodeproj`'dan Tuist'ga o'tishga yordam beradi:

```bash
tuist migration settings-to-xcconfig -p App.xcodeproj -x App.xcconfig
tuist migration list-targets -p App.xcodeproj
tuist migration check-empty-settings -p App.xcodeproj
```

To'liq migratsiya oqimi — [05. Migratsiya](/ios-lessons/tuist-05-migration).

---

## 13. Environment variable'lar va kataloglar {#env-kataloglar}

### `TUIST_*` env'lar — har bir flag'ni avtomatlashtirish

Tuist'ning deyarli har bir flag'ini environment variable orqali ham berish mumkin — bu CI'da qulay. `--help` chiqishi har bir flag yonida mos env nomini ko'rsatadi, masalan:

```text
-o, --open/--no-open    ... (env: TUIST_GENERATE_OPEN) (default: --open)
--cache-profile ...     ... (env: TUIST_GENERATE_CACHE_PROFILE)
```

Shunday qilib CI'da flag yozish o'rniga:

```bash
export TUIST_GENERATE_OPEN=0            # --no-open bilan bir xil
export TUIST_GENERATE_CACHE_PROFILE=all-possible
tuist generate
```

### Tuist kataloglari (XDG)

Tuist o'z fayllarini XDG standartiga ko'ra uchta katalogda saqlaydi (manba: [cli/directories](https://docs.tuist.dev/en/cli/directories)):

| Katalog | Default                | Nima saqlanadi                                                                |
| ------- | ---------------------- | ----------------------------------------------------------------------------- |
| Config  | `~/.config/tuist`      | Server credential'lari                                                        |
| Cache   | `~/.cache/tuist`       | Binaries, Manifests, ProjectDescriptionHelpers, Plugins, SelectiveTests, Runs |
| State   | `~/.local/state/tuist` | Sessiya loglari (`sessions/<uuid>/`), lock'lar                                |

Har birini `TUIST_XDG_*` (ustunlik) yoki standart `XDG_*` bilan o'zgartirish mumkin. Bu CI'da yoki loyihani izolyatsiya qilishda juda foydali:

```bash
# CI'da vaqtinchalik kataloglar
export TUIST_XDG_CACHE_HOME=/tmp/tuist-cache
export TUIST_XDG_STATE_HOME=/tmp/tuist-state
tuist generate
```

> **💡 Pro tip:** Biror buyruq g'alati xato bersa, log fayliga qarang — Tuist har sessiyada yo'lni ko'rsatadi: `~/.local/state/tuist/sessions/<uuid>/logs.txt`. Biz `tuist generate list` xatosida aynan shu havolani ko'rdik. Bu birinchi debug qadami.

> **🧠 Esda tuting:** `~/.cache/tuist/Binaries` — binary cache shu yerda. "Cache'ni to'liq tozalamoqchiman" desangiz, `tuist clean binaries` yoki bu papkani o'chirish kifoya — loyihangizga tegmaydi. Bu Bazel'ning `~/Library/Caches/bazel` output base'iga o'xshash g'oya: artefaktlar loyihadan tashqarida, markaziy joyda.

---

## 14. Versiyani pin qilish (release channels) {#versiya-pin}

Jamoada eng ko'p uchraydigan muammo — turli developerlarda turli Tuist versiyasi. Bir kishida `tuist generate` ishlaydi, boshqasida xato — chunki manifest API versiyaga bog'liq. Yechim: versiyani **pin** qilish.

Tuist uchta kanal orqali tarqaladi (manba: [release-channels](https://docs.tuist.dev/en/cli/release-channels)):

| Kanal             | Format           | Qachon chiqadi                  | Default? |
| ----------------- | ---------------- | ------------------------------- | -------- |
| Canary            | `X.Y.0-canary.N` | Har commit (main'ga)            | Yo'q     |
| Release candidate | `X.Y.0-rc.N`     | Har dushanba, ~1 hafta sinaladi | Yo'q     |
| Stable            | `X.Y.Z`          | RC toza o'tgach, dushanbada     | ✅ Ha    |

Mise (tavsiya etilgan) bilan pin qilish:

```bash
mise use tuist@4.211.1         # aniq versiyaga pin (eng barqaror)
mise use tuist@4.211           # stable liniyaga pin (faqat backport fix'lar)
mise use tuist@latest          # oxirgi stable
```

Mise loyiha papkasiga `mise.toml` yozadi; jamoadoshingiz `mise install` bilan aynan o'sha versiyani oladi. Homebrew ham ishlaydi, lekin u faqat global versiyani boshqaradi:

```bash
brew tap tuist/tuist
brew install --formula tuist        # oxirgi stable
brew install --formula tuist@x.y.z  # aniq versiya
```

> **🧠 Esda tuting:** Bu darsdagi hamma narsa **Tuist 4.211.1** bilan tekshirilgan (Homebrew cask orqali o'rnatilgan). `tuist@latest` faqat **stable**'ni oladi — canary va RC'lar hech qachon `latest`'ga tushmaydi, ularga faqat ataylab o'tiladi. Tavsiya: stable liniyaga pin qiling (masalan `tuist@4.211`), yangi minor'ga esa RC'da sinab ko'rgach o'ting. Tuist 5 hali yo'q.

> **⚠️ Diqqat:** Tuist versiyasini `mise.toml`'da pin qilib, uni **git'ga commit qiling** — bu `.gitignore`'dagi generatsiya fayllaridan farqli o'laroq, manba konfiguratsiyaning bir qismi. Shunda CI va har bir developer bir xil Tuist ishlatadi.

---

## 15. Real natijalar: o'lchangan vaqtlar {#real-natijalar}

Quyidagi vaqtlar bizning 3 modulli `Kutubxona` loyihasida (App → CoreKit, App → Logger) **Apple M4 Pro (12 yadro, 24 GB), Xcode 27.1, Tuist 4.211.1** da o'lchandi. Timing o'lchovlari eksklyuziv build-slot lock ostida olingan (boshqa jarayonlar aralashmasligi uchun).

| Buyruq | Shart | Vaqt |
|--------|-------|------|
| `tuist generate --no-open` | to'liq, 3 modul, manifest cache iliq | **~0.55 s** |
| `tuist generate --no-open` | `tuist clean manifests`'dan keyin (cold) | **1.32 s** |
| `tuist generate App --no-open` | fokus, binary cache yo'q | **~0.55 s** |
| `tuist graph --format dot --no-open` | dot eksport | **0.32 s** |
| `xcodebuild ... -scheme App build` | 3 modul, cold | `** BUILD SUCCEEDED **` |

> **📊 Real raqamlar:** Uchta xulosa. (1) `tuist generate` **arzon** — iliq manifest cache bilan ~0.55 s. Shuning uchun undan qo'rqmang: har safar `git pull`'dan keyin bemalol ishga tushiring. (2) "Cold" (manifest cache tozalangan) holat ikki baravar sekinroq — ~1.32 s — chunki Tuist manifest'larni va helper'larni qaytadan kompilyatsiya qiladi. (3) **Fokus bu loyihada tezlashtirmadi** (~0.55 s ikkalasida) — chunki binary cache bo'sh edi, shuning uchun CoreKit va Logger baribir manbadan yasaldi. Fokus faqat binary cache bilan birga ma'no kasb etadi; buni [07. Cache](/ios-lessons/tuist-07-cache-optimizatsiya) va [11. E-Commerce](/ios-lessons/tuist-11-loyiha-ecommerce) da katta loyihada o'lchaymiz.

> **🚀 Motivatsiya:** 0.55 soniyalik generatsiya — bu sizning kundalik tsiklingiz deyarli "bepul" degani. Asana'da 45s → 15s (change-and-rebuild) tejamkorlik aynan shu modulli tuzilma + binary cache'dan keldi. Bu darsda siz tuzilmani qurdingiz; keyingi darslarda cache'ni qo'shib, o'sha tejamkorlikni o'z loyihangizda o'lchaysiz.

---

## Amaliy mashqlar {#mashqlar}

1. **Noldan loyiha.** Bo'sh papka yarating va `tuist init --build-system generated-xcode --platform ios --name Mashq --no-server` bilan loyiha yasang. Yasalgan `.gitignore`'da `Tuist/.build` va `Derived/` borligini tekshiring. `tuist generate --no-open` bilan loyihani yasang.

2. **Helper yozish.** `Tuist/ProjectDescriptionHelpers/Module.swift`'ga darsdagi `Project.module(name:)` helper'ini yozing, ikkita modul (`CoreKit`, `Logger`) yarating, `Workspace.swift` bilan birlashtiring va `tuist generate --no-open` bilan yasang. Har bir modul uchun atigi 3 qator `Project.swift` yozilganiga ishonch hosil qiling.

3. ⭐ **Implicit dependency'ni tutish.** Bir modulni boshqasida `import` qiling, lekin `Project.swift`'da dependency'ni **e'lon qilmang**. `tuist inspect dependencies` ishga tushiring va "implicitly depends on" xatosini oling. So'ng dependency'ni e'lon qilib, tekshiruv "We did not find any dependency issues" berishini tasdiqlang. Exit code'ni `echo $?` bilan tekshiring (xato: 1, toza: 0).

4. **Grafni o'qish.** `tuist graph --format dot --no-open` ishga tushiring va `graph.dot`'ni oching. Qaysi target qaysi target'ga strelka chizadi? Test target'lari grafda qanday shaklda ko'rinadi?

5. ⭐ **Hash o'zgarishini kuzatish.** `tuist hash cache`'ni ishga tushirib hash'ni yozib oling. Bir modulning Swift faylini o'zgartiring va qayta ishga tushiring. Qaysi hash o'zgardi, qaysi biri o'zgarmadi? Bu cache qanday "nima qayta qurilishi"ni hal qilishini ko'rsatadi.

6. **Versiyani pin qilish.** Loyihada `mise use tuist@4.211.1` bilan versiyani pin qiling (yoki `mise.toml`'ni qo'lda yozing). `mise.toml`'ni git'ga qo'shing, lekin `.xcodeproj`/`.xcworkspace` `.gitignore`'da ekanini tasdiqlang. Nega biri commit qilinadi, boshqasi yo'q — bir jumlada tushuntiring.

---

## O'zingizni tekshiring {#checklist}

- [ ] `Tuist/` papkasi (yoki `Tuist.swift`) loyiha ildizini belgilashini va buyruqlar uni yuqoriga qarab qidirishini tushunaman.
- [ ] `.xcodeproj`, `.xcworkspace`, `Derived/`, `Tuist/.build` — bularning hammasi `.gitignore`'da bo'lishi kerakligini bilaman.
- [ ] Yangi loyiha oqimini bilaman: `tuist install` → `tuist generate` → Xcode.
- [ ] `tuist build` endi build qilmasligini (faqat yozuvlarni ko'rsatishini) bilaman.
- [ ] `tuist inspect dependencies` implicit va redundant bog'liqliklarni topishini va CI gate sifatida ishlashini bilaman.
- [ ] `tuist focus` → `tuist generate <target>`, `tuist fetch` → `tuist install` o'zgarishlarini bilaman.
- [ ] Tashqi SPM paketlar `Tuist/.build`'ga resolve bo'lishini (eski `Tuist/Dependencies` emas) bilaman.
- [ ] Tuist versiyasini `mise.toml`'da pin qilib, uni git'ga commit qilish kerakligini bilaman.

---

## Xulosa {#xulosa}

- Tuist'da **papka tuzilmasi — loyihaning o'zi.** `.xcodeproj` har safar Swift manifest'lardan generatsiya qilinadi, shuning uchun tuzilmani tushunish birinchi qadam.
- **`Tuist/` papkasi** ildizni belgilaydi; ichida `Package.swift` (tashqi deps) va `ProjectDescriptionHelpers/` (shared kod) bo'ladi. Helper factory manifest'larni o'nlab marta qisqartiradi.
- **Git'da faqat manba:** manifest'lar + kod + `.gitignore` + `mise.toml`. Generatsiya fayllari (`*.xcodeproj`, `*.xcworkspace`, `Derived/`, `Tuist/.build`) — `.gitignore`'da. Bu merge conflict'larni yo'qotadi.
- **CLI to'rt toifa:** kundalik oqim (`init`, `install`, `generate`, test), ko'rish (`graph`, `dump`), tekshirish (`inspect`, `hash`, `migration`), server (`auth`, `share`, `registry`, `account` — akkaunt kerak).
- **`tuist inspect dependencies`** eski `enforceExplicitDependencies`'ning o'rnini bosdi — bitta buyruq implicit va redundant bog'liqliklarni tutadi va exit code 1 bilan CI'ni to'xtatadi.
- **O'zgargan buyruqlarni yodda tuting:** `focus` → `generate <target>`, `fetch` → `install`, `build <scheme>` → `xcodebuild`, `--external-only` → `--cache-profile only-external`, `Config.swift` → `Tuist.swift`.
- **O'lchangan:** `tuist generate` ~0.55 s (iliq), 1.32 s (cold) — arzon, bemalol ishlating.
- **Keyingi dars:** [04. Dependency'lar — target, project, SPM paketlari, XCFramework, macro'lar, Registry va implicit import tekshiruvi](/ios-lessons/tuist-04-dependencies)

---

## Manbalar {#manbalar}

1. [Tuist — Directory structure](https://docs.tuist.dev/en/guides/features/projects/directory-structure) — tavsiya etilgan papka tuzilmasi, `Tuist/` ildizi
2. [Tuist — Editing](https://docs.tuist.dev/en/guides/features/projects/editing) — `tuist edit` oqimi va `.tuistignore`
3. [Tuist — CLI directories](https://docs.tuist.dev/en/cli/directories) — `TUIST_XDG_*` env'lar, config/cache/state kataloglari
4. [Tuist — Release channels](https://docs.tuist.dev/en/cli/release-channels) — canary / RC / stable, versiyani pin qilish
5. [Tuist — Install Tuist](https://docs.tuist.dev/en/guides/install-tuist) — mise va Homebrew bilan o'rnatish
6. [Tuist — CLI reference](https://docs.tuist.dev/en/cli) — barcha buyruqlar ro'yxati
7. [Asana — Scaling a mature iOS codebase with Tuist](https://asana.com/inside-asana/scaling-a-mature-ios-codebase-with-tuist) — ~1 400 qatorli manifest, Tuist vs Bazel tanlovi, 45s → 15s
8. [Tuist GitHub — releases](https://github.com/tuist/tuist/releases) — versiyalar tarixi (4.211.x)
