Paste into login OAuth code field is broken (works fine in main chat prompt, same terminal)

Resolved 💬 6 comments Opened Apr 14, 2026 by lcortez-code Closed Apr 15, 2026

Summary

The single-line input field on the OAuth login screen ("Paste code here if prompted >") silently rejects pasted input. Typing works, but pasting from the clipboard inserts nothing (or only a few stray characters). The same terminals can paste into Claude Code's main chat prompt without issue, so this looks like a bug specific to the login prompt's input widget rather than a general TUI/terminal compatibility issue.

This blocks completion of the OAuth login flow on any host where the only way to get a long auth code from a browser into the terminal is via clipboard.

Reproduction

  1. On a fresh machine (no existing ~/.claude/.credentials.json), run claude
  2. Choose 1. Claude account with subscription · Pro, Max, Team, or Enterprise
  3. Browser doesn't open, copy the printed https://claude.com/cai/oauth/authorize?... URL into a browser
  4. Authorize in browser → get redirected to https://platform.claude.com/oauth/callback?code=...
  5. Copy the code from the callback page (or the full code#state blob, depending on flow)
  6. Try to paste it into the Paste code here if prompted > field in the terminal

Expected: The pasted code appears in the input field, Enter submits it, login completes.

Actual: Nothing visible appears in the input field. Pressing Enter does nothing, or submits an empty value, or the prompt re-shows. Login cannot complete via this path.

Workaround that proves it's not an OAuth/network problem: typing one character at a time works (but is impractical for ~100-char codes). Generating a long-lived token via claude setup-token on a machine where the login flow does work, then exporting it as CLAUDE_CODE_OAUTH_TOKEN on the broken host, completely bypasses the login screen and Claude Code starts normally — confirming the OAuth credentials are valid; the input widget on the login screen is the only blocker.

Evidence it's the login widget, not the terminal

Pasting a long string (e.g. a code block or a URL) into the main chat prompt of an already-logged-in Claude Code session works fine in the exact same terminal session that just failed at the login prompt. Same Ink runtime, same stdin, same terminal — different input component.

Tested environments

All affected:

| Terminal | Host | Result |
|---|---|---|
| Warp v0.x (latest) | macOS 15.7.1 → SSH → Ubuntu 24.04.4 | paste fails on login screen, works in main chat prompt |
| Apple Terminal | macOS 15.7.1 → SSH → Ubuntu 24.04.4 | same |
| TigerVNC viewer → tigervnc-server on Ubuntu 24.04.4, native xterm | direct on the Ubuntu host, no SSH | same |

Versions

  • Claude Code (Linux server, where login fails): 2.1.105
  • Claude Code (macOS, where login works fine): 2.1.107
  • Node.js: v24.14.1
  • OS: Ubuntu 24.04.4 LTS, kernel 6.8.0-107-generic
  • macOS: 15.7.1 (24G231)

Hypothesis

Modern terminals send pasted text wrapped in bracketed paste escape sequences:

\x1b[200~<pasted text>\x1b[201~

Raw-mode TUI apps must explicitly handle these escape markers to distinguish paste from typed input. Claude Code's main chat prompt clearly handles them correctly. The login OAuth-code input widget appears to be a separate component that does not, so each character of the bracketed-paste payload is processed as an individual keystroke and either:

  • the leading \x1b[200~ is interpreted as escape-then-command-keys and discarded
  • the input reader has length/character validation that rejects the burst
  • per-keystroke re-renders are racing with the input buffer and dropping characters

Confirming this would be straightforward by enabling debug logging on the login widget's keystroke handler and observing what arrives during a paste.

Workaround for users

Skip the login flow entirely:

# On a working machine
claude setup-token
# copy the printed sk-ant-oat01-... token

# On the affected machine
echo 'export CLAUDE_CODE_OAUTH_TOKEN="sk-ant-oat01-..."' >> ~/.profile
. ~/.profile
claude   # opens directly into the chat TUI, no login screen

This is the path I'm using on a headless Ubuntu server where the login paste is unrecoverable. It works perfectly — claude recognizes the env var, the existing OAuth credentials work, and the broken login widget is never touched. So the underlying auth path is fine; only the on-screen paste step is broken.

Suggested fix

The OAuth login input widget should:

  1. Enable bracketed paste reception explicitly (process.stdin with bracketed-paste escape detection)
  2. Buffer characters between \x1b[200~ and \x1b[201~ markers as a single atomic input
  3. Insert the buffered string into the field state in one update rather than per-character

Or simpler: reuse whatever input widget powers the post-login chat prompt, since that one already handles paste correctly.

Why this matters

CLAUDE_CODE_OAUTH_TOKEN is documented but obscure. New users on a fresh machine — especially ones provisioning a remote dev environment, a headless server, or any environment where a graphical browser callback can't reach localhost directly — will hit the OAuth code-paste path as the default flow, can't complete it, and have no obvious next step. Fixing the input widget makes the documented "happy path" actually work.

Happy to test a fix on the affected hosts and confirm if helpful.

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗