All Articles
Reading Time
15 min read
Published
2026-10-31
Word Count
3,627words

Grab a coffee — this one is a deep dive!

Skip: From SwiftUI to Android — A Practical Setup Guide

Summary

A Skip SwiftUI Android setup guide: validate your environment with skip checkup, decide between Lite and Fuse mode, and actually get your first SwiftUI screen running on Android.

  • Skip has been completely free and open source since January 21, 2026; setup starts with a single brew install skip command.
  • Fuse mode compiles native Swift via the Swift SDK for Android, Lite mode transpiles Swift to Kotlin — the Android UI is a real Jetpack Compose tree in both modes.
  • The Lite transpiler doesn't support in-function type declarations or arity-6+ tuples, and has limited support for some generic+protocol constructor combinations.
  • Mode is chosen at the Swift module level; since native compilation is slower than transpiling, settle the decision at the start of the project.
Skip: From SwiftUI to Android — A Practical Setup Guide

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?

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:

bash
1# 1) Install Skip via Homebrew (along with Android SDK and gradle dependencies)
2brew install skip
3 
4# 2) Validate your environment — checks Xcode, Android SDK versions
5# and builds a sample hello-skip project
6skip checkup
7 
8# 3) Create a new project — choose App or Library, Fuse or Lite
9skip create

Running 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.

swift
1// ContentView.swift — one source, two platforms
2import SwiftUI
3 
4struct ContentView: View {
5 @State private var count = 0
6 
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 += 1
14 }
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 struct or class inside 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:

swift
1// Pattern that won't transpile: a tuple with 6+ elements
2// func userSummary() -> (String, Int, Bool, String, Int, Bool) { ... }
3 
4// Instead: a struct with named fields
5struct UserSummary {
6 let name: String
7 let age: Int
8 let active: Bool
9 let city: String
10 let score: Int
11 let verified: Bool
12}
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:

swift
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#endif
7 
8// #if SKIP: always transpiled to Kotlin.
9// Use this when you need to call Kotlin/Java APIs directly.
10#if SKIP
11// Only Kotlin/Java-specific calls go here
12#endif

The 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

Tags

#Skip#SwiftUI#Android#Cross-Platform#Kotlin Multiplatform#Swift#Jetpack Compose
Muhittin Camdali

Muhittin Çamdalı

Senior Mobile Engineer

Senior Mobile Engineer with 12+ years of experience. I build mobile products with iOS, Flutter and React Native, working full-stack and AI-native.

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

Share