Claude Code keeps asking you to log in? Fixes

Why Claude Code keeps asking you to log in: expired logins, two programs sharing one login, a stray API key. How to find the cause and fix it for good.

Contents

Usually one of three things: your saved login expired and Claude Code couldn't refresh it, two programs are refreshing the same login and knocking each other out, or another credential (an ANTHROPIC_API_KEY, a long-lived token) is taking over. Run /status first. It shows which credential and account are active, and that tells you which fix you need.

We spent a lot of time in this exact loop while building Shuriken, which juggles several Claude accounts at once. The causes below are in the order we'd check them.

How Claude Code stores your login#

A few facts from Anthropic's authentication docs explain almost every repeated login prompt:

  • Where it lives. On macOS, in the Keychain. On Linux, in ~/.claude/.credentials.json. On Windows, in %USERPROFILE%\.claude\.credentials.json.
  • One login per configuration directory. If you set CLAUDE_CONFIG_DIR, Claude Code keeps the credentials file under that directory and keys the Keychain entry to it. A different directory means a different login.
  • Logins expire and refresh. Three days before a login expires, Claude Code warns you at startup: Your login expires in 3 days · run /login to renew. The warning never blocks a request; the login works until it actually expires. Once it has expired and can't be refreshed, every model request fails with Login expired · Please run /login until you sign in again.
  • There's an order of precedence. Cloud provider settings, then ANTHROPIC_AUTH_TOKEN, then ANTHROPIC_API_KEY, then an apiKeyHelper script, then CLAUDE_CODE_OAUTH_TOKEN, then an Anthropic profile named in ANTHROPIC_PROFILE, and only then the login you made with /login. Anything higher on that list wins.

Keep those four in mind and the causes below stop looking random.

The common causes#

1. The login expired and couldn't refresh#

The plain case. Anthropic lists it first: "your earlier sign-in expired and Claude Code can't refresh it." Their troubleshooting page adds one thing worth checking if it happens often: token validation depends on correct timestamps, so a machine with a wrong clock can look logged out all the time.

The docs single out sessions nobody is watching: a background session in agent view or a Remote Control session that outlives the login stops making progress once it expires, and can't recover until you sign in again. If you see the three-day warning before leaving something running, run /login first.

People do report the loop beyond that. Issue #1757, "Claude code requires users to constantly login", was still open on 24 October 2026. #89490, about a session that expires mid-session and doesn't refresh on its own, was closed as not planned on 23 October 2026.

2. Two programs refreshing the same login#

This is the sneaky one, and the one we hit most. When a login refreshes, the old refresh token stops being valid. If two programs hold copies of the same login and both try to refresh, one of them presents a token that's already been used, and the whole login can get revoked. Then everything that used it asks you to log in again, at the same moment.

Anthropic describes a version of this in its own troubleshooting notes: before Claude Code v2.1.211, waking a machine from sleep could make two sessions renew with the same token, "which revoked the saved login and prompted every open session to log in again at once." Parallel sessions on one machine now coordinate their renewal. But the race still shows up in reports: see #80085 (concurrent instances sharing one Keychain login on macOS) and #91708 (concurrent sessions on Windows racing on the credentials file), both open on 24 October 2026.

It gets worse when programs outside Claude Code copy the login around: account-switcher scripts that swap .credentials.json in and out, a credentials file synced between two computers, a wrapper app that reads and refreshes the same entry. Each copy is a second refresher.

Illustration of a common cause of repeated login prompts. Your terminal and a second program both hold a copy of the same saved login. Step 1: the terminal refreshes it and gets a new token, and the old refresh token stops being valid. Step 2: the other program refreshes with the old token. Step 3: the login is revoked, and both ask you to log in again. Your terminal claude Another program switcher, wrapper, synced copy One saved login same refresh token 1 Your terminal refreshes the login It gets a new token. The old refresh token is now used up. 2 The other program refreshes with its old copy It presents a refresh token that was already used. 3 The login can be revoked for both Every session that used it asks you to log in again. Illustration

3. Two accounts in one configuration directory#

If you sign in as your work account in the same directory your personal account lives in, the new login replaces the old one. Switch back, and you're asked to log in again. That's not a bug: one directory, one claude.ai login.

A related report, #98437, describes running /login in one CLI session and seeing other live sessions show the new account while still using the old one's quota. Another reason to keep accounts in separate directories.

4. Another credential is taking over#

If ANTHROPIC_API_KEY is set and you approved it once, Claude Code uses the key instead of your subscription. An old key from a previous job or project in your shell profile can cause odd failures, such as "This organization has been disabled" (#8327). Finding and removing the key everywhere it hides is in Claude Code using your API key, not your plan. When that key's Console organisation has no prepaid credits, the same mistake shows up as Credit balance is too low.

CLAUDE_CODE_OAUTH_TOKEN has its own trap. Per the docs, if you run /login while it's set, the current session switches to the new login, but every new session reads the variable again. So you log in, everything looks fine, and tomorrow you're back on the old token.

5. The macOS Keychain refused the write#

When the Keychain is locked, which happens in SSH sessions, or its password is out of sync with your account password, Claude Code falls back to the plaintext ~/.claude/.credentials.json. Things can then look inconsistent between a local terminal and an SSH session on the same Mac.

6. Less common: policy, old versions, remote shells#

  • An administrator set forceLoginOrgUUID or forceLoginMethod, and your login isn't the kind or organization they require. The prompt appears whether or not you're a member.
  • Before v2.1.290, the login prompt appeared during first-launch setup even when you were signed in. Updating fixes it.
  • In WSL2, SSH sessions and containers, the browser can't reach Claude Code's local callback, so it shows a code instead. Paste that code at the Paste code here if prompted prompt.

Fix it, step by step#

Work down the list and stop when the prompts stop.

  1. See what's active. Run /status. Since v2.1.210, a Login row reads Expired — log in again when your saved claude.ai login has expired, with the organisation and email it saved. That row shows only while the saved claude.ai login is the active credential. When a login and an API key are both configured, /status marks the one that isn't in use.
  2. Check your environment. In a fresh terminal: env | grep -E 'ANTHROPIC|CLAUDE_CODE_OAUTH|CLAUDE_CONFIG_DIR'. Anything you didn't expect? Remove it from ~/.zshrc, ~/.bashrc or ~/.profile (on Windows, your PowerShell $PROFILE and User environment variables).
  3. Update and check the clock. Run claude update, and make sure your system time is set automatically.
  4. Reset the login cleanly. Anthropic's recipe: run /logout, close Claude Code, start claude again and sign in. Logging out also resets first-launch setup and removes saved MCP server logins and plugin secrets, so you'll go through setup and authorize those again.
  5. On a Mac, check the Keychain. Run claude doctor. If it warns that the macOS Keychain is not writable, unlock it with security unlock-keychain ~/Library/Keychains/login.keychain-db, or resync its password in Keychain Access. Then /logout and /login to move the login back into the Keychain.
  6. Over SSH or in a container, press c at the login prompt to copy the sign-in link, or use claude auth login, open the printed link on your own computer, and paste the code back. claude auth login reads the code from standard input, which helps when pasting into the prompt doesn't work. If you see OAuth error: Invalid code. Please make sure the full code was copied, the code expired or was cut off: press Enter and finish the sign-in quickly.
  7. Stop sharing one login. If a switcher script, a second app or a synced folder holds a copy of the same login, give each program its own login, or remove the copy. This is the fix for cause 2, and nothing else on this list will stick until you do it.

Several accounts without overwriting each other#

Anthropic's own answer is one configuration directory per account. Their example, for Bash or Zsh:

bash
alias claude-work='CLAUDE_CONFIG_DIR=~/.claude-work claude'

Open a new terminal, run claude-work, sign in once with your work account, and claude keeps your personal one. Each directory has its own settings, session history and login. One caveat from the docs: separate directories don't keep two Claude Console sign-ins without an API key apart, because that kind of sign-in is stored outside the directory.

This works well. The friction is everything around it: each directory has its own MCP sign-ins, a chat started under one alias can't continue under the other, and you still have to notice when an account runs out. Our guide on switching Claude accounts without logging out goes through the options. And only use accounts you own and are entitled to use: what's known about the rules is in its own guide.

How Shuriken keeps sign-ins apart#

We built Shuriken because we were tired of /login.

Every source has its own sign-in. A source is an account or API key you add. Each Claude source gets its own configuration directory, the same idea as the alias above, managed for you. Signing in to one never replaces another. And the agents Shuriken starts don't inherit the API keys or login tokens your shell profile exports (ANTHROPIC_API_KEY, CLAUDE_CODE_OAUTH_TOKEN and the like), so a forgotten variable can't quietly put a chat on the wrong account.

The login your terminal already uses can be a source too. In Add source, Add current adds the sign-in that's already on the device. Then two programs do hold the same login, which is exactly cause 2. So Shuriken never refreshes a login another program owns: it reads the current access token and leaves the refreshing to Claude Code. When Shuriken refreshes a sign-in of its own, it takes the same lock the Claude Code CLI uses and re-reads the login first, so a chat's CLI and Shuriken never spend the same refresh token twice.

Sign in once, use it on every device. Sign-ins sit in your vault, encrypted before they leave your device, and reach your other computers and servers end-to-end encrypted. You don't type a Claude password into a server's terminal, and our cloud stores the sign-in only encrypted. Your Claude sign-in is never shown to our cloud, not even to check that someone else holds the same account. The security page has the details.

When a sign-in does stop working, the chat doesn't. The source shows Sign in again in Sources, you get a notification that it needs you, and the chat moves on to another of your sources that can take it. We wrote about that change in a refused account no longer ends your chat. When an account simply runs out of room, source switching does the same at your switch point, 99% by default.

MCP sign-ins don't depend on the account. With Global MCPs, you sign in to an MCP server once and the sign-in belongs to the server, so switching Claude accounts never asks you to authorize Notion or GitHub again.

What Shuriken can't do is make Anthropic's login last longer than Anthropic allows. If a login really has expired, you sign in again. The difference is that it's one button, for one source, and your chats keep going on the others while you do.

If you'd rather never type /login between accounts again, download Shuriken and add your accounts as sources.

Sources

  1. Authentication (Claude Code docs) (accessed 24 October 2026)
  2. Troubleshoot installation and login (Claude Code docs) (accessed 24 October 2026)
  3. Issue #1757: Claude code requires users to constantly login (accessed 24 October 2026)
  4. Issue #89490: OAuth session expires mid-session and fails to auto-refresh (closed, not planned) (accessed 24 October 2026)
  5. Issue #98437: /login in one CLI session switches the account shown in other live sessions (accessed 24 October 2026)
  6. Issue #80085: Repeated mid-session logouts on macOS with concurrent instances sharing one Keychain OAuth chain (accessed 24 October 2026)
  7. Issue #91708: concurrent sessions race on OAuth refresh against the file credential store (accessed 24 October 2026)
  8. Issue #8327: 'Organization has been disabled' when ANTHROPIC_API_KEY overrides a subscription (accessed 24 October 2026)

Frequently asked questions

How do I fix the OAuth token has expired error in Claude Code?

Run /login to sign in again. If it keeps coming back, run /status to see which credential is active, update Claude Code, check your system clock, and make sure no second program refreshes the same login.

Why was I logged out after switching Claude accounts?

One configuration directory holds one claude.ai login, so signing in as another account replaces the first. Give each account its own directory with CLAUDE_CONFIG_DIR and both stay signed in.

Where does Claude Code keep its login on a Mac?

In the macOS Keychain. When the Keychain refuses the write, for example when it is locked in an SSH session, Claude Code saves the login to ~/.claude/.credentials.json instead. claude doctor tells you which happened.

Does /logout remove my MCP sign-ins too?

Yes. Anthropic's troubleshooting page says logging out removes all stored credentials, including saved MCP server logins and plugin secrets, so expect to authorize those again.

Free tools