Skip to content

Platform Workshop

Uniite CLI

The original Swift CLI that unified mobile CI/CD — linting, building, deploying, and secrets — across 20+ projects. Now succeeded by Franky.

SwiftSwift Argument ParserFastlaneSwiftLintDetektSonarQubeHashiCorp Vault

Problem

Mobile teams had fragmented commands and repeated per-project setup for iOS, Android, and Flutter tooling.

Solution

Built a Swift CLI wrapping the common workflows — SwiftLint, Detekt, Flutter analyze, Fastlane builds, SonarQube scans, store/Firebase deploys, and Vault secret injection — behind one command.

Role

Designed and built the shared mobile workflow CLI in Swift.

Impact

  • Ran across 20+ iOS, Android, and Flutter projects in CI
  • One command for lint, build, scan, deploy, and secrets
  • Same workflow locally and in CI
  • Later reimagined in Go as Franky CLI

Visual metaphor

Terminal machine and linter robot cleaning code on a conveyor belt.

Highlights

Cross-platform lint/build/scan
Vault secret injection
Predecessor to Franky

Context

Across Android, iOS, and Flutter, the same engineering chores show up again and again: wiring a linter, running SwiftLint or Detekt, invoking the Flutter Analyzer, kicking off a Sonar scan. Every team solved these slightly differently, which meant fragmented commands, copy-pasted setup, and CI configs that drifted apart over time. The cost wasn’t any single command — it was the absence of a shared, predictable way to run them.

Uniite’s premise: collapse those scattered workflows behind one command-line entry point so quality tooling becomes a default, not a per-project project.

Approach

The CLI is built in Swift on top of Swift Argument Parser, which keeps the command surface structured and self-documenting. Two principles guided the design:

  • Wrap, don’t reinvent. Uniite orchestrates the tools teams already trust (SwiftLint, Detekt, Flutter Analyzer, SonarQube) behind a consistent interface rather than replacing them.
  • CI-first ergonomics. Every command is designed to run identically on a developer’s machine and inside Bitrise, so "works locally" and "works in CI" stop being two different things.

How it works

Engineers invoke a single tool that exposes consistent subcommands for linting, building, scanning, deploying, and pulling secrets across platforms. Under the hood each subcommand shells out to the right tool (SwiftLint, Detekt, Fastlane, SonarQube, Vault) with sane defaults, so a new repository can adopt the full workflow without re-deriving configuration.

The mental model — a terminal machine and a linter robot cleaning code on a conveyor belt — reflects the goal: quality checks that run automatically and uniformly instead of being remembered and re-wired by hand.

Outcome

Uniite ran across 20+ iOS, Android, and Flutter projects in CI: easier integration, less repetitive setup, and one workflow that behaved the same on a laptop and on a runner.

It also taught me where a Swift CLI hits its limits — a ~40–60 MB binary, macOS gravity, and a build path that got brittle over time. Those lessons became the design brief for its Go successor, Franky.

What I’d build next

The honest answer: I rebuilt it. Franky CLI carries Uniite's ideas into a smaller, cross-platform Go binary with a declarative config, native environment setup, and a shape that's easier to maintain — including with AI.