[FEATURE] Preview should allow localhost subdomains (e.g. playground.localhost)

Status Fixed / completed
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Apr 13, 2026 · closed Aug 17, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

When using the Preview feature, navigating to a localhost subdomain like playground.localhost:3000 is blocked with the message:

Link to playground.localhost was blocked. Preview only supports localhost URLs.

Localhost subdomains resolve to 127.0.0.1 the same as localhost and are commonly used in local development (e.g. multi-tenant apps that route by subdomain). The preview URL allowlist should permit *.localhost in addition to localhost.

<img width="549" height="93" alt="Image" src="https://github.com/user-attachments/assets/45cf473d-62e4-4c11-9206-846a943bb106" />

Proposed Solution

The Preview URL allowlist should permit *.localhost in addition to localhost. All subdomains of localhost (e.g. playground.localhost, app.localhost) resolve to 127.0.0.1 per RFC 6761 and are safe to allow. No configuration should be needed — this should just work out of the box.

Alternative Solutions

Currently there's no workaround within Preview. The only option is to open the URL manually in a separate browser, which defeats the purpose of the integrated preview.

Priority

High - Significant impact on productivity

Feature Category

CLI commands and flags

Use Case Example

  1. I'm building a multi-tenant SaaS app (Tightknit) where each community is accessed via a localhost subdomain in local dev (e.g. playground.localhost:3000)
  2. I set up .claude/launch.json and start the dev server via Preview
  3. The app loads at localhost:3000 then redirects to playground.localhost:3000
  4. Preview blocks the redirect with "Link to playground.localhost was blocked"
  5. I have to copy the URL and open it in a separate browser, losing the integrated preview workflow

Additional Context

Localhost subdomains are guaranteed to resolve to loopback by RFC 6761 and are widely used by frameworks like Next.js, Vite, and Rails for multi-tenant local development. Most browsers and dev tools treat them identically to localhost.

View original on GitHub ↗

3 Comments

timherby · 3 months ago

Running into the same thing. We use subdomains, and I'm looking to switch from Conductor due to the upcoming June 15 billing change Anthropic is imposing. Very disappointed to learn that the Claude Code preview doesn't work for subdomains.

We use 2 local loopback subdomains of our own, so need to be able to allowlist these to custom loopback domains.

Link to local.companydomain.com was blocked. Preview only supports localhost URLs.

🙏 Please listen to the numerous people on this thread and fix this prevalent issue.

bcherny collaborator · 14 days ago

The Desktop preview now treats *.localhost subdomains as localhost, alongside localhost, 127.0.0.1, and ::1. You can also point a .claude/launch.json entry at the subdomain directly with a url field, e.g. "url": "http://playground.localhost:3000". See https://code.claude.com/docs/en/desktop. Closing as shipped in a recent release; please reopen if a subdomain is still blocked on the latest Desktop build.

🤖 Generated with Claude Code

tonydattolo · 13 days ago

Still getting this issue on 2.1.234 with claude code cli developing locally:

Connecting Claude Code to a remote MCP server served on a *.localhost
subdomain in local dev fails during the OAuth flow with:

    Refusing to send credentials to non-https token endpoint
    'http://demo.localhost:3000/api/oauth/token'. OAuth token requests
    MUST use TLS (localhost / 127.0.0.1 / ::1 are exempt).

The MCP OAuth client's loopback TLS exemption covers only the four literal
hostnames localhost, 127.0.0.1, [::1], and ::1. From the v2.1.234
bundle:

​``js
function J9d(e){return e==="localhost"||e==="127.0.0.1"||e==="[::1]"||e==="::1"}
function DAb(e){let t=new URL(String(e));if(t.protocol!=="https:"&&!J9d(t.hostname))throw new W9d(t.href);return t}
``

Per RFC 6761 §6.3, every *.localhost name resolves to loopback, so the
security rationale for the exemption applies to them identically.

Why this matters

Multi-tenant apps (Next.js, Rails, Vite) resolve the tenant from the
subdomain, so in local dev the app — and its tenant-scoped OAuth server —
only exists at http://<tenant>.localhost:3000. There is no way to move
the token endpoint to bare localhost without breaking tenant resolution,
and no local HTTPS setup is trusted by the Claude Code runtime out of the box.