New AI projects on Hugging Face or GitHub, May 29 2026. One repo taught its agent to fail over from Claude to Gemini mid-conversation.
The shipment worth reading on May 29 was not a new model on a leaderboard. It was a cross-vendor failover, built over one evening inside the open-source macOS agent Fazm. When the built-in Claude key dies or hits a rate limit, the agent now quietly continues the same chat on Gemini instead of showing an error. This is that day, read in the commits: the failure it solves, the decision tree it follows, and the line that makes the switch invisible.
Direct answer, verified 2026-05-30
No platform publishes an official "May 29, 2026" list of new AI projects. Both Hugging Face and GitHub order discovery by a rolling trending score, not by calendar date. New work surfaces continuously across three live feeds:
- huggingface.co/models sorted by trending, for weights and quantized variants.
- huggingface.co/papers, for research with implementations linked.
- github.com/trending, for the agent code, harnesses, and applications.
The records that genuinely carry that exact date are tagged releases and commit logs. The notable one for 2026-05-29: the open-source macOS agent Fazm pushed 74 commits and cut three patch releases (v2.9.53 through v2.9.55), recorded in CHANGELOG.json. Most of the day built one feature: a transparent Claude-to-Gemini failover that keeps a chat alive when the built-in Claude key cannot serve a turn. It shipped to users the next morning as v2.9.56. The rest of this page opens that feature.
Why a Claude Code wrapper would ever route to Gemini
Fazm wraps Claude Code over the Agent Client Protocol, and most of the time it serves chat with a bundled, shared Claude key so a new user can talk to the agent without bringing their own account. That shared key has two failure modes the user did not cause and cannot fix: the backend can rotate or revoke it, and it can hit a rate limit because it is shared. Before May 29, both ended the same way: an error bubble, and a retry that reproduced the same failure on the next turn.
Gemini queries in Fazm do not bill the Anthropic key. They run on a separate bundled Gemini path. That is the whole reason Gemini is the escape hatch: it is a backend that is still available precisely when the Claude path is not. The work on May 29 was wiring that escape hatch so it triggers automatically, and so the user never has to know it happened.
The decision tree, in order
The failover is not a single catch block. It is a sequence that tries the cheapest recovery first and only reaches Gemini when Claude is genuinely unusable. Each step is a real branch in the sendMessage error handler in ChatProvider.swift.
What happens when a built-in Claude turn fails
Built-in Claude turn fails
rate limit or invalid key, builtin mode only
Refetch /v1/keys once
30s cooldown; restart bridge if the key rotated
Still bad?
same or empty key returned means the key is dead
Pick a Gemini id
geminiFallbackModelId: prefer gemini-pro-latest, then flash
Replay the same prompt
retryAfterBuiltinKeyRefetch = true, errorMessage = nil
Conversation continues
no error bubble; the switch is silent
The key refetch is the careful part. A shared key that just rotated on the backend looks identical to a dead key from inside the app, so the handler refetches once from /v1/keys, and if the key actually changed it restarts the bridge so the new ANTHROPIC_API_KEY lands in the subprocess, then replays on Claude. Only a same-or-empty key sends the turn to Gemini. A 30-second cooldown (builtinKeyRefetchCooldown) stops a backend that keeps returning a bad key from spinning in an infinite refetch loop.
The two code paths, before and after
The difference between the old behavior and the new one is small in line count and large in what the user experiences. The left is the dead-end; the right is the May 29 reroute.
// Before May 29: built-in Claude key dead or rate-limited.
// Only path out was to surface the failure to the user.
errorMessage = bridgeError.errorDescription
showCreditExhaustedAlert = true
// The conversation dead-ends on a retry-only error.
// Retrying just reproduces the same failure next turn.// May 29: builtinKeyInvalid -> refetch /v1/keys once per 30s.
// Same or empty key back means the key is genuinely dead.
let geminiId = geminiFallbackModelId // prefer gemini-pro-latest
builtinClaudeKeyDead = true // session-long redirect
ShortcutSettings.shared.selectedModel = geminiId
retryAfterBuiltinKeyRefetch = true // replay the same prompt
errorMessage = nil // nothing shown to the userTwo lines carry the new behavior. Setting builtinClaudeKeyDead to true turns this into a session-long redirect: later turns route even hard-coded Claude sends (like the onboarding model) to Gemini, so the app stops wasting a doomed Claude attempt every turn. Setting errorMessage to nil is what makes it silent: with the pending message re-armed, the same prompt replays on Gemini and the answer simply appears.
Dead key versus rate limit: one reroute, two policies
The handler treats the two failures differently on purpose, even though both end up on Gemini.
- Refetch /v1/keys once; restart bridge if rotated.
- Same or empty key back means the key is genuinely dead.
- Sets builtinClaudeKeyDead = true.
- Later turns also redirect to Gemini for the session.
- Re-tries Claude on the next app launch.
- The key works; the shared cap is temporarily full.
- Does NOT set builtinClaudeKeyDead.
- Switches to Gemini for the current turn only.
- Claude auto-recovers on a later turn once the cap resets.
- Only a message if no Gemini model is available.
Both branches clear errorMessage and replay through the same retry tail, and both guard on whether a Gemini model is actually advertised before rerouting. The rate-limit version started as inline code and was refactored the same evening (commit 9ed461f6) to go through a retry queue, which is the kind of cleanup that only shows up in the commit log, never on a trending page.
The day, by the numbers
The failover was the headline, but it was one thread of a busy day. The counts below come from the public commit log between 2026-05-29 00:00 and 2026-05-30 00:00.
The net-line figure is the combined diff of the failover commits in ChatProvider.swift; the other three are direct counts from git log --since=2026-05-29 --until=2026-05-30 --no-merges.
What else landed the same day
Three other changes are worth noting because they show where an open-source desktop agent spends its time when it is not chasing a single headline bug.
- Custom API endpoint mode (commits around 16:40). The ACP bridge can now route a turn through a corporate proxy, GitHub Copilot, or any Anthropic-compatible gateway. When a custom endpoint is set, the bundled key and built-in credits are explicitly disabled so a user routing through their own gateway is never silently billed against Fazm.
- In-app RoutineScheduler (commit 887dbcbb, a 175-line new file plus AppDelegate start/stop wiring). Recurring routines now fire on time while the app is open, fixing scheduled routines that previously never ran.
- Founder-chat attachments (commits d463f5ee through 63bd6a3e). Paste, drag-and-drop, or attach a file in the in-app support chat, backed by signed GCS upload URLs.
Why this beats a trending list for May 29
A trending feed tells you which models and repositories existed at the end of the day. It cannot tell you that an agent decided to keep a conversation alive across a vendor boundary, or why the cheap recovery (refetch the key, restart the bridge) has to run before the expensive one (switch vendors). The commit log can. On May 29 it showed a maintainer adding a session flag, wiring two distinct failure policies onto one reroute, refactoring the rate-limit path into a retry queue, and shipping it as three small releases inside one day.
The lesson generalizes past Fazm. Any agent that serves a shared, bundled model key inherits two failures the user cannot fix: rotation and rate limits. The portable shape of the answer is the order: try the free recovery first, declare the key dead only when a refetch confirms it, fall back to a backend that bills differently, and make the switch silent by re-arming the pending prompt instead of surfacing an error. The fallback is a few dozen lines. The order is the part worth copying.
Serving a shared model key in your own agent?
In twenty-five minutes we open the failover commit, your retry path, and your billing boundary together, and decide whether your stack needs the same cross-vendor escape hatch.
Frequently asked questions
What new AI projects appeared on Hugging Face or GitHub on May 29, 2026?
Neither platform publishes a dated release list. Models, datasets, papers, and repositories surface continuously, ordered by a rolling trending score rather than by calendar date. The closest thing to a true daily record is a tagged release or a commit log, where each change carries an author, a message, and a timestamp. The record that genuinely carries 2026-05-29 and is worth reading: the open-source macOS agent Fazm pushed 74 commits across 30 files and cut three patch releases (v2.9.53 at 10:41, v2.9.54 at 14:30, v2.9.55 at 18:08 Pacific). Most of the evening went into one feature that is unusual for a Claude Code wrapper: a transparent failover from Claude to Gemini. When the bundled Claude key dies or hits a rate limit, the agent quietly continues the same conversation on Gemini instead of showing an error.
What exactly is the Claude-to-Gemini failover Fazm built that day?
It is a cross-vendor fallback that keeps a chat alive when the built-in (shared) Claude key cannot serve a turn. The logic lives in ChatProvider.swift behind a session flag named builtinClaudeKeyDead and a computed property geminiFallbackModelId. When a turn throws because the built-in key authentication failed, the app refetches the key from the backend /v1/keys endpoint once, restarts the bridge if the key actually rotated, and replays the message silently. If the refetch returns the same or an empty key, the key is treated as genuinely dead: the app sets builtinClaudeKeyDead, switches the selected model to a Gemini id, re-arms the pending message, and clears errorMessage so nothing surfaces to the user. The combined change is roughly +154 / -17 lines in ChatProvider.swift across commits 947a5eb3, f336947c, ecfdbd1b, 9ed461f6, and 647ee8bf. It shipped to users the next morning as v2.9.56.
Why fall back to Gemini instead of just retrying Claude?
Because retrying Claude with a dead or throttled built-in key reproduces the same failure every turn. The app already does the cheap recovery first: it refetches the key once per 30 seconds (a cooldown named builtinKeyRefetchCooldown) in case the backend rotated it, and restarts the bridge so the new ANTHROPIC_API_KEY lands in the subprocess. Gemini is the path taken only after that recovery fails, or while the rate limit is still in effect. Gemini queries do not bill the Anthropic key (they run on Fazm's bundled Gemini access), so the user is not blocked behind a cap that has not reset. The design goal stated in the source comments is to avoid dead-ending on a retry-only error.
Does the failover tell the user it switched models?
It is deliberately silent. The branches that route to Gemini all set errorMessage = nil and re-arm the pending message through a flag named retryAfterBuiltinKeyRefetch, so the same prompt replays on Gemini and the assistant answer just appears. There is no modal, no error bubble, and no manual model switch required. The model picker reflects the new selection, but the conversation continues from the next message as if nothing happened. The trade-off the author accepts is that the user is now talking to a different model family; the alternative was a hard stop.
Why does the fallback prefer gemini-pro-latest?
The geminiFallbackModelId property picks, in order: gemini-pro-latest if the picker probe has advertised it, then gemini-flash-latest, then any advertised Gemini id, then the canonical gemini-pro-latest alias the bridge accepts even before the probe populates. The comment in the source says it prefers Pro because it is the smartest available, so a silent downgrade in vendor is not also a silent downgrade in capability when it can be avoided. Routing in the bridge is model-id-based, so the alias resolves even if the probe has not finished listing the user's available Gemini variants yet.
Is the dead-key fallback the same as the rate-limit fallback?
They share the Gemini reroute but differ in whether Claude is allowed to recover. The dead-key path (builtinKeyInvalid) sets builtinClaudeKeyDead = true, which makes later turns route hard-coded Claude sends to Gemini too, so the app does not waste a doomed Claude attempt per turn for the rest of the session. The rate-limit path (credit/rate limit exhausted, isRateLimitExhaustion true) deliberately does NOT set builtinClaudeKeyDead, because the limit resets: it switches to Gemini for the current turn and lets Claude auto-recover on a later turn. One is a session-long redirect; the other is a per-turn rescue. Both clear errorMessage and replay silently, and both only fire if a Gemini model is actually available to fall back to.
What else shipped on May 29 besides the failover?
Three things stand out in the same log. First, a custom API endpoint mode for the ACP bridge (commits around 16:40), so a turn can route through a corporate proxy, GitHub Copilot, or any Anthropic-compatible gateway, with the bundled key and built-in credits explicitly disabled when a custom endpoint is set. Second, an in-app RoutineScheduler (commit 887dbcbb, a 175-line new file plus AppDelegate wiring) that fires recurring routines on time while the app is open, fixing scheduled routines that never ran. Third, founder-chat attachments: paste, drag-and-drop, or attach a file, backed by GCS signed URLs (commits d463f5ee through 63bd6a3e). v2.9.55 also fixed Gemini occasionally returning an empty reply by rescuing text the engine streamed under a mismatched session id, the routing decision tested in decideGeminiRoute.
How do I read any project's real May 29 myself?
Three artifacts, in order. Open the project's CHANGELOG.json or CHANGELOG.md at the root and read the entries dated 2026-05-29. Open the commit log with `git log --since=2026-05-29 --until=2026-05-30 --no-merges` and read the messages, ignoring the release-changelog commits. Then pick one commit whose subject sounds load-bearing (here, 'Add Gemini fallback when built-in Claude key is dead') and run `git show <hash>` to read the diff and the comment the author left for future readers. The trending page tells you what existed at the end of the day; the diff tells you what someone decided, and why.
Where do I find the actual files this page cites?
github.com/mediar-ai/fazm is the public repo. The failover lives in Desktop/Sources/Providers/ChatProvider.swift: the builtinClaudeKeyDead flag and geminiFallbackModelId property near the top of the class, the dead-key and rate-limit branches in the sendMessage error handler, and the send-time redirect that rewrites a hard-coded Claude model id to Gemini while the key is dead. The empty-reply routing logic is in acp-bridge/src/gemini-provider.ts (decideGeminiRoute) with tests in acp-bridge/test/gemini-route.test.mjs. Release notes are in CHANGELOG.json at the repo root.
Related guides
New AI projects, Hugging Face or GitHub, May 28 2026
The day before: a one-line model bump from claude-opus-4-7 to claude-opus-4-8 broke every long chat, and the 55-line poisoned-thinking-block fix that saved them.
New AI projects, Hugging Face or GitHub, May 27 2026
Two days back: a 15-second per-tool stall detector and a SIGKILL escape hatch that walks the process tree for wedged Playwright subprocesses.
New AI projects on Hugging Face or GitHub, May 2026
The monthly companion. Why the two platforms are complements, what each is good for, and how to triage a daily feed without drowning in roundups.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.