# Let your coding agent test the real Windows UI `pointframe verify` lets an agent verify a change to a Windows desktop app in its real UI: it runs your project's own build and test commands and, for each scenario in the spec, launches the built app, drives it through its controls, and writes a verdict with screenshots and a signed evidence bundle. A Stop hook then keeps your coding agent (Claude Code or Codex) working until the last verdict is a fresh pass, with two exceptions: the agent may stop unverified when verify hits an error only a person can fix, such as an untrusted or invalid spec, and after five blocks. The stop message then says the work was not verified. Build and test gates run headless, including in CI; checks of the real UI need an unlocked, interactive Windows session. This page shows how to set it up in your own project. The full reference is in the [CLI README](README.md#verify-a-desktop-app-from-a-spec). The fields of the spec file are in the [spec reference](verify-spec.md). ## Coding agents: start here The same recipe is the guide `Pointframe.Mcp/Guides/verify-desktop-work.md`, which the MCP server serves as `pointframe://guides/verify-desktop-work` and the Pointframe plugin ships as a skill. This is the short path from it; run `pointframe verify setup` afterwards for interactive desktop tools. Run everything from the project root, in an interactive, unlocked Windows desktop session. 1. Install the CLI (skip this if `pointframe --version` works). Run this one line as it is, in one tool call; it works from Bash and from PowerShell: ``` pwsh -NoProfile -Command '$u="https://github.com/dimitar-radenkov/Pointframe/releases/latest/download/Pointframe.Cli-win-x64.zip"; $d=Join-Path $env:TEMP "pointframe-cli"; Remove-Item $d -Recurse -Force -ErrorAction Ignore; New-Item -ItemType Directory $d | Out-Null; Invoke-WebRequest $u -OutFile "$d\cli.zip"; Invoke-WebRequest "$u.sha256" -OutFile "$d\cli.zip.sha256"; if ((Get-FileHash "$d\cli.zip").Hash -ne ((Get-Content "$d\cli.zip.sha256" -Raw).Trim() -split "\s+")[0]) { throw "SHA-256 mismatch" }; Expand-Archive "$d\cli.zip" "$d\x"; & "$d\x\Pointframe.Cli.exe" install; "$env:LOCALAPPDATA\Programs\Pointframe.Cli\pointframe.exe"' ``` `install` puts `pointframe` on the user `Path` for new shells only. In the shell you already have open, call the exe path the line prints (`%LOCALAPPDATA%\Programs\Pointframe.Cli\pointframe.exe`) in place of `pointframe`. 2. Write the spec, with your built exe's path relative to the project root (one line, for a single-project WPF app): ``` pointframe verify init --app bin/Release/net10.0-windows/MyApp.exe --hooks none ``` 3. Add one scenario to the `scenarios` array of `.pointframe/verify.json`: an action, the resulting state, and a negative control (a check with `expectFailure` and a deliberately wrong expectation, which must fail): ```jsonc { "id": "save-text", "criteria": ["Saving shows the typed text in the status line."], "steps": [ { "enterText": { "automationId": "textBox", "text": "hello" } }, { "invoke": { "automationId": "saveButton" } }, { "check": { "kind": "textEquals", "automationId": "statusLabel", "expected": "Saved hello", "criterion": "C1" } }, { "check": { "kind": "textEquals", "automationId": "statusLabel", "expected": "Not saved", "expectFailure": true, "timeoutSeconds": 1 } } ] } ``` 4. Make it a `verify-` skill (pstack-compatible), so the next agent can repeat the proof. Use ONE folder, the project skill folder the repo already has: `.claude/skills/` for Claude Code, `.agents/skills/` for Codex and other agents. The folder and the `name:` in the SKILL.md frontmatter are both `verify-`: ``` /verify-/SKILL.md (frontmatter: name: verify-, description: Prove that a change to works ... Use after changing .) /verify-/features/README.md (lists the feature files) /verify-/features/.md (one per feature) ``` Each feature file has exactly four H2 sections, with these exact headings: `Sub-features`, `How to get to it (user POV)`, `Driving it with Pointframe`, `Gotchas`. `Driving it with Pointframe` and `Gotchas` name the scenario id (for example `save-text`) and say to run `pointframe verify run --scenario `; they never copy steps from the spec. Write all skill files in one shell command, before step 5. 5. Run `pointframe verify run`. It runs the gates, launches the app, drives the scenario in the real UI, and installs the MCP server itself on its first run. Read `status` in the printed JSON: `pass` is exit 0, `fail` is exit 1, a wrong spec is exit 2. Run `verify run` last: any later edit, even to docs or skill files, makes the pass stale (`verify status` then shows `fresh: false`), so write everything first and run again if you change anything. 6. Evidence: `artifacts/pointframe-verify/verdict.json` is the verdict, and each scenario's signed bundle (`report.json`, `evidence/` screenshots, `index.html`) is under `artifacts/pointframe-verify/runs/