Skip to content
Back to skills

Coding Bash

ASecurity

Authors, hardens, reviews, and debugs Bash and shell scripts. Use whenever creating, editing, or reading any .sh/.bash file, and ShellCheck remediation.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 20, 2026
toolspythonrustgoshellbashexpresstestinggitsecurity

Works with

  • cli

Security analysis

A100/100

Pro scans all 17 files and shows the line behind each finding

Scanned September 20, 2026

npx -y skills add bsamiee/Parametric_Forge --skill coding-bash --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Coding Bash?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Coding Bash
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bsamiee-coding-bash-parametric-forge/badge)](https://www.skillsdirectory.com/skills/bsamiee-coding-bash-parametric-forge)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: coding-bash
description: >-
    Authors, hardens, reviews, and debugs Bash and shell scripts. Use whenever
    creating, editing, or reading any .sh/.bash file, and ShellCheck remediation.
---

# [CODING_BASH]

All code follows these governing principles:
- [FUNCTIONAL] — immutable locals, pure functions, dispatch tables, and tightly bounded mutable shell state
- [POLYMORPHIC] — one parser, one dispatcher, one logger; extend via table entries not code branches
- [PRODUCTION_HARDENED] — ERR traps, atomic I/O, signal forwarding, cleanup registries, version gating
- [FORK_MINIMAL] — `printf -v`, `$(<file)`, `EPOCHSECONDS`, fork-free `${ }`, `BASH_MONOSECONDS` timing, `mapfile` over subshell patterns
- [ECOSYSTEM_FIRST] — `rg`/`fd`/`jq`/`sd`/`choose`/`mlr` over sed/grep/find/cut when available
- [EXECUTABLE_DOCTRINE] — examples and templates must pass syntax, ShellCheck, and their own self-tests

## [01]-[ROUTING]

[FOUNDATION]: every task loads [bash-scripting-guide.md](references/bash-scripting-guide.md) — primitives, strict mode, expansion, arrays.

[TASK_ROUTED]: load only when the task matches.
- [01]-[VERSION_FEATURES](references/version-features.md): runtime features, fork-free substitution, version gating
- [02]-[VARIABLE_FEATURES](references/variable-features.md): call stacks, namerefs, traps, process lifecycle, runtime variables
- [03]-[ARRAY_OPERATIONS](references/array-operations.md): set algebra, structural transforms, higher-order traversal
- [04]-[STRING_OPERATIONS](references/string-operations.md): transform pipelines, regex extraction, codecs, templates
- [05]-[FILE_OPERATIONS](references/file-operations.md): atomic writes, FD multiplexing, directory traversal
- [06]-[SCRIPT_PATTERNS](references/script-patterns.md): arg parsing, help, ERR traps, parallel, retry
- [07]-[BASH_LOGGING](references/bash-logging.md): structured logging, CI integration, tracing
- [08]-[BASH_TESTING](references/bash-testing.md): bats-core suites, coverage, hypothesis PBT
- [09]-[BASH_PORTABILITY](references/bash-portability.md): cross-shell compat, containers, POSIX
- [10]-[TEXT_PROCESSING_GUIDE](references/text-processing-guide.md): rg/awk/sd/jq/yq/mlr tool selection
- [11]-[VALIDATION](references/validation.md): ShellCheck codes, static analysis, CI

[EXAMPLES]: read the one matching the target archetype before writing.
- [01]-[CLI_TOOL](examples/cli-tool.sh): two-dimensional verb:resource dispatch CLI
- [02]-[DATA_PIPELINE](examples/data-pipeline.sh): file processing with jq pipelines, accumulation
- [03]-[SERVICE_WRAPPER](examples/service-wrapper.sh): container entrypoint, signal dispatch, coproc

[TEMPLATE]: scaffold a new script from [standard.template.md](templates/standard.template.md) — strict-mode header, logging, cleanup stack, traps, flag parsing, self-test.

## [02]-[PARADIGM]

- [IMMUTABILITY]: `local -r` for every non-mutating function local, `readonly` for module-level constants
- [FROZEN_ARGS]: Mutable state only for argument parsing — frozen via `readonly` in `_main` before core logic
- [DISPATCH_TABLES]: `declare -Ar` for O(1) command routing and two-dimensional `verb:resource` dispatch
- [DATA_TABLES]: `declare -Ar` also tables option metadata, validation rules, log-level gating, and env contracts (regex per var)
- [CASE_RESERVED]: `case/esac` reserved exclusively for glob/regex pattern matching — never conditional routing
- [PURE_FUNCTIONS]: Input via positional parameters, output via stdout or nameref (`local -n`); no global reads except `readonly` constants
- [SIDE_EFFECTS]: Side effects isolated to `_main`, trap handlers, cleanup registries, and explicitly marked shell boundary loops
- [METADATA_DRIVEN_HELP]: `_OPT_META` with `short|long|desc|VALUE_NAME|default` entries generates `_usage`. One entry + one `case` branch per option
- [MIDDLEWARE_COMPOSITION]: `_use()` registers middleware into `_MIDDLEWARE`; `_run_with_middleware()` executes the chain before handler dispatch
- [PARSE_PHASES]: Argument parsing composes subcommand dispatch (O(1) table lookup), flag parsing (`case/esac`), positional collection
- [EXPRESSION_OVER_STATEMENT]: `${var:-default}` over if-empty, `${var:?message}` over assert-nonempty, `(( expr ))` over `test`, expansion over forks
- [FORK_ELIMINATION]: `printf -v var '%(%F %T)T' -1` over `$(date)`, `$(<file)` over `$(cat file)`, `EPOCHSECONDS`/`EPOCHREALTIME` over `$(date +%s)`, `mapfile` over `while read`, `BASH_REMATCH` over `grep -oP`
- [ATOMIC_IO]: Every file write goes `mktemp` + write + `mv` — rename is atomic on the same filesystem; `umask 077` before `mktemp` for sensitive data
- [DYNAMIC_FD]: Dynamic FDs via `exec {fd}>file`

## [03]-[CONVENTIONS]

[ECOSYSTEM_TOOL_SELECTION]: richer ecosystem tools own each available operation:

| [INDEX] | [TASK]           | [PREFERRED] | [FALLBACK]         | [NEVER]               |
| :-----: | :--------------- | :---------- | :----------------- | :-------------------- |
|  [01]   | File search      | `fd`        | `find`             | `ls -R`               |
|  [02]   | Content search   | `rg`        | `grep -rn`         | `find -exec grep`     |
|  [03]   | JSON             | `jq`        | `python3 -c`       | `sed`/`awk` on JSON   |
|  [04]   | YAML             | `yq eval`   | `python3 -c`       | `sed` on YAML         |
|  [05]   | CSV/TSV          | `mlr`       | `awk -F`           | `cut` for multi-field |
|  [06]   | Stream edit      | `sd`        | `sed`              | `awk` for simple sub  |
|  [07]   | Column select    | `choose`    | `awk '{print $N}'` | `cut -d`              |
|  [08]   | Interactive JSON | `jnv`       | `jq`               | --                    |

[SELECTION_RULES]:
- Probe availability via `command -v` before use; fall back gracefully
- `rg` and `fd` own repo-aware searches through default `.gitignore` integration
- `jq` is mandatory for JSON — never parse JSON with sed/awk/grep
- `mlr` handles format conversion (CSV to JSON, TSV to JSON) natively
- Pipeline preference: single `awk` program over chained `grep | sed | cut`

## [04]-[CONTRACTS]

[VARIABLE_DISCIPLINE]:
- `local -r` for all non-mutating function locals. `readonly` for all module-level constants.
- Mutable state (parsed args, log level) declared at module level, frozen via `readonly` in `_main` before core logic.
- `declare -Ar` for all dispatch tables, option metadata, and lookup maps.
- `local -n` (nameref) for passing arrays to functions — never `eval` or indirect expansion.
- Nameref return channels: a scalar-returning function takes the result var last (`_ext "$item" key`), writing via `printf -v "$2"` or `local -n`.
- Callers pass a name, never `$()`. Multi-return via multiple namerefs (`_project_meta "$slug" name created`).
- Naming: `UPPER_SNAKE` for constants/env, `lower_snake` for locals/functions, `_` prefix for internal functions.

[CONTROL_FLOW]:
- `case/esac` for pattern matching (globs, regexes) only — never for if/elif-style routing.
- `declare -Ar` dispatch tables for command routing: `"${_DISPATCH[${cmd}]}" "${args[@]}"`. Nest for subdomains: `_CONFIG_SUBCMDS`, `_INIT_SUBCMDS`.
- `[[ ]]` over `[ ]`. `(( ))` for arithmetic. `&&`/`||` for short-circuit.
- `mapfile -t` / `readarray -d ''` over `while read` loops for collection.
- Streaming consumers may use `while IFS= read -r` with a comment naming the stream boundary.
- Ternary via arithmetic: `(( condition )) && action1 || action2` or `${var:+if_set}${var:-if_unset}`.
- Bounded concurrency: `wait -n -p finished_pid` with job-count gate `(( ${#jobs[@]} >= MAX_JOBS ))` — see `_run_pool` pattern in examples.
- Shell reality exceptions are explicit: option parsing uses `case`; cleanup stacks may use a static `eval` template over shell-quoted commands.
- Bounded counters and polling loops may mutate when the mutation is the resource protocol.

[ERROR_HANDLING]:
- `set -Eeuo pipefail` + `shopt -s inherit_errexit` in every script. No exceptions.
- ERR trap with `BASH_COMMAND`, `BASH_LINENO`, `FUNCNAME` context. Stack trace for multi-level call chains.
- `_CLEANUP_STACK` LIFO registry invoked by EXIT trap. `_CLEANING` guard prevents re-entrant execution on cascading signals.
- Exit codes: 0=success, 1=general error, 2=usage error. Custom codes in `EX_*` constants.
- `_die()` for fatal errors (log + exit). `_die_usage()` for argument errors (log + hint + exit 2).
- Timing: `BASH_MONOSECONDS` for elapsed-time durations — monotonic, immune to NTP drift, zero forks.
- `EPOCHREALTIME` only for absolute timestamps and microsecond benchmarks (`_bench()` shape: `(end_s - start_s) * 1000000 + 10#end_us - 10#start_us`).
- Version-safe `BASH_MONOSECONDS` / `EPOCHREALTIME` fallback dispatch: `references/version-features.md`.

[LOGGING_ARCHITECTURE]:
- `declare -Ar _LOG_EMIT=([json]=_log_json [text]=_log_text_emit)` tables the emitters.
- Format resolves once at startup: `readonly _LOG_EMITTER="${_LOG_EMIT[${LOG_FORMAT:-text}]}"`.
- `_log()` gates on `_LOG_LEVELS` numeric threshold, then dispatches via `"${_LOG_EMITTER}"` — zero branching per call.
- JSON emitter: `jq -nc --arg` for injection-safe serialization with `EPOCHREALTIME` microsecond timestamps and optional W3C trace context fields.
- `FUNCNAME` offset accounts for `_info` -> `_log` -> `_LOG_EMITTER` call chain depth (typically `FUNCNAME[3]`, `BASH_LINENO[2]`).

[SURFACE]:
- `_` prefix for all internal functions. Public surface = `_main` entry point only.
- One dispatch table per concern — extend by adding entries, not code branches.
- No utility/helper files — colocate all logic in the script. `source` only for test frameworks.
- `--self-test` flag runs embedded smoke tests and exits — validates dispatch tables, config parsing, and key pure functions.
- ~350 LOC scrutiny threshold — investigate compression via dispatch tables and awk programs, not file splitting.

[RESOURCES]:
- Temporary files: `mktemp` + `_register_cleanup "rm -f -- $(printf '%q' "${tmp}")"` or an equivalent static quoted cleanup template.
- Work directories: `mktemp -d` with `SRANDOM` in path for uniqueness.
- Signal forwarding for PID 1: trap TERM/INT, `kill -"${sig}" "${_CHILD_PID}"`, exit with signal code (143/130). Guard on `(( _CHILD_PID > 0 ))`.
- `BASH_TRAPSIG` carries the signal number, so one unified handler routes every signal through a dispatch table.
- `GLOBSORT` controls glob ordering (e.g., `-mtime` for newest-first file discovery).
- Retry: `_retry_exec max delay max_delay cmd...` — backoff `delay=$(( delay * 2 > max_delay ? max_delay : delay * 2 ))` with `SRANDOM` jitter.
- Env contracts: `declare -Ar _ENV_CONTRACT=([VAR]='^regex$')` validated at startup — dispatch table over env vars, regex per key.
- Health endpoint: `socat TCP-LISTEN:${port},reuseaddr,fork SYSTEM:"printf 'HTTP/1.1 200 OK\r\n...'"` backgrounded with cleanup registration.
- W3C tracing: parse `TRACEPARENT` via `BASH_REMATCH`, generate via `printf -v TRACE_ID '%08x%08x%08x%08x' "${SRANDOM}"...`, export for children.

## [05]-[ANTI_PATTERNS]

[STATE_VIOLATIONS]:
- MUTABLE STATE: `let`/global mutation outside `declare -g` config loading. Use `local -r`/`readonly`; freeze parsed args in `_main`.
- FORK IN HOT PATH: `$(date)`, `$(cat file)`, `$(wc -l < file)` in loops. Use `printf -v`, `$(<file)`, `EPOCHSECONDS`, `mapfile`.

[CONTROL_FLOW_VIOLATIONS]:
- IMPERATIVE DISPATCH: `if/elif/else` chain for command routing. Use `declare -Ar` dispatch table + O(1) lookup.
- WHILE-READ COLLECTION: `while IFS= read -r line` loop to build arrays. Use `mapfile -t arr < <(cmd)`.
- UNMARKED STREAM LOOP: `while read` without a streaming-boundary comment. Streaming consumers are valid; collection loops are not.
- NAKED WRITE: Direct `>` or `>>` for output files. Use `mktemp` + `mv` atomic pattern.

[SAFETY_VIOLATIONS]:
- HARDCODED FD: `exec 3>file` with literal FD numbers. Use `exec {fd}>file` for safe dynamic allocation.
- UNQUOTED EXPANSION: `$var` without quotes. Always `"${var}"` — exceptions only in `(( ))` arithmetic.
- EVAL INJECTION: `eval "$user_string"` with untrusted input. Use `declare -Ar` dispatch or `case/esac` pattern match.
- ECHO OVER PRINTF: `echo -e`/`echo -n` for formatted output. Use `printf` — portable, no ambiguity, format strings.

[ORGANIZATION_VIOLATIONS]:
- UTILITY EXTRACTION: `lib/utils.sh`, `common.sh` helper files. Colocate all logic in the script.
- RANDOM OVER SRANDOM: `$RANDOM` for security-relevant randomness (temp names, jitter, tokens). Use `$SRANDOM` (cryptographic entropy).

## [06]-[VALIDATION_GATE]

- Required: `bash -n script.sh` (syntax check), ShellCheck clean (static analysis).
- Required for executable examples: run `--self-test` when present.
- Reject completion when strict mode, readonly discipline, ShellCheck compliance, or example self-tests are not satisfied.

## [07]-[FIRST_CLASS_TOOLS]

| [INDEX] | [TOOL]       | [PROVIDES]                                 |
| :-----: | :----------- | :----------------------------------------- |
|  [01]   | `bash`       | Shell runtime, builtins, `${ }`            |
|  [02]   | `shellcheck` | Static analysis, SC codes                  |
|  [03]   | `bats-core`  | Test framework, TAP output                 |
|  [04]   | `kcov`       | Coverage instrumentation                   |
|  [05]   | `rg`         | Content search, `.gitignore`-aware         |
|  [06]   | `fd`         | File search, `.gitignore`-aware            |
|  [07]   | `jq`         | JSON processing, streaming, `trim`, `skip` |
|  [08]   | `yq`         | YAML processing                            |
|  [09]   | `mlr`        | CSV/TSV/JSON format transforms             |
|  [10]   | `sd`         | Stream editing (sed replacement)           |
|  [11]   | `choose`     | Column selection (cut replacement)         |

Files in this skill

  • SKILL.md13.5 KB
  • examples/cli-tool.sh11.3 KB
  • examples/data-pipeline.sh12.1 KB
  • examples/service-wrapper.sh10.9 KB
  • references/array-operations.md14.1 KB
  • references/bash-logging.md19 KB
  • references/bash-portability.md15.6 KB
  • references/bash-scripting-guide.md15.7 KB
  • references/bash-testing.md25.7 KB
  • references/file-operations.md11.8 KB
  • references/script-patterns.md18 KB
  • references/string-operations.md14.5 KB
  • references/text-processing-guide.md14.3 KB
  • references/validation.md11.6 KB
  • references/variable-features.md14.6 KB
  • references/version-features.md27.3 KB
  • templates/standard.template.md8.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…