Platform Workshop
Franky CLI
A single Go binary that runs the entire mobile build–test–scan–deploy pipeline for iOS, Android, and Flutter.
30-second summary
Disclosure: Anonymized case study
Problem
Mobile CI stitched together a fragile chain of tools — a Swift CLI for secrets, rbenv/FVM for versions, Fastlane for signing, SonarQube for scans — each configured per machine, per pipeline.
Ownership
Designed and built the Go tool, its declarative config, and the cross-platform command surface.
Key decision
Replaced the Swift CLI and scattered shell steps with one small Go binary reading one franky.yml per project.
Result
- One command surface covers build, test, scan, and deploy across iOS, Android, and Flutter.
- doctor --setup bootstraps a fresh machine into a build-ready environment.
Trade-off
Chose Go for a portable, self-updating binary that reaches every CI environment instead of keeping the tool macOS-focused in Swift.
What I’d change now
Add native Vault integration, richer security scanning, and per-command telemetry to expose where pipeline time is spent.
Highlights
Context
Mobile CI at Mekari was a relay race between tools. A Jenkins pipeline had to pull secrets with one CLI, pin Ruby and Flutter versions with rbenv and FVM, sign and upload with Fastlane, and scan with SonarQube — each configured per machine, per pipeline. The chain worked, but every new project re-derived it, and every broken link failed a build.
The first version of this was Uniite, a Swift CLI. Franky is the rewrite that learned from it.
Approach
Franky is a single Go binary built on Cobra, driven by one franky.yml per
project. Three ideas shaped it:
- One binary, one config. Everything a pipeline needs — build, test, lint, scan, deploy, secrets — lives behind one tool reading one declarative file, instead of a stack of shell steps.
- Go for reach and maintainability. A small static binary that runs anywhere, starts fast, self-updates — and, deliberately, is easy for an AI agent to read and extend. Swift was fine on macOS; Go goes everywhere the CI does.
- Bootstrap, don't document.
franky doctor --setupinstalls and pins the whole toolchain on a fresh machine, so onboarding a runner isn't a wiki page.
How it works
A developer or Jenkins stage calls one command:
franky build --config staging --platform flutter --vault
Franky handles the rest — pulling secrets from Vault, pinning the right tool
versions, running the platform build, and preparing artifacts. The command
surface covers build, test, lint, security, sonar-scan, deploy,
env, version, and doctor, with a franky.yml that each project owns.
Outcome
- One command surface for build, test, scan, and deploy across iOS, Android, and Flutter.
- A fresh machine goes from empty to build-ready with a single
doctor --setup. - A small, self-updating binary that replaced both the fragmented Jenkins tool-chain and the legacy Swift CLI.
What I'd build next
Native Vault integration to drop the last subprocess dependency, richer
security scanning, and per-command telemetry so I can see which parts of the
pipeline actually cost time.