Skip to content
xcross
Documentation menu

CLI reference

Every xcross command and flag for Flutter and Compose Multiplatform, taken from the CLI source.

xcross <command> [subcommand] [options]. Add --help at any level. -v / --verbose works everywhere.

ImportantComing from 1.x? In 2.0 xcross doctor became flutter doctor / compose doctor, xcross clean became flutter clean / compose clean / sdk clean, and auth clear became auth clean.

At a glance

Machinesetup · sdk install · sdk clean · auth · config · update
Devicetunnel · tunnel --wifi
Flutterflutter run · flutter build · flutter doctor · flutter clean · ide
Composecompose setup · compose build · compose run · compose doctor · compose clean
CommandDoes
setupInstall or verify host tools
sdk install <Xcode.xip>Extract the Darwin SDK
sdk cleanRemove the installed Darwin SDK
auth / auth cleanSave or remove Apple credentials
config / show / validateEdit, print, check configuration
tunnel [--wifi]Mount DDI + start the iOS 17+ RSD tunnel
flutter run / buildRun or build a Flutter app
flutter doctor / compose doctorRead-only readiness check for that framework
flutter clean / compose cleanClear this project’s xcross caches
compose setup / build / runSet up, build or run a Compose app
ide vscode / ideaWire up IDE debugging (Flutter)
updateVerified self-update
completionPrint a bash/zsh completion script

setup

xcross setup

Idempotent. On Linux it installs LLVM, device utilities and pymobiledevice3 through apt, dnf or pacman (Homebrew on macOS), and needs Swift on PATH first. On Windows it runs a setup script for winget, Scoop or Chocolatey (or direct.ps1, which downloads signed vendor installers), asking before each package: VS Build Tools, Swift, LLVM, Python.

Before any script runs, xcross prints its name, source URL and SHA-256 and waits for y.

Flag
--manager <name>Windows: pick winget, scoop, choco or direct (asks when several are installed)
-y, --yesAccept the script and every installer prompt
--refresh-scriptRe-download a configured setup script without running it
What setup does on Linux
  • Detects apt-get, dnf or pacman, prompting if several exist.
  • Installs clang, lld, llvm, Python, usbmuxd, usbip and Swift’s build dependencies.
  • Probes ld64.lld for the broken selector-stub bug and symlinks a newer ld64.lld-<N> into /usr/local/bin if needed.
  • Installs pymobiledevice3 through pipx.
What setup does on Windows
wingetscoopchocodirect
VS Build ToolsMicrosoft.VisualStudio.2022.BuildToolsvendor installervisualstudio2022buildtoolsvendor installer
SwiftSwift.Toolchainmain/swiftvendor installervendor installer
LLVMLLVM.LLVMmain/llvmllvmGitHub release
PythonPython.Python.3.13main/pythonpython313python.org

Vendor installers only run with a valid Microsoft or Apple Authenticode signature. Downloads are checked against the published SHA-256. Pin versions for direct with XCROSS_SWIFT_VERSION, XCROSS_LLVM_VERSION, XCROSS_PYTHON_VERSION. When another LLVM is already on PATH, the pinned LLVM goes into XCROSS_LLVM_DIR. Chocolatey needs an Administrator PowerShell, Scoop a normal one.

sdk install

xcross sdk install <path-to-Xcode.xip>   # or an Xcode.app on macOS
xcross sdk clean                         # remove it, plus leftover backup/staging copies

No flags. Replaces any previous SDK. See Darwin SDK.

auth

xcross auth --apple-id you@example.com
xcross auth --issuer-id <uuid> --key-id <id> --private-key AuthKey.p8
xcross auth clean
Flag
--apple-id, --passwordApple ID login (prompted if omitted)
--issuer-id, --key-id, --private-keyApp Store Connect API key
--adi-library-dirADI libraries for hosts other than x64 / ARM64

auth clean deletes the saved key, the Apple ID session and every certificate, key and profile xcross minted. The old auth clear spelling fails with a pointer to the new one.

doctor

xcross flutter doctor   # in a Flutter project
xcross compose doctor   # in a Gradle project

Read-only. Each checks only what its own framework needs: the project, its toolchain, the Darwin SDK, then the shared deployment checks (device tools, auth, connected iOS versions). Output is grouped into project, toolchain and deployment sections, each headed by its worst status. Missing project or device context is a warning. A failed requirement exits non-zero.

compose doctor lists every Compose requirement on its own row (Kotlin/Native, JDK 21+, Gradle, swiftc, clang, ld64.lld). A missing Kotlin/Native download is only a warning, since the first build fetches it.

tunnel

xcross tunnel          # USB
xcross tunnel --wifi   # pair / reconnect wirelessly

Needs sudo or Administrator. Run once per device reconnect. See Run over Wi-Fi.

Device selection

Shared by flutter run and compose run.

Flag
-d, --device-idDevice id or name
-u, --udidExact UDID, wins over -d
--usb / --wifiSearch one transport only
--device-connectionattached · wireless · both (default)

flutter

xcross flutter run
xcross flutter run -u <UDID> -D API_URL=https://staging.example.com
xcross flutter build -i --flavor staging -t lib/main_staging.dart
Flagrunbuild
-t, --target✓✓Entry point (default lib/main.dart)
--flavor✓✓App flavor
-D, --dart-define✓✓KEY=VALUE, repeatable
--dart-define-from-file✓✓.json / .env, repeatable
--[no-]pub✓✓flutter pub get first (on)
--route✓Initial route
-a, --dart-entrypoint-args✓Args for main()
--build-name, --build-number✓Version strings
-i, --ipa✓Output .ipa instead of .app
--target-platform✓iphone (default) or simulator (arm64 Simulator app, verified on macOS ARM64, no --ipa)
--[no-]tree-shake-icons✓Tree shake icon fonts (on)

Always debug (JIT). Shaders are compiled with the host impellerc, like flutter build. flutter dap is internal, spawned by your IDE.

App ID on first device run

The first device build of an app asks which App ID to register, and saves the answer so it can be committed:

Choice
App ID
Good for
Prefixed (default)
XCR-<TEAM>.com.example.app
never collides with another team
Original
com.example.app
Sign in with Apple, push, passkeys, associated domains
# pubspec.yaml (Compose: xcross_project.yaml)
xcross:
  bundle_id: original # or prefixed

Precedence: XCROSS_BUNDLE_ID=original|prefixed for one run, then the saved bundle_id, then an App ID the team already has, then the question. CI and IDE sessions can’t be asked: they use the saved value, else fall back to prefixed.

compose

xcross compose setup
xcross compose build --ipa
xcross compose run --watch
CommandFlags
compose setup--check (verify only), --force (refresh Kotlin/Native cache)
compose build--configuration debug|release, --bundle-id, --app-name, --ipa, --target-platform iphone|simulator (simulator needs a macOS host)
compose rundevice flags, --bundle-id, -a app args, --watch
compose doctorread-only readiness check
compose cleanclear this project’s xcross build output and Kotlin/Native caches

See Compose Multiplatform.

ide

xcross ide vscode
xcross ide idea

No flags. See IDE integration.

config

xcross config            # TUI editor
xcross config show
xcross config validate

update

xcross update
Flag
--checkReport the target version only
--ref <ref>Install a tag, branch or commit
--forceReinstall even if current
-y, --yesSkip the confirmation

clean

xcross flutter clean   # this project's native asset + SwiftPM caches (device and simulator)
xcross compose clean   # this project's xcross build output + Kotlin/Native caches
xcross sdk clean       # the installed Darwin SDK

Shared caches and unrelated build output are left alone.

completion

xcross completion >> ~/.zshrc

Environment

Variable
XCROSS_OFFLINE=1Skip Apple and sign from the cache. See offline
XCROSS_BUNDLE_IDoriginal or prefixed for this run
XCROSS_APP_GROUPApp Group to use with an API key
XCROSS_CONFIGPath to a config file
XCROSS_NO_UPDATE_CHECK=1Silence the new-release hint
ESC