swift-syntax: a source-accurate SwiftSyntax tree for macros, linters and formatters
A set of Swift libraries for parsing, inspecting, generating, and transforming Swift source code.
At a glance
- What is it?
- swift-syntax is the Swift package that parses Swift source into a lossless tree, and it is the backbone of Swift's macro system. Here is what it does, how to add it, and where it stops being the right tool.
- Who is it for?
- Adopt swift-syntax if you are writing a Swift macro, a formatter, or a tool that needs to see every byte of a Swift file including trivia. Do not adopt it if you only need a syntax highlighter in an editor, or if you cannot accept a package whose major version tracks the Swift toolchain you build against.
- Can I use it commercially?
- Yes. Apache-2.0 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 received new commits within the last day.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What swift-syntax solves, and who actually needs it
Most Swift tooling starts with the same question: how do I read Swift code as data without losing the parts a compiler would throw away? swift-syntax answers that with the SwiftSyntax tree, described in the README as "a source-accurate tree representation of Swift source code". Source-accurate is the load-bearing phrase. Whitespace, comments and other trivia survive in the tree, so a tool can rewrite one node and reproduce the rest of the file unchanged.
The README states the tree "forms the backbone of Swift's macro system": macro expansion nodes are SwiftSyntax nodes, and a macro produces a SwiftSyntax tree that gets inserted into the source file. That makes the package unavoidable for anyone writing a Swift macro that manipulates syntax rather than just emitting a fixed string.
It is also aimed at a second, quieter audience. Formatters, linters, migration scripts and code generators all need the same thing: parse a file, walk it, change a node, print it back. The repository ships an Examples directory with usage samples, and the README points to swift-ast-explorer.com as an interactive way to inspect the tree for a given source file. If you have ever wanted to know exactly which node holds the attribute on a function, that explorer is the fastest route.
How the SwiftSyntax tree is structured and where macros plug in
The package is a set of libraries rather than one monolith. The repository root carries a Package.swift, a BUILD.bazel, a CMakeLists.txt and a CodeGeneration directory, which tells you the sources are partly generated from a schema rather than hand-written. The SwiftParserCLI and SwiftSyntaxDevUtils entries at the top level are the tooling side of that arrangement.
The data flow for a macro is the part worth understanding before you adopt anything. A macro is invoked during compilation; the compiler hands it syntax nodes; the macro returns a new SwiftSyntax tree; that tree is spliced into the file being compiled. The macro never touches raw text. This is why a macro cannot quietly emit malformed Swift: what it returns has to be representable as nodes.
The same tree shape is what makes non-macro tools viable. Because trivia is retained, a tool that changes an argument label can print the file back with the original indentation and comments intact. The trade-off is memory and allocation cost: a full-fidelity tree is heavier than a plain abstract syntax tree that discards trivia, and the README does not publish performance figures for either parsing or printing, so you should measure against your own inputs rather than assume a number.
Installing swift-syntax with SwiftPM or Xcode
The README gives the SwiftPM route directly. Add the package to your Package.swift dependencies, substituting the tag that matches your toolchain, since the README writes the version as a placeholder rather than a fixed number.
dependencies: [
.package(url: "https://github.com/swiftlang/swift-syntax.git", from: "<#latest swift-syntax tag#>"),
]Then add the specific library you need as a target dependency. The package is split into libraries, so pulling in the whole thing when you only need the parser is a choice you are making, not a requirement. After resolving, build and you should see the package appear in your resolved dependencies.
For an Xcode project the README describes a GUI path instead of a file edit: open the Package Dependencies tab of the project, click the plus button, and search for https://github.com/swiftlang/swift-syntax.git. Both routes resolve the same repository.
A first real use is inspecting syntax. The README points to https://swift-ast-explorer.com as an interactive way to explore the tree of a source file, and to the Examples directory in the repository for a set of example usages. Read Examples/README.md before writing your own walker; the node names in a generated tree are not always what you would guess from the Swift grammar.
The Bazel build is experimental, and the version story is the real constraint
Two limitations matter more than any feature list.
The first is versioning. The README states that releases are aligned with language and tooling releases, and gives the example that major version 509 of swift-syntax corresponds to Swift 5.9. So the version you depend on is not a free choice; it is dictated by the Swift release you build against. Upgrading your toolchain can force a swift-syntax major bump, and a major bump is where source-breaking changes live. The Changelog.md and the Release Notes directory at the repository root are where those changes are recorded, and they are the files to read before an upgrade, not after.
The second is the Bazel path. The README calls the Bazel configuration experimental and notes it is maintained by Keith Smiley. Bzlmod support arrived with release 509.0.0 and above, and the README recommends MODULE.bazel over WORKSPACE. It also documents a WORKSPACE fallback using http_archive with an explicit sha256 and strip_prefix, which means you pin a tarball and a checksum yourself. The README asks that Bazel-related issues be tagged with the label "Bazel", which is a reasonable signal that this path gets less traffic than SwiftPM.
There is also a build-time trade-off documented in the README: each library has an associated Library_opt target, such as SwiftSyntax_opt, that "forces SwiftSyntax to always build with optimizations enabled". The README says this may help local runtime performance at the cost of debuggability and initial build time. That is a deliberate, documented trade, and it tells you the default build is the debuggable one.
When swift-syntax is the wrong dependency
If your goal is syntax highlighting in an editor, swift-syntax is heavier than you need. The RELATED SEARCHES around highlighting point at a job that is usually solved by a grammar or a tokenizer, not by constructing a full-fidelity tree for every keystroke. Parsing a whole file to color it is a mismatch between the tool and the task.
The same applies to tools that only need to detect patterns in text. A regex over source is fragile, but it is also cheap and dependency-free; if your transformation never needs to print the file back, the tree buys you less than it costs.
A third case is toolchain coupling. If you ship a binary that must build against several Swift versions at once, the release alignment rule turns every toolchain upgrade into a dependency upgrade with its own changelog. That is not a reason to avoid the package, but it is a reason to budget for it.
Finally, note what the README does not document. There is no rollback procedure, no supported-version matrix beyond the alignment example, and no published benchmark for parse or print throughput. If those matter for your decision, they are gaps to close by measurement, not by reading.
How swift-syntax differs from a plain Swift parser or a compiler frontend
The obvious alternative is to use the Swift compiler's own parsing facilities directly rather than a separate package. The difference in approach is fidelity and stability. A compiler frontend is built to type-check and emit code; its internal syntax representation is not a public API and changes with the compiler. swift-syntax exposes the tree as a versioned package with a documented release alignment, so you depend on a tag instead of on compiler internals.
The second alternative is a hand-written parser or a generated one for the subset of Swift you care about. That is genuinely cheaper for a narrow job, and it avoids the version coupling entirely. It also means you own every edge case in the Swift grammar, including the trivia rules that swift-syntax already handles.
The third is the macro system itself. If your need is only to generate code at compile time from a fixed template, the macro machinery may be enough and you may never touch the tree API directly. The README's framing is that macro expansion nodes are SwiftSyntax nodes, so the tree is underneath either way, but the surface you write against can be much smaller.
Licence and the cost of keeping up
swift-syntax is Apache-2.0, and the README points to LICENSE.txt for the terms. Apache-2.0 is a permissive licence with an explicit patent grant and a notice requirement; it is not copyleft. This is a description of the licence identifier, not legal advice, and if you redistribute the package or a derivative you should read LICENSE.txt and your own obligations rather than take this paragraph as sufficient.
Upgrade cost is dominated by the alignment rule. Because major versions track Swift releases, an upgrade is usually a deliberate step tied to a toolchain change, and the Changelog.md plus the Release Notes directory are the primary sources for what moved. The repository also carries a .swift-format configuration, an .editorconfig and a .license_header_template, which suggests contributions are expected to follow formatting and header conventions; that affects contributors more than consumers.
On activity: the last push to the default branch was on 2026-09-23, and the most recent stable release listed is 604.0.0, published on 2026-09-15. Prerelease tags such as 605.0.0-prerelease-2026-09-15 exist alongside it. If you depend on a prerelease tag, you are tracking a moving target by definition.
Editorial conclusion
Adopt swift-syntax if you are writing a Swift macro, a formatter, or a tool that needs to see every byte of a Swift file including trivia. Do not adopt it if you only need a syntax highlighter in an editor, or if you cannot accept a package whose major version tracks the Swift toolchain you build against. Before committing, check the release tag that matches your Swift version, run the Examples package to see the tree shape, and confirm you are not depending on a prerelease tag such as 605.0.0-prerelease-2026-09-15 in a shipping target.
Frequently asked questions
What is swift-syntax?
It is a set of Swift libraries that work on a source-accurate tree representation of Swift source code, called the SwiftSyntax tree. The README states that this tree forms the backbone of Swift's macro system.
Is swift-syntax similar to Python?
No. swift-syntax is a Swift package for parsing and transforming Swift source code, and the README describes it as libraries operating on a SwiftSyntax tree. It is not a general-purpose language and the README makes no comparison to Python.
Does swift-syntax handle syntax highlighting?
The README does not describe highlighting as a feature. It documents parsing and a source-accurate tree, and points to swift-ast-explorer.com for interactively exploring the tree of a source file.
Official sources
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.
[](https://hysenlabs.com/projects/swiftlang-swift-syntax)