Skip to content
RudreshRajvanshPublic

About

A focus timer that drops a marble in a jar every time you finish a session. Fully offline — no trackers, no accounts, no paywall. Built with Jetpack Compose and Material 3.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

🫙 FocusJar

Every session you finish drops a marble in the jar. Watch it fill up.

© 2026 Rudresh Rajvansh. Licensed under AGPL-3.0.

License: AGPL v3 Platform Made with Kotlin No trackers


What this is

A focus timer that doesn't nag you, doesn't upsell you, and doesn't phone home.

Most productivity apps I tried wanted a subscription before they'd let me change a colour. FocusJar is the opposite: everything in it is free, there is no account, and nothing you do in the app is tracked, logged, or sent anywhere.

The jar is the whole idea. Finish a 25-minute session, earn a marble. The jar fills over the week. It's a small thing, but watching it fill turns out to be a much better motivator than a number on a dashboard.


Screenshots

Home Timer The Jar
Home Timer Jar
Analytics History Settings
Analytics History Settings

Features

  • Focus timer that keeps running with the screen off, the app backgrounded, or the phone in your pocket
  • Marble jar — one marble per completed session, stacked with a bit of physics so it looks like an actual jar
  • Streaks that survive time-zone changes and reset honestly when you miss a day
  • Analytics — weekly charts, heatmaps, and totals. Free, like everything else
  • 6 colour themes and 5 launcher icons
  • Home screen widget showing today's marbles and your current streak
  • Local backup — export your sessions and settings to a JSON file you pick, import it back any time. No cloud, no account
  • Daily reminders if you want them, silence if you don't
  • Light, dark, and AMOLED-black, following the system theme by default

Privacy

No analytics. No crash reporting. No advertising ID. No account. Nothing about how you use the app is ever collected or transmitted.

The app does hold INTERNET, for exactly one reason: the Privacy Policy and Terms screens load those two documents from my website so they stay current without shipping an app update. Nothing else in FocusJar touches the network, and no data is sent — it's a plain GET for two static HTML pages. If you open those screens offline, a bundled copy is shown instead.

Here is every permission in the shipped APK:

Permission Why
FOREGROUND_SERVICE + ..._SPECIAL_USE Keeps the countdown alive when you leave the app
POST_NOTIFICATIONS Tells you the session ended
VIBRATE Buzzes when the session ends
INTERNET Loads the Privacy Policy and Terms pages, nothing else
WAKE_LOCK Pulled in by WorkManager, which runs the daily reminder
RECEIVE_BOOT_COMPLETED Also WorkManager — it reschedules the reminder after a reboot
ACCESS_NETWORK_STATE Also WorkManager, for network-constrained jobs FocusJar doesn't use

The last two come from the WorkManager library rather than from app code.

Your sessions live in a Room database on your device and go nowhere else. Uninstalling deletes them.


Install

Grab an APK from Releases.

Builds are signed with my key, so if you switch between a build you made yourself and a release APK you'll need to uninstall first — Android refuses to replace an app with one signed differently.


Building

You need JDK 17 and an Android SDK with API 36.

git clone https://github.com/RudreshRajvansh/focusjar.git
cd focusjar && ./gradlew assembleDebug

The APK lands in app/build/outputs/apk/debug/.

Release builds are signed from a keystore.properties in the project root — copy keystore.properties.template and fill in your own keystore. Without that file the release build still compiles, it just comes out unsigned.


Built with

Nothing proprietary. Every dependency here is free software, which is what makes the F-Droid build possible.

Kotlin Language
Jetpack Compose + Material 3 Entire UI, no XML layouts
Hilt Dependency injection
Room Session history
DataStore Settings
WorkManager Runs the daily reminder
Glance Home screen widget
kotlinx.serialization Backup files
Timber Logging

Architecture is plain MVVM: a screen and a ViewModel per feature under presentation/, repository interfaces in data/repository/ with the implementations bound in di/RepositoryModule.kt. The timer itself lives in a foreground service and publishes its state as a StateFlow that the ViewModel collects.


Contributing

Yes please — bug reports especially. See CONTRIBUTING.md for how to get set up and what I'll and won't merge.


License

© 2026 Rudresh Rajvansh. GNU Affero General Public License v3.0.

Do what you like with it: use it, change it, share it. If you distribute a modified version, it has to stay free too, you have to ship the source, and the copyright notices stay intact. The same goes if you run a modified version as a network service.

About

A focus timer that drops a marble in a jar every time you finish a session. Fully offline — no trackers, no accounts, no paywall. Built with Jetpack Compose and Material 3.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages