- Posted on
- • Artificial Intelligence
Automatically Generate Bash Functions with Artificial Intelligence
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Automatically Generate Bash Functions with Artificial Intelligence
You know that tiny shell helper you’ve been meaning to write—again? The one to mkdir + cd, parse logs, or kill a process safely? What if you could turn “I want a function that…” into a robust, shellchecked Bash function in seconds?
In this article you’ll learn how to wire up a small Bash tool that asks an AI model to write safe, documented Bash functions on demand, drops them into a reusable file, and loads them into your shell automatically. You’ll get step‑by‑step setup, real examples, and practical guardrails so the output is both fast and trustworthy.
Why this is worth your time
Bash is everywhere. Clean functions speed up daily tasks, CI scripts, and remote maintenance.
LLMs are surprisingly good at producing shell snippets—if you prompt them well and add validation.
You can standardize your functions, keep them versioned, and share across your team.
With a thin wrapper, you can go from intent to working function with minimal friction.
Prerequisites and installation
We’ll use curl for API calls and jq to parse JSON. ShellCheck is optional but recommended for safety.
Install these with your package manager:
Debian/Ubuntu (apt):
sudo apt update sudo apt install -y bash curl jq shellcheck ca-certificatesFedora/RHEL/CentOS (dnf):
sudo dnf install -y bash curl jq ShellCheck ca-certificatesopenSUSE (zypper):
sudo zypper refresh sudo zypper install -y bash curl jq ShellCheck ca-certificates
You’ll also need an AI API. The script below defaults to OpenAI’s Chat Completions API, but you can point it at any OpenAI‑compatible endpoint. Set your API key as an environment variable:
export OPENAI_API_KEY="sk-...your-key..."
Tip: Add that line to ~/.bashrc or your secret manager, not your public dotfiles.
Step 1 — Create the generator script
Save the following as ~/.local/bin/ai-func and make it executable:
mkdir -p ~/.local/bin
chmod 700 ~/.local/bin
cat > ~/.local/bin/ai-func <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
usage() {
cat <<USAGE
ai-func: Generate and install a Bash function with help from an AI model.
Usage:
ai-func [-m MODEL] [-e ENDPOINT] [-t TEMP] <function_name> <free-form description>
Environment:
OPENAI_API_KEY API key (required for most hosted providers)
AI_MODEL Default model (e.g., gpt-4o-mini). Can be overridden with -m.
AI_ENDPOINT Default endpoint. Can be overridden with -e.
BASH_AI_FILE Destination file for generated functions (default: ~/.bash_ai_functions)
Examples:
ai-func mkcd "Create a directory if missing and cd into it; support -p, print final path"
ai-func px "Find processes by substring and interactively confirm before sending SIGTERM"
USAGE
}
command -v curl >/dev/null || { echo "curl not found. Install with apt/dnf/zypper."; exit 1; }
command -v jq >/dev/null || { echo "jq not found. Install with apt/dnf/zypper."; exit 1; }
AI_MODEL="${AI_MODEL:-gpt-4o-mini}"
AI_ENDPOINT="${AI_ENDPOINT:-https://api.openai.com/v1/chat/completions}"
TEMP="0.2"
DEST="${BASH_AI_FILE:-$HOME/.bash_ai_functions}"
while getopts ":m:e:t:h" opt; do
case "$opt" in
m) AI_MODEL="$OPTARG" ;;
e) AI_ENDPOINT="$OPTARG" ;;
t) TEMP="$OPTARG" ;;
h) usage; exit 0 ;;
*) usage; exit 2 ;;
}
done
shift $((OPTIND - 1))
if [ "$#" -lt 2 ]; then
usage
exit 2
fi
FUNC_NAME="$1"; shift
DESCRIPTION="$*"
# Build a careful prompt for safer Bash.
SYS_PROMPT=$'You are an expert Bash engineer. You write portable, safe Bash functions.\nRules:\n- Output ONLY a single Bash function inside one fenced code block: ```bash ... ```\n- The function name must be exactly as requested.\n- Use strict, defensive coding (set -u is fine; avoid set -e inside the function unless very deliberate).\n- Quote variables; avoid unsafe word splitting and globbing.\n- Print usage/help when args are invalid; return non-zero on error.\n- Write clear error messages to stderr.\n- Prefer built-ins where practical; avoid external deps unless necessary.\n- No comments or text outside the single fenced code block.'
USER_PROMPT=$(cat <<EOP
Write a Bash function named "$FUNC_NAME" that does the following:
$DESCRIPTION
Requirements:
- Must be a single Bash function definition named "$FUNC_NAME".
- Include a brief usage guard and helpful error messages.
- Be idempotent and robust where reasonable.
- Avoid destructive defaults.
Return ONLY a fenced code block containing the function.
EOP
)
JSON_REQ=$(jq -n \
--arg model "$AI_MODEL" \
--arg sys "$SYS_PROMPT" \
--arg user "$USER_PROMPT" \
--argjson temp "$TEMP" \
'{model:$model, temperature:$temp, messages:[{role:"system",content:$sys},{role:"user",content:$user}]}')
# Prepare headers (OpenAI-compatible). If you point AI_ENDPOINT elsewhere, ensure it accepts these.
HEADERS=(-H "Content-Type: application/json")
if [ -n "${OPENAI_API_KEY:-}" ]; then
HEADERS+=(-H "Authorization: Bearer ${OPENAI_API_KEY}")
fi
RAW=$(curl -sS "${HEADERS[@]}" -X POST -d "$JSON_REQ" "$AI_ENDPOINT" || true)
# Try to read OpenAI-style content. Fall back if provider differs.
CONTENT=$(jq -r '
.choices[0].message.content // .choices[0].text // .message?.content // .error?.message // empty
' <<<"$RAW")
if [ -z "$CONTENT" ]; then
echo "AI response was empty or invalid:"
echo "$RAW"
exit 1
fi
# Extract code between the first and second triple backticks.
CODE=$(awk '
BEGIN{inblock=0}
/^```/{
if(inblock==0){ inblock=1; next }
else { inblock=0; exit }
}
inblock==1{print}
' <<<"$CONTENT")
# If we failed to detect fenced code, assume the entire content is code.
if [ -z "$CODE" ]; then
CODE="$CONTENT"
fi
mkdir -p "$(dirname "$DEST")"
touch "$DEST"
# Replace previous block for this function using BEGIN/END markers.
TMP="$(mktemp)"
START="# BEGIN AIFUNC:${FUNC_NAME}"
END="# END AIFUNC:${FUNC_NAME}"
awk -v start="$START" -v end="$END" '
BEGIN{skip=0}
$0==start {skip=1; next}
$0==end {skip=0; next}
skip==0 {print}
' "$DEST" > "$TMP"
{
cat "$TMP"
printf "%s\n" "$START"
printf "%s\n" "$CODE"
printf "%s\n" "$END"
} > "$DEST"
rm -f "$TMP"
# Optionally lint with ShellCheck if available.
if command -v shellcheck >/dev/null; then
printf "%s\n" "$CODE" | shellcheck - --shell=bash -S warning -x || true
fi
# Ensure the file is sourced in future shells.
if ! grep -qF "$DEST" "$HOME/.bashrc" 2>/dev/null; then
{
echo ""
echo "# Load AI-generated functions"
echo "[ -r \"$DEST\" ] && source \"$DEST\""
} >> "$HOME/.bashrc"
echo "Added source line to ~/.bashrc"
fi
# Source now for the current session, if interactive.
if [ -r "$DEST" ]; then
# shellcheck disable=SC1090
source "$DEST"
fi
# Show the newly created function.
echo "Generated function '$FUNC_NAME'. Preview:"
type "$FUNC_NAME" || true
EOF
chmod +x ~/.local/bin/ai-func
Ensure ~/.local/bin is on your PATH:
case ":$PATH:" in
*:$HOME/.local/bin:*) ;;
*) echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc ;;
esac
source ~/.bashrc
Step 2 — Configure your AI endpoint and model
Default endpoint: https://api.openai.com/v1/chat/completions
Default model: gpt-4o-mini (tweak with -m)
Examples:
export OPENAI_API_KEY="sk-...your-key..."
export AI_MODEL="gpt-4o-mini" # or another model your provider supports
export AI_ENDPOINT="https://api.openai.com/v1/chat/completions"
You can also override per command with -m and -e.
Step 3 — Generate your first function
Let’s create a safe mkcd helper:
ai-func mkcd "Create a directory if missing and cd into it; support -p flag; print final path; return non-zero on errors; do not follow symlinks into files"
Then use it:
mkcd -p ./sandbox/project
pwd
The function body is saved in ~/.bash_ai_functions with markers so you can track and update it safely.
Step 4 — Validate and iterate
The script will run ShellCheck automatically if installed and show any warnings.
If the function isn’t quite right, re-run ai-func with a clearer description. The existing block will be replaced in place.
You can keep ~/.bash_ai_functions under version control (or copy functions into your dotfiles repo) for auditability and rollbacks.
Step 5 — Real-world examples you can try now
Use these prompts as-is; the script will turn them into functions instantly.
1) Safer process killer with confirmation
ai-func px "Find processes whose command line contains a substring; list candidates with PIDs; prompt interactively before sending SIGTERM by default; support -s SIGNAL (e.g., -s 9); refuse to kill PID 1 or itself; print errors to stderr"
Usage:
px ssh
px -s 9 chrome
2) Pretty Git graph
ai-func git_graph "Show a compact git log graph with decorated refs; default to last 20 commits; support -n N; detect if not in a git repo and print a helpful message"
Usage:
git_graph
git_graph -n 50
3) JSON fetch-and-pretty-print (uses curl + jq)
ai-func httpjson "Fetch a URL over HTTP(S) and pretty-print JSON; support -H header multiple times; support -d data for POST; validate content-type when possible; handle network errors robustly; requires jq"
Usage:
httpjson https://api.github.com/repos/tux/awesome
httpjson -H 'Accept: application/json' -d '{"q":"bash"}' https://httpbin.org/post
4) Disk usage summary for the current tree
ai-func dus "Summarize disk usage for the current directory; show top 10 largest items; support -a to include hidden files; handle permission errors gracefully"
Usage:
dus
dus -a
If you want to adjust the style or constraints (e.g., insist on POSIX sh compatibility), put that in your description—your prompt is part spec, part test.
Tips for safer automation
Be explicit in prompts about error handling, quoting, return codes, and non-destructive defaults.
Keep ShellCheck installed; treat warnings as a review checklist.
Skim the generated code. It’s fast, not magic—trust but verify.
Version your functions file and review diffs in code review like any other change.
Conclusion and next steps
With a 100-line Bash wrapper, you’ve turned “I wish I had a function for…” into a one-liner that generates, lint-checks, installs, and loads that function for you. Start with mkcd and px, then build out a personal toolbox tailored by short, clear prompts.
Call to action:
Install the prerequisites and drop ai-func onto your PATH.
Generate two helpers you’ve rewritten more than once this month.
Put ~/.bash_ai_functions under version control and share the best ones with your team.
Your shell just got an AI pair-programmer—put it to work.