สร้างและเผยแพร่แอป Mac และ iOS โดยไม่ต้องเปิด Xcode
(scottwillsey.com)- เมื่อทำการตั้งค่าบัญชี Apple และใบรับรองเริ่มต้นเสร็จแล้ว ก็สามารถทำระบบอัตโนมัติสำหรับการบิลด์ เซ็น และเผยแพร่แอป Mac และ iOS ได้ด้วย เครื่องมือ CLI ภายใน Xcode.app เพียงอย่างเดียว
- ใช้ XcodeGen ใน
project.ymlเพื่อสร้าง.xcodeprojขึ้นใหม่ และจัดการตั้งแต่การสร้างโปรเจ็กต์ไปจนถึงการ notarize บน Mac และติดตั้งลง iPhone ด้วยxcodebuild,notarytool,stapler,devicectl - การเผยแพร่บน Mac ใช้เพียง
scripts/release.shตัวเดียวเพื่อรันตามลำดับคือ archive, เซ็นด้วย Developer ID, notarize, staple ticket, ตรวจสอบกับ Gatekeeper และติดตั้งไปยัง/Applicationsโดยจะหยุดทันทีเมื่อเกิดข้อผิดพลาด - สำหรับการคอมไพล์และทดสอบอย่างรวดเร็วสามารถใช้
CODE_SIGNING_ALLOWED=NOได้ แต่ บิลด์แบบเซ็นชั่วคราว นี้จะไม่ผ่าน Gatekeeper และสิทธิ์อย่าง iCloud KVS กับ App Group ก็จะไม่ผูกกับ Team ID จริง - ให้เก็บ private key สำหรับการเซ็นและรหัสผ่านสำหรับ notarization ไว้ใน login keychain และบันทึกคำสั่งกับกฎการเผยแพร่ไว้ใน
CLAUDE.mdหรือAGENTS.mdเพื่อให้เอเจนต์อย่าง Claude Code รันเวิร์กโฟลว์ทั้งหมดซ้ำได้
สิ่งที่ทำได้โดยไม่ใช้ Xcode GUI
- ยังต้องติดตั้ง Xcode แต่ไม่จำเป็นต้องเปิดใช้งาน และ
xcodebuild,notarytool,stapler,devicectlล้วนเป็น เครื่องมือเชลล์ภายใน Xcode.app ที่รันแยกได้ - การตั้งค่าเริ่มต้น เช่น ล็อกอิน Apple ID, สร้างใบรับรอง Developer ID, และบันทึกรหัสผ่านสำหรับ notarization ยังต้องใช้ GUI หรือเทอร์มินัลแบบโต้ตอบ
- หลังตั้งค่าเริ่มต้นเสร็จแล้ว สามารถทำทุกอย่างได้โดยไม่ต้องใช้เมาส์ ตั้งแต่สร้างโปรเจ็กต์, บิลด์, archive, export แอปที่เซ็นแล้ว, notarize, ตรวจสอบ, ติดตั้ง ไปจนถึง deploy ลง iPhone จริง
- หากติดขัดเรื่องการตั้งค่าหรือการเขียนสคริปต์ สามารถให้ Claude Code หรือเครื่องมือโค้ดดิ้ง LLM อื่น ๆ สร้างเวิร์กโฟลว์ได้ โดยส่งความต้องการงานและค่าที่เฉพาะกับโปรเจ็กต์ให้
เลือกใช้ toolchain ของ Xcode แบบเต็ม
- ควรตรวจสอบก่อนว่าผลของ
xcode-select -pเป็น/Applications/Xcode.app/Contents/Developerหรือไม่ - หากเลือกใช้ Command Line Tools แบบแยกอยู่ ให้ระบุ toolchain ของ Xcode แบบเต็ม ด้วยคำสั่งต่อไปนี้
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
/Library/Developer/CommandLineToolsที่ติดตั้งด้วยxcode-select --installมีclangและgitแต่ไม่มีเครื่องมือพัฒนาแอปครบชุด เช่น iOS SDK,notarytool,devicectl- หากติดตั้ง Xcode ไว้แล้ว ก็ไม่จำเป็นต้องติดตั้งแพ็กเกจ Command Line Tools แยกต่างหาก
- การยอมรับไลเซนส์และติดตั้งส่วนประกอบเพิ่มเติมก็ทำผ่าน CLI ได้
sudo xcodebuild -license accept
sudo xcodebuild -runFirstLaunch
สร้างโปรเจ็กต์ซ้ำได้ด้วย XcodeGen
- XcodeGen ใช้จัดการการตั้งค่าโปรเจ็กต์ Xcode ด้วย YAML และจะสร้าง
.xcodeprojใหม่ทุกครั้งที่บิลด์ - สามารถ ดาวน์โหลดจาก GitHub หรือติดตั้งผ่าน Homebrew ได้
brew install xcodegen
.xcodeprojเป็นโฟลเดอร์ที่บน macOS ดูเหมือนไฟล์ และเนื่องจาก Xcode เปลี่ยนไฟล์ภายในกับ reference อยู่เรื่อย ๆ จึงอาจเกิด conflict หรือความเปลี่ยนแปลงที่ไม่จำเป็นใน Git repository- หาก commit เฉพาะ
project.ymlลง Git และ ignore.xcodeprojที่สร้างขึ้น ก็จะทำให้การตั้งค่าโปรเจ็กต์ยังคง reproducible
xcodegen generate
ตั้งค่าบัญชีนักพัฒนา Apple และใบรับรอง
- ต้องเพิ่ม Apple ID ใน
Settings → Accountsของ Xcode - การเผยแพร่แอปและ notarization ต้องใช้ บัญชี Apple Developer แบบเสียเงิน
- สร้างใบรับรองสำหรับการเผยแพร่ได้ที่
Settings → Accounts → Apple ID → Manage Certificates… → + → Developer ID Application - Apple Development และ Developer ID Application ใช้คนละกรณี
- Apple Development ใช้สำหรับรันบนอุปกรณ์ของตัวเองหรือส่งไปยัง iPhone เพื่อดีบักแบบโลคัล
- Developer ID Application จำเป็นเมื่อต้องเผยแพร่
.appที่ notarize แล้วและผ่าน Gatekeeper บน Mac ของผู้อื่น
- เมื่อสร้างใบรับรอง Developer ID Application แล้ว ตัวใบรับรองและ private key ที่จับคู่กันจะถูกติดตั้งไว้ใน login keychain
- การเซ็นจริงจะใช้ private key และไม่สามารถดาวน์โหลดใหม่ได้ ดังนั้นอย่าลบ และควร สำรอง keychain ไว้
เก็บ credential สำหรับ notarization ไว้ใน keychain
- การ notarize แอป Mac คือกระบวนการอัปโหลดแอปที่เซ็นแล้วไปให้ Apple ตรวจสอบมัลแวร์
notarytoolจะยืนยันตัวตนด้วยโปรไฟล์ที่เก็บไว้ใน keychain และตอนสร้างโปรไฟล์ครั้งแรกต้องกรอกรหัสผ่านเฉพาะแอปแบบโต้ตอบ
xcrun notarytool store-credentials App-Name \
--apple-id "you@example.com" \
--team-id YOUR-TEAM-ID
- ไม่ควรยืมใช้โปรไฟล์ notarization ของแอปอื่น ควร สร้างตามชื่อแอปนั้น ๆ เพื่อหลีกเลี่ยงการล้มเหลวแบบเงียบ ๆ ในสภาพแวดล้อมอื่น
- รหัสผ่านเฉพาะแอปไม่เหมือนกับรหัสผ่าน Apple ID และสร้างได้จาก
Sign-In & Security → App-Specific Passwordsที่ เว็บไซต์ Apple ID - หากเปลี่ยนรหัสผ่าน Apple ID รหัสผ่านเฉพาะแอปอาจหมดอายุโดยไม่มีการแจ้งเตือนแยก
- ถ้าเกิด
401 invalid credentialsระหว่าง notarization ก่อนจะสงสัยว่าการตั้งค่าทั้งหมดผิด ควรตรวจสอบก่อนว่ารหัสผ่านเฉพาะแอปหมดอายุหรือไม่
- ถ้าเกิด
- ตรวจสอบได้ว่าบันทึกโปรไฟล์แล้วหรือยังด้วยคำสั่งนี้
xcrun notarytool history --keychain-profile App-Name
- หากเก็บรหัสผ่านเฉพาะแอปไว้ในคลัง 1Password ที่ Claude Code เข้าถึงได้ ก็สามารถให้เอเจนต์สร้างโปรไฟล์ notarization สำหรับแอปใหม่ได้เช่นกัน
- แม้จะสามารถทำให้การกรอกรหัสผ่านอัตโนมัติด้วย
--passwordได้ แต่ อาจทิ้งรหัสผ่านไว้ใน shell history ดังนั้นจึงควรกรอกเองครั้งเดียวแล้วเก็บไว้ใน keychain หรือ 1Password
แยกการตั้งค่าการเซ็นในเครื่องกับข้อมูลลับ
- Team ID และ bundle prefix ที่จำเป็นต่อการเซ็นจริงให้เก็บไว้ใน
Local.xcconfig
cp Local.xcconfig.example Local.xcconfig
BUNDLE_PREFIX = your.real.prefix
DEVELOPMENT_TEAM = YOUR-TEAM-ID
- ควรเพิ่ม
Local.xcconfigลงใน.gitignoreเพื่อไม่ให้การตั้งค่าโลคัลของแต่ละโปรเจ็กต์เข้าไปอยู่ใน repository - private key สำหรับการเซ็นจะอยู่ใน login keychain ส่วนรหัสผ่านเฉพาะแอปสำหรับ notarization จะอยู่ใน keychain profile ของ
notarytoolดังนั้น ข้อมูลลับจะไม่ถูกบันทึกลง Git
ทำระบบอัตโนมัติสำหรับการเผยแพร่บน Mac ด้วย release.sh
scripts/release.shใน repository จะรัน pipeline การเผยแพร่แอป Mac ทั้งหมดด้วยคำสั่งเดียว
./scripts/release.sh
-
สคริปต์ทำงานตามลำดับดังนี้
- ตรวจสอบล่วงหน้าว่ามี
xcodegenและโปรไฟล์ notarization อยู่หรือไม่ - สร้างโปรเจ็กต์ใหม่ด้วย
xcodegen generate - สร้าง Release archive ด้วย
xcodebuild archive - export แอปที่เซ็นด้วย Developer ID โดยใช้
ExportOptions.plistและxcodebuild -exportArchive - zip แอปแล้วส่งให้ Apple ด้วย
notarytool submit --wait - ติด ticket notarization ด้วย
stapler staple - ตรวจสอบว่า Gatekeeper อนุญาตหรือไม่ด้วย
spctl - ปิดโปรเซสเดิมแล้วคัดลอกแอปไปยัง
/Applications - ลงทะเบียนแอปที่ติดตั้งแล้วด้วย
lsregister - ตรวจสอบ ticket และสถานะ Gatekeeper ของ bundle ที่ติดตั้งแล้วอีกครั้ง
- ตรวจสอบล่วงหน้าว่ามี
-
แม้โมเดลจะรู้ขั้นตอนการเผยแพร่ทั่วไป แต่ข้อมูลเฉพาะโปรเจ็กต์ เช่น ชื่อ scheme, Team ID, ชื่อโปรไฟล์ notarization, ตำแหน่งติดตั้ง ยังต้องให้ผู้ใช้ระบุ
-
หากสคริปต์ตัวแรกทำงานล้มเหลว ก็ต้องปรับแก้ตามผลลัพธ์ที่รันออกมาก่อน แต่เมื่อเวิร์กโฟลว์นิ่งแล้ว ก็สามารถรันคำสั่งเผยแพร่ได้โดยไม่ต้องแก้เพิ่ม
-
ป้องกันความล้มเหลวและการเผยแพร่ที่ไม่สมบูรณ์
set -euo pipefailจะหยุดสคริปต์ทันทีเมื่อมีคำสั่งใดคำสั่งหนึ่งล้มเหลว เพื่อไม่ให้สถานะที่ไม่สมบูรณ์ถูกมองว่าสำเร็จcd "$(dirname "$0")/.."จะย้ายไปยัง root ของ repository ไม่ว่าสคริปต์จะถูกเรียกจากไดเรกทอรีใด- บล็อกตรวจสอบล่วงหน้า ใช้เช็ก
xcodegenและโปรไฟล์ notarization ก่อนเข้าสู่ขั้นตอน archive ที่ใช้เวลานาน - ไม่เพียงตรวจสอบแอปที่ export แล้ว แต่ยังตรวจสอบแอปที่คัดลอกไปไว้ใน
/Applicationsอีกครั้ง เพื่อจับกรณีที่ bundle เสียหายระหว่างการคัดลอก - หากต้องใช้โปรไฟล์ notarization อื่น ก็สามารถ override ด้วย environment variable ได้
TZED_NOTARY_PROFILE=<name> ./scripts/release.sh
ส่งต่อกฎการเผยแพร่ให้เอเจนต์
- หาก
release.shสามารถเผยแพร่ได้ด้วยคำสั่งเดียวCLAUDE.mdหรือAGENTS.mdก็จะทำให้เอเจนต์ใช้คำสั่งนั้นทุก session โดยไม่ต้องสั่งเพิ่ม - ในเอกสารควรบันทึกการสร้างโปรเจ็กต์ใหม่, unit test, การบิลด์ macOS แบบรวดเร็ว, และคำสั่งเผยแพร่จริง
xcodegen generate
swift test
xcodebuild -project YOUR-APP-NAME.xcodeproj \
-scheme YOUR-APP-NAME-macOS \
-destination 'platform=macOS' \
CODE_SIGNING_ALLOWED=NO build
./scripts/release.sh
- ควรระบุความต่างของเส้นทางบิลด์ทั้งสองแบบไว้ในเอกสารด้วย
- บิลด์
CODE_SIGNING_ALLOWED=NOเหมาะกับ CI และการตรวจสอบโลคัลแบบรวดเร็ว - หากเป็นการเผยแพร่แอปเมนูบาร์จริง การผ่านคุณสมบัติ quarantine และการซิงก์ iCloud จำเป็นต้องใช้
release.shที่ทำการเซ็นด้วย Developer ID และ notarize
- บิลด์
- หากสั่งให้ไปอ้างอิงรูปแบบที่ทำไว้ในอีกแอปหนึ่งบน repository อื่น Claude Code ก็สามารถคัดลอกการตั้งค่าเดียวกันไปใช้กับแอปถัดไปได้
บิลด์และทดสอบแบบเร็วโดยไม่เซ็นจริง
- unit test ที่อิงกับ Swift Package Manager สามารถรันได้โดยไม่ต้องบิลด์ผ่าน Xcode
swift test
- การตรวจสอบการคอมไพล์ของแอป macOS แบบรวดเร็วทำได้โดยปิดการเซ็น
xcodebuild -project TZed.xcodeproj \
-scheme TZed-macOS \
-destination 'platform=macOS' \
CODE_SIGNING_ALLOWED=NO build
- การบิลด์สำหรับ iOS app และ widget extension บน simulator ก็ทำได้ด้วยวิธีเดียวกัน
xcodebuild -project TZed.xcodeproj \
-scheme TZed-iOS \
-destination 'generic/platform=iOS Simulator' \
CODE_SIGNING_ALLOWED=NO build
- บิลด์แบบเซ็นชั่วคราว ที่สร้างด้วย
CODE_SIGNING_ALLOWED=NOใช้สำหรับคอมไพล์และรันบน simulator ได้ - แต่บิลด์นี้จะถูก Gatekeeper ปฏิเสธ และเนื่องจากไม่มี team prefix จึงไม่สามารถผูกสิทธิ์อย่าง iCloud KVS และ App Group ได้ จึงใช้สำหรับการเผยแพร่ไม่ได้
ทำ headless deploy ลง iPhone จริง
- การ deploy ไปยังอุปกรณ์ iOS ไม่มีขั้นตอน notarization แบบเดียวกับแอป Mac และใช้
xcodebuildกับdevicectl - แอปสำหรับอุปกรณ์จริงจะถูกบิลด์และเซ็นด้วยใบรับรอง Apple Development และ development provisioning profile
xcodebuild -project TZed.xcodeproj \
-scheme TZed-iOS \
-destination 'generic/platform=iOS' \
-allowProvisioningUpdates \
-derivedDataPath build/ios \
archive -archivePath build/TZed-iOS.xcarchive
.appที่สร้างขึ้นสามารถติดตั้งได้โดยระบุ UDID ของอุปกรณ์ที่เชื่อมต่ออยู่
xcrun devicectl device install app \
--device <DEVICE-UDID> build/ios/…/TZed.app
devicectl list devicesจะแสดงอุปกรณ์ที่เชื่อมต่อและจับคู่แล้วพร้อม UDID- เมื่อระบุ
-allowProvisioningUpdatesระบบจะดึง development provisioning profile ที่จำเป็นมาให้
การทำงานของ code signing โดยไม่ใช้ GUI
-
เมื่อสร้างใบรับรอง Developer ID Application, Apple จะออกใบรับรอง ส่วน Mac จะสร้าง private key ที่จับคู่กันและเก็บทั้งคู่ไว้ใน login keychain
-
codesignที่ถูกเรียกโดยxcodebuildจะใช้ private key เซ็นไบนารี และฝังใบรับรองที่เชื่อมโยงไปถึง Apple root certificate ลงในแอปเพื่อให้ตรวจสอบผู้เซ็นได้ -
หากใช้
signingStyle: automatic,xcodebuildจะเลือกใบรับรองที่ตรงกับ Team ID และดึง provisioning profile ที่จำเป็นจาก Apple -
ดังนั้นจึงไม่จำเป็นต้อง commit provisioning profile ลงใน repository
-
สิทธิ์, notarization, และการ staple
- ไฟล์
.entitlementsของแต่ละ target จะมีสิทธิ์ต่าง ๆ เช่น sandbox, network client, iCloud KVS, App Group - สิทธิ์เหล่านี้จะถูกผูกเข้ากับ Team ID จริงตอนเซ็นจริง ดังนั้นในบิลด์แบบเซ็นชั่วคราว iCloud และ App Group จะไม่ทำงานอย่างถูกต้อง
- การเซ็นและการ notarize เป็นคนละขั้นตอนกัน
- การเซ็นคือการพิสูจน์ว่าใครเป็นผู้สร้างแอป
- การ notarize คือกระบวนการที่ Apple ตรวจสอบมัลแวร์ในแอปที่เซ็นแล้วและออก ticket ให้
- การ staple คือการแนบ ticket นั้นเข้าไปในแอป เพื่อให้ Gatekeeper เชื่อถือได้แม้อยู่แบบออฟไลน์
- สำหรับแอปเมนูบาร์แบบ
LSUIElementที่ใช้ UI ซ่อนอยู่ การ notarize จำเป็นต่อการหลีกเลี่ยงการถูกตรวจจับโดย XProtect
- ไฟล์
-
คำสั่งตรวจสอบด้วยตนเอง
codesign -dv --verbose=4 /Applications/TZed.app spctl -a -vvv -t exec /Applications/TZed.app stapler validate /Applications/TZed.appcodesignใช้ตรวจสอบผู้เซ็นและใบรับรองspctlใช้ตรวจสอบว่า Gatekeeper จะอนุญาตให้รันหรือไม่stapler validateใช้ตรวจว่ามี ticket notarization ถูกแนบไว้แล้วหรือไม่
เครื่องมือมาตรฐานที่เอเจนต์ใช้รัน
- ไม่จำเป็นต้องมี MCP server สำหรับบิลด์หรือปลั๊กอินเฉพาะทางแยกต่างหาก โดย Claude Code จะรัน CLI มาตรฐานผ่าน non-interactive shell
- เครื่องมือที่ใช้คือ
xcodebuild,xcrun notarytool,xcrun stapler,spctl,codesign,devicectl,xcodegen,swift CLAUDE.mdใช้บอกเอเจนต์ถึงกฎการตั้งชื่อโปรไฟล์ notarization, ความต่างระหว่างบิลด์แบบเร็วกับการเผยแพร่จริง, และกฎว่าต้องใช้release.shตอนเผยแพร่- มีเพียงขั้นตอนแรกของ
notarytool store-credentialsเท่านั้นที่ยังเป็นแบบโต้ตอบ ส่วนขั้นตอนหลังจากนั้นทั้งหมดสามารถทำอัตโนมัติได้
แทนที่งานใน Xcode GUI ด้วย CLI
- การสร้าง
.xcodeprojที่ปกติ Xcode จัดการให้ สามารถแทนด้วยproject.ymlและxcodegen generate ⌘Bหรือปุ่ม Run ตรงกับxcodebuild … buildProduct → Archiveทำได้ด้วยxcodebuild … archive- การเผยแพร่แอปผ่าน Organizer สามารถแทนได้ด้วย
xcodebuild -exportArchive - การอัปโหลดผ่าน Organizer ทำได้ด้วย
xcrun notarytool submit --wait - การแนบ ticket อัตโนมัติใช้
xcrun stapler staple - ขั้นตอนติดตั้งด้วยการลากแล้ววางไปยัง
/Applicationsสามารถแทนด้วยcp -Rและlsregister - การกด Run บน iPhone จริง แทนได้ด้วย
xcodebuild archiveและdevicectl device install - เมื่อทำครบทั้งการติดตั้ง Xcode และ XcodeGen, การตั้งค่า credential ครั้งแรก, และการเขียน
release.shกับCLAUDE.mdแล้ว การเผยแพร่บิลด์ใหม่ในครั้งถัดไปจะทำได้ด้วย ประโยคเดียวหรือคำสั่งเดียว
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
มีหลายอย่างที่แก้ในแซนด์บ็อกซ์ไม่ได้ จึงรันเอเจนต์ AI โดยตรงบน Mac แต่พอเห็น เหตุการณ์ที่ xAI อัปโหลดโฮมไดเรกทอรีที่มีแม้กระทั่งคีย์ SSH รวมอยู่ด้วย ก็ทำให้ต้องกลับมาคิดทบทวนทางเลือกนี้อย่างจริงจัง
ไม่ได้กังวลมากนักว่าตัวเครื่องจะพัง เพราะส่วนใหญ่สำรองไว้หรือ commit ไว้ใน Git แล้ว จึงกู้คืนได้ภายในไม่กี่ชั่วโมง แต่ไม่ต้องการให้ไดเรกทอรี
.sshถูกส่งไปยังเอเจนต์ AI เด็ดขาด และไม่ควรพยายามกันด้วยพรอมป์ต์ แต่ควร บล็อกในระดับระบบ กำลังพิจารณาวิธีสร้างผู้ใช้แยกต่างหากและตั้งสิทธิ์700ให้โฮมไดเรกทอรี ความปลอดภัยเหมือนถอยกลับไปยุค 1990 แต่ก็มีอีกด้านคือแลกกับการทำงานให้เสร็จได้เร็วอย่างไม่เคยมีมาก่อน ผมเองก็ใช้วิธีเสี่ยงแบบนี้อยู่ จึงไม่ได้จะตำหนิคนอื่นถ้าต้องการโซลูชันแบบแพ็กเกจ สามารถใช้โอเพนซอร์สอย่าง Tart https://tart.run/ หรือ VirtualBuddy https://github.com/insidegui/VirtualBuddy ได้ หรือจะ vibe coding เครื่องมือที่ห่อหุ้ม OS API https://developer.apple.com/documentation/virtualization เองก็ได้ ช่วงหลังยังมี Apple container https://github.com/apple/container ออกมาด้วย
agentเมื่อหนึ่งปีก่อนเคยล้มเหลวเพราะ OAuth และ keychain แต่เมื่อไม่นานมานี้ Claude แนะนำว่าสามารถใช้CLAUDE_CODE_OAUTH_TOKENได้ จึงทำสำเร็จต้องมีเครื่องมือช่วยตั้งสิทธิ์ด้วย ACL แต่ตอนนี้ใช้งานได้บน macOS ระดับความเสี่ยงอยู่ประมาณกึ่งกลางระหว่างแซนด์บ็อกซ์ Claude พื้นฐานกับการแยกแบบคอนเทนเนอร์/เครื่องเต็มรูปแบบ พอแซนด์บ็อกซ์ของ Claude เองดีขึ้น ก็เคยสงสัยว่าการลงทุนกับโปรเจกต์ป้องกันสองชั้นนี้คุ้มหรือไม่ แต่เมื่อดูความเป็นไปได้ที่โฮมไดเรกทอรีจะรั่ว ก็มีเหตุผลเพียงพอที่จะทำต่อ ยังไม่ได้เปิดเป็นโอเพนซอร์ส แต่ยินดีคุยกับคนที่สนใจ
กำลังลอง ใช้แค่ Linux เพื่อ build และทดสอบแอป iOS สนุก ๆ อยู่ ซึ่งง่ายอย่างน่าประหลาดใจ และ https://github.com/xtool-org/xtool ก็ทำงานได้ดีมาก
แม้บน Linux ก็สามารถติดตั้งลง iPhone โดยตรงผ่าน USB ได้ โดยไม่ต้องอัปโหลดขึ้น TestFlight หรือ App Store หากยังไม่แน่ใจ สามารถขอให้ coding agent สร้างแอป iOS Hello World แล้วอัปโหลดให้ ก็เริ่มต้นได้ง่าย
โปรเจกต์โอเพนซอร์สของผม Axiom ช่วยให้เครื่องมือรันโค้ดทำงานด้านการพัฒนาสำหรับระบบปฏิบัติการของ Apple ได้อย่างมีประสิทธิภาพ
นอกจากเทคนิคและเอเจนต์หลากหลายแบบแล้ว ยังมีเครื่องมือสำหรับ LLM อย่าง
xclog,xcprof,xcsym,xcuiด้วย เครื่องมือเหล่านี้เปิดเผยฟังก์ชันที่จำเป็นอย่างประหยัดโทเค็น และมีประโยชน์ต่อเทคนิคหรือเอเจนต์ภายนอก Axiom เช่นกัน Axiom: https://charleswiltgen.github.io/Axiom/, เครื่องมือ CLI: https://charleswiltgen.github.io/Axiom/tools/พออ่านประโยคที่ว่า “ให้ Claude Code ทำสคริปต์ที่ archive, ลงนาม Developer ID, notarize, staple, ติดตั้งลง
/Applicationsโดยไม่ต้องเปิด Xcode และให้หยุดอย่างชัดเจนหากขั้นตอนไหนล้มเหลว” แล้วรู้สึกแปลก ๆ เพราะบทความที่กำลังอ่านอยู่นี้เองก็เหมือน Claude กำลังพูดกับเราในแทบทุกขั้นตอนของบทความยังมีคำแนะนำซ้ำ ๆ ทำนองว่า “เอาบทความนี้ให้ Claude Code หรือเครื่องมือ coding LLM ที่ต้องการดู แล้วให้มันจัดการเอง”, “ถ้าไม่รู้ก็ถาม LLM ให้ช่วยตั้งค่า”, “จุดประสงค์ของการใช้ LLM คือหลีกเลี่ยงงาน manual ที่ไม่ต้องการ”, “ให้มันสร้าง workflow ให้” ซึ่งทำให้รู้สึกแปลกที่ แนะนำให้กลับไปถาม LLM อีกที
จากมุมมองของคนที่พัฒนาแอป Mac และ iOS ด้วยเอเจนต์มานานกว่าหนึ่งปี ผมมองว่าบทความนี้เป็นคำแนะนำที่ไม่ดี โดยเฉพาะอย่างยิ่ง Xcode MCP ที่ยอดเยี่ยมนั้นต้องให้ Xcode กำลังทำงานอยู่
เมื่อใช้เครื่องมือ MCP จะเข้าถึงฟังก์ชันต่าง ๆ ได้เร็วและกระชับกว่า
xcodebuildมาก และยังสร้างและเรนเดอร์#Previewซึ่งทำไม่ได้หากปิด Xcode ไปแล้วได้ด้วย MCP และเอเจนต์ในตัวของ Xcode 27 ยังควบคุม simulator ได้ดีมากผ่าน DeviceHub โดย DeviceHub มาแทนที่ Simulator.app และดูเหมือนว่าเอเจนต์จะเข้าใจและจัดการได้โดยไม่ต้องใช้เครื่องมืออย่างaxeไปดัดแปลง Accessibility API แบบอ้อม ๆXcode MCP ไม่ได้สมบูรณ์แบบ ปัญหาที่หน้าต่างขอสิทธิ์เด้งขึ้นมาทุกครั้งที่เรียกใช้เอเจนต์นั้น ผมเลี่ยงด้วยการให้ Keyboard Maestro อนุมัติอัตโนมัติ ถึงอย่างนั้น Xcode 27 ก็ปรับปรุง ความใช้งานได้ของการ vibe coding บน Xcode ไปมาก ตอนนี้ผมไม่ได้จัดการ MCP แยกต่างหาก แต่รัน Codex จาก UI เอเจนต์ของ Xcode เอง ซึ่งสภาพแวดล้อมการรันนี้ช่วยชี้นำโมเดลให้ใช้เครื่องมือที่มีอยู่ได้ดีขึ้น สุดท้ายจึงได้สิ่งที่สำคัญที่สุดคือ feedback ที่เร็วขึ้นและการตรวจสอบที่แข็งแรงขึ้น
Xcode-mcp-proxyที่ทำหน้าที่ proxy Xcode MCP พร้อมคลิกกล่องโต้ตอบและกู้คืนการเชื่อมต่อให้ด้วย สงสัยว่าการทดสอบแอป macOS ใช้ Peekaboo หรือใช้การทำ screenshot automation ทั่วไปถ้าอยากแตะ IDE ของ iOS และ Android ให้น้อยที่สุด React Native กับ Expo ก็เป็นตัวเลือกที่ดี
Xcode และ Android Studio ใช้เฉพาะตอนติดตั้ง device simulator ส่วนที่เหลือไปจนถึงการปล่อยขึ้นสโตร์ toolchain ของ Expo จะจัดการให้ บน Windows ที่ติดตั้ง Xcode ไม่ได้ หากใช้แอปแบบ managed ของ Expo ก็สามารถรันแอป iOS บน iPhone ได้โดยตรง จุดเริ่มต้นบนพื้นฐาน RN และ Expo ที่ดูแลดีคือ Ignite ซึ่งยอดเยี่ยม: https://github.com/infinitered/ignite
พูดอย่างเคร่งครัดแล้วก็ยังเป็นการ ใช้ Xcode อยู่ดี Xcode คือ GUI ที่บั๊กเยอะมาก ซึ่งห่อหุ้มยูทิลิตีและแอประดับระบบ UNIX หลายตัวที่โดยรวมค่อนข้างเสถียร
วิธีปล่อยแอปผ่าน CLI เป็นแนวปฏิบัติเก่าแก่ และทำได้อย่างน้อยก็ตั้งแต่ปี 2012 ตอนที่ผมปล่อยแอป Xcode ตัวแรก
อย่างน้อยในการดีบักบางส่วน ทุกคนก็ หลีกเลี่ยงการใช้ Xcode ไม่ได้
เรื่อง build นั้นเอเจนต์สามารถจัดการส่วนใหญ่จาก command line ได้อยู่แล้ว และถ้าให้คำสั่งที่ชัดเจนตามสถานการณ์ก็ build ได้เร็วขึ้น หากใช้ file system synchronization groups ของ Xcode อยู่ XcodeGen อาจเป็นงานเสริมที่ไม่จำเป็นก็ได้
สำหรับ iOS สิ่งที่อยากแนะนำที่สุดคือเพิ่ม ฟังก์ชัน App Store Connect ให้เอเจนต์: https://github.com/rorkai/App-Store-Connect-CLI แบบนั้นไม่เพียงไม่ต้องเปิด Xcode ค้างไว้ตลอด แต่ยังไม่ต้องอยู่ใกล้ MacBook ด้วย คุณแก้ผ่าน Codex บน iPhone แล้วสั่ง
ascให้ build และอัปโหลดไป TestFlight จากนั้นดาวน์โหลดเวอร์ชันใหม่มารันแล้ววนซ้ำได้เลยยังรู้สึกติดใจอยู่เรื่อย ๆ กับความเป็นจริงที่ว่านักพัฒนาที่งบไม่พอซื้อ Mac แทบจะถูก กันออกจากการพัฒนา iOS โดยปริยาย ทุกครั้งที่ราคาผลิตภัณฑ์ Apple สูงขึ้น ก็ยิ่งมีคนที่เข้าร่วมพัฒนาไม่ได้มากขึ้น
ถ้าจะ vibe coding แอป ระยะยาวแล้ว Expo เป็นตัวเลือกที่ดีกว่า เพราะใช้ React เป็นพื้นฐาน ทำให้ในข้อมูลฝึกของ LLM มีโค้ด React มากกว่า Swift มาก และคุณภาพของโค้ดผลลัพธ์ก็ดีกว่าด้วย
ทำทุกอย่างจาก command line ได้ และเพราะเป็น web view การดีบักก็ง่าย หลัง compile เป็นแอป iOS native แล้ว ความรู้สึกใช้งานก็คล้ายแอป native อื่น ๆ เมื่อจับคู่ Expo กับ Fastlane จะทำให้การส่งและ deploy บน iOS เป็นอัตโนมัติได้ทั้งหมด จนสามารถอัปเวอร์ชันใหม่ขึ้น App Store ได้ด้วยคำสั่งเดียว