Skip to content

Web UI does not open after ExitPlanMode on Windows + Claude Code (0.19.15) — server runs, plan captured #724

@NotMyself

Description

@NotMyself

Description

On Windows with Claude Code, the PermissionRequest:ExitPlanMode hook fires correctly and the Plannotator server starts on a random port — but the browser tab never auto-opens, so the user sees no UI and the plan-mode permission appears to be granted without review.

Structurally this looks like the same class of bug as #551 (closed; OpenCode + Linux + xdg-open), but with cmd.exe /c start ${url} failing silently in the Claude Code hook subprocess context on Windows.

Environment

OS Windows 11 Pro 10.0.26200
Agent Claude Code 2.1.140
Plannotator 0.19.15 (plugin); bun 1.3.11 (binary)
Default browser Microsoft Edge
Install /plugin install plannotator@plannotator (user scope)

Steps to reproduce

  1. Enable the plannotator plugin in Claude Code.
  2. Enter plan mode (Shift+Tab) and ask Claude to make a plan.
  3. Wait for the model to call ExitPlanMode.

Expected behavior

Browser tab auto-opens at http://localhost:<random> showing the plan UI for annotation/approval.

Actual behavior

  • ExitPlanMode permission is granted effectively instantly with no UI prompt.
  • No browser tab opens.
  • The plannotator server is running. Confirmed by:
    • ~/.plannotator/sessions/<pid>.json is created with a fresh port + URL.
    • The plan is captured in ~/.plannotator/history/<project>/<title>-<date>/NNN.md.
    • curl -sI http://localhost:<port>/ returns HTTP 200 with the expected ~17 MB HTML payload — the UI is reachable, just never opened.

So the hook works end-to-end except for openBrowser().

Root cause hypothesis

In packages/server/browser.ts:

if (platform === "win32" || wsl) {
  await $`cmd.exe /c start ${url}`.quiet();
}

Wrapped in try/catch with .quiet(). When this fails in the Claude Code hook subprocess context — likely the same "child process can't reach the interactive desktop / env not propagated" mode that #551 hit on Linux/OpenCode — the failure is swallowed and only the VS Code IPC fallback is attempted. On a non-VS-Code Claude Code install there's no IPC registry to fall back to, so the user sees nothing.

(Bun's shell template-tag $ interpolation may also be a factor — possible URL escaping/splitting that confuses cmd.exe start — but I haven't verified that vs. the subprocess-context theory.)

Related

Workaround (interactive)

The UI is reachable; you can open it manually:

Get-Content ~/.plannotator/sessions/*.json |
  ConvertFrom-Json |
  Sort-Object startedAt |
  Select-Object -Last 1 -ExpandProperty url

Open the printed URL in a browser. Plan / annotation flow works normally from there.

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions