swiftlint

Swift linting and style enforcement via CLI

3,891 stars

Best use case

swiftlint is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Swift linting and style enforcement via CLI

Teams using swiftlint should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/swiftlint/SKILL.md --create-dirs "https://raw.githubusercontent.com/openclaw/skills/main/skills/alexissan/swiftlint/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/swiftlint/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How swiftlint Compares

Feature / AgentswiftlintStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Swift linting and style enforcement via CLI

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# SwiftLint

Enforce Swift style and conventions with static analysis. Lint entire projects, autocorrect fixable violations, manage rules, and integrate with Xcode and CI — all from the CLI.

---

## Verify Installation

```bash
swiftlint version
```

If not installed:

```bash
brew install swiftlint
```

Or via Mint:

```bash
mint install realm/SwiftLint
```

Or as a Swift Package Manager plugin (add to `Package.swift`):

```swift
.package(url: "https://github.com/realm/SwiftLint.git", from: "0.57.0")
```

Then run:

```bash
swift package plugin swiftlint
```

---

## Basic Usage

### Lint Current Directory

```bash
swiftlint
```

This recursively lints all `.swift` files from the current directory.

### Lint a Specific Path

```bash
swiftlint lint --path Sources/
```

### Lint Specific Files

```bash
swiftlint lint --path Sources/App/ViewModel.swift
```

### Lint from Standard Input

```bash
cat MyFile.swift | swiftlint lint --use-stdin --quiet
```

> **Agent guidance:** When a user says "check my code style" or "lint my Swift code," run `swiftlint` from the project root. If they point to a specific file or folder, use `--path`.

---

## Autocorrect

SwiftLint can automatically fix certain violations.

### Fix All Autocorrectable Violations

```bash
swiftlint --fix
```

### Fix a Specific Path

```bash
swiftlint --fix --path Sources/
```

### Fix a Specific File

```bash
swiftlint --fix --path Sources/App/ViewModel.swift
```

### Preview What Would Be Fixed (Dry Run)

Lint first to see violations, then fix:

```bash
swiftlint lint --path Sources/ && swiftlint --fix --path Sources/
```

> **Agent guidance:** Always lint before autocorrecting so the user sees what will change. Some violations are not autocorrectable — report those separately after fixing.

---

## Output Formats

### Default (Human-Readable)

```bash
swiftlint
```

Output: `Sources/App.swift:12:1: warning: Line Length Violation: ...`

### JSON

```bash
swiftlint lint --reporter json
```

### CSV

```bash
swiftlint lint --reporter csv
```

### Checkstyle (XML)

```bash
swiftlint lint --reporter checkstyle
```

### GitHub Actions

```bash
swiftlint lint --reporter github-actions-logging
```

### Xcode Summary (plist)

```bash
swiftlint lint --reporter xcode-summary
```

### SonarQube

```bash
swiftlint lint --reporter sonarqube
```

### Markdown

```bash
swiftlint lint --reporter markdown
```

### Save to File

```bash
swiftlint lint --reporter json > swiftlint-results.json
```

### All Available Reporters

| Reporter | Format | Best For |
|---|---|---|
| `xcode` | Xcode-compatible (default) | Local development |
| `json` | JSON array | Programmatic processing |
| `csv` | CSV | Spreadsheet analysis |
| `checkstyle` | XML | Jenkins, CI tools |
| `codeclimate` | Code Climate JSON | Code Climate integration |
| `github-actions-logging` | GitHub annotations | GitHub Actions CI |
| `sonarqube` | SonarQube JSON | SonarQube integration |
| `markdown` | Markdown table | PR comments |
| `emoji` | Emoji-decorated | Fun terminal output |
| `html` | HTML report | Browser viewing |
| `junit` | JUnit XML | Test reporting tools |
| `xcode-summary` | Plist | Xcode build summaries |

> **Agent guidance:** Use `--reporter json` when you need to parse results programmatically. Use `--reporter github-actions-logging` on GitHub Actions to get inline annotations on PRs.

---

## Rules

### List All Rules

```bash
swiftlint rules
```

### Search for a Specific Rule

```bash
swiftlint rules | grep "force_cast"
```

### Show Rule Details

```bash
swiftlint rules force_cast
```

### Rule Identifiers Quick Reference

Rules fall into categories:

**Enabled by Default (Common)**

| Rule | What It Catches |
|---|---|
| `line_length` | Lines exceeding max length (default 120 warning, 200 error) |
| `trailing_whitespace` | Whitespace at end of lines |
| `trailing_newline` | Missing or extra trailing newlines |
| `opening_brace` | Opening brace placement |
| `closing_brace` | Closing brace placement |
| `colon` | Colon spacing (e.g., `let x : Int` → `let x: Int`) |
| `comma` | Comma spacing |
| `force_cast` | Use of `as!` |
| `force_try` | Use of `try!` |
| `force_unwrapping` | Use of `!` on optionals (opt-in) |
| `type_body_length` | Type bodies exceeding max lines |
| `function_body_length` | Function bodies exceeding max lines |
| `file_length` | Files exceeding max lines |
| `cyclomatic_complexity` | High cyclomatic complexity |
| `nesting` | Deep nesting levels |
| `identifier_name` | Naming convention violations |
| `type_name` | Type naming convention violations |
| `unused_import` | Unused import statements (opt-in) |
| `unused_declaration` | Unused declarations (opt-in) |
| `vertical_whitespace` | Excessive blank lines |
| `todo` | TODO/FIXME comments as warnings |
| `mark` | Improper MARK comment format |
| `void_return` | Explicit `-> Void` instead of `-> ()` |
| `syntactic_sugar` | Prefer `[Int]` over `Array<Int>` |
| `redundant_optional_initialization` | `var x: Int? = nil` (nil is default) |
| `redundant_string_enum_value` | Enum case name matches raw value |

**Opt-In (Must Be Explicitly Enabled)**

| Rule | What It Catches |
|---|---|
| `explicit_type_interface` | Missing explicit type annotations |
| `missing_docs` | Missing documentation comments |
| `multiline_arguments` | Multiline function call formatting |
| `multiline_parameters` | Multiline function param formatting |
| `vertical_parameter_alignment` | Parameter alignment in declarations |
| `sorted_imports` | Unsorted import statements |
| `file_header` | Missing or incorrect file headers |
| `accessibility_label_for_image` | Images without accessibility labels |
| `accessibility_trait_for_button` | Buttons without accessibility traits |
| `strict_fileprivate` | Prefer `private` over `fileprivate` |
| `prohibited_interface_builder` | Storyboard/XIB usage |
| `no_magic_numbers` | Magic numbers in code |
| `prefer_self_in_static_references` | `Self` over explicit type name in static context |
| `balanced_xctest_lifecycle` | setUp without tearDown |
| `test_case_accessibility` | Test methods not marked correctly |

> **Agent guidance:** When setting up SwiftLint for a new project, start with defaults and only add opt-in rules the user specifically requests. Don't overwhelm with every possible rule.

---

## Configuration (.swiftlint.yml)

SwiftLint reads `.swiftlint.yml` from the current directory (or parent directories).

### Generate a Default Config

There's no built-in generator, but here's a minimal config:

```yaml
# .swiftlint.yml

# Paths to include (default: all Swift files)
included:
  - Sources
  - Tests

# Paths to exclude
excluded:
  - Pods
  - DerivedData
  - .build
  - Packages

# Disable specific rules
disabled_rules:
  - todo
  - trailing_whitespace

# Enable opt-in rules
opt_in_rules:
  - sorted_imports
  - unused_import
  - missing_docs

# Configure specific rules
line_length:
  warning: 120
  error: 200
  ignores_comments: true
  ignores_urls: true

type_body_length:
  warning: 300
  error: 500

file_length:
  warning: 500
  error: 1000

function_body_length:
  warning: 50
  error: 100

identifier_name:
  min_length:
    warning: 2
    error: 1
  max_length:
    warning: 50
    error: 60
  excluded:
    - id
    - x
    - y
    - i
    - j
    - ok

type_name:
  min_length:
    warning: 3
    error: 0
  max_length:
    warning: 50
    error: 60

cyclomatic_complexity:
  warning: 10
  error: 20

nesting:
  type_level:
    warning: 2
  function_level:
    warning: 3
```

### Using a Config from a Custom Path

```bash
swiftlint lint --config path/to/.swiftlint.yml
```

### Multiple Configs (Child Config)

```yaml
# Feature/.swiftlint.yml — inherits parent config and overrides
child_config: ../.swiftlint.yml

disabled_rules:
  - force_cast
```

### Parent Config (Extend from Another)

```yaml
# .swiftlint.yml
parent_config: shared/.swiftlint-base.yml
```

### Remote Config

```yaml
parent_config: https://raw.githubusercontent.com/org/repo/main/.swiftlint.yml
```

> **Agent guidance:** When a project already has `.swiftlint.yml`, always read it before suggesting changes. Modify the existing config rather than creating a new one.

---

## Inline Rule Management

### Disable a Rule for a Line

```swift
let value = dict["key"] as! String // swiftlint:disable:this force_cast
```

### Disable a Rule for a Block

```swift
// swiftlint:disable force_cast
let a = x as! String
let b = y as! Int
// swiftlint:enable force_cast
```

### Disable All Rules for a Block

```swift
// swiftlint:disable all
// Legacy code that can't be refactored yet
// swiftlint:disable:enable all
```

### Disable for Next Line Only

```swift
// swiftlint:disable:next force_cast
let value = dict["key"] as! String
```

### Disable for Previous Line

```swift
let value = dict["key"] as! String
// swiftlint:disable:previous force_cast
```

> **Agent guidance:** Prefer targeted disables (`disable:this`, `disable:next`) over broad block disables. Never suggest `disable all` unless the user is dealing with generated code or legacy code they explicitly don't want to lint.

---

## Xcode Integration

### Build Phase Script

Add a Run Script Phase in Xcode (Build Phases):

```bash
if command -v swiftlint >/dev/null 2>&1; then
  swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi
```

### Build Phase with Autocorrect

```bash
if command -v swiftlint >/dev/null 2>&1; then
  swiftlint --fix && swiftlint
fi
```

### Swift Package Plugin (Xcode 15+)

If SwiftLint is added as a package dependency:

```bash
swift package plugin swiftlint
```

Or in Xcode: right-click the project → "SwiftLintBuildToolPlugin".

> **Agent guidance:** For modern projects (Xcode 15+), prefer the SPM plugin over a build phase script — it pins the SwiftLint version to the project and doesn't require a local install.

---

## CI Integration

### GitHub Actions

```yaml
- name: SwiftLint
  run: |
    brew install swiftlint
    swiftlint lint --reporter github-actions-logging --strict
```

With only changed files:

```yaml
- name: SwiftLint Changed Files
  run: |
    git diff --name-only --diff-filter=d origin/main...HEAD -- '*.swift' | \
    xargs -I{} swiftlint lint --path {} --reporter github-actions-logging --strict
```

### Bitrise

```yaml
- script:
    inputs:
    - content: |
        brew install swiftlint
        swiftlint lint --strict
```

### Jenkins (Checkstyle)

```bash
swiftlint lint --reporter checkstyle > swiftlint-checkstyle.xml
```

Then use the Checkstyle plugin to parse `swiftlint-checkstyle.xml`.

---

## Analyzing Results

### Count Violations by Rule

```bash
swiftlint lint --reporter json | python3 -c "
import json, sys, collections
data = json.load(sys.stdin)
counts = collections.Counter(v['rule_id'] for v in data)
for rule, count in counts.most_common():
    print(f'{count:>5}  {rule}')
"
```

### Show Only Errors (Not Warnings)

```bash
swiftlint lint --strict 2>&1 | grep "error:"
```

### Strict Mode (Warnings Become Errors)

```bash
swiftlint lint --strict
```

This makes SwiftLint return a non-zero exit code for any violation (not just errors).

### Quiet Mode (Errors Only in Output)

```bash
swiftlint lint --quiet
```

Suppresses warnings from output, only shows errors.

### Enable/Disable Specific Rules via CLI

```bash
swiftlint lint --enable-rules sorted_imports,unused_import
swiftlint lint --disable-rules todo,trailing_whitespace
```

---

## Custom Rules

Define custom regex-based rules in `.swiftlint.yml`:

```yaml
custom_rules:
  no_print_statements:
    name: "No Print Statements"
    regex: "\\bprint\\s*\\("
    message: "Use os_log or Logger instead of print()"
    severity: warning
    match_kinds:
      - identifier

  no_hardcoded_strings:
    name: "No Hardcoded Strings in Views"
    regex: "Text\\(\"[^\"]+\"\\)"
    message: "Use LocalizedStringKey or String(localized:) for user-facing text"
    severity: warning
    included: ".*View\\.swift"

  no_force_unwrap_iboutlet:
    name: "No Force Unwrap IBOutlet"
    regex: "@IBOutlet\\s+(weak\\s+)?var\\s+\\w+:\\s+\\w+!"
    message: "Use optional IBOutlets to avoid crashes"
    severity: error

  accessibility_identifier_required:
    name: "Accessibility Identifier"
    regex: "\\.accessibilityIdentifier\\("
    message: "Good — accessibilityIdentifier found"
    severity: warning
    match_kinds:
      - identifier

  prefer_logger_over_print:
    name: "Prefer Logger"
    regex: "\\bNSLog\\s*\\("
    message: "Use Logger (os.Logger) instead of NSLog"
    severity: warning
```

### Match Kinds

| Kind | What It Matches |
|---|---|
| `identifier` | Variable/function names |
| `string` | String literals |
| `comment` | Comments |
| `keyword` | Swift keywords |
| `typeidentifier` | Type names |
| `number` | Numeric literals |
| `parameter` | Function parameters |
| `argument` | Function arguments |

> **Agent guidance:** Custom rules are powerful but regex-based — they can produce false positives. Always test custom rules on the codebase before suggesting them as permanent additions.

---

## Common Flags Reference

| Flag | Purpose |
|---|---|
| `--path <path>` | Lint specific file or directory |
| `--config <path>` | Use custom config file |
| `--reporter <name>` | Output format (json, csv, etc.) |
| `--strict` | Treat warnings as errors |
| `--quiet` | Only show errors in output |
| `--fix` | Autocorrect fixable violations |
| `--enable-rules <rules>` | Enable specific rules (comma-separated) |
| `--disable-rules <rules>` | Disable specific rules (comma-separated) |
| `--use-stdin` | Read Swift from stdin |
| `--force-exclude` | Exclude files even if explicitly passed |
| `--cache-path <path>` | Custom cache directory |
| `--no-cache` | Disable caching |
| `--use-alternative-excluding` | Use alternative file-excluding method |
| `--in-process-sourcekit` | Use in-process SourceKit |
| `--compiler-log-path` | Path to xcodebuild log for analyzer rules |
| `--progress` | Show progress bar |

---

## Common Workflows

### Set Up SwiftLint for a New Project

```bash
# 1. Install
brew install swiftlint

# 2. Run initial lint to see baseline
swiftlint lint --path Sources/ --reporter json > baseline.json

# 3. Create config based on results
cat > .swiftlint.yml << 'EOF'
included:
  - Sources
  - Tests
excluded:
  - Pods
  - DerivedData
  - .build
disabled_rules:
  - todo
opt_in_rules:
  - sorted_imports
  - unused_import
line_length:
  warning: 120
  error: 200
  ignores_urls: true
EOF

# 4. Fix autocorrectable issues
swiftlint --fix --path Sources/

# 5. Re-lint to see remaining issues
swiftlint
```

### Fix All Issues Before a PR

```bash
# Autocorrect what we can
swiftlint --fix

# Check what remains
swiftlint lint --strict
```

### Lint Only Changed Files (vs. main)

```bash
git diff --name-only --diff-filter=d origin/main...HEAD -- '*.swift' | \
  xargs -I{} swiftlint lint --path {} --strict
```

### Compare Violation Counts Between Branches

```bash
# Current branch count
CURRENT=$(swiftlint lint --quiet 2>&1 | wc -l | tr -d ' ')

# Main branch count
git stash
git checkout main
MAIN=$(swiftlint lint --quiet 2>&1 | wc -l | tr -d ' ')
git checkout -
git stash pop

echo "main: $MAIN violations, current: $CURRENT violations"
```

---

## Troubleshooting

### Common Errors

| Error | Solution |
|---|---|
| `No lintable files found` | Check `included` paths in config or run from project root |
| `Invalid configuration` | Validate YAML syntax in `.swiftlint.yml` |
| `SourceKit not found` | Run `sudo xcode-select -s /Applications/Xcode.app` |
| `Rule not found` | Check rule name with `swiftlint rules`, may be opt-in |
| `Slow linting` | Add `excluded` paths for Pods/DerivedData, use `--cache-path` |

### Performance Tips

- Always exclude `Pods/`, `DerivedData/`, `.build/`, and `Packages/` in config
- Use `--cache-path` to persist cache across CI runs
- Lint only changed files on CI instead of the entire project
- Use `--no-cache` only when debugging unexpected results

---

## Notes

### Agent Tips

> When a user asks to "clean up" or "fix style" in Swift code, run `swiftlint --fix` first, then `swiftlint lint` to report remaining issues.

> Before adding SwiftLint to an existing project, run `swiftlint lint --reporter json` to assess the violation count. If there are hundreds of violations, suggest a phased approach: fix autocorrectable ones first, then tackle the rest by category.

> Always check for an existing `.swiftlint.yml` before creating one. Read it to understand the team's style preferences.

> For projects targeting accessibility (which should be all of them), suggest enabling `accessibility_label_for_image` and `accessibility_trait_for_button` opt-in rules.

> When the user's project uses SwiftUI, suggest a custom rule to catch hardcoded strings in `Text()` views — all user-facing strings should use `String(localized:)` for localization support.

> The `--strict` flag is essential for CI — without it, SwiftLint exits 0 even with warnings, which means your CI pipeline won't catch style regressions.

Related Skills

---

3891
from openclaw/skills

name: article-factory-wechat

Content & Documentation

humanizer

3891
from openclaw/skills

Remove signs of AI-generated writing from text. Use when editing or reviewing text to make it sound more natural and human-written. Based on Wikipedia's comprehensive "Signs of AI writing" guide. Detects and fixes patterns including: inflated symbolism, promotional language, superficial -ing analyses, vague attributions, em dash overuse, rule of three, AI vocabulary words, negative parallelisms, and excessive conjunctive phrases.

Content & Documentation

find-skills

3891
from openclaw/skills

Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.

General Utilities

tavily-search

3891
from openclaw/skills

Use Tavily API for real-time web search and content extraction. Use when: user needs real-time web search results, research, or current information from the web. Requires Tavily API key.

Data & Research

baidu-search

3891
from openclaw/skills

Search the web using Baidu AI Search Engine (BDSE). Use for live information, documentation, or research topics.

Data & Research

agent-autonomy-kit

3891
from openclaw/skills

Stop waiting for prompts. Keep working.

Workflow & Productivity

Meeting Prep

3891
from openclaw/skills

Never walk into a meeting unprepared again. Your agent researches all attendees before calendar events—pulling LinkedIn profiles, recent company news, mutual connections, and conversation starters. Generates a briefing doc with talking points, icebreakers, and context so you show up informed and confident. Triggered automatically before meetings or on-demand. Configure research depth, advance timing, and output format. Walking into meetings blind is amateur hour—missed connections, generic small talk, zero leverage. Use when setting up meeting intelligence, researching specific attendees, generating pre-meeting briefs, or automating your prep workflow.

Workflow & Productivity

self-improvement

3891
from openclaw/skills

Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong...', 'Actually...'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.

Agent Intelligence & Learning

botlearn-healthcheck

3891
from openclaw/skills

botlearn-healthcheck — BotLearn autonomous health inspector for OpenClaw instances across 5 domains (hardware, config, security, skills, autonomy); triggers on system check, health report, diagnostics, or scheduled heartbeat inspection.

DevOps & Infrastructure

linkedin-cli

3891
from openclaw/skills

A bird-like LinkedIn CLI for searching profiles, checking messages, and summarizing your feed using session cookies.

Content & Documentation

notebooklm

3891
from openclaw/skills

Google NotebookLM 非官方 Python API 的 OpenClaw Skill。支持内容生成(播客、视频、幻灯片、测验、思维导图等)、文档管理和研究自动化。当用户需要使用 NotebookLM 生成音频概述、视频、学习材料或管理知识库时触发。

Data & Research

小红书长图文发布 Skill

3891
from openclaw/skills

## 概述

Content & Documentation