{"id":48911898,"url":"https://github.com/giannimassi/webview-cli","last_synced_at":"2026-04-23T06:01:32.906Z","repository":{"id":351884418,"uuid":"1212906611","full_name":"giannimassi/webview-cli","owner":"giannimassi","description":"Native macOS UIs for CLI AI agents. 193KB single binary, ~180ms cold start, no Electron. Renders A2UI declarative UI.","archived":false,"fork":false,"pushed_at":"2026-04-17T09:10:10.000Z","size":619,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-21T04:13:07.852Z","etag":null,"topics":["a2ui","agent","ai-tools","claude-code","cli","macos","mcp","swift","webview","wkwebview"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/giannimassi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-16T21:12:03.000Z","updated_at":"2026-04-21T01:59:23.000Z","dependencies_parsed_at":"2026-04-19T02:01:29.611Z","dependency_job_id":null,"html_url":"https://github.com/giannimassi/webview-cli","commit_stats":null,"previous_names":["giannimassi/webview-cli"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/giannimassi/webview-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giannimassi%2Fwebview-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giannimassi%2Fwebview-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giannimassi%2Fwebview-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giannimassi%2Fwebview-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/giannimassi","download_url":"https://codeload.github.com/giannimassi/webview-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giannimassi%2Fwebview-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32122001,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T00:31:26.853Z","status":"online","status_checked_at":"2026-04-22T02:00:05.693Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a2ui","agent","ai-tools","claude-code","cli","macos","mcp","swift","webview","wkwebview"],"created_at":"2026-04-17T00:05:38.773Z","updated_at":"2026-04-22T05:01:16.559Z","avatar_url":"https://github.com/giannimassi.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ewebview-cli\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eNative macOS UIs for CLI AI agents.\u003c/strong\u003e\u003cbr\u003e\n  \u003csub\u003e~290KB · ~180ms cold start · no Electron · no npm · no runtime\u003c/sub\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"media/hero-deploy.png\" alt=\"Deploy approval window — an agent asks for production deploy approval with a native macOS UI\" width=\"560\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/giannimassi/webview-cli/actions\"\u003e\u003cimg src=\"https://github.com/giannimassi/webview-cli/workflows/CI/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-blue\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/macOS-12%2B-black\" alt=\"macOS 12+\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/binary-~290KB-green\" alt=\"193KB\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/cold%20start-~180ms-orange\" alt=\"~180ms\"\u003e\n\u003c/p\u003e\n\n```bash\ncurl -sSL https://raw.githubusercontent.com/giannimassi/webview-cli/main/install.sh | bash\n```\n\n*One command. Installs the binary via Homebrew, installs the Claude Code skill if `~/.claude` exists, runs a smoke test.*\n\n---\n\n## ~290KB vs Electron's 50MB+\n\nYour AI agent needs to ask you a question that doesn't fit in a terminal prompt. The choices today:\n\n- **Electron app:** 50MB+ runtime, 500–800ms cold start, requires a persistent app bundle. Way too heavy for a subprocess the agent spawns 20 times per session.\n- **Tauri / Wails:** 8–15MB, 300–500ms. Still too heavy, still designed as app frameworks.\n- **`osascript` AppleScript dialog:** built-in, ~300ms, gives you 2 buttons and a text field. Useless for anything structured.\n- **Terminal `[y/N]`:** the default. Fine for yes/no, terrible for \"review this diff\" or \"pick one of these 12 PRs.\"\n\n**webview-cli:** ~290KB single binary, ~180ms cold start, a real native macOS window, structured JSON back to the agent, process dies clean.\n\n| | webview-cli | Electron | Tauri / Wails | osascript |\n|---|---|---|---|---|\n| Binary size | **~290KB** | 50MB+ | 8–15MB | built-in |\n| Cold start | **~180ms** | 500–800ms | 300–500ms | ~300ms |\n| Rich HTML/CSS UI | ✅ | ✅ | ✅ | ❌ |\n| Structured JSON out | ✅ | app-specific | app-specific | ❌ (string) |\n| Spawnable subprocess | ✅ | ❌ (app lifecycle) | ❌ (app lifecycle) | ✅ |\n| Runtime deps | **none** | Electron bundle | WebView2/WebKit2 + Rust | none |\n| Agent-first design | ✅ | ❌ | ❌ | ❌ |\n\n## Why it's this small\n\nThe numbers aren't optimization magic. They come from not bundling things that were already there.\n\n**WKWebView is already on your Mac.** The same engine Safari uses. We wrap it instead of shipping Chromium. That's ~50MB saved, no install-time download, and a decade of Apple's work on rendering correctness and memory management comes for free.\n\n**The Swift runtime ships with macOS 12+.** `libswiftCore`, `libswiftFoundation`, and friends live on the OS. We don't bundle them, version-pin them, or worry about ABI skew. Another ~12MB avoided, and none of the dylib-shipping pain that usually comes with cross-platform Swift.\n\n**A2UI is declarative, not imperative.** Your agent describes *what* UI it wants in a flat JSONL stream; the renderer decides how to lay it out, handle focus, and collect form data. ~250 lines of vanilla JavaScript covers the entire catalog — no React, no templating engine, no build step.\n\nEach subtraction compounded. Together they produced a binary that starts in ~180ms — faster than Electron finishes parsing its own bootstrap scripts.\n\n## Who it's for\n\nAgent developers on macOS.\n\nClaude Code was macOS-first. Cursor is macOS-first. Codex CLI, ChatGPT Desktop, Raycast, Warp, the wave of indie MCP servers being published on GitHub every week — the people building and using agent workflows skew heavily toward macOS. If you've opened Claude Code recently, you're probably holding a Mac.\n\nmacOS-only is a choice, not a gap. A Linux port (GTK + WebKit2) and a Windows port (WebView2) are both technically straightforward, and the protocol is platform-independent — but shipping them at v0.1 would mean three build pipelines, three sets of edge cases, and slower iteration on the platform the audience actually uses. **Depth over breadth.** If you need this on another OS badly enough to maintain a port, open an issue — a clean implementation gets merged.\n\n---\n\n## Use it\n\n### With Claude Code\n\nInstall the bundled skill once:\n\n```bash\nln -s \"$(pwd)/skill\" ~/.claude/skills/webview   # or use the installer flag\n```\n\nThen ask your agent anything that needs structured input from you. The skill handles the rest — generates A2UI, spawns the binary, parses the result, returns typed data. You never write JSONL by hand.\n\n**Example: deploy approval.** Agent says:\n\n\u003e \"I'm about to deploy `payment-service` to production. Should I proceed?\"\n\nThe skill opens a native window with the change summary, a rollout radio (canary / full), a comment field, and Approve/Cancel. You click. The agent receives:\n\n```json\n{\"action\": \"approve\", \"data\": {\"rollout\": \"canary\", \"note\": \"Monitoring on standby\"}}\n```\n\nand continues. No terminal input. No context loss.\n\nOther patterns the skill handles out of the box: single-select from agent-found options (PRs to review, branches to rebase), multi-field config forms, diff-and-acknowledge flows. Full skill docs: [`skill/SKILL.md`](skill/SKILL.md).\n\n### With OpenAI Codex CLI, Gemini CLI, or any subprocess-capable agent\n\nThe binary is protocol-agnostic. Anything that can `spawn_subprocess` and read stdout works:\n\n```python\nimport subprocess, json\n\nresult = subprocess.run(\n    [\"webview-cli\", \"--a2ui\", \"--timeout\", \"120\"],\n    input=your_a2ui_jsonl,\n    capture_output=True, text=True\n)\n# result.returncode: 0=submitted, 1=cancelled, 2=timeout, 3=error\n# json.loads(result.stdout) has {\"status\", \"data\": {\"action\", \"data\": {...}}}\n```\n\nA complete wrapper plus a Codex tool definition you can paste into your agent config: [`examples/openai-codex-tool.md`](examples/openai-codex-tool.md).\n\n### From a shell script or MCP server\n\nIt's a Unix tool. Stdin in, stdout out, exit codes report outcome. Pipes work. Blocking works. Put it wherever a subprocess can run:\n\n```bash\n# Approval gate in a CI/deploy script\nRESULT=$(cat my-form.jsonl | webview-cli --a2ui --title \"Deploy?\" --timeout 300)\ncase $? in\n  0) ACTION=$(echo \"$RESULT\" | jq -r '.data.action'); [ \"$ACTION\" = \"approve\" ] \u0026\u0026 deploy ;;\n  1) echo \"User cancelled.\" ;;\n  2) echo \"Timed out — no response in 5 min.\" ;;\nesac\n```\n\n---\n\n## Common patterns\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### Pick from options\n\nAgent enumerates candidates (PRs, branches, files). User picks one with radio buttons. Agent proceeds with the choice.\n\n\u003cimg src=\"media/select-pr.png\" alt=\"PR picker with 5 options\" width=\"100%\"\u003e\n\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### Multi-field config\n\nText inputs + selects + checkboxes in one native form. Better than six `read -p` prompts in a row.\n\n\u003cimg src=\"media/form-config.png\" alt=\"Multi-field config form\" width=\"100%\"\u003e\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### Destructive confirmation\n\nIrreversible action with context, safety checkbox, and a danger-variant button. Prevents the \"yes 40 times in a row\" mistake.\n\n\u003cimg src=\"media/confirm-destructive.png\" alt=\"Destructive confirmation with safety check\" width=\"100%\"\u003e\n\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### Triage / classification\n\nPriority dropdown, complexity radio, and notes in one native form. Agent gets structured metadata back to act on.\n\n\u003cimg src=\"media/triage.png\" alt=\"Triage form\" width=\"100%\"\u003e\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### Markdown review\n\nAgent generates a spec or doc. User reviews with paragraph-level comments, optionally edits the source, and submits structured feedback. Agent reads the review and can iterate.\n\n[Full example](examples/markdown-review.md)\n\n\u003c/td\u003e\n\u003ctd width=\"50%\" valign=\"top\"\u003e\n\n### Combine markdown review with form\n\nReview a spec AND pick options in one window. Comments, edits, and form fields together.\n\n[Full example](examples/markdown-review-edits.md)\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\n\u003c/table\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eWhat the raw A2UI JSONL looks like\u003c/b\u003e (click to expand — the skill writes this for you)\u003c/summary\u003e\n\n```json\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"root\",\"component\":{\"Column\":{\"children\":{\"explicitList\":[\"card\"]}}}}]}}\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"card\",\"component\":{\"Card\":{\"children\":{\"explicitList\":[\"title\",\"diff\",\"risk\",\"note\",\"btns\"]}}}}]}}\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"title\",\"component\":{\"Text\":{\"usageHint\":\"h2\",\"text\":{\"literalString\":\"Deploy payment-service to prod?\"}}}}]}}\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"diff\",\"component\":{\"Text\":{\"usageHint\":\"body\",\"text\":{\"literalString\":\"3 files · +47/-12 · CI green · ENG-1234\"}}}}]}}\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"risk\",\"component\":{\"RadioGroup\":{\"label\":{\"literalString\":\"Rollout\"},\"fieldName\":\"rollout\",\"options\":[{\"value\":\"canary\",\"label\":\"Canary (10%)\"},{\"value\":\"full\",\"label\":\"Full rollout\"}]}}}]}}\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"note\",\"component\":{\"TextInput\":{\"label\":{\"literalString\":\"Deploy note\"},\"fieldName\":\"note\",\"multiline\":true}}}]}}\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"btns\",\"component\":{\"Row\":{\"alignment\":\"end\",\"children\":{\"explicitList\":[\"c\",\"go\"]}}}}]}}\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"c\",\"component\":{\"Button\":{\"label\":{\"literalString\":\"Cancel\"},\"variant\":\"secondary\",\"action\":{\"name\":\"cancel\"}}}}]}}\n{\"surfaceUpdate\":{\"components\":[{\"id\":\"go\",\"component\":{\"Button\":{\"label\":{\"literalString\":\"Deploy\"},\"variant\":\"success\",\"action\":{\"name\":\"approve\"}}}}]}}\n{\"beginRendering\":{\"root\":\"root\"}}\n```\n\nThat's the whole approval UI above. One line per component, flat adjacency list, LLM-friendly to generate. The skill produces this from a short natural-language description of the UI.\n\n\u003c/details\u003e\n\n---\n\n## Install\n\n### One command (recommended)\n\n```bash\ncurl -sSL https://raw.githubusercontent.com/giannimassi/webview-cli/main/install.sh | bash\n```\n\nHandles Homebrew tap + formula install + Claude Code skill install + smoke test. Flags:\n\n- `--with-claude-skill` — force skill install even if `~/.claude` not detected\n- `--no-claude-skill` — skip skill install\n\n### Homebrew only\n\n```bash\nbrew tap giannimassi/tap\nbrew install webview-cli\n```\n\n### From source\n\n```bash\ngit clone https://github.com/giannimassi/webview-cli.git\ncd webview-cli\nmake install   # copies to ~/bin/webview-cli\n```\n\nRequires macOS 12+ and the Swift toolchain (Xcode Command Line Tools is enough).\n\n---\n\n## Supported A2UI components\n\n`Text`, `TextInput`, `Button`, `Column`, `Row`, `Card`, `Select`, `Checkbox`, `RadioGroup`, `Image`, `Divider`. Subset of [Google's A2UI v0.8 standard catalog](https://a2ui.org/specification/v0.8-a2ui/).\n\nFull prop reference: [`docs/a2ui-subset.md`](docs/a2ui-subset.md). Protocol reference: [`docs/protocol.md`](docs/protocol.md). Architecture tour: [`docs/architecture.md`](docs/architecture.md).\n\n---\n\n## How it works\n\nOne Swift file, ~550 lines. `NSApplication` with `.accessory` policy (no Dock icon), one `NSWindow` with a `WKWebView`, `WKScriptMessageHandler` bridging JS events to stdout, `WKURLSchemeHandler` serving an embedded renderer via `agent://`. Stdin feeds A2UI JSONL into the renderer.\n\nThe renderer itself is ~250 lines of vanilla ES — no React, no framework, no build step. It's embedded as a string literal in the Swift binary. \"What CSS framework is that?\" is a frequent question. The answer is none — system fonts, `-apple-system`, CSS custom properties, ~60 lines of hand-written styles.\n\nSee [`docs/architecture.md`](docs/architecture.md) for the tour.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n## Credits\n\n- [A2UI](https://a2ui.org/) by Google — the declarative UI spec this renders a subset of\n- Opus 4.7 — this tool was built in one evening with Claude Code driving the keyboard. It pairs well with its builder.\n\n---\n\n\u003cp align=\"center\"\u003e\n  Built by \u003ca href=\"https://github.com/giannimassi\"\u003e@giannimassi\u003c/a\u003e. If this unblocks one of your agent workflows, \u003ca href=\"https://github.com/giannimassi/webview-cli\"\u003ea star\u003c/a\u003e is appreciated.\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiannimassi%2Fwebview-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgiannimassi%2Fwebview-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiannimassi%2Fwebview-cli/lists"}