| Concern | Tool | Version Strategy |
|---|---|---|
| Linter | shellcheck | Latest in container |
| Formatter | shfmt | Latest in container |
| Tests | bats | Latest in container |
Config file: .shellcheckrc at repository root.
Recommended .shellcheckrc:
# Default shell dialect
shell=bash
# Enable all optional checks
enable=all
shellcheck validates all shell scripts against best practices and catches common errors (quoting, globbing, portability issues).
No config file. Flags are passed on the command line.
Required flags:
| Flag | Meaning |
|---|---|
-i 2 |
Indent with 2 spaces |
-ci |
Indent switch cases |
-bn |
Binary operators at start of next line |
Format check: shfmt -d -i 2 -ci -bn .
Format fix: shfmt -w -i 2 -ci -bn .
No config file required. Test files use the .bats extension and live in the tests/ directory.
Example test structure:
#!/usr/bin/env bats
@test "script exits zero on success" {
run ./scripts/my-script.sh --help
[ "$status" -eq 0 ]
}| Target | Command | Description |
|---|---|---|
_lint |
shellcheck scripts/*.sh |
Lint all shell scripts |
_format |
shfmt -d -i 2 -ci -bn . |
Check formatting (no changes) |
_format (fix) |
shfmt -w -i 2 -ci -bn . |
Apply formatting fixes |
_test |
bats tests/ |
Run bats test suite |
See DEVELOPMENT.md for the full Makefile contract and two-layer delegation pattern.
These run on every commit via pre-commit:
repos:
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: "" # container manages version
hooks:
- id: shellcheck
- repo: https://github.com/scop/pre-commit-shfmt
rev: "" # container manages version
hooks:
- id: shfmt
args: [-i, "2", -ci, -bn]These run via make test in CI pipelines. They are not configured as pre-commit hooks due to execution time:
bats tests/-- full test suite
- All shell scripts must begin with
#!/usr/bin/env bashandset -euo pipefail. No exceptions. See DEVELOPMENT.md Shell Script Conventions for full coding standards. - Scripts must be idempotent -- safe to re-run without side effects.
- Use shared logging functions (
log_info,log_warn,log_error,log_debug,die) fromlib/log.sh. No rawechofor status messages. - Variables:
UPPER_SNAKE_CASEwithreadonlyfor constants,lower_snake_casefor locals. - Functions:
lower_snake_case, prefixed by purpose (install_,check_,log_). - Every script supports
--helpand usesgetoptsfor argument parsing. - All tools are pre-installed in the dev-toolchain container. Do not install them on the host.
- For cross-cutting practices (DRY, idempotency, error handling, testing, naming) and git workflow (branching, code review, conventional commits), see Coding Practices and Git Workflow.