A CLAUDE.md is just a markdown file at the root of your repo. Copy the content below into your own project's CLAUDE.md to give your agent the same context.
npx versuz@latest install nicklockwood-swiftformat --kind=claude-mdcurl -o CLAUDE.md https://raw.githubusercontent.com/nicklockwood/SwiftFormat/HEAD/CLAUDE.md# SwiftFormat
SwiftFormat is a code formatting tool for Swift. It applies a set of rules to Swift source files, transforming them to follow consistent style conventions.
## Project Structure
- `Sources/Rules/` - Individual formatting rules (one file per rule)
- `Tests/Rules/` - Test cases for rules
- `Sources/Formatter.swift` - Core formatter class with token manipulation APIs
- `Sources/ParsingHelpers.swift` - Parsing helpers for Swift grammar (types, declarations, expressions, etc.)
- `Sources/FormattingHelpers.swift` - Higher-level formatting utilities
- `Sources/Options.swift` - Options for configuring the behavior of individual rules
- `Sources/OptionDescriptor.swift` - Command line flag configuration for rule options
## Branching
All changes and pull requests should target the `develop` branch, not `main`.
## Building and Testing
```sh
# Build the project
swift build
# Run all tests (on macOS)
swift test
# Run all tests (on Linux)
# --enable-test-discovery is required because LinuxMain.swift (kept for Mint
# compatibility) has an empty test list that overrides automatic discovery.
swift test --enable-test-discovery
# Test a specific rule (works on both macOS and Linux)
./Scripts/test_rule.sh <ruleName>
# Format the codebase (run after making changes)
# ./Scripts/test_rule.sh runs this automatically
./format.sh
```
## Adding New Rules
### Before You Start
**Read the helper files thoroughly.** Before writing any rule, familiarize yourself with the existing helpers:
- `Sources/Formatter.swift` - Token manipulation APIs
- `Sources/ParsingHelpers.swift` - Parsing helpers for types, declarations, expressions, properties, functions, etc.
- `Sources/FormattingHelpers.swift` - Higher-level formatting utilities
- `Sources/Declarations.swift` - Helpers related to individual declarations
You MUST review the APIs available in these files using:
```bash
$ rg "^ (func|var) " Sources/Formatter.swift Sources/FormattingHelpers.swift Sources/ParsingHelpers.swift Sources/Declaration.swift
```
Many rules can be implemented using existing helpers. Before writing custom token parsing code, verify no existing helper does what you need.
### Rule File Structure
Create a new file in `Sources/Rules/` named after your rule (e.g., `MyRule.swift`). Rules are defined as static properties on `FormatRule`:
```swift
//
// MyRule.swift
// SwiftFormat
//
import Foundation
public extension FormatRule {
/// Brief description of what the rule does
static let myRule = FormatRule(
help: "Description shown in --help output."
) { formatter in
// Rule implementation goes here. For example:
formatter.forEach(.keyword("let")) { i, _ in
// Process each occurrence
}
} examples: {
"""
```diff
- before
+ after
```
"""
}
}
```
Rule tests are implemented in `Tests/Rules/MyRuleTests.swift`.
### Best Practices
- **File author names:** when creating new files, always use the name of the actual user / human author, and the current date. **NEVER** write a file header like "Created by Claude Code" or "Created by GitHub Copilot". Prefer the user's full name as opposed to just their username.
- **Minimal changes only.** Only modify tokens when an actual change is needed. Any modification triggers a lint error in `--lint` mode.
- **Preserve comments.** Prefer preserving code as-is if updating would require removing comments.
- **Keep it simple.** Write as little code as possible. If a change dramatically increases complexity, consider asking if it should be de-scoped.
- **Define local helpers** in extensions on `Formatter` at the bottom of the rule file. Mark them `internal` for discoverability. Move helpers used by multiple rules to `ParsingHelpers.swift`. Parsing code should almost always be factored out into a rule-specific helper (or later a shared helper if necessary) rather than being implemented directly in the rule implementation closure.
**Always use Formatter APIs.** Never manipulate token arrays directly:
```swift
// ✓ Good - use Formatter APIs
formatter.insert(.space(" "), at: index)
formatter.removeToken(at: index)
formatter.replaceToken(at: index, with: .keyword("let"))
// ✗ Bad - array manipulation
var tokens = Array(formatter.tokens[start...end])
tokens.append(.space(" "))
formatter.replaceTokens(in: start...end, with: tokens)
```
**Never use raw index loops.** Always traverse tokens using helpers:
```swift
// ✓ Good - use traversal helpers
formatter.index(of: .nonSpaceOrCommentOrLinebreak, after: i)
formatter.index(of: .keyword("func"), before: i)
formatter.endOfLine(at: i)
// ✗ Bad - raw index manipulation
while i < formatter.tokens.count { i += 1 }
for i in 0..<formatter.tokens.count { ... }
```
### Writing Tests
Use the `testFormatting` helper defined in `XCTestCase` extensions:
```swift
func testMyRule() {
let input = """
// input code
"""
let output = """
// expected output
"""
testFormatting(for: input, output, rule: .myRule)
}
```
- Create several test scenarios covering different cases, but don't exhaustively test every configuration.
- Use `testFormatting(for: input, [output], rules: [.myRule, .otherRule])` to test multiple rules together.
- Prefer formatting `input` and `output` code to match the behavior of other rules, instead of excluding other rules with `exclude:`. Only use `exclude:` if the other rule being applied directly conflicts with what the test case is trying to test.
- Do not use `// MARK` comments in tests.
- Always use multi-line string literals (""") for input and output code.
### Debugging
To debug a rule, run the existing tests or create new test cases. **NEVER** try to directly run SwiftFormat on a file via the command line.
Use print debugging as necessary to gather more context. Run individual test cases using:
```sh
# On macOS:
swift test --filter <TestClassName>.<testMethodName>
# On Linux (--enable-test-discovery required):
swift test --enable-test-discovery --filter <TestClassName>.<testMethodName>
```
### After Writing the Rule
1. **Run the rule tests:** `./Scripts/test_rule.sh <ruleName>`
2. **Run the full test suite:** `swift test` (or `swift test --enable-test-discovery` on Linux)
3. **[VERY IMPORTANT] Review your code** - ensure it follows all best practices above
4. **[VERY IMPORTANT] Simplify further** - look for functionality that could be removed to reduce complexity
**Note:** Do not modify `Rules.md` directly. It's auto-generated when running the test suite. `MetadataTests` may fail after adding a new rule; re-run after metadata regenerates.
## See Also
@CONTRIBUTING.md