Concerns (6 files): - coding-style.md (163 lines): patterns, anti-patterns, error handling, SOLID - naming.md (105 lines): naming conventions table per language - documentation.md (149 lines): docstrings, WHY vs WHAT, README standards - testing.md (134 lines): AAA pattern, mocking philosophy, TDD - git-workflow.md (118 lines): conventional commits, branch naming, PR format - project-structure.md (82 lines): directory layout, entry points, config placement Languages (4 files): - python.md (224 lines): uv, ruff, pyright, pytest, pydantic, idioms, anti-patterns - typescript.md (150 lines): strict mode, discriminated unions, satisfies, as const - nix.md (129 lines): flake structure, module patterns, alejandra, anti-patterns - shell.md (100 lines): set -euo pipefail, shellcheck, quoting, POSIX Frameworks (1 file): - n8n.md (42 lines): workflow design, node patterns, Error Trigger, security Context budget: 975 lines (concerns + python) < 1500 limit Refs: T6-T16 of rules-system plan
101 lines
1.5 KiB
Markdown
101 lines
1.5 KiB
Markdown
# Shell Scripting Rules
|
|
|
|
## Shebang
|
|
|
|
Always use `#!/usr/bin/env bash` for portability. Never hardcode `/bin/bash`.
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
```
|
|
|
|
## Strict Mode
|
|
|
|
Enable strict mode in every script.
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
```
|
|
|
|
- `-e`: Exit on error
|
|
- `-u`: Error on unset variables
|
|
- `-o pipefail`: Return exit status of last failed pipe command
|
|
|
|
## Shellcheck
|
|
|
|
Run shellcheck on all scripts before committing.
|
|
|
|
```bash
|
|
shellcheck script.sh
|
|
```
|
|
|
|
## Quoting
|
|
|
|
Quote all variable expansions and command substitutions. Use arrays instead of word-splitting strings.
|
|
|
|
```bash
|
|
# Good
|
|
"${var}"
|
|
files=("file1.txt" "file2.txt")
|
|
for f in "${files[@]}"; do
|
|
process "$f"
|
|
done
|
|
|
|
# Bad
|
|
$var
|
|
files="file1.txt file2.txt"
|
|
for f in $files; do
|
|
process $f
|
|
done
|
|
```
|
|
|
|
## Functions
|
|
|
|
Define with parentheses, use `local` for variables.
|
|
|
|
```bash
|
|
my_function() {
|
|
local result
|
|
result=$(some_command)
|
|
echo "$result"
|
|
}
|
|
```
|
|
|
|
## Command Substitution
|
|
|
|
Use `$()` not backticks. Nests cleanly.
|
|
|
|
```bash
|
|
# Good
|
|
output=$(ls "$dir")
|
|
|
|
# Bad
|
|
output=`ls $dir`
|
|
```
|
|
|
|
## POSIX Portability
|
|
|
|
Write POSIX-compliant scripts when targeting `/bin/sh`.
|
|
|
|
- Use `[[` only for bash scripts
|
|
- Use `printf` instead of `echo -e`
|
|
- Avoid `[[`, `((`, `&>` in sh scripts
|
|
|
|
## Error Handling
|
|
|
|
Use `trap` for cleanup.
|
|
|
|
```bash
|
|
cleanup() {
|
|
rm -f /tmp/lockfile
|
|
}
|
|
trap cleanup EXIT
|
|
```
|
|
|
|
## Readability
|
|
|
|
- Use 2-space indentation
|
|
- Limit lines to 80 characters
|
|
- Add comments for non-obvious logic
|
|
- Separate sections with blank lines
|