ShellCheck - Shell Script Static Analysis
Auto-routes when user mentions shellcheck, shell linting, bash script analysis, or SC error codes.
Overview
ShellCheck is a GPLv3-licensed static analysis tool that identifies bugs in bash/sh shell scripts. It detects:
- Syntax errors and parsing issues
- Semantic problems causing unexpected behavior
- Quoting issues and word splitting bugs
- POSIX compatibility warnings
- Style and best practice violations
Voice Notification
When executing a workflow, do BOTH:
Send voice notification:
curl -s -X POST http://localhost:8888/notify \ -H "Content-Type: application/json" \ -d '{"message": "Running the WORKFLOWNAME workflow from the ShellCheck skill"}' \ > /dev/null 2>&1 &Output text notification:
Running the **WorkflowName** workflow from the **ShellCheck** skill...
Workflow Routing
| Workflow | Trigger | File |
|---|---|---|
| Analyze | "shellcheck this", "lint script", "check shell" | Workflows/Analyze.md |
| Fix | "fix shell errors", "apply shellcheck fixes" | Workflows/Fix.md |
| Setup | "setup shellcheck", "configure shellcheck" | Workflows/Setup.md |
| Explain | "explain SC2086", "what is SC code" | Workflows/Explain.md |
Quick Reference
Basic Usage
# Check a script
shellcheck myscript.sh
# Specify shell dialect
shellcheck -s bash myscript.sh
# Exclude specific codes
shellcheck -e SC2086,SC2046 myscript.sh
# Output formats
shellcheck -f gcc myscript.sh # Editor integration
shellcheck -f json myscript.sh # Machine readable
shellcheck -f diff myscript.sh # Auto-fix patches
Common SC Codes
| Code | Issue | Fix |
|---|---|---|
| SC2086 | Unquoted variable | "$var" |
| SC2046 | Unquoted command substitution | "$(cmd)" |
| SC2034 | Unused variable | Remove or export |
| SC2154 | Unassigned variable | Assign or disable |
| SC2155 | Declare and assign separately | Split declaration |
Inline Directives
# Disable for next command
# shellcheck disable=SC2086
echo $var
# Disable for entire file (after shebang)
#!/bin/bash
# shellcheck disable=SC2086,SC2046
Full Documentation
- Error Codes:
SkillSearch('shellcheck error codes')-> loads ErrorCodes.md - Configuration:
SkillSearch('shellcheck config')-> loads Configuration.md - CI/CD Integration:
SkillSearch('shellcheck ci')-> loads Integration.md - Best Practices:
SkillSearch('shellcheck practices')-> loads BestPractices.md
Examples
Example 1: Analyze a script
User: "shellcheck my deploy script"
-> Invokes Analyze workflow
-> Runs shellcheck with JSON output
-> Presents findings grouped by severity
-> Suggests fixes with wiki links
Example 2: Fix common issues
User: "fix the shellcheck errors in scripts/"
-> Invokes Fix workflow
-> Generates diff output
-> Applies fixes interactively
-> Re-runs validation
Example 3: Setup for project
User: "setup shellcheck for this repo"
-> Invokes Setup workflow
-> Creates .shellcheckrc
-> Adds pre-commit hook
-> Configures CI workflow
Example 4: Explain an error code
User: "what does SC2086 mean?"
-> Invokes Explain workflow
-> Fetches wiki documentation
-> Shows examples and fixes
-> Provides context-specific guidance
Gotchas
- SC2086 is wrong inside
[[ ]]: Bash's[[ ]]does not word-split, so[[ -n $var ]]is safe unquoted. Disabling SC2086 on[[ ]]blocks is a sign you're applying the lint to the wrong construct, not a sign the rule is broken. - SC2034 fires on indirectly-used variables: Variables consumed via
${!prefix*}indirection,declare -pintrospection, or sourced into another script trigger "unused" false positives. Use# shellcheck disable=SC2034with a comment explaining the indirection — don't silence globally. - Shebang determines the dialect, not the filename:
script.shwith#!/bin/shis checked as POSIX sh and rejects bashisms like[[ ]]or arrays. Either set the correct shebang or pass-s bashexplicitly; never rely on the.shextension. shellcheck -e SC2086,SC2046in.shellcheckrchides real bugs: Project-wide disables compound — a year later nobody remembers why and unquoted expansions ship to prod. Prefer inline disables with a justification comment over global suppression.- Source-following requires
-xflag:source ./lib.shis not analyzed by default. Run withshellcheck -x script.shfor full coverage, or add# shellcheck source=./lib.shdirectives. CI configs frequently miss this and ship un-linted sourced files. -f diffpatches assume the script parses cleanly: Syntax errors prevent the auto-fix output entirely, with no clear message. If-f diffproduces nothing, run without-ffirst and fix parse errors before re-running for patches.