A fast C# linter that respects .editorconfig. Uses Roslyn syntax-only parsing for fast single-file linting, with opt-in semantic analysis (--semantic) for deeper checks.
Pre-built binaries support Windows and Linux. macOS is supported when built from source or installed as a dotnet tool.
dotnet format --verify-no-changes can be slow because it loads the full Roslyn Workspaces layer with semantic analysis. CsLint skips most of that — it parses syntax trees directly and reads rules from .editorconfig, making it fast enough to run as a hook on every file edit. When you need deeper analysis, the --semantic flag enables Tier 4 rules that use the Roslyn semantic model.
scoop bucket add lucaspimentel https://github.com/lucaspimentel/scoop-bucket
scoop install cslintRequires .NET 10 SDK.
dotnet tool install --global cslintRequires PowerShell 7+.
irm https://raw.githubusercontent.com/lucaspimentel/cslint/main/install-remote.ps1 | iexRequires PowerShell 7+ and .NET 10 SDK.
git clone https://github.com/lucaspimentel/cslint
cd cslint
./install-local.ps1# Lint current directory (default if no path specified)
cslint
# Lint a single file
cslint path/to/File.cs
# Lint a directory (recursively)
cslint src/
# Lint multiple paths
cslint src/ProjectA src/ProjectB path/to/File.cs
# Output as JSON or SARIF
cslint src/ --format json
cslint src/ --format sarif
# Filter by minimum severity
cslint src/ --severity warning
# Exclude files by glob pattern
cslint src/ --exclude "**/Generated/*.cs" --exclude "**/*.g.cs"
# Enable semantic analysis (Tier 4 rules)
cslint src/ --semantic
# Run only specific rules, ignoring .editorconfig
cslint src/ --rules IDE0011,IDE0036
# Run all rules, ignoring .editorconfig
cslint src/ --rules all
# Show summary of diagnostics grouped by rule
cslint src/ --summary
# List all available rules
cslint --list-rules
# Show resolved .editorconfig settings for a path
cslint --show-config .
cslint --show-config src/MyFile.cs
# Show version
cslint --version| Code | Meaning |
|---|---|
| 0 | No violations found |
| 1 | Violations found |
| 2 | Error (bad path, etc.) |
CsLint implements a subset of rules from Microsoft's .NET code analysis framework, including IDE code style analyzers and StyleCop (SA) rules. Rules are read from your .editorconfig and organized into four tiers:
Text-level checks: indentation, line endings, whitespace, max line length, #region, file headers, UTF-8 encoding.
Naming conventions via the standard 3-part dotnet_naming_rule / dotnet_naming_symbols / dotnet_naming_style system (IDE1006), plus built-in defaults for PascalCase types/members, I-prefix interfaces, camelCase parameters, _camelCase fields.
Code style preferences (var usage, expression-bodied members, braces, namespaces, pattern matching, sealed types, member ordering) and CA code quality rules (naming conventions, design guidelines, performance hints, bug detection). CA rules are enabled by default, matching the .NET SDK.
Rules that use the Roslyn semantic model: unused usings (IDE0005), unused locals, unreachable code, duplicate enum values (CA1069), self-assignment, unnecessary casts (IDE0004), redundant await, unused/unread private members (IDE0051/IDE0052).
See docs/rule-mappings.md for the complete rule reference with editorconfig keys and analyzer ID mappings.
Suppress specific CsLint rules with #pragma warning disable:
#pragma warning disable CSLINT001
class Foo { } // trailing whitespace not reported
#pragma warning restore CSLINT001- Supports single or multiple rule IDs:
#pragma warning disable CSLINT001, IDE0007 #pragma warning disable(no IDs) suppresses all CsLint rules in that range- Without a matching
restore, suppression continues to end of file - Third-party rule IDs (StyleCop
SA*and MicrosoftIDE*) are also recognized and mapped to the corresponding CsLint rules. Legacy CSLINT IDs from older versions are still accepted. For example:
| Third-Party ID | CsLint ID(s) | Rule |
|---|---|---|
SA1302 |
CSLINT101 |
Interface prefix |
SA1313 |
CSLINT103 |
Parameter naming |
SA1306 |
CSLINT104 |
Field naming |
IDE0160/IDE0161 |
CSLINT203 |
Namespace declarations |
IDE1006 |
CSLINT102, CSLINT103, CSLINT104 |
General naming |
See docs/rule-mappings.md for the full alias mapping table.
CsLint can run as a Claude Code hook to lint .cs files automatically after every edit. Make sure cslint is installed and available on your PATH (see Installation), then choose one of the options below.
The linters plugin sets up PostToolUse hooks for CsLint and other linters automatically. First add the marketplace, then install the plugin:
From the CLI:
claude plugin marketplace add https://github.com/lucaspimentel/claude-plugins
claude plugin install linters@lucasp-claude-pluginsOr from inside Claude Code:
/plugin marketplace add https://github.com/lucaspimentel/claude-plugins
/plugin install linters@lucasp-claude-plugins
Add a PostToolUse hook in ~/.claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/cs-lint.sh"
}
]
}
]
}
}With ~/.claude/hooks/cs-lint.sh:
#!/bin/bash
FILE_PATH=$(jq -r ".tool_input.file_path")
if [[ "$FILE_PATH" == *.cs ]]; then
OUTPUT=$(cslint "$FILE_PATH" 2>&1)
if [[ -n "$OUTPUT" ]]; then
echo "$OUTPUT" >&2
exit 2
fi
fiWhen a hook exits with code 2, Claude Code receives the output as feedback and can fix the violations automatically.
This project is licensed under the MIT License.