Agent Skills: Run Linters

Run linters, lint the code, check code style, or fix linting issues. Use when the user wants to lint, run linters, check code quality, verify code style, fix linting errors, or run code checks after completing code modifications.

UncategorizedID: Cloud-Officer/claude-code-plugin-dev/run-linters

Install this agent skill to your local

pnpm dlx add-skill https://github.com/Cloud-Officer/claude-code-plugin-dev/tree/HEAD/skills/run-linters

Skill Files

Browse the full folder contents for run-linters.

Download Skill

Loading file tree…

skills/run-linters/SKILL.md

Skill Metadata

Name
run-linters
Description
Run linters, lint the code, check code style, or fix linting issues. Use when the user wants to lint, run linters, check code quality, verify code style, fix linting errors, or run code checks after completing code modifications.

Run Linters

Execute linters after code changes are complete to ensure code quality and consistency.

Arguments

An optional path or glob may be passed to scope the run. Validate it before any use: a scope not matching ^[A-Za-z0-9._*][A-Za-z0-9._/*-]*$ is refused and reported to the user, never passed to any command. Two mechanisms carry the fence, each against its own threat: the anchored first character keeps - out of position one, and the class body keeps out $, backtick, quote, space and semicolon, so nothing the shell could expand, split or chain survives validation — but a character class cannot stop a linter's own option parser, which is why every sink also passes the scope after an end-of-options separator. When present, both the linting and the fix loop are restricted to files under it, passed as one quoted argument after -- to each linter's own path argument (npx eslint -- "<path>", rubocop -- "<path>", ruff check -- "<path>", golangci-lint run -- "<path>/...", and likewise per tool); the quoting keeps an admitted * a literal argument for the linter's own globbing rather than the shell's. The linters wrapper, which takes no path, is skipped in favour of the per-tool commands when a scope is given. When absent, the whole repository is linted as before.

When to Use

  • After completing a set of code changes (not after each small edit)
  • Before creating a commit or PR
  • When asked to verify code quality

Step 0: Check for the linters wrapper

The linters wrapper is the preferred path, but it is not installed everywhere. Check for it first:

which linters

If linters is found: continue to Step 1 unchanged.

If linters is NOT found: tell the user plainly that the linters wrapper is not installed on this machine and that you are falling back to the repository's own linters. Then detect which linters the repository configures and run them directly:

| Config file present | Linter to run | | --- | --- | | .eslintrc*, eslint.config.* | npx eslint . | | .rubocop.yml | bundle exec rubocop (or rubocop) | | ruff.toml, .ruff.toml, pyproject.toml (with tool.ruff) | ruff check . | | .golangci.yml, .golangci.yaml | golangci-lint run | | Cargo.toml | cargo clippy | | .markdownlint* | npx markdownlint-cli2 . | | .yamllint* | yamllint . | | *.sh files | shellcheck on the shell scripts |

Prefer the project's own runner whenever one exists — an npm run lint script in package.json, a rake lint task, or a make lint target that already wraps the linter — over invoking the binary directly. Use the package manager the repository already uses (npm, yarn, or pnpm).

If neither the linters wrapper nor any recognised linter config is found, stop and tell the user exactly which config files you searched for. Do NOT claim the code is lint-clean.

Step 1: Run Linters

Execute the linters command which auto-detects active linters in the current repository and runs them with proper configurations:

linters

Step 2: Analyze Results

An issue is any diagnostic the linter emits at severity error or warning. Diagnostics at note, info, style or convention are listed to the user and not fixed. A non-zero exit with no diagnostic lines is a failed run, not an issue.

  • If no issues: Report success and proceed
  • If issues found: Continue to Step 3

Step 3: Fix Issues

For each issue reported:

  1. Read the affected file
  2. Understand the linting error
  3. Fix the issue in the source code using Edit tool
  4. Re-run linters to verify the fix

Repeat until all issues are resolved.

Important Rules

  • Do NOT run after every small change - wait until a logical set of changes is complete
  • Fix all issues before reporting completion
  • NEVER report lint success without a linter having actually run and produced output - a missing command, a failed invocation, or a run you skipped is not a pass
  • NEVER modify linter configuration files to suppress or ignore issues
  • NEVER add inline disable comments (e.g., // eslint-disable, # noqa, // nolint) to bypass issues
  • Always fix the actual code, not the linter rules
  • If an issue seems impossible to fix properly, ask the user for guidance

Forbidden Files - NEVER Modify

The following configuration files must NEVER be edited to work around linting issues:

JavaScript/TypeScript:

  • .eslintrc, .eslintrc.js, .eslintrc.json, .eslintrc.yml
  • .prettierrc, .prettierrc.js, .prettierrc.json
  • eslint.config.js, eslint.config.mjs
  • tsconfig.json (for strict mode or type checking options)

Python:

  • .flake8, setup.cfg (flake8 section)
  • pyproject.toml (tool.flake8, tool.pylint, tool.ruff sections)
  • .pylintrc, pylintrc
  • ruff.toml, .ruff.toml
  • mypy.ini, .mypy.ini

Ruby:

  • .rubocop.yml, .rubocop_todo.yml

Go:

  • .golangci.yml, .golangci.yaml

Rust:

  • clippy.toml, .clippy.toml
  • rustfmt.toml, .rustfmt.toml

Markdown:

  • .markdownlint.json, .markdownlint.yaml, .markdownlint.yml
  • .markdownlintrc

General:

  • .editorconfig
  • Any file that defines linting rules or ignores

Forbidden Patterns - NEVER Use

Do NOT add these patterns to bypass linting:

# JavaScript/TypeScript
/* eslint-disable */
// eslint-disable-line
// eslint-disable-next-line
/* prettier-ignore */
// @ts-ignore
// @ts-nocheck

# Python
# noqa
# type: ignore
# pylint: disable
# ruff: noqa

# Go
//nolint
//nolint:all

# Ruby
# rubocop:disable

# Rust
#[allow(...)]
#![allow(...)]

If you encounter an issue that seems unfixable, explain the problem to the user and ask how they want to proceed.

Shell Script Linting Rules (SL0001, SL0002)

When fixing shell script lint errors (e.g., from shellcheck or custom shell linters), apply these rules:

SL0001: Variables must use braces

Always wrap shell variables in ${} braces. This prevents ambiguity and word-splitting bugs.

# Bad
echo "$HOME/.local/bin:$PATH"
if [ "$CURRENT_BRANCH" != "$MASTER_BRANCH" ]; then

# Good
echo "${HOME}/.local/bin:${PATH}"
if [ "${CURRENT_BRANCH}" != "${MASTER_BRANCH}" ]; then

SL0002: Use == instead of = for string comparison — inside [[ ]] only

In [[ ]] test expressions, use == for string equality, not =.

Inside single-bracket [ ], keep =. == is not POSIX there: shellcheck reports SC3014 and dash fails at runtime with test: ==: unexpected operator. Never rewrite = to == in a #!/bin/sh script.

# Bad
if [[ "${CONFIGURATION}" = "Debug" ]]; then

# Good
if [[ "${CONFIGURATION}" == "Debug" ]]; then

# Also correct - leave as is
if [ "${CONFIGURATION}" = "Debug" ]; then

General Shell Script Fixes

  • Quote all variable expansions"${VAR}" not $VAR
  • Use [[ over [ when possible — safer, supports &&, ||, pattern matching
  • Use $(command) over backticks`command` is deprecated