Catch App Store & Google Play rejection reasons before you submit.
Static analysis for mobile apps β checks your project against 71 Apple & Google guidelines so you don't get rejected.
Installation β’ Quick Start β’ AI-Ready Output β’ 71 Rules β’ Platforms β’ 4 Languages
25% of all iOS apps get rejected. Google Play blocked 1.75M apps in 2024 alone. Most rejections are preventable. Guidelint finds them before Apple and Google do.
npx guidelint ./MyApp guidelint v0.1.0
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Platform: IOS
Files: 47 files scanned
Rules: 30 rules checked
CRITICAL (3)
β [IOS-PRIV-100] PrivacyInfo.xcprivacy not found
β PrivacyInfo.xcprivacy file is missing. Required since May 2024.
β Fix: Create via Xcode > New File > iOS > Resource > App Privacy
β [IOS-PRIV-001] NSCameraUsageDescription missing
β Camera usage detected but NSCameraUsageDescription is not in Info.plist
β File: Info.plist
β Fix: Add NSCameraUsageDescription to Info.plist
β Guideline 5.1.1
β [COM-SEC-001] Hardcoded API key/secret detected
β Hardcoded API key or secret found in source code
β File: NetworkService.swift
β Fix: Use environment variables or Keychain
HIGH (5)
β [IOS-SEC-001] App Transport Security fully disabled
β NSAllowsArbitraryLoads=true β all HTTP traffic is allowed
β File: Info.plist
β Fix: Remove NSAllowsArbitraryLoads, use NSExceptionDomains for specific domains
β [IOS-IAP-001] StoreKit imported, Restore Purchases missing
β StoreKit is imported but no Restore Purchases implementation found
β Fix: Add a Restore Purchases button
β Guideline 3.1.1
β [IOS-PRIV-300] Account deletion not found
β User authentication detected but no account deletion feature found
β Fix: Add in-app account deletion flow
β [COM-SEC-002] HTTP URL usage
β HTTP URL detected β use HTTPS instead
β Fix: Change all URLs to HTTPS
β [COM-META-001] Lorem ipsum placeholder content
β Lorem ipsum detected β will be rejected in store review
β Fix: Replace with real content
SCORE: 57/100 β RISKY β Review issues before submitting
privacy ββββββββββββββββββββ 50/100
performance ββββββββββββββββββββ 73/100
security ββββββββββββββββββββ 30/100
design ββββββββββββββββββββ 70/100
business ββββββββββββββββββββ 85/100
legal ββββββββββββββββββββ 85/100
- Why Guidelint?
- Installation
- Quick Start
- AI-Ready Output β the killer feature
- Auto-Fix β
--fixflag - Ignore Files β
.guidelintignore - Language Support β EN, TR, DE, NL
- Supported Platforms
- All 71 Rules β complete reference
- Scoring System
- Output Formats
- CI/CD Integration
- Programmatic API
- What Guidelint Catches β real rejection data
- Roadmap
- Contributing
You've spent weeks building your app. You submit it. Then you wait. Days later β rejected.
Missing PrivacyInfo.xcprivacy. A NSCameraUsageDescription that says "We need camera access." An http:// URL hiding in line 847. A targetSdkVersion stuck at 33.
These are not bugs. They're checklist items that cost developers days of back-and-forth with review teams. The review cycle typically takes 24-48 hours per attempt. One missing key in Info.plist? That's 2 days wasted.
Guidelint scans your project in seconds and tells you exactly what to fix β in your language.
| Feature | Guidelint | Manual review | Other linters |
|---|---|---|---|
| App Store guidelines | β 71 rules | β Human error | β Code-only |
| Google Play guidelines | β 23 rules | β Human error | β Code-only |
| Privacy manifest (2024) | β Auto-detect | β Not supported | |
| AI-ready output | β
--format prompt |
β | β |
| Multi-language | β EN/TR/DE/NL | β | β |
| Cross-platform | β iOS+Android+RN+Flutter | β Platform-specific | |
| Auto-fix | β
--fix flag |
β | |
| Ignore files | β
.guidelintignore |
β | β |
| Zero config | β
npx guidelint . |
β | |
| Readiness score | β 0-100 with verdict | β | β |
# Run directly β no install needed
npx guidelint ./MyApp
# Or install globally
npm install -g guidelint
guidelint ./MyAppRequirements: Node.js 18 or higher.
That's it. No config files, no setup, no accounts. Point it at your project and go.
guidelint ./MyiOSAppguidelint [path] [options]
Options:
-f, --format <format> Output format: terminal, prompt, json (default: "terminal")
-l, --lang <language> Output language: en, tr, de, nl (default: "en")
--ios-only Only run iOS rules
--android-only Only run Android rules
--min-severity <severity> Minimum severity to report (default: "low")
--ignore <patterns...> Glob patterns to ignore
--fix Auto-fix simple issues where possible
-V, --version Output version number
-h, --help Display help# Scan and get AI-ready fix instructions
guidelint ./MyApp --format prompt
# Scan in Turkish
guidelint ./MyApp --lang tr
# JSON output for CI/CD pipelines
guidelint ./MyApp --format json
# Only iOS rules
guidelint ./MyApp --ios-only
# Only Android rules
guidelint ./MyApp --android-only
# Show only critical and high severity issues
guidelint ./MyApp --min-severity high
# Auto-fix common issues
guidelint ./MyApp --fix
# Ignore specific directories
guidelint ./MyApp --ignore "test/**" "vendor/**"
# Combine: German, prompt format, critical only
guidelint ./MyApp --lang de --format prompt --min-severity critical
# Copy AI-ready report to clipboard (macOS)
guidelint ./MyApp --format prompt | pbcopy
# Pipe JSON to jq for custom filtering
guidelint ./MyApp --format json | jq '.findings[] | select(.severity == "critical")'This is what makes Guidelint different from every other linter.
Run with --format prompt and get a structured markdown report designed to be pasted directly into ChatGPT, Claude, Copilot, or any AI assistant:
guidelint ./MyApp --format prompt | pbcopyThe AI receives:
- Full context β project info, platform, scores
- Every finding β rule ID, severity, category, file path, guideline reference
- A prioritized action plan β step-by-step instructions the AI can follow
## AI Fix Instructions
If you are an AI assistant helping fix these issues, here is a prioritized action plan:
### Step 1: Fix Critical Issues (must fix before submission)
1. **[IOS-PRIV-100]** Create PrivacyInfo.xcprivacy via Xcode > New File > App Privacy
2. **[IOS-PRIV-001]** Add NSCameraUsageDescription to Info.plist β in `Info.plist`
3. **[COM-SEC-001]** Move API key to environment variable β in `NetworkService.swift`
### Step 2: Fix High Severity Issues (strongly recommended)
1. **[IOS-SEC-001]** Remove NSAllowsArbitraryLoads, use NSExceptionDomains β in `Info.plist`
2. **[IOS-IAP-001]** Add Restore Purchases handler and button
3. **[IOS-PRIV-300]** Add in-app account deletion flow
4. **[COM-SEC-002]** Change all URLs to HTTPS β in `NetworkService.swift`
5. **[COM-META-001]** Replace lorem ipsum with real content β in `ViewController.swift`
### Step 3: Review Medium/Low Issues (nice to have)
- **[COM-CRASH-001]** Log errors instead of silently swallowing them
- **[COM-META-003]** Review all TODO/FIXME comments before submissionPaste this into Claude or ChatGPT β it fixes your entire project, file by file, in priority order.
1. npx guidelint ./MyApp --format prompt | pbcopy
2. Open ChatGPT/Claude
3. Paste
4. AI fixes everything
5. Run guidelint again to verify
6. Submit to App Store / Google Play
Guidelint speaks your language. All findings, fix instructions, and UI labels are fully translated.
| Flag | Language | Example |
|---|---|---|
--lang en |
π¬π§ English (default) | guidelint . --lang en |
--lang tr |
πΉπ· TΓΌrkΓ§e | guidelint . --lang tr |
--lang de |
π©πͺ Deutsch | guidelint . --lang de |
--lang nl |
π³π± Nederlands | guidelint . --lang nl |
Example in Turkish:
β [IOS-PRIV-100] PrivacyInfo.xcprivacy bulunamadΔ±
β PrivacyInfo.xcprivacy dosyasΔ± eksik. MayΔ±s 2024'ten itibaren zorunlu.
β ΓΓΆzΓΌm: Xcode > New File > iOS > Resource > App Privacy ile oluΕtur
SKOR: 57/100 β RΔ°SKLΔ° β SorunlarΔ± gΓΆzden geΓ§ir
Example in German:
β [IOS-PRIV-100] PrivacyInfo.xcprivacy nicht gefunden
β PrivacyInfo.xcprivacy-Datei fehlt. Seit Mai 2024 erforderlich.
β LΓΆsung: Erstelle ΓΌber Xcode > New File > iOS > Resource > App Privacy
BEWERTUNG: 57/100 β RISKANT β Probleme vor dem Einreichen prΓΌfen
Want to add a language? See Contributing.
Run with --fix to automatically correct common issues:
guidelint ./MyApp --fix β Auto-fixed 5 issue(s): AND-GRADLE-001, AND-GRADLE-002, AND-GRADLE-003, AND-GRADLE-004, COM-SEC-002
What it fixes:
| Issue | Before | After |
|---|---|---|
| targetSdkVersion | 33 | 35 |
| compileSdk | 33 | 35 |
| debuggable (release) | true | false |
| minifyEnabled (release) | false | true |
| NSAllowsArbitraryLoads | true | false |
| HTTP URLs | http:// |
https:// |
The tool only fixes safe, deterministic changes. Complex issues still require manual review.
Create a .guidelintignore file in your project root. Same syntax as .gitignore:
# Skip test files
test/**
tests/**
__tests__/**
*.spec.ts
*.test.ts
# Skip vendor code
vendor/**
Pods/**
# Skip generated files
generated/**
*.g.dart
guidelint ./MyApp --ignore "test/**" "vendor/**" "*.spec.ts"Guidelint auto-detects your project type and runs the right rules.
| Platform | How it's detected | Files scanned |
|---|---|---|
| iOS β Swift | .xcodeproj, Info.plist, *.swift |
Info.plist, PrivacyInfo.xcprivacy, *.entitlements, Podfile, Package.swift, all .swift files |
| iOS β Objective-C | *.m, *.h files |
Same as above + .m, .h files |
| Android β Kotlin | AndroidManifest.xml, *.kt |
AndroidManifest.xml, build.gradle, network_security_config.xml, gradle.properties, all .kt files |
| Android β Java | AndroidManifest.xml, *.java |
Same as above + .java files |
| React Native | package.json + metro.config.* |
Both iOS and Android files + .js, .jsx, .ts, .tsx |
| Flutter | pubspec.yaml + *.dart |
Both iOS and Android files + .dart, pubspec.yaml |
If you have a React Native or Flutter project, Guidelint scans both the ios/ and android/ directories automatically. You get iOS + Android findings in a single run.
These are automatically excluded from scanning:
node_modules/ build/ dist/ .gradle/
DerivedData/ Pods/ .dart_tool/ .pub-cache/
vendor/ __tests__/ test/ tests/
Guidelint ships with 71 rules across 6 categories:
| Category | # Rules | Weight | What it covers |
|---|---|---|---|
| π Privacy | 23 | 30% | Usage descriptions, privacy manifest, ATT, tracking, dangerous permissions, background modes |
| π‘οΈ Security | 14 | 25% | Hardcoded secrets, HTTP URLs, ATS, cleartext traffic, banned device IDs, signing passwords |
| β‘ Performance | 18 | 20% | Crash risks, SDK versions, PendingIntent, force unwrap, Hermes, AsyncTask, inlineRequires |
| π¨ Design | 5 | 10% | Placeholder content, bundle ID, metadata, KeyboardAvoidingView |
| π° Business | 2 | 10% | In-App Purchase compliance, restore purchases |
| βοΈ Legal | 3 | 5% | Account deletion requirement, privacy policy |
| Platform | Rules | Highlights |
|---|---|---|
| iOS | 27 | Privacy manifest, 11 usage descriptions, ATT, StoreKit, background modes, force unwrap |
| Android | 23 | targetSdk, 7 dangerous permissions, exported, PendingIntent, signing passwords, arm64 |
| React Native | 7 | Hermes, Flipper, __DEV__ leak, console.log, bridge deprecation, inlineRequires |
| Flutter | 6 | debugPrint, kDebugMode, permission plugins, obfuscation, android:exported |
| Cross-platform | 8 | Hardcoded secrets, HTTP URLs, placeholder content, empty catch, sensitive logging |
Every rule:
- Checks a condition β e.g., "Does Info.plist have NSCameraUsageDescription?"
- Cross-references with source code β e.g., "Is AVCaptureSession actually used in any .swift file?"
- Only fires when both conditions are true β no false positives for unused permissions
This means Guidelint won't flag you for missing NSCameraUsageDescription if your app doesn't use the camera. It understands your actual code.
π iOS Rules (23) β click to expand
| Rule | Severity | What it checks |
|---|---|---|
IOS-PLIST-001 |
π΄ Critical | Info.plist file exists in the project |
IOS-PRIV-100 |
π΄ Critical | PrivacyInfo.xcprivacy exists (required since May 2024) |
IOS-PRIV-101 |
π΄ Critical | PrivacyInfo.xcprivacy contains all 4 required keys: NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyCollectedDataTypes, NSPrivacyAccessedAPITypes |
IOS-PRIV-001 |
π΄ Critical | NSCameraUsageDescription in Info.plist when AVCaptureSession / UIImagePickerController is used |
IOS-PRIV-002 |
π΄ Critical | NSMicrophoneUsageDescription when AVAudioSession / AVAudioRecorder is used |
IOS-PRIV-003 |
π΄ Critical | NSLocationWhenInUseUsageDescription when CLLocationManager is used |
IOS-PRIV-004 |
π΄ Critical | NSPhotoLibraryUsageDescription when PHPhotoLibrary / PHAsset is used |
IOS-PRIV-005 |
π΄ Critical | NSContactsUsageDescription when CNContactStore is used |
IOS-PRIV-006 |
π΄ Critical | NSBluetoothAlwaysUsageDescription when CBCentralManager is used |
IOS-PRIV-007 |
π΄ Critical | NSFaceIDUsageDescription when LAContext / biometrics is used |
IOS-PRIV-008 |
π΄ Critical | NSCalendarsUsageDescription when EKEventStore is used |
IOS-PRIV-009 |
π΄ Critical | NSMotionUsageDescription when CMMotionManager is used |
IOS-PRIV-010 |
π΄ Critical | NSSpeechRecognitionUsageDescription when SFSpeechRecognizer is used |
IOS-PRIV-200 |
π΄ Critical | AppTrackingTransparency framework imported when IDFA / advertisingIdentifier is accessed |
IOS-PRIV-201 |
π΄ Critical | NSUserTrackingUsageDescription in Info.plist when ATT framework is used |
IOS-PRIV-400 |
π‘ Medium | Usage description quality β rejects generic text like "We need access" or "Required" |
| Rule | Severity | What it checks |
|---|---|---|
IOS-SEC-001 |
π High | NSAllowsArbitraryLoads is not set to true (App Transport Security) |
| Rule | Severity | What it checks |
|---|---|---|
IOS-IAP-001 |
π High | Restore Purchases is implemented when StoreKit is imported (Guideline 3.1.1) |
IOS-PRIV-300 |
π High | Account deletion available when user authentication exists (required since 2022) |
| Rule | Severity | What it checks |
|---|---|---|
IOS-CRASH-001 |
π‘ Medium | Force unwrap (!) usage count β escalates to High at 10+ |
IOS-CRASH-002 |
π High | No fatalError() in production code |
| Rule | Severity | What it checks |
|---|---|---|
IOS-META-001 |
π High | Bundle ID doesn't contain com.example, com.test, com.demo, org.reactjs.native.example |
π€ Android Rules (20) β click to expand
| Rule | Severity | What it checks |
|---|---|---|
AND-MANIF-001 |
π΄ Critical | AndroidManifest.xml exists in the project |
AND-MANIF-100 |
π΄ Critical | READ_SMS permission β requires Play Console declaration |
AND-MANIF-101 |
π΄ Critical | READ_CALL_LOG permission β requires Play Console declaration |
AND-MANIF-102 |
π΄ Critical | PROCESS_OUTGOING_CALLS β deprecated and banned |
AND-MANIF-103 |
π΄ Critical | BIND_ACCESSIBILITY_SERVICE β very strict review |
AND-MANIF-104 |
π High | ACCESS_BACKGROUND_LOCATION β requires additional approval |
AND-MANIF-105 |
π High | MANAGE_EXTERNAL_STORAGE β strict review |
AND-MANIF-106 |
π High | REQUEST_INSTALL_PACKAGES β security review required |
AND-MANIF-200 |
π High | android:exported attribute set on all components with intent-filters (required Android 12+) |
| Rule | Severity | What it checks |
|---|---|---|
AND-GRADLE-001 |
π΄ Critical | targetSdkVersion >= 35 (Google Play requirement for new apps, 2025) |
AND-GRADLE-002 |
π High | compileSdk >= 34 |
AND-GRADLE-003 |
π΄ Critical | Release build type is not debuggable=true |
AND-GRADLE-004 |
π‘ Medium | Release build has minifyEnabled=true (code protection) |
| Rule | Severity | What it checks |
|---|---|---|
AND-SEC-001 |
π High | usesCleartextTraffic not set to true in manifest |
AND-SEC-100 |
π΄ Critical | No banned device identifiers (IMEI, getDeviceId(), getMacAddress()) |
| Rule | Severity | What it checks |
|---|---|---|
AND-CRASH-001 |
π High | PendingIntent uses FLAG_IMMUTABLE or FLAG_MUTABLE (crashes on Android 12+) |
| Rule | Severity | What it checks |
|---|---|---|
AND-PRIV-001 |
π‘ Medium | Privacy policy URL or reference exists in the project |
AND-PRIV-002 |
π High | Account deletion available when user authentication exists |
π Common Rules (8) β Both Platforms
| Rule | Severity | What it checks |
|---|---|---|
COM-SEC-001 |
π΄ Critical | No hardcoded API keys, secrets, tokens, or passwords in source code (16+ char strings assigned to sensitive variable names) |
COM-SEC-002 |
π High | No http:// URLs (except localhost, 127.0.0.1, 10.*, 192.168.*) |
COM-SEC-003 |
π High | No sensitive data (password, token, secret, apiKey, credit_card, ssn, cvv) in print/Log/console.log statements |
COM-META-001 |
π High | No "lorem ipsum" placeholder text anywhere in source code |
COM-META-002 |
π‘ Medium | No placeholder image filenames (placeholder.jpg, test_image.png, sample.png) |
COM-CRASH-001 |
π‘ Medium | No empty catch blocks β escalates to High at 5+ |
COM-META-003 |
π΅ Low | TODO/FIXME/HACK/XXX comment count β escalates to Medium at 10+ |
COM-META-004 |
π΅ Low | Debug print/Log.d/console.log/debugPrint statement count |
Every project gets a readiness score from 0 to 100, broken down by category.
Each finding deducts points from its category:
| Severity | Points Deducted | Meaning |
|---|---|---|
| π΄ Critical | -25 | Will definitely cause rejection |
| π High | -15 | Very likely to cause rejection |
| π‘ Medium | -8 | May cause rejection or delays |
| π΅ Low | -2 | Best practice, unlikely to cause rejection |
| βΉοΈ Info | 0 | Informational only |
Categories are weighted by their real-world impact on App Store / Google Play review outcomes:
| Category | Weight | Why this weight |
|---|---|---|
| π Privacy | 30% | #1 rejection reason on both stores. Privacy manifest, usage descriptions, ATT β Apple and Google are cracking down hard. |
| π‘οΈ Security | 25% | Hardcoded secrets and cleartext traffic are instant rejections. Apple's ATS enforcement is strict. |
| β‘ Performance | 20% | Crashes during review = immediate rejection. SDK version requirements are enforced automatically. |
| π¨ Design | 10% | Placeholder content and metadata issues. Less common but still cause rejections. |
| π° Business | 10% | IAP compliance (Guideline 3.1.1). Missing Restore Purchases is a classic rejection. |
| βοΈ Legal | 5% | Account deletion, privacy policy. Lower weight because these are usually caught early. |
Overall Score = (Privacy Γ 0.30) + (Security Γ 0.25) + (Performance Γ 0.20)
+ (Design Γ 0.10) + (Business Γ 0.10) + (Legal Γ 0.05)
| Score | Verdict | What it means |
|---|---|---|
| 80β100 | β Ready | Safe to submit. No critical issues found. |
| 50β79 | You might get through, but review the findings first. | |
| 0β49 | β Not Ready | Critical issues detected. Fix them before submitting. |
| Code | Meaning | Use in CI/CD |
|---|---|---|
0 |
No critical findings | Pipeline passes |
1 |
Critical findings exist | Pipeline fails / PR blocked |
Colored output with severity icons (β β ~ Β·), fix instructions, visual score bars, and verdict. Best for local development.
guidelint ./MyAppStructured markdown with a prioritized, step-by-step fix plan designed for AI assistants. Includes file paths, guideline references, and actionable instructions.
# Save to file
guidelint ./MyApp --format prompt > report.md
# Copy to clipboard (macOS)
guidelint ./MyApp --format prompt | pbcopy
# Copy to clipboard (Linux)
guidelint ./MyApp --format prompt | xclip -selection clipboardMachine-readable output with full ScanResult object. Perfect for CI/CD pipelines, custom dashboards, or integration with other tools.
# Pretty print
guidelint ./MyApp --format json
# Filter critical findings with jq
guidelint ./MyApp --format json | jq '.findings[] | select(.severity == "critical")'
# Get just the score
guidelint ./MyApp --format json | jq '.score'JSON schema:
{
"projectPath": "/path/to/project",
"platforms": ["ios", "android"],
"findings": [
{
"ruleId": "IOS-PRIV-100",
"title": "PrivacyInfo.xcprivacy not found",
"severity": "critical",
"category": "privacy",
"platform": "ios",
"message": "PrivacyInfo.xcprivacy file is missing. Required since May 2024.",
"fix": "Create via Xcode > New File > iOS > Resource > App Privacy",
"file": null,
"line": null,
"guideline": "May 2024 requirement",
"docsUrl": "https://developer.apple.com/documentation/bundleresources/privacy-manifest-files"
}
],
"score": {
"overall": 57,
"categories": {
"privacy": 50,
"performance": 73,
"security": 30,
"design": 70,
"business": 85,
"legal": 85
},
"verdict": "risky"
},
"filesScanned": 47,
"rulesChecked": 30,
"timestamp": "2026-03-18T03:15:51.587Z"
}name: Guidelint
on: [push, pull_request]
jobs:
guidelint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
# Fail on critical issues
- name: Run Guidelint
run: npx guidelint . --min-severity high
# Optional: upload report as artifact
- name: Generate Report
if: always()
run: npx guidelint . --format json > guidelint-report.json
- name: Upload Report
if: always()
uses: actions/upload-artifact@v4
with:
name: guidelint-report
path: guidelint-report.jsonguidelint:
image: node:20
script:
- npx guidelint . --min-severity high
artifacts:
when: always
paths:
- guidelint-report.json# .husky/pre-commit
npx guidelint . --min-severity criticalpipelines:
default:
- step:
name: Guidelint
image: node:20
script:
- npx guidelint . --min-severity highUse Guidelint as a library in your own tools:
import { scan, setLocale, translateFindings, formatPrompt } from 'guidelint';
// Set language
setLocale('en');
// Scan
const result = await scan('./MyApp', {
iosOnly: false,
androidOnly: false,
minSeverity: 'low',
});
// Access results
console.log(result.score.overall); // 72
console.log(result.score.verdict); // "risky"
console.log(result.findings.length); // 8
console.log(result.platforms); // ["ios", "android"]
// Translate findings
result.findings = translateFindings(result.findings);
// Format as AI-ready prompt
const report = formatPrompt(result);Based on Apple's 2024 App Store Transparency Report (1.93M rejections analyzed) and Google Play's 2024 enforcement data (1.75M apps blocked):
| Rejection Reason | Real-world Frequency | Guidelint Detects |
|---|---|---|
| Missing/broken privacy policy | π΄ Very High | β Yes |
| App crashes during review | π΄ Very High | β Partial (crash risks) |
| PrivacyInfo.xcprivacy missing (iOS) | π΄ Very High (since 2024) | β Yes |
| Missing permission usage descriptions | π High | β Yes (11 permissions) |
| Account deletion not available | π High | β Yes |
| Target API level outdated (Android) | π High | β Yes |
| Data Safety section mismatch (Android) | π High | |
| Placeholder content (lorem ipsum) | π‘ Medium | β Yes |
| IAP rule violations (no restore) | π‘ Medium | β Yes |
| Metadata mismatch | π‘ Medium | |
| Hardcoded secrets in source | π‘ Medium | β Yes |
| HTTP URLs (cleartext traffic) | π‘ Medium | β Yes |
| Version | Feature | Status |
|---|---|---|
| v0.1 | Core engine, 51 rules, 3 output formats, 4 languages | β Released |
| v0.2 | React Native (7) + Flutter (6) rules, --fix, --ignore, .guidelintignore, 20 new rules |
β Released |
| v0.3 | .ipa / .apk binary analysis |
π Planned |
| v0.4 | Custom rules via .guidelintrc config |
π Planned |
| v0.5 | More --fix handlers, watch mode |
π Planned |
| v1.0 | Xcode & Android Studio plugins | π Backlog |
| v1.1 | AI-powered analysis (usage description quality, permission relevance) | π Backlog |
| v2.0 | Web dashboard + GitHub App | π Backlog |
Contributions are welcome! Whether it's new rules, new languages, platform support, bug fixes, or documentation.
git clone https://github.com/kayrademirkan/guidelint.git
cd guidelint
npm install
npm run buildnode dist/cli.js ./path-to-your-project
node dist/cli.js ./path-to-your-project --lang tr
node dist/cli.js ./path-to-your-project --format promptRules live in src/rules/. Each rule implements the Rule interface:
import type { Rule } from '../types.js';
const myRule: Rule = {
id: 'IOS-CUSTOM-001', // Unique ID: PLATFORM-CATEGORY-NUMBER
title: 'My custom check', // Short title (shown in output)
severity: 'high', // critical | high | medium | low | info
category: 'privacy', // privacy | security | performance | design | business | legal
platform: 'ios', // ios | android | both
guideline: 'Guideline 5.1.1', // Optional: Apple/Google guideline reference
check(ctx) {
// ctx.plistRaw β raw Info.plist XML string
// ctx.privacyManifestRaw β raw PrivacyInfo.xcprivacy XML string
// ctx.manifest β raw AndroidManifest.xml string
// ctx.buildGradle β raw build.gradle string
// ctx.sourceFiles β array of { path, content, language }
// ctx.files β array of { path, name, relativePath, size }
// Return Finding if issue found, null if OK
return null;
},
};Don't forget to add translations in src/i18n/en.ts, tr.ts, de.ts, nl.ts.
- Create
src/i18n/xx.ts(copyen.tsas template) - Translate all strings
- Add import in
src/i18n/index.ts - Add to
Localetype andlocalesmap
MIT β use it however you want.
Stop getting rejected. Run npx guidelint . before you submit.
Made by Kayra Demirkan