You don't need any extra tooling beyond Xcode and Homebrew to bring Skip into your SwiftUI project — Skip has been completely free and open source since January 21, 2026, and setup starts with a single brew install skip command. In this guide you'll see whether Skip transpiles or compiles natively, the practical difference between Lite and Fuse mode, and, step by step, how to actually get your first SwiftUI screen running on Android.
💡 Pro Tip: Before you start the install, run skip checkup — it validates your Xcode and Android SDK versions in one pass and builds a sample hello-skip project, so if a dependency is missing you find out up front instead of losing hours.Table of Contents
- Skip's Architecture: Transpile or Runtime?
- Lite vs. Fuse: Which Mode Should You Choose
- Setup: Xcode, Android SDK, and skip checkup
- Running Your First Screen on Both Platforms
- The Parts of SwiftUI That Don't Convert to Compose
- Writing Platform-Specific Code
- What "Compose First" Means in Practice
- Real Project Limits
- When You Should Choose KMP Instead
- FAQ
- How does SwiftUI code run on Android with Skip?
- What's the difference between Skip Lite and Skip Fuse?
- Is Skip free?
- Is the Android app Skip produces native?
- Can I start with Fuse and move a module to Lite later (or the reverse)?
- Conclusion
- Sources
Skip's Architecture: Transpile or Runtime?
Skip isn't a single engine — it's a toolset offering two different ways of working. Which mode you pick determines whether your code compiles on Android as real Swift or gets converted to Kotlin, and that distinction shapes your project's architecture from the start.
Fuse mode builds on the Swift SDK for Android, which became official with Swift 6.3, as a layer underneath: your Swift code is actually compiled natively on Android, runs with full Swift language support and deterministic memory management, and can access Apple's Foundation library. Here Skip isn't a competing runtime — it's a project toolchain built on top of the official SDK.
Lite mode follows a different strategy: it transpiles your Swift source code into Kotlin at build time. The result is a genuine Kotlin project, so you can interop directly with existing Kotlin/Java libraries — but not every Swift language feature is supported by the transpiler (you'll see those limits in the next section).
The mode is chosen at the Swift module level; skip create only picks the project's default mode. Within the same Skip project, it's possible to compile some modules with Fuse and others with Lite.
This dual-mode approach is the core feature that sets Skip apart from other single-engine cross-platform solutions. If a team wants deep access to the Kotlin ecosystem in a business-logic-heavy module, they can keep that module on Lite while compiling a performance-critical module, or one heavily dependent on Apple frameworks, with Fuse. That flexibility comes at a cost: two different build paths mean two different debugging experiences and two different toolchains — the next section compares the two modes with more concrete criteria.
Lite vs. Fuse: Which Mode Should You Choose
The choice between the two comes down directly to how much your project will depend on the Kotlin/Java ecosystem. The table below compares both modes against practical criteria:
Criterion | Skip Lite | Skip Fuse |
|---|---|---|
How it works | Swift → Kotlin transpile | Native Swift compilation (Swift SDK for Android) |
Kotlin/Java interop | Direct, maximum | Via SkipBridge's automatic bridge and #if SKIP blocks |
Language coverage | Subset supported by the transpiler | Full Swift language |
Memory management | JVM garbage collector | Swift's deterministic ARC |
Apple Foundation access | Common API subset rewritten in Kotlin by SkipFoundation | Full |
Why you'd choose it | Deep integration into an existing Kotlin codebase | Keeping a single Swift codebase native on both platforms |
In short: if you want to add a Swift module to an existing Android/Kotlin project, Lite is the fit; if you're starting from scratch and want to keep Swift as your one language, Fuse causes fewer surprises.
Factor your team's existing skill set in too. Lite gives full stack traces through the generated Kotlin, so you can use Android Studio's Kotlin/Java debugging tools directly — an advantage for a Kotlin-comfortable team, but a learning curve for pure SwiftUI teams. In Fuse mode, debugging native code on Android is harder than debugging generated Kotlin, as the official docs note in their trade-offs list; also, using a Kotlin/Java library from Fuse means going through SkipBridge's extra abstraction layer.
Setup: Xcode, Android SDK, and skip checkup
Per Skip's official setup docs, the tools you need are: Xcode, Android Studio, and Homebrew. The install sequence is:
1# 1) Install Skip via Homebrew (along with Android SDK and gradle dependencies)2brew install skip3 4# 2) Validate your environment — checks Xcode, Android SDK versions5# and builds a sample hello-skip project6skip checkup7 8# 3) Create a new project — choose App or Library, Fuse or Lite9skip createRunning skip create opens an interactive wizard that asks you the project type (App/Library) and mode (Fuse/Lite). The sample output in the setup docs may show a specific Skip version number — that's just an example of how the command behaves; check skip checkup's own output on your machine for the version you actually get. Skip ships patches frequently (several releases a week were seen in September 2026); at the time this article was written (September 24, 2026), the latest tag on GitHub was 1.9.11.
Running Your First Screen on Both Platforms
An App project created with skip create is set up to produce both an iOS and an Android target from a single SwiftUI source file. On the Xcode side you get a normal SwiftUI preview; on the Android side, the project opens as a Gradle module in Android Studio and runs on an emulator or a physical device.
1// ContentView.swift — one source, two platforms2import SwiftUI3 4struct ContentView: View {5 @State private var count = 06 7 var body: some View {8 VStack(spacing: 16) {9 Text("Hello from Skip")10 .font(.title)11 Text("Count: \(count)")12 Button("Increment") {13 count += 114 }15 }16 .padding()17 }18}In both modes, the Android-side interface is a genuine Jetpack Compose tree — not a parallel widget set; real Compose components run directly. The difference isn't in the UI layer, it's in how the business logic gets compiled: in Fuse mode this code compiles as native Swift on Android, and SkipFuseUI acts as a thin bridge layer handing rendering off to SkipUI, which then implements SwiftUI views as Jetpack Compose composables. In Lite mode, the transpiler converts Swift into idiomatic Kotlin. This distinction underlies the "Compose First" decision covered in the next section.
In practice: in Xcode you compile normally with Cmd+R and preview in the iOS simulator — you won't even notice Skip stepping in, since either mode's iOS side runs directly on Apple's own SwiftUI. For Android, open the Gradle module skip create generated in Android Studio, then a normal Gradle sync and "Run" launches it on an emulator or device. The first build (especially in Fuse mode, when the Swift SDK for Android toolchain downloads for the first time) is noticeably slower than later, incremental builds. As the official docs note, compiling native Swift through the Android toolchain is slower than transpiling; moving a module from Lite to Fuse (or back) changes its build-time profile — so settling the mode decision early, ideally in week one, saves real time.
The Parts of SwiftUI That Don't Convert to Compose
Skip Lite's Swift → Kotlin transpiler supports a broad subset of SwiftUI and the Swift language, but it isn't unlimited. Per the official docs, as of September 24, 2026, the areas that are unsupported or only partially supported are:
- In-function type declarations: defining a
structorclassinside a function's body can't be transpiled. - Tuples of arity 6 and above: tuples with six or more elements aren't supported by the transpiler.
- Certain generic + protocol constructor combinations: certain patterns where a generic type combines with protocol-based initializers have limited support.
If you hit one of these limits you have two options: rewrite the code in a simpler pattern, or move that module to Fuse mode (since Fuse compiles native Swift, it isn't subject to the transpiler's limits).
For example, instead of expecting a function returning an arity-6+ tuple to transpile under Lite, defining a small struct that carries the same data is both more readable and transpiler-compatible:
1// Pattern that won't transpile: a tuple with 6+ elements2// func userSummary() -> (String, Int, Bool, String, Int, Bool) { ... }3 4// Instead: a struct with named fields5struct UserSummary {6 let name: String7 let age: Int8 let active: Bool9 let city: String10 let score: Int11 let verified: Bool12}13 14func userSummary() -> UserSummary {15 UserSummary(name: "Ada", age: 29, active: true, city: "Izmir", score: 87, verified: true)16}This swap isn't just about transpiler compatibility — it's generally preferable API design too. Using named fields instead of a tuple leaves less ambiguity for another developer reading the code.
Writing Platform-Specific Code
Sometimes you need different behavior on each platform — requesting an Android permission, say, or calling a Kotlin library directly. Skip offers two different compilation directives for this, and their meanings are clearly distinct:
1// #if os(Android): a platform check.2// In Fuse mode this block stays native Swift,3// in Lite mode it gets transpiled — but it runs in both modes.4#if os(Android)5print("Running on Android")6#endif7 8// #if SKIP: always transpiled to Kotlin.9// Use this when you need to call Kotlin/Java APIs directly.10#if SKIP11// Only Kotlin/Java-specific calls go here12#endifThe practical difference: #if os(Android) is a platform question — "is this code running on Android?" #if SKIP is a compilation-target question — "does this code get converted to Kotlin?" Code that needs to reach a Kotlin/Java API should always live in an #if SKIP block, because that block is always transpiled to Kotlin regardless of mode; in Fuse mode, an #if os(Android) block stays native Swift, and you can't call Kotlin/Java APIs from there.
What "Compose First" Means in Practice
At Google I/O 2026, the Android team announced a significant direction change: all new UI development would now happen with Jetpack Compose, while the classic View toolkit moved into "maintenance mode." That decision directly validated Skip's architecture, since Skip has followed a Compose-first approach since its inception: in Lite mode the transpiler converts SwiftUI into idiomatic Compose, and in Fuse mode native Swift bridges directly to Compose — in both cases, the Android UI is a real Compose tree, not a parallel widget hierarchy. A similar principle holds on the iOS side — Skip's own runtime doesn't imitate SwiftUI, it uses Apple's own SwiftUI framework directly. So when Apple introduces a new visual language (e.g., the Liquid Glass look that came with iOS 26), Skip apps inherit it automatically — you don't have to wait for a separate widget update.
The practical result of this decision is a lower risk of seeing unexpected component-level behavior differences on the Android side. Before Skip, most "single codebase" tools hide both platforms' UI systems behind their own abstraction layer, which means when a platform update ships, you have to wait for that abstraction layer to be updated. Skip's Compose-first and SwiftUI-first stance keeps that waiting period out of the picture: since the Android-side output is a standard Compose tree in both modes, you can use Jetpack Compose's own updates (a new component, a new modifier) directly, like an ordinary Android developer — you don't need Skip to separately "support" them.
Real Project Limits
When evaluating Skip, don't lump it into the same category as other cross-platform tools. Flutter, Compose Multiplatform's iOS target, and React Native use "pixel-painted widgets" (imitating the platform's look with their own rendering engine) or an older bridge architecture; when the platform's design language changes, catching up is a separate engineering effort for these tools. Skip, running real Compose on Android and real SwiftUI on iOS, largely eliminates that synchronization cost. That comes at a price: transpiler limits (see above), roughly 60 MB of extra Android package size from Fuse bundling the Swift standard library, Foundation, and internationalization libraries, and dependence on a Swift SDK for Android that's still maturing. See the real production state of the Swift Android SDK, and where it still falls short, in Swift on Android: Does the 6.3 SDK Actually Work?.
A concrete example: the GitHub issue asking for Cupertino widget support for the "Liquid Glass" design language that came with iOS 26 (flutter/flutter #170310) opened in June 2025 and, as of September 24, 2026, is still open — because Flutter's own rendering engine needs separate work to "imitate" Apple's new look. In Skip's Fuse mode this doesn't come up: since SwiftUI is directly Apple's framework, the new design language arrives automatically. What you pay in return is depending on a toolchain — the Swift SDK for Android — that only became official with Swift 6.3, so it isn't as mature as Flutter's years of Android support.
When You Should Choose KMP Instead
Skip isn't a fit for every project. If you want to manage the UI layer from a single source too, and develop both iOS and Android at once with a team that already knows SwiftUI, Skip is a reasonable choice. But in the following scenarios, Kotlin Multiplatform (KMP) offers a lower-friction path:
- Your team already has a strong Android/Kotlin core and you only want to share business logic (networking, database, use cases) — you want the UIs to stay platform-native.
- You already have an Android app and are newly entering iOS; KMP's "shared core only" model requires less of a rewrite.
- Your team has limited SwiftUI experience but deep Kotlin experience.
Before deciding, it's useful to line up the two tools' sharing scope side by side:
Question | Skip | KMP |
|---|---|---|
What's shared | UI + business logic (single SwiftUI source) | Usually just the business-logic core |
UI language | SwiftUI (on both platforms) | Platform-native (SwiftUI + Jetpack Compose separately) |
Team prerequisite | Strong SwiftUI experience needed | Strong Kotlin experience needed |
Best-fit scenario | Launching two platforms together from scratch | Adding a shared core to existing native apps |
For an in-depth analysis comparing Skip and KMP on the shared-core decision, see Swift Android SDK or KMP? The Shared-Core Decision; for Kotlin's own attempt to bridge to the Swift side, see Kotlin 2.4 Swift Export: Is the Obj-C Bridge in KMP Ending?. For a quick side-by-side comparison of the two tools, the Skip vs. Kotlin Multiplatform (2026) page offers a faster summary.
GOLDEN TIP
The most valuable insight in this article
This tip holds the article's most important takeaway.
Easter Egg
You found a hidden gem!
There's a hidden detail in this section. Want to uncover it?
Reader Reward
If you've followed this guide from start to finish, you're now ready to set up your first project with Skip. The checklist below is here so you can see, at a glance, any steps you may have skipped from setup to your first build — settling on your mode choice before the project grows in particular cuts down significantly on the cost of switching later.
FAQ
How does SwiftUI code run on Android with Skip?
One of two ways: in Fuse mode, your Swift code is compiled natively via the Swift SDK for Android and runs as real Swift on Android; SkipFuseUI acts as a thin bridge layer handing rendering off to SkipUI, which implements SwiftUI views as Jetpack Compose composables. In Lite mode, the Swift source code gets transpiled to Kotlin at build time. In both modes, the interface running on Android is a genuine Jetpack Compose tree — not a parallel widget set. Either way, the single source you write is SwiftUI code; what determines which engine is in play is the mode you choose when creating the project or module.
What's the difference between Skip Lite and Skip Fuse?
Lite converts Swift to Kotlin, giving maximum interop with existing Kotlin/Java libraries, but is limited on certain Swift patterns the transpiler doesn't support or only partially supports (in-function type declarations, arity-6+ tuples, certain generic+protocol constructor combinations). Fuse compiles natively using the Swift SDK for Android, supports the full Swift language, and provides deterministic memory management, but needs SkipBridge's automatic bridge and #if SKIP blocks (or AnyDynamicObject) to reach the Kotlin/Java side.
Is Skip free?
Yes. With version 1.7, released on January 21, 2026, Skip removed the license-key requirement; the toolset, including the "skipstone" engine, became completely free and open source, with development funded through sponsorships.
Is the Android app Skip produces native?
In Fuse mode, yes — your Swift code compiles natively with the Swift SDK for Android. In Lite mode, since the app becomes a genuine Kotlin/Compose project, it runs as a native Kotlin app on Android's own runtime; the difference is the source language — both produce a real Android app running on the platform's own runtime (JVM/ART). This is what sets Skip apart from WebView-based tools or ones using their own separate rendering engine: the output draws its interface with the platform's own Compose tree.
Can I start with Fuse and move a module to Lite later (or the reverse)?
Since the mode choice is made per module, yes — but don't think of it as a free operation. Moving a module from one mode to the other means that module's build-time profile changes (as the official docs note, compiling native Swift through the Android toolchain is slower than compiling via transpilation), and you'll need to re-check how the Kotlin/Java or Apple framework APIs the module uses are handled on the other side. That's why settling the mode decision early, based on the criteria in the "Lite vs. Fuse" section, is the most practical way to avoid the cost of moving a module later.
Conclusion
The big obstacle keeping you from trying Skip has probably already disappeared: setup is a single brew install skip command, and the license cost is zero. The real decision point is choosing a mode — Lite if you want deep integration with the Kotlin/Java ecosystem, Fuse if you want to keep Swift as your one language. You can follow Skip's real maturity on the Swift SDK for Android in Swift on Android: Does the 6.3 SDK Actually Work?, and the shared-core decision in Swift Android SDK or KMP?. For production experience on the Kotlin side, check out Kotlin Multiplatform 1.1 Stable: Production Case Study 2026 and Compose Multiplatform: Android + iOS Production Deployment 2026; for an iOS developer's perspective moving to Android, see An iOS Developer's Move to Android: The Roadmap.
Sources
- Skip Releases (GitHub Atom feed) — release history and dates, confirming 1.9.11 shipped on September 19, 2026.
- Skip: Getting Started — official setup steps (Homebrew, skip checkup, skip create).
- Skip: Modes (Lite and Fuse) — the two modes' architectural differences, Fuse's ~60 MB package-size and build-time cost.
- Skip: Swift Language Support — Swift patterns the Lite transpiler doesn't support.
- Skip: Platform Customization — usage of the #if os(Android) and #if SKIP directives.
- Skip: Bridging Reference — converting fully-qualified Kotlin/Java types to AnyDynamicObject.
- Skip: SkipFuseUI — SkipFuseUI's role as a thin bridge layer handing rendering off to SkipUI.
- Skip is Free (skip.dev blog) — removal of the license key and the open-source announcement.
- Skip: Compose First (skip.dev blog) — the Google I/O 2026 Compose-first decision and Skip's alignment with it.
- Swift 6.3 Released (swift.org) — the official first release of the Swift SDK for Android.
- Skip: Swift 6.3 Android Support (skip.dev blog) — Skip's relationship to the official Android SDK.
- Support for iOS 26 "Liquid Glass" Design in Cupertino Widgets (GitHub Issue #170310) — a concrete example of the cost of keeping up with platform design-language changes in Flutter.
Tags
iOS Development News
Weekly Swift tips, SwiftUI tricks and iOS best practices. No spam, only valuable content.
Your subscription starts when you open the link in the confirmation email and press “Confirm my subscription”. The newsletter keeps open/click statistics; you can unsubscribe anytime with one click. Privacy
