{"id":44983362,"url":"https://github.com/k-kohey/axe","last_synced_at":"2026-04-02T21:39:57.754Z","repository":{"id":338796749,"uuid":"1159210442","full_name":"k-kohey/axe","owner":"k-kohey","description":"A SwiftUI Preview command-line tool with hot reload support, and a VS Code extension powered by that tool","archived":false,"fork":false,"pushed_at":"2026-02-28T22:44:05.000Z","size":3007,"stargazers_count":12,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-01T00:48:28.165Z","etag":null,"topics":["hotreload","ios","swift","swiftui","xcode"],"latest_commit_sha":null,"homepage":"","language":"Go","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/k-kohey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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-02-16T13:03:49.000Z","updated_at":"2026-02-28T22:44:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/k-kohey/axe","commit_stats":null,"previous_names":["k-kohey/axe-cli"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/k-kohey/axe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-kohey%2Faxe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-kohey%2Faxe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-kohey%2Faxe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-kohey%2Faxe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/k-kohey","download_url":"https://codeload.github.com/k-kohey/axe/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-kohey%2Faxe/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30253941,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T08:59:44.879Z","status":"ssl_error","status_checked_at":"2026-03-08T08:58:02.867Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["hotreload","ios","swift","swiftui","xcode"],"created_at":"2026-02-18T19:00:36.898Z","updated_at":"2026-03-08T11:02:50.946Z","avatar_url":"https://github.com/k-kohey.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/icon.png\" alt=\"axe\" width=\"128\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eaxe\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eSwiftUI live preview with hot-reload, and view hierarchy inspection, all from the command line.\u003c/p\u003e\n\n## Features\n\n### 🖥️ VS Code / Cursor Extension\n\nOpen a Swift file with `#Preview` and the preview starts automatically. See [vscode-extension/README.md](vscode-extension/README.md).\n\naxe is a CLI tool for running SwiftUI Previews with hot-reload support.\nIt works standalone, but also supports Protobuf-defined input/output schemas so you can pair it with any frontend.\nAs a reference implementation, a VS Code / Cursor extension is available:\nhttps://marketplace.visualstudio.com/items?itemName=k-kohey.axe-extension\nMulti-simulator management, preview frame streaming, and input forwarding are all handled by axe as the backend.\n\nTo build your own client (Emacs, Vim, web frontend, etc.), try the serve command:\n\n```bash\naxe preview serve [flags]\n```\n\n\u003cimg src=\"docs/demo.gif\" alt=\"VS Code Extension demo\"\u003e\n\n### 🤖 AI Agent Coding Support\n\nCLI-first design enables AI agents to operate SwiftUI Previews directly.\n\nSince every operation is available through the CLI, AI agents such as Claude Code can use axe without a GUI. The simulator runs headlessly.\nA Claude Code plugin is provided with skills for capturing previews, reviewing UI, and inspecting view hierarchies — all driven autonomously by the agent. Files with multiple `#Preview` blocks are fully supported.\n\nInstall the Claude Code plugin:\n```bash\n# Register the marketplace\nclaude plugin marketplace add k-kohey/axe\n\n# Install the plugin\nclaude plugin install axe-preview@axe\n```\n\nAll features are accessible via the CLI, making it straightforward to capture previews from multiple processes or integrate with CI.\n\n\u003cimg src=\"docs/ai_agent_skill_demo.gif\" alt=\"AI Agent Coding Support demo\"\u003e\n\n### 📸 Report\n\nBatch-capture screenshots of every `#Preview` block and generate a Storybook-style report.\n\n`axe preview report` captures screenshots of all `#Preview` blocks in the specified Swift files and outputs them as PNG, Markdown, or HTML. Useful for visual review in PRs or automated UI catalog generation. Host the generated HTML to use it as a living storybook.\n\n\u003cimg src=\"docs/report_demo.png\" alt=\"Preview Report demo\"\u003e\n\n### 🔍 View Hierarchy Inspection\n\nDump the UIKit/SwiftUI view hierarchy via LLDB, with an interactive TUI browser and per-view PNG snapshots.\n\nProcessing images is generally slower than processing text. The `axe view` command provides a text-based alternative for quickly inspecting views or helping AI agents understand view structure.\n\n\u003cimg src=\"docs/inspect_demo.png\" alt=\"View Hierarchy Inspection demo\"\u003e\n\n\n## Requirements\n\n- macOS (Apple Silicon)\n- Xcode (command-line tools)\n- [`idb_companion`](https://github.com/facebook/idb) — for headless simulator management\n\n## Install\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/k-kohey/axe/main/install.sh | sh\n```\n\nThe installer also installs `idb_companion` via Homebrew if not present. To install it manually:\n\n```bash\nbrew install facebook/fb/idb-companion\n```\n\nOr download a binary from the [Releases](https://github.com/k-kohey/axe/releases) page.\n\n## Quick Start\n\nCreate a `.axerc` in your project root so you don't have to pass flags every time:\n\n```\nPROJECT=MyApp.xcodeproj\nSCHEME=MyApp\n```\n\nThen preview any Swift file containing `#Preview`:\n\n```bash\n# Oneshot: capture screenshot to stdout\naxe preview MyView.swift \u003e screenshot.png\n\n# Watch mode: hot-reload on file changes\naxe preview watch MyView.swift\n```\n\n## Usage\n\n### `axe preview`\n\nLaunch a SwiftUI preview on a headless iOS Simulator.\n\nThe `preview` command has several subcommands:\n\n| Command | Description |\n|---|---|\n| `axe preview \u003cfile\u003e` | Oneshot: capture a PNG screenshot to stdout, then exit |\n| `axe preview watch \u003cfile\u003e` | Watch for file changes and hot-reload |\n| `axe preview serve` | Run as multi-stream IDE backend (JSON Lines protocol) |\n| `axe preview report` | Capture screenshots of all `#Preview` blocks |\n| `axe preview simulator` | Manage simulators for preview |\n\n#### Oneshot Mode (default)\n\n```bash\naxe preview MyView.swift \u003e screenshot.png\naxe preview \u003csource-file.swift\u003e [flags]\n```\n\nBuilds and launches the preview, captures a **PNG screenshot to stdout**, then exits (exit 0 on success, exit 1 on failure).\n\n| Flag | Description |\n|---|---|\n| `--preview` | Select a `#Preview` block by title or index (e.g. `--preview \"Dark Mode\"` or `--preview 1`) |\n| `--reuse-build` | Skip xcodebuild and reuse previous build artifacts |\n| `--full-thunk` | Use full thunk compilation (per-file dynamic replacement) |\n\n#### `axe preview watch`\n\n```bash\naxe preview watch MyView.swift\naxe preview watch \u003csource-file.swift\u003e [flags]\n```\n\nWatch the source file for changes and hot-reload the preview. Body-only changes are hot-reloaded without rebuilding; structural changes trigger a full rebuild automatically. When an untracked dependency file changes, axe attempts an incremental reload (adding the file to the tracked set) before falling back to a full rebuild.\n\n| Flag | Description |\n|---|---|\n| `--preview` | Select a `#Preview` block by title or index |\n| `--reuse-build` | Skip xcodebuild and reuse previous build artifacts |\n| `--strict` | Require full thunk compilation (no degraded fallback) |\n| `--headless` | Run simulator headlessly without a display window |\n| `--max-thunk-files` | Maximum number of tracked files for incremental thunk generation (default `32`, `0` = unlimited) |\n| `--pre-thunk-depth` | Dependency depth for initial thunk generation (`0` = target only, `1` = direct deps; default `0`) |\n\n#### `axe preview serve`\n\n```bash\naxe preview serve [flags]\n```\n\nRun as a multi-stream IDE backend. Streams are managed via JSON Lines commands on stdin (`AddStream`/`RemoveStream`), and events (`Frame`/`StreamStarted`/`StreamStopped`/`StreamStatus`) are emitted on stdout. Used by the VS Code / Cursor extension.\n\n| Flag | Description |\n|---|---|\n| `--strict` | Require full thunk compilation (no degraded fallback) |\n| `--max-thunk-files` | Maximum number of tracked files for incremental thunk generation (default `32`, `0` = unlimited) |\n| `--pre-thunk-depth` | Dependency depth for initial thunk generation (`0` = target only, `1` = direct deps; default `0`) |\n\n#### Common Flags\n\nThese flags are shared by all `preview` subcommands:\n\n| Flag | Description |\n|---|---|\n| `--project` | Path to `.xcodeproj` |\n| `--workspace` | Path to `.xcworkspace` (mutually exclusive with `--project`) |\n| `--scheme` | Xcode scheme to build (required) |\n| `--device` | Simulator UDID to use (searches axe set first, then standard Xcode set) |\n| `--configuration` | Build configuration (e.g. `Debug`) |\n\nAll flags fall back to `.axerc` values when not specified.\n\n#### `axe preview report`\n\nCapture all `#Preview` blocks in one or more Swift files as screenshots (`png`), a Markdown report (`md`), or an HTML report (`html`).\n\n```bash\n# Single file → single file\naxe preview report Sources/FooView.swift -o screenshot.png\n\n# Multiple files → directory (auto-created)\naxe preview report Sources/FooView.swift Sources/BarView.swift -o ./screenshots/\n\n# Markdown report + external PNG assets (directory required)\naxe preview report Sources/FooView.swift Sources/BarView.swift --format md -o ./preview-report\n\n# HTML report (responsive, dark-mode, lightbox) + external PNG assets\naxe preview report Sources/FooView.swift Sources/BarView.swift --format html -o ./preview-report\n```\n\nWhen `--output` is a directory, screenshots are saved as `\u003cbasename\u003e--preview-\u003cindex\u003e.png`.\nFor `--format md` or `--format html`, `--output` must be a directory, and axe writes:\n- `axe_swiftui_preview_report.md` (or `.html`)\n- `axe_swiftui_preview_report_assets/*.png`\nThe project build is reused automatically after the first capture.\n\n| Flag | Description |\n|---|---|\n| `-o`, `--output` | Output path. Required. For `--format png`: directory or file. For `--format md`/`html`: directory only |\n| `--format` | Output format: `png` (default), `md`, or `html` |\n| `--wait` | Rendering delay before capture (default `10s`) |\n\nProject flags (`--project`, `--scheme`, etc.) are shared with the parent `preview` command.\n\n#### Simulator Management\n\naxe manages its own isolated simulator device set, separate from your normal simulators. When `--device` specifies a UDID from the standard Xcode simulator set, axe uses it directly and does **not** shut it down on exit.\n\n```bash\n# List managed simulators\naxe preview simulator list\n\n# List available device types and runtimes\naxe preview simulator list --available\n\n# Add a simulator\naxe preview simulator add \\\n  --device-type com.apple.CoreSimulator.SimDeviceType.iPhone-16-Pro \\\n  --runtime com.apple.CoreSimulator.SimRuntime.iOS-18-2\n\n# Set the default simulator\naxe preview simulator default \u003cudid\u003e\n\n# Remove a simulator\naxe preview simulator remove \u003cudid\u003e\n```\n\n### `axe view`\n\nInspect the UIKit view hierarchy of a running app on a simulator.\n\n```bash\naxe view [0xADDRESS] [flags]\n```\n\n**Tree mode** (default):\n\n```bash\n# Full view hierarchy\naxe view\n\n# Frontmost view controller only\naxe view --frontmost\n\n# Limit depth\naxe view --depth 3\n```\n\n**Detail mode** (with address):\n\n```bash\n# Detailed info + PNG snapshot for a specific view\naxe view 0x10150e5a0\n\n# Include SwiftUI tree\naxe view 0x10150e5a0 --swiftui compact\n```\n\n**Interactive mode**:\n\n```bash\naxe view -i\n```\n\n| Flag | Description |\n|---|---|\n| `--depth` | Maximum tree depth to display |\n| `--frontmost` | Show only the frontmost view controller's subtree |\n| `--swiftui` | SwiftUI tree mode: `none`, `compact`, `full` (detail mode only) |\n| `-i`, `--interactive` | Interactive TUI navigation |\n| `--simulator` | Target simulator by UDID or name |\n\n### Global Flags\n\n| Flag | Description |\n|---|---|\n| `--app` | Target app process name (overrides `.axerc`) |\n| `-v`, `--verbose` | Verbose output |\n\n## VS Code Extension\n\nA VS Code / Cursor extension that runs `axe preview` automatically when you open a Swift file containing `#Preview`.\n\nDownload the `.vsix` from the [Releases](https://github.com/k-kohey/axe/releases) page:\n\n- **VS Code**: `code --install-extension axe-swiftui-preview-\u003cversion\u003e.vsix`\n- **Cursor**: `Cmd+Shift+P` \u003e \"Install from VSIX...\"\n\nSee [vscode-extension/README.md](vscode-extension/README.md) for configuration and development details.\n\n## Configuration (`.axerc`)\n\nPlace a `.axerc` file in your project root. Flags specified on the command line take precedence.\n\n```\nPROJECT=MyApp.xcodeproj\nSCHEME=MyApp\nCONFIGURATION=Debug\nDEVICE=\u003csimulator-udid\u003e\n```\n\n## Known Issues\n\n### Hot Reload (`preview watch`)\n\n- **Stored properties cannot be hot-reloaded**: `let`, `@State`, `@Published` etc. change memory layout and automatically trigger a full rebuild. Computed properties and methods are hot-reloaded.\n- **Generic/static/class methods and initializers are not hot-reloaded**.\n- **Without the Index Store, only direct (1-level) dependencies are watched**: Transitive dependency detection relies on the Index Store that `xcodebuild` generates. If the Index Store is unavailable (e.g. before the first build or after deleting DerivedData), axe falls back to 1-level resolution — changes to indirect dependencies will not trigger hot-reload until the next build regenerates the Index Store.\n\n### Source Parsing\n\n- **Indirect protocol conformance is not detected**: `struct Foo: MyProtocol` where `MyProtocol: View` is not recognized. Direct `: View` and `extension`-based conformance are supported.\n\n### Preview Macro\n\n- **`#Preview(traits:)` display traits are ignored**: The preview block itself works, but trait parameters such as `.landscapeLeft` have no effect.\n\n### Platform\n\n- **Apple Silicon only**: The preview compiler targets `arm64` exclusively.\n\n## Contributing\n\nContributions are welcome! Bug reports, feature requests, and pull requests are all appreciated.\n\n```bash\nmise install   # Set up dependencies\nmise run test  # Run tests\nmise run check # Lint\n```\n\nRunning `mise install` sets up the full development environment.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk-kohey%2Faxe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fk-kohey%2Faxe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk-kohey%2Faxe/lists"}