Desktop preview: navigator.clipboard.writeText() fails with 'Write permission denied' (embedded browser denies clipboard-write)

Resolved 💬 2 comments Opened Jun 19, 2026 by fronrich-silktide Closed Jun 23, 2026

Summary

In the Claude Code desktop app's built-in app preview, any previewed web app that calls navigator.clipboard.writeText(...) (or clipboard.write(...)) fails. The async Clipboard API exists but its permission is denied by the preview's embedded browser, so the call rejects with:

NotAllowedError: Failed to execute 'writeText' on 'Clipboard': Write permission denied

This is not an issue with the previewed app — it is the preview environment's clipboard permission policy.

Environment

  • Claude Code desktop app, built-in preview (MCP Claude_Preview: preview_start / preview_eval).
  • Previewed app: Next.js dev server on http://localhost:<port>.
  • macOS (Darwin).

Repro

  1. Run any web app in the desktop preview.
  2. From a user gesture (button click), call navigator.clipboard.writeText("hello").
  3. The promise rejects with NotAllowedError: ... Write permission denied.

Observed (probed via preview_eval in the live preview)

{
  "isTopLevel": true,            // top-level context, NOT a nested iframe
  "hasFrameElement": false,
  "isSecureContext": true,       // localhost is a secure context
  "writeTextExists": "function", // API present
  "permClipboardWrite": "denied" // navigator.permissions.query({name:'clipboard-write'}) -> "denied"
}

Analysis

The context is top-level and secure, so this is not an iframe-delegation problem and cannot be fixed by a Permissions-Policy response header from the previewed app (a document header can only restrict, never grant beyond the embedder). With clipboard-write reported as denied in a top-level Electron/embedded-browser context, the denial originates from the embedder's permission handler (e.g. session.setPermissionRequestHandler / setPermissionCheckHandler) — i.e. inside the Claude Code desktop app, out of the previewed app's control.

Expected

The preview's embedded browser should grant (or at least allow, on user gesture) the clipboard-write permission, so that standard navigator.clipboard.writeText() works during preview testing — matching normal localhost browser behavior.

Suggested fix

In the preview's Electron session, allow clipboard-sanitized-write (and optionally clipboard-read) in the permission request/check handler for previewed localhost origins.

Workaround (for app authors)

Catch the rejection and fall back to a legacy document.execCommand("copy") (works under a real user gesture with focus), then degrade to a toast.

View original on GitHub ↗

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