Linting
shuck check lints shell scripts, supported embedded shell snippets, and whole project trees. It is the command to use in CI, pre-commit hooks, editor save hooks, and local review before a script lands.
Basic usage
# Check one script
shuck check script.sh
# Check the current project
shuck check .
# Check multiple roots in one run
shuck check scripts/ .github/workflows/ci.yml
# Read a script from stdin
printf 'echo $name\n' | shuck check -When no path is passed, shuck check checks the current directory.
What gets checked
Shuck discovers shell files by extension, shebang, and supported host-file extraction.
Standalone shell files include common Bash, POSIX shell, Dash, Korn shell, mksh, and zsh script paths. Embedded extraction is enabled by default for supported GitHub Actions workflow and composite-action run: blocks.
[check]
embedded = trueSet [check].embedded = false when you only want standalone shell files. See Embedded Scripts for the extraction and remapping details.
Rule selection
By default, Shuck enables implemented non-style rules:
- Correctness rules (
C) - Performance rules (
P) - Portability rules (
X) - Security rules (
K)
Style rules (S) are opt-in. Selectors can name a category prefix, a narrower prefix, an exact rule code, a named group such as google, or ALL.
# Add all style rules to the default set
shuck check --extend-select S .
# Run one rule
shuck check --select C001 script.sh
# Run everything except a noisy rule
shuck check --select ALL --ignore S074 .The same model is available in config:
[lint]
extend-select = ["S"]
ignore = ["S074"]
per-file-ignores = { "vendor/**" = ["ALL"] }Use Rules to browse the rule catalog and Configuration for the full selection model.
Fixes and ignore comments
Run safe fixes with --fix:
shuck check --fix .Unsafe fixes require an explicit opt-in:
shuck check --fix --unsafe-fixes .You can narrow which rules are eligible for fixes:
shuck check --fix --fixable C,S074 --unfixable C001 .When a warning is intentional, --add-ignore writes native Shuck ignore comments on the affected lines:
shuck check --add-ignore="legacy input shape" .See Suppression for native # shuck: directives and ShellCheck-compatible suppression comments.
Output and CI
The default output format is human-readable. Use --output-format for tools that need structured or compact output:
shuck check --output-format concise .
shuck check --output-format json-lines .
shuck check --output-format github .
shuck check --output-format sarif .shuck check exits with:
0when there are no diagnostics;1when diagnostics are reported;2for parse errors, file errors, or runtime errors.
Use --exit-zero for exploratory runs where diagnostics should not fail the command. Use --exit-non-zero-on-fix when CI should fail if a fix changed files.
Watch mode
Use --watch during local editing:
shuck check --watch .Watch mode reruns when requested files, relevant config files, or discovered source dependencies change.
Dialect overrides
Shuck infers a script's dialect from the file path, shebang, and parser context. Override unusual layouts with per-file shell mappings:
shuck check --per-file-shell "scripts/**/*.bash:bash" --extend-per-file-shell "zsh/**:zsh" .[lint]
per-file-shell = { "scripts/**/*.bash" = "bash" }
extend-per-file-shell = { "zsh/**" = "zsh" }For zsh projects, Zsh Support covers plugin resolution and dotfile-specific setup.
Related workflows
- Use Formatting for
shuck format. - Use LSP Server for live editor diagnostics and code actions.
- Use ShellCheck Compatibility when an existing tool expects a ShellCheck-shaped command line.