quality-run-linting-formatting
npx skills add https://github.com/dawiddutoit/custom-claude --skill quality-run-linting-formatting
Agent 安装分布
Skill 文档
Run Linting and Formatting Workflow
Table of Contents
Quick Start â Purpose | When to Use | Quick Start
Core Operations â Run Linting | Auto-Fix | Formatting
Configuration â Ruff Config | Violation Codes | Common Fixes
Workflows â Common Workflows | Output Interpretation | Integration
Help â Troubleshooting | Requirements
Purpose
Master ruff usage for linting (code quality) and formatting (code style) in temet. Understand when to check vs format, how to auto-fix violations, and interpret common error codes.
When to Use
Use this skill when:
- Running code quality checks before commits
- Fixing linting violations
- Formatting code to match project standards
- Understanding ruff error codes (F401, E501, etc.)
- Configuring ruff for project-specific rules
User trigger phrases:
- “run linting”
- “format code”
- “fix lint errors”
- “ruff check”
- “what does E501 mean?”
Quick Start
Most common workflows:
# Check for lint violations (don't modify files)
ruff check src/ tests/
# Auto-fix violations (safe fixes only)
ruff check src/ tests/ --fix
# Format code (modifies files)
ruff format src/ tests/
# Check formatting without modifying
ruff format src/ tests/ --check
# Full workflow (lint + format)
ruff check src/ tests/ --fix && ruff format src/ tests/
Instructions
Understanding Ruff vs Other Tools
Ruff replaces multiple tools:
| Tool | What It Did | Ruff Equivalent |
|---|---|---|
black |
Code formatting | ruff format |
isort |
Import sorting | ruff check --select I |
flake8 |
Linting | ruff check |
pylint |
Linting | ruff check |
pyupgrade |
Python version upgrades | ruff check --select UP |
autoflake |
Remove unused imports | ruff check --select F401 --fix |
Why ruff:
- â¡ 10-100x faster than other tools (written in Rust)
- ð¯ One tool replaces 5-6 tools
- ð§ Auto-fix for most violations
- ð Configurable (select/ignore rules)
Step 1: Run Linting (ruff check)
Basic usage:
ruff check src/ tests/
Output (success):
All checks passed!
Output (with violations):
src/temet/core/event_bus.py:15:1: F401 [*] `logging` imported but unused
src/temet/core/event_bus.py:42:80: E501 Line too long (102 > 100)
src/temet/plugins/hooks/session_start/plugin.py:23:5: B008 Do not perform function call `dict` in argument defaults
Found 3 errors.
[*] 1 fixable with the `--fix` option.
Understanding output:
- File:line:col – Location of violation
- Code – Error code (e.g., F401, E501, B008)
- [*] – Fixable with –fix
- Message – Description of violation
Step 2: Auto-Fix Violations
Safe auto-fix (recommended):
ruff check src/ tests/ --fix
What gets fixed:
- â Unused imports removed
- â Imports sorted (isort-compatible)
- â Unnecessary parentheses removed
- â Quoted strings normalized
- â Whitespace issues fixed
- â ï¸ Does NOT fix: Complex violations requiring manual intervention
Check what would be fixed (dry-run):
ruff check src/ tests/ --fix --diff
Unsafe fixes (use with caution):
ruff check src/ tests/ --fix --unsafe-fixes
When to use:
--fix: Before every commit (auto-fix safe issues)--fix --diff: Preview changes before applying--unsafe-fixes: Only when you understand the changes
Step 3: Run Formatting (ruff format)
Format files in-place:
ruff format src/ tests/
Output:
3 files reformatted, 244 files left unchanged
Check formatting without modifying:
ruff format src/ tests/ --check
Output (violations):
Would reformat: src/temet/core/event_bus.py
Would reformat: src/temet/plugins/hooks/session_start/plugin.py
2 files would be reformatted, 245 files left unchanged
See what would change (dry-run):
ruff format src/ tests/ --diff
When to use:
ruff format: Before commits (format all code)ruff format --check: In CI/CD (verify formatting)ruff format --diff: Review formatting changes
Step 4: Understand Ruff Configuration
temet ruff configuration (pyproject.toml):
[tool.ruff]
line-length = 100 # Max line length
target-version = "py312" # Python 3.12
[tool.ruff.lint]
select = ["ALL"] # Enable ALL rules by default
ignore = [
"D", # pydocstyle (docstrings not enforced)
"COM812", # Trailing comma (conflicts with formatter)
"ISC001", # Single-line implicit concat (conflicts with formatter)
"T201", # print() allowed (CLI tool needs print)
"BLE001", # Catching Exception allowed (plugin error handling)
"ARG001", # Unused function args (test fixtures, protocols)
"ARG002", # Unused method args (test fixtures, protocols)
]
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = [
"S101", # assert allowed in tests
"ANN", # Type annotations optional in tests
]
[tool.ruff.format]
quote-style = "double" # Use " not '
indent-style = "space" # 4 spaces (not tabs)
Key rules:
- Line length: 100 characters (not 80)
- Target: Python 3.12 (uses modern syntax)
- Quotes: Double quotes preferred
- Indentation: 4 spaces
Step 5: Common Violation Codes
Import-related (F):
| Code | Description | Fix |
|---|---|---|
| F401 | Imported but unused | ruff check --fix removes |
| F403 | from module import * |
Specify imports explicitly |
| F811 | Redefined unused variable | Rename or remove duplicate |
Code style (E/W):
| Code | Description | Fix |
|---|---|---|
| E501 | Line too long (> 100) | Break line or shorten |
| E711 | Comparison to None should be is |
Use is None |
| W291 | Trailing whitespace | ruff check --fix removes |
Best practices (B):
| Code | Description | Fix |
|---|---|---|
| B008 | Function call in argument defaults | Use default_factory or None |
| B006 | Mutable default argument | Use None and create in function |
| B011 | assert False instead of raise |
Use raise AssertionError |
Type checking (ANN):
| Code | Description | Fix |
|---|---|---|
| ANN001 | Missing type annotation (arg) | Add type annotation |
| ANN201 | Missing return type | Add -> ReturnType |
| ANN401 | Any type (too vague) |
Use specific type |
See: Ruff rule reference for complete list
Common Workflows
Workflow 1: Pre-Commit (Fix + Format)
# Fix lint violations + format code
ruff check src/ tests/ --fix && ruff format src/ tests/
# Verify no violations remain
ruff check src/ tests/
ruff format src/ tests/ --check
Time: 1-2 seconds
Workflow 2: Development (Check Only)
# Check for violations (don't modify files)
ruff check src/ tests/
# If violations: Fix manually or use --fix
Time: < 1 second
Workflow 3: CI/CD (Verify Only)
# In CI pipeline: Verify linting and formatting
ruff check src/ tests/
ruff format src/ tests/ --check
# If violations: Fail CI (developer must fix locally)
Time: < 1 second (fast feedback)
Workflow 4: Format on Save (IDE Integration)
VSCode settings.json:
{
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.fixAll": true
}
}
}
Result: Auto-fix + format on every file save
Interpreting Lint Output
Example Output
src/temet/core/event_bus.py:15:1: F401 [*] `logging` imported but unused
src/temet/core/event_bus.py:42:80: E501 Line too long (102 > 100)
src/temet/core/event_bus.py:67:5: B006 [*] Do not use mutable data structures for argument defaults
src/temet/plugins/hooks/session_start/plugin.py:23:10: ANN001 Missing type annotation for function argument `event`
Found 4 errors.
[*] 2 fixable with the `--fix` option.
Breakdown:
- F401 – Unused import (fixable) â
ruff check --fix - E501 – Line too long â Break line manually
- B006 – Mutable default (fixable) â
ruff check --fix - ANN001 – Missing annotation â Add type manually
Action plan:
# 1. Auto-fix what's possible
ruff check src/ tests/ --fix
# 2. Manually fix remaining issues
# - E501: Break long line
# - ANN001: Add type annotation
# 3. Verify all fixed
ruff check src/ tests/
Fixing Common Violations
Violation 1: F401 – Unused Import
Error:
src/temet/core/event_bus.py:15:1: F401 [*] `logging` imported but unused
Fix (auto):
ruff check src/ tests/ --fix
Or manually:
# â Before
import logging # Unused
from typing import Any
# â
After
from typing import Any # Removed unused import
Violation 2: E501 – Line Too Long
Error:
src/temet/core/event_bus.py:42:80: E501 Line too long (102 > 100)
Fix (manual):
# â Before (102 characters)
def process_event(event: Event, handlers: list[Callable], config: dict[str, Any]) -> dict[str, Any]:
# â
After (break line)
def process_event(
event: Event,
handlers: list[Callable],
config: dict[str, Any],
) -> dict[str, Any]:
Violation 3: B006 – Mutable Default Argument
Error:
src/temet/core/event_bus.py:67:5: B006 [*] Do not use mutable data structures for argument defaults
Fix (auto or manual):
# â Before (dangerous - shared mutable default)
def process(data: dict[str, Any] = {}):
data["key"] = "value" # Modifies shared default!
# â
After (safe - create new dict each call)
def process(data: dict[str, Any] | None = None):
if data is None:
data = {}
data["key"] = "value"
Violation 4: ANN001 – Missing Type Annotation
Error:
src/temet/plugins/hooks/session_start/plugin.py:23:10: ANN001 Missing type annotation for function argument `event`
Fix (manual):
# â Before
def handle(self, event):
return event.data
# â
After
def handle(self, event: Event) -> dict[str, Any]:
return event.data
Integration with Other Skills
Before linting:
setup-temet-project– Ensure ruff installedrun-type-checking-workflow– Fix type errors first (easier to lint)
After linting:
run-quality-gates– Run all gates (includes ruff)git-commit-push– Lint passes as pre-commit requirement
During development:
interpret-check-all-output– Understand check_all.sh results (includes ruff)
Troubleshooting
Issue: ruff: command not found
Solution:
# Use uv run prefix
uv run ruff check src/ tests/
# Or ensure ruff installed
uv pip install -e ".[dev]"
Issue: Too many violations to fix manually
Solution:
# Auto-fix everything possible
ruff check src/ tests/ --fix
# Then fix remaining violations one file at a time
ruff check src/temet/core/event_bus.py --fix
Issue: Conflict between ruff and pyright
Symptoms: Ruff suggests one fix, pyright suggests another
Solution:
# 1. Fix pyright errors first (type safety)
pyright src/ tests/
# 2. Then run ruff (code style)
ruff check src/ tests/ --fix
Rationale: Type safety > code style. Fix types first, style second.
Issue: --fix breaks code
Symptoms: Auto-fix changes behavior or introduces bugs
Solution:
# 1. Review changes before applying
ruff check src/ tests/ --fix --diff
# 2. If looks wrong, skip auto-fix
# 3. Fix manually with understanding
# 4. If auto-fix is wrong, report bug to ruff
# (Rare - ruff is well-tested)
Issue: Want to ignore specific violation
Solution (per-line ignore):
# Ignore specific rule on one line
result = some_call() # noqa: E501
Solution (file-level ignore):
# In pyproject.toml
[tool.ruff.lint.per-file-ignores]
"src/temet/legacy/*.py" = ["E501", "F401"] # Ignore in legacy code
Rule: Only ignore with justification comment:
# noqa: E501 - API URL cannot be broken
api_url = "https://very-long-api-url.example.com/v1/endpoint/with/many/parameters"
Requirements
Dependencies (auto-installed with [dev]):
ruff– Linter and formatter
Configuration files:
pyproject.toml– Ruff configuration (required).vscode/settings.json– IDE integration (optional)
No manual installation needed – included in pyproject.toml.
Expected Output
Success (No Violations)
$ ruff check src/ tests/
All checks passed!
$ ruff format src/ tests/ --check
247 files already formatted
â Ready to commit
Violations Found
$ ruff check src/ tests/
src/temet/core/event_bus.py:15:1: F401 [*] `logging` imported but unused
src/temet/core/event_bus.py:42:80: E501 Line too long (102 > 100)
Found 2 errors.
[*] 1 fixable with the `--fix` option.
$ ruff format src/ tests/ --check
Would reformat: src/temet/core/event_bus.py
1 file would be reformatted, 246 files left unchanged
ð§ Fix with:
ruff check src/ tests/ --fix && ruff format src/ tests/