Claude-skill-registry linting-workflow

Generic linting workflow for multiple languages with auto-fix and error resolution guidance

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
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"
manifest: skills/data/linting-workflow/SKILL.md
source content

What I do

I provide a generic linting workflow that can be adapted for multiple languages:

  1. Detect Language: Automatically detect project language (JavaScript/TypeScript, Python, etc.)
  2. Detect Linter: Identify and configure appropriate linter (ESLint, Ruff, etc.)
  3. Detect Package Manager: Determine package manager for running linter commands
  4. Run Linting: Execute linter with appropriate command
  5. Apply Auto-Fix: Use linter's auto-fix capability when available
  6. Guide Error Resolution: Provide step-by-step guidance for fixing linting errors
  7. Verify Fixes: Re-run linting to ensure all errors are resolved
  8. 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:

IndicatorLanguageLinter
package.json
+
tsconfig.json
TypeScriptESLint
package.json
JavaScriptESLint
pyproject.toml
or
requirements.txt
PythonRuff
go.mod
Gogolint, golangci-lint
Gemfile
RubyRuboCop

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:

LanguageManagerDetectionRun Command
JavaScript/TypeScriptnpm
package-lock.json
exists
npm run <script>
JavaScript/TypeScriptyarn
yarn.lock
exists
yarn <script>
JavaScript/TypeScriptpnpm
pnpm-lock.yaml
exists
pnpm run <script>
PythonPoetry
pyproject.toml
exists
poetry run <script>
Pythonpip
requirements.txt
exists
python -m <script>
or
<script>

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:

CategoryDescription
Syntax ErrorsInvalid syntax that prevents code from running
Style ViolationsCode doesn't follow style guidelines
Potential BugsCode patterns that may cause bugs
Deprecation WarningsUse of deprecated features
Type Errors (TypeScript)Type mismatches or missing type definitions
Missing DocstringsFunctions/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:

LinterAuto-FixWhat It Fixes
ESLint
--fix
Style violations, unused variables, simple syntax issues
Prettier
--write
Formatting, indentation, quotes
Ruff
--fix
Style violations, unused imports, simple refactorings
BlackDirectFormatting, 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 TypeDescriptionFix
Unused variablesVariables defined but never usedRemove or use variable
Missing semicolonsMissing semicolons in JavaScriptAdd semicolons
Unused importsImports not used in fileRemove import
React hooks violationsIncorrect React hook usageFix hook dependencies/rules
No-unused-varsVariables declared but not usedRemove or use variable
prefer-constVariables could be constChange
let
to
const

Python Errors:

Error TypeDescriptionFix
F401Unused importsRemove unused import
F841Unused variablesRemove or use variable
E501Line too longBreak long lines
W291Trailing whitespaceRemove trailing spaces
E722Missing docstringAdd function docstring
F821Redefinition of variableRename 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>
  1. 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:

ContextCommit Message
General fixes
Fix linting errors
ESLint fixes
Fix ESLint errors
Ruff fixes
Fix Ruff linting errors
Specific fixes
Fix <error type> errors

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:

LanguageDocstring FormatKey Tags/Sections
PythonPEP 257 (Google, NumPy, Sphinx)Args, Returns, Raises
JavaJavadoc@param, @return, @throws, @see
TypeScriptJSDoc/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):

  1. eslint.config.ts
    /
    eslint.config.mjs
    /
    eslint.config.js
    (ESLint 9+)
  2. .eslintrc.json
  3. .eslintrc.js
  4. .eslintrc.yaml
  5. package.json
    (in
    eslintConfig
    field)

Common ESLint Rules:

  • no-unused-vars
    : Detect unused variables
  • no-console
    : Detect console statements
  • prefer-const
    : Suggest using
    const
    over
    let
  • eqeqeq
    : Enforce
    ===
    instead of
    ==
  • no-var
    : Require
    let
    /
    const
    instead of
    var
  • React hooks rules: Enforce correct React hook usage

Python

Ruff Configuration Files:

  1. pyproject.toml
    (in
    [tool.ruff]
    section)
  2. .ruff.toml
  3. ruff.toml

Common Ruff Rules:

  • F401
    : Unused imports
  • F841
    : Unused variables
  • E501
    : Line too long (> 88 characters)
  • W291
    : Trailing whitespace
  • E722
    : Missing docstrings
  • I001
    : Import ordering

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-ruff-linter
    : Python-specific Ruff linting guidance
  • (Future)
    javascript-eslint-linter
    : JavaScript/TypeScript-specific ESLint guidance

Supporting framework skills:

  • pr-creation-workflow
    : For running linting before PR creation
  • test-generator-framework
    : For ensuring code quality before testing