anthropics / anthropics/claude-code
[FEATURE] Desktop browser preview: auto-allow RFC 6761 reserved TLDs (*.test) that resolve to loopback, like *.localhost
- Lingua principale
- Python
- Stelle
- 145k
- Fork
- 23.1k
- Metriche di merge delle PR
- Metriche PR in attesa
Descrizione
### Preflight Checklist
- [x] I have searched [existing requests](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20label%3Aenhancement) and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
### Problem Statement
The Claude Desktop app (Code tab) built-in Browser pane treats only `localhost`, `*.localhost`, `127.0.0.1` and `::1` as local dev servers. Every other origin goes through the "allow this site" flow, and on top of that through a second, separate gate for private-network read tools (`read_page`, `get_page_text`, screenshots).
Laravel Herd, Valet and Laragon serve **every** site on `*.test` by default. That is the standard local PHP/Laravel/WordPress setup on macOS and Windows. `.test` is a TLD reserved by [RFC 6761](https://www.rfc-editor.org/rfc/rfc6761#section-6.2), exactly like `.localhost`, and can never be a routable public domain.
In practice this means that for each project I have to:
1. Approve navigation to `https://myapp.test` ("Always allow").
2. Approve it again for `http://myapp.test` if the redirect or a link uses plain http (scheme counts as a separate origin).
3. Approve the private-network read gate separately, otherwise `read_page` / screenshot fail with "This site requires per-action approval; Browser read tools are not available on it".
Each approval lands as a separate literal entry in `claude_desktop_config.json`. After a few projects my `preferences` block looks like this (real, trimmed):
```json
"launchPreviewAllowedOrigins": [
"https://app-one.test",
"http://app-two.test",
"https://app-three.test",
"https://app-four.test",
"http://app-four.test",
"https://app-five.test"
],
"launchPreviewPrivateNetworkReadOrigins": [
"https://app-four.test",
"https://app-one.test"
],
"launchPreviewPrivateNetworkReadPins": {
"https://app-four.test": ["127.0.0.1"],
"https://app-one.test": ["127.0.0.1"]
}
```
Note the `Pins` block: the app **already resolves these origins and pins them to `127.0.0.1`**. So the loopback check exists, it just is not used to short-circuit the permission flow.
The alternative, switching Herd to `*.localhost`, is a global setting that affects every site on the machine and breaks tooling that assumes the Herd default (`herd link`, `herd secure`, shared `.env` files across a team).
### Proposed Solution
Any one of these would solve it; the first is the cleanest:
1. **Auto-allow reserved local TLDs pinned to loopback.** On first visit, if the host ends in `.test` / `.localhost` and resolves to a loopback address (`127.0.0.0/8`, `::1`), allow it silently **and record the resolved address in `launchPreviewPrivateNetworkReadPins`**, exactly as the manual "Always allow" flow does today. On every later visit require both conditions: the host still resolves to loopback **and** the result matches the stored pin. Any drift (different address, non-loopback, NXDOMAIN) drops the automatic trust and falls back to the current prompt. The pin mechanism already exists; this only changes who creates the first pin (the app instead of a click). Trusting the live lookup alone would remove the one check that catches a `.test` name being re-pointed later.
2. **Wildcard / pattern support** in `launchPreviewAllowedOrigins` and `launchPreviewPrivateNetworkReadOrigins`, e.g. `"https://*.test"`, `"*://*.test"`.
3. **A trusted-local-TLD preference**, e.g. `"launchPreviewTrustedLocalTlds": ["test"]`, applied with the same loopback check as in (1).
Also, regardless of the above: an "Always allow" approval for one origin should cover both the navigation gate and the private-network read gate, and `http`/`https` for the same host. Today they are three independent prompts, which is what makes this feel broken rather than merely strict.
### Alternative Solutions
- **Manually editing `claude_desktop_config.json`** while the app is closed, adding the origin to both lists plus a `127.0.0.1` pin. Works, but is undocumented, fragile, and has to be repeated per project and per scheme.
- **Herd on `*.localhost`**: global change, breaks team conventions and Herd defaults, see above.
- **`.claude/launch.json` with `"url": "https://myapp.test"`**: still hits both prompts; `launch.json` only auto-trusts `localhost` origins.
- **Using Claude in Chrome instead of the built-in pane**: loses `preview_start` / `preview_logs` integration and the whole point of the built-in Browser pane.
### Priority
High - Significant impact on productivity
### Feature Category
Configuration and settings
### Use Case Example
1. `herd link` in `D:\Herd\myapp` → site is served on `https://myapp.test`, resolving to `127.0.0.1`.
2. Ask Claude Code Desktop to fix a layout bug and verify it in the preview.
3. Claude runs `preview_start` with the `.test` URL → prompt 1 (navigate). Approve.
4. Claude runs `read_page` / screenshot → prompt 2 (private-network read). Approve.
5. Page redirects to `http://` once → prompt 3.
6. Next project, repeat from step 3.
With the proposal: step 3 onward is silent, same as it is today for `http://localhost:3000`.
### Additional Context
- Related: #91495 (open, `area:desktop` / `area:permissions`, same Herd `*.test` scenario, per-call prompts), #78315 (closed as invalid, describes the navigate-vs-read two-gate inconsistency), #27263 (closed as completed, external URL whitelist).
- Docs: https://code.claude.com/docs/en/desktop.md, section "Open the preview at a specific URL", lists the four auto-allowed local patterns.
- RFC 6761 §6.2 reserves `.test` for testing; §6.3 reserves `.localhost`. Browsers already special-case `.localhost` as loopback (Chrome resolves `*.localhost` to loopback without DNS). `.test` is the de-facto equivalent for local PHP tooling.
- Environment: Windows 11 Pro 10.0.26220, Claude Desktop (Code tab, built-in browser), Claude Code CLI 2.1.250, Laravel Herd (Windows) serving `*.test`.
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Direzione di ricerca
Start with the desktop.md section on opening previews at a specific URL, then trace the preview_start, read_page, and screenshot permission flows. Compare the existing localhost handling with launchPreviewAllowedOrigins, launchPreviewPrivateNetworkReadOrigins, and launchPreviewPrivateNetworkReadPins. Done means loopback-resolved .test origins follow the agreed trust and pin behavior without weakening fallback prompts.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- python
- Ambito
- desktop, networking, security
- Tipo di issue
- Funzionalità
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Attiva
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 45/100