Skip to content

kayrademirkan/guidelint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ” Guidelint

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.

npm version npm downloads license stars

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

Table of Contents


Why Guidelint?

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.

What makes it different

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 ⚠️ Easy to forget ❌ Not supported
AI-ready output βœ… --format prompt ❌ ❌
Multi-language βœ… EN/TR/DE/NL ❌ ❌
Cross-platform βœ… iOS+Android+RN+Flutter ❌ Platform-specific ⚠️ Usually one
Auto-fix βœ… --fix flag ❌ ⚠️ Limited
Ignore files βœ… .guidelintignore ❌ βœ…
Zero config βœ… npx guidelint . ❌ ⚠️ Config files
Readiness score βœ… 0-100 with verdict ❌ ❌

Installation

# Run directly β€” no install needed
npx guidelint ./MyApp

# Or install globally
npm install -g guidelint
guidelint ./MyApp

Requirements: Node.js 18 or higher.

That's it. No config files, no setup, no accounts. Point it at your project and go.


Quick Start

Basic scan

guidelint ./MyiOSApp

All CLI options

guidelint [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

Examples

# 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")'

AI-Ready Output

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 | pbcopy

The AI receives:

  1. Full context β€” project info, platform, scores
  2. Every finding β€” rule ID, severity, category, file path, guideline reference
  3. 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 submission

Paste this into Claude or ChatGPT β†’ it fixes your entire project, file by file, in priority order.

The workflow

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

Language Support

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.


Auto-Fix

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.


Ignore Files

.guidelintignore

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

--ignore flag

guidelint ./MyApp --ignore "test/**" "vendor/**" "*.spec.ts"

Supported Platforms

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

Cross-platform detection

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.

Ignored directories

These are automatically excluded from scanning:

node_modules/    build/         dist/          .gradle/
DerivedData/     Pods/          .dart_tool/    .pub-cache/
vendor/          __tests__/     test/          tests/

Rules

Overview

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 breakdown

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

How rules work

Every rule:

  1. Checks a condition β€” e.g., "Does Info.plist have NSCameraUsageDescription?"
  2. Cross-references with source code β€” e.g., "Is AVCaptureSession actually used in any .swift file?"
  3. 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.

All Rules β€” Complete Reference

🍎 iOS Rules (23) β€” click to expand

Privacy & Permissions

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"

Security

Rule Severity What it checks
IOS-SEC-001 🟠 High NSAllowsArbitraryLoads is not set to true (App Transport Security)

Business & Legal

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)

Crash Prevention

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

Metadata

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

Manifest & Permissions

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+)

Build Configuration

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)

Security

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())

Crash Prevention

Rule Severity What it checks
AND-CRASH-001 🟠 High PendingIntent uses FLAG_IMMUTABLE or FLAG_MUTABLE (crashes on Android 12+)

Privacy & Legal

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

Scoring

Every project gets a readiness score from 0 to 100, broken down by category.

Severity deductions

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

Category weights

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.

Score formula

Overall Score = (Privacy Γ— 0.30) + (Security Γ— 0.25) + (Performance Γ— 0.20)
              + (Design Γ— 0.10) + (Business Γ— 0.10) + (Legal Γ— 0.05)

Verdicts

Score Verdict What it means
80–100 βœ… Ready Safe to submit. No critical issues found.
50–79 ⚠️ Risky You might get through, but review the findings first.
0–49 ❌ Not Ready Critical issues detected. Fix them before submitting.

Exit codes

Code Meaning Use in CI/CD
0 No critical findings Pipeline passes
1 Critical findings exist Pipeline fails / PR blocked

Output Formats

Terminal (default)

Colored output with severity icons (βœ— ⚠ ~ Β·), fix instructions, visual score bars, and verdict. Best for local development.

guidelint ./MyApp

Prompt β€” AI-ready Markdown

Structured 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 clipboard

JSON

Machine-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"
}

CI/CD Integration

GitHub Actions

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.json

GitLab CI

guidelint:
  image: node:20
  script:
    - npx guidelint . --min-severity high
  artifacts:
    when: always
    paths:
      - guidelint-report.json

Pre-commit Hook (Husky)

# .husky/pre-commit
npx guidelint . --min-severity critical

Bitbucket Pipelines

pipelines:
  default:
    - step:
        name: Guidelint
        image: node:20
        script:
          - npx guidelint . --min-severity high

Programmatic API

Use 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);

What Guidelint Catches

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 ⚠️ Partial
Placeholder content (lorem ipsum) 🟑 Medium βœ… Yes
IAP rule violations (no restore) 🟑 Medium βœ… Yes
Metadata mismatch 🟑 Medium ⚠️ Partial
Hardcoded secrets in source 🟑 Medium βœ… Yes
HTTP URLs (cleartext traffic) 🟑 Medium βœ… Yes

Roadmap

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

Contributing

Contributions are welcome! Whether it's new rules, new languages, platform support, bug fixes, or documentation.

Setup

git clone https://github.com/kayrademirkan/guidelint.git
cd guidelint
npm install
npm run build

Test locally

node 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 prompt

Adding a new rule

Rules 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.

Adding a new language

  1. Create src/i18n/xx.ts (copy en.ts as template)
  2. Translate all strings
  3. Add import in src/i18n/index.ts
  4. Add to Locale type and locales map

License

MIT β€” use it however you want.


Stop getting rejected. Run npx guidelint . before you submit.

Made by Kayra Demirkan

Releases

No releases published

Packages

 
 
 

Contributors