Home avatar

ISLAND

SugarLite's Incremental KMP Migration (Part 3): Direct Observation with KMP-ObservableViewModel — iOS ViewModels Retire

At the end of Part 2, our answer was “KMP ViewModel + SKIE + a 50-line StateHolder per ViewModel.” We claimed the cost was low — usually under 50 lines of bridging per ViewModel.

We later took that statement back.

The per-VM cost was indeed low, but it was a quantity tax — 23 ViewModels meant 23 StateHolders, each a copy-paste of @Published property mapping, a for await subscription loop, and a manual deinit cancellation. Worse, the KMP ViewModel lifecycle on iOS was left dangling: androidx.lifecycle.ViewModel has no ViewModelStore on iOS, so viewModelScope was never cancelled by the system — only our hand-written deinit cancel() calls kept things tidy. Miss one, and you leak a coroutine.

opencodex: Run Codex and Claude Code on Any LLM

opencodex is a local proxy that translates Codex’s Responses API into whatever protocol your LLM provider speaks. You can use Claude, Gemini, DeepSeek, Grok, GLM, Qwen, or even a local Ollama model inside Codex CLI, Codex App, and SDK — and in Claude Code too — without waiting for anyone to add official support.

Streaming, tool calls, reasoning tokens, image generation — everything works, in both directions.

npm install -g @bitkyc08/opencodex
ocx init
ocx start

Three commands, and Codex is rerouted. It forwards your ChatGPT login by default; you can add more models anytime.

SugarLite's Incremental KMP Migration (Part 2): ViewModels, Local Storage & Platform Abstractions

Part 1 documented how SugarLite sunk its data layer from the Supabase Swift SDK down into the KMP shared/ module. But we left one thing deliberately untouched — ViewModels stayed on iOS using @Observable. We said we’d “keep them put” for now.

Well, we broke that promise.

As Android development accelerated, 21 of our 23 ViewModels needed to work on both platforms. Maintaining one set of Swift ViewModels for iOS and another set of Kotlin ViewModels for Android was clearly unsustainable — why write the same business logic (fetch today’s blood sugar, build a timeline, calculate glycemic response) twice?

SugarLite's Incremental KMP Migration (Part 1): Sinking the Data Layer & Adapting CI/CD

SugarLite started as a pure iOS app built with SwiftUI + MVVM + Supabase Swift SDK. When the Android version became a priority, copying the business logic over to Kotlin would have doubled the maintenance burden — network layer, data models, and business rules all needed dual-platform upkeep. That’s why we chose Kotlin Multiplatform: the shared/ module carries all cross-platform business logic, while the iOS side only keeps SwiftUI and system framework calls (HealthKit, SwiftData, WidgetKit).

Configuring Claude Desktop in CC Switch

I’ve previously covered the basics of CC Switch. Today, let’s take a closer look at the Claude Desktop panel — added in recent versions specifically for connecting the official Claude Desktop client to third-party providers.

In CC Switch, “Claude” and “Claude Desktop” are two separate panels. They map to Claude Code (the CLI) and Claude Desktop (the desktop client), respectively. Claude Desktop uses its own 3P profile config rather than ~/.claude/settings.json. The two panels are distinguished by a small badge on the icon.

Quickly Switch Claude Code Providers with cc switch and cc desktop switch

In the world of AI programming tools, Claude Code is undoubtedly one of the most powerful choices today. However, with major cloud service providers launching their own LLM APIs, how to conveniently switch between different providers has become a practical need. Today, I’ll introduce two tools: cc switch and cc desktop switch, which help you quickly switch Claude Code model providers.

Project Links:

cc switch is a cross-platform desktop application specifically designed for managing provider configurations for five major AI programming CLI tools: Claude Code, Codex, Gemini CLI, OpenCode, and OpenClaw.