Posted on
Artificial Intelligence

Learning Artificial Intelligence Bash

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

Learning Artificial Intelligence with Bash: Automate AI from the Terminal

If you love living in the terminal, you don’t need notebooks or heavy GUI tools to get real work done with AI. Bash can be your AI command center: reproducible, scriptable, and perfect for automating everyday tasks like summarizing logs, classifying tickets, batch-rewriting documentation, and more.

This post shows why “AI from Bash” is a powerful pattern, then gives you practical, copy‑pasteable snippets to start shipping value today.

Why Bash + AI is a great fit

  • Glue for everything: Bash orchestrates curl, jq, python, git, and system tools you already use.

  • Reproducible and auditable: Shell scripts make prompts, parameters, and outputs easy to track in version control.

  • Fast to automate: Turn one-off commands into cron jobs and CI steps without changing tools.

  • Portable: Works across servers, containers, and your laptop with minimal dependencies.

Prerequisites: Set up your AI-friendly shell

We’ll use standard CLI tools:

  • curl (HTTP), jq (JSON), git (versioning), Python 3 (for local servers and helpers), sqlite3 (optional storage), wget (optional downloads).

Install them with your package manager.

Debian/Ubuntu (apt):

sudo apt update
sudo apt install -y curl jq git python3 python3-venv python3-pip sqlite3 wget

Fedora/RHEL/CentOS (dnf):

sudo dnf install -y curl jq git python3 python3-virtualenv python3-pip sqlite sqlite-devel wget

openSUSE (zypper):

sudo zypper refresh
sudo zypper install -y curl jq git python3 python3-venv python3-pip sqlite3 wget

Tip: Store your API keys securely and load them in your shell session.

mkdir -p ~/.config
cat > ~/.config/ai.env <<'EOF'
# Example: OpenAI-compatible API
export OPENAI_API_KEY="put-your-key-here"
# Optional: Use a custom endpoint that is OpenAI-compatible
# export OPENAI_BASE_URL="https://api.example.com/v1"
EOF

# Load in current shell
source ~/.config/ai.env

# Load automatically in new terminals
grep -q 'source ~/.config/ai.env' ~/.bashrc || echo 'source ~/.config/ai.env' >> ~/.bashrc

Security note: Never commit keys to git. Consider a secrets manager for production.

1) Call an LLM API with curl (no SDK required)

You can talk to any OpenAI-compatible API from pure Bash. That includes many popular providers and local servers that expose the same schema.

Single prompt:

MODEL="gpt-4o-mini"   # change to your provider’s model name
BASE="${OPENAI_BASE_URL:-https://api.openai.com/v1}"

curl -sS "$BASE/chat/completions" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "'"$MODEL"'",
        "messages": [{"role":"user","content":"In one sentence, explain Bash arrays."}],
        "temperature": 0.3
      }' | jq -r '.choices[0].message.content'

Reusable Bash function:

llm() {
  local prompt="$1"
  local model="${2:-gpt-4o-mini}"
  local base="${OPENAI_BASE_URL:-https://api.openai.com/v1}"

  curl -sS "$base/chat/completions" \
    -H "Authorization: Bearer $OPENAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
          "model": "'"$model"'",
          "messages": [{"role":"user","content":'"$(jq -Rn --arg p "$prompt" '$p')"' }],
          "temperature": 0.2
        }' | jq -r '.choices[0].message.content'
}

Use it:

llm "Summarize last week's on-call postmortem in 5 bullet points."

Batch over files:

for f in docs/*.md; do
  echo "Processing $f"
  llm "Rewrite this more concisely while preserving meaning:\n\n$(cat "$f")" > "out/$(basename "$f")"
done

2) Stream outputs for better UX

Streaming gives you tokens as they arrive (great for long answers). Most OpenAI-compatible APIs support SSE.

MODEL="gpt-4o-mini"
BASE="${OPENAI_BASE_URL:-https://api.openai.com/v1}"

curl -N -sS "$BASE/chat/completions" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "'"$MODEL"'",
        "stream": true,
        "messages": [{"role":"user","content":"List 5 Linux backup strategies with pros/cons."}],
        "temperature": 0.2
      }' \
| sed -u 's/^data: //; /"delta":{}/d' \
| jq -r '.choices[0].delta.content // empty'

3) Run a local model server (no Internet, no data leaves your box)

Prefer local inference? The llama.cpp Python server runs entirely on your machine.

Create a venv and install:

python3 -m venv ~/.venvs/llm
~/.venvs/llm/bin/pip install --upgrade pip
~/.venvs/llm/bin/pip install "llama-cpp-python[server]"

Download a GGUF model (example: a small instruct model). Verify license and pick a size your CPU/RAM can handle:

mkdir -p ~/models
cd ~/models
wget https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/TinyLlama-1.1B-Chat-v1.0.Q4_K_M.gguf -O tinyllama.gguf

Start the server:

~/.venvs/llm/bin/python -m llama_cpp.server --model ~/models/tinyllama.gguf --host 0.0.0.0 --port 8000

Call it with the same curl shape (OpenAI-compatible):

export OPENAI_BASE_URL="http://127.0.0.1:8000/v1"
unset OPENAI_API_KEY   # local server typically doesn’t need a key

curl -sS "$OPENAI_BASE_URL/chat/completions" \
  -H "Content-Type: application/json" \
  -d '{
        "model": "local-llama",
        "messages": [{"role":"user","content":"Explain what a Bash here-doc is, with an example."}]
      }' | jq -r '.choices[0].message.content'

Tip: For better performance, use models that fit in RAM and support your CPU features. GPU acceleration is possible but outside this short guide.

4) Real-world examples you can run today

A) Summarize yesterday’s logs into a Slack-ready report

YDAY=$(date -d "yesterday" +%F)  # or: date -v-1d +%F on BSD/mac
LOG=/var/log/syslog

grep "$YDAY" "$LOG" | tail -n 2000 > /tmp/yesterday.log

SUMMARY=$(llm "Summarize key incidents and recurring warnings in this log. Output bullet points:\n\n$(cat /tmp/yesterday.log)")

printf "*Ops Daily Summary (%s)*\n%s\n" "$YDAY" "$SUMMARY"

B) Classify support tickets (CSV) into categories

input="tickets.csv"   # columns: id,subject,body
mkdir -p classified

tail -n +2 "$input" | while IFS=, read -r id subject body; do
  prompt="Subject: $subject

Body:
$body

Classify into one of: [Billing, Bug, Feature, How-To]. Respond with only the label."
  label=$(llm "$prompt")
  echo "$id,$label" >> classified/labels.csv
done

C) Batch-translate Markdown to English, preserve code blocks

mkdir -p translated

for f in content/*.md; do
  text=$(cat "$f")
  prompt="Translate the following Markdown to English. Preserve code fences and formatting. Do not translate code:\n\n$text"
  llm "$prompt" > "translated/$(basename "$f")"
done

D) Programmatic prompt templates with variables

prompt_render() {
  local tpl="$1"; shift
  # usage: prompt_render template.txt VAR1="value" VAR2="value"
  local envs=()
  for kv in "$@"; do envs+=(-v "${kv%%=*}=${kv#*=}"); done
  awk "${envs[@]}" '{ while (match($0, /\{\{[A-Z0-9_]+\}\}/)) {
      key=substr($0, RSTART+2, RLENGTH-4);
      gsub("{{"key"}}", ENVIRON[key]);
    } print }' "$tpl"
}

export PRODUCT="Backup CLI"
export TONE="friendly and concise"

prompt_render prompt.txt PRODUCT="$PRODUCT" TONE="$TONE" | while read -r chunk; do
  : # build prompt if template is multiline; for simplicity, cat the template:
done

llm "$(prompt_render prompt.txt PRODUCT="$PRODUCT" TONE="$TONE")"

Example prompt.txt:

Write a {{TONE}} README introduction for {{PRODUCT}}. Mention Linux support and a one-line install command.

5) Make it reliable: retries, rate limits, and logs

Turn your one-off commands into robust jobs.

request_llm() {
  local prompt="$1"
  local out="$2"
  local tries=0
  local max=5
  local backoff=2

  while (( tries < max )); do
    if resp=$(llm "$prompt"); then
      printf "%s\n" "$resp" | tee "$out"
      return 0
    fi
    tries=$((tries+1))
    sleep $((backoff**tries))
  done
  echo "ERROR: Failed after $max attempts" >&2
  return 1
}

# Example usage
request_llm "Summarize: $(head -c 5000 /var/log/syslog)" out/summary.txt

Schedule with cron:

crontab -e
# Every day at 07:00
0 7 * * * source ~/.config/ai.env && /home/user/bin/daily-log-summary.sh >> /home/user/logs/ai-jobs.log 2>&1

Optional: a tiny local knowledge assistant

Keep notes in Markdown and ask an LLM to answer with citations.

Index file names and top headings:

find notes -name '*.md' -maxdepth 1 -type f -print0 \
| xargs -0 -I{} sh -c 'echo "## {}"; sed -n "1,100p" "{}"' \
> /tmp/notes-heads.txt

Ask a question with open-book context:

QUESTION="How do we deploy our staging environment?"
CONTEXT=$(cat /tmp/notes-heads.txt | head -c 12000)

llm "Using only this context, answer and cite files in parentheses:

Context:
$CONTEXT

Question: $QUESTION

Answer with bullet points and file names in parentheses." 

It’s not full RAG, but it’s quick, local, and often good enough.

Troubleshooting tips

  • JSON errors: Pipe responses to jq to see exact errors.

  • Long prompts: Many APIs cap tokens. Trim inputs or work in chunks.

  • Cost control: Log token usage if your provider supports it; sample fewer files.

  • Speed: Lower temperature, pick smaller models, stream results, or run locally.

Conclusion and next steps

You don’t need to leave the terminal to leverage AI. With curl, jq, and a few small scripts, you can:

  • Call cloud or local LLMs

  • Automate summarization, classification, translation

  • Schedule reliable jobs with retries and logs

Next steps:

  • Wrap your favorite snippets into a ~/bin toolkit.

  • Add a Makefile target (e.g., make summarize-logs) for your team.

  • Experiment with a local model server for private data.

  • Keep prompts and scripts in git for reproducibility.

If this helped, turn one repetitive task you do weekly into a Bash+AI job today—and enjoy the time you get back.