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
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
How it works
-
tr -d '\n'flattens each page to one line, thensedputs 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, andawk 'length < 300'drops the long lines that are left, such as inline scripts. Table rows are short. -
grep -F -f models.txtkeeps the rows that mention one of your IDs.sort -umakes 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 exits1if 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
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 $?"
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
(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.
o3would also matcho3-miniando3-pro. Use full IDs, likeo3-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-5also 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.txtis 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)