Posted on
Artificial Intelligence

Artificial Intelligence Reporting Projects

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

AI-Powered Reporting Projects You Can Build in Bash (Today)

If your mornings start with grepping logs and scanning dashboards, you’re spending human attention on machine work. What if a tiny Bash script could pull your signals (health, security, code activity), ask an AI to summarize the noise, and hand you an executive-grade report every day?

This article shows you how to build practical “AI reporting” projects on Linux using Bash. You’ll get:

  • Why AI reporting is worth it

  • A drop-in Bash function to call either a local LLM (Ollama) or a cloud API

  • Three real-world reporting projects you can automate

  • Installation commands for apt, dnf, and zypper

  • Tips for scheduling, formatting, and safe operations

Why AI Reporting on Linux?

  • Time-to-signal: Logs, metrics, and commit histories are verbose. AI compresses them into high-signal summaries and action items.

  • Repeatable automation: A single script runs via cron/systemd, delivering a digest at the same time every day or week.

  • Flexible backends: Use local models for privacy (Ollama) or a cloud API for stronger reasoning (OpenAI) — switchable by an env var.

  • Native to your stack: Bash + standard CLI tools = zero vendor lock-in, easy review and diffing of generated reports.

Prerequisites and Installation

We’ll rely on a few standard tools. Install them with your package manager.

  • curl and jq (API calls + JSON processing)

  • pandoc (optional, to render HTML/PDF)

  • cron/cronie (scheduling)

  • git (for the Git report example)

Debian/Ubuntu (apt):

sudo apt update
sudo apt install -y curl jq pandoc git cron
sudo systemctl enable --now cron

Fedora/RHEL (dnf):

sudo dnf install -y curl jq pandoc git cronie
sudo systemctl enable --now crond

openSUSE (zypper):

sudo zypper refresh
sudo zypper install -y curl jq pandoc git cronie
sudo systemctl enable --now cron

Local LLM (Ollama) — optional but recommended for privacy:

curl -fsSL https://ollama.com/install.sh | sh
# Pull a model once:
ollama pull llama3

Cloud LLM (OpenAI) — optional:

  • Set your API key safely as an env var: export OPENAI_API_KEY="sk-..." (don’t hardcode in scripts)

  • Choose a model via OPENAI_MODEL (example: gpt-4o-mini)

A Drop-in Bash Function: ai_summarize

Create this helper in ~/bin/ai_summarize.sh to call either Ollama or OpenAI with the same interface.

#!/usr/bin/env bash
# ai_summarize.sh
# Usage: ai_summarize "PROMPT" "INPUT"
set -euo pipefail

ai_summarize() {
  local prompt="${1:-}"
  local input="${2:-}"
  local backend="${AI_BACKEND:-ollama}"

  case "$backend" in
    ollama)
      local model="${OLLAMA_MODEL:-llama3}"
      # Make sure model is available; non-fatal if already pulled
      ollama pull "$model" >/dev/null 2>&1 || true
      ollama run "$model" "$(printf '%s\n\nContext:\n%s\n' "$prompt" "$input")"
      ;;

    openai)
      : "${OPENAI_API_KEY:?Set OPENAI_API_KEY env var for openai backend}"
      local model="${OPENAI_MODEL:-gpt-4o-mini}"

      jq -n \
        --arg p "$prompt" \
        --arg i "$input" \
        --arg m "$model" \
        '{
          model: $m,
          messages: [
            {role:"system", content:"You are a concise Linux reporting assistant. Output Markdown."},
            {role:"user", content: ($p + "\n\nContext:\n" + $i)}
          ],
          temperature: 0.2
        }' \
      | curl -sS https://api.openai.com/v1/chat/completions \
          -H "Authorization: Bearer ${OPENAI_API_KEY}" \
          -H "Content-Type: application/json" \
          -d @- \
      | jq -r '.choices[0].message.content'
      ;;

    *)
      echo "Unknown AI_BACKEND: $backend" >&2
      return 1
      ;;
  esac
}

# If sourced, export function; if executed directly, run with args
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
  ai_summarize "$@"
else
  export -f ai_summarize
fi

Make it executable and ensure your PATH includes ~/bin:

mkdir -p ~/bin
chmod +x ~/bin/ai_summarize.sh

Optional: keep settings in ~/.ai-report.env:

AI_BACKEND=ollama
OLLAMA_MODEL=llama3
# For OpenAI backend:
# OPENAI_API_KEY=...
# OPENAI_MODEL=gpt-4o-mini

Project 1: Daily Server Health Report (Markdown + optional HTML/Slack)

This script aggregates health signals, asks the AI to summarize, and writes a Markdown report you can also convert to HTML.

Save as ~/bin/ai_health_report.sh:

#!/usr/bin/env bash
set -euo pipefail
[[ -f "$HOME/.ai-report.env" ]] && source "$HOME/.ai-report.env"
source "$HOME/bin/ai_summarize.sh"

REPORT_DIR="$HOME/ai-reports/health"
mkdir -p "$REPORT_DIR"

HOST="$(hostname -f 2>/dev/null || hostname)"
NOW="$(date -Is)"
PROMPT="Create a concise daily server health report in Markdown with sections: Overview, Disk, Memory, CPU/Load, Notable Logs, Action Items. Prioritize clarity and concrete next steps."

# Collect signals
DISK="$(df -hT --exclude-type=tmpfs --exclude-type=devtmpfs)"
MEM="$(free -m)"
LOAD="$(uptime && ps -eo pid,comm,pcpu,pmem --sort=-pcpu | head -n 10)"
LOGS="$(journalctl --since '24 hours ago' -p warning..alert --no-pager -n 2000 || true)"

INPUT="$(cat <<'EOF'
=== Host ===
__HOST__

=== Disk (df -hT) ===
__DISK__

=== Memory (free -m) ===
__MEM__

=== CPU & Top Procs ===
__LOAD__

=== Recent Warnings/Errors (journalctl) ===
__LOGS__
EOF
)"
INPUT="${INPUT/__HOST__/$HOST}"
INPUT="${INPUT/__DISK__/$DISK}"
INPUT="${INPUT/__MEM__/$MEM}"
INPUT="${INPUT/__LOAD__/$LOAD}"
INPUT="${INPUT/__LOGS__/$LOGS}"

SUMMARY="$(ai_summarize "$PROMPT" "$INPUT")"

OUT_MD="$REPORT_DIR/${HOST}-health-$(date +%F).md"
{
  echo "# ${HOST} — Daily Health Report"
  echo "_Generated: ${NOW}_"
  echo
  echo "$SUMMARY"
} > "$OUT_MD"

# Optional: Convert to HTML (requires pandoc)
if command -v pandoc >/dev/null 2>&1; then
  pandoc "$OUT_MD" -o "${OUT_MD%.md}.html" --metadata title="${HOST} Health Report"
fi

# Optional: Send to Slack (set SLACK_WEBHOOK_URL)
if [[ -n "${SLACK_WEBHOOK_URL:-}" ]]; then
  # Escape Markdown as plain text; Slack supports simple Markdown-like formatting
  payload="$(jq -n --arg text "$(cat "$OUT_MD")" '{text:$text}')"
  curl -sS -X POST -H 'Content-type: application/json' --data "$payload" "$SLACK_WEBHOOK_URL" >/dev/null || true
fi

echo "Wrote: $OUT_MD"

Make it executable:

chmod +x ~/bin/ai_health_report.sh

Schedule it with cron:

  • Debian/Ubuntu (apt):

    • Cron is already enabled above. Edit your crontab:
    crontab -e
    

    Add (runs at 06:15 daily):

    15 6 * * * . $HOME/.ai-report.env; $HOME/bin/ai_health_report.sh >> $HOME/ai-reports/health/cron.log 2>&1
    
  • Fedora/RHEL (dnf) and openSUSE (zypper):

    • With cronie enabled above:
    crontab -e
    

    Add the same line:

    15 6 * * * . $HOME/.ai-report.env; $HOME/bin/ai_health_report.sh >> $HOME/ai-reports/health/cron.log 2>&1
    

Tip: Keep sensitive info out of LOGS or redact before sending to a cloud API.

Project 2: SSH Security Anomaly Digest

Summarize failed logins, top source IPs, and suspicious patterns from the last 24 hours.

Save as ~/bin/ai_security_digest.sh:

#!/usr/bin/env bash
set -euo pipefail
[[ -f "$HOME/.ai-report.env" ]] && source "$HOME/.ai-report.env"
source "$HOME/bin/ai_summarize.sh"

REPORT_DIR="$HOME/ai-reports/security"
mkdir -p "$REPORT_DIR"

HOST="$(hostname -f 2>/dev/null || hostname)"
NOW="$(date -Is)"
PROMPT="Summarize SSH authentication anomalies from the last 24 hours. Include Top IPs, Attack Patterns, Impact/Risk, and Recommended Actions (commands in code blocks). Keep it concise and actionable."

# Collect logs (cover common unit names)
LOG="$(journalctl --since '24 hours ago' -u ssh -u sshd --no-pager -o short-iso || true)"

TOP_IPS="$(echo "$LOG" \
  | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' \
  | sort | uniq -c | sort -nr | head -n 20 || true)"

FAIL_LINES="$(echo "$LOG" | grep -E 'Failed password|Connection closed|Invalid user' | tail -n 200 || true)"

INPUT="$(cat <<'EOF'
=== Host ===
__HOST__

=== Top Source IPs (counts) ===
__TOP_IPS__

=== Sample Failure Lines ===
__FAIL_LINES__
EOF
)"
INPUT="${INPUT/__HOST__/$HOST}"
INPUT="${INPUT/__TOP_IPS__/$TOP_IPS}"
INPUT="${INPUT/__FAIL_LINES__/$FAIL_LINES}"

SUMMARY="$(ai_summarize "$PROMPT" "$INPUT")"

OUT_MD="$REPORT_DIR/${HOST}-ssh-digest-$(date +%F).md"
{
  echo "# ${HOST} — SSH Security Digest"
  echo "_Generated: ${NOW}_"
  echo
  echo "$SUMMARY"
} > "$OUT_MD"

echo "Wrote: $OUT_MD"

Run it ad-hoc or schedule weekly:

crontab -e
# Fridays at 08:00
0 8 * * 5 . $HOME/.ai-report.env; $HOME/bin/ai_security_digest.sh >> $HOME/ai-reports/security/cron.log 2>&1

Note: For cloud AI, consider redacting internal usernames/IP ranges before sending.

Project 3: Weekly Git Repository Summary

Turn a week of commits into a manager-ready summary of what changed and where risk might be.

Save as ~/bin/ai_git_weekly.sh:

#!/usr/bin/env bash
set -euo pipefail
[[ -f "$HOME/.ai-report.env" ]] && source "$HOME/.ai-report.env"
source "$HOME/bin/ai_summarize.sh"

REPO="${1:?Usage: ai_git_weekly.sh /path/to/repo}"
cd "$REPO"

REPORT_DIR="$HOME/ai-reports/git"
mkdir -p "$REPORT_DIR"

NAME="$(basename "$REPO")"
NOW="$(date -Is)"
SINCE="${SINCE:-7 days ago}"

PROMPT="Produce a weekly engineering summary in Markdown: Highlights, Areas of Risk, Testing/Docs, Notable Files, and Next Steps. Be specific and concise."

COMMITS="$(git log --since="$SINCE" --pretty=format:'%h %an %ad %s' --date=short || true)"
AUTHORS="$(git shortlog -sne --since="$SINCE" || true)"
FILES="$(git log --since="$SINCE" --name-only --pretty=format: | sort | uniq -c | sort -nr | head -n 30 || true)"

INPUT="$(cat <<'EOF'
=== Repo ===
__NAME__

=== Commits (since __SINCE__) ===
__COMMITS__

=== Top Contributors ===
__AUTHORS__

=== Most-Touched Files ===
__FILES__
EOF
)"
INPUT="${INPUT/__NAME__/$NAME}"
INPUT="${INPUT/__SINCE__/$SINCE}"
INPUT="${INPUT/__COMMITS__/$COMMITS}"
INPUT="${INPUT/__AUTHORS__/$AUTHORS}"
INPUT="${INPUT/__FILES__/$FILES}"

SUMMARY="$(ai_summarize "$PROMPT" "$INPUT")"

OUT_MD="$REPORT_DIR/${NAME}-weekly-$(date +%F).md"
{
  echo "# ${NAME} — Weekly Summary"
  echo "_Generated: ${NOW}_"
  echo
  echo "$SUMMARY"
} > "$OUT_MD"

echo "Wrote: $OUT_MD"

Usage:

chmod +x ~/bin/ai_git_weekly.sh
~/bin/ai_git_weekly.sh ~/code/your-repo

Schedule it (Sundays at 17:30):

crontab -e
30 17 * * 0 . $HOME/.ai-report.env; $HOME/bin/ai_git_weekly.sh $HOME/code/your-repo >> $HOME/ai-reports/git/cron.log 2>&1

Formatting and Delivery Options

  • Convert Markdown to HTML (already in Project 1):

    pandoc report.md -o report.html
    
  • Slack webhooks:

    • Set SLACK_WEBHOOK_URL, then post JSON with curl as shown in the health report script.
  • Static site:

    • Serve ~/ai-reports from Nginx or push to a Git repo/GitHub Pages.

Practical Tips

  • Privacy first:

    • Prefer Ollama (local) for sensitive logs; for cloud, redact obvious secrets and internal IP ranges.
  • Keep inputs bounded:

    • Limit log lines (e.g., -n 2000), or summarize sections separately and stitch results.
  • Reproducibility:

    • Save raw inputs next to the AI output for auditing: tee "$OUT_MD.input.txt".
  • Fail safe:

    • If AI call fails, still write a minimal report with raw metrics and a note.
  • Version prompts:

    • Track prompt changes in Git so you can see when summaries improved or regressed.

Your Next Step (CTA)

Pick one project above and wire it into your environment today: 1) Install prerequisites via your package manager. 2) Drop in ai_summarize.sh and set AI_BACKEND to ollama or openai. 3) Run ai_health_report.sh once, inspect the output, then schedule it.

From there, customize prompts, add more signals, and make the AI do the boring reporting — so you can do the interesting engineering.