martinholovsky/sota-skills · Archived

sota-shell-scripting

>- State-of-the-art shell scripting (bash-focused, defensive) for writing and auditing shell scripts, CI scripts, init/deploy scripts, container entrypoints, and Makefile recipes. Use when the task involves creating, modifying, reviewing, or hardening any shell code — trigger keywords: bash, shell script, sh, zsh, shellcheck, shfmt, CI script, Makefile shell, entrypoint script, set -euo pipefail, dotfiles, install script, cron job, wrapper script.

First seen Jun 17, 2026

Installation

$ npx skills add martinholovsky/sota-skills --skill sota-shell-scripting

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from martinholovsky/sota-skills · top by installs.

npx skills add martinholovsky/sota-skills

Browse all from martinholovsky/sota-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 18
License LICENSE
Default branch main
Open issues 0
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,736 B
  • docs SUMMARY.md 478 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

SOTA Shell Scripting

Purpose: produce shell scripts that survive contact with reality — unusual filenames, missing commands, partial failures, hostile input, signals, and concurrent invocation — and audit existing scripts for the defect classes that cause most production shell incidents: unquoted expansions, silent error swallowing, injection, secret leakage, and temp-file races.

Bash-focused (bash 5.x current; macOS ships bash 3.2 and defaults to zsh — see portability rules). POSIX sh only when the target demands it (busybox/dash containers, init systems).

First decision: should this be shell at all?

Do NOT use shell when any of these hold. Recommend Python/Go (or the project's primary language) instead, and say so explicitly in BUILD and AUDIT output:

  • Script exceeds ~100 lines of actual logic (not counting boilerplate/usage text).
  • Needs real data structures (nested maps, JSON manipulation beyond a jq one-liner, sets).
  • Needs granular error handling (retry this step, distinguish error kinds, partial rollback).
  • Does arithmetic beyond integers, date math, or float comparison.
  • Parses structured formats (JSON/YAML/XML) with string surgery instead of jq/yq.
  • Needs portable concurrency beyond "run N jobs and wait".
  • Is security-critical input handling (auth, parsing untrusted network data).

Shell is the right tool for: gluing processes together, CI steps, container entrypoints, small install/deploy wrappers, environment setup — anything that is mostly invoking other programs rather than computing.

BUILD mode

When writing or modifying shell scripts:

  1. Pick the dialect deliberately. #!/usr/bin/env bash unless the target is a minimal

container/init context that only guarantees POSIX sh. Never #!/bin/sh with bashisms.

  1. Start every bash script from the safety preamble (rules/01): set -euo pipefail,

trap-based cleanup, IFS discipline — and know where set -e does NOT fire.

  1. Quote every expansion. "$var", "$@", "$(cmd)". Build commands with arrays,

never with string concatenation.

  1. Errors are loud and routed to stderr with script name + context; exit codes are

meaningful and documented in --help.

  1. Make it idempotent and interrupt-safe: mktemp + trap cleanup, atomic writes via

mv, check-before-create, flock if concurrent runs are possible.

  1. **Run shellcheck (treat all findings as blockers, suppress only with a justifying

comment) and shfmt -d before declaring done.** If they are unavailable locally, state that and flag CI must run them.

  1. Provide --help always; --version for distributed tools; set -x behind a

DEBUG/TRACE env guard, never unconditionally (secret leakage).

AUDIT mode

When reviewing existing shell scripts, hunt the defect classes in rules/ files bottom-up (each rules file ends with an audit checklist of grep patterns and ShellCheck codes). Run shellcheck -S style on every script if available; correlate findings with context — ShellCheck flags symptoms, you judge exploitability and blast radius.

Severity conventions:

Severity Meaning Examples
CRITICAL Exploitable or data-destroying now eval on untrusted input; unquoted var in rm -rf; secrets in argv/set -x; curl\ bash of unpinned URL in prod
HIGH Will corrupt/fail on realistic input or failure unquoted expansions in destructive paths; missing set -e/error checks around critical steps; predictable temp files; non-atomic config writes; missing exec in entrypoint (signals lost)
MEDIUM Latent bug or fragility parsing ls; which instead of command -v; missing pipefail; no -- separators; no timeouts on network calls; echo for variable data
LOW Style/maintainability with safety implications missing local; [ ] where [[ ]] intended; missing readonly; inconsistent error messages

Finding format:

[SEVERITY] file:line — short title (SCxxxx if applicable)
  Evidence: the offending line(s), verbatim
  Impact: what input/condition triggers it and what breaks
  Fix: concrete replacement code
  Effort: trivial | small | medium | large

Rules index

File Covers
[rules/01-safety-baseline.md](rules/01-safety-baseline.md) Shebang discipline, set -euo pipefail and its real limitations, quoting & word-splitting bug catalog, zsh-vs-bash deviations that bite pasted commands (joining, pipestatus, and NOMATCH — an unquoted glob in a flag value aborts the command and fakes a clean sweep), arrays, IFS, traps & mktemp cleanup, [[ ]], printf, local/readonly, globbing pitfalls, never parse ls
[rules/02-robustness-correctness.md](rules/02-robustness-correctness.md) Argument parsing (getopts/while-case, --help/--version), input validation, POSIX vs bash portability, stderr/exit-code discipline, PIPESTATUS, command -v, network timeouts & retries, flock & background jobs, idempotency & atomic writes, safe filename handling
[rules/03-security.md](rules/03-security.md) eval/injection, secrets discipline (argv/env/set -x), PATH hygiene, sudo discipline, curl\ bash both directions, temp-file races, umask, ShellCheck+shfmt in CI
[rules/04-ci-and-operational.md](rules/04-ci-and-operational.md) GitHub Actions shell pitfalls (${{ }} injection, multiline run, quoting in YAML), container entrypoints (exec, PID 1, privilege drop), Makefile shell gotchas, long-running script logging

Top 10 non-negotiables

  1. #!/usr/bin/env bash + set -euo pipefail on every bash script — and explicit error

handling where -e is known not to fire (conditions, &&/||, command substitution in assignments-with-modifiers, process substitution).

  1. Quote every expansion: "$var", "$@", "${arr[@]}", "$(cmd)". SC2086 is a

bug, not style.

  1. Build argument lists with arrays; pass them as "${args[@]}". Never accumulate a

command in a string and eval/word-split it.

  1. trap cleanup EXIT with an idempotent cleanup function; temp paths only via mktemp.
  2. Never eval, bash -c, or sh -c with interpolated untrusted data; use -- before

positional file/user arguments to every command that supports it.

  1. No secrets in argv, in environment dumps, or under set -x; set +x around sensitive

sections; read secrets from files or fds.

  1. Errors to stderr with context (script: failed to X: $detail); meaningful exit codes;

never exit 0 on failure paths.

  1. Network calls get --fail, --max-time/timeouts, and bounded retries — never bare

curl url | ....

  1. Handle arbitrary filenames: find -print0 | xargs -0 / -exec ... +, while IFS= read -r,

never iterate $(ls) or unquoted globs from variables.

  1. ShellCheck (clean, or annotated suppressions) + shfmt enforced in CI; a shell script

without CI linting is unreviewed code.

Cross-references

  • CI pipeline hardening, ${{ }} injection, action pinning → sota-devsecops
  • Secret storage/rotation → sota-secrets-management
  • Container image/runtime hardening → sota-sandboxing, sota-cloud-infrastructure
  • When the "don't use shell" rule fires → sota-python / sota-golang