skiptools/skip
Skip enables the creation of native SwiftUI apps for iOS and Android
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 1d ago
- ✓3 active contributors
- ✓MPL-2.0 licensed
Show 4 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Small team — 3 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 96% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/skiptools/skip)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/skiptools/skip on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: skiptools/skip
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/skiptools/skip shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 1d ago
- 3 active contributors
- MPL-2.0 licensed
- CI configured
- Tests present
- ⚠ Small team — 3 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 96% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live skiptools/skip
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/skiptools/skip.
What it runs against: a local clone of skiptools/skip — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in skiptools/skip | Confirms the artifact applies here, not a fork |
| 2 | License is still MPL-2.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of skiptools/skip. If you don't
# have one yet, run these first:
#
# git clone https://github.com/skiptools/skip.git
# cd skip
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of skiptools/skip and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "skiptools/skip(\\.git)?\\b" \\
&& ok "origin remote is skiptools/skip" \\
|| miss "origin remote is not skiptools/skip (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MPL-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MPL-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is MPL-2.0" \\
|| miss "license drift — was MPL-2.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "Sources/skip/SkipToolMain.swift" \\
&& ok "Sources/skip/SkipToolMain.swift" \\
|| miss "missing critical file: Sources/skip/SkipToolMain.swift"
test -f "Sources/SkipDrive/GradleDriver.swift" \\
&& ok "Sources/SkipDrive/GradleDriver.swift" \\
|| miss "missing critical file: Sources/SkipDrive/GradleDriver.swift"
test -f "Plugins/SkipPlugin/SkipPlugin.swift" \\
&& ok "Plugins/SkipPlugin/SkipPlugin.swift" \\
|| miss "missing critical file: Plugins/SkipPlugin/SkipPlugin.swift"
test -f "Sources/SkipDrive/GradleHarness.swift" \\
&& ok "Sources/SkipDrive/GradleHarness.swift" \\
|| miss "missing critical file: Sources/SkipDrive/GradleHarness.swift"
test -f "Package.swift" \\
&& ok "Package.swift" \\
|| miss "missing critical file: Package.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/skiptools/skip"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Skip is a Swift-to-multiplatform compiler that transforms a single Swift/SwiftUI codebase into native iOS apps (SwiftUI) and native Android apps (Jetpack Compose). It operates in two modes: Skip Fuse compiles Swift natively for Android using the official Swift SDK, while Skip Lite transpiles Swift source to Kotlin for maximum Android ecosystem interoperability. The core innovation is eliminating the need to rewrite UI or business logic for Android—developers write once in Swift and get genuinely native experiences on both platforms without WebViews or custom runtimes. Monorepo structure: Sources/ contains core modules (skip CLI entry point in Sources/skip/SkipToolMain.swift, build driving logic in Sources/SkipDrive/, test harness in Sources/SkipTest/). Plugins/ directory holds Swift Package Manager build plugins (SkipPlugin and SkipLink) that integrate compilation into Xcode workflows. GradleDriver.swift orchestrates Android build invocation; SourceMap.swift manages source-to-generated mappings for debugging. Tests/ mirrors source structure with corresponding test suites.
👥Who it's for
Swift/SwiftUI developers and teams who want to build cross-platform mobile apps without learning Kotlin, Java, or using hybrid frameworks like React Native or Flutter. Also targets iOS development shops expanding to Android who want to leverage existing Swift expertise and code sharing to reduce time-to-market and maintenance burden.
🌱Maturity & risk
Actively developed and production-capable. The repo shows continuous CI/CD pipeline (ci.yml, release.yml, skipcheck.yml), organized plugin architecture (SkipLink, SkipPlugin), and comprehensive test coverage (SkipDriveTests, SkipTestTests). The 301K+ lines of Swift code and structured package layout indicate a mature, well-maintained project. Verdict: Actively developed, production-ready for early adopters with strong momentum.
Primary risk: relatively young ecosystem compared to established cross-platform tools—depends heavily on the Swift SDK for Android maturity (released 2024) and Jetpack Compose stability. Secondary risk: the transpiler/compiler approach (Skip Lite) may have edge cases with advanced Swift features not mapping cleanly to Kotlin. Maintenance concentration in skiptools organization—single-point-of-failure if core team shrinks. No visible open issue backlog in file list, but dependency on evolving Swift/Android toolchains means breaking changes possible with major platform updates.
Active areas of work
Active development across CI/CD infrastructure (multiple GitHub workflows for testing, building, and releases). The presence of skipcheck.yml suggests continuous validation of Skip compiler correctness. No specific recent commit info in data provided, but organized versioning system (Sources/SkipDrive/Version.swift) and release workflow indicate regular versioned releases.
🚀Get running
- Clone:
git clone https://github.com/skiptools/skip.git && cd skip - Build:
swift build(Swift Package Manager is the primary tool, visible in Package.swift) - Verify:
swift testto run the test suite in Tests/SkipDriveTests/ and Tests/SkipTestTests/ - Install CLI:
swift build -c releasethen link the binary to your PATH, or useswift run skip --helpdirectly
Daily commands:
Development: swift build builds the Skip compiler and CLI tools. Testing: swift test runs the full test suite. Running the CLI: swift run skip --help or after swift build -c release, invoke the binary directly. The Gradle integration is invoked by Skip for Android compilation—you don't run Gradle manually; Skip orchestrates it via GradleDriver.
🗺️Map of the codebase
Sources/skip/SkipToolMain.swift— Primary entry point for the Skip CLI tool that orchestrates compilation and cross-platform code generation.Sources/SkipDrive/GradleDriver.swift— Core driver that manages Gradle-based Android compilation pipeline, essential for understanding Swift-to-Kotlin transpilation flow.Plugins/SkipPlugin/SkipPlugin.swift— Swift Package Manager plugin that integrates Skip compilation into the build system for iOS and Android targets.Sources/SkipDrive/GradleHarness.swift— Manages Gradle build execution and orchestration; critical for understanding how Android builds are triggered and monitored.Package.swift— Defines the entire Skip package structure, dependencies, and plugin registration; must-read to understand project organization.Sources/SkipDrive/SourceMap.swift— Handles source map generation for debugging cross-platform code; crucial for error reporting and developer experience..github/workflows/ci.yml— CI/CD pipeline showing how Skip verifies iOS and Android builds; reveals testing strategy and platform-specific requirements.
🧩Components & responsibilities
- SkipPlugin (SPM Plugin) (Swift, SPM Plugin API) — Orchestrates the build-time transpilation pipeline; hooks into Swift Package Manager build phases to generate Kotlin and Compose code
- Failure mode: If plugin crashes, entire build fails; must validate Swift syntax early and report errors clearly
- GradleDriver (Gradle, Kotlin) — Invokes Gradle, manages Android build configuration, and coordinates Kotlin compilation; central to Android build reliability
- Failure mode: Gradle invocation failures cascade to failed Android builds; version mismatches cause cryptic compilation errors
- GradleHarness (Gradle, JUnit, XCTest) — Manages test execution on Android; bridges XCTest expectations to Gradle test runners
- Failure mode: Test harness misconfiguration leads to false negatives or flaky cross-platform tests
- SourceMap (Source map format, debug symbols) — Tracks mapping between original Swift source lines and transpiled Kotlin; critical for debugging
- Failure mode: Incorrect mappings make Android stack traces unreadable and hinder debugging efforts
- CLI (SkipToolMain) (Swift CLI) — User-facing command dispatcher; parses arguments, coordinates plugins, and reports errors to developers
- Failure mode: Poor error messages or incorrect command routing confuses users and masks underlying build issues
🔀Data flow
Developer's Swift source→SkipPlugin— Swift files in Xcode project are read and parsed by SkipPlugin during buildSkipPlugin (parsed AST)→Kotlin code generators— Abstract syntax tree is
🛠️How to make changes
Add a new Swift-to-Kotlin compiler pass
- Create a new compiler phase handler in the main SkipPlugin (
Plugins/SkipPlugin/SkipPlugin.swift) - Integrate the pass into the GradleDriver to apply transformations during Android build (
Sources/SkipDrive/GradleDriver.swift) - Add test coverage in the appropriate test suite (
Tests/SkipDriveTests/SkipDriveTests.swift)
Add support for a new Swift API or SwiftUI component
- Define the transpilation rules in the SkipPlugin code generation phase (
Plugins/SkipPlugin/SkipPlugin.swift) - Map the Swift API to equivalent Jetpack Compose in the Gradle build output (
Sources/SkipDrive/GradleDriver.swift) - Verify the mapping works end-to-end via GradleHarness integration tests (
Tests/SkipTestTests/GradleDriverTests.swift)
Integrate a new iOS or Android toolchain version
- Update version checks and compatibility logic (
Sources/SkipDrive/Version.swift) - Adjust Gradle configuration and Android build parameters if needed (
Sources/SkipDrive/GradleDriver.swift) - Update CI workflow to test against the new toolchain version (
.github/workflows/ci.yml) - Add integration tests to validate toolchain compatibility (
Tests/SkipTestTests/GradleDriverTests.swift)
🔧Why these technologies
- Swift & SwiftUI — Single-language codebase that compiles natively for iOS; leverages existing Swift ecosystem and type safety
- Jetpack Compose — Android's modern declarative UI framework; allows Skip to generate idiomatic Android UIs from SwiftUI descriptions
- Gradle — Standard Android build system; provides reliable dependency management and build automation for Android platform
- Swift Package Manager — Native Swift dependency manager; integrated via plugins for seamless build-time code generation and transpilation
- Kotlin — Target language for Android; offers interoperability with Java ecosystem and null safety guarantees
⚖️Trade-offs already made
-
Transpilation vs. runtime compatibility layer
- Why: Transpiling Swift to Kotlin produces native platform code rather than relying on a shared runtime
- Consequence: Better performance and platform integration on Android, but requires maintaining two code generators and more complex debugging workflows
-
SwiftUI as the single UI abstraction
- Why: Skip uses SwiftUI syntax as the unified cross-platform UI model instead of a custom DSL
- Consequence: Developers use familiar Apple frameworks, but Android Compose APIs must be carefully mapped to SwiftUI semantics
-
Gradle as the Android build driver
- Why: Gradle is the standard Android build system, ensuring compatibility with the broader ecosystem
- Consequence: Dependency on third-party tool stability and version compatibility; requires careful version management
🚫Non-goals (don't propose these)
- Supporting non-SwiftUI iOS UI frameworks (UIKit, AppKit, etc.)
- Cross-platform code execution on a shared runtime (e.g., WebAssembly or JVM)
- Supporting Windows or macOS as deployment targets
- Providing a visual designer or low-code development experience
- Runtime reflection or dynamic code generation at app execution time
🪤Traps & gotchas
- Android toolchain requirement: Skip Fuse mode requires Swift SDK for Android (released mid-2024) installed and configured in PATH; Skip will fail silently if the Android Swift toolchain is missing. 2. Gradle wrapper versioning: The GradleHarness may expect specific Gradle versions; mismatches between local Gradle and Skip's expected version can cause cryptic build failures. 3. Source map coherence: If transpilation changes without updating SourceMap.swift logic, debugging symbols will point to wrong lines—test against actual Android builds after changing transpiler code. 4. SPM module naming: Plugin modules must be properly registered in Package.swift or Xcode won't invoke them; forgetting to register a new plugin leaves it unused. 5. Cross-platform path handling: SourceMap and GradleDriver deal with both forward-slash (Unix) and backslash (Windows) paths; path logic bugs only surface on one platform.
🏗️Architecture
💡Concepts to learn
- Source-to-source transpilation (Swift → Kotlin) — Skip Lite's core mechanism—it doesn't compile to bytecode or JVM, but generates readable Kotlin source. Understanding transpilation (vs. compilation) explains why some Swift idioms don't map 1:1 and why debugging intermediate Kotlin is often necessary.
- Swift SDK for Android (native compilation mode) — Skip Fuse uses Apple's official Swift compiler targeting Android; this is fundamentally different from transpilation. It's native Swift runtime on Android, which means understanding Swift runtime behavior on non-iOS is critical for Fuse developers.
- Jetpack Compose UI framework mapping — Skip's core UI capability is mapping SwiftUI components to Jetpack Compose equivalents. Understanding the impedance mismatch (e.g., SwiftUI's declarative state vs. Compose's recomposition model) explains limitations and performance characteristics.
- Build plugin architecture (SPM plugins) — Skip integrates via Swift Package Manager build plugins (SkipPlugin, SkipLink) rather than Xcode build phases. Understanding SPM plugin contracts is essential for extending Skip's Xcode integration.
- Source mapping and debug symbol generation — SourceMap.swift maintains mappings from generated Kotlin back to original Swift source, enabling IDE-level debugging. Understanding how transpilers maintain line/column fidelity is crucial for contributing debugger or error reporting improvements.
- Gradle build orchestration and harness abstraction — GradleDriver and GradleHarness abstract Gradle invocation, allowing Skip to control Android builds without users touching gradle files directly. Understanding how Skip wraps build tools explains CI integration and cross-platform build caching.
- Semantic versioning and compatibility matrix — Skip must track compatibility across three independent ecosystems: Swift language/SDK, Kotlin/Gradle, and Jetpack Compose versions. Version.swift and release.yml hint at complex dependency tracking.
🔗Related repos
skiptools/skip-ui— Companion repo providing SkipUI framework—the SwiftUI-to-Jetpack Compose mapping layer that Skip depends on to translate UI code across platformsapple/swift— Upstream Swift language repo; Skip Fuse mode relies on the Swift SDK for Android distributed in official Swift releases, making this the foundation for native compilation moderealm/realm-swift— Example of a mature cross-platform Swift library; developers using Skip often need persistence, and Realm shows how to structure libraries that work in both Skip Fuse and Lite contextsReactiveX/RxSwift— Reactive programming library compatible with Skip; many Skip apps use RxSwift or Combine for state management, making this a natural companion ecosystem to understandjetbrains/kotlin— Upstream Kotlin compiler and stdlib; Skip Lite mode transpiles to Kotlin, so understanding Kotlin semantics is critical for diagnosing transpilation edge cases
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for SourceMap.swift
SourceMap.swift is a critical component for mapping compiled code back to source locations, but there are no visible tests for it in Tests/SkipDriveTests/. This is essential for debugging and error reporting in the Skip compiler toolchain. A new contributor could add tests covering source map generation, line/column mapping accuracy, and edge cases.
- [ ] Create Tests/SkipDriveTests/SourceMapTests.swift
- [ ] Add tests for SourceMap initialization and parsing
- [ ] Add tests for location mapping (source -> compiled code)
- [ ] Add tests for edge cases (empty maps, invalid ranges, out-of-bounds queries)
- [ ] Add integration test verifying SourceMap works correctly with GradleDriver.swift
Add GitHub Actions workflow for Swift package validation and linting
The repo has ci.yml, release.yml, and skipcheck.yml workflows, but there's no dedicated workflow for Swift package validation (SwiftLint, SwiftFormat consistency, package integrity checks). This would catch code style issues and package configuration problems early. A new contributor could create a reusable workflow that runs on PRs.
- [ ] Create .github/workflows/swift-lint.yml or extend existing workflow
- [ ] Add SwiftLint checks for Sources/skip and Sources/SkipDrive directories
- [ ] Add swift package validate step to verify Package.swift correctness
- [ ] Add check for duplicate imports and unused dependencies
- [ ] Configure to run on all PRs and commits to main
Add unit tests for Version.swift and ToolSupport.swift
Version.swift and ToolSupport.swift in Sources/SkipDrive are core utilities for version management and tool integration, yet there are no dedicated test files for them. These modules are critical for gradle driver compatibility and toolchain setup. A contributor could add tests for version parsing, comparison, and tool detection logic.
- [ ] Create Tests/SkipDriveTests/VersionTests.swift for semantic versioning logic
- [ ] Add tests for version parsing, comparison operators (>=, <=, ==), and range validation
- [ ] Create Tests/SkipDriveTests/ToolSupportTests.swift
- [ ] Add tests for tool detection, path resolution, and environment variable handling
- [ ] Add integration tests verifying tools are correctly validated before gradle execution
🌿Good first issues
- Add integration test for SourceMap correctness across Swift-to-Kotlin transpilation: Tests/SkipDriveTests/ has basic driver tests but no dedicated test verifying that source map line/column mappings survive transpilation. Write a test that transpiles a multi-line Swift file and validates that generated Kotlin map back correctly.
- Document GradleDriver.swift environment variable requirements: GradleDriver.swift likely requires ANDROID_HOME and/or JAVA_HOME but these are not mentioned in README or inline comments. Add a troubleshooting section to README.md and docstring to ToolSupport.swift listing required env vars.
- Add Version.swift validation to CI pipeline: Sources/SkipDrive/Version.swift likely tracks Skip version, but there's no visible CI check that verifies version consistency between Package.swift and release tags. Add a workflow step to .github/workflows/ci.yml that validates version coherence.
⭐Top contributors
Click to expand
Top contributors
- @marcprux — 96 commits
- @dfabulich — 3 commits
- @tifroz — 1 commits
📝Recent commits
Click to expand
Recent commits
6473282— Release 1.8.14 (marcprux)8b28d4b— Update test case patterns (marcprux)1fd2e5c— Release 1.8.13 (marcprux)8b6dd3a— Release 1.8.12 (marcprux)c70164f— Release 1.8.11 (marcprux)88a5408— Add support for test filters (#669) (dfabulich)56010fb— Release 1.8.10 (marcprux)f15d7c3— Release 1.8.9 (marcprux)bd9ed9c— Release 1.8.8 (marcprux)e517ab7— Release 1.8.7 (marcprux)
🔒Security observations
The Skip codebase shows reasonable security posture for an open-source compiler/build tool project. No critical vulnerabilities were identified in the visible file structure. Key security considerations: (1) Complete Package.swift dependency analysis is needed to assess third-party risks, (2) Gradle and build tool integration requires careful input validation to prevent command injection, (3) GitHub Actions workflows should be audited for secret management, (4) Source map handling needs verification to prevent information disclosure. The project would benefit from: dependency version pinning, SBOM generation, regular security audits of build plugins, and clear security policy documentation.
- Medium · Missing Package.swift Dependency Analysis —
Package.swift. The Package.swift file content was not provided for analysis. This file typically contains all Swift package dependencies and their versions. Without reviewing this file, potential security issues related to outdated or vulnerable dependencies cannot be identified. Fix: Provide Package.swift content for complete dependency vulnerability scanning. Ensure all dependencies are pinned to specific versions and regularly updated using tools like 'swift package update --major' with careful testing. - Low · GitHub Workflows Visibility —
.github/workflows/. CI/CD workflow files (.github/workflows/*.yml) are present and likely contain build/test steps. While these are typically public in open-source repos, they should be reviewed for accidental secret exposure in logs or environment variables. Fix: Audit workflow files to ensure: (1) No secrets are logged in console output, (2) Use GitHub Secrets for sensitive values, (3) Implement branch protection rules, (4) Review third-party action versions to avoid supply chain attacks. - Low · Gradle Build System Security —
Sources/SkipDrive/GradleDriver.swift, Sources/SkipDrive/GradleHarness.swift. The codebase includes Gradle driver components (GradleDriver.swift, GradleHarness.swift) which execute build commands. If these execute user input or remote commands without proper validation, there could be injection risks. Fix: Ensure all Gradle command construction uses parameterized/array-based execution rather than string concatenation. Validate and sanitize any user-supplied build parameters. Use allowlists for permitted Gradle tasks. - Low · Source Map Information Exposure —
Sources/SkipDrive/SourceMap.swift. The presence of SourceMap.swift suggests the tool generates source maps for debugging. Source maps can expose source code structure and intellectual property if served publicly or included in production builds. Fix: Ensure source maps are only generated for development builds and excluded from production releases. Implement access controls if source maps are served from any backend.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.