AS
AgSkills.dev
MARKETPLACE

shellcheck-configuration

Master ShellCheck static analysis configuration and usage for shell script quality. Use when setting up linting infrastructure, fixing code issues, or ensuring script portability.

27.0k
2.9k

Preview

SKILL.md
name
shellcheck-configuration
description
Master ShellCheck static analysis configuration and usage for shell script quality. Use when setting up linting infrastructure, fixing code issues, or ensuring script portability.

ShellCheck Configuration and Static Analysis

Comprehensive guidance for configuring and using ShellCheck to improve shell script quality, catch common pitfalls, and enforce best practices through static code analysis.

When to Use This Skill

  • Setting up linting for shell scripts in CI/CD pipelines
  • Analyzing existing shell scripts for issues
  • Understanding ShellCheck error codes and warnings
  • Configuring ShellCheck for specific project requirements
  • Integrating ShellCheck into development workflows
  • Suppressing false positives and configuring rule sets
  • Enforcing consistent code quality standards
  • Migrating scripts to meet quality gates

ShellCheck Fundamentals

What is ShellCheck?

ShellCheck is a static analysis tool that analyzes shell scripts and detects problematic patterns. It supports:

  • Bash, sh, dash, ksh, and other POSIX shells
  • Over 100 different warnings and errors
  • Configuration for target shell and flags
  • Integration with editors and CI/CD systems

Installation

# macOS with Homebrew brew install shellcheck # Ubuntu/Debian apt-get install shellcheck # From source git clone https://github.com/koalaman/shellcheck.git cd shellcheck make build make install # Verify installation shellcheck --version

Configuration Files

.shellcheckrc (Project Level)

Create .shellcheckrc in your project root:

# Specify target shell
shell=bash

# Enable optional checks
enable=avoid-nullary-conditions
enable=require-variable-braces

# Disable specific warnings
disable=SC1091
disable=SC2086

Environment Variables

# Set default shell target export SHELLCHECK_SHELL=bash # Enable strict mode export SHELLCHECK_STRICT=true # Specify configuration file location export SHELLCHECK_CONFIG=~/.shellcheckrc

Common ShellCheck Error Codes

SC1000-1099: Parser Errors

# SC1004: Backslash continuation not followed by newline echo hello\ world # Error - needs line continuation # SC1008: Invalid data for operator `==' if [[ $var = "value" ]]; then # Space before == true fi

SC2000-2099: Shell Issues

# SC2009: Consider using pgrep or pidof instead of grep|grep ps aux | grep -v grep | grep myprocess # Use pgrep instead # SC2012: Use `ls` only for viewing. Use `find` for reliable output for file in $(ls -la) # Better: use find or globbing # SC2015: Avoid using && and || instead of if-then-else [[ -f "$file" ]] && echo "found" || echo "not found" # Less clear # SC2016: Expressions don't expand in single quotes echo '$VAR' # Literal $VAR, not variable expansion # SC2026: This word is non-standard. Set POSIXLY_CORRECT # when using with scripts for other shells

SC2100-2199: Quoting Issues

# SC2086: Double quote to prevent globbing and word splitting for i in $list; do # Should be: for i in $list or for i in "$list" echo "$i" done # SC2115: Literal tilde in path not expanded. Use $HOME instead ~/.bashrc # In strings, use "$HOME/.bashrc" # SC2181: Check exit code directly with `if`, not indirectly in a list some_command if [ $? -eq 0 ]; then # Better: if some_command; then # SC2206: Quote to prevent word splitting or set IFS array=( $items ) # Should use: array=( $items )

SC3000-3999: POSIX Compliance Issues

# SC3010: In POSIX sh, use 'case' instead of 'cond && foo' [[ $var == "value" ]] && do_something # Not POSIX # SC3043: In POSIX sh, use 'local' is undefined function my_func() { local var=value # Not POSIX in some shells }

Practical Configuration Examples

Minimal Configuration (Strict POSIX)

#!/bin/bash # Configure for maximum portability shellcheck \ --shell=sh \ --external-sources \ --check-sourced \ script.sh

Development Configuration (Bash with Relaxed Rules)

#!/bin/bash # Configure for Bash development shellcheck \ --shell=bash \ --exclude=SC1091,SC2119 \ --enable=all \ script.sh

CI/CD Integration Configuration

#!/bin/bash set -Eeuo pipefail # Analyze all shell scripts and fail on issues find . -type f -name "*.sh" | while read -r script; do echo "Checking: $script" shellcheck \ --shell=bash \ --format=gcc \ --exclude=SC1091 \ "$script" || exit 1 done

.shellcheckrc for Project

# Shell dialect to analyze against
shell=bash

# Enable optional checks
enable=avoid-nullary-conditions,require-variable-braces,check-unassigned-uppercase

# Disable specific warnings
# SC1091: Not following sourced files (many false positives)
disable=SC1091

# SC2119: Use function_name instead of function_name -- (arguments)
disable=SC2119

# External files to source for context
external-sources=true

Integration Patterns

Pre-commit Hook Configuration

#!/bin/bash # .git/hooks/pre-commit #!/bin/bash set -e # Find all shell scripts changed in this commit git diff --cached --name-only | grep '\.sh$' | while read -r script; do echo "Linting: $script" if ! shellcheck "$script"; then echo "ShellCheck failed on $script" exit 1 fi done

GitHub Actions Workflow

name: ShellCheck on: [push, pull_request] jobs: shellcheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run ShellCheck run: | sudo apt-get install shellcheck find . -type f -name "*.sh" -exec shellcheck {} \;

GitLab CI Pipeline

shellcheck: stage: lint image: koalaman/shellcheck-alpine script: - find . -type f -name "*.sh" -exec shellcheck {} \; allow_failure: false

Handling ShellCheck Violations

Suppressing Specific Warnings

#!/bin/bash # Disable warning for entire line # shellcheck disable=SC2086 for file in $(ls -la); do echo "$file" done # Disable for entire script # shellcheck disable=SC1091,SC2119 # Disable multiple warnings (format varies) command_that_fails() { # shellcheck disable=SC2015 [ -f "$1" ] && echo "found" || echo "not found" } # Disable specific check for source directive # shellcheck source=./helper.sh source helper.sh

Common Violations and Fixes

SC2086: Double quote to prevent word splitting

# Problem for i in $list; do done # Solution for i in $list; do done # If $list is already quoted, or for i in "${list[@]}"; do done # If list is an array

SC2181: Check exit code directly

# Problem some_command if [ $? -eq 0 ]; then echo "success" fi # Solution if some_command; then echo "success" fi

SC2015: Use if-then instead of && ||

# Problem [ -f "$file" ] && echo "exists" || echo "not found" # Solution - clearer intent if [ -f "$file" ]; then echo "exists" else echo "not found" fi

SC2016: Expressions don't expand in single quotes

# Problem echo 'Variable value: $VAR' # Solution echo "Variable value: $VAR"

SC2009: Use pgrep instead of grep

# Problem ps aux | grep -v grep | grep myprocess # Solution pgrep -f myprocess

Performance Optimization

Checking Multiple Files

#!/bin/bash # Sequential checking for script in *.sh; do shellcheck "$script" done # Parallel checking (faster) find . -name "*.sh" -print0 | \ xargs -0 -P 4 -n 1 shellcheck

Caching Results

#!/bin/bash CACHE_DIR=".shellcheck_cache" mkdir -p "$CACHE_DIR" check_script() { local script="$1" local hash local cache_file hash=$(sha256sum "$script" | cut -d' ' -f1) cache_file="$CACHE_DIR/$hash" if [[ ! -f "$cache_file" ]]; then if shellcheck "$script" > "$cache_file" 2>&1; then touch "$cache_file.ok" else return 1 fi fi [[ -f "$cache_file.ok" ]] } find . -name "*.sh" | while read -r script; do check_script "$script" || exit 1 done

Output Formats

Default Format

shellcheck script.sh # Output: # script.sh:1:3: warning: foo is referenced but not assigned. [SC2154]

GCC Format (for CI/CD)

shellcheck --format=gcc script.sh # Output: # script.sh:1:3: warning: foo is referenced but not assigned.

JSON Format (for parsing)

shellcheck --format=json script.sh # Output: # [{"file": "script.sh", "line": 1, "column": 3, "level": "warning", "code": 2154, "message": "..."}]

Quiet Format

shellcheck --format=quiet script.sh # Returns non-zero if issues found, no output otherwise

Best Practices

  1. Run ShellCheck in CI/CD - Catch issues before merging
  2. Configure for your target shell - Don't analyze bash as sh
  3. Document exclusions - Explain why violations are suppressed
  4. Address violations - Don't just disable warnings
  5. Enable strict mode - Use --enable=all with careful exclusions
  6. Update regularly - Keep ShellCheck current for new checks
  7. Use pre-commit hooks - Catch issues locally before pushing
  8. Integrate with editors - Get real-time feedback during development

Resources

GitHub Repository
wshobson/agents
Stars
27,021
Forks
2,972
Open Repository
Install Skill
Download ZIP1 files