Posted on
Artificial Intelligence

Prompt Engineering Checklists

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Prompt Engineering Checklists for Bash Users

If you’ve ever asked an AI to “write a Bash one‑liner” and got back something brittle, unsafe, or just wrong, you’re not alone. The problem isn’t only the model—it’s the prompt. In the terminal, ambiguity becomes risk: a missing -i, an unquoted glob, or a misjudged rm can ruin your day. Prompt engineering checklists bring structure, repeatability, and safety to how you ask AI for shell help, so your outputs are predictable, testable, and safer to run.

This article shows how to turn prompt checklists into a practical, command-line workflow. You’ll learn why checklists work, get ready-to-use Bash snippets, and see real examples that reduce hallucinations and improve shell safety. Stick around for a complete script you can drop into your dotfiles.

Why checklists work (especially in Bash)

  • Consistency beats cleverness: Repeating a known-good structure (role, task, constraints, output) drastically improves quality.

  • Fewer foot‑guns: Safety rails like “dry run,” “don’t delete,” “quote all variables,” and “JSON output only” remove ambiguity.

  • Automatable: The same checklist can be wrapped in a Bash function, versioned, and reused in CI or your local scripts.

  • Debuggable: Deterministic outputs (e.g., JSON) can be parsed with jq and tested—no more screen‑scraping freeform text.

What you’ll need

We’ll use curl to call an LLM API, jq to parse responses, git for diffs, and shellcheck to lint AI‑generated scripts.

Install on Debian/Ubuntu (apt):

sudo apt update
sudo apt install -y curl jq shellcheck git

Install on Fedora/RHEL (dnf):

sudo dnf install -y curl jq ShellCheck git
  • On RHEL/CentOS, if ShellCheck isn’t found:
sudo dnf install -y epel-release
sudo dnf install -y ShellCheck

Install on openSUSE (zypper):

sudo zypper refresh
sudo zypper install -y curl jq ShellCheck git

Note: You’ll also need access to an LLM endpoint. The examples below use the OpenAI Chat Completions API, but you can adapt the same structure to another provider or a local server. Set your API key:

export OPENAI_API_KEY="sk-...your_key..."

The core checklist (R–T–C–O)

At the heart of reliable prompting is a small but powerful checklist:

  • Role: Who is the model supposed to be?

  • Task: What exactly should it do?

  • Constraints: What must it avoid? What context should it use?

  • Output: What exact format should it return?

Below is a drop‑in Bash helper that applies this checklist and adds shell‑friendly constraints.

Save as prompt-checklist.sh and source it from your shell.

#!/usr/bin/env bash
# prompt-checklist.sh
set -euo pipefail

: "${OPENAI_API_KEY:?Set OPENAI_API_KEY first}"

pe_env_inventory() {
  # Only include a focused, useful inventory to keep prompts compact.
  printf "OS: %s\n" "$(uname -a)"
  printf "Bash: %s\n" "$(bash --version | head -n1)"
  printf "Available tools:\n"
  for t in bash sh awk sed grep rg ripgrep fd find xargs tar gzip unzip curl wget jq python3 perl git make docker podman kubectl; do
    if command -v "$t" >/dev/null 2>&1; then
      printf " - %s: %s\n" "$t" "$(command -v "$t")"
    fi
  done
}

pe_call_openai() {
  local user_content="$1"
  curl -sS https://api.openai.com/v1/chat/completions \
    -H "Authorization: Bearer ${OPENAI_API_KEY}" \
    -H "Content-Type: application/json" \
    -d @- <<'JSON' | jq -r '.choices[0].message.content'
{
  "model": "gpt-4o-mini",
  "temperature": 0,
  "messages": [
    {
      "role": "system",
      "content": "You are a senior Bash, POSIX shell, and Linux CLI engineer. Prefer portable, safe, idempotent solutions, explain trade-offs briefly only when asked."
    },
    {
      "role": "user",
      "content": "USER_CONTENT_PLACEHOLDER"
    }
  ]
}
JSON
}

# Compose a robust prompt with R–T–C–O
pe_prompt() {
  local role="$1" task="$2" constraints="$3" output_spec="$4"
  local env_info
  env_info="$(pe_env_inventory)"

  local prompt
  prompt=$(cat <<EOF
ROLE:
$role

TASK:
$task

CONSTRAINTS:

- Use only commands likely available on a typical Linux CLI.

- Never run destructive actions by default; prefer --dry-run or print commands.

- Quote all variables; avoid word splitting and globbing issues.

- Add 'set -euo pipefail' to any script output.

- If something is dangerous (rm, dd, chmod -R, find -delete), propose a safer alternative first.

- Respect this environment:
$env_info

OUTPUT:
$output_spec
EOF
)
  # Replace placeholder and call the API
  pe_call_openai "${prompt//\"/\\\"}" | sed 's/```//g'
}

# Example helper: ask for JSON with explanation + safe command
pe_explain_and_sanitize() {
  local cmd="$*"
  pe_prompt \
    "You are auditing and improving Bash one-liners." \
    "Explain what this command does and emit a safer alternative if needed:\n$cmd" \
    "Be precise and mention edge cases." \
    "Return strict JSON with keys: explanation (array of bullet strings), safe_command (string), notes (array). No extra text."
}

Source it:

source ./prompt-checklist.sh

Test it on a risky command:

pe_explain_and_sanitize 'find . -type f -mtime -7 -print0 | xargs -0 tar -cvzf recent.tar.gz -T -' | jq .

You’ll get machine‑parsable JSON you can inspect, log, or feed into other scripts.

4 actionable checklists you can use today

1) Job framing: R–T–C–O template

  • Role: Set expertise (Linux + Bash), not “generalist.”

  • Task: Be specific (“convert to idempotent script,” “explain line by line,” “emit only JSON”).

  • Constraints: Safety first—dry runs, quoted vars, portability, no sudo assumptions, mention alternatives.

  • Output: JSON keys, or a single Bash script block with no commentary.

Example (JSON‑only request):

pe_prompt \
  "Senior Linux/Bash engineer" \
  "Given a directory with mixed media files, produce a plan to normalize names to snake_case and a safe, idempotent Bash script to do it." \
  "Handle collisions, preserve extensions, log changes, and preview first." \
  "Strict JSON: { plan: string, preview_command: string, script: string }"

Then parse:

pe_prompt ... | jq -r '.script' > normalize.sh
chmod +x normalize.sh
bash normalize.sh --dry-run

2) Ground the model with your environment Many bad suggestions come from the model assuming tools you don’t have. Include a compact inventory:

  • OS/binary versions (e.g., GNU vs BusyBox).

  • Core tools present (jq, ripgrep, fd, etc.).

  • Any constraints (no root, no internet).

pe_env_inventory adds this automatically. If you need more, append:

extra="No root access. Home directory has 5GB free. Network is firewalled."
pe_prompt "Senior Bash engineer" \
  "Generate a script to index *.log files into a single CSV with columns ts,level,msg." \
  "Do not fetch anything from the internet. $extra" \
  "Emit only a Bash script, no prose."

3) Demand deterministic, testable output Freeform text is hard to automate. Prefer:

  • JSON for plans, diffs, and structured advice.

  • A single, self-contained Bash script with set -euo pipefail at top.

  • Use jq to validate and extract fields.

Example: get a plan and a script, then run the preview:

resp="$(pe_prompt \
  "SRE teammate" \
  "Rotate logs larger than 50MB in ./logs (keep 7 compressed backups)." \
  "No root; work on GNU userland; idempotent; preview first." \
  "JSON: { preview: string, script: string, caveats: [string] }")"

echo "$resp" | jq -r '.preview' | bash
echo "$resp" | jq -r '.script' > rotate.sh
shellcheck rotate.sh
bash rotate.sh

4) Build safety rails into every prompt Bake in guardrails and keep them non‑negotiable:

  • “No destructive actions by default; provide preview.”

  • “Quote all variables; use -- after options; avoid for f in * where find -print0 + xargs -0 is safer.”

  • “Add comments that indicate which lines to review before running.”

  • “Use temporary directories; clean up on exit with trap.”

Example one‑liner to request a safe refactor:

pe_prompt \
  "Bash safety auditor" \
  "Refactor this to be safer and POSIX‑portable: for f in *.txt; do cat $f >> all.txt; done" \
  "Avoid globbing pitfalls and handle filenames with spaces/newlines." \
  "Emit only a Bash script."

Bonus: Lint what you get back

shellcheck -S style -x script.sh

If ShellCheck isn’t installed:

  • apt: sudo apt install -y shellcheck

  • dnf: sudo dnf install -y ShellCheck

  • zypper: sudo zypper install -y ShellCheck

Real‑world example: Explain and make safer

Let’s analyze and improve a classic risky pipeline.

Command:

find . -type f -mtime -7 -print0 | xargs -0 tar -cvzf recent.tar.gz -T -

Run:

pe_explain_and_sanitize 'find . -type f -mtime -7 -print0 | xargs -0 tar -cvzf recent.tar.gz -T -' | jq -r '.explanation[], .notes[]'

Then inspect the suggested safe_command:

pe_explain_and_sanitize 'find . -type f -mtime -7 -print0 | xargs -0 tar -cvzf recent.tar.gz -T -' | jq -r '.safe_command'

Expectations from a good answer:

  • Explain -print0/-0 handling of spaces/newlines.

  • Point out that -T - expects file list on stdin and that xargs may be redundant.

  • Suggest a safer alternative, e.g., using tar --null --files-from directly and perhaps a --warning=no-file-changed and a dry‑run preview:

find . -type f -mtime -7 -print0 \
  | tar --null --files-from=- -czvf recent.tar.gz --no-recursion

Troubleshooting and tips

  • Getting tools you don’t have? Expand pe_env_inventory to list more explicitly what exists and what’s forbidden.

  • Outputs too chatty? Set temperature: 0 and require “JSON only” or “script only.”

  • Need diffs instead of full files? Ask for unified diff format and apply with patch:

pe_prompt \
  "Diff-focused Bash editor" \
  "Given this script, add robust error handling and logging." \
  "Keep behavior the same; only add safety/logging." \
  "Output unified diff only."

# Save diff to change.patch and apply:
git init -q && git add script.sh && git commit -qm "base"
pe_prompt ... > change.patch
git apply --index change.patch && git commit -qm "AI edit"

Conclusion and next step (CTA)

Checklists turn vague, risky prompts into reliable, automatable workflows for the shell. Start using the R–T–C–O template, include your environment, demand deterministic output, and embed safety rails.

Next steps: 1) Copy prompt-checklist.sh into your dotfiles and source it in your shell startup. 2) Install prerequisites: - apt: sudo apt update && sudo apt install -y curl jq shellcheck git - dnf: sudo dnf install -y curl jq ShellCheck git - zypper: sudo zypper install -y curl jq ShellCheck git 3) Try pe_explain_and_sanitize 'your command here' on a risky one‑liner from your history. 4) Evolve the checklist to your team’s standards, and version it in git.

Your shell is powerful—use prompts that respect it.