OAuth login on headless EC2: code paste broken after recent update
Problem
After a recent Claude CLI update, the OAuth login flow on headless EC2 instances no longer allows reliable copy-paste of the OAuth code.
Environment
- Ubuntu 24.04 on EC2 (headless, no browser)
- SSH from Windows terminal
- Claude CLI (latest)
What broke
claude auth loginprints an OAuth URL and prompts for the code- After authorizing in a local browser, the returned code (format:
XXXXXX#YYYYYY) cannot be pasted back reliably:
Ctrl+Vdoesn't work in SSH terminals on Windows- The
#character in OAuth codes gets interpreted as a shell comment - Right-click paste is unreliable
- Piping via
echo "code" | claude auth loginopens a new PKCE flow, ignoring the piped input expectcannot detect the raw terminal>prompt
Current workaround
Using tmux send-keys to deliver the code into the same process that generated the PKCE challenge:
# Start login in tmux
tmux new-session -d -s login 'bash -lc "claude auth login" 2>&1 | tee /tmp/tmux_login.log'
sleep 6
cat /tmp/tmux_login.log
# Open the URL in local browser, get the code, then:
tmux send-keys -t login "CODE_HERE" Enter
This works but is cumbersome for production environments with multiple EC2 instances.
Suggestion
Consider one of:
- A
--codeflag:claude auth login --code <oauth-code>(non-interactive) - A file-based flow:
claude auth login --code-file /tmp/oauth-code.txt - Support for piped stdin:
echo "code" | claude auth login - A device-code flow that doesn't require pasting back into the CLI
What Does NOT Work
| Method | Why It Fails |
|--------|-------------|
| Copying credentials from local machine | OAuth tokens are machine-bound |
| Piping stdin via echo "code" \| claude auth login | CLI opens a new OAuth flow |
| expect with prompt matching | Raw terminal input undetectable |
| Starting multiple login attempts | Each creates new PKCE challenge |
| Ctrl+V / right-click paste in SSH | Unreliable on Windows; # in codes breaks |
Key Insight: PKCE Challenge Binding
Each claude auth login generates a unique code_challenge. The OAuth code returned after authorization is cryptographically bound to that specific challenge. This means:
- You MUST use the code with the SAME session that generated the URL
- Starting a new
claude auth logininvalidates all previous codes - The tmux approach works because
send-keystypes into the SAME process
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗