iOS client for Grain
grain.social
ios
photography
atproto
Development#
Requirements#
- Xcode 26+
- XcodeGen
- just
- xcbeautify
- SwiftFormat
- SwiftLint
brew install xcodegen just xcbeautify swiftformat swiftlint
Setup#
Generate the Xcode project and open it:
just generate
open Grain.xcodeproj
If using a non-Xcode editor with SourceKit-LSP (e.g. Zed), run once after generating:
xcode-build-server config -scheme Grain -project Grain.xcodeproj
No local backend needed — just sim and just device both hit the production API at grain.social.
Device builds#
Device builds require an Apple Developer account. Create a .env in the repo root:
APPLE_TEAM_ID=YOUR_TEAM_ID
BUNDLE_ID=com.yourorg.grain
BUNDLE_NAME=Grain
Then re-run just generate before building.
Pass your device UDID directly or via an env var:
just device 00000000-0000000000000000 # explicit UDID
just device $iphonemax # via shell env var
Find your device UDID with xcrun devicectl list devices.
Commands#
just sim # Build + install + launch on simulator (production API)
just sim-local # Build + install + launch on simulator (local/dev API)
just device DEVICE_ID # Build + install to a plugged-in iOS device
just test # Run tests (iPhone 17 Pro Max simulator)
just generate # Regenerate Xcode project from project.yml
just format-fix # Fix formatting in-place
just lint-fix # Fix lint violations
just release # Bump build, archive, upload to App Store Connect
Note: The Xcode project is generated from
project.yml— runjust generateafter adding or removing Swift files, or after pulling changes that touchproject.yml.