DEV Community

Cover image for A 24-Line Script That Tells You When a Model Shutdown Date Moves
Nabil A
Nabil A

Posted on AI-assisted

A 24-Line Script That Tells You When a Model Shutdown Date Moves

Between Friday and Saturday morning, Microsoft moved claude-haiku-4-5 on Foundry from November 15, 2026 to February 22, 2027, and Google moved five Gemini API previews off November 17. I found out by reading the pages again.

So here is a script that reads them for you. It fetches four provider pages, keeps only the rows that mention the model IDs you use, and prints a diff when one of those rows changes. Bash, curl, sed, awk and grep. No API keys.

The script

Save it as watch-retirements.sh:

#!/usr/bin/env bash
# Prints a diff when a retirement row changes for a model you use.
# Usage: ./watch-retirements.sh models.txt   (one model ID per line)
set -uo pipefail
models="$1"; state=".retirement-watch"; mkdir -p "$state"; changed=0
pages=(
  https://platform.claude.com/docs/en/about-claude/model-deprecations
  https://developers.openai.com/api/docs/deprecations
  https://aistudio.google.com/docs/deprecations
  https://learn.microsoft.com/en-us/azure/foundry/openai/concepts/model-retirement-schedule
)
for url in "${pages[@]}"; do
  f="$state/$(echo "$url" | cut -d/ -f3)"
  curl -sfL "$url" | tr -d '\n' \
    | sed -e 's#</tr>#\n#g' -e 's# --- #\n#g' -e 's/<[^>]*>/ /g' \
    | tr -s ' \t' ' ' | awk 'length < 300' \
    | grep -F -f "$models" | sort -u > "$f.new"
  [ -s "$f.new" ] || { echo "could not read $url"; rm -f "$f.new"; continue; }
  if [ -f "$f.txt" ] && ! diff -u "$f.txt" "$f.new"; then
    echo "^ changed: $url"; changed=1
  fi
  mv "$f.new" "$f.txt"
done
exit $changed
Enter fullscreen mode Exit fullscreen mode

And list the model IDs your code calls in models.txt, one per line:

claude-haiku-4-5
claude-sonnet-4-5-20250929
o3-2025-04-16
gemini-2.5-flash-preview-tts
Enter fullscreen mode Exit fullscreen mode

How it works

  • tr -d '\n' flattens each page to one line, then sed puts every table row on its own line. HTML tables end rows with </tr>. Google's page comes back as Markdoc, where rows are separated by ---, so the script splits on that too.
  • sed 's/<[^>]*>/ /g' strips the tags, and awk 'length < 300' drops the long lines that are left, such as inline scripts. Table rows are short.
  • grep -F -f models.txt keeps the rows that mention one of your IDs. sort -u makes the output stable, so a diff only shows real changes.
  • The first run saves a snapshot per site in .retirement-watch/. Each later run compares against it and exits 1 if anything changed, which is what a scheduled CI job needs to fail loudly.

What it printed

I ran it on November 14, 2026 in an empty folder, on macOS with bash 3.2 and curl 8.7.

The first run saves the snapshots and prints nothing. The Microsoft one looked like this:

 claude-haiku-4-5 1 GA 2027-02-22 claude-haiku-5-5
 claude-haiku-4-5 2 GA 2027-02-22 claude-haiku-5-5
Enter fullscreen mode Exit fullscreen mode

The second run, right after, printed nothing and exited 0.

Then I put back Friday's date in the snapshot, to see what Saturday morning would have looked like:

sed -i '' 's/claude-haiku-4-5 1 GA 2027-02-22/claude-haiku-4-5 1 GA 2026-11-15/' \
  .retirement-watch/learn.microsoft.com.txt
./watch-retirements.sh models.txt; echo "exit $?"
Enter fullscreen mode Exit fullscreen mode

That printed:

@@ -1,2 +1,2 @@
- claude-haiku-4-5 1 GA 2026-11-15 claude-haiku-5-5
+ claude-haiku-4-5 1 GA 2027-02-22 claude-haiku-5-5
  claude-haiku-4-5 2 GA 2027-02-22 claude-haiku-5-5
^ changed: https://learn.microsoft.com/en-us/azure/foundry/openai/concepts/model-retirement-schedule
exit 1
Enter fullscreen mode Exit fullscreen mode

(The diff -u header lines with file names and times come first; I left them out here.) On Linux, use sed -i without the ''.

Running it every day

Run it once a morning from cron, or from a scheduled CI job that keeps .retirement-watch/ between runs (commit it, or cache it). Exit code 1 means a row for one of your models changed. Read the diff, then read the page.

What it does not do

  • It matches substrings. o3 would also match o3-mini and o3-pro. Use full IDs, like o3-2025-04-16.
  • It is not a parser. If a provider redesigns its page, you get one noisy diff, then quiet again. That is the right failure: you get told, and you look.
  • I tested these four pages only. For another page, such as the Amazon Bedrock model lifecycle, run the pipeline once by hand and check that each row comes out on one line.
  • Anthropic's page lists replacements in its history tables, so claude-haiku-4-5 also matches old rows that name it as the replacement for Claude 1, Claude 3 Haiku and Claude 3.5 Haiku. That is noise, but stable noise: it never shows up in a diff.
  • It does not know which of your files call the model. For that, git grep -n -F -f models.txt is a good start.

Which page would you add to the list, and does it come out one row per line?

I'm Nabil. I build Since, which tracks what your code depends on and tells you before it breaks.

Top comments (0)