curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add aarch64-apple-ios aarch64-apple-ios-sim # iOS
rustup target add aarch64-linux-android # Androidgit submodule update --init --recursive- Xcode 26+ (App Store) —
sudo xcodebuild -license accept - xcodegen:
brew install xcodegen - libimobiledevice:
brew install libimobiledev 6A0D ice(for device logs) - CocoaPods:
sudo gem install cocoapods
- Android Studio / SDK (API 31+)
- Android NDK r25c+
- Set env vars:
export ANDROID_NDK_ROOT=$HOME/Library/Android/sdk/ndk/<version> export ANDROID_HOME=$HOME/Library/Android/sdk
cargo install cargo-ndk
./scripts/run-ios.sh device # full build + install + launch
./scripts/run-ios.sh sim # simulator
./scripts/run-ios.sh device --release # release build
./scripts/ios-log.sh tail # stream device logs
./scripts/ios-log.sh tail --filter zedra # filtered logsSee docs/IOS_WORKFLOW.md for full pipeline details.
./scripts/build-android.sh # build Rust .so
cd android && ./gradlew installDebug && cd .. # install APK
./scripts/log-android.sh start # background log monitor
./scripts/log-android.sh tail # view logsAndroid release builds read signing credentials from Gradle properties. Gradle
loads ~/.gradle/gradle.properties automatically, so a global config can use:
ZEDRA_KEYSTORE=/absolute/path/to/zedra-release.jks
ZEDRA_KEYSTORE_ALIAS=zedra
ZEDRA_KEYSTORE_PASSWORD=...
# Optional when the key password differs from the keystore password:
ZEDRA_KEY_PASSWORD=...cargo run -p zedra-host -- start # start, show QR
cargo run -p zedra-host -- start --workdir ~/project # specific directory
cargo run -p zedra-host -- start --detach # keep running after SSH logout
cargo run -p zedra-host -- start --static-qr # static startup QR for review/testing
cargo run -p zedra-host -- qr --workdir . # refresh one-time QR
cargo run -p zedra-host -- qr --workdir . --static # static QR for testing/store review
cargo run -p zedra-host -- logs --workdir . # show recent daemon logs
cargo run -p zedra-host -- client # measure RTT
cargo run -p zedra-host -- stop # stop daemonScan the printed QR from the app, or pass the URL during development:
./scripts/run-ios.sh sim --no-build --launch-url 'zedra://connect?ticket=...'Windows support is for the host daemon, not a native desktop client.
irm https://zedra.dev/install.ps1 | iex
zedra start --workdir C:\path\to\project --detach
zedra qr --workdir C:\path\to\project
zedra status --workdir C:\path\to\project
zedra logs --workdir C:\path\to\project
zedra client --workdir C:\path\to\project --count 3
zedra stop --workdir C:\path\to\projectRuntime files are stored under %APPDATA%\zedra\workspaces\. daemon.lock uses the lock hash for the workdir; daemon.log, sessions.json, host-info.json, and API discovery files use the stable workspace hash. Terminal sessions use ZEDRA_SHELL when set, otherwise Zedra detects the shell that launched the host, then falls back to SHELL, then %ComSpec% (cmd.exe). Supported launch shells are cmd.exe, pwsh.exe, powershell.exe, and Git Bash/POSIX-style shells.
To build from source instead, install the MSVC Rust toolchain and Git for Windows, then run cargo build -p zedra-host.
cargo fmt
cargo check -p zedra-rpc -p zedra-session -p zedra-terminal -p zedra-host- Black screen (Android): surface dimensions must be physical pixels. Check Vulkan 1.1+:
adb shell getprop ro.hardware.vulkan - Submodule missing:
git submodule update --init --recursive - iOS provisioning: check
DEVELOPMENT_TEAMinios/project.yml - Metal shader fail:
xcodebuild -downloadComponent MetalToolchain