Open-source project
realm/SwiftLint avatar
realm/SwiftLint

SwiftLint: the config file that sets its working directory, and the source it is not designed to lint

A tool to enforce Swift style and conventions.

19,791 stars2,345 forksSwiftMIT

At a glance

What is it?
SwiftLint enforces Swift style rules that are mostly built on SwiftSyntax, with a subset still reaching into Clang and SourceKit for type information. That split explains its packaging, its plugin behaviour, and its one hard precondition: the code has to compile.
Who is it for?
SwiftLint suits a team with a working Swift toolchain, a repository layout where source files live inside the project directory, and a build that can be linted after it compiles. It does not suit a setup that wants to lint half written code, an Xcode project whose targets point outside the project folder, or a pipeline that needs a pinned version from Homebrew.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • realm/SwiftLint19,791 ★ · +50
Star history
Repository2026-09-212026-11-14
realm/SwiftLint19.7k19.8k

50 Stars in the last 54 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Type information rules drag Clang and SourceKit into every install

SwiftLint's rules are predominantly based on SwiftSyntax, and some of them still hook into Clang and SourceKit to access type information. That second clause shapes installation, packaging, and what you can lint. A purely syntactic rule reads a file and decides. A rule that needs types has to resolve enough of your project to know what a thing is, which means the tool expects a working Swift toolchain in the environment, and which means its own distribution has to carry pieces of that toolchain. The container image shows the bill. The runtime stage installs libcurl4-openssl-dev and libxml2-dev, then copies libsourcekitdInProc.so and a long run of lib_CompilerSwift shared libraries out of the builder stage. The practical consequence is that the rules are not all the same kind of rule, and the subset that resolves types will not behave the same way in an environment that cannot resolve them.

SwiftLint expects compilable source, and autocorrect makes bad input worse

The setup section opens by saying SwiftLint is designed to analyze valid source code that is compilable, and that non compiling code can very easily lead to unexpected and confusing results, especially when running with --fix or --autocorrect. That is an unusual thing to lead with, and it is the thing to plan around. A linter you can point at a half written file is convenient. This one treats that file as outside its contract. The danger it names specifically is autocorrection: a rule that misreads a file it cannot fully parse can apply an edit based on a structure that is not there, and that edit goes to disk. So ordering inside a build is not a style preference. Run it against code that compiles, keep it out of the save path while a file is being written, and read a surprising autocorrect as a report that the input was not what the tool expects rather than as a defect in the rule.

The build tool plugin derives its working directory from a config file

When SwiftLint runs as a build tool plugin, nobody hands it a path. It locates the topmost config file within the package or project directory, and if no config file is found there, the package or project directory itself becomes the working directory. That single decision is how the plugin decides what to lint, so its picture of your project comes from where the config file sits. The failure is explicit rather than silent: the plugin throws an error when it cannot resolve the working directory at all, and the example given is an Xcode project where the target's Swift files are not located within the project directory. The recommendation that follows is to avoid project structures that require the --config option, on the grounds that a layout which only works when you pass a path by hand is a layout the plugin cannot drive on its own.

The plugins live in a second repository, and the note says why

Installing through Swift Package Manager does not point at this repository by default. The documented declaration is a .package line for https://github.com/SimplyDanny/SwiftLintPlugins, either with from: "<version>" to take the latest release or with exact: "<version>" to pin, and the placeholder is meant to be replaced with the version you want. The note attached to it says that consuming the plugins straight from the SwiftLint repository comes with several drawbacks, and that the plugins from the SwiftLint repository are absolutely functional anyway, so https://github.com/realm/SwiftLint can be used in the same declarations. The stated reason is that the plugin code and the releases are kept in sync, so there is no difference in functionality between the two and the split saves overhead.

CocoaPods is the only documented route that lets you pin a version

Homebrew hands you the newest release. Homebrew is a single command:

bash
brew install swiftlint

and the CocoaPods section says outright that installing that way gives you the latest rather than a version of your choosing. Pods are different. Adding this to a Podfile:

ruby
pod 'SwiftLint'

downloads the SwiftLint binaries and their dependencies into Pods/ during your next pod install, and allows pinning to a specific version instead. The binary is then invoked as ${PODS_ROOT}/SwiftLint/swiftlint from a Script Build Phase. The cost is stated in the same paragraph. That directory gains the SwiftLint binaries, the binaries of its dependencies, and the Swift binary library distribution, which is the reason checking Pods/ into Git is discouraged. Version control of your linter therefore arrives attached to a directory you are told not to commit.

Bazel, Mint, the pkg, and a source build each price differently

Bazel is documented twice, once for MODULE.bazel:

bzl
bazel_dep(name = "swiftlint", version = "0.52.4", repo_name = "SwiftLint")

and once through WORKSPACE with an http_archive block, ending in the command that runs it in the current directory:

console
bazel run -c opt @SwiftLint//:swiftlint

The MODULE.bazel line in the documentation pins version 0.52.4 while the newest release is 0.65.1, so a copied snippet installs something considerably older until you edit it. Mint is one line, `mint install realm/SwiftLint`. The pre built package is a download of SwiftLint.pkg from the latest GitHub release that you then run. Building from source is the heaviest of the set: it requires Bazel and a recent Swift toolchain, all discoverable in your PATH, and then a `make install`, where the Makefile sets BINARIES_FOLDER to /usr/local/bin and BUILD_TOOL to xcodebuild unless you override them.

The container image copies compiler libraries but not the compiler

The Dockerfile fixes its own inputs through two build arguments, SWIFT_VERSION=6.3.2 and UBUNTU_VERSION=noble. The builder stage is FROM swift:${SWIFT_VERSION}-${UBUNTU_VERSION} AS builder, copies Plugins, Source, Tests, and Package.* into /workspace, runs swift build -c release --product swiftlint, and then moves the produced binary up into the workspace root. The runtime stage is a plain ubuntu:${UBUNTU_VERSION} image rather than a Swift image, carrying three org.opencontainers labels, an apt-get update, and libcurl4-openssl-dev with libxml2-dev. What follows is a run of COPY lines pulling libsourcekitdInProc.so and one lib_CompilerSwift library after another from the builder into /usr/lib. So the image that runs the linter contains no Swift compiler. It contains selected pieces of one, tied to the toolchain version named in the first line, and changing SWIFT_VERSION changes both the build and the set of libraries that have to be copied.

The repository lints itself, and ships the config that does it

Among the top level entries are .swiftlint.yml, the configuration file for the tool, next to .pre-commit-hooks.yaml, a Dangerfile, .markdownlint.yml, a .buildkite directory for continuous integration, and a Gemfile with a lock file and a separate .ruby-version. That combination is the most direct reference for configuring the thing, because the project maintaining SwiftLint is linted by it and the file doing the linting sits in the repository rather than in a wiki. The release naming is a small window on the project's rhythm. The three most recent releases are 0.65.1 and 0.65.0, both titled Fresh Folded Fixtures, and 0.64.1 titled All Windows Opened, dated 2026-08-21, 2026-06-27, and 2026-06-23. The last push is dated 2026-10-16, while the presentation offered as the high level overview was recorded in January 2017.

Editorial conclusion

SwiftLint suits a team with a working Swift toolchain, a repository layout where source files live inside the project directory, and a build that can be linted after it compiles. It does not suit a setup that wants to lint half written code, an Xcode project whose targets point outside the project folder, or a pipeline that needs a pinned version from Homebrew. Before adopting it, check three things: whether your rules need type information and therefore a real toolchain, whether your directory layout lets the build tool plugin find a working directory without --config, and how you will pin the version, since Homebrew gives only the latest while CocoaPods and the Swift Package Manager exact: declaration pin a specific one.

Frequently asked questions

How do I disable Swift Lint?

Rule behaviour is driven by the config file, and the repository ships its own as .swiftlint.yml at the top level. When SwiftLint runs as a build tool plugin it finds the topmost config file inside the package or project directory and uses that location as its working directory, so the config file also decides which files get linted.

What are the differences between SwiftFormat and SwiftLint?

The README states that SwiftLint enforces Swift style and conventions loosely based on the now archived GitHub Swift Style Guide, that its rules are predominantly based on SwiftSyntax with some still using Clang and SourceKit for type information, and that it can rewrite files with --fix or --autocorrect.

How do I install SwiftLint in an Xcode project?

Add https://github.com/SimplyDanny/SwiftLintPlugins as an Xcode Package Dependency, or use SwiftLint as a build tool plugin, which works for both Swift Package projects and Xcode projects. The plugin throws an error when it cannot resolve its working directory, which is what happens when a target's Swift files are not located within the project directory.

How do I install SwiftLint from a Mac terminal?

Homebrew takes one command, brew install swiftlint, and Mint takes mint install realm/SwiftLint. A pre built SwiftLint.pkg can be downloaded from the latest GitHub release, and building from source needs Bazel and a recent Swift toolchain on your PATH followed by make install.

What does SwiftLint do?

It enforces Swift style and conventions that are loosely based on the now archived GitHub Swift Style Guide, and the rules are well described in popular guides such as Kodeco's Swift Style Guide. Its rules are predominantly based on SwiftSyntax, with some still hooking into Clang and SourceKit to access type information.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. realm/SwiftLint on GitHub
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/realm-swiftlint.svg)](https://hysenlabs.com/projects/realm-swiftlint)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/realm-swiftlint.svg)](https://hysenlabs.com/projects/realm-swiftlint)

Was this useful?