RepoPilotOpen in app →

realm/SwiftLint

A tool to enforce Swift style and conventions.

Healthy

Healthy across the board

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 2d ago
  • 12 active contributors
  • MIT licensed
Show 3 more →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 60% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/realm/swiftlint)](https://repopilot.app/r/realm/swiftlint)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/realm/swiftlint on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: realm/SwiftLint

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/realm/SwiftLint shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 2d ago
  • 12 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 60% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live realm/SwiftLint repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/realm/SwiftLint.

What it runs against: a local clone of realm/SwiftLint — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in realm/SwiftLint | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 32 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>realm/SwiftLint</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of realm/SwiftLint. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/realm/SwiftLint.git
#   cd SwiftLint
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of realm/SwiftLint and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "realm/SwiftLint(\\.git)?\\b" \\
  && ok "origin remote is realm/SwiftLint" \\
  || miss "origin remote is not realm/SwiftLint (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift" \\
  && ok "Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift" \\
  || miss "missing critical file: Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift"
test -f "Package.swift" \\
  && ok "Package.swift" \\
  || miss "missing critical file: Package.swift"
test -f "Source/SwiftLintBuiltInRules/Exports.swift" \\
  && ok "Source/SwiftLintBuiltInRules/Exports.swift" \\
  || miss "missing critical file: Source/SwiftLintBuiltInRules/Exports.swift"
test -f "Plugins/SwiftLintBuildToolPlugin/SwiftLintBuildToolPlugin.swift" \\
  && ok "Plugins/SwiftLintBuildToolPlugin/SwiftLintBuildToolPlugin.swift" \\
  || miss "missing critical file: Plugins/SwiftLintBuildToolPlugin/SwiftLintBuildToolPlugin.swift"
test -f "Plugins/SwiftLintCommandPlugin/SwiftLintCommandPlugin.swift" \\
  && ok "Plugins/SwiftLintCommandPlugin/SwiftLintCommandPlugin.swift" \\
  || miss "missing critical file: Plugins/SwiftLintCommandPlugin/SwiftLintCommandPlugin.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 32 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/realm/SwiftLint"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

SwiftLint is a Swift static analysis and style enforcement tool that automatically detects and reports violations of Swift style conventions and best practices. It parses Swift code using SwiftSyntax (the official Swift parser framework) and optionally hooks into Clang/SourceKit for type information, providing IDE integration (Xcode), CLI linting, and build/command plugins for automated code quality enforcement. Monorepo structure: core linting engine in SwiftLint (main package), command-line interface in Sources/swiftlint/, individual rule implementations organized under Sources/SwiftLintFramework/Rules/, configuration parsing in Sources/SwiftLintFramework/Config/, test suite in Tests/. Build system: both Bazel (BUILD files, MODULE.bazel) and Swift Package Manager (Package.swift, Package.resolved) supported. Plugins defined separately in SwiftLintPlugins repo (command and build tool variants).

👥Who it's for

Swift developers and teams who want to enforce consistent code style across codebases—specifically iOS/macOS developers using Xcode, CI/CD pipeline operators integrating linting into build processes, and maintainers of Swift packages who need automated style checking without manual code review.

🌱Maturity & risk

Highly mature and production-ready. The project has 18K+ GitHub stars, uses professional CI/CD (Buildkite, GitHub Actions), maintains comprehensive documentation (.jazzy.yaml for docs generation), has a structured changelog, and follows semantic versioning. Evidence of active development: recent GitHub workflows for releases, post-release automation, and Bazel/SPM dual-build system. This is a widely-adopted tool in the Swift ecosystem.

Standard open source risks apply.

Active areas of work

Active development with recent infrastructure work: GitHub Actions workflows for Docker builds (.github/workflows/docker.yml), Bazel integration (MODULE.bazel, .bazelrc), plugin synchronization pipeline (.github/plugins-sync.yml), and Buildkite CI setup (.buildkite/pipeline.yml). The .bcr/ directory indicates Bazel Central Registry publication. Recent work involves Swift syntax migration and rule enhancements based on community feedback.

🚀Get running

git clone https://github.com/realm/SwiftLint.git
cd SwiftLint
# Using Swift Package Manager:
swift build
# Or using Bazel:
bazel build //:swiftlint
# Run with:
./.build/debug/swiftlint lint path/to/swift/file.swift

Daily commands:

# Development build:
swift build
# Run tests:
swift test
# Or with Make (Makefile present):
make build
make test
# Lint a file:
./.build/debug/swiftlint lint path/to/file.swift
# Generate rules documentation:
./.build/debug/swiftlint rules

🗺️Map of the codebase

  • Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift — Core registry of all built-in rules—essential to understand how SwiftLint discovers and registers linting rules.
  • Package.swift — Defines the SwiftLint package structure, dependencies (SwiftSyntax, Clang), and build targets—required reading for build setup.
  • Source/SwiftLintBuiltInRules/Exports.swift — Public API entry point for SwiftLintBuiltInRules module—needed to understand how rules are exported and accessed.
  • Plugins/SwiftLintBuildToolPlugin/SwiftLintBuildToolPlugin.swift — Build tool plugin integration point—shows how SwiftLint integrates with Xcode's build pipeline.
  • Plugins/SwiftLintCommandPlugin/SwiftLintCommandPlugin.swift — Command-line plugin entry point—illustrates how SwiftLint is exposed as a Xcode command plugin.
  • README.md — Project overview and rationale—explains why SwiftLint uses SwiftSyntax and Clang, and the style guides it enforces.
  • .swiftlint.yml — Default SwiftLint configuration—demonstrates the project's own linting rules and best practices.

🛠️How to make changes

Add a New Linting Rule

  1. Create a new rule file in Source/SwiftLintBuiltInRules/Rules/Idiomatic/ (or appropriate category folder) following the pattern of existing rules like ForceCastRule.swift (Source/SwiftLintBuiltInRules/Rules/Idiomatic/YourNewRule.swift)
  2. Register your rule in the BuiltInRules.swift registry by adding it to the rules array (Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift)
  3. Implement the rule struct with required properties (description, kind, name) and analysis method using SwiftSyntax visitors (Source/SwiftLintBuiltInRules/Rules/Idiomatic/YourNewRule.swift)
  4. Export the rule through Exports.swift to make it publicly available (Source/SwiftLintBuiltInRules/Exports.swift)
  5. Update Rules.md with documentation of your new rule's behavior and examples (Rules.md)

Extend Plugin Functionality

  1. For build-time integration, modify SwiftLintBuildToolPlugin.swift to hook into the build phase and configure rule execution (Plugins/SwiftLintBuildToolPlugin/SwiftLintBuildToolPlugin.swift)
  2. For IDE command access, update SwiftLintCommandPlugin.swift to expose new command options and parameters (Plugins/SwiftLintCommandPlugin/SwiftLintCommandPlugin.swift)
  3. Use CommandContext.swift to wrap and pass execution parameters through the plugin (Plugins/SwiftLintCommandPlugin/CommandContext.swift)
  4. Use Path+Helpers.swift utilities for cross-platform path resolution in plugins (Plugins/SwiftLintBuildToolPlugin/Path+Helpers.swift)

Update Project Dependencies & Build Configuration

  1. Modify Package.swift to add/update dependencies (e.g., newer SwiftSyntax or Clang versions) (Package.swift)
  2. Update .swiftlint.yml to reflect new rules or enforcement levels for the project itself (.swiftlint.yml)
  3. For Bazel builds, update MODULE.bazel with new dependencies and build targets (MODULE.bazel)
  4. Update Makefile with new build targets or development workflows (Makefile)

🔧Why these technologies

  • SwiftSyntax — Official Swift language parsing library; provides reliable, compiler-maintained AST for syntax analysis without external dependencies.
  • Clang/SourceKit — Type information and semantic analysis not available from syntax alone; used selectively for rules requiring type context (e.g., type inference).
  • Xcode Build Tool Plugin & Command Plugin — Native integration with Xcode IDE; allows linting to run during build and via IDE commands without external tooling.
  • Swift Package Manager (SPM) — Official Swift dependency manager; simplifies distribution and integration into Swift projects.
  • Bazel — Reproducible build system for complex C/Swift interop (Clang workarounds) and cross-platform support (Windows, Linux).

⚖️Trade-offs already made

  • Hybrid SwiftSyntax + Clang approach instead of pure syntax

    • Why: SwiftSyntax alone cannot resolve types; some rules (e.g., implicit unwrapping, type interfaces) need semantic info.
    • Consequence: Added complexity and Clang dependency; slower analysis on large codebases; but enables comprehensive style checks.
  • Rules split into separate category folders (Idiomatic, etc.) instead of flat list

    • Why: Organizes ~100+ rules by semantic purpose; easier discovery and maintenance.
    • Consequence: Slightly more complex file structure; easier onboarding for contributors.
  • Plugin-based Xcode integration rather than standalone CLI-only tool

    • Why: Immediate IDE feedback during development; seamless Xcode workflow.
    • Consequence: Must maintain Xcode plugin APIs; tighter coupling to Xcode versions.
  • C workaround (DyldWarningWorkaround) for Clang framework linking issues

    • Why: Clang framework has runtime linking quirks on macOS; workaround prevents spurious warnings.
    • Consequence: Additional C code to maintain; platform-specific fragility.

🚫Non-goals (don't propose these)

  • Automatic code fixing (formatters like SwiftFormat handle that)
  • Performance benchmarking or optimization beyond typical project scales
  • Runtime/dynamic code analysis (static analysis only)
  • Cross-language linting (Swift projects only)
  • Authentication or cloud-based rule distribution

🪤Traps & gotchas

Swift version coupling: SwiftLint rules depend heavily on SwiftSyntax APIs which change with Swift compiler releases—building with an unsupported Swift version will fail. Clang/SourceKit deprecation: Some older rules still require SourceKit setup; migration to pure SwiftSyntax is ongoing and incomplete. Bazel vs SPM: Two parallel build systems exist; Bazel is primary for CI but SPM is simpler locally—mixing them can cause build cache issues. Rule loading: Rules are discovered via reflection at runtime; custom rule plugins require exact module structure. Configuration inheritance: .swiftlint.yml nested in subdirectories inherit parent configs with non-obvious precedence rules; test this carefully. No vendored SwiftSyntax: Depends on system Swift toolchain version matching project's expected Swift version.

🏗️Architecture

💡Concepts to learn

  • Abstract Syntax Tree (AST) Visitor Pattern — All SwiftLint rules inherit from Rule and implement visit methods to traverse SwiftSyntax AST nodes—understanding the Visitor pattern is fundamental to writing or modifying rules
  • SwiftSyntax API & SyntaxVisitor — Core to rule implementation; rules walk the parsed Swift source tree using SwiftSyntax's visitor methods (visitFunctionDecl, visitIfExpr, etc.) to detect violations
  • Static Analysis & Linting — SwiftLint performs compile-time analysis without executing code to enforce style conventions and catch common mistakes—the foundational concept of the entire tool
  • Configuration-Driven Rule Loading — Rules are discovered and configured at runtime via .swiftlint.yml; understanding how Configuration.swift parses and applies per-rule settings is essential for customization
  • Swift Package Manager Command Plugins — SwiftLint integrates as SPM command plugin for seamless project integration; understanding plugin manifests and invocation is required for plugin-based usage
  • SourceKit and Clang Integration — Some legacy rules rely on SourceKit (Apple's IDE framework) and Clang for type information beyond what SwiftSyntax provides; understanding their deprecation matters for rule modernization
  • Bazel Build System — Repository uses dual build systems (Bazel for CI, SPM for local dev); understanding Bazel configuration (BUILD files, MODULE.bazel) is needed for CI/hermetic build debugging
  • swiftlang/swift-syntax — Official Swift syntax parser framework that SwiftLint rules depend on for AST analysis—understanding this is essential
  • apple/swift-format — Apple's official Swift code formatter; SwiftLint is linting-focused while swift-format handles auto-fixing, often used together
  • realm/SwiftLintPlugins — Separate repo containing official SwiftLint command and build tool plugins for SPM integration—recommended way to use SwiftLint in projects
  • SimplyDanny/SwiftLintPlugins — Community-maintained mirror of SwiftLint plugins with better maintenance for package consumers—recommended distribution point for plugins
  • nicklockwood/SwiftFormat — Community alternative formatter/linter tool; represents different philosophy (opinionated formatting vs configurable linting)

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for SwiftLintBuildToolPlugin

The Plugins/SwiftLintBuildToolPlugin directory contains plugin logic (SwiftLintBuildToolPlugin.swift, Path+Helpers.swift, SwiftLintBuildToolPluginError.swift) but there are no visible test files in the repo structure for these critical build integration components. This plugin is a key entry point for Xcode integration, and adding unit tests would improve reliability and catch regressions in build tool behavior.

  • [ ] Create Tests/SwiftLintBuildToolPluginTests/ directory structure
  • [ ] Add unit tests for Path+Helpers.swift helper functions with edge cases
  • [ ] Add unit tests for SwiftLintBuildToolPluginError.swift error handling
  • [ ] Add integration tests for SwiftLintBuildToolPlugin.swift plugin execution
  • [ ] Ensure tests cover Xcode build system interactions

Add Windows platform-specific CI workflow

The repo has Platforms/Windows/ directory with WiX installer project files (.wixproj, .wxs), indicating Windows support is a maintained feature. However, the .github/workflows directory shows builds for macOS/Linux but no dedicated Windows CI workflow. This gap means Windows builds aren't being regularly validated, risking regressions for Windows users.

  • [ ] Create .github/workflows/windows-build.yml workflow file
  • [ ] Configure Windows runner (windows-latest) with Swift toolchain setup
  • [ ] Add build steps mirroring .buildkite/pipeline.yml for Windows context
  • [ ] Add WiX installer validation steps using Platforms/Windows/SwiftLint.wixproj
  • [ ] Integrate with existing test.yml patterns for consistency

Document and test DyldWarningWorkaround C code integration

Source/DyldWarningWorkaround/DyldWarningWorkaround.c exists but there is no visible documentation explaining why this C workaround is needed, when it's invoked, or how it integrates with the Swift codebase. This is a critical runtime dependency that should have clear documentation and integration tests to prevent accidental breakage.

  • [ ] Add comments to DyldWarningWorkaround.c explaining the dyld issue and Apple version context
  • [ ] Document in CONTRIBUTING.md when and why this workaround is needed
  • [ ] Create integration tests or validation that DyldWarningWorkaround is properly linked in built binaries
  • [ ] Add entry to Rules.md or technical docs referencing this platform-specific workaround
  • [ ] Verify the workaround is included in all distribution builds (Bazel, SPM, Windows installer)

🌿Good first issues

  • Add missing test coverage for underutilized rules in Tests/SwiftLintFrameworkTests/RulesTests/—pick a rule with <5 test cases and add edge case tests for complex syntax scenarios
  • Improve rule documentation in .swiftlint.yml comments section—many rules lack examples of violations and fixes; add concrete before/after code snippets for 3-5 rules
  • Create missing integration tests in .github/workflows/—test.yml runs unit tests but lacks end-to-end tests of the CLI against real Swift projects; add a workflow job that lints a sample Swift package

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 3343034 — Support access level modifiers on imports in unused_imports (#6631) (SimplyDanny)
  • 767d780 — Taint variables in tuples (#6629) (SimplyDanny)
  • 98b687f — Bump github.com/krzyzanowskim/cryptoswift from 1.9.0 to 1.10.0 (#6618) (dependabot[bot])
  • 16c87ea — Bump swift_argument_parser from 1.7.0 to 1.7.1 (#6624) (dependabot[bot])
  • 9af2854 — Bump rules_cc from 0.2.17 to 0.2.18 (#6616) (dependabot[bot])
  • ce00cb1 — Bump DavidAnson/markdownlint-cli2-action from 23.0.0 to 23.1.0 (#6625) (dependabot[bot])
  • 48ff40d — Bump ruby/setup-ruby from 1.302.0 to 1.306.0 (#6626) (dependabot[bot])
  • d19bfac — Bump apple_support from 2.5.3 to 2.5.4 (#6623) (dependabot[bot])
  • 33e85aa — Use SwiftSyntax 6.4 pre-release 2026-04-21 (#6628) (Copilot)
  • a6198b7 — Add support for Swift 6.3.1 (#6627) (Copilot)

🔒Security observations

The SwiftLint codebase demonstrates a generally secure structure with no critical vulnerabilities identified in the provided context. The project maintains proper code organization, uses standard build tools (Bazel, Swift Package Manager), and implements a multi-stage Docker build. Primary concerns are minor Docker configuration issues (incomplete COPY command, suboptimal layer optimization) and lack of image integrity verification. No hardcoded secrets, SQL injection patterns, or dependency injection vulnerabilities are evident from the file structure. The build system and dependency management appear sound with no suspicious external dependencies visible in the partial package information provided. Recommend addressing the truncated Dockerfile command and implementing standard container security best practices.

  • Medium · Incomplete Dockerfile COPY Command — Dockerfile (lines 17-18). The Dockerfile has a truncated COPY command in the runtime image section. The line 'COPY --from=builder /usr/lib/swift/host/compiler/lib_CompilerSwiftCompilerPlug' appears incomplete, which could indicate a build issue or potential misconfiguration that might affect runtime dependencies. Fix: Complete the truncated COPY command and ensure all necessary runtime dependencies are properly copied from the builder image.
  • Low · apt-get Cache Not Cleaned in Single Layer — Dockerfile (lines 13-15). While the Dockerfile does clean apt cache with 'rm -r /var/lib/apt/lists/', it's done after installing packages. For optimal image size and to prevent potential package re-installation issues, consider combining RUN commands to minimize layers. Fix: Combine the apt-get update, install, and cleanup into a single RUN command: 'RUN apt-get update && apt-get install -y libcurl4-openssl-dev libxml2-dev && rm -r /var/lib/apt/lists/'
  • Low · Swift Version Pinning Without Verification — Dockerfile (line 3). The Dockerfile pins Swift to version 6.1.2, but there is no integrity verification (checksums, signatures) of the downloaded image. This could potentially allow image tampering if the registry is compromised. Fix: Consider implementing image signing verification or using a registry with strong security controls. Document the Swift version selection process.
  • Low · Missing Health Check and Security Headers — Dockerfile (lines 1-18). The Dockerfile does not include HEALTHCHECK directives or any security-focused metadata beyond basic labels. The image lacks documentation about running it securely. Fix: Add HEALTHCHECK instructions and security-related labels documenting safe usage practices and any required security configurations.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · realm/SwiftLint — RepoPilot