Claude-skill-registry linting-workflow
Generic linting workflow for multiple languages with auto-fix and error resolution guidance
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/linting-workflow" ~/.claude/skills/majiayu000-claude-skill-registry-linting-workflow && rm -rf "$T"
skills/data/linting-workflow/SKILL.mdWhat I do
I provide a generic linting workflow that can be adapted for multiple languages:
- Detect Language: Automatically detect project language (JavaScript/TypeScript, Python, etc.)
- Detect Linter: Identify and configure appropriate linter (ESLint, Ruff, etc.)
- Detect Package Manager: Determine package manager for running linter commands
- Run Linting: Execute linter with appropriate command
- Apply Auto-Fix: Use linter's auto-fix capability when available
- Guide Error Resolution: Provide step-by-step guidance for fixing linting errors
- Verify Fixes: Re-run linting to ensure all errors are resolved
- Commit Fixes: Optionally commit linting fixes as separate commit
When to use me
Use this framework when:
- You need to lint code before committing or creating PRs
- You want to ensure code follows industry standards and style guidelines
- You're building a workflow skill that includes code quality checks
- You need linting for multiple languages in a consistent way
- You want to integrate linting into automated workflows (PR creation, etc.)
This is a framework skill - it provides linting logic that other skills extend.
Core Workflow Steps
Step 1: Detect Project Language
Purpose: Determine which language and linter to use
Detection Logic:
# Check for language indicators if [ -f "package.json" ]; then LANGUAGE="javascript" # Further check TypeScript if [ -f "tsconfig.json" ] || grep -q "typescript" package.json; then LANGUAGE="typescript" fi elif [ -f "pyproject.toml" ] || [ -f "requirements.txt" ] || [ -f "setup.py" ]; then LANGUAGE="python" elif [ -f "go.mod" ]; then LANGUAGE="go" elif [ -f "Gemfile" ]; then LANGUAGE="ruby" else echo "Unable to detect language. Please specify manually." exit 1 fi echo "Detected language: $LANGUAGE"
Language Detection Summary:
| Indicator | Language | Linter |
|---|---|---|
+ | TypeScript | ESLint |
| JavaScript | ESLint |
or | Python | Ruff |
| Go | golint, golangci-lint |
| Ruby | RuboCop |
Step 2: Detect Linter and Configuration
Purpose: Identify which linter is available and configured
JavaScript/TypeScript Linter Detection:
# Check package.json for ESLint if grep -q "\"eslint\"" package.json; then LINTER="eslint" # Check for ESLint config ESLINT_CONFIG="" [ -f ".eslintrc.json" ] && ESLINT_CONFIG=".eslintrc.json" [ -f ".eslintrc.js" ] && ESLINT_CONFIG=".eslintrc.js" [ -f "eslint.config.js" ] && ESLINT_CONFIG="eslint.config.js" [ -f "eslint.config.mjs" ] && ESLINT_CONFIG="eslint.config.mjs" [ -f "eslint.config.ts" ] && ESLINT_CONFIG="eslint.config.ts" echo "Detected linter: ESLint" echo "Config file: $ESLINT_CONFIG" # Check for other linters elif grep -q "\"prettier\"" package.json; then LINTER="prettier" echo "Detected linter: Prettier" elif grep -q "\"stylelint\"" package.json; then LINTER="stylelint" echo "Detected linter: Stylelint" fi
Python Linter Detection:
# Check for Ruff if grep -q "ruff" pyproject.toml 2>/dev/null || grep -q "ruff" requirements.txt 2>/dev/null; then LINTER="ruff" echo "Detected linter: Ruff" # Check for other linters elif grep -q "flake8" requirements.txt 2>/dev/null; then LINTER="flake8" echo "Detected linter: Flake8" elif grep -q "pylint" requirements.txt 2>/dev/null; then LINTER="pylint" echo "Detected linter: Pylint" elif grep -q "black" requirements.txt 2>/dev/null; then LINTER="black" echo "Detected linter: Black" fi
Step 3: Detect Package Manager
Purpose: Determine how to run linter commands
Package Manager Detection:
| Language | Manager | Detection | Run Command |
|---|---|---|---|
| JavaScript/TypeScript | npm | exists | |
| JavaScript/TypeScript | yarn | exists | |
| JavaScript/TypeScript | pnpm | exists | |
| Python | Poetry | exists | |
| Python | pip | exists | or |
Implementation:
# Detect package manager if [ -f "package-lock.json" ]; then PKG_MANAGER="npm" RUN_CMD="npm run" elif [ -f "yarn.lock" ]; then PKG_MANAGER="yarn" RUN_CMD="yarn" elif [ -f "pnpm-lock.yaml" ]; then PKG_MANAGER="pnpm" RUN_CMD="pnpm run" elif command -v poetry &>/dev/null && [ -f pyproject.toml ]; then PKG_MANAGER="poetry" RUN_CMD="poetry run" else PKG_MANAGER="pip" RUN_CMD="" # Direct command fi echo "Package manager: $PKG_MANAGER"
Step 4: Determine Lint Command
Purpose: Build the appropriate command to run the linter
JavaScript/TypeScript (ESLint):
# Run ESLint with package manager if [ "$PKG_MANAGER" = "npm" ]; then LINT_CMD="npm run lint" LINT_FIX_CMD="npm run lint -- --fix" elif [ "$PKG_MANAGER" = "yarn" ]; then LINT_CMD="yarn lint" LINT_FIX_CMD="yarn lint --fix" elif [ "$PKG_MANAGER" = "pnpm" ]; then LINT_CMD="pnpm run lint" LINT_FIX_CMD="pnpm run lint --fix" else # Direct ESLint command LINT_CMD="npx eslint ." LINT_FIX_CMD="npx eslint . --fix" fi echo "Lint command: $LINT_CMD" echo "Auto-fix command: $LINT_FIX_CMD"
Python (Ruff):
# Run Ruff with package manager if [ "$PKG_MANAGER" = "poetry" ]; then LINT_CMD="poetry run ruff check ." LINT_FIX_CMD="poetry run ruff check . --fix" else # Direct Ruff command LINT_CMD="ruff check ." LINT_FIX_CMD="ruff check . --fix" fi echo "Lint command: $LINT_CMD" echo "Auto-fix command: $LINT_FIX_CMD"
Step 5: Run Linting
Purpose: Execute linter to check code quality
Implementation:
# Run linter echo "" echo "🔍 Running linter..." echo "" $LINT_CMD # Capture exit code LINT_EXIT_CODE=$? if [ $LINT_EXIT_CODE -eq 0 ]; then echo "" echo "✅ No linting errors found!" else echo "" echo "❌ Linting errors found (exit code: $LINT_EXIT_CODE)" fi
Linting Output Categories:
| Category | Description |
|---|---|
| Syntax Errors | Invalid syntax that prevents code from running |
| Style Violations | Code doesn't follow style guidelines |
| Potential Bugs | Code patterns that may cause bugs |
| Deprecation Warnings | Use of deprecated features |
| Type Errors (TypeScript) | Type mismatches or missing type definitions |
| Missing Docstrings | Functions/classes without documentation (industry best practice) |
Step 6: Apply Auto-Fix
Purpose: Use linter's auto-fix capability to resolve fixable errors
Implementation:
if [ $LINT_EXIT_CODE -ne 0 ]; then read -p "Apply auto-fix for linting errors? (y/n): " APPLY_FIX if [ "$APPLY_FIX" = "y" ]; then echo "" echo "🔧 Applying auto-fix..." echo "" # Run auto-fix command $LINT_FIX_CMD # Capture exit code FIX_EXIT_CODE=$? if [ $FIX_EXIT_CODE -eq 0 ]; then echo "" echo "✅ Auto-fix applied successfully!" else echo "" echo "⚠️ Auto-fix completed with errors (exit code: $FIX_EXIT_CODE)" echo "Some errors may require manual fixing." fi # Re-run linting to check remaining errors echo "" echo "🔍 Re-running linter to check remaining errors..." echo "" $LINT_CMD fi fi
Auto-Fix Capabilities:
| Linter | Auto-Fix | What It Fixes |
|---|---|---|
| ESLint | | Style violations, unused variables, simple syntax issues |
| Prettier | | Formatting, indentation, quotes |
| Ruff | | Style violations, unused imports, simple refactorings |
| Black | Direct | Formatting, indentation, line length |
Step 7: Display Error Summary
Purpose: Show user which files and lines have linting errors
Implementation:
# Get linting errors (language-specific) if [ "$LINTER" = "eslint" ]; then # ESLint JSON output $LINT_CMD --format json > /tmp/lint-results.json cat /tmp/lint-results.json | jq -r '.[] | "\(.filePath):\(.message) at line \(.line)"' elif [ "$LINTER" = "ruff" ]; then # Ruff output $LINT_CMD --output-format concise fi # Summary echo "" echo "📊 Linting Error Summary:" echo "" echo "Total errors: <count>" echo "Files affected: <count>" echo "Most common error: <error type>"
Step 8: Guide Error Resolution
Purpose: Provide step-by-step guidance for fixing common linting errors
Common Error Categories:
JavaScript/TypeScript Errors:
| Error Type | Description | Fix |
|---|---|---|
| Unused variables | Variables defined but never used | Remove or use variable |
| Missing semicolons | Missing semicolons in JavaScript | Add semicolons |
| Unused imports | Imports not used in file | Remove import |
| React hooks violations | Incorrect React hook usage | Fix hook dependencies/rules |
| No-unused-vars | Variables declared but not used | Remove or use variable |
| prefer-const | Variables could be const | Change to |
Python Errors:
| Error Type | Description | Fix |
|---|---|---|
| F401 | Unused imports | Remove unused import |
| F841 | Unused variables | Remove or use variable |
| E501 | Line too long | Break long lines |
| W291 | Trailing whitespace | Remove trailing spaces |
| E722 | Missing docstring | Add function docstring |
| F821 | Redefinition of variable | Rename variable |
Resolution Guidance Template:
For each error found: 1. **File: <file>** Line: <line number> Error: <error message> 2. **Recommended Fix:** <step-by-step fix instructions> 3. **Example:** ```<language> # Before (incorrect) <code> # After (corrected) <code>
- Apply Fix: <action to take>
### Step 9: Re-Verify After Manual Fixes **Purpose**: Re-run linting after user manually fixes errors **Implementation**: ```bash echo "" read -p "Have you manually fixed the errors? Re-run linting? (y/n): " RE_RUN if [ "$RE_RUN" = "y" ]; then echo "" echo "🔍 Re-running linter..." echo "" $LINT_CMD if [ $? -eq 0 ]; then echo "" echo "✅ All linting errors resolved!" else echo "" echo "⚠️ Some errors remain. Please review and fix." fi fi
Step 10: Commit Linting Fixes
Purpose: Commit linting fixes as separate commit (optional)
Implementation:
# Check if there are changes to commit GIT_STATUS=$(git status --porcelain) if [ -n "$GIT_STATUS" ]; then echo "" read -p "Commit linting fixes? (y/n): " COMMIT_FIXES if [ "$COMMIT_FIXES" = "y" ]; then git add . git commit -m "Fix linting errors" echo "" echo "✅ Linting fixes committed" fi else echo "" echo "No changes to commit." fi
Commit Message Options:
| Context | Commit Message |
|---|---|
| General fixes | |
| ESLint fixes | |
| Ruff fixes | |
| Specific fixes | |
Step 11: Check Docstrings (Industry Best Practice)
Purpose: Verify all public functions, classes, and methods have proper docstrings
Implementation:
echo "" echo "📝 Checking docstrings..." echo "" # Check for undocumented functions/classes UNDOC_COUNT=0 MISSING_DOCSTRINGS=() for file in $(git diff --name-only HEAD~1..HEAD); do case "$file" in *.py) UNDOC=$(grep -c 'def ' "$file" - $(grep -c '"""' "$file")) FUNCTIONS=$(grep -c 'def ' "$file") ;; *.java) UNDOC=$(grep -c 'public.*(' "$file" - $(grep -c '/\*\*' "$file")) METHODS=$(grep -c 'public.*(' "$file") ;; *.ts|tsx) UNDOC=$(grep -c 'function' "$file" - $(grep -c '/\*\*' "$file")) FUNCTIONS=$(grep -c 'function ' "$file") ;; *.cs|csx) UNDOC=$(grep -c 'public.*(' "$file" - $(grep -c '///' "$file")) METHODS=$(grep -c 'public.*(' "$file") ;; esac if [[ $UNDOC -gt 0 ]]; then UNDOC_COUNT=$((UNDOC_COUNT + UNDOC)) MISSING_DOCSTRINGS+=("$file") fi done if [[ $UNDOC_COUNT -gt 0 ]]; then echo "" echo "❌ Found $UNDOC_COUNT undocumented items:" for item in "${MISSING_DOCSTRINGS[@]}"; do echo " - $item" done echo "" echo "💡 Consider using 'docstring-generator' skill to add missing documentation" else echo "" echo "✅ All functions/classes have docstrings!" fi
Docstring Check Results:
- Count undocumented items
- List files with missing docstrings
- Suggest using docstring-generator skill
- Check docstring format compliance (PEP 257, Javadoc, JSDoc, XML docs)
Language-Specific Docstring Standards:
| Language | Docstring Format | Key Tags/Sections |
|---|---|---|
| Python | PEP 257 (Google, NumPy, Sphinx) | Args, Returns, Raises |
| Java | Javadoc | @param, @return, @throws, @see |
| TypeScript | JSDoc/TSDoc | @param, @returns, @throws, @type |
| C# | XML Documentation Comments | <summary>, <param>, <returns>, <exception> |
Language-Specific Linter Configuration
JavaScript/TypeScript
ESLint Configuration Files (in priority order):
/eslint.config.ts
/eslint.config.mjs
(ESLint 9+)eslint.config.js.eslintrc.json.eslintrc.js.eslintrc.yaml
(inpackage.json
field)eslintConfig
Common ESLint Rules:
: Detect unused variablesno-unused-vars
: Detect console statementsno-console
: Suggest usingprefer-const
overconstlet
: Enforceeqeqeq
instead of=====
: Requireno-var
/let
instead ofconstvar- React hooks rules: Enforce correct React hook usage
Python
Ruff Configuration Files:
(inpyproject.toml
section)[tool.ruff].ruff.tomlruff.toml
Common Ruff Rules:
: Unused importsF401
: Unused variablesF841
: Line too long (> 88 characters)E501
: Trailing whitespaceW291
: Missing docstringsE722
: Import orderingI001
Best Practices
- Linting Before Commit: Always run linting before committing code
- Auto-Fix First: Apply auto-fix before manual fixes
- Incremental Fixes: Fix errors in batches, re-run linting between batches
- Clear Commit Messages: Describe what was fixed in commit message
- Fix Linting Errors: Don't disable rules as a workaround
- Consistent Style: Follow language and project style guidelines
- Editor Configuration: Configure editor to run linting on save
- CI/CD Integration: Include linting in automated pipelines
- Pre-Commit Hooks: Use Husky or pre-commit to enforce linting
Common Issues
Linter Not Found
Issue: Linter is not installed or not found in PATH
Solution:
# JavaScript/TypeScript: Install ESLint npm install --save-dev eslint # Python: Install Ruff pip install ruff # Or with Poetry poetry add --group dev ruff
Configuration File Not Found
Issue: Linter cannot find configuration file
Solution:
# Verify config file exists ls -la | grep -E "(eslint|ruff|pylint)" # Create default config if missing # ESLint cat > .eslintrc.json <<EOF { "extends": "eslint:recommended", "rules": {} } EOF # Ruff cat > pyproject.toml <<EOF [tool.ruff] line-length = 88 target-version = "py311" EOF
Too Many Errors
Issue: Large number of linting errors at once
Solution:
- Focus on one category at a time (syntax, style, etc.)
- Fix errors incrementally
- Re-run linting after each fix batch
- Use editor integration to fix errors as you go
Auto-Fix Doesn't Work
Issue:
--fix flag doesn't resolve errors
Solution:
- Some errors require manual intervention (semantic issues)
- Review error messages for guidance
- Check if linter supports auto-fix for that rule
- Manually fix and re-run linting
Git Changes Conflict
Issue: Linting fixes conflict with other uncommitted changes
Solution:
# Stage only linting fixes git add <files-with-linting-fixes> # Commit linting fixes separately git commit -m "Fix linting errors"
Troubleshooting Checklist
Before linting:
- Language is detected correctly
- Linter is installed
- Configuration file exists
- Package manager is detected
- Working directory is clean (or changes are staged)
After linting:
- Linting command executed successfully
- Errors are categorized and displayed
- Auto-fix is attempted (if errors found)
- User receives guidance for manual fixes
- Linting is re-run after fixes
After committing fixes:
- Linting fixes are committed
- Commit message is clear
- No unintended changes are included
- Working tree is clean (or ready for next step)
Related Commands
# JavaScript/TypeScript npm run lint # Run linter npm run lint -- --fix # Run linter with auto-fix npm install --save-dev eslint # Install ESLint npx eslint . # Run ESLint directly # Python poetry run ruff check . # Run Ruff with Poetry poetry run ruff check . --fix # Run Ruff with auto-fix ruff check . # Run Ruff directly pip install ruff # Install Ruff # Git git add . # Stage changes git commit -m "Fix linting" # Commit changes git status # Check git status
Relevant Skills
Language-specific linting skills that use this framework:
: Python-specific Ruff linting guidancepython-ruff-linter- (Future)
: JavaScript/TypeScript-specific ESLint guidancejavascript-eslint-linter
Supporting framework skills:
: For running linting before PR creationpr-creation-workflow
: For ensuring code quality before testingtest-generator-framework