Contents
ShellCheck reads a shell script without running it and points out mistakes and risky patterns. It runs on your own computer and sends your script nowhere, so you can check a script as soon as you write it.
This review is for people who are starting to write sh or bash scripts. After reading it, you can do the following:
- Install ShellCheck and check a script on your computer
- Look up a warning code such as SC2086 on the official wiki
- Silence warnings you don’t need, and add ShellCheck to CI
What ShellCheck is for
The official README lists these goals:
- Explain the beginner syntax errors that make the shell print cryptic messages
- Point out intermediate-level code that behaves in surprising ways
- Point out subtle pitfalls that can make a working script fail later
ShellCheck supports the sh (POSIX), bash, dash, ksh, and busybox dialects. It picks the dialect from the shebang (such as #!/bin/bash) or the file extension. You can also set it with an option like -s bash.
These checks matter for security:
| Code | What it flags | What can go wrong |
|---|---|---|
| SC2086 | A variable without double quotes | If the value contains spaces or *, word splitting and glob expansion turn it into other arguments or file names |
| SC2115 | Code like rm -rf "$STEAMROOT/"* that becomes /* when the variable is empty |
An empty variable deletes everything in the root directory |
The SC2115 wiki page shows the fix "${STEAMROOT:?}/"*. With :?, the command fails and stops when the variable is empty or unset.
Try it safely
-
Install it with a package manager. The official README lists options such as these:
Environment Command Debian-based sudo apt install shellcheckFedora-based dnf install ShellCheckmacOS (Homebrew) brew install shellcheckWindows winget install --id koalaman.shellcheck,choco install shellcheck, orscoop install shellcheckDocker docker run --rm -v "$PWD:/mnt" koalaman/shellcheck:stable myscriptGitHub Releases also has prebuilt binaries for Linux, macOS, and Windows.
-
Create a practice file named
test.shwith these two lines. Don’t run it.#!/bin/bash echo $1 -
Run
shellcheck test.sh. ShellCheck flags$1with SC2086. -
Change the line to
echo "$1"and run ShellCheck again. When the warning is gone, you’re done.
To try it without installing anything, you can paste a script into ShellCheck.net. The pasted script is sent to a server, though. See “Cautions” below.
Reading results and common options
Each warning has a code that starts with SC and a severity. Open https://www.shellcheck.net/wiki/SC<number> to read a bad example, a fixed example, and the reason. Severities, from most to least serious, are error, warning, info, and style.
| Goal | How |
|---|---|
| Show only warning and above | shellcheck --severity=warning myscript (short form -S) |
| Exclude a code for one run | shellcheck -e SC2059 myscript |
| Silence the next command only | # shellcheck disable=SC2059 on the line before |
| Silence a whole file | # shellcheck disable=SC2059 right after the shebang |
| Silence a whole project | disable=SC2059,SC2034 in .shellcheckrc |
| Get machine-readable output | -f json1, -f checkstyle, -f gcc, and others |
ShellCheck exits with 0 when it finds no issues and 1 when it finds some. So adding shellcheck myscripts/*.sh to a Makefile or CI job is enough to fail the build on warnings. The README recommends pinning a specific version in CI, so a new release with new warnings doesn’t break your build by surprise. An official pre-commit hook is also available.
In editors, you can see warnings as you type in VS Code (vscode-shellcheck), Vim (ALE and others), Emacs (Flycheck and others), Sublime Text (SublimeLinter), and more.
Cautions
- When you paste a script into ShellCheck.net, your browser sends it to the site’s server (
shellcheck.php) for analysis. I could not find an official statement on whether the server stores submissions or for how long, so this is unconfirmed. Check scripts that contain passwords, API keys, or internal host names with the localshellcheckcommand. - When you silence a warning with
disable, leave a comment with the reason so you can review it later. The official wiki notes that incommand1; command2on one line, a directive applies only to the first command. - ShellCheck never runs the scripts it checks, so it is safe for reading scripts you received from others. Still, a clean result is not a reason to run a script you don’t trust.
Read next
Sources
- Official repository (README)github.com/koalaman/shellcheck
- Manual page (shellcheck.1.md)github.com/koalaman/shellcheck/blob/master/shellcheck.1.md
- Wiki: SC2086www.shellcheck.net/wiki/SC2086
- Wiki: SC2115www.shellcheck.net/wiki/SC2115
- Wiki: Ignoregithub.com/koalaman/shellcheck/wiki/Ignore
- ShellCheck.net (online version)www.shellcheck.net
- ShellCheck.net source (shellcheck.js)github.com/koalaman/shellcheck.net/blob/master/shellcheck.js
Checked on 2026-10-25
Similar tools
Gitleaks
Impact Local onlyA command-line tool that finds passwords, API keys, and tokens that have slipped into Git repositories and files.
- Purpose
- Defense
- Type
- Command line
- Difficulty
- Beginner
- License
- PermissiveMIT
- Category
- Vulnerability scanning
Trivy
Impact Local onlyA scanner that finds vulnerabilities, misconfigurations, and embedded secrets in container images, code, and Kubernetes.
- Purpose
- Defense
- Type
- Command line
- Difficulty
- Beginner
- License
- PermissiveApache-2.0
- Category
- Vulnerability scanning / Containers and cloud