ReviewOS

craft-native/craft

Headless/automation mode: no way to drive the webview from outside the process

#48
Closed glennmichael123 opened this 10 days ago ·
10 days ago

There is currently no way to test a craft app's actual window from CI or a script:

  • --eval/--eval-file run JS on craft's own runtime with no window and no WebKit (cli.zig:35-38), so they cannot drive a page.
  • No remote-debugging port, no external evaluate-in-page, no screenshot CLI. The only screenshot path is craft.screenCapture from inside the page.
  • e2e_test.zig:241 declares headless: bool = false and never reads it; test-utils.ts:12 mirrors the same unused field.
  • ui_automation.zig walks native AX hierarchies (finds NSButtons) but is not webview-aware.

What this costs downstream, concretely (stacksjs/harness): three separate test artifacts exist to work around it — a headless-Chromium stand-in that stubs window.craft and cannot cover the real NSMenu, key delivery, gestures or cold start; an AppleScript driver that needs a GUI session + Accessibility permission and whose ground truth is a marker file written through a PTY because frontmost of process reads false while keystrokes land; and an HTTP probe endpoint the page POSTs to, because the only way to know what the injected bridge actually has is to ask the page. Perf measurement loops also had to spawn visible windows repeatedly, which is genuinely hostile to photosensitive users.

Suggested surface, in order of value:

  1. --remote-debugging / --automation: enable WebKit's remote inspector for the created WKWebView (_setRemoteInspectionAllowed: / inspectable = YES on modern SDKs) and print the port/UUID. That alone makes every existing WebDriver-ish tool usable.
  2. craft eval-in-page <js> against a running instance (evaluateJavaScript over a local control socket) — the two-way version of what injectCraftScripts already does one-way.
  3. craft screenshot [--window] via the existing capture path, callable from outside.
  4. --headless: create the window off-screen/orderOut: so measurement loops stop flashing windows at the operator.

🤖 Generated with Claude Code

Sign in to comment on this issue.