From adjutant-agent
Sets up automatic TestFlight deployment for iOS projects using Fastlane and GitHub Actions. Auto-detects Xcode projects, dependencies, schemes; generates CI/CD configs and manual guides.
npx claudepluginhub lupusdei/adjutant --plugin adjutant-agentThis skill uses the workspace's default tool permissions.
Set up automatic TestFlight deployment for any iOS project. Generates Fastlane configuration, GitHub Actions workflow, and a step-by-step manual setup guide.
Sets up Fastlane for iOS/macOS app automation by installing via Homebrew and creating Appfile/Fastfile with test, beta, and release lanes for TestFlight/App Store.
Sets up Fastlane release pipelines for iOS/Android mobile apps: code signing with Match/keystores, beta distribution to TestFlight/Firebase, App Store/Google Play submission, CI integration, versioning.
App build, code signing, TestFlight, and App Store distribution for all Apple platforms. Use when preparing releases, configuring signing, uploading to TestFlight, or submitting to App Store.
Share bugs, ideas, or general feedback.
Set up automatic TestFlight deployment for any iOS project. Generates Fastlane configuration, GitHub Actions workflow, and a step-by-step manual setup guide.
Before generating any files, gather all the information needed to configure the deployment pipeline.
Use Glob to search for Xcode project files:
**/*.xcworkspace and **/*.xcodeproj at the project root and common subdirectories (ios/, app/, Sources/)..xcworkspace is found alongside a Podfile in the same directory, prefer the workspace.Record the project/workspace filename and its directory path relative to the repository root.
Check for the presence of these files in the project directory and repository root:
Podfile — CocoaPodsPackage.swift — Swift Package Manager (SPM)Cartfile — CarthageIf multiple are found, use this precedence: CocoaPods > SPM > Carthage. Record the primary dependency manager.
Glob for scheme files:
<project>.xcodeproj/xcshareddata/xcschemes/*.xcscheme<workspace>.xcworkspace/xcshareddata/xcschemes/*.xcschemeExtract scheme names by stripping the .xcscheme extension from filenames. If multiple schemes are found, ask the user to pick the one used for TestFlight builds. If none are found, ask the user for the scheme name.
Attempt to determine the Xcode version:
.xcode-version file in the repository root.project.pbxproj and look for SWIFT_VERSION or LastUpgradeCheck values.macos-14macos-15macos-15 / Xcode 16.2 and inform the user of the default.If the Xcode project lives in a subdirectory (e.g., ios/MyApp.xcodeproj), record the relative path from the repository root. This affects:
working-directory setting in GitHub Actionsproject or workspace argument in the FastfileIf the project is at the repository root, the working directory is empty (no override needed).
Ask the user all of the following in a single question:
com.company.appnamegit@github.com:org/certs.git)Before proceeding to file generation, display a summary table of all detected and user-provided values:
| Setting | Value | Source |
|--------------------------|------------------------------------|---------------|
| Xcode project/workspace | MyApp.xcworkspace | Auto-detected |
| Dependency manager | CocoaPods | Auto-detected |
| Scheme | MyApp | Auto-detected |
| Xcode version | 16.2 | Auto-detected |
| macOS runner | macos-15 | Derived |
| Working directory | ios/ | Derived |
| Bundle ID | com.company.myapp | User input |
| Apple Developer Team ID | ABCDE12345 | User input |
| App Store Connect Team ID | 123456789 | User input |
| Match cert repo | git@github.com:org/certs.git | User input |
| Apple ID email | dev@company.com | User input |
Ask the user to confirm or correct any values before proceeding.
Read each template from references/, replace all {{PLACEHOLDER}} values with the discovered/provided values, and write the result to the target path. Generate files in the order listed below.
gem "fastlane" is NOT present, use Edit to append gem "fastlane" after the last gem line. If already present, skip.references/fastlane-templates.md, section "Gemfile".fastlane/ directory if it does not exist (mkdir -p fastlane).references/fastlane-templates.md, section "Appfile".{{BUNDLE_ID}}, {{APPLE_ID}}, {{ITC_TEAM_ID}}, {{TEAM_ID}}.references/fastlane-templates.md, section "Matchfile".{{MATCH_GIT_URL}}, {{BUNDLE_ID}}.references/fastlane-templates.md, section "Fastfile".{{SCHEME}}, {{WORKSPACE_OR_PROJECT}}.{{WORKSPACE_OR_PROJECT}}:
,\n workspace: "<name>.xcworkspace",\n project: "<name>.xcodeproj"ios/MyApp.xcworkspace)..github/workflows/ directory if it does not exist (mkdir -p .github/workflows).references/workflow-template.md.{{MACOS_RUNNER}}, {{XCODE_VERSION}}, {{DEP_MANAGER_STEPS}}, {{WORKING_DIRECTORY}}.{{DEP_MANAGER_STEPS}}: select the appropriate conditional block from the template based on the detected dependency manager (CocoaPods, SPM, or Carthage).${{ secrets.* }} or ${{ hashFiles(...) }} — those are GitHub Actions runtime expressions, not template placeholders.docs/ directory if it does not exist (mkdir -p docs).references/setup-guide-template.md.{{APP_NAME}}, {{BUNDLE_ID}}, {{MATCH_GIT_URL}}.Before writing each file, check whether it already exists and handle accordingly:
Existing Gemfile: Read the file first. If gem "fastlane" is already present, skip it entirely. If the gem is missing, use Edit to append gem "fastlane" after the last gem line. Do not overwrite or remove other gems.
Existing fastlane/Fastfile: Read the file first. If a beta lane already exists, warn the user and ask whether to overwrite the existing lane or skip generation. If no beta lane exists, append the new beta lane block to the end of the existing file (inside the platform :ios do block if present). Do not replace existing lanes.
Existing .github/workflows/testflight.yml: Warn the user that the workflow file already exists. Ask whether to overwrite it or skip. Do not silently overwrite.
Existing fastlane/Appfile or fastlane/Matchfile: Warn the user that the file exists and ask whether to overwrite. These files are simple key-value configurations where merging is not practical — it is safer to replace entirely or skip.
No fastlane/ directory: This is the default happy path. Create the directory and all files fresh without prompting.
After all files are generated, verify and summarize the results.
List all files that were created or modified, with their full paths relative to the repository root. Example:
Created:
- Gemfile
- fastlane/Appfile
- fastlane/Matchfile
- fastlane/Fastfile
- .github/workflows/testflight.yml
- docs/testflight-setup.md
Modified:
- Gemfile (added gem "fastlane")
Display the final configuration values used:
Print the key manual steps the user must complete before the pipeline will work. These come from docs/testflight-setup.md:
.p8 filefastlane match appstore locally to generate initial certificatesASC_KEY_ID — App Store Connect API key IDASC_ISSUER_ID — App Store Connect API issuer IDASC_KEY_CONTENT — Full contents of the .p8 key file (including header/footer lines)MATCH_PASSWORD — passphrase for match encryptionMATCH_GIT_PRIVATE_KEY — SSH private key for the match certificate repositorySuggest to the user:
Follow
docs/testflight-setup.mdfor detailed instructions on each step. Once complete, push tomainto trigger your first TestFlight build.
All templates use {{PLACEHOLDER}} syntax. Replace every placeholder before writing files.
| Placeholder | Source | Example |
|---|---|---|
{{BUNDLE_ID}} | User input | com.company.myapp |
{{APPLE_ID}} | User input | dev@company.com |
{{TEAM_ID}} | User input | ABCDE12345 |
{{ITC_TEAM_ID}} | User input | 123456789 |
{{MATCH_GIT_URL}} | User input | git@github.com:org/certs.git |
{{SCHEME}} | Auto-detected | MyApp |
{{XCODE_VERSION}} | Auto-detected | 16.2 |
{{MACOS_RUNNER}} | Derived from Xcode version | macos-15 |
{{WORKSPACE_OR_PROJECT}} | Derived from dep manager | workspace or project arg |
{{DEP_MANAGER_STEPS}} | Derived from dep manager | CocoaPods/SPM/Carthage steps |
{{WORKING_DIRECTORY}} | Derived from project path | ios/ or empty |
{{WORKING_DIRECTORY_DEFAULT}} | Derived from project path | defaults: block or empty |
{{PROJECT_PATH}} | Derived from project path | ios/ or empty |
{{PROJECT_NAME}} | Auto-detected from .xcodeproj | MyApp |
{{WORKSPACE_NAME}} | Auto-detected from .xcworkspace | MyApp |
{{APP_NAME}} | Derived from scheme name | MyApp |
All questions MUST be sent to the user via Adjutant MCP messages. This is non-negotiable.
send_message({ to: "user", body: "Question about TestFlight setup: <your question>" })
Rules:
AskUserQuestion — it blocks execution and the user may not be at the terminal{{PLACEHOLDER}} syntax — replace ALL placeholders before writing files{{...}} placeholdersmkdir -p)${{ }} expressions must NOT be replaced — they are runtime expressions