A privacy-first iPhone and iPad app that turns paper invoices into structured, searchable records using an on-device Gemma model.
Invoice Monitoring is a production SwiftUI application for scanning invoices, extracting line items locally, tracking records over time, and exporting clean CSV data. The complete invoice-parsing path works without a hosted AI service: scans stay on the device unless the user explicitly enables iCloud sync.
- Native multi-page document capture with VisionKit
- Local multimodal extraction with Gemma 4 E2B and LiteRT-LM
- Defensive JSON decoding, normalization, reconciliation, and retry handling
- SwiftData-backed invoices and line items
- Profiles, categories, custom prompts, and batch-aware scan processing
- iCloud Drive mirroring with local-first storage and tombstone-based deletion
- CSV and spreadsheet export
- Versioned, checksummed invoice and line-item barcodes
- StoreKit-ready entitlement flow, currently configured with paid gates disabled
- Unit-tested parsing, profile, barcode, and string-processing internals
flowchart LR
A[VisionKit scan] --> B[Scan queue]
B --> C[On-device Gemma]
C --> D[JSON validation]
D --> E[Invoice normalization]
E --> F[(SwiftData)]
F --> G[Review and edit]
F --> H[CSV export]
F -. optional .-> I[iCloud Drive]
The UI orchestrates a set of focused stores and coordinators. ScanStore
manages capture and retries, GPTService owns the local model boundary,
InvoiceSummarySanitizer makes model output safe and consistent, and the file
coordinators mirror user data only when iCloud is enabled. See
Architecture for the detailed boundaries.
- macOS 26 or later
- Xcode 26.2 or later
- XcodeGen 2.44 or later
- iOS or iPadOS 18.5 or later
- A physical device for document-camera capture
- An Apple Developer team and iCloud container for signed iCloud builds
- Roughly 3 GB of free disk space for the optional local model
The app and unit tests build without the model. Invoice extraction requires it.
git clone https://github.com/theos2node/Invoice-uploaderV2.2.git
cd Invoice-uploaderV2.2
cp Config/Local.xcconfig.example Config/Local.xcconfig
# Fill in your bundle ID, Apple team, and iCloud container.
xcodegen generate
open "Invoice uploaderV2.xcodeproj"Download the pinned model when you want to exercise invoice extraction:
./Scripts/download_model.shThe download script verifies the model’s SHA-256 checksum before installing it
under Invoice uploaderV2/Models/. That 2.6 GB file is ignored by Git.
Run the test suite from Xcode or the command line:
swift test
# Full iOS-hosted suite (requires an installed simulator runtime):
xcodebuild \
-project "Invoice uploaderV2.xcodeproj" \
-scheme "Invoice uploaderV2" \
-destination "platform=iOS Simulator,OS=latest,name=iPhone 16e" \
CODE_SIGNING_ALLOWED=NO \
testswift test executes the 16 platform-neutral parsing, barcode, and string
tests directly on macOS. The Xcode scheme adds profile and service-boundary
coverage and compiles the complete iOS test bundle.
Public defaults live in Config/Base.xcconfig. Local identity and signing
values belong in the ignored Config/Local.xcconfig:
INVOICE_BUNDLE_ID = com.yourcompany.InvoiceMonitoring
INVOICE_ICLOUD_CONTAINER = iCloud.com.yourcompany.InvoiceMonitoring
INVOICE_KVSTORE_IDENTIFIER = $(AppIdentifierPrefix)com.yourcompany.InvoiceMonitoring
DEVELOPMENT_TEAM = YOUR_TEAM_ID
The checked-in Xcode project is generated from project.yml. Change the spec,
regenerate the project, and commit both when target or build settings change.
Invoice uploaderV2/ SwiftUI app, data models, stores, and coordinators
Config/ Public build settings and local template
Scripts/ Verified model download and build embedding
Tests/ XCTest unit tests
Package.swift Portable core test harness for macOS CI
Vendor/LiteRTLM/ Audited LiteRT-LM Swift wrapper pinned to v0.12.0
docs/ Architecture, model, privacy, and release notes
project.yml Reproducible XcodeGen project definition
Invoice images and extracted contents are not sent to a hosted parser. The model executes on device. iCloud sync is optional, export is user initiated, diagnostic logging treats file names, record identifiers, paths, and errors as private, and the repository contains no production credentials or user data. Read the full privacy design.
The model is not part of this source repository. It comes from the pinned
litert-community/gemma-4-E2B-it-litert-lm
release and remains subject to its upstream terms. The vendored LiteRT-LM Swift
wrapper is an unmodified copy of upstream v0.12.0. See
third-party notices.
Bug reports and focused pull requests are welcome. Start with CONTRIBUTING.md, review the security policy, and include tests for changes to parsing or persistence behavior.
Licensed under the Apache License 2.0.