Skip to content

Instantly share code, notes, and snippets.

@jotafeldmann
Last active September 3, 2026 15:26
Show Gist options
  • Select an option

  • Save jotafeldmann/be24e4f66ceedd7f534757e358624e25 to your computer and use it in GitHub Desktop.

Select an option

Save jotafeldmann/be24e4f66ceedd7f534757e358624e25 to your computer and use it in GitHub Desktop.
ai-status.sh: Quick diagnostic for the four major AI providers plus the shared layers underneath. Generated by Qwen3.8-27B Locally on an NVIDIA RTX 5090
#!/usr/bin/env bash
# ai-status.sh
# Quick diagnostic for the four major AI providers plus the shared layers underneath.
# Separates an edge failure (CDN/DNS) from an inference failure (provider status page).
#
# Usage:
# ./ai-status.sh # run once, everything
# ./ai-status.sh edge # run once, edge only
# ./ai-status.sh --watch # loop every 300s (default)
# ./ai-status.sh --watch 60 # loop every 60s
# ./ai-status.sh --watch 60 edge # loop every 60s, edge section only
# ./ai-status.sh 60 # shorthand: bare number implies --watch
# ./ai-status.sh --watch --clear # loop and redraw in place
#
# Sections: all (default) | edge | status | infra
# Requires: curl. Optional: dig (dnsutils), jq (clean status page output).
set -uo pipefail
RED=$'\033[31m'; GRN=$'\033[32m'; YEL=$'\033[33m'; DIM=$'\033[2m'; BLD=$'\033[1m'; RST=$'\033[0m'
TIMEOUT=8
MODE="all"
WATCH=0
INTERVAL="${AI_STATUS_INTERVAL:-300}"
CLEAR=0
have() { command -v "$1" >/dev/null 2>&1; }
is_num() { [[ "${1:-}" =~ ^[0-9]+$ ]]; }
hr() { printf '%s\n' "${DIM}$(printf '=%.0s' {1..64})${RST}"; }
head2() { printf '\n%s%s%s\n' "$BLD" "$1" "$RST"; }
usage() {
awk 'NR==1 { next } /^#/ { sub(/^# ?/, ""); print; next } { exit }' "$0"
exit 0
}
# ---------- argument parsing ----------
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
-w|--watch)
WATCH=1
# optional interval right after the flag
if is_num "${2:-}"; then INTERVAL="$2"; shift; fi
;;
-n|--interval)
if is_num "${2:-}"; then INTERVAL="$2"; WATCH=1; shift
else printf '%serror: --interval needs a number of seconds%s\n' "$RED" "$RST" >&2; exit 2; fi
;;
-c|--clear) CLEAR=1 ;;
-1|--once) WATCH=0 ;;
-h|--help) usage ;;
all|edge|status|infra) MODE="$1" ;;
*)
if is_num "$1"; then WATCH=1; INTERVAL="$1"
else printf '%serror: unknown argument %s (try --help)%s\n' "$RED" "$1" "$RST" >&2; exit 2; fi
;;
esac
shift
done
if [[ "$INTERVAL" -lt 10 ]]; then
printf '%swarning: interval below 10s risks rate limiting, raising to 10s%s\n' "$YEL" "$RST" >&2
INTERVAL=10
fi
}
# ---------- layer 1: DNS + edge ----------
edge_check() {
local label="$1" host="$2"
printf ' %-22s' "$label"
# name resolution
local ips=""
if have dig; then
ips=$(dig +short +time=3 +tries=1 A "$host" 2>/dev/null | grep -E '^[0-9]+\.' | head -3 | paste -sd, -)
else
ips=$(getent ahostsv4 "$host" 2>/dev/null | awk '{print $1}' | sort -u | head -3 | paste -sd, -)
[[ -z "$ips" ]] && ips=$(getent hosts "$host" 2>/dev/null | awk '{print $1}' | head -3 | paste -sd, -)
fi
if [[ -z "$ips" ]]; then
printf '%sDNS FAILED%s (name does not resolve)\n' "$RED" "$RST"
return
fi
# HTTP headers
local hdrs code server edge
hdrs=$(curl -sS -m "$TIMEOUT" -o /dev/null -D - "https://$host" 2>/dev/null)
code=$(printf '%s' "$hdrs" | awk 'toupper($1) ~ /^HTTP/ {c=$2} END{print c}')
server=$(printf '%s' "$hdrs" | grep -i '^server:' | head -1 | cut -d' ' -f2- | tr -d '\r')
# who sits in front
if printf '%s' "$hdrs" | grep -qi '^cf-ray:'; then edge="Cloudflare"
elif printf '%s' "$hdrs" | grep -qi 'x-amz-cf-id\|^x-amz-cf-pop:'; then edge="AWS CloudFront"
elif printf '%s' "$hdrs" | grep -qi '^x-served-by:.*fastly\|^fastly-'; then edge="Fastly"
elif printf '%s' "$hdrs" | grep -qi '^x-azure-ref:'; then edge="Azure Front Door"
elif printf '%s' "$hdrs" | grep -qi '^via:.*google'; then edge="Google"
else edge="${server:-?}"
fi
local color="$GRN"
[[ -z "$code" ]] && { code="no response"; color="$RED"; }
[[ "$code" =~ ^5 ]] && color="$RED"
[[ "$code" =~ ^4 ]] && color="$YEL"
printf '%s%-12s%s edge:%-17s ip:%s\n' "$color" "$code" "$RST" "$edge" "${ips%%,*}"
}
run_edge() {
head2 "EDGE (DNS + CDN + HTTP)"
printf ' %sHTTP 401/403 on an API endpoint is expected, it means the edge is alive.%s\n' "$DIM" "$RST"
edge_check "Claude web" "claude.ai"
edge_check "Claude API" "api.anthropic.com"
edge_check "ChatGPT web" "chatgpt.com"
edge_check "OpenAI API" "api.openai.com"
edge_check "Grok web" "grok.com"
edge_check "xAI API" "api.x.ai"
edge_check "Gemini web" "gemini.google.com"
edge_check "Google AI API" "generativelanguage.googleapis.com"
}
# ---------- layer 2: provider status pages ----------
# Atlassian Statuspage convention: /api/v2/summary.json
statuspage() {
local label="$1" url="$2"
printf ' %-22s' "$label"
local json
json=$(curl -sS -m "$TIMEOUT" "$url" 2>/dev/null)
if [[ -z "$json" ]]; then
printf '%s? no response%s\n' "$YEL" "$RST"
return
fi
local desc unresolved
if have jq; then
desc=$(printf '%s' "$json" | jq -r '.status.description // "?"' 2>/dev/null)
unresolved=$(printf '%s' "$json" \
| jq -r '[.incidents[]? | select(.status!="resolved") | .name] | join(" | ")' 2>/dev/null)
else
desc=$(printf '%s' "$json" | grep -o '"description":"[^"]*"' | head -1 | cut -d'"' -f4)
unresolved=$(printf '%s' "$json" | grep -o '"name":"[^"]*"' | head -3 | cut -d'"' -f4 | paste -sd' | ' -)
fi
local color="$GRN"
[[ "$desc" != "All Systems Operational" ]] && color="$YEL"
[[ "$desc" == *"Major"* ]] && color="$RED"
printf '%s%s%s\n' "$color" "${desc:-?}" "$RST"
[[ -n "${unresolved:-}" && "$unresolved" != "null" ]] && printf ' %s-> %s%s\n' "$DIM" "$unresolved" "$RST"
}
run_status() {
head2 "PROVIDER STATUS PAGES"
statuspage "Anthropic / Claude" "https://status.claude.com/api/v2/summary.json"
statuspage "OpenAI" "https://status.openai.com/api/v2/summary.json"
statuspage "xAI / Grok" "https://status.x.ai/api/v2/summary.json"
# Google does not use Statuspage
printf ' %-22s' "Google Cloud / AI"
local g
g=$(curl -sS -m "$TIMEOUT" "https://status.cloud.google.com/incidents.json" 2>/dev/null)
if [[ -z "$g" ]]; then
printf '%s? no response%s\n' "$YEL" "$RST"
elif have jq; then
local open
open=$(printf '%s' "$g" | jq -r '[.[] | select(.end==null) | .external_desc] | join(" | ")' 2>/dev/null)
if [[ -z "$open" || "$open" == "null" ]]; then
printf '%sNo open incidents%s\n' "$GRN" "$RST"
else
printf '%s%s%s\n' "$YEL" "${open:0:80}" "$RST"
fi
else
printf '%sfetched, install jq to parse%s\n' "$DIM" "$RST"
fi
}
# ---------- layer 3: shared infrastructure ----------
run_infra() {
head2 "SHARED INFRASTRUCTURE (root cause usually lives here)"
statuspage "Cloudflare" "https://www.cloudflarestatus.com/api/v2/summary.json"
statuspage "AWS" "https://health.aws.amazon.com/api/v2/summary.json"
statuspage "Azure" "https://azure.status.microsoft/api/v2/summary.json"
statuspage "Fastly" "https://status.fastly.com/api/v2/summary.json"
# local resolver sanity check
printf '\n %-22s' "Local DNS resolver"
if have dig; then
local t
t=$(dig +short +time=3 +tries=1 cloudflare.com 2>/dev/null | head -1)
[[ -n "$t" ]] && printf '%sok%s\n' "$GRN" "$RST" || printf '%sfailing, retry against 1.1.1.1%s\n' "$RED" "$RST"
else
printf '%sdig not installed%s\n' "$DIM" "$RST"
fi
}
# ---------- how to read it ----------
verdict() {
head2 "HOW TO READ THIS"
cat <<'EOF'
Edge 5xx across all four at once -> shared CDN or DNS, check Cloudflare first.
Edge fine but status page degraded -> provider-internal inference failure.
One provider only, edge and status clean -> your network, VPN, proxy or account.
Login failing while API works -> identity plane, switching models will not help.
EOF
}
# ---------- run one full pass ----------
run_once() {
local iter="${1:-1}"
[[ "$CLEAR" -eq 1 ]] && printf '\033[2J\033[H'
hr
if [[ "$WATCH" -eq 1 ]]; then
printf '%sAI STATUS%s %s %s(pass %s, every %ss, ctrl-c to stop)%s\n' \
"$BLD" "$RST" "$(date '+%Y-%m-%d %H:%M:%S %Z')" "$DIM" "$iter" "$INTERVAL" "$RST"
else
printf '%sAI STATUS%s %s\n' "$BLD" "$RST" "$(date '+%Y-%m-%d %H:%M:%S %Z')"
fi
if [[ "$iter" -eq 1 ]]; then
have dig || printf '%s warning: dig missing (apt install dnsutils), falling back to getent%s\n' "$YEL" "$RST"
have jq || printf '%s warning: jq missing (apt install jq / brew install jq), degraded output%s\n' "$YEL" "$RST"
fi
hr
case "$MODE" in
edge) run_edge ;;
status) run_status ;;
infra) run_infra ;;
*)
run_edge; run_status; run_infra
# the reading guide is static, show it on the first pass only
[[ "$iter" -eq 1 ]] && verdict
;;
esac
printf '\n'
}
main() {
parse_args "$@"
if [[ "$WATCH" -eq 0 ]]; then
run_once 1
return
fi
trap 'printf "\n%sstopped after %s passes%s\n" "$DIM" "$i" "$RST"; exit 0' INT TERM
local i=1
while :; do
run_once "$i"
[[ "$CLEAR" -eq 0 ]] && printf '%s next pass in %ss%s\n' "$DIM" "$INTERVAL" "$RST"
sleep "$INTERVAL"
i=$((i + 1))
done
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment