Configuration¶
Rude is configured via pyproject.toml under the [tool.rude] section.
Settings from the config file can be overridden by CLI flags.
Config file discovery¶
Rude searches upward from the current working directory for a pyproject.toml
that contains a [tool.rude] section. You can override this with --config:
rude check --config path/to/pyproject.toml src/
Rule selection¶
select¶
Enable specific rules or rule prefixes. When set, only matching rules are active:
[tool.rude]
select = ["PAT", "META", "F"]
This enables all rules whose code starts with PAT, META, or F. You can
also specify individual codes:
[tool.rude]
select = ["PAT001", "PAT008", "F841", "META"]
ignore¶
Exclude rules from the active set. Applied after select:
[tool.rude]
select = ["PAT"]
ignore = ["PAT004"]
This enables all pattern rules except PAT004 (long function).
Both select and ignore support individual codes (F841) and prefixes (F).
Plugins¶
Entry-point plugins¶
Third-party packages can register rules via the rude.plugins entry point.
List them in plugins to load them explicitly by module name:
[tool.rude]
plugins = ["rude-django", "rude-flask"]
Rude also auto-discovers any installed package that declares the
rude.plugins entry point, even without listing it here. The plugins option
is for loading modules by name that don’t use the entry-point mechanism.
Local rules¶
Load rules from local Python files without creating a package:
Warning
local-rules and installed plugins execute arbitrary Python at startup.
Only list paths you control, and only install plugins you trust – see
SECURITY.md
for the full trust model.
[tool.rude]
local-rules = ["tools/rules.py", "tools/extra_rules/"]
Paths are resolved relative to the pyproject.toml location. If a directory
is given, all .py files in it (excluding those starting with _) are loaded.
See the Plugin development guide for details on writing plugins and local rules.
Per-rule options¶
Many rules accept configuration via [tool.rude.rules.<CODE>] sub-tables:
[tool.rude.rules.PAT001]
max_params = 7
[tool.rude.rules.PAT004]
max_lines = 100
[tool.rude.rules.META001]
ticket_pattern = "(PROJ-\\d+|#\\d+)"
Each rule documents its accepted options. Check the Built-in Rules page for built-in rule options.
Inline suppression¶
Suppress individual diagnostics with # noqa comments:
eval(user_input) # noqa: PAT008
Suppress multiple codes on one line:
eval(user_input) # noqa: PAT008,F841
A blanket # noqa (without codes) suppresses all diagnostics on that line,
but is flagged by the META002 rule as bad practice:
eval(user_input) # noqa
Tip
Always specify the exact codes you intend to suppress. Blanket # noqa
comments hide real issues and make code harder to maintain.
File filtering¶
Rude automatically skips common non-source directories when scanning for Python files:
Version control:
.git,.hg,.svnVirtual environments:
.venv,venv,.env,envBuild artifacts:
dist,build,*.egg-info,.eggsCache directories:
__pycache__,.mypy_cache,.pytest_cache,.ruff_cache,.hypothesis,.coverage,htmlcovOthers:
node_modules,.tox,.nox,.ipynb_checkpoints
Additionally, Rude respects your project’s .gitignore file. Any path
matched by .gitignore is excluded from linting.
Tip
To exclude specific paths from linting, add them to your .gitignore or
pass only the directories you want to check:
# Lint only src/ and tests/, ignoring everything else
rude check src/ tests/
For per-rule file filtering, use should_check_file() in custom rules
(see Writing custom rules) or the paths option on template rules:
[tool.rude.rules.EX003]
forbidden = ["print"]
paths = ["src/"]
exclude_paths = ["src/scripts/"]
Complete example¶
[tool.rude]
# Enable pattern, hygiene, pyflakes, and pycodestyle rules
select = ["PAT", "META", "F", "E", "W"]
# Ignore line-length (handled by formatter) and long-function checks
ignore = ["E501", "PAT004"]
# Load a third-party plugin
plugins = ["rude-django"]
# Load project-specific local rules
local-rules = ["tools/lint_rules.py"]
# --- Per-rule configuration ---
[tool.rude.rules.PAT001]
max_params = 7
[tool.rude.rules.PAT002]
max_branches = 15
[tool.rude.rules.PAT003]
max_depth = 5
[tool.rude.rules.PAT005]
max_methods = 25
[tool.rude.rules.META001]
ticket_pattern = "(PROJ-\\d+|#\\d+)"
# --- Template rules (require configuration to activate) ---
[tool.rude.rules.EX001]
pattern = "*Service"
required_base = "BaseService"
paths = ["src/services/"]
[tool.rude.rules.EX002]
required_decorator = "audit_log"
paths = ["src/api/"]
exclude_pattern = "_*"
[tool.rude.rules.EX003]
forbidden = ["print", "pdb.set_trace", "breakpoint"]
paths = ["src/"]
exclude_paths = ["src/scripts/", "tests/"]
[tool.rude.rules.EX004]
pattern = "*Model"
required_fields = ["created_at", "updated_at"]
paths = ["src/models/"]
Integration with Ruff¶
Rude is designed to complement Ruff, not replace it. A typical workflow chains both tools:
# Lint with Ruff (standard rules) + Rude (custom rules), then format
ruff check src/ && rude check src/ && ruff format src/
Or in a Makefile:
.PHONY: lint
lint:
ruff check src/ tests/
rude check src/ tests/
format:
ruff format src/ tests/
ruff check --fix src/ tests/
rude check --fix src/ tests/
Since Rude focuses on custom and organization-specific rules, there is minimal overlap with Ruff’s built-in rule set. Use Ruff for standard PEP 8 style, import sorting, and code upgrades. Use Rude for project-specific conventions, complexity checks, and rules that need semantic analysis.