The project's README from github.com/Innei/lody-ios. As one markdown file: README.md.
https://github.com/user-attachments/assets/0bc0ab48-6f12-44e9-ae13-07af9c6b780d
[!IMPORTANT] This is a third-party project. Lody iOS is an independent, community-maintained client. It is not affiliated with, endorsed by, or supported by the official Lody team. Report issues in this repository, not upstream.
The project is still under development. It iterates quickly, so APIs, sync behavior, and UI may change without notice, and builds can be unstable or break existing sessions. Evaluate the risk yourself before relying on it.
[!IMPORTANT] 本项目为第三方项目。 Lody iOS 由社区独立维护,与 Lody 官方团队无关,也不代表官方立场;本项目的问题请在本仓库反馈,不要提交给上游。
项目仍在开发中。 迭代速度较快,接口、同步行为与界面可能随时调整,版本可能不稳定甚至破坏已有会话数据,请在评估风险后使用。
Install the current build on your iPhone through TestFlight:
https://testflight.apple.com/join/1rR6Ku8f
Requires iOS 26 or later. Beta builds track main and update automatically; they are pre-release and may be unstable, as described above.
Lody iOS is an independent open-source client crafted for iPhone, providing a lightweight and secure bridge between remote Lody services and local workspaces.
The project uses a hybrid architecture of React Native + a deeply customized Swift native module (LodyKit). While preserving the rapid iteration advantages of declarative cross-platform UI, critical interactions (infinite chat collection, streaming text rendering, code diff highlighting, file tree, etc.) are built with native Swift and CoreText to deliver an authentic iOS system feel.
Lody iOS started as a one-day prototype and became a usable TestFlight client in about a week, driven by coding agents under tight product constraints: iOS only, one native kit module, system UI when React Native cannot meet HIG, and an offscreen WebView for Flock/Loro because official Node/CRDT packages do not bundle in Metro.
The full first-person write-up is Prototype in a Day, Shipped in a Week: Building Lody iOS in Live.
What that week actually looked like:
main.UIBarButtonItem, system sheets, and semantic colors were required; RN fakes of system chrome were rejected on screenshots.present() runtime, and system grouped rows use UIKit UICollectionViewListCell via LodyGroupedList.apps/mobile/locales, is checked in CI, and is projected into native xcstrings catalogs by the local withLocales config plugin.UICollectionView, maintaining full 60/120 fps smoothness even with extensive message histories.CTRunDraw character alpha transitions delivers gentle, flicker-free streaming output during AI generation.ChatComposerView): Pixel-perfect keyboard avoidance matching system input methods, local draft persistence with automatic restoration, and real-time model thinking effort controls.LodyCodeView or system Quick Look.Agent Conversation Sync in Settings lists supported local projects and agents on your own computers. Refresh their history, select conversations to import, and explicitly confirm any conflict replacement. Imports run in batches and retain partial progress; this is a manual history import, not automatic device-to-device mirroring.
AVSampleBufferDisplayLayer, touches go back over the same WebSocket, and the device frame and its side buttons are drawn natively. Hardware actions (Home, lock, rotate, shake, volume, screenshot) sit in the navigation bar.WKWebView, completely avoiding Node/CRDT/Zstd dependency bundling issues in React Native.flowchart TB
subgraph UI ["React Native Presentation Layer (Expo Router)"]
direction TB
Nav["Native Stack · Typed Routes"]
Presentation["definePage / present() Presentation Runtime"]
Screens["Session Details / File Tree / Diff Viewer / Settings"]
end
subgraph NativeKit ["Local Native Module (modules/lody-kit)"]
direction TB
LodyKitModule["LodyKit NativeModule Facade"]
ChatView["LodyChatView (UICollectionView)"]
Markdown["MarkdownView & Litext (CoreText Glyph Fade-In)"]
DiffView["Shared DOM Diff + Native Inline Diff"]
Composer["ChatComposerView (Native Input & Keyboard Avoidance)"]
end
subgraph DataEngine ["Offscreen Data Engine (Swift Watchdog)"]
direction TB
OffscreenWV["Offscreen WKWebView"]
Flock["Flock WASM / Loro Streams Incremental Core"]
Watchdog["Swift Native Watchdog (2s Probing / Hot Restart)"]
SQLite["Local SQLite View Projection Snapshot"]
end
subgraph External ["System & Cloud Communication"]
Keychain["iOS Keychain Credential Storage"]
CloudStreams["Remote Lody Cloud Streams / Machine RPC"]
end
UI -->|"Invocations & Event Subscriptions"| NativeKit
NativeKit -->|"State Changes & Dispatches"| DataEngine
DataEngine -->|"Read-Only Incremental Projections"| UI
DataEngine -->|"Encrypted Envelope Requests"| CloudStreams
DataEngine -->|"Snapshot Persistence"| SQLite
NativeKit -->|"Credential Operations"| Keychain
lody-ios/
├── apps/
│ └── mobile/
│ ├── src/
│ │ ├── app/ # Expo Router routes (typed routes) and the Stack declaration
│ │ ├── screens/ # *Screen pages defined with definePage
│ │ ├── features/ # Domain logic (sessions, diff, licenses)
│ │ ├── cloud/ # Cloud protocol (auth, catalog, send, kv, settings)
│ │ ├── models/ # Shared data shapes
│ │ ├── ui/ # Shared React Native base components
│ │ ├── hooks/ # Screen bindings (session nav, page runtime, process sheet)
│ │ └── lib/ # Infrastructure (presentation, i18n, theme)
│ ├── modules/
│ │ └── lody-kit/ # First-party local native Swift module (LodyKit)
│ │ ├── ios/ # Swift / UIKit / CoreText native code
│ │ ├── data-runtime/ # Offscreen data runtime RPC and adapter scripts
│ │ ├── decoder/ # Flock decoder bundled into the offscreen WebView
│ │ ├── src/ # Typed native component interfaces for React Native
│ │ └── verification/ # Deterministic Swift behavior checks
│ ├── verification/ # Offline UI/native baselines and Simulator tooling
│ ├── tests/ # Node test-runner suites
│ ├── locales/ # en / zh-Hans catalogs (projected into xcstrings)
│ ├── plugins/ # Local Expo config plugins (MarkdownView, locales)
│ ├── scripts/ # native:assets, license generation, locale checks
│ └── package.json
├── packages/
│ └── dom-webview/ # Vendored Expo DOM WebView (MIT) hosting the shared diff view
├── docs/ # Architecture design, specs, and evolution docs
├── package.json # Monorepo root configuration
└── pnpm-workspace.yaml
>= 22.13 (React Native 0.86 also accepts ^20.19.4, ^24.3, and >= 25)11.10.0 (corepack enable)apps/mobile/Gemfile pins cocoapods ~> 1.16 and cocoapods-spmClone the repository and install JavaScript dependencies:
git clone https://github.com/Innei/lody-ios.git
cd lody-ios
pnpm install
Install the CocoaPods toolchain (into apps/mobile/vendor/bundle):
cd apps/mobile
bundle install
cd ../..
Generate the native project and launch simulator:
pnpm ios
[!TIP] This project uses
cocoapods-spmto integrate SPM static library dependencies.pnpm iosrunsnative:assets, generates the native project, and executesbundle exec pod installto fetch dependencies and link symbols. After building native code once, runpnpm startdirectly when modifying only JavaScript to connect to the hot reload server.
Update native assets:
If you modify runtime assets in modules/lody-kit/data-runtime/ or modules/lody-kit/decoder/, run:
pnpm --filter @lody-ios/mobile native:assets
pnpm check # TypeScript, locale catalogs, generated license notices, Prettier
pnpm test # Node test suites, Simulator tooling tests, vendored DOM WebView tests
pnpm bundle # Verify iOS Hermes JavaScript production bundle integrity
pnpm licenses:build # Regenerate the in-app notices after dependency changes
UI baselines run without login, user credentials, cloud access, or a connected machine: EXPO_PUBLIC_UI_VERIFY=1 injects deterministic data at the Auth/Catalog boundary, and every case starts from the development-only Debug page.
pnpm verify:simulator --name '<current verify>' -- <command> # Lease a Lody * Verify Simulator
pnpm verify:native # Swift behavior checks
pnpm verify:ui --app /absolute/path/to/Lody.app # Offline UI baselines
pnpm verify:ui --suite core --embedded --app /absolute/path/to/Lody.app # PR core paths, Release app
The runner captures screenshots for visual states and video for temporal behavior; missing scenes and timeouts fail the run. See apps/mobile/verification/ui/README.md for the case inventory and Simulator leasing rules.
Pushing to main runs .github/workflows/ship.yml. A push always archives a TestFlight build through .github/workflows/release.yml; a manual dispatch publishes an OTA update to the configured expo-updates server when the Expo fingerprint matches the published baseline, and falls back to TestFlight when it changes. Native runtime assets are regenerated before either route. Join the beta at https://testflight.apple.com/join/1rR6Ku8f.
Lody iOS is released under the GNU Affero General Public License v3.0 (AGPL-3.0-only). You may use, modify, and distribute it, including commercially, provided that derivative works and network-served modifications stay under the same license and their source stays available to users.
Bundled third-party libraries and assets keep their own licenses. The full list and license texts are available in the app under Settings → Open Source Licenses. The notices are generated from the production dependency closure by pnpm licenses:build and verified in CI by pnpm check.
Lody iOS is made possible thanks to these open-source projects and creators:
packages/dom-webview (MIT) and extended to host the shared diff view.AVSampleBufferDisplayLayer, raw UIKit touch forwarding, never dropping input behind video) shaped the design of Lody's simulator viewer.