Claude Agent Skill · by Wshobson

Shellcheck Configuration

A solid reference for getting ShellCheck properly configured in your projects. Covers the practical stuff like setting up .shellcheckrc files, integrating with

Install
Terminal · npx
$npx skills add https://github.com/wshobson/agents --skill shellcheck-configuration
Works with Paperclip

How Shellcheck Configuration fits into a Paperclip company.

Shellcheck Configuration drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md450 lines
Expand
---name: shellcheck-configurationdescription: 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 ```bash# macOS with Homebrewbrew install shellcheck # Ubuntu/Debianapt-get install shellcheck # From sourcegit clone https://github.com/koalaman/shellcheck.gitcd shellcheckmake buildmake install # Verify installationshellcheck --version``` ## Configuration Files ### .shellcheckrc (Project Level) Create `.shellcheckrc` in your project root: ```# Specify target shellshell=bash # Enable optional checksenable=avoid-nullary-conditionsenable=require-variable-braces # Disable specific warningsdisable=SC1091disable=SC2086``` ### Environment Variables ```bash# Set default shell targetexport SHELLCHECK_SHELL=bash # Enable strict modeexport SHELLCHECK_STRICT=true # Specify configuration file locationexport SHELLCHECK_CONFIG=~/.shellcheckrc``` ## Common ShellCheck Error Codes ### SC1000-1099: Parser Errors ```bash# SC1004: Backslash continuation not followed by newlineecho hello\world  # Error - needs line continuation # SC1008: Invalid data for operator `=='if [[ $var =  "value" ]]; then  # Space before ==    truefi``` ### SC2000-2099: Shell Issues ```bash# SC2009: Consider using pgrep or pidof instead of grep|grepps aux | grep -v grep | grep myprocess  # Use pgrep instead # SC2012: Use `ls` only for viewing. Use `find` for reliable outputfor 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 quotesecho '$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 ```bash# SC2086: Double quote to prevent globbing and word splittingfor 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 listsome_commandif [ $? -eq 0 ]; then  # Better: if some_command; then # SC2206: Quote to prevent word splitting or set IFSarray=( $items )  # Should use: array=( $items )``` ### SC3000-3999: POSIX Compliance Issues ```bash# SC3010: In POSIX sh, use 'case' instead of 'cond && foo'[[ $var == "value" ]] && do_something  # Not POSIX # SC3043: In POSIX sh, use 'local' is undefinedfunction my_func() {    local var=value  # Not POSIX in some shells}``` ## Practical Configuration Examples ### Minimal Configuration (Strict POSIX) ```bash#!/bin/bash# Configure for maximum portability shellcheck \  --shell=sh \  --external-sources \  --check-sourced \  script.sh``` ### Development Configuration (Bash with Relaxed Rules) ```bash#!/bin/bash# Configure for Bash development shellcheck \  --shell=bash \  --exclude=SC1091,SC2119 \  --enable=all \  script.sh``` ### CI/CD Integration Configuration ```bash#!/bin/bashset -Eeuo pipefail # Analyze all shell scripts and fail on issuesfind . -type f -name "*.sh" | while read -r script; do    echo "Checking: $script"    shellcheck \        --shell=bash \        --format=gcc \        --exclude=SC1091 \        "$script" || exit 1done``` ### .shellcheckrc for Project ```# Shell dialect to analyze againstshell=bash # Enable optional checksenable=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 contextexternal-sources=true``` ## Integration Patterns ### Pre-commit Hook Configuration ```bash#!/bin/bash# .git/hooks/pre-commit #!/bin/bashset -e # Find all shell scripts changed in this commitgit 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    fidone``` ### GitHub Actions Workflow ```yamlname: 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 ```yamlshellcheck:  stage: lint  image: koalaman/shellcheck-alpine  script:    - find . -type f -name "*.sh" -exec shellcheck {} \;  allow_failure: false``` ## Handling ShellCheck Violations ### Suppressing Specific Warnings ```bash#!/bin/bash # Disable warning for entire line# shellcheck disable=SC2086for 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.shsource helper.sh``` ### Common Violations and Fixes #### SC2086: Double quote to prevent word splitting ```bash# Problemfor i in $list; do done # Solutionfor i in $list; do done  # If $list is already quoted, orfor i in "${list[@]}"; do done  # If list is an array``` #### SC2181: Check exit code directly ```bash# Problemsome_commandif [ $? -eq 0 ]; then    echo "success"fi # Solutionif some_command; then    echo "success"fi``` #### SC2015: Use if-then instead of && || ```bash# Problem[ -f "$file" ] && echo "exists" || echo "not found" # Solution - clearer intentif [ -f "$file" ]; then    echo "exists"else    echo "not found"fi``` #### SC2016: Expressions don't expand in single quotes ```bash# Problemecho 'Variable value: $VAR' # Solutionecho "Variable value: $VAR"``` #### SC2009: Use pgrep instead of grep ```bash# Problemps aux | grep -v grep | grep myprocess # Solutionpgrep -f myprocess``` ## Performance Optimization ### Checking Multiple Files ```bash#!/bin/bash # Sequential checkingfor script in *.sh; do    shellcheck "$script"done # Parallel checking (faster)find . -name "*.sh" -print0 | \    xargs -0 -P 4 -n 1 shellcheck``` ### Caching Results ```bash#!/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 1done``` ## Output Formats ### Default Format ```bashshellcheck script.sh # Output:# script.sh:1:3: warning: foo is referenced but not assigned. [SC2154]``` ### GCC Format (for CI/CD) ```bashshellcheck --format=gcc script.sh # Output:# script.sh:1:3: warning: foo is referenced but not assigned.``` ### JSON Format (for parsing) ```bashshellcheck --format=json script.sh # Output:# [{"file": "script.sh", "line": 1, "column": 3, "level": "warning", "code": 2154, "message": "..."}]``` ### Quiet Format ```bashshellcheck --format=quiet script.sh # Returns non-zero if issues found, no output otherwise``` ## Best Practices 1. **Run ShellCheck in CI/CD** - Catch issues before merging2. **Configure for your target shell** - Don't analyze bash as sh3. **Document exclusions** - Explain why violations are suppressed4. **Address violations** - Don't just disable warnings5. **Enable strict mode** - Use `--enable=all` with careful exclusions6. **Update regularly** - Keep ShellCheck current for new checks7. **Use pre-commit hooks** - Catch issues locally before pushing8. **Integrate with editors** - Get real-time feedback during development