Posted on
Artificial Intelligence

Your First AI-Powered Bash Script

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

Your First AI-Powered Bash Script

Ever wished you could ask your terminal to “explain that weird one-liner,” “write a safe Bash snippet,” or “summarize this log file” on the spot? With a tiny Bash script and a single environment variable, you can bolt AI directly onto your command line and supercharge your workflow—no IDE plugins, no heavyweight apps.

In this guide, you’ll build a small, dependable Bash script that:

  • Talks to an AI model via curl (cloud-based or local)

  • Explains commands, generates snippets, and summarizes files

  • Plays nicely with Linux tooling (pipes, redirection, environment variables)

We’ll cover setup, the “why,” and 3–5 practical, real-world examples you can adopt today.


Why put AI in Bash?

  • It’s where your work happens: You already think and operate in the shell; AI should fit that flow.

  • Composable: AI output can feed into pipes, files, or other commands.

  • Lightweight and universal: Works over SSH, inside containers, and on minimal systems.

  • Auditable: You see every request leaving your machine and can script guardrails.


Prerequisites (install with your package manager)

We’ll use curl to call an API and jq to handle JSON. Install them with your distro’s package manager:

  • Debian/Ubuntu (apt):

    sudo apt update
    sudo apt install -y curl jq
    
  • Fedora/RHEL/CentOS (dnf):

    sudo dnf install -y curl jq
    
  • openSUSE (zypper):

    sudo zypper refresh
    sudo zypper install -y curl jq
    

You’ll also need:

  • An API key from an AI provider (for example, OpenAI). Set it as an environment variable: export OPENAI_API_KEY="sk-...your-key..." Tip: Add this line to your shell profile (e.g., ~/.bashrc) so it’s always available.

Optional (local, no cloud): If you prefer local models, you can use Ollama and skip any cloud keys. Install it using their official instructions, then run:

ollama pull llama3.2

The Script: ai.sh

This script supports two providers:

  • openai (default, uses OPENAI_API_KEY)

  • ollama (local, set PROVIDER=ollama)

It provides helpful subcommands:

  • ask — freeform question

  • explain — explain a shell command safely

  • gen — generate a Bash snippet (aims to be safe and POSIX-friendly)

  • summarize — summarize a text file (limits size)

Create ai.sh:

#!/usr/bin/env bash
set -euo pipefail

# Dependencies: curl, jq
# Provider selection: export PROVIDER=openai (default) or PROVIDER=ollama
PROVIDER="${PROVIDER:-openai}"

# OpenAI config (used when PROVIDER=openai)
MODEL="${MODEL:-gpt-4o-mini}"
ROLE="${ROLE:-You are a helpful Linux and Bash assistant. Prefer concise answers and safe, POSIX-compliant examples. Explain trade-offs and add cautions where relevant.}"

# Ollama config (used when PROVIDER=ollama)
OLLAMA_MODEL="${OLLAMA_MODEL:-llama3.2}"

usage() {
  cat <<'USAGE'
Usage:
  ai.sh ask "your question"
  ai.sh explain "command to explain"
  ai.sh gen "describe the Bash you want"
  ai.sh summarize /path/to/file

Environment:
  PROVIDER=openai|ollama
  MODEL=gpt-4o-mini (for OpenAI; override if you wish)
  OLLAMA_MODEL=llama3.2 (for Ollama)
  OPENAI_API_KEY=... (required for PROVIDER=openai)

Examples:
  ai.sh explain "find . -type f -mtime -1 -print0 | xargs -0 tar -czf backup.tgz"
  ai.sh gen "rename files by replacing spaces with underscores"
  ai.sh ask "What's the safest way to parse CSV in Bash?"
  ai.sh summarize /var/log/nginx/access.log
USAGE
}

ensure_tools() {
  command -v curl >/dev/null 2>&1 || { echo "curl not found"; exit 1; }
  command -v jq >/dev/null 2>&1 || { echo "jq not found"; exit 1; }
}

ask_openai() {
  local prompt="$1"
  : "${OPENAI_API_KEY:?Set OPENAI_API_KEY for PROVIDER=openai}"

  # Build JSON with jq to avoid quoting issues
  local payload
  payload="$(jq -nc --arg model "$MODEL" --arg role "$ROLE" --arg prompt "$prompt" '{
    model: $model,
    messages: [
      {role: "system", content: $role},
      {role: "user", content: $prompt}
    ],
    temperature: 0.2
  }')"

  curl -fsS https://api.openai.com/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${OPENAI_API_KEY}" \
    -d "$payload" \
  | jq -r '.choices[0].message.content'
}

ask_ollama() {
  local prompt="$1"
  # We prepend ROLE to the prompt to provide instruction to the local model
  local combined_prompt
  combined_prompt="$ROLE

$prompt"

  local payload
  payload="$(jq -nc --arg model "$OLLAMA_MODEL" --arg prompt "$combined_prompt" '{
    model: $model,
    prompt: $prompt,
    stream: false
  }')"

  curl -fsS http://localhost:11434/api/generate \
    -H "Content-Type: application/json" \
    -d "$payload" \
  | jq -r '.response'
}

ask_ai() {
  local prompt="$1"
  if [[ "$PROVIDER" == "ollama" ]]; then
    ask_ollama "$prompt"
  else
    ask_openai "$prompt"
  fi
}

explain_command() {
  local cmd="$1"
  ask_ai "Explain the following shell command step by step, including what each flag does. Add safety notes and potential pitfalls. Command:
$cmd"
}

gen_bash() {
  local task="$1"
  ask_ai "Write a safe, POSIX-compliant Bash snippet to accomplish the following. Explain assumptions and include set -euo pipefail and comments. Task:
$task"
}

summarize_file() {
  local file="$1"
  [[ -r "$file" ]] || { echo "File not readable: $file" >&2; exit 1; }

  # Limit content to avoid sending large/secret data unintentionally
  # You can tune the limit; here we use 50KB.
  local limit=51200
  local content
  content="$(head -c "$limit" -- "$file")"

  ask_ai "Summarize the following file content in bullet points. If it looks like logs, extract key trends, errors, and counts. If it's code, summarize structure and responsibilities. Truncated to ${limit} bytes:
$content"
}

main() {
  ensure_tools
  local subcmd="${1:-}"
  shift || true

  case "$subcmd" in
    ask)
      [[ $# -gt 0 ]] || { usage; exit 1; }
      ask_ai "$*"
      ;;
    explain)
      [[ $# -gt 0 ]] || { usage; exit 1; }
      explain_command "$*"
      ;;
    gen)
      [[ $# -gt 0 ]] || { usage; exit 1; }
      gen_bash "$*"
      ;;
    summarize)
      [[ $# -eq 1 ]] || { usage; exit 1; }
      summarize_file "$1"
      ;;
    *)
      usage
      exit 1
      ;;
  esac
}

main "$@"

Make it executable:

chmod +x ai.sh

Provider selection:

  • Cloud (default): export OPENAI_API_KEY=... and run ./ai.sh ...

  • Local (Ollama): export PROVIDER=ollama and run ./ai.sh ... (make sure ollama serve is running and you’ve pulled a model)


4 Real-World Things You Can Do Immediately

1) Explain scary one-liners before you run them

./ai.sh explain "find . -type f -mtime -1 -print0 | xargs -0 tar -czf backup.tgz"
  • You’ll get a breakdown of each flag, what the pipeline does, and safety notes (e.g., -print0 and -0 to avoid issues with spaces/newlines).

2) Generate safe Bash for common tasks

./ai.sh gen "rename files by replacing spaces with underscores in the current directory"
  • Expect a snippet with set -euo pipefail, comments, and a careful loop using find -print0 and while IFS= read -r -d ''.

3) Summarize logs or configs quickly

./ai.sh summarize /var/log/nginx/access.log
  • Useful for spotting spikes, common status codes, or IPs. The script trims large files to 50KB by default; raise the limit if you need more context.

4) Ask for safer patterns or alternatives

./ai.sh ask "Is parsing JSON with grep safe? What's a safer alternative in Bash?"
  • This nudges you toward best practices (e.g., using jq instead of brittle text parsing).

Bonus: Pipe and redirect like any other tool

./ai.sh gen "one-liner to list largest 10 files under /var with sizes" | tee largest-files.sh
bash largest-files.sh

Tips, Safety, and Customization

  • Don’t paste secrets: Avoid sending credentials, tokens, private data, or sensitive logs. Consider redacting/sanitizing first.

  • Set usage limits: For large files, increase/decrease the limit in summarize_file.

  • Swap models: Try faster/cheaper or more capable models by changing MODEL (OpenAI) or OLLAMA_MODEL (local).

    MODEL=gpt-4o-mini ./ai.sh ask "How do I parse INI files in Bash?"
    OLLAMA_MODEL=llama3.2 ./ai.sh ask "Show a POSIX-safe way to create temp files"
    
  • Version control your prompts: Tune the ROLE text to define the assistant’s style and guardrails for your team.

  • Handle costs and quotas: Cloud APIs may be billable. Add caching or store results if you repeat queries.

  • CI/CD and servers: Works over SSH and in containers; just bring curl, jq, and the right environment variables.


Troubleshooting

  • 401/403 errors: Check OPENAI_API_KEY and your account permissions.

  • Connection refused (Ollama): Ensure the service is running (ollama serve) and that you’ve pulled a model.

  • Missing tools: Install with your package manager:

    • apt:
    sudo apt update && sudo apt install -y curl jq
    
    • dnf:
    sudo dnf install -y curl jq
    
    • zypper:
    sudo zypper refresh && sudo zypper install -y curl jq
    

Conclusion and Next Steps

You’ve just wired AI into your terminal with a single script. From here:

  • Extend ai.sh with project-aware context (e.g., include git diff or README.md automatically).

  • Add a lint subcommand that asks AI to review a script for portability and pitfalls.

  • Wrap frequent prompts in aliases or functions (e.g., alias aiex='ai.sh explain').

Call to Action:

  • Drop this script into your dotfiles repo and share it with your team.

  • Try it on your trickiest one-liner today—and never run a mystery command again.