feat: Claude CLI OAuth token expiry warning

New GET /auth/status endpoint reads ~/.claude/.credentials.json and
returns hours remaining + warning flag. UI shows a dismissible amber
banner when < 24h remain, turning red if expired. Checked on page load
and every 30 minutes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-17 23:06:28 -04:00
parent 7b51e7cc44
commit 48a6734ec3
6 changed files with 108 additions and 2 deletions

View File

@@ -905,3 +905,30 @@
helpModal.addEventListener('click', (e) => {
if (e.target === helpModal) helpModal.classList.remove('open');
});
// ── Auth token warning banner ─────────────────────────────
const authBanner = document.getElementById('auth-banner');
const authBannerMsg = document.getElementById('auth-banner-msg');
const authBannerClose = document.getElementById('auth-banner-close');
async function checkAuthStatus() {
try {
const res = await fetch('/auth/status');
if (!res.ok) return;
const d = await res.json();
if (!d.warning) return;
const msg = d.expired
? '✕ Claude CLI token has expired — run `claude` in a terminal to re-authenticate'
: `⚠ Claude CLI token expires in ${d.hours_remaining}h — run \`claude\` in a terminal to re-authenticate`;
authBannerMsg.textContent = msg;
authBanner.classList.toggle('expired', !!d.expired);
authBanner.classList.add('show');
} catch { /* silently ignore — don't break the UI */ }
}
authBannerClose.addEventListener('click', () => authBanner.classList.remove('show'));
checkAuthStatus();
// Re-check every 30 minutes
setInterval(checkAuthStatus, 30 * 60 * 1000);