Skip to content
Latchkey

shellcheck: Lint Shell Scripts in CI

shellcheck parses shell scripts and reports quoting bugs, unset variable risks, and portability issues, exiting 1 when it finds any.

ShellCheck catches the classic shell footguns before they hit production. In CI you run it across your scripts and fail on findings.

What it does

shellcheck reads one or more script files (or stdin with -), infers the shell from the shebang or --shell, and prints findings keyed by SC#### codes. It exits 1 when issues are reported, 0 when clean. Optional checks must be turned on with --enable.

Common usage

Terminal
shellcheck script.sh
# lint every script in the repo
shellcheck $(find . -name "*.sh")
# force the dialect and turn on all optional checks
shellcheck --shell=bash --enable=all deploy.sh

Flags

FlagWhat it does
--shell <sh>Treat input as sh, bash, dash, or ksh
--severity <level>Minimum severity to report (error/warning/info/style)
--exclude <codes>Comma list of SC codes to ignore
--enable <checks>Turn on optional checks (or =all)
--format <fmt>Output format (tty, gcc, checkstyle, json, json1)
-xFollow sourced files via source/.

In CI

find piping works but breaks on filenames with spaces; prefer git ls-files "*.sh" piped to xargs, or the shellcheck action with a file glob. Optional checks like add-default-case are off by default, so add --enable to use them.

Common errors in CI

"SC1071: ShellCheck only supports sh/bash/dash/ksh scripts. Sorry!" means a non-shell shebang (zsh, fish); set --shell or exclude the file. "SC1091: Not following: <file> was not specified as input" means a sourced file is not on the path; pass -x or the source path. A clean file still exits 0; the gate is the exit code.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →