Bash coding
Skill nguyenthdat/opencode-manager/registry/skills/bash-coding
Project-scoped OpenCode TUI plugin for grouping and managing MCP servers, custom agent skills, and pinned vendor skill registries.
npx -y skills add nguyenthdat/opencode-manager --skill bash-codingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 13 days oldThe repository was created 13 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Comprehensive idiomatic Bash/POSIX Shell guidance: 134 prioritized rules across 12 categories. Use when writing, reviewing, refactoring, or debugging shell scripts (`.sh`, `.bash`, `#!/bin/bash`, `#!/bin/sh`). Covers variable handling/quoting, error handling (errexit/pipefail), I/O and redirection, portability (POSIX sh vs Bash), security (injection/suid), function design, testing (Bats/shellspec), and anti-patterns. Target Bash 5.x+; distinguish Bash-isms from POSIX sh for portable scripts.
SKILL.md
20.4 KB, as published. Nobody here has run it
Bash / Shell Best Practices
Comprehensive guide for writing high-quality, idiomatic, and robust Bash/POSIX shell scripts. Contains 134 rules across 12 categories, prioritized by impact to guide LLMs in code generation and refactoring.
When to Apply
Reference these guidelines when:
- Writing new Bash scripts or shell functions
- Reviewing shell scripts for correctness and security
- Debugging variable scoping, quoting, or exit code issues
- Refactoring legacy shell scripts to modern standards
- Writing scripts that must run on both Linux and macOS
- Choosing between Bash features and POSIX-compatible alternatives
- Setting up CI/CD with ShellCheck and Bats testing
- Handling user input, secrets, or temporary files securely
Bash 5.x & Modern Shell Features
This skill targets Bash 5.x (released 2019) while noting POSIX compatibility. Key features to leverage:
- Associative arrays (
declare -A): string-keyed maps for configuration, caching, dispatch tables (Bash 4.0+) - Namerefs (
declare -n,local -n): safe indirect variable/array access, replacingeval(Bash 4.3+) - Process substitution (
<(cmd),>(cmd)): pipe without subshells, preserve variable state (Bash 4.0+) - Here-strings (
<<<): single-string stdin without pipes or forks (Bash 4.0+) [[ ]]conditional: regex matching (=~), pattern matching (==), safe unquoted variablesglobstar(shopt -s globstar): recursive**/*.txtglob patterns (Bash 4.0+)nullglob/failglob: control glob behavior for empty matchesextglob: extended patterns (@(),!(),+(),*(),?())readarray/mapfile: read file/command output directly into arraysBASH_REMATCH: capture regex groups from[[ =~ ]]matchingEPOCHSECONDS/EPOCHREALTIME: wall-clock timestamps withoutdatefork (Bash 5.0+)BASH_SOURCEvs$0: reliably determine script location regardless of how it's invoked- Subshell vs command grouping:
(cmd)is a subshell (variable changes lost),{ cmd; }is in-process
For POSIX sh (#!/bin/sh, dash, ash, busybox sh), avoid all of the above and see port-avoid-bashisms.
Rule Categories by Priority
| Priority | Category | Impact | Prefix | Rules |
|---|---|---|---|---|
| 1 | Variable Handling & Quoting | CRITICAL | var- | 14 |
| 2 | Error Handling & Exit Codes | CRITICAL | err- | 13 |
| 3 | Input/Output & Redirection | HIGH | io- | 12 |
| 4 | Security | HIGH | sec- | 11 |
| 5 | Function Design | HIGH | fn- | 11 |
| 6 | Portability (POSIX vs Bash) | HIGH | port- | 11 |
| 7 | Naming & Style Conventions | MEDIUM | name- | 11 |
| 8 | Arrays & Data Structures | MEDIUM | arr- | 9 |
| 9 | Testing (Bats/shellspec) | MEDIUM | test- | 10 |
| 10 | Debugging & Logging | MEDIUM | debug- | 9 |
| 11 | Performance & Efficiency | MEDIUM | perf- | 9 |
| 12 | Anti-patterns | REFERENCE | anti- | 14 |
Quick Reference
1. Variable Handling & Quoting (CRITICAL)
var-always-quote- Always quote variable expansions:"$var"not$varvar-brace-variables- Use${var}for disambiguation and clarityvar-default-values- Use${var:-default}and${var:=default}for defaultsvar-local-in-functions- Declare function variables withlocalvar-readonly-constants- Usereadonlyordeclare -rfor constantsvar-uppercase-env- UPPER_CASE for environment variables and globalsvar-null-vs-unset- Use${var+isset}vs${var-unset}for existence checksvar-indirect-reference- Usedeclare -n(nameref) instead ofevalvar-no-eval-expand- Never useevalfor variable expansionvar-arrays-cautious- Use arrays for lists; don't misuse strings with spacesvar-no-glob-wordsplitting- Set IFS carefully; disable word splitting for safetyvar-prefix-suffix-remove- Use${var#prefix},${var%suffix},${var//pattern/replacement}var-length-count- Use${#var}for string length,${#arr[@]}for array sizevar-avoid-export-in-loop- Don't export variables inside loops unnecessarily
2. Error Handling & Exit Codes (CRITICAL)
err-errexit-set- Useset -euo pipefailat top of scriptserr-pipefail-required- Always useset -o pipefailto catch pipe errorserr-check-exit-status- Check$?after critical commandserr-trap-errors- Usetrap '...' ERRfor error handlingerr-trap-exit-cleanup- Usetrap '...' EXITfor cleanuperr-meaningful-exit- Exit with meaningful non-zero codeserr-avoid-ignore-errors- Don't use|| trueto ignore errors without commenterr-command-exists- Checkcommand -vbefore using external toolserr-set-e-cautious- Understandset -eedge cases in conditionalserr-no-unchecked-cd- Always checkcdsuccess:cd dir || exit 1err-mkdir-parent- Usemkdir -pto avoid "already exists" errorserr-return-over-exit-fn- Usereturnin functions,exitonly at top levelerr-dry-run-pattern- Support--dry-runin destructive scripts
3. Input/Output & Redirection (HIGH)
io-heredoc-quote- Quote heredoc delimiter to prevent expansion:<<'EOF'io-stderr-redirect- Redirect stderr explicitly:2>/dev/nullor2>&1io-read-while-pipe- Usewhile IFS= read -r linepattern correctlyio-process-substitution- Use<(cmd)and>(cmd)for piping without subshellsio-avoid-cat-pipe- Avoidcat file | cmd; usecmd < fileorcmd fileio-file-descriptor-management- Useexecfor custom file descriptorsio-here-string- Use<<<for simple string inputio-tempfile-safely- Usemktempfor temporary files; never hardcode/tmpio-null-dev-null- Use/dev/nullexplicitly; avoid writing to stdoutio-read-r-preserve- Useread -rto preserve backslashesio-no-binary-in-pipe- Don't pipe binary data through text processingio-buffered-flush- Usestdbuforunbufferwhen needed for line-buffered pipes
4. Security (HIGH)
sec-no-unquoted-expansion- Quote all shell expansions to prevent word splitting/globsec-no-eval-user- Never useevalwith user-supplied inputsec-sanitize-input- Validate and sanitize user input before usesec-path-injection- Never trust$PATH; use absolute paths or set PATH explicitlysec-no-exec-user-test- Don't use user input in command namessec-tempfile-race- Usemktempto avoid TOCTOU racessec-suid-cautious- Avoid setuid shell scripts; usesudoinsteadsec-secrets-in-env- Pass secrets via environment, never CLI argssec-no-hardcoded-secrets- Use environment variables or secret managers for credentialssec-umask-restrictive- Setumask 077for scripts handling sensitive datasec-shellcheck-required- Runshellcheckon all shell scripts
5. Function Design (HIGH)
fn-return-values- Capture function output with$(...); usereturnfor statusfn-argument-count- Check$#for required argument countfn-argument-names- Name function arguments at top:local name=$1fn-main-function- Put main logic inmain()function; call at endfn-pure-when-possible- Write functions that don't depend on global statefn-small-focused- Keep functions small and single-purposefn-no-side-effects- Minimize side effects; document globals modifiedfn-usage-help- Provideusage()function with help textfn-option-parsing- Usegetoptsfor argument parsing; avoid manual$1$2loopsfn-library-source- Source library scripts; don't copy-paste functionsfn-lowercase-names- Use lowercase function names (POSIX namespace safety)
6. Portability (POSIX vs Bash) (HIGH)
port-shebang-choice- Use#!/usr/bin/env bashfor Bash;#!/bin/shfor POSIXport-avoid-bashisms- Avoid[[ ]], arrays,${!ref},source,==in POSIX sh scriptsport-posix-test- Use[ ]instead of[[ ]]when portability mattersport-printf-over-echo- Useprintfinstead ofechofor portable outputport-no-local-posix- Don't uselocalin POSIX sh (Bash-ism)port-command-v-which- Usecommand -voverwhichfor command checkingport-readlink-realpath- Don't assumereadlink -f/realpathis availableport-sed-i-portable- Usesed -i.bakfor portable in-place editingport-array-alternatives- Use IFS-delimited strings when arrays aren't availableport-shellcheck-directive- Use ShellCheck directives for bash-only scriptsport-coproc-portable- Document Bash-specific features when used
7. Naming & Style Conventions (MEDIUM)
name-variables-uppercase-env- UPPER_CASE for environment/export variablesname-variables-lowercase-local- lowercase_with_underscores for local varsname-functions-lowercase- lowercase function names; avoid UpperCasename-constants-readonly-readonly VARIABLE_NAMEfor constantsname-files-kebab-case- Use kebab-case.sh for script file namesname-library-prefix- Prefix library functions with namespace_ (e.g.,log_info)name-boolean-true-false- Use 0/1 for boolean return valuesname-descriptive-vars- Use descriptive variable names; avoid a, b, c, xname-no-reserved-words- Avoid bash keywords as function/variable namesname-globals-caps- UPPER_CASE for globals in scriptsname-temp-vars-prefix- Prefix temp variables with_to mark as internal
8. Arrays & Data Structures (MEDIUM)
arr-declare-arrays- Usedeclare -afor indexed,declare -Afor associativearr-expand-properly- Use"${arr[@]}"to expand arrays with proper quotingarr-iterate-keys- Iterate associative array keys with"${!arr[@]}"arr-append-elements- Usearr+=("new")to append to arraysarr-length-count- Use${#arr[@]}for array lengtharr-no-spaces-in-keys- Use sensible keys for associative arraysarr-pass-to-function- Pass arrays by name withdeclare -n(nameref)arr-slice-subset- Use${arr[@]:offset:length}for array slicingarr-read-into-array- Usereadarray/mapfilefor reading lines into array
9. Testing (Bats/shellspec) (MEDIUM)
test-bats-framework- Use Bats (Bash Automated Testing System) for testingtest-run-helper- Use Batsrunhelper to capture output and statustest-assert-output- Use[ "$output" = "expected" ]and[ "$status" -eq 0 ]test-setup-teardown- Usesetup()andteardown()for test fixturestest-mock-commands- Override functions or use stub scripts for mockingtest-temp-dirs- Create and clean test directories in setup/teardowntest-one-assertion- Test one behavior per test casetest-skip-not-installed- Skip tests when dependencies not installedtest-shellcheck-build- Run ShellCheck as part of the test suitetest-ci-integration- Output TAP format for CI integration
10. Debugging & Logging (MEDIUM)
debug-set-x-trace- Useset -xfor command tracing; wrap in subshelldebug-ps4-enhanced- Set enhanced PS4 for file:line:function tracesdebug-trap-debug- Usetrap '...' DEBUGfor custom debuggingdebug-log-function- Write alog()function with timestamps and levelsdebug-verbose-flag- Support--verbose/-vflag for debug outputdebug-no-echo-debug- Use stderr for debug, stdout for program outputdebug-assert-function- Createassert()helper for runtime checksdebug-color-output- Usetputor ANSI codes; check if output is terminaldebug-stack-trace- Print stack trace in ERR trap withcaller
11. Performance & Efficiency (MEDIUM)
perf-avoid-fork- Use builtins ([[ ]],${var##},printf) to avoid subshell forksperf-avoid-cat-useless- Avoid useless use of cat (UUOC)perf-inline-grep- Use Bash pattern matching overgrepwhen possibleperf-batch-process- Batch operations:gitcommands, database queriesperf-parallel-xargs- Usexargs -Pfor parallel executionperf-avoid-subshell-loop- Don't pipe intowhile; use process substitutionperf-here-string-speed- Here-strings (<<<) are faster thanecho |pipeperf-glob-over-find- Use glob patterns overfindfor simple directory walksperf-cache-results- Cache expensive command results in variables
12. Anti-patterns (REFERENCE)
anti-unquoted-variables- Never leave variable expansions unquotedanti-eval-everything- Don't useeval; find builtin alternativesanti-bare-variable-in-test- Don't use[ $var = "value" ]on empty varanti-pipe-while-subshell- Don't modify variables in pipewhileloops (subshell issue)anti-ls-in-for- Never usefor f in $(ls); use globs:for f in *anti-backticks- Use$()over backticks for command substitutionanti-newlines-in-names- Don't create files/vars with spaces or newlinesanti-cd-without-check- Always checkcdsuccessanti-echo-in-function-output- Don't echo debug info in functions that return dataanti-global-variable-everywhere- Don't use global variables for everythinganti-source-without-path- Don'tsourcescripts without specifying pathanti-single-brackets-bash- Don't use[ ]for compound tests in Bash (use[[ ]])anti-rm-rf-asterisk-danger- Never userm -rf $VAR/*without validating$VARanti-interactive-suppress- Don't useyes |in scripts; handle interaction properly
Recommended Shell Settings
#!/usr/bin/env bash
# Safer bash defaults — include at top of every script
set -euo pipefail
IFS=$'\n\t'
# Additional safety options (opt-in)
shopt -s nullglob # Non-matching globs → empty (not literal *)
shopt -s inherit_errexit # Subshells inherit errexit (Bash 4.4+)
shopt -s shift_verbose # shift errors when count exceeds $#
# For debuggable scripts:
# shopt -s failglob # Non-matching globs → error (stricter than nullglob)
How to Use
This skill provides rule identifiers for quick reference. When generating or reviewing shell scripts:
- Check relevant category based on task type
- Apply rules with matching prefix
- Prioritize CRITICAL > HIGH > MEDIUM > REFERENCE
- Read rule files in
rules/for detailed examples with Bad/Good code
Rule Application by Task
| Task | Primary Categories |
|---|---|
| New script skeleton | err-, fn-, name- |
| Variable handling | var-, sec- |
| Function writing | fn-, var- |
| File/pipe processing | io-, perf- |
| Security review | sec-, anti- |
| Cross-platform script | port-, name- |
| Test writing | test-, debug- |
| Debugging failures | debug-, err- |
| Code review | anti-, sec- |
Related Skills
- design-patterns — choosing and implementing GoF/idiomatic patterns in shell scripts (pipeline/filter, command dispatch).
- security-review — cross-language security/correctness review methodology (phases, finding format, severity guidance) applies to shell-script reviews; it does not yet ship a dedicated shell bug-class reference file, so apply the general workflow to injection, unsafe
eval/word-splitting, and TOCTOU risks.
Sources
This skill synthesizes best practices from:
- Google Shell Style Guide
- ShellCheck Wiki
- Bash Hackers Wiki
- Wooledge BashGuide
- POSIX Shell Command Language
- Production codebases: Git, Docker, Homebrew, various CI/CD pipelines
- Community conventions and ShellCheck diagnostics