Setup Swift Gitignore

This documentation was generated with the assistance of AI. Please report any inaccuracies.

Create or refresh the root .gitignore for a Swift package or Apple app project, composing a universal SwiftPM/Xcode base plus conditionally-detected sections for generator-managed Xcode projects, Package.resolved, Fastlane, macOS desktop distribution output, command-line tool outputs (flavor: cli), signing material, and Antora/DocC documentation output — never overwriting an existing file without warning the user, showing a diff of the proposed merge, and asking Update / Keep as is / Replace first.

Purpose

iru-setup-swift-gitignore composes a Swift/Xcode-appropriate .gitignore: an unconditional base (.build/, DerivedData/, .xcresult, xcuserdata/, .xcuserstate, the narrowly-scoped .swiftpm/xcode/, .DS_Store) plus sections detected from the actual project — an XcodeGen/Tuist-generated .xcodeproj/ .xcworkspace (only when project.yml/Project.swift is present; otherwise the project file is hand-maintained and must stay tracked), a Package.resolved commit-vs-ignore decision (resolved via args or asked through AskUserQuestion, informed by flavor), Fastlane output paths, macOS desktop distribution output, signing material, and Antora/DocC build output. A macOS desktop app is recognised by scripts/make-dmg.sh or a root ExportOptions-.plist (the iru-setup-macos-app layout): its archive/export/DMG/notarization output lands under the root build/, so the skill first checks (git ls-files — build, ls build) whether anything there must stay tracked, then adds an anchored /build/ plus .xcarchive/, .dmg and -notarize.zip — or, when build/ holds tracked or hand-made content such as a branding icon source, only its generated subfolders (/build/dd*/, /build/docc/, /build/export*/). /build/ is anchored so it never matches docs/build/. The base now also ignores the transient .simulator-test.lock/ directory that iru-swift-code-one-task-group creates around every app-kind xcodebuild test run (simulator or macOS desktop UI tests). The section was verified against a real iru-setup-macos-app scaffold run. For an app (flavor: app) or a package with UI (never flavor: cli) it also ignores the UI tests' unanchored .ui-screenshots/ capture directory from the catalog’s UI contract, and never ignores .ui-quality.yml. It announces whether it is creating .gitignore from scratch or updating an existing one. It mirrors the diff-and-approve contract shared with the sibling Setup Java Gitignore / Setup TypeScript Gitignore / Setup Android Gitignore skills, adapted for the Swift/Xcode ecosystem, and fits into the catalog’s Swift/Apple bootstrap pipeline as the leaf step that runs once scaffolding and docs are in place.

Purpose group

Plugin

Shipped by the iru-swift plugin of the ai-catalog marketplace (install with /plugin install iru-swift@ai-catalog; see Plugins).

Invocation

/iru-setup-swift-gitignore

Inputs

Argument Required Description Default

mode

No

new or existing — whether a root .gitignore is being created from scratch or merged into one that already exists. Informational: the file actually on disk decides, and an existing .gitignore always goes through the warn-and-ask step, even under mode: new.

Detected from whether a root .gitignore already exists.

flavor

No

library, app or cli — informs the Package.resolved commit-vs-ignore recommendation. Passed straight through by an orchestrator (e.g. iru-setup-swift-library/iru-setup-apple-app/iru-setup-cli-repository) instead of re-detecting it.

Inferred (the cli rule first): an .executableTarget on ArgumentParser with no Xcode project means cli; otherwise from Package.swift’s declared products or the presence of an `.xcodeproj/.xcworkspace/app Info.plist; left unresolved (asked together with package-resolved) if no signal is present yet.

package-resolved

No

commit or ignore — the pre-resolved answer for whether Package.resolved is tracked or ignored, so a caller that already knows the answer skips the AskUserQuestion prompt.

Asked via AskUserQuestion (recommended default: commit for flavor: app and flavor: cli, ignore for flavor: library); if flavor is unknown and the user has no preference, defaults to commit.

on-existing

No

ask, keep, update or replace — how an existing .gitignore is treated: ask shows the diff and asks; the others apply that choice without asking (the warning and diff are still printed). Meant for scripted runs.

ask

Command-line tool outputs

With flavor: cli (or when scripts/generate-docs.sh exists) the skill adds root-anchored /dist/, /build/, /.tar.gz, /.zip and /SHA256SUMS for the docs generator’s and release packaging’s output. The generated Antora partial cli-reference.adoc stays committed, and Package.resolved is committed by default for a CLI.

Outputs

  • A .gitignore file at the repository root — newly created, updated (merged), or replaced.

  • If .gitignore didn’t previously exist: it is written directly, no approval step needed.

  • If .gitignore already existed: a diff of the proposed merge is shown first (via git diff --no-index), then the user chooses Update (merge, keeping every hand-added entry), Keep as is (file untouched; missing expected entries are listed), or Replace (template only; hand-added entries lost), unless on-existing answers for them.

  • A closing report stating the path announced (from scratch or update), the action actually taken (created / updated / replaced / kept as is) and who chose it (user or on-existing), naming which conditional sections (generator-managed Xcode project, Package.resolved, Fastlane, command-line tool outputs, signing material, Antora build output, DocC output) were included versus skipped and why, the Package.resolved commit-vs-ignore decision and its reasoning, and warnings that detection is heuristic and that an already-tracked path this skill now proposes to ignore needs a manual git rm -r --cached.

Execution flow

flowchart TD A[Start /iru-setup-swift-gitignore] --> B["Step 0: Resolve mode/flavor/\npackage-resolved/on-existing from args\nor detect/defer"] B --> C{".gitignore already\nexists at root?"} C -- no --> C1["Announce: creating .gitignore\nfrom scratch"] C -- yes --> E["Announce: updating existing .gitignore;\nread content and warn"] C1 --> D E --> D["Step 2: Compose universal base\n(.build/, DerivedData/, *.xcresult,\nxcuserdata/, .swiftpm/xcode/, .DS_Store)"] D --> F["Step 3: Detect project-specific additions:\nXcodeGen/Tuist manifest, fastlane/,\nAntora docs, DocC catalog/plugin"] F --> F2["macOS desktop app signals?\nmake-dmg.sh / ExportOptions-*.plist:\ncheck whether build/ holds tracked content"] F2 --> G{"Package.swift present?\nResolve Package.resolved"} G -- "package-resolved given" --> H["Use pre-resolved value"] G -- "not given" --> I["AskUserQuestion:\ncommit or ignore\n(informed by flavor)"] H --> J["Step 4: Compose proposed content\n(merge with existing lines if any)"] I --> J J --> K{"Did .gitignore\nalready exist?"} K -- no --> L["Step 6: Write .gitignore directly"] K -- yes --> M["Step 5: Show diff; on-existing\nor ask Update / Keep as is / Replace"] M -- "Update or Replace" --> L M -- "Keep as is" --> N["Leave existing .gitignore untouched;\nlist missing expected entries"] L --> O["Report + warnings"] N --> O

Dependencies

Invokes

None — iru-setup-swift-gitignore is a leaf skill; it does not call any other skill in this catalog.

Invoked by

  • Setup Swift Repository — Step 7 runs iru-setup-swift-gitignore after iru-setup-swift-library/iru-setup-apple-app and iru-setup-antora have run, so it can detect their generated files (the SwiftPM/Xcode project layout, Antora docs build output) already in place, passing flavor, and package-resolved and on-existing when supplied. mode is deliberately not passed, since the skill’s own .gitignore-presence check is the more precise signal.

  • Setup CLI Repository — for the swift flavor, with flavor: cli, after iru-setup-swift-cli; on-existing is passed only when supplied.

  • Setup macOS Repository — Step 6, with flavor: app, after iru-setup-macos-app and iru-setup-antora, so the macOS distribution section can detect scripts/make-dmg.sh/ExportOptions-*.plist; on-existing is passed only when supplied.

None — this skill does not delegate any part of its work to a built-in agent.

Source

SKILL.md on GitHub — the file this page was generated from.