feat(provider): re-authenticate Claude from within T3 Code#4151
feat(provider): re-authenticate Claude from within T3 Code#4151sideeffffect wants to merge 3 commits into
Conversation
When Claude Code's OAuth token expires mid-turn ("Failed to authenticate.
API Error: 401 OAuth access token has expired. Re-authenticate to
continue.") the only way to recover was to leave T3 Code and run the login
command in an external shell. This adds an in-app re-authentication path.
- contracts: add an optional ServerProviderReauthentication descriptor on
ServerProvider (command / executable / args / label). Additive and
back-compat: legacy producers omit it and consumers hide the action.
- server: the Claude provider advertises "claude setup-token", resolved to
the instance's configured binary, on its installed snapshots so custom
binaries re-authenticate the same executable they run.
- web: the thread error banner (on auth-looking turn failures) and the
provider status banner (when a provider reports "unauthenticated") offer a
"Re-authenticate" action that runs the login command in the thread's
integrated terminal, reusing the proven project-script launcher. The user
completes the interactive OAuth prompt (open URL, paste code) in-app.
Docs (docs/providers/claude.md) and tests (contracts + provider snapshot)
included.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a new user-facing feature (in-app re-authentication for Claude) with new UI elements, terminal integration, and error detection heuristics. New features introducing user-facing behavior warrant human review. You can customize Macroscope's approvability policy. Learn more. |
Resolves the Cursor Bugbot / Macroscope review findings on pingdotgg#4151: - Propagate CLAUDE_CONFIG_DIR (High): the re-authentication descriptor now carries an optional `env` map, and the Claude provider fills it with the instance's resolved home (via resolveClaudeHomePath) when a custom home is configured. The web launcher layers it onto the terminal env, so `setup-token` refreshes the correct instance's credentials instead of the default config dir. Adds contract + provider tests. - Pending snapshot exposes re-auth (Medium): makePendingClaudeProvider now attaches the descriptor, so a turn failing before the first status check still offers the recovery action. - Target the failing instance (Medium): the thread error banner resolves the re-auth provider from the thread session's providerInstanceId (the one that produced lastError), not the composer's currently-selected provider. - Tighten auth-error heuristic (Medium): isProviderAuthError now matches credential-specific phrasing instead of bare 401/403/oauth/api-key substrings that also appear in generic tool/HTTP failures. - Shell-quote the command (Low): the login command line is POSIX-quoted so a configured binary path with spaces is not word-split when pasted.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c5276be. Configure here.
…s the POSIX single-quoting added in the previous commit: it broke && other shells the integrated terminal may use — cmd.exe treats single quotes && as literal (word-splitting a spaced path), and single quotes suppress ~ && expansion in bash/zsh. No single pre-joined string is correct across all of && them, so `command` is now a plain space-join optimized for the common && `claude`/PATH (and unquoted-path) case, with `executable`/`args` exposed && separately for callers needing exact argv.

Problem
When Claude Code's OAuth token expires, a turn fails with:
Today the only way to recover is to leave T3 Code, open a shell, and run the
Claude login command by hand. There is no way to trigger and finish the
authentication flow from within the app.
What this does
Adds an in-app Re-authenticate action for Claude:
Re-authenticate button.
unauthenticated, the provider status bannershows the same button (previously it only said "Sign in via the CLI to
authenticate again." — a dead end). This generalizes to any provider that
advertises a re-auth command.
Clicking it opens the thread's integrated terminal and runs
claude setup-tokenfor that provider — using the instance's configuredbinary and Claude HOME — so the interactive OAuth prompt (open URL, paste the
authorization code) is completed entirely inside T3 Code. No external shell.
How it works
packages/contracts/src/server.ts): new optionalServerProviderReauthenticationdescriptor (command/executable/args/label) onServerProvider. Additive and back-compat — legacyproducers omit it and consumers simply hide the action.
ClaudeProvider.ts,providerSnapshot.ts): the Claude provideradvertises
claude setup-token(resolved to the configuredbinaryPath) onits installed snapshots, threaded through
buildServerProvider.ProviderStatusBanner,ThreadErrorBanner,ChatView): render theaction and run the command by reusing the existing project-script terminal
launcher (open/reuse a terminal, focus it, write the command). A fresh
terminal is preferred so the OAuth prompt does not collide with an in-flight
shell.
claude setup-tokenwas chosen because it is the supported interactive loginfor the CLI/SDK model T3 Code already uses and produces a fresh long-lived
token.
Tests / checks
pnpm typecheck— clean.pnpm lint— 0 errors, no new warnings.pnpm fmt:check— clean.(
server.test.ts) and the Claude snapshot exposing it(
ProviderRegistry.test.ts). Touched suites pass (contracts 5/5, serverprovider registry 36/36, web ChatView logic 22/22).
Notes / scope
the web UI; mobile is unaffected (it only reads
auth.status).attempted here: Claude Code's local init still succeeds with cached
credentials, so the reliable signal is the runtime 401, which is exactly
where the thread-error-banner button appears. The status-banner button covers
providers that do report
unauthenticated.this environment; the launch reuses the already-shipping project-script path.
Docs:
docs/providers/claude.mdgains a short "My Claude Login Expired"section.
Note
Low Risk
Additive contract field and UI recovery path; no changes to turn execution or credential storage beyond launching the existing CLI login command with correct env.
Overview
Adds an optional
ServerProviderReauthenticationdescriptor on provider snapshots so the client can run an interactive CLI login without leaving the app.Claude advertises
claude setup-token(respecting configured binary andCLAUDE_CONFIG_DIRfor custom homes) on checked and pending snapshots;Pathis wired through pending snapshot creation in the driver.Web:
ProviderStatusBannerandThreadErrorBannershow a Re-authenticate button when the provider is unauthenticated or the thread error matches a narrow auth-expiry heuristic;ChatViewlaunches the command via the existing project-script terminal path (new terminal, optional env), targeting the thread session’s provider instance rather than the composer selection.Contract tests, registry tests, and
docs/providers/claude.mddocument the recovery flow.Reviewed by Cursor Bugbot for commit b11de81. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add in-app Claude re-authentication from the thread error and provider status banners
ServerProviderReauthenticationschema to provider snapshots carrying the command, executable, args, label, and optional env needed to launch a login flow.claude setup-token) includingCLAUDE_CONFIG_DIRwhen a custom home path is configured.ChatViewContentdetects auth-related thread errors and surfaces a "Re-authenticate" button that runs the login command in a new integrated terminal.ProviderStatusBannerandThreadErrorBannereach gain an optionalonReauthenticatecallback that renders a "Re-authenticate" button with a Key icon.Macroscope summarized b11de81.