guidelint
v0.2.0
Published
App Store & Google Play pre-submission linter. Catch rejection reasons before review.
Maintainers
Readme
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/100Table of Contents
- Why Guidelint?
- Installation
- Quick Start
- AI-Ready Output — the killer feature
- Language Support — EN, TR, DE, NL
- Supported Platforms
- All 51 Rules — complete reference
- Scoring System
- Output Formats
- CI/CD Integration
- Programmatic API
- What Guidelint Catches — real rejection data
- Roadmap
- Contributing
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 | ✅ 51 rules | ❌ Human error | ❌ Code-only |
| Google Play guidelines | ✅ 20 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 |
| 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 ./MyAppRequirements: 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 ./MyiOSAppAll 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")
-V, --version Output version number
-h, --help Display helpExamples
# 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
# 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 | 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.
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 PlayLanguage 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çirExample 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üfenWant to add a language? See Contributing.
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 51 rules across 6 categories:
| Category | # Rules | Weight | What it covers | |---|---|---|---| | 🔒 Privacy | 21 | 30% | Usage descriptions, privacy manifest, ATT, tracking, dangerous permissions | | 🛡️ Security | 10 | 25% | Hardcoded secrets, HTTP URLs, ATS, cleartext traffic, banned device IDs | | ⚡ Performance | 10 | 20% | Crash risks, SDK versions, PendingIntent flags, force unwrap | | 🎨 Design | 4 | 10% | Placeholder content, bundle ID validation, metadata | | 💰 Business | 2 | 10% | In-App Purchase compliance, restore purchases | | ⚖️ Legal | 3 | 5% | Account deletion requirement, privacy policy |
How rules work
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.
All Rules — Complete Reference
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 |
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 |
| 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 ./MyAppPrompt — 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 clipboardJSON
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.jsonGitLab CI
guidelint:
image: node:20
script:
- npx guidelint . --min-severity high
artifacts:
when: always
paths:
- guidelint-report.jsonPre-commit Hook (Husky)
# .husky/pre-commit
npx guidelint . --min-severity criticalBitbucket Pipelines
pipelines:
default:
- step:
name: Guidelint
image: node:20
script:
- npx guidelint . --min-severity highProgrammatic 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 formats, 4 languages | ✅ Released |
| v0.2 | React Native & Flutter specific rules | 🔜 Planned |
| v0.3 | --fix flag for auto-fixable issues | 🔜 Planned |
| v0.4 | .ipa / .apk binary analysis | 🔜 Planned |
| v0.5 | Custom rules via .guidelintrc config | 🔜 Planned |
| v0.6 | --ignore flag and .guidelintignore file | 🔜 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 buildTest 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 promptAdding 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
- Create
src/i18n/xx.ts(copyen.tsas template) - Translate all strings
- Add import in
src/i18n/index.ts - Add to
Localetype andlocalesmap
License
MIT — use it however you want.
