You SSH into a fresh server, run claude, and it wants to open a browser. There is no browser. Here's how to sign in with your Claude Pro or Max plan anyway, which method to pick, and what to do when the login expires.
The short answer
You have two working options:
- Normal login, finished on another device. Run
claude auth loginon the server, open the printed link on your laptop or phone, sign in, and paste the code it shows back into the server. Use this if you want Remote Control. - A long-lived token. Run
claude setup-token, copy the token, and setCLAUDE_CODE_OAUTH_TOKENon the server. Use this for scripts,claude -pjobs and CI. It does not work for Remote Control.
That second point catches a lot of people, so it gets its own section below.
What people run into
- #22992: a request for a device-code login for Pro and Max on headless machines, because "Claude Code's OAuth flow requires a browser redirect back to the machine running Claude Code."
- #65506: "Cannot authenticate Claude Code on headless remote server (VPS)". The login wizard kept coming back over SSH.
- #102985: a headless Linux server that "loses its OAuth login every 1–2 days" when many Claude Code processes share one credentials file.
Option 1: sign in on the server, finish in your laptop's browser
On the server:
claude auth login(Or run claude and type /login. Same flow.) Choose the claude.ai subscription option. Claude Code tries to open a browser, fails quietly, and prints:
If the browser didn't open, visit: https://claude.com/cai/oauth/authorize?...
Paste code here if prompted >Copy that whole URL. If it wraps across lines in a narrow SSH window, the troubleshooting docs suggest pressing c in the interactive login to copy it cleanly. Open it on your laptop or phone, sign in, approve, and the page shows a code. Paste the code at the prompt on the server. You should see Login successful.
You don't need SSH port forwarding. On Claude Code 2.1.303 the printed link points to a page on platform.claude.com that shows the code, not to a local port on the server. The authentication docs describe this paste-the-code path for SSH sessions, WSL2 and containers.
Check it worked:
claude auth status --textIt exits 0 when you're signed in. On Linux the login lives in ~/.claude/.credentials.json, file mode 0600.
If you get OAuth error: Invalid code, the code expired or got cut off while copying. Run the login again and paste quickly.
Option 2: a one-year token with setup-token
On any machine with a browser (or on the server, using the same paste-the-code step):
claude setup-tokenIt runs the same browser sign-in and prints a token. It does not save it, so copy it now. On the server:
echo 'export CLAUDE_CODE_OAUTH_TOKEN=your-token' >> ~/.bashrc
source ~/.bashrc
claude -p "say hi"For a systemd service, put it in an EnvironmentFile readable only by that user, not in the unit file itself. Treat it like a password: it's your subscription.
What the token can and can't do, per the docs:
- It lasts one year and needs a Pro, Max, Team or Enterprise plan.
- It "can only make model requests, so it can't establish Remote Control sessions or fetch claude.ai connectors." Local MCP servers still work.
--baremode doesn't read it.
Why Remote Control fails with the token
If CLAUDE_CODE_OAUTH_TOKEN is set and you run claude remote-control, you'll see "Remote Control requires a full-scope login token". The env variable also wins over a normal /login in every new session. So on a box where you want Remote Control:
unset CLAUDE_CODE_OAUTH_TOKEN
claude auth loginand remove the export from ~/.bashrc or any .env file. Use Option 1 there. If you see "Remote Control environments are not available for your account" instead, that guide walks through the other causes.
When the login expires
A /login login doesn't last forever. Claude Code gives you three signals:
- At startup, within three days of expiry:
Your login expires in 3 days · run /login to renew. /statusshows aLoginrow readingExpired — log in again.- Once expired, each request fails with
Login expired · Please run /login. Remote Control showsRemote Control disconnected — Claude.ai login expired — run /login to restore Remote Control.
The catch on a server: the startup warning only shows when you start Claude, and a session that runs for weeks never restarts. The docs say it plainly: a Remote Control session that outlives the login "stops making progress once the credential expires and can't recover until you sign in again."
To renew, SSH in, attach to your tmux session and run /login, then /remote-control if asked. A cheap guard is a daily cron that checks the login and emails you if it fails:
0 9 * * * claude auth status >/dev/null || echo "Claude login expired on $(hostname)" | mail -s "claude login" you@example.comThat needs a working mail setup. Swap in whatever alert you already use. Test it once with a logged-out config first: the docs promise a non-zero exit only for "not logged in", so check that your version also exits non-zero once a login has expired.
Many processes, one login
If you run several Claude Code processes on one account (a server, a few -p jobs, an SDK app), they share ~/.claude/.credentials.json and take turns refreshing it. #102985 shows that going wrong. If you see "Could not refresh your login because another Claude Code process is refreshing it", wait a minute and retry. If it keeps happening, run fewer processes on that login, or give scripts their own setup-token token.
Related fixes
- Claude Code Remote Control keeps disconnecting: sleep, network and idle drops.
- "Remote Control environments are not available for your account": when Remote Control won't start.
- Running Claude Code on a server: the whole always-on setup.
If you'd rather not keep a machine awake
Running your own server means you're also the one who notices when the login runs out. Podway is an always-on cloud computer for Claude Code. You sign in with your own Pro or Max plan and open the session from the Claude app via Remote Control. Before your Claude login expires, Podway tells you, with a one-click reconnect. If the agent crashes, Podway restarts it and reconnects Remote Control. On Team or Enterprise, your org Owner needs to enable Remote Control.
Your first pod is free, no card needed, and pods start at $4/month. Start a pod, or see the agent computer page.