Master ShellCheck static analysis configuration and usage for shell script quality. Use when setting up linting infrastructure, fixing code issues, or ensuring script portability.
npx mdskills install sickn33/shellcheck-configuration@sickn33? Sign in with GitHub to claim this listing.Comprehensive ShellCheck reference with excellent examples, error codes, and integration patterns
1---2name: shellcheck-configuration3description: Master ShellCheck static analysis configuration and usage for shell script quality. Use when setting up linting infrastructure, fixing code issues, or ensuring script portability.4---56# ShellCheck Configuration and Static Analysis78Comprehensive guidance for configuring and using ShellCheck to improve shell script quality, catch common pitfalls, and enforce best practices through static code analysis.910## Do not use this skill when1112- The task is unrelated to shellcheck configuration and static analysis13- You need a different domain or tool outside this scope1415## Instructions1617- Clarify goals, constraints, and required inputs.18- Apply relevant best practices and validate outcomes.19- Provide actionable steps and verification.20- If detailed examples are required, open `resources/implementation-playbook.md`.2122## Use this skill when2324- Setting up linting for shell scripts in CI/CD pipelines25- Analyzing existing shell scripts for issues26- Understanding ShellCheck error codes and warnings27- Configuring ShellCheck for specific project requirements28- Integrating ShellCheck into development workflows29- Suppressing false positives and configuring rule sets30- Enforcing consistent code quality standards31- Migrating scripts to meet quality gates3233## ShellCheck Fundamentals3435### What is ShellCheck?3637ShellCheck is a static analysis tool that analyzes shell scripts and detects problematic patterns. It supports:38- Bash, sh, dash, ksh, and other POSIX shells39- Over 100 different warnings and errors40- Configuration for target shell and flags41- Integration with editors and CI/CD systems4243### Installation4445```bash46# macOS with Homebrew47brew install shellcheck4849# Ubuntu/Debian50apt-get install shellcheck5152# From source53git clone https://github.com/koalaman/shellcheck.git54cd shellcheck55make build56make install5758# Verify installation59shellcheck --version60```6162## Configuration Files6364### .shellcheckrc (Project Level)6566Create `.shellcheckrc` in your project root:6768```69# Specify target shell70shell=bash7172# Enable optional checks73enable=avoid-nullary-conditions74enable=require-variable-braces7576# Disable specific warnings77disable=SC109178disable=SC208679```8081### Environment Variables8283```bash84# Set default shell target85export SHELLCHECK_SHELL=bash8687# Enable strict mode88export SHELLCHECK_STRICT=true8990# Specify configuration file location91export SHELLCHECK_CONFIG=~/.shellcheckrc92```9394## Common ShellCheck Error Codes9596### SC1000-1099: Parser Errors97```bash98# SC1004: Backslash continuation not followed by newline99echo hello\100world # Error - needs line continuation101102# SC1008: Invalid data for operator `=='103if [[ $var = "value" ]]; then # Space before ==104 true105fi106```107108### SC2000-2099: Shell Issues109110```bash111# SC2009: Consider using pgrep or pidof instead of grep|grep112ps aux | grep -v grep | grep myprocess # Use pgrep instead113114# SC2012: Use `ls` only for viewing. Use `find` for reliable output115for file in $(ls -la) # Better: use find or globbing116117# SC2015: Avoid using && and || instead of if-then-else118[[ -f "$file" ]] && echo "found" || echo "not found" # Less clear119120# SC2016: Expressions don't expand in single quotes121echo '$VAR' # Literal $VAR, not variable expansion122123# SC2026: This word is non-standard. Set POSIXLY_CORRECT124# when using with scripts for other shells125```126127### SC2100-2199: Quoting Issues128129```bash130# SC2086: Double quote to prevent globbing and word splitting131for i in $list; do # Should be: for i in $list or for i in "$list"132 echo "$i"133done134135# SC2115: Literal tilde in path not expanded. Use $HOME instead136~/.bashrc # In strings, use "$HOME/.bashrc"137138# SC2181: Check exit code directly with `if`, not indirectly in a list139some_command140if [ $? -eq 0 ]; then # Better: if some_command; then141142# SC2206: Quote to prevent word splitting or set IFS143array=( $items ) # Should use: array=( $items )144```145146### SC3000-3999: POSIX Compliance Issues147148```bash149# SC3010: In POSIX sh, use 'case' instead of 'cond && foo'150[[ $var == "value" ]] && do_something # Not POSIX151152# SC3043: In POSIX sh, use 'local' is undefined153function my_func() {154 local var=value # Not POSIX in some shells155}156```157158## Practical Configuration Examples159160### Minimal Configuration (Strict POSIX)161162```bash163#!/bin/bash164# Configure for maximum portability165166shellcheck \167 --shell=sh \168 --external-sources \169 --check-sourced \170 script.sh171```172173### Development Configuration (Bash with Relaxed Rules)174175```bash176#!/bin/bash177# Configure for Bash development178179shellcheck \180 --shell=bash \181 --exclude=SC1091,SC2119 \182 --enable=all \183 script.sh184```185186### CI/CD Integration Configuration187188```bash189#!/bin/bash190set -Eeuo pipefail191192# Analyze all shell scripts and fail on issues193find . -type f -name "*.sh" | while read -r script; do194 echo "Checking: $script"195 shellcheck \196 --shell=bash \197 --format=gcc \198 --exclude=SC1091 \199 "$script" || exit 1200done201```202203### .shellcheckrc for Project204205```206# Shell dialect to analyze against207shell=bash208209# Enable optional checks210enable=avoid-nullary-conditions,require-variable-braces,check-unassigned-uppercase211212# Disable specific warnings213# SC1091: Not following sourced files (many false positives)214disable=SC1091215216# SC2119: Use function_name instead of function_name -- (arguments)217disable=SC2119218219# External files to source for context220external-sources=true221```222223## Integration Patterns224225### Pre-commit Hook Configuration226227```bash228#!/bin/bash229# .git/hooks/pre-commit230231#!/bin/bash232set -e233234# Find all shell scripts changed in this commit235git diff --cached --name-only | grep '\.sh$' | while read -r script; do236 echo "Linting: $script"237238 if ! shellcheck "$script"; then239 echo "ShellCheck failed on $script"240 exit 1241 fi242done243```244245### GitHub Actions Workflow246247```yaml248name: ShellCheck249250on: [push, pull_request]251252jobs:253 shellcheck:254 runs-on: ubuntu-latest255256 steps:257 - uses: actions/checkout@v3258259 - name: Run ShellCheck260 run: |261 sudo apt-get install shellcheck262 find . -type f -name "*.sh" -exec shellcheck {} \;263```264265### GitLab CI Pipeline266267```yaml268shellcheck:269 stage: lint270 image: koalaman/shellcheck-alpine271 script:272 - find . -type f -name "*.sh" -exec shellcheck {} \;273 allow_failure: false274```275276## Handling ShellCheck Violations277278### Suppressing Specific Warnings279280```bash281#!/bin/bash282283# Disable warning for entire line284# shellcheck disable=SC2086285for file in $(ls -la); do286 echo "$file"287done288289# Disable for entire script290# shellcheck disable=SC1091,SC2119291292# Disable multiple warnings (format varies)293command_that_fails() {294 # shellcheck disable=SC2015295 [ -f "$1" ] && echo "found" || echo "not found"296}297298# Disable specific check for source directive299# shellcheck source=./helper.sh300source helper.sh301```302303### Common Violations and Fixes304305#### SC2086: Double quote to prevent word splitting306307```bash308# Problem309for i in $list; do done310311# Solution312for i in $list; do done # If $list is already quoted, or313for i in "${list[@]}"; do done # If list is an array314```315316#### SC2181: Check exit code directly317318```bash319# Problem320some_command321if [ $? -eq 0 ]; then322 echo "success"323fi324325# Solution326if some_command; then327 echo "success"328fi329```330331#### SC2015: Use if-then instead of && ||332333```bash334# Problem335[ -f "$file" ] && echo "exists" || echo "not found"336337# Solution - clearer intent338if [ -f "$file" ]; then339 echo "exists"340else341 echo "not found"342fi343```344345#### SC2016: Expressions don't expand in single quotes346347```bash348# Problem349echo 'Variable value: $VAR'350351# Solution352echo "Variable value: $VAR"353```354355#### SC2009: Use pgrep instead of grep356357```bash358# Problem359ps aux | grep -v grep | grep myprocess360361# Solution362pgrep -f myprocess363```364365## Performance Optimization366367### Checking Multiple Files368369```bash370#!/bin/bash371372# Sequential checking373for script in *.sh; do374 shellcheck "$script"375done376377# Parallel checking (faster)378find . -name "*.sh" -print0 | \379 xargs -0 -P 4 -n 1 shellcheck380```381382### Caching Results383384```bash385#!/bin/bash386387CACHE_DIR=".shellcheck_cache"388mkdir -p "$CACHE_DIR"389390check_script() {391 local script="$1"392 local hash393 local cache_file394395 hash=$(sha256sum "$script" | cut -d' ' -f1)396 cache_file="$CACHE_DIR/$hash"397398 if [[ ! -f "$cache_file" ]]; then399 if shellcheck "$script" > "$cache_file" 2>&1; then400 touch "$cache_file.ok"401 else402 return 1403 fi404 fi405406 [[ -f "$cache_file.ok" ]]407}408409find . -name "*.sh" | while read -r script; do410 check_script "$script" || exit 1411done412```413414## Output Formats415416### Default Format417418```bash419shellcheck script.sh420421# Output:422# script.sh:1:3: warning: foo is referenced but not assigned. [SC2154]423```424425### GCC Format (for CI/CD)426427```bash428shellcheck --format=gcc script.sh429430# Output:431# script.sh:1:3: warning: foo is referenced but not assigned.432```433434### JSON Format (for parsing)435436```bash437shellcheck --format=json script.sh438439# Output:440# [{"file": "script.sh", "line": 1, "column": 3, "level": "warning", "code": 2154, "message": "..."}]441```442443### Quiet Format444445```bash446shellcheck --format=quiet script.sh447448# Returns non-zero if issues found, no output otherwise449```450451## Best Practices4524531. **Run ShellCheck in CI/CD** - Catch issues before merging4542. **Configure for your target shell** - Don't analyze bash as sh4553. **Document exclusions** - Explain why violations are suppressed4564. **Address violations** - Don't just disable warnings4575. **Enable strict mode** - Use `--enable=all` with careful exclusions4586. **Update regularly** - Keep ShellCheck current for new checks4597. **Use pre-commit hooks** - Catch issues locally before pushing4608. **Integrate with editors** - Get real-time feedback during development461462## Resources463464- **ShellCheck GitHub**: https://github.com/koalaman/shellcheck465- **ShellCheck Wiki**: https://www.shellcheck.net/wiki/466- **Error Code Reference**: https://www.shellcheck.net/467
Full transparency — inspect the skill content before installing.