Files
AGENTS/rules/languages/shell.md
m3tm3re 8910413315 feat(rules): add initial rule files for concerns, languages, and frameworks
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
2026-02-17 19:05:45 +01:00

1.5 KiB

Shell Scripting Rules

Shebang

Always use #!/usr/bin/env bash for portability. Never hardcode /bin/bash.

#!/usr/bin/env bash

Strict Mode

Enable strict mode in every script.

#!/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.

shellcheck script.sh

Quoting

Quote all variable expansions and command substitutions. Use arrays instead of word-splitting strings.

# 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.

my_function() {
  local result
  result=$(some_command)
  echo "$result"
}

Command Substitution

Use $() not backticks. Nests cleanly.

# 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.

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