Welcome to v2.3.0! Auto-categorization gets a speed boost with TypeSafe's System One Jev model, uncertain guesses now surface as one-tap suggestion chips, and you can sign in with passkeys — no password needed.
Highlights
- Sign in with passkeys
- Super-fast auto-categorization with System One Jev
- Suggestion chips when the category is uncertain
Sign in with passkeys
Register a passkey in account settings and sign in with your fingerprint, face, or security key. Passkeys work for every account type — email, social, and guest accounts with no email address — and the login screen remembers your last used method.
Your credentials, managed in one place
Creating a guest account now asks you to pick a backup sign-in — a recovery link (recommended) or a passkey — and both stay manageable side by side in account settings afterwards. Removing your last sign-in method is blocked, so you can't lock yourself out.
Guests choose: recovery link or passkey
One tap to get back in
Super-fast auto-categorization with System One Jev
The local dictionary and group-history matching existed largely to work around slow LLM categorization: even after exploring vector stores and embeddings over larger datasets, the LLM still took ~2 seconds on a good day. Jev reaches good accuracy in ~250 ms, so it can now do the heavy lifting.
The cascade stays the same — dictionary, then group history, then exactly one AI engine (AI_CATEGORY_ENGINE=llm|system-one, default llm) — but the shipped default for CATEGORY_LOCAL_MIN_SCORE moves from 0.7 to 0.8, giving the AI engine more room. Spliit Cloud runs with the higher gate so Jev sees more titles; self-hosters staying on the LLM can set it back toward 0.7 with CATEGORY_LOCAL_* overrides. Prefer to self-host the decision model? Point AI_SYSTEM_ONE_BASE_URL at a /v1/systemone-compatible server (e.g. Kev or Laya) and keep AI_CATEGORY_ENGINE=system-one.
When no stage is confident enough, the expense form now shows the runners-up as suggestion chips — one scrolling row with category icons, no wrapping — so a near miss is one tap away instead of a manual category hunt. Decisive verdicts stay quiet. And if you'd rather skip AI altogether, category extraction can be switched off in account settings.
"margarita" lands on drinks, with dining-out one tap away
What's Changed
🚀 Features
- Category suggestions can now use a System One decision-model engine instead of the LLM: set
AI_CATEGORY_ENGINE=system-onewithAI_SYSTEM_ONE_API_KEY(TypeSafe's Jev viajev-latestby default; a self-hosted/v1/systemone-compatible model such as Kev or Laya viaAI_SYSTEM_ONE_BASE_URL, withAI_SYSTEM_ONE_MODELandAI_SYSTEM_ONE_TIMEOUT_SECONDSoverrides) (1961edb0by @antonio-ivanovski) - Uncertain categories now surface as one-tap suggestion chips: when nothing auto-applies, the expense form shows the closest runners-up in a single horizontally scrolling row with category icons; a near-tie runner-up is offered next to an applied suggestion too, covering dictionary guesses, LLM runner-ups, and Jev's probability split, while decisive verdicts stay quiet (
1961edb0by @antonio-ivanovski) - Local suggestion stages are tunable per deployment and stay in sync between app and server:
CATEGORY_DICTIONARY_ENABLED/CATEGORY_HISTORY_ENABLEDtoggles plusCATEGORY_LOCAL_MIN_SCORE(now0.8, was0.7) andCATEGORY_LOCAL_SETTLEMENT_MIN_SCOREgates, with one sharedAI_CATEGORY_MIN_CONFIDENCEfloor (default0.5) for both AI engines; the LLM now reports confidence in its verdict, and per-user AI preferences in account settings can switch category extraction off (1961edb0by @antonio-ivanovski) - Passkey sign-in for every account type: register passwordless credentials in account settings and sign in with fingerprint, face, or security key — including guest and social accounts with no email address. New guest accounts pick a backup sign-in (recovery link or passkey, one required), both manageable side by side afterwards, and removing the last sign-in method is blocked so accounts can't be locked out. Returning guests sign back in with their link or a passkey. Disable per instance with
ENABLE_PASSKEY_AUTH=false(3479fac1by @antonio-ivanovski)
🐛 Bug fixes
- Smarter local category suggestions: short words like "in"/"to" no longer trigger false brand matches ("Beers in Prague" suggested insurance), the generic "premium" alias no longer maps alcohol to insurance, and a near-exact dictionary hit now overrules a twice-repeated past mislabel (
1961edb0by @antonio-ivanovski) - AI extraction works again on the OpenCode Go endpoint: receipt, voice, and category requests now send a stable
x-opencode-sessionheader whenAI_BASE_URLpoints atopencode.ai/zen/go, instead of failing with a missing-session routing error (eae9349bby @antonio-ivanovski) - Fixed sign-out hanging when no service worker is registered: push-subscription lookup now resolves instead of pending forever;
vite previewalso moved off:3000to:4173so a previewed build can't keep serving its precache to dev pages (61c0b3e7by @antonio-ivanovski)
Full Changelog: v2.2.1...v2.3.0
🐳 Docker images for this release
ghcr.io/antonio-ivanovski/spliit-cloud-api:v2.3.0(also available as:latest)ghcr.io/antonio-ivanovski/spliit-cloud-migrate:v2.3.0(also available as:latest)ghcr.io/antonio-ivanovski/spliit-cloud-worker:v2.3.0(also available as:latest)ghcr.io/antonio-ivanovski/spliit-cloud-mcp:v2.3.0(also available as:latest)ghcr.io/antonio-ivanovski/spliit-cloud-web:v2.3.0(also available as:latest)
Pin with
SPLIIT_TAG=v2.3.0or follow stable withSPLIIT_TAG=latest— seecompose.yaml



