Formerly Grove.
A native Android Org-mode note-taking app: a first-class mobile companion for Emacs org-mode users.
Bloom edits plain .org files in a folder you choose. There is no account, no proprietary database, and no export step: the files on disk are your notes, byte-for-byte, and they sync to your laptop with whatever tool you already trust (Syncthing is the recommended pairing). If you stop using Bloom tomorrow, your notes are exactly where they always were.
- File-first:
.orgfiles in a synced folder are the sole source of truth. Bloom's internal database is only a rebuildable search index. - Non-destructive org engine: a custom parser models documents as a thin view over the raw text. Parse → serialize is byte-identical by construction, so Bloom never reformats a file it didn't deliberately edit.
- Zero-friction capture: org-capture style templates with
%U,%^{prompt},%cursor-style placeholders; targets include top/bottom of file, under a heading (by name orIDof heading), and year/month/day datetrees. Reachable from a home-screen widget, the share sheet, an optional persistent notification, andbloom://capturedeep links (the pre-renamegrove://scheme still works). - Home-screen widgets: a one-tap Capture widget, and an Agenda ledger widget (overdue + day-grouped upcoming tasks, mark-done and a small quick-add composer right from the home screen — no need to open the app).
- Real editor: raw org subtree editing with syntax highlighting, a formatting toolbar (the link button inserts a URL link on tap, or long-press to link to any file or heading in the vault, by name or by
ID/CUSTOM_ID), list continuation on Enter, a metadata sheet (TODO state, priority, tags with autocomplete, SCHEDULED/DEADLINE), repeater advancement on DONE, and autosave with a stale-file guard (switchable off in Settings › Notes, in which case read mode renders your unsaved buffer until you save). - One canvas for both dates: scheduling opens a full-screen editor that puts SCHEDULED and DEADLINE on the same calendar (with the lead time between them shaded and a warning if you'd start already late), and commits both in one edit. Each carries presets, a time range and an org repeater, and a shorthand box parses lines like
fri 10-11am ++1word: aug 5as you type. - Reminders: a notification fires when a heading's SCHEDULED or DEADLINE time arrives, with Complete (marks the heading done) and Reschedule (reopens the dates screen) actions right on the notification. Enabled by default. Notification access is asked for first; once it's on, a one-time prompt asks for Android's "Alarms & reminders" access so reminders fire on the minute instead of up to an hour late. Settings › Reminders shows whichever access is still missing, with an Allow button.
- Outline operations: collapsible heading tree with body previews, expand/collapse all, move/cut/copy/paste subtrees, cycle state by swipe, narrow to a subtree.
- Heading-less content is first-class: text before a file's first heading (or a whole org-roam note with no headings) shows as its own row above the outline, opens in a read view, is counted as a note, and is searchable. Adding metadata to it inserts a blank heading above the content first.
- Nested vault folders: subdirectories inside the vault are first-class. The Notebooks screen shows the whole vault as an inline tree (a folder with more than 20 files becomes a tappable drill-down instead), a notebook's identity is its vault-relative path, and
+/ "Move to folder…" create and relocate notebooks across folders. - Orgzly-compatible search:
i.todo s.7d t.work .b.archive OR p.a, saved searches, and anad.Nagenda view. Backed by a SQLite FTS5 trigram index, so substring search stays instant as the vault grows and covers full note bodies. See docs/search-syntax.md. - Sync that respects your tools: change detection by file revision, Syncthing
.sync-conflict-*detection with a keep-local / keep-remote / keep-both picker, manual through continuous sync modes,.orgzlyignoresupport. - A calm, deliberate design: IBM Plex Sans/Serif/Mono, 20 light and dark themes (Bloom Light by default, plus Bloom Dark, Catppuccin, Rosé Pine, Tokyo Night and more), and org syntax tokens colored the way an Emacs theme would.
| Notebooks | Outline | Read mode |
|---|---|---|
![]() |
![]() |
![]() |
| Edit mode | Agenda | Widget |
|---|---|---|
![]() |
![]() |
![]() |
- Android 6.0+ (
minSdk 23) - To build: JDK 17+, Android SDK 36. Open in Android Studio, or:
./gradlew assembleDebug # build
./gradlew testDebugUnitTest # unit tests
./gradlew lintDebug # lint./gradlew testDebugUnitTest # JVM unit tests (run in CI on every push)
./gradlew connectedAndroidTest # instrumented + Compose UI tests (needs a device/emulator)CI runs the unit tests on every push and the Compose UI tests nightly. Maestro
end-to-end flows live in .maestro/.
The Macrobenchmark suite (:macrobenchmark) measures cold/warm startup and
scroll jank, and regenerates the Baseline Profile that ships in the APK. It is
not run in CI: benchmark numbers off a shared-runner emulator are noise, so
run it locally on a real device instead.
./gradlew :macrobenchmark:connectedBenchmarkReleaseAndroidTest # startup + scroll benchmarks
./gradlew :app:generateBaselineProfile # writes app/src/main/baselineProfiles/Results land in macrobenchmark/build/outputs/connected_android_test_additional_output/.
- Launch Bloom and pick your org folder (any folder reachable through Android's file picker).
- Point Syncthing (or any other sync tool) at the same folder to share it with your other machines.
- Capture something.
Following is the list of features/enhancements I'm planning to make to this app:
- Image support
- Nested search expressions
- WebDAV support
- Clickable org links
- Tips & Tricks page
- What's New screen (Settings › About)
- Multi-day events
- Bare active timestamps
app/src/main/java/com/rrajath/grove/
├── org/ Org-mode engine: parser, mutations, timestamps, line editing
├── vault/ File access: recursive FileStore abstraction, SAF + JVM impls, Vault facade
├── sync/ Sync engine, state machine, conflict handling, Android triggers
├── data/ Room index (rebuildable cache) over the vault
├── capture/ Capture templates, placeholder expansion, entry insertion
├── search/ Orgzly-style query parser, matcher, snippets, saved searches
├── settings/ Preferences (DataStore) and settings repository
├── widget/ Home-screen widgets (Capture, Agenda ledger) + persistent capture notification
└── ui/ Jetpack Compose screens, view models, theme
| Document | What it covers |
|---|---|
| docs/architecture.md | Layers, data flow, threading, and the invariants that hold the app together |
| docs/terminology.md | Glossary of org-mode and Bloom-specific terms used throughout the code |
| docs/search-syntax.md | Full reference for the search query language |
docs-site/ is the public landing page and user docs (Astro + Starlight), deployed as a Cloudflare Worker with static assets (npm run deploy). It's a separate npm project — see docs-site/README.md for setup and deployment details. Changes there don't trigger the app CI workflow (.github/workflows/build.yml ignores docs-site/**).
Kotlin 2.2 · Jetpack Compose (Material 3) · Room (on bundled SQLite, for FTS5) · DataStore · WorkManager · Glance · kotlinx.serialization · JUnit 4
Bloom bundles IBM Plex Sans, Serif, and Mono, licensed under the SIL Open Font License (see FONT_LICENSE_OFL.txt).
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
This app was built with help from LLM-based coding tools (Claude Code). All design decisions, architecture, and every piece of code are reviewed and tested by me. LLMs are a tool in the workflow, not an autopilot.





