Skip to content

Instantly share code, notes, and snippets.

@kumeS
Created May 13, 2025 03:56
Show Gist options
  • Select an option

  • Save kumeS/109c3f24847b4a67ad422a59367909be to your computer and use it in GitHub Desktop.

Select an option

Save kumeS/109c3f24847b4a67ad422a59367909be to your computer and use it in GitHub Desktop.
iOSアプリ開発をCLIで自動化するbashスクリプトです。プロジェクト構造の生成、SwiftUIエントリポイント&APIキー設定ファイル作成、XcodeGenによる.xcodeproj生成、ビルド→シミュレータ起動→インストール→起動、各種設定/ドキュメントファイルの雛形作成までを一括で行います。
#!/usr/bin/env bash
set -euo pipefail
#===================================================
# init_ios_project.sh
# - プロジェクト名を引数に、
# 1. フォルダ&Sources/・Sources/Config・Resources・Tests 作成
# 2. APIKeys.swift, SwiftUI エントリポイント生成
# 3. project.yml + XcodeGen で .xcodeproj 生成
# 4. ビルド → インストール → 起動
# 5. .env.example, .gitignore, .swiftlint.yml, .swiftformat,
# Tests/*Tests.swift, .cursor/rules, README.md, Makefile, AGENT_GUIDE.md の生成
#===================================================
if [ $# -lt 1 ]; then
echo "Usage: $0 <ProjectName>"
exit 1
fi
PROJECT="$1"
BUNDLE_ID="com.example.${PROJECT}"
# ────────────────────────────────────────────────
# 1) シミュレータ自動検出
# ────────────────────────────────────────────────
SIM_NAME=$(
xcrun simctl list devices available \
| grep -E "iPhone [0-9]+" \
| head -n1 \
| sed -E 's/.*(iPhone [0-9A-Za-z \-]+) \(.*/\1/'
)
if [ -z "$SIM_NAME" ]; then
echo "⚠️ 利用可能な iPhone シミュレータが見つからず、汎用指定にフォールバック"
DEST="generic/platform=iOS Simulator"
else
echo "▶ 検出されたシミュレータ: ${SIM_NAME}"
DEST="platform=iOS Simulator,name=${SIM_NAME}"
fi
echo "▶ Destination: ${DEST}"
# ────────────────────────────────────────────────
# 2) ディレクトリ構造 & 必要ファイル生成
# ────────────────────────────────────────────────
mkdir -p "${PROJECT}"/{Sources,Resources,Tests,Sources/Config}
cd "${PROJECT}"
# 2.1) APIKeys.swift
cat <<'EOF' > Sources/Config/APIKeys.swift
/**
* APIキー設定ファイル
*
* 使用方法:
* 1. このファイルを `APIKeys.swift` としてコピー
* 2. 以下の定数に実際のAPIキーを設定
* 3. .gitignore でリポジトリにコミットされないことを確認
*/
enum APIKeys {
/// OpenAI APIキー
/// GPT-4 Vision モデルへのアクセス権が必要
/// https://platform.openai.com/ から取得できます
static let openAI = "YOUR_OPENAI_API_KEY_HERE"
}
EOF
# 2.2) SwiftUI エントリポイント
cat <<EOF > Sources/${PROJECT}App.swift
import SwiftUI
@main
struct ${PROJECT}App: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
Text("Hello, ${PROJECT}!")
.padding()
}
}
EOF
# ────────────────────────────────────────────────
# 3) project.yml の生成
# ────────────────────────────────────────────────
cat <<EOF > project.yml
name: ${PROJECT}
options:
bundleIdPrefix: com.example
settings:
SWIFT_VERSION: 5.9
configs:
Debug: debug
Release: release
targets:
${PROJECT}:
type: application
platform: iOS
deploymentTarget: "17.0"
sources: [Sources]
settings:
PRODUCT_BUNDLE_IDENTIFIER: ${BUNDLE_ID}
GENERATE_INFOPLIST_FILE: YES
EOF
# ────────────────────────────────────────────────
# 4) XcodeGen プロジェクト生成
# ────────────────────────────────────────────────
echo "▶ xcodegen generate..."
xcodegen generate
# ────────────────────────────────────────────────
# 5) ビルド → インストール → 起動
# ────────────────────────────────────────────────
DERIVED_DATA="build"
echo "▶ Building..."
xcodebuild \
-scheme "${PROJECT}" \
-destination "${DEST}" \
-derivedDataPath "${DERIVED_DATA}" \
build
if [[ "${DEST}" != generic* ]]; then
echo "▶ Simulator 起動..."
xcrun simctl boot "${SIM_NAME}" || true
APP_PATH="${DERIVED_DATA}/Build/Products/Debug-iphonesimulator/${PROJECT}.app"
echo "▶ App インストール..."
xcrun simctl install booted "${APP_PATH}"
echo "▶ App 起動..."
xcrun simctl launch booted "${BUNDLE_ID}"
else
echo "▶ 汎用シミュレータのため install/launch はスキップ"
fi
# ────────────────────────────────────────────────
# 6) 各種設定ファイル生成
# ────────────────────────────────────────────────
# .env.example
cat <<EOF > .env.example
# Environment variables example
OPENAI_API_KEY=your_openai_api_key_here
EOF
# .gitignore
cat <<EOF > .gitignore
# APIキー設定ファイルを除外
Sources/Config/APIKeys.swift
# 環境変数ファイル
.env
# Xcode ビルド成果物
build/
DerivedData/
# SwiftLintキャッシュ
.swiftlint.yml
EOF
# SwiftLint config
cat <<EOF > .swiftlint.yml
disabled_rules:
- trailing_whitespace
- line_length
EOF
# SwiftFormat config
cat <<EOF > .swiftformat
--indent 4
--line-length 100
EOF
# Basic unit test
cat <<EOF > Tests/${PROJECT}Tests.swift
import XCTest
@testable import ${PROJECT}
final class ${PROJECT}Tests: XCTestCase {
func testExample() throws {
XCTAssertTrue(true)
}
}
EOF
# .cursor/rules
mkdir -p .cursor
cat << 'EOF' > .cursor/rules
style:
- Use Swift 5.9, SwiftUI 3, async/await only
folders:
- Sources: src code
- Sources/Config: config code
- Resources: assets & plist
- Tests: unit tests
restrictions:
- Do NOT import UIKit unless explicitly asked
- Keep imports alphabetically sorted
- Log with os_log only
testing:
- Always add failing unit test before bug-fix
file_safety:
protect:
- "*.xcodeproj"
- "*.xcworkspace"
- "init_ios_project.sh"
- "Makefile"
- ".cursor/rules"
- "README.md"
- "AGENT_GUIDE.md"
- "Sources/Config/APIKeys.swift"
delete:
allow_patterns:
- "DerivedData/**"
- "build/**"
forbid_patterns:
- "Sources/**"
- "Resources/**"
- "Tests/**"
tests:
enforce_location: "Tests/"
naming_pattern: "*Tests.swift"
max_per_feature: 3
EOF
# README.md
cat << EOF > README.md
# ${PROJECT}
## Overview
- **Description**: (アプリの概要)
- **Target**: iOS 17 / Swift 5.9
- **Bundle ID**: ${BUNDLE_ID}
## Features
1. Feature A
2. Feature B
3. Feature C
## Usage
\`\`\`bash
make run
\`\`\`
EOF
# Makefile
cat << 'EOF' > Makefile
SCHEME = ${PROJECT}
DEST = ${DEST}
build:
xcodebuild -scheme $(SCHEME) -destination $(DEST) -derivedDataPath build build
run: build
@[ "\$(echo \$(DEST) | grep -q '^platform'; echo \$?)" -eq 0 ] && \
xcrun simctl boot "${SIM_NAME}" && \
xcrun simctl install booted build/Build/Products/Debug-iphonesimulator/\$(SCHEME).app && \
xcrun simctl launch booted com.example.\$(SCHEME) || \
echo "⚠️ generic simulator; skipping install+launch"
test:
xcodebuild test -scheme $(SCHEME) -destination $(DEST) -derivedDataPath build
format:
swift format .
clean:
rm -rf build
xcodebuild clean -scheme $(SCHEME)
EOF
# AGENT_GUIDE.md
cat << 'EOF' > AGENT_GUIDE.md
# Agent Interaction Guide
## 開発開始
1. Cursor Editor でフォルダを開く: \`cd ${PROJECT}\`
2. 右上歯車メニュー → **Index Workspace** を実行
## Agent モードの開発フロー例
- 🛠 新しい SwiftUI 画面 "QuizListView" を Sources/QuizListView.swift に作成して。プレビュー付きで。
- 🐛 モジュールインポートエラーが出たから、Sources/OCRService.swift に import Vision と import OpenAI を追加してビルドを通して。
- 🎨 ContentView を「Hello, ${PROJECT}!」から「Welcome!」に変更して、プレビューとシミュレータで確認まで。
## ビルド/実行のワンライナー
\`\`\`bash
make run
\`\`\`
## トラブル対応テンプレート
- 🚑 simctl のログを貼るので、原因と対処を教えて。
- 🔍 ビルドログ全文を貼るので、原因特定して修正して。
EOF
echo "✅ Initialization complete! cd ${PROJECT} → open in Cursor Editor and index the workspace."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment