iOS App Store Pre-Submission Linter
Built your app with AI?
Catch issues before you submit.
ShipLint scans your Xcode project for the rejection risks that AI-generated code misses — privacy manifests, entitlements, Info.plist issues — before you upload to App Store Connect.
npx shiplint scan .
Free and open source. No account required. Works with Xcode projects AND Swift Package Manager (Package.swift) — no .xcodeproj required.
According to Apple's 2024 App Store Transparency Report, approximately 25% of app submissions are rejected. Each rejection cycle costs developers 10-30 minutes of upload time alone, not counting the fixes. ShipLint checks 16 rules covering the most preventable rejection causes.
of App Store submissions are rejected
— Apple 2024 Transparency Report
wasted per upload/rejection cycle
before you even start fixing
covering the most preventable
App Store rejection causes
AI writes great Swift. It doesn't know Apple's rules.
Cursor, Copilot, and Claude produce working iOS code — but App Store submission isn't just about code that compiles. Apple requires specific project configurations that AI tools don't generate. ShipLint catches these gaps.
AI generates code
Your AI writes the Swift, sets up the views, handles the logic. It works in the simulator.
Apple rejects it
Missing privacy manifest. Vague usage string. Entitlement mismatch. Days lost to a rejection email.
ShipLint helps catch it
Run one command before you submit. Fix issues in minutes, not days. Ship with confidence.
What ShipLint Catches
16 rules targeting the most common App Store rejection causes — the "surprise" errors that AI-generated code doesn't know to avoid.
Each rule maps to a specific Apple guideline or ITMS error code. ShipLint tells you exactly what's wrong and how to fix it.
Privacy Manifests
Checks for PrivacyInfo.xcprivacy and required API declarations (UserDefaults, file timestamps, disk space, etc.).
Usage Description Strings
Detects missing or overly generic NS*UsageDescription strings. Vague strings like "This app needs camera access" get rejected.
Entitlements Validation
Verifies entitlements match your provisioning profile. Catches capabilities declared in code but missing from signing.
ITMS-90078Info.plist Validation
Required keys, valid bundle identifiers, version string format (CFBundleShortVersionString), and required device capabilities.
App Transport Security
Flags ATS exceptions that need written justification. NSAllowsArbitraryLoads is almost always rejected without one.
Sign in with Apple
If your app uses third-party login (Google, Facebook), Apple requires Sign in with Apple as an option. ShipLint checks for SIWA entitlement.
Guideline 4.8URL Schemes
Validates custom URL scheme registration and deep link configuration. Catches mismatches between code and plist.
Build Settings
Deployment target compatibility, required architectures, and build configuration issues in .pbxproj.
Third-Party SDK Declarations
Detects SDKs that Apple requires privacy declarations for (e.g., Firebase, Facebook SDK, AdMob) and checks for matching manifest entries.
ITMS-91053Asset Validation
Checks for required app icon sizes, launch screen configuration, and asset catalog completeness.
Required Reason API Detection
NewScans your Swift source for Required Reason API usage (UserDefaults, file timestamps, disk space, boot time, etc.) and verifies matching privacy manifest declarations. The #1 privacy-related rejection reason in 2024.
ITMS-91053privacy-010-required-reason-api
Install and Scan in 30 Seconds
No account. No config file. One command.
Install globally (or use npx)
Point it at your project
Fix what it flags, then ship
Every issue includes a clear explanation and fix suggestion. Copy the fix into your project, re-scan, submit with confidence.
Output Formats
--format text
--format json
--format sarif
Frequently Asked Questions
Common questions about App Store rejections and how ShipLint helps.
Why did Apple reject my app?
According to Apple's 2024 App Store Transparency Report, approximately 25% of app submissions are rejected. The most common preventable causes include:
- • Missing privacy manifest (
ITMS-91053) — required since iOS 17 for apps using UserDefaults, file timestamps, and other system APIs - • Missing required reason API declaration (
ITMS-90683) — you must declare why you use certain APIs - • Vague usage description strings — generic strings like "This app needs access" are rejected under Guideline 5.1.1
- • Entitlement mismatches (
ITMS-90078) — capabilities in code that don't match your provisioning profile - • App Transport Security exceptions without written justification
ShipLint checks for all 16 of the most preventable rejection causes before you submit.
How do I fix ITMS-90683?
ITMS-90683 means your app uses a "required reason API" but hasn't declared the reason in a privacy manifest. Since Spring 2024, Apple requires apps to include a PrivacyInfo.xcprivacy file declaring why they use specific system APIs.
To fix it:
- Create a
PrivacyInfo.xcprivacyfile in your Xcode project - Add the required API type (e.g.,
NSPrivacyAccessedAPICategoryUserDefaults) - Specify the reason code (e.g.,
CA92.1for app functionality) - Add the file to your target's "Copy Bundle Resources" build phase
ShipLint detects which APIs in your code trigger this requirement and tells you exactly which privacy manifest entries to add.
Does ShipLint replace Fastlane?
No — they're complementary tools that check different layers.
Fastlane Precheck validates your App Store Connect metadata: screenshots, app description, age rating, and pricing. It operates at the store listing level.
ShipLint validates your project files: Info.plist, entitlements, privacy manifests, build settings, and pbxproj configuration. It operates at the code and config level.
For maximum coverage, use both: ShipLint for project-level checks, Fastlane Precheck for store-level checks. They don't overlap.
Can ShipLint check apps built with Cursor, Copilot, or Claude?
Yes — in fact, that's exactly what ShipLint is designed for.
AI coding tools like Cursor, GitHub Copilot, and Claude are excellent at generating functional Swift code. But they often miss Apple's platform configuration requirements — privacy manifests, entitlement declarations, usage description strings — because these aren't about code correctness, they're about App Store compliance.
ShipLint bridges that gap. It checks the project-level files that AI tools don't generate or configure properly, catching issues before submission.
Just point ShipLint at your .xcodeproj, Package.swift, or project directory — it doesn't matter how the code was written. Swift PM projects work without any .xcodeproj at all.
What's the difference between ShipLint and Xcode validation?
Different timing, different scope.
Xcode's built-in validation (Archive → Validate) runs at archive time and catches binary-level issues: invalid architectures, missing symbols, code signing problems. It requires a full build.
ShipLint runs at development time — no build required. It catches configuration-level issues: missing privacy manifests, vague usage descriptions, entitlement mismatches. It runs in seconds from your terminal or CI pipeline.
Think of it as shift-left validation: catch config issues during development, not after a 10-minute archive process. ShipLint gives you feedback in seconds; Xcode validation requires a successful build first.
Is ShipLint free?
Yes. ShipLint is free and open source, licensed under MIT. Install it with npm install -g shiplint and start scanning immediately. No account, no API key, no usage limits.
View the source code at github.com/Signal26AI/ShipLint.
For AI Agents & CI Pipelines
ShipLint outputs structured JSON and SARIF for automated workflows. Integrate into GitHub Actions, Xcode Cloud, or your AI coding agent's toolchain.
name: ShipLint
on: [push, pull_request]
jobs:
lint:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- run: npm install -g shiplint
- run: shiplint scan . --format sarif > results.sarif
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: results.sarif
{
"version": "1.0.0",
"project": "VibeApp.xcodeproj",
"summary": {
"errors": 2,
"warnings": 1,
"passed": 7
},
"issues": [
{
"rule": "privacy-manifest",
"severity": "error",
"code": "ITMS-91053",
"message": "Missing privacy manifest for UserDefaults API",
"file": "Info.plist",
"fix": "Add PrivacyInfo.xcprivacy with NSPrivacyAccessedAPICategoryUserDefaults"
}
]
}
AI Agent Ready via Model Context Protocol
ShipLint works with Claude, Cursor, Windsurf, and any MCP-compatible AI coding agent. Exposes 3 tools: scan (run full project scan), rules (list all 16 rules), and explain (get detailed fix guidance for any issue) — all locally, no network required.
{
"mcpServers": {
"shiplint": {
"command": "npx",
"args": ["shiplint", "mcp"]
}
}
}
Integration Tips
--format json for machine-parseable output
0 = pass, 1 = issues
fix field with actionable remediation
Your AI wrote the code.
Now catch issues before you submit.
One command. 30 seconds. Know before you submit.
npm install -g shiplint