Sarukani is a WaniKani client for iOS 26 with reverse-recall practice. I use WaniKani and wanted a modern SwiftUI client that also asks me to produce Japanese from an English meaning, rather than only recognize Japanese. I wanted to use an app like this myself, and it gave me a concrete reason to work through Swift 6 strict concurrency in a full iOS application.
I built Sarukani as a new app, not a fork of Tsurukame. I use Tsurukame as a reference for the WaniKani API and its learning rules. NOTICE identifies code actually derived from it under Apache 2.0, including the romaji conversion rules that now live in a separate KBKanaKit package.
Architecture
The app shell contains SwiftUI screens, resources, and dependency assembly. Most of the work lives in a Swift package split into WaniKani, Store, ReviewEngine, and DesignKit. WaniKani owns the API client and domain model. Store uses GRDB for schema migrations, synchronization, and observed queries. ReviewEngine contains answer checking and session state. DesignKit contains the visual tokens and shared SwiftUI components.
WaniKani, Store, and ReviewEngine cannot import a UI framework. A CI purity script checks that rule, so adding SwiftUI to a domain module fails the build instead of waiting for review. Swift 6 strict concurrency applies throughout, but only the UI targets use main-actor default isolation. Applying it to the API client or review engine would serialize domain work on the wrong actor.
Reverse recall
Reverse recall shows an English meaning and asks for Japanese, the direction associated with KaniWani. For v1, it follows its own local schedule because the WaniKani API has nowhere to record this kind of attempt. The grader has five outcomes so it does not treat a valid answer to an ambiguous English prompt as a simple failure. It can accept the expected spelling, recognize a correct reading, identify another real word with the same meaning, credit that other word when it comes due for review, or mark the answer incorrect.
Romaji-to-kana conversion runs through KBKanaKit. I kept it outside this repository because Japanese input can help other apps and does not depend on WaniKani.
Verification
The fast make verify gate takes about 9 seconds. The current package suite has 647 tests and runs in about 1.7 seconds inside that gate. The app unit bundle has 200 tests, including hosted layout tests, and the UI suite has 17 tests. Screenshot capture runs the tour in light and dark mode and takes about four minutes at minimum.
Those captures have caught real layout bugs. On September 26, the layout truncated four settings titles at the largest text size because their rows gave the labels only one line of height. The capture showed the missing text, and hosted layout tests now cover the shared label and the three standalone rows.
Current state
The app can sign in, synchronize WaniKani data, run lessons and reviews, practice reverse recall, play pronunciation audio, and show review counts in a widget. I continue developing it and working through the remaining behavior and accessibility checks before deciding how to distribute it.