with one click
shell
Shell scripting, CLI development, Bash, PowerShell, Makefiles, and cross-platform tooling. Activate when working with .sh, .bash, .ps1, Makefile files or discussing shell/CLI patterns.
Menu
Shell scripting, CLI development, Bash, PowerShell, Makefiles, and cross-platform tooling. Activate when working with .sh, .bash, .ps1, Makefile files or discussing shell/CLI patterns.
| name | shell |
| description | Shell scripting, CLI development, Bash, PowerShell, Makefiles, and cross-platform tooling. Activate when working with .sh, .bash, .ps1, Makefile files or discussing shell/CLI patterns. |
| Task | Tool | Command |
|---|---|---|
| Lint | shellcheck | shellcheck *.sh |
| Format | shfmt | shfmt -w *.sh |
| Security | shellharden | shellharden --check *.sh |
| POSIX check | checkbashisms | checkbashisms *.sh |
| Test | bats | bats test/ |
Scripts MUST use the portable shebang:
#!/usr/bin/env bash
POSIX-only scripts MAY use #!/bin/sh when bash features are not needed.
All bash scripts MUST enable strict mode:
set -euo pipefail
| Flag | Meaning |
|---|---|
-e | Exit on error |
-u | Error on undefined variables |
-o pipefail | Fail on pipe errors |
Variables MUST be quoted to prevent word splitting:
# Correct
echo "$variable"
cp "$source" "$destination"
# Incorrect
echo $variable
Arrays MUST use proper expansion:
"${array[@]}" # Each element as separate word
"${array[*]}" # All elements as single string
| Scope | Convention | Example |
|---|---|---|
| Environment/Global | UPPER_CASE | LOG_LEVEL, CONFIG_PATH |
| Local/Script | lower_case | file_count, temp_dir |
| Constants | UPPER_CASE + readonly | readonly MAX_RETRIES=3 |
No magic values: MUST NOT use literal strings or numbers inline when they represent a domain concept, configuration, or repeated value. Extract to readonly constants at the top of the script. Literals are fine for array indices, test assertions, single-use messages, and well-known exit codes (0, 1, 2).
In bash scripts, [[ ]] MUST be used over [ ]:
if [[ -f "$file" ]]; then
echo "File exists"
fi
if [[ "$string" =~ ^[0-9]+$ ]]; then
echo "Numeric"
fi
POSIX scripts MUST use [ ] for compatibility.
Functions MUST use local for internal variables:
my_function() {
local input="$1"
local result=""
result=$(process "$input")
echo "$result"
}
Naming: snake_case, prefix private functions with underscore: _helper_function
Temporary files MUST be created with mktemp using simple assignments:
temp_file="$(mktemp)"
temp_dir="$(mktemp -d)"
Named templates are allowed when useful:
temp_file="$(mktemp -t my-tool.XXXXXX)"
temp_file="$(mktemp /tmp/my-tool.XXXXXX)"
Cleanup MUST be easy to verify. Prefer exact quoted targets and --:
rm -f -- "$temp_file"
rm -rf -- "$temp_dir"
For multi-step scripts, use an EXIT trap with the same exact cleanup form:
temp_file="$(mktemp)"
trap 'rm -f -- "$temp_file"' EXIT
When a temporary directory owns derived files, keep child paths directly under that directory and clean up either the child file or the directory:
temp_dir="$(mktemp -d)"
output_file="$temp_dir/output.txt"
rm -f -- "$output_file"
rm -rf -- "$temp_dir"
Do not use cleanup forms that are hard to verify:
rm -f /tmp/*.tmp
rm -f -- "${temp_file:-/}"
rm -f -- "$temp_file" "$HOME/important-file"
temp_file="$(some_command)"
rm -f -- "$temp_file"
Do not reassign a temp variable before cleanup. Do not execute a temp file with
bash, sh, source, or . unless that execution is the explicit purpose of
the script and the payload is reviewed separately.
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Misuse (invalid arguments, missing dependencies) |
main() {
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <argument>" >&2
exit 2
fi
if ! process_data "$1"; then
echo "Error: Processing failed" >&2
exit 1
fi
}
# Continue on optional failure
rm -f "$optional_file" || true
# Exit on critical failure
cd "$required_dir" || exit 1
# Custom error message
command_that_might_fail || {
echo "Error: command failed" >&2
exit 1
}
| Feature | POSIX | Bash |
|---|---|---|
| Test syntax | [ ] | [[ ]] |
| Arrays | Not available | Supported |
local | Not standard | Supported |
source | Use . | Both work |
| Process substitution | Not available | <(cmd) |
validate_input() {
local input="$1"
if [[ -z "$input" ]]; then
echo "Error: Input cannot be empty" >&2
return 1
fi
if [[ ! "$input" =~ ^[a-zA-Z0-9_-]+$ ]]; then
echo "Error: Invalid characters" >&2
return 1
fi
}
Modern syntax MUST be used:
# Correct
result=$(command)
# Incorrect - MUST NOT use backticks
result=`command`
log_info() {
echo "[INFO] $*"
}
log_error() {
echo "[ERROR] $*" >&2
}
log_debug() {
[[ "${DEBUG:-0}" == "1" ]] && echo "[DEBUG] $*"
}
#!/usr/bin/env bash
set -euo pipefail
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"
usage() {
cat <<EOF
Usage: $SCRIPT_NAME [options] <argument>
Options:
-h, --help Show this help message
-v, --verbose Enable verbose output
EOF
}
main() {
local verbose=0
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
-v|--verbose)
verbose=1
shift
;;
*)
break
;;
esac
done
if [[ $# -lt 1 ]]; then
usage >&2
exit 2
fi
# Script logic here
}
main "$@"
Scripts SHOULD NOT exceed 100 lines (excluding comments/blanks).
When a script exceeds 100 lines:
Brave browser tab URL capture. Activate when the user asks to capture, export, list, archive, save, or recover open Brave tabs, browser tabs, tab URLs, or session files.
Private datastore workflow. Activate when writing, saving, archiving, packing, encrypting, committing, or storing sensitive local files under private/ or Dolos encrypted archives.
Use when working with X/Twitter: x.com feed extraction, tweet/profile checks, following/follower lists, twitterapi.io, browser-agent pulls, or local encrypted X data handling.
Use when the user asks to create, draft, write, improve, optimize, or build an inline Pi /goal command, goal prompt file, long-running objective, or goal_prompt_file.md. Triggers: /goal prompt, goal prompt, pi goal, goal_prompt_file.md, write a goal for, turn this into a goal.
Personal development philosophy emphasizing experiment-driven, fail-fast approach. Activate when planning implementations, reviewing code architecture, making design decisions, or when user asks to apply development principles. Guides against over-engineering and towards solving real problems with simple solutions.
Activate when user mentions analyze, review, validate, critique, debug, troubleshoot, red-team, adversarial, or "what could go wrong". Use for code review, debugging, validation, and error investigation.