Posted on
Artificial Intelligence

The Complete Guide to Artificial Intelligence Bash Automation

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

The Complete Guide to Artificial Intelligence Bash Automation

Ever stared at a wall of logs at 3 AM wishing something could just “tell you what matters”? Good news: with a few lines of Bash, you can pipe real-world context into an AI model and get back summaries, classifications, suggested commands—and even safe, automated actions. This guide shows you how to connect AI to your shell, responsibly and reproducibly.

Why AI + Bash is a powerful combo

  • Bash is the glue of Linux: it’s great for piping, filtering, and scheduling (cron/systemd).

  • Modern AI models are HTTP-first: you can talk to them with curl + jq and a small wrapper.

  • Automation pays off fast: summarize huge logs, extract structured data, propose fixes, or batch-process content with a few reusable shell functions.

  • Local or cloud: choose local models (e.g., Ollama) for privacy, or cloud APIs for capability—same Bash patterns work for both.


Prerequisites and installation

We’ll use:

  • curl for HTTP

  • jq to parse JSON

  • parallel for batch jobs

  • git for the commit-message example

  • Optionally: ollama for local models

Install system tools:

  • Debian/Ubuntu (apt):

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

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

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

Optional: install Ollama (local models):

curl -fsSL https://ollama.com/install.sh | sh
# then pull a model, e.g.:
ollama pull llama3.1:8b

Environment setup (choose a backend and model):

# Pick one backend: openai | openrouter | ollama
export AI_BACKEND=openai
export AI_MODEL=gpt-4o-mini

# Set your API key if using a cloud provider:
export OPENAI_API_KEY="sk-..."
# or
export OPENROUTER_API_KEY="or-..."

# Ollama runs locally; no key needed. Example:
# export AI_BACKEND=ollama
# export AI_MODEL=llama3.1:8b

Security tip: store API keys in your shell keychain or an .env file with restricted permissions:

install -m 600 /dev/null ~/.ai-secrets
echo 'export OPENAI_API_KEY="sk-..."' >> ~/.ai-secrets
echo 'export AI_BACKEND=openai' >> ~/.ai-secrets
echo 'export AI_MODEL=gpt-4o-mini' >> ~/.ai-secrets
echo 'source ~/.ai-secrets' >> ~/.bashrc

Core pattern: a universal ai() function

Create a provider-agnostic function that reads a prompt from stdin and prints the model’s reply to stdout. Save this as ~/.bash_ai.sh and source it from your ~/.bashrc.

# ~/.bash_ai.sh
set -o pipefail

_ai_openai() {
  local prompt
  prompt=$(cat)
  curl -sS https://api.openai.com/v1/chat/completions \
    -H "Authorization: Bearer ${OPENAI_API_KEY}" \
    -H "Content-Type: application/json" \
    -d "$(jq -n --arg m "${AI_MODEL:-gpt-4o-mini}" --arg p "$prompt" \
          '{model:$m, temperature:0.2, messages:[{role:"user", content:$p}]}')" \
  | jq -r '.choices[0].message.content'
}

_ai_openrouter() {
  local prompt
  prompt=$(cat)
  curl -sS https://openrouter.ai/api/v1/chat/completions \
    -H "Authorization: Bearer ${OPENROUTER_API_KEY}" \
    -H "Content-Type: application/json" \
    -d "$(jq -n --arg m "${AI_MODEL:-openrouter/auto}" --arg p "$prompt" \
          '{model:$m, temperature:0.2, messages:[{role:"user", content:$p}]}')" \
  | jq -r '.choices[0].message.content'
}

_ai_ollama() {
  local prompt
  prompt=$(cat)
  curl -sS http://localhost:11434/api/chat \
    -H "Content-Type: application/json" \
    -d "$(jq -n --arg m "${AI_MODEL:-llama3.1:8b}" --arg p "$prompt" \
          '{model:$m, stream:false, messages:[{role:"user", content:$p}]}')" \
  | jq -r '.message.content'
}

ai() {
  case "${AI_BACKEND}" in
    openai) _ai_openai ;;
    openrouter) _ai_openrouter ;;
    ollama) _ai_ollama ;;
    *) echo "Set AI_BACKEND to openai|openrouter|ollama" >&2; return 2 ;;
  esac
}

Activate it:

echo 'source ~/.bash_ai.sh' >> ~/.bashrc
source ~/.bashrc

Usage:

echo "Explain what this script does: $(sed -n '1,80p' myscript.sh)" | ai

1) Summarize and triage logs

Tackle noisy logs quickly by piping a slice of context to the model. This example pulls the last 2,000 lines of an app log and asks for a prioritized incident summary.

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

LOGFILE="${1:-/var/log/syslog}"
SNIPPET=$(tail -n 2000 "$LOGFILE")

PROMPT=$(cat <<'EOF'
You are an SRE assistant. Summarize the following logs in bullet points:

- Identify top 3 issues with evidence (timestamps, error codes)

- Suggest likely root causes

- Propose next diagnostic steps (CLI commands)
Keep it under 200 words. Logs:
EOF
)

printf "%s\n%s\n" "$PROMPT" "$SNIPPET" | ai

Tip:

  • Rotate context: sometimes head + tail provides broader coverage than a single tail.

  • Never paste secrets; scrub with sed before sending to cloud APIs, or use a local model (Ollama) for sensitive data.


2) Extract structured data with validation

Ask the model for strict JSON, then validate with jq. If invalid, retry with a stronger instruction.

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

INPUT="${1:-errors.txt}"
TEXT=$(cat "$INPUT")

attempts=0
max_attempts=3
while (( attempts < max_attempts )); do
  ((attempts++))
  OUT=$(printf "%s\n\nTEXT:\n%s\n" \
"Extract a JSON list of objects from TEXT with keys:

- timestamp (RFC3339 if missing, set to null)

- service (string)

- severity (one of: INFO, WARN, ERROR)

- message (string)
Output ONLY compact JSON. No commentary." \
"$TEXT" | ai)

  if echo "$OUT" | jq -e . >/dev/null 2>&1; then
    echo "$OUT" | jq .
    exit 0
  else
    echo "Attempt $attempts: invalid JSON, retrying..." >&2
    TEXT="IMPORTANT: Output strictly valid JSON. Do not add extra text. Original content follows.\n$TEXT"
  fi
done

echo "Failed to get valid JSON after $max_attempts attempts." >&2
exit 1

Use cases:

  • Normalize error lines into a structured feed for dashboards.

  • Extract table-like info from CLI output (e.g., kubectl, aws, ps).


3) Suggest commands—then confirm before running

LLMs can propose shell commands, but you should always confirm and constrain. This pattern asks for a single safe command, shows it, and executes only if you agree and it matches an allowlist.

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

TOPIC="${1:-"Find large directories under /var"}"

CMD=$(printf "%s\n" \
"Propose ONE safe Linux command to accomplish the task:
$TOPIC
Constraints:

- Use read-only commands when possible.

- Avoid destructive operations (rm, dd, mkfs, sudo).

- No shell explanations; output JUST the command." | ai)

# Trim and sanitize
CMD=$(printf "%s" "$CMD" | tr -d '\r' | sed -e 's/^```.*//' -e 's/```$//' -e 's/^$//')

echo "Proposed command:"
echo "  $CMD"

# Allowlist for a demo; adapt to your needs
ALLOW='^(ls|du|df|grep|find|awk|sed|head|tail|cut|sort|uniq|wc|cat|less|tree)\b'

if [[ ! "$CMD" =~ $ALLOW ]]; then
  echo "Rejected: command not in allowlist." >&2
  exit 2
fi

read -r -p "Run this command? [y/N] " ans
if [[ "$ans" =~ ^[Yy]$ ]]; then
  bash -c "$CMD"
else
  echo "Aborted."
fi

Ideas:

  • “Show top 10 disk hogs under /home”

  • “Grep nginx errors with 5xx in the last hour”

  • “List pods using >500Mi memory in kube-system”


4) Batch jobs with GNU parallel

Process many files by fanning out AI calls (mind your rate limits). This example generates concise, conventional commit messages from staged changes.

Install tools if you haven’t:

  • apt:

    sudo apt update && sudo apt install -y git parallel curl jq
    
  • dnf:

    sudo dnf install -y git parallel curl jq
    
  • zypper:

    sudo zypper refresh && sudo zypper install -y git parallel curl jq
    

Prepare a commit-message helper:

#!/usr/bin/env bash
set -euo pipefail
DIFF=$(git diff --staged)

printf "%s\n\n%s\n" \
"Generate a concise Conventional Commit message (type(scope): summary) for these staged changes. 70 chars max for summary. Include a brief body if needed." \
"$DIFF" | ai

Or wire it as a Git hook (.git/hooks/prepare-commit-msg):

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

# Only fill in if empty
[[ -s "$1" ]] && exit 0

DIFF=$(git diff --staged)
MSG=$(printf "%s\n\n%s\n" \
"Generate a concise Conventional Commit message (type(scope): summary) for these staged changes. 70 chars max for summary. If no changes, output 'chore: update'." \
"$DIFF" | ai)

printf "%s\n" "$MSG" > "$1"

Make it executable:

chmod +x .git/hooks/prepare-commit-msg

For true batching (e.g., caption images with a local model), you could:

find images/ -type f -name "*.jpg" \
| parallel -j4 --bar '
  f={};
  CAP=$(printf "Write a short alt-text for this file name: %s" "$f" | ai);
  printf "%s\t%s\n" "$f" "$CAP" >> captions.tsv
'

Note: add sleep/backoff if your provider rate-limits.


5) Caching, cost, and privacy controls

Avoid re-paying for the same prompt. Cache by hashing input.

ai_cached() {
  local key dir file prompt
  prompt=$(cat)
  dir="${XDG_CACHE_HOME:-$HOME/.cache}/bash-ai"
  mkdir -p "$dir"
  key=$(printf "%s" "$AI_BACKEND|$AI_MODEL|$prompt" | sha256sum | awk '{print $1}')
  file="$dir/$key.txt"
  if [[ -s "$file" ]]; then
    cat "$file"
    return 0
  fi
  # shellcheck disable=SC2005
  echo "$prompt" | ai | tee "$file"
}

Usage:

echo "Summarize this README briefly:"; cat README.md | ai_cached

Additional tips:

  • Redact tokens and PII before sending to cloud.

  • For large inputs, pre-summarize chunks with head, tail, sed -n '1,200p', etc.

  • Keep temperature low (0–0.3) for reproducibility.

  • Consider local models (Ollama) for confidential data.


Real-world example: incident triage script

Pulling multiple sources, snipping context, and producing an action plan:

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

journal=$(journalctl -p err -n 500 --no-pager 2>/dev/null || true)
nginx=$(tail -n 1000 /var/log/nginx/error.log 2>/dev/null || true)
dmesg=$(dmesg --ctime | tail -n 400 2>/dev/null || true)

PROMPT=$(cat <<'EOF'
You are an on-call SRE assistant. From the provided snippets:

- Summarize symptoms

- Hypothesize root causes (ranked)

- Provide immediate next steps with concrete Linux commands

- Estimate blast radius and customer impact
Keep under 220 words. Use bullet points. If info is insufficient, say what else is needed.
EOF
)

printf "%s\n\n[JOURNAL]\n%s\n\n[NGINX]\n%s\n\n[DMESG]\n%s\n" \
  "$PROMPT" "$journal" "$nginx" "$dmesg" | ai

Safety and reliability checklist

  • Always review AI-suggested commands; use allowlists and confirmations.

  • Validate structured outputs with jq; retry if invalid.

  • Log inputs/outputs for audit (redact secrets).

  • Rate-limit and cache to control cost.

  • Prefer local models for sensitive data.


Your next step (CTA)

  • Install the tooling:

    • apt:
    sudo apt update && sudo apt install -y curl jq parallel git
    
    • dnf:
    sudo dnf install -y curl jq parallel git
    
    • zypper:
    sudo zypper refresh && sudo zypper install -y curl jq parallel git
    
  • Choose a backend:

    • Cloud: set OPENAI_API_KEY or OPENROUTER_API_KEY
    • Local: curl -fsSL https://ollama.com/install.sh | sh && ollama pull llama3.1:8b
  • Save the ai() function to ~/.bash_ai.sh and source it.

  • Automate one pain point today: summarize logs, extract JSON from CLI output, or generate commit messages.

Bash is still the automation backbone. With a few careful patterns, AI becomes just another tool in your toolbox—fast, scriptable, and surprisingly capable.