How I always wanted to organise my life: notes, tasks, plans and project work in one place, local-first, with a hub I host myself and AI tools as first-class users.
Pre-alpha. Not ready for real use. Scratch is unstable and changes often. Vault, sync and hub data formats may change without a migration path, so keep your own backups and expect to start over. There are no support, security or compatibility promises, and issues or pull requests may go unanswered.
- Pages and blocks. Everything is a page made of blocks: text, headings, tasks, tables, code, embeds. You edit blocks, not markup.
- Properties and views. Any page can carry properties, and pages nest. A view block shows a page's children as a list, table, board, calendar or gallery, with each page drawn as a card. There are no separate databases to set up.
- Local-first. A vault is a folder on your device. Pages are Loro CRDT documents, indexed in SQLite for search, and the app works offline.
- Your own hub. Devices sync through a small server you run yourself: the hub built into the desktop app, or
notes-hubon a server behind your own TLS and OIDC login. See Running your own hub. - Agent tab. A built-in agent, on BubblePaw, that reads and edits the vault with you and asks before running tools.
- MCP access. Claude, ChatGPT and other MCP clients use the vault through the hub, with scoped agent tokens or OAuth.
- Windows, Android and a CLI. A Windows app with an installer, an Android app, and the
notescommand line tool.
flowchart LR
app["Flutter app<br/>Windows, Android"] -- FRB --> bridge[notes_bridge]
bridge --> core[vault_core]
bridge --> sync[vault_sync]
bridge --> agent[vault_agent]
cli["notes CLI"] --> tools[vault_tools]
tools --> core
sync -- HTTP --> hub["notes_hub<br/>or the app's built-in hub"]
hub --> core
hub --> mcp[vault_mcp]
mcp --> tools
clients["MCP clients"] -- MCP --> hub
| Crate | Path | What it does |
|---|---|---|
vault_core |
crates/core | Vault storage, page CRDTs, the SQLite index and search |
vault_sync |
crates/sync | The sync client and the hub's sync routes, over HTTP |
notes_hub |
crates/hub | notes-hub, the server: sync, OIDC login, device tokens, /mcp, /agent/ws |
vault_tools |
crates/tools | Transport-independent vault tools, and the notes CLI |
vault_mcp |
crates/mcp | The MCP server, over stdio and streamable HTTP |
vault_agent |
crates/agent | The BubblePaw agent over a vault: tools, sessions, approvals, AI tasks |
notes_agent_wire |
crates/agent_wire | The agent wire format shared by /agent/ws and the bridge |
scratch_cli |
crates/cli | Runs a desktop vault's AI tasks without the app's UI |
notes_bridge |
app/rust | The flutter_rust_bridge layer between the app and the crates |
The app is in app/, and its add-ons (calendar, agent, schedule, board and others) are in app/lib/addons.
Documentation. How each part works now is in the project wiki. Good first pages are the data model, the Flutter app and sync and storage.
You need stable Rust, Flutter 3.47.5 and flutter_rust_bridge_codegen 2.13.0. Windows builds need Visual Studio 2022 with ATL; Android builds need NDK 27.3.13750724 and JDK 17. The Rust workspace fetches its agent crates from BubblePaw-Core on GitHub.
cargo install flutter_rust_bridge_codegen --version 2.13.0 --locked
cargo test --workspace --locked --exclude notes-tauri # Rust tests
cd app && flutter pub get
flutter build windows --release # Windows app
flutter build apk --release # Android (debug-signed without a release keystore)
cargo build --release --locked -p vault_tools --bin notes # notes CLI
cargo build --release --locked -p notes_hub # hub server (notes-hub)The Windows installer is described in Windows installer. The screenshots come from app/test/golden_test.dart; the wordmark is Bricolage Grotesque, outlined by design/readme/wordmark.py.
AGPL-3.0-or-later; see LICENSE. Bundled third-party components and their licences are listed in THIRD_PARTY.md.
Scratch is made by BubbleBuffer.