A clean, native sudoku for the foldable iPhone Duo, for iPhone and for iPad.
No ads, no accounts, no tracking.
Sudeux is built first for the iPhone Duo, the foldable iPhone, and for playing a puzzle next to something else: a video in picture in picture, or another app in split view. It has to work well at any window size, in every pose of the Duo (closed, open and half-open), in light and dark mode, with touch, Apple Pencil or a keyboard.
And it stays out of the way: no ads, paywalls, accounts or analytics. The only connection it makes is to your own iCloud, to sync your puzzles and finished lessons between your devices, and to continue a puzzle on another one with Handoff. Everything is native SwiftUI, following the platform’s own controls and conventions rather than a custom look.
The same puzzle on the iPhone Duo open (top) and half-open (bottom), where the board and the controls each get one half.
You need a Mac with Xcode 27.2 (the iOS 27.2 SDK). The app runs on iOS and iPadOS 27.0 and later.
sudeux.xcodeproj.sudeux scheme and an iPhone or iPad simulator. For the foldable layouts, choose an iPhone Duo simulator; its pose can be changed in Device Hub.To run it on your own device, you need a paid Apple Developer Program membership: the app uses iCloud (CloudKit and the key-value store) and push notifications for sync, and Enhanced Security, which a free personal team can’t sign. Choose your team under Signing & Capabilities for the sudeux and SudeuxWidgetsExtension targets, and give the app identifiers of your own. They’re set once, as the project’s build settings APP_BUNDLE_IDENTIFIER, APP_GROUP_IDENTIFIER and ICLOUD_CONTAINER_IDENTIFIER, which the targets’ identifiers, entitlements and Info.plists read.
All game logic lives in the local Swift package Packages/Logic, so most tests run without a simulator:
cd Packages/Logic && swift test -Xswiftc -O
(Optimised: the puzzle generator is about 100 times slower without it.)
scripts/check.sh hook runs what the pre-commit hook runs: the version check (CHANGELOG.md against the project), formatting (swift-format, part of Xcode), linting (swiftlint), a check that mutation testing can test every mutant from one build, the package tests, a build of the app and its tests, and the translation check (every text has its Dutch). scripts/check.sh full adds the snapshot tests, the UI tests and mutation testing, which needs swift-mutation-testing. To use the hook and install the tools:
git config core.hooksPath scripts/hooks
brew install swiftlint
brew tap ericodx/homebrew-tools && brew trust --formula ericodx/tools/swift-mutation-testing && brew install swift-mutation-testing
The UI tests (SudeuxUITests) run from Xcode or xcodebuild test on any simulator, with a store of their own, so they never touch your puzzles.
| Folder | What’s in it |
|---|---|
Sudeux/ |
The app: SwiftUI views and system glue only |
SudeuxWidgets/ |
The widgets |
Packages/Logic/ |
SudokuCore (the game, generator and solver), UILogic (the screen’s decisions) and AppServices (storage, logs, settings, sync) |
SudeuxUITests/ |
End-to-end tests |
SudeuxSnapshotTests/ |
Snapshot tests: each screen compared with a reference picture per simulator |
scripts/ |
The checks, and the scripts that draw the app icon, symbols and difficulty pictures |
docs/ |
PLAN.md, the full design with every decision made while building it |
site/ |
The app’s web pages: the privacy policy and the support page |
All code in this repository was generated by Claude Code.
Sudeux is licensed under the Apache License 2.0. The puzzle generator’s constraint propagation and uniqueness check are ported from sudoku.js (MIT); see NOTICE and THIRD_PARTY_NOTICES.md. The app icon, symbols and pictures are drawn from scratch by the scripts in scripts/.