A localhost, self-hosted take on Rork: a browser tab with a live iOS simulator, a Rork-style Publish flow, and App Store screenshot tooling. Open it in Cursor, Claude Code, or any browser-capable agent and iterate on your app end to end.
- Simulator streaming is powered by
serve-simby Evan Bacon (60 FPS stream, full touch/keyboard input, logs). - Publishing and screenshots are powered by the
ascCLI by Rudrank Riyam (asc publish,asc screenshots,asc web apps create).
The device switcher and simulator tools panels come from serve-sim.
- macOS (Apple Silicon) with Xcode command line tools (
xcrun simctl) - Node.js 20+
ascinstalled on yourPATH, or setASC_BIN=/path/to/ascasc auth logincompleted (publishing calls the App Store Connect API)- For screenshot framing:
pipx install "koubou==0.18.1"(used byasc screenshots frame) - For creating brand-new apps:
asc web auth login(app creation uses Apple's web API)
From your app's directory:
npx rork-local
# → http://localhost:3131Or from a checkout of this repo:
bun install
bun run build
bun start # scans the current directory
node dist/cli.js /path/to/app # or point it at an app codebaseOn startup the server:
- Boots an iPhone simulator if none is booted (and opens Simulator.app).
- Auto-detects publish settings from your app codebase (see below).
- Starts the
serve-simstreaming helper in the background. - Serves the UI on
http://localhost:3131with the simulator mounted at/.sim.
Screenshots and editor state live next to your app in
<project>/.rork-local/; rork.config.json overrides are read from the
directory you launch rork-local in (usually your app's directory).
The Publish button opens a popover with an App Store section ("Submit this app's signed build to TestFlight and the App Store"). Submit to App Store opens a bottom-sheet wizard with three steps, modeled on Rork's publish dialog:
- App Info — a Project field (edit it to re-point detection at another
directory; the change is persisted to
rork.config.json), plus App ID, version, IPA path, TestFlight/App Store destination, and beta groups. Everything auto-fills Xcode-style from the detected project. No app on App Store Connect yet? When the App ID field is empty, a Create new app link expands inline fields (App Name, Bundle ID, SKU) and runsasc web apps create— the new app ID drops straight into the form. - App Store Connect — checks both credentials: API key (publishing) via
asc auth status, and Web session (app creation) viaasc web auth status. - Submit — runs
asc publish testflight|appstoreand streams live progress ("Uploading to TestFlight", "Processing", …) plus the raw CLI log. You can close the sheet; the publish continues in the background.
The camera button in the top bar snaps the booted simulator (with a shutter flash). The screenshots panel lets you:
- Capture raw screenshots (
xcrun simctl io booted screenshot) - Frame them into Apple device bezels (
asc screenshots frame, Koubou-powered; devices: iphone-air, iphone-17-pro, iphone-17-pro-max, iphone-17, iphone-16e), producing App-Store-ready sizes (e.g. 1206×2622 →IPHONE_61) - Edit captures in the built-in slide editor: canvas presets for the App Store sizes (iPhone 6.9″/6.5″/6.1″, iPad 12.9″), solid or gradient backgrounds, a headline with color/size/position controls, and the capture composed in a clean device bezel you can drag and resize — with a deck strip to reorder, duplicate, and delete slides. Exports are pixel-exact PNGs validated against the chosen device type.
- Accept & Upload framed, raw, or editor-made slides to your App Store
listing via
asc screenshots upload --app … --version … --device-type …
Files live in .rork-local/screenshots/raw/, …/framed/, and …/listing/
inside your project.
The server continuously scans the project directory and pre-fills the forms:
- Bundle ID + version from
app.json(Expo) or an Xcodeproject.pbxproj - IPA path: the newest
.ipafound in the project tree - App Store Connect app ID: resolved from the bundle ID via
asc apps list --bundle-id …(requiresasc auth login) - Beta groups: fetched via
asc testflight groups list --app …
The project directory resolves in this order: CLI argument → RORK_PROJECT
env → projectDir in rork.config.json → current working directory (an
explicit per-invocation choice beats a persisted one). Change it live from
the wizard's Project field.
Pre-fill the forms by editing rork.config.json (values here always win over
detection):
{
"projectDir": "/path/to/my-app",
"appId": "6759231657",
"ipa": "/path/to/MyApp.ipa",
"group": "External Testers",
"version": "1.0.0"
}ASC_APP_ID in the environment also pre-fills the app ID.
An Agent Skill
ships in skills/rork-local — it teaches AI coding agents
(Claude Code, Cursor, Codex CLI, and any host implementing the open Agent Skills
standard) how to start rork-local from an app project and drive the whole flow
over HTTP: status/detection, TestFlight and App Store publishing with SSE logs,
screenshot capture/frame/upload, and first-publish app creation.
Install it in Claude Code via the plugin marketplace:
/plugin marketplace add rorkai/rork-local
/plugin install rork-localor in any Agent Skills-compatible tool:
bunx add-skill rorkai/rork-local
# or
npx skills add rorkai/rork-localAgent-facing repo docs live in AGENTS.md (with CLAUDE.md
symlinked to it), and a project-scoped dev skill for working on rork-local
itself lives in .codex/skills/rork-local-dev.
The server is TypeScript in src/. Bun is the dev/build toolchain (like
serve-sim), but the published artifacts in dist/ target plain Node — users
running the CLI via npx don't need Bun:
src/
cli.ts entry point (the published bin points at dist/cli.js)
server.ts route wiring + HTTP API + boot
http.ts router, static files, JSON bodies (on node:http, no framework)
config.ts paths, rork.config.json, asc binary resolution, project dir
detect.ts Xcode-style project detection + caching
jobs.ts single-job asc runner + SSE fan-out
screenshots.ts simctl capture, asc frame, shot listing
sim.ts simulator boot + serve-sim helper
types.ts shared API payload types
bun install
bun run build # bun build → dist/ (node target) + tsc declarations
bun run dev # run src/cli.ts directly under Bun
bun run format # format frontend TypeScript/TSX with Prettier
bun run format:check
bun run typecheck # tsc --noEmit
bun start # node dist/cli.js (runs the built output)The browser UI is maintained as React TSX + Tailwind CSS in frontend/. bun run build:frontend bundles it into static assets under public/; those
generated assets are what the plain-Node server ships to npx rork-local
users.
Apache 2.0 — see LICENSE.

