This is the full developer documentation for Brainstorm # Brainstorm Docs > Your apps, your data, your AI — all on your machine, under permissions you grant. ## Find your way around [Section titled “Find your way around”](#find-your-way-around) Start here New to Brainstorm? [Read the overview](/start-here/what-is-brainstorm/), then [install](/start-here/install/) and [run through the quickstart](/start-here/quickstart/). Concepts Understand [vaults](/concepts/vaults/), [apps and permissions](/concepts/apps-and-permissions/), and how [local-first sync](/concepts/local-first-and-sync/) keeps your data yours. Apps Brainstorm ships nothing but apps — [Notes, Database, Files, Graph and more](/apps/). Build Build your own app on the platform — [the app model, manifest, capabilities, SDK and data layer](/build/overview/). For agents Every page has a Markdown twin. Point an agent at [`/llms.txt`](/llms.txt) or [`/llms-full.txt`](/llms-full.txt). # Apps > Brainstorm ships nothing but apps — focused, sandboxed tools that all work over the same shared objects. Brainstorm’s shell hosts **apps** — and that’s all it does. Each app is a focused tool, sandboxed and independently updatable, and every app works over the same shared [objects](/concepts/objects/) in your vault. Add the ones you want; ignore the rest. Twenty first-party apps ship with the public beta. Each page below describes the app in full, with screenshots. ## Knowledge & planning [Section titled “Knowledge & planning”](#knowledge--planning) | App | What it’s for | | ----------------------------------- | ------------------------------------------------------------------- | | **[Notes](/apps/notes/)** | A block editor with mentions, transclusion, and embeds. | | **[Database](/apps/database/)** | Every object in your vault as a grid, board, calendar, or timeline. | | **[Tasks](/apps/tasks/)** | Inbox, Today, boards, and timelines over shared Task objects. | | **[Calendar](/apps/calendar/)** | Everything with a date, on one calendar. | | **[Journal](/apps/journal/)** | Daily entries with moods, habits, and streaks. | | **[Contacts](/apps/contacts/)** | People and companies as real objects. | | **[Bookmarks](/apps/bookmarks/)** | Save the web, keep it readable offline. | | **[Files](/apps/files/)** | Browse and organize the whole vault. | | **[Graph](/apps/graph/)** | The shape of your vault, drawn live. | | **[Whiteboard](/apps/whiteboard/)** | An infinite canvas next to your data. | ## AI & automation [Section titled “AI & automation”](#ai--automation) | App | What it’s for | | ------------------------------------- | ------------------------------------------------------- | | **[Agent](/apps/agent/)** | AI chat grounded in your vault, under your permissions. | | **[Automations](/apps/automations/)** | Reviewable workflows that drive the other apps. | ## Connected [Section titled “Connected”](#connected) | App | What it’s for | | ----------------------------- | -------------------------------------------------------- | | **[Mailbox](/apps/mailbox/)** | Email as vault objects — Gmail or any IMAP/SMTP account. | | **[Browser](/apps/browser/)** | Tabbed browsing that clips pages into your vault. | | **[Chat](/apps/chat/)** | Team channels over shared vault objects. | ## Tools [Section titled “Tools”](#tools) | App | What it’s for | | ----------------------------------------- | ------------------------------------------------------ | | **[Books](/apps/books/)** | Read EPUB and PDF, keep highlights. | | **[Code Editor](/apps/code-editor/)** | A real editor for code-shaped objects. | | **[Form Designer](/apps/form-designer/)** | Forms that create real objects — plus invoices to PDF. | | **[Preview](/apps/preview/)** | Quick previews for almost any file. | | **[Theme Editor](/apps/theme-editor/)** | Design the OS you work in. | ## How apps get access [Section titled “How apps get access”](#how-apps-get-access) An app can only touch what you allow. The first time an app needs a capability it asks, and you can review or revoke grants any time. See [Apps & permissions](/concepts/apps-and-permissions/). # Agent > AI that works inside your vault. **Agent.** A chat surface over the shared AI broker: run a local Ollama model or bring your own key for Anthropic, OpenAI, Gemini, or GLM. Conversations are vault objects, answers cite the objects they drew from, and the agent can only act within capabilities you granted. ![Agent: A grounded conversation](/screenshots/apps/agent/01-conversation.webp)![Agent: A grounded conversation](/screenshots/apps/agent/midnight/01-conversation.webp) **A grounded conversation** — The agent reads the brief from the vault and drafts against it — the conversation is itself a vault object. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Hybrid retrieval grounds every answer in your vault, with citations that open the source object. * Attach context explicitly: @-mention documents and people, drop in text files, or add images for vision models. * Long-term memory is opt-in and off by default — every remembered item is visible, redactable, and deletable. * “Summarize with the agent” and “Ask the agent about this” appear on objects across the other apps. * Save a conversation as an automation: its tool trace becomes a workflow, opened in the builder for review. * Fail-closed capability model: the agent’s tools are always a subset of what you granted the conversation, re-checked on every call. ## Related [Section titled “Related”](#related) * [Apps & permissions](/concepts/apps-and-permissions/) — the same grants govern agents * [Your data & security](/concepts/your-data-and-security/) — why local AI matters # Automations > Reviewable workflows over your own apps. **Automations.** A builder for workflows triggered by time, entity events, or run by hand, composed from steps that drive other apps through intents. Every workflow declares exactly what it may touch before you can save it. ![Automations: Workflows](/screenshots/apps/automations/01-workflows.webp)![Automations: Workflows](/screenshots/apps/automations/midnight/01-workflows.webp) **Workflows** — Each workflow shows its trigger and step count next to its enabled state. ![Automations: Starter templates](/screenshots/apps/automations/02-templates.webp)![Automations: Starter templates](/screenshots/apps/automations/midnight/02-templates.webp) **Starter templates** — One-click starting points that arrive disabled until you review what they touch. ![Automations: Reminders](/screenshots/apps/automations/03-reminders.webp)![Automations: Reminders](/screenshots/apps/automations/midnight/03-reminders.webp) **Reminders** — Quick-capture reminders in their own list, with done and snooze built in. ## What it can do [Section titled “What it can do”](#what-it-can-do) * A linear builder with intent, entity, notify, wait, AI-call, AI-agent, branch, for-each, expression, export, and sub-workflow steps. * Time, entity-event, and manual triggers; starter templates arrive disabled so you review before enabling. * A save-time capability sheet shows the permissions the steps need against what is granted — over-reach blocks the save. * AI-agent steps use intents as tools, fail-closed inside the workflow’s capability envelope. * Run history records status, per-step logs, and cost; lightweight reminders get their own quick-capture view. * Import and export workflows as JSON; a single designated automation host keeps multi-device vaults from double-running. ## Related [Section titled “Related”](#related) * [Apps & permissions](/concepts/apps-and-permissions/) — workflows run inside a capability envelope # Bookmarks > Save the web, keep it readable. **Bookmarks.** A saved-link library that scrapes each page’s title, favicon, and share image through the shell’s network broker — and can capture the page’s readable content for offline reading. Bookmarks are vault objects: tag them, collect them, embed them in notes. ![Bookmarks: The inbox](/screenshots/apps/bookmarks/01-inbox.webp)![Bookmarks: The inbox](/screenshots/apps/bookmarks/midnight/01-inbox.webp) **The inbox** — Saved pages with scraped titles, favicons, and tags. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Opt-in readable capture stores the cleaned article body offline, with provenance stamped on machine-extracted content. * A reading view with a cover band and an editable body — annotate the captured article in place. * Tags plus an interactive tag kanban board; smart collections save live filters, manual collections hold explicit sets. * Content-kind labels — article, video, image, product — folded from OpenGraph metadata. * Duplicate URLs are detected and merged. * Paste a URL in Notes and it becomes an embedded bookmark card; a dashboard widget shows recent saves. ## Related [Section titled “Related”](#related) * [Browser](/apps/browser/) — clip pages into bookmarks as you browse # Books > Read EPUB and PDF, keep highlights. **Books.** A reading app with an in-vault library: import an EPUB or PDF and it becomes a Book object that remembers your position and progress. Highlights are first-class objects you can embed in notes. ![Books: The library](/screenshots/apps/books/01-library.webp)![Books: The library](/screenshots/apps/books/midnight/01-library.webp) **The library** — Imported books with author and progress, ready to reopen where you left off. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Paginated reflow reading for EPUB with five typography controls — family, size, leading, measure, theme — that re-paginate without losing your place. * PDF reading with the document’s real outline, page navigation, and safe clickable links. * Select to highlight in five colors and attach a note; the anchor survives typography changes. * A library shelf with search and sorting, showing author and progress per book. * Reopen any book exactly where you left off. * Embed a highlight card in Notes with the /book command. ## Related [Section titled “Related”](#related) * [Notes](/apps/notes/) — embed a highlight card with the /book command # Browser > Browsing that saves into your vault. **Browser.** Tabbed browsing over isolated, Node-less web renderers the app itself never touches — it sees metadata, never page bytes. One click clips the page into a bookmark, with the readable article body captured when the page allows it. ![Browser: A page, loaded at arm's length](/screenshots/apps/browser/01-tabs.webp)![Browser: A page, loaded at arm's length](/screenshots/apps/browser/midnight/01-tabs.webp) **A page, loaded at arm's length** — The page paints in an isolated, Node-less renderer beside the app — the app itself gets the title, favicon, and security state, never the page's pixels or bytes. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Tabs with pinning, private tabs on throwaway sessions, a recently-closed ring, and full session restore across restarts. * Save to vault writes a Bookmark object with the cleaned readable content attached; a blocked page degrades to a link, never a failed clip. * Per-tab security state surfaced in the chrome. * Find in page, and browsing history kept as vault objects with visit counts. * Per-site device permissions are deny-by-default, surfaced through an explicit banner. * Cookies persist encrypted under the vault key. ## Related [Section titled “Related”](#related) * [Bookmarks](/apps/bookmarks/) — where clipped pages land # Calendar > A time view over any dated objects in your vault — events, tasks, and anything with a date property. **Calendar** is a time-based lens over your vault. Anything with a date — an event, a task’s due date, a note’s deadline — can appear on it. ![Calendar: Month](/screenshots/apps/calendar/01-month.webp)![Calendar: Month](/screenshots/apps/calendar/midnight/01-month.webp) **Month** — Events, task due dates, journal days, and birthdays project onto one month grid. ![Calendar: Week](/screenshots/apps/calendar/02-week.webp)![Calendar: Week](/screenshots/apps/calendar/midnight/02-week.webp) **Week** — Timed events and multi-day ribbons laid out hour by hour. ![Calendar: Agenda](/screenshots/apps/calendar/03-agenda.webp)![Calendar: Agenda](/screenshots/apps/calendar/midnight/03-agenda.webp) **Agenda** — A linear agenda of everything coming up, one row per item. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Recurring events on a full RRULE engine, edited through a plain-language recurrence editor. * ICS import and export, plus two-way CalDAV sync through the connector framework. * Attendees with per-person RSVP, event status, colors, location, and per-event reminders. * Click empty space to create, drag a chip to reschedule, multi-select for bulk reschedule. * Time-zone aware events and multi-day ribbons that lay out cleanly across the week. * Ranked event search with keyboard navigation, and Today’s Agenda / Week Ahead dashboard widgets. ## A view, not a separate store [Section titled “A view, not a separate store”](#a-view-not-a-separate-store) The Calendar doesn’t keep its own private list of events. It reads [objects](/concepts/objects/) that have a date [property](/concepts/objects/) and lays them out in time. Create a task in the [Database](/apps/database/) with a due date and it shows up on the Calendar automatically — they’re the same object. ## Working with time [Section titled “Working with time”](#working-with-time) * See your week or month at a glance. * Move an object in time by dragging it; the change writes straight back to the object. * Jump from a calendar entry to the object itself to add detail. ## Related [Section titled “Related”](#related) * [Database](/apps/database/) — create dated objects that surface here * [Objects](/concepts/objects/) — the date properties the Calendar reads # Chat > Team channels over shared vault objects. **Chat.** Channels whose messages are the same Message objects the rest of the vault uses, synced to members through collection sharing. Share a channel and it cascades to everyone on the roster — no separate chat silo. ![Chat: A channel](/screenshots/apps/chat/01-channel.webp)![Chat: A channel](/screenshots/apps/chat/midnight/01-channel.webp) **A channel** — Messages are vault objects — formatting, mentions, and attachments in the composer. ![Chat: Members](/screenshots/apps/chat/02-members.webp)![Chat: Members](/screenshots/apps/chat/midnight/02-members.webp) **Members** — The membership panel, backed by a signed roster. ## What it can do [Section titled “What it can do”](#what-it-can-do) * A rich composer with inline formatting and links; Enter sends, Shift+Enter breaks. * @-mention people and pin documents or media to a message as attachment chips. * A membership panel backed by a signed roster, with earlier posters shown as guests. * Messages group by author within a five-minute window, with day dividers and stable per-author colors. * Deterministic message ordering converges to the same transcript on every device. ## Related [Section titled “Related”](#related) * [Local-first & sync](/concepts/local-first-and-sync/) — how messages reach other devices # Code Editor > A real editor for code-shaped notes. **Code Editor.** Edits snippets, configs, and other code-shaped objects in the vault with a genuinely capable editor: Shiki highlighting, multi-cursor, folding, diagnostics, and diffs. It opens any source-code MIME the vault hands it. ![Code Editor: Editing a snippet](/screenshots/apps/code-editor/01-editor.webp)![Code Editor: Editing a snippet](/screenshots/apps/code-editor/midnight/01-editor.webp) **Editing a snippet** — Shiki highlighting and diagnostics over a collaborative buffer that is a vault object. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Shiki syntax highlighting with lazily loaded per-language grammars and light/dark themes. * Multi-cursor and select-next-occurrence, bracket matching, auto-close pairs, code folding, and word wrap. * Quick-open (Cmd/Ctrl+P) and a fuzzy command palette (Cmd/Ctrl+Shift+P). * Built-in diagnostics with inline squiggles, gutter change markers, and unified or side-by-side diffs against the saved baseline. * Prettier formatting for web languages, on save or on demand. * A collaborative Y.Text buffer on the same local-first substrate as everything else, with virtualized rendering for large files. ## Related [Section titled “Related”](#related) * [Objects](/concepts/objects/) — code files are vault objects too # Contacts > People and companies as real objects. **Contacts.** An address book over the shared Person and Company types every other app can read. Relationships are links — click a company or a connected person and it opens wherever it lives. ![Contacts: A person](/screenshots/apps/contacts/01-person.webp)![Contacts: A person](/screenshots/apps/contacts/midnight/01-person.webp) **A person** — Contact methods, role, and the company link — people are objects the other apps reference. ![Contacts: New contact](/screenshots/apps/contacts/02-new-contact.webp)![Contacts: New contact](/screenshots/apps/contacts/midnight/02-new-contact.webp) **New contact** — Capture name, company, email, and phone in one compose card. ## What it can do [Section titled “What it can do”](#what-it-can-do) * A searchable, alphabetically grouped people list with emails, phones, role, bio, birthday, and anniversary per person. * Company grouping: open a company to see its people; company links from other apps land here. * vCard 3.0 and 4.0 import and export. * Birthdays recur yearly on the shared Calendar. * Mailbox resolves inbound addresses to existing people — linking, never auto-creating. * A dashboard widget keeps a pinned people list on the desktop. ## Related [Section titled “Related”](#related) * [Objects](/concepts/objects/) — people and companies are objects other apps link to # Database > Structured tables of objects with typed properties and multiple views — table, board, and more. **Database** turns your [objects](/concepts/objects/) into structured, queryable tables — tasks, contacts, a reading list, a CRM, an inventory. ![Database: A query-backed list](/screenshots/apps/database/01-collection.webp)![Database: A query-backed list](/screenshots/apps/database/midnight/01-collection.webp) **A query-backed list** — The studio's tasks as a live collection — status and priority pills in typed cells, counts in the sidebar. ![Database: Same objects, board view](/screenshots/apps/database/02-board.webp)![Database: Same objects, board view](/screenshots/apps/database/midnight/02-board.webp) **Same objects, board view** — Flip the view and the list becomes a kanban grouped by status — no export, no copy. ![Database: Row inspector](/screenshots/apps/database/03-inspector.webp)![Database: Row inspector](/screenshots/apps/database/midnight/03-inspector.webp) **Row inspector** — Open any row in the right panel and edit its properties without leaving the view. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Six view kinds per List: grid, list, gallery, kanban board, calendar, and timeline with drag and dependency lines. * Filters with AND/OR groups and live relative-date ranges like “last 7 days”. * Formula and rollup columns compute across properties and relations; footers aggregate sum, average, median, and more. * Edit cells in place with the same typed cells the rest of the platform uses. * CSV import with type inference; export a List to CSV, JSON, or Markdown. * Save any object as a template and start new rows from it. * Embed a live List inside a note with the /database command. ## Typed properties [Section titled “Typed properties”](#typed-properties) Each row is an object, and each column is a typed **property** — text, number, date, checkbox, select, link, and more. Properties are defined at the vault level, so a “Status” or “Due date” means the same thing wherever that object appears. Cells are edited inline through Brainstorm’s shared property system. ## Multiple views [Section titled “Multiple views”](#multiple-views) The same set of objects can be viewed several ways without duplicating data: * **Table** — the classic rows-and-columns grid. * **Board** — a kanban grouped by a property. * **List**, **Gallery**, and other layouts for different shapes of data. A view defines how objects are filtered, sorted, and grouped; switching views never changes the underlying objects. ## Shared with every app [Section titled “Shared with every app”](#shared-with-every-app) Rows are ordinary objects, so a task you create in a Database can appear on the [Calendar](/apps/calendar/), as a node in the [Graph](/apps/graph/), and linked from a [Note](/apps/notes/). The database is one lens over your data, not a silo. ## Related [Section titled “Related”](#related) * [Objects](/concepts/objects/) — the rows and properties model * [Calendar](/apps/calendar/) — a time view over the same objects # Files > Bring documents and media into your vault and browse them alongside your other objects. **Files** brings existing documents and media — PDFs, images, and other attachments — into your vault so they live alongside your notes, tasks, and databases. ![Files: The vault as files](/screenshots/apps/files/01-list.webp)![Files: The vault as files](/screenshots/apps/files/midnight/01-list.webp) **The vault as files** — Folders are entities; the list view shows type and metadata per row. ![Files: File inspector](/screenshots/apps/files/03-inspector.webp)![Files: File inspector](/screenshots/apps/files/midnight/03-inspector.webp) **File inspector** — Preview, Properties, and Links tabs on the selected file. ## What it can do [Section titled “What it can do”](#what-it-can-do) * List, icon-list, grid, and gallery views, remembered per folder. * Smart folders capture a search’s query and scope as a live sidebar entry. * Upload real files through the OS picker or drag them in from Finder — bytes, MIME type, size, and SHA-256 hash included. * Multi-select bulk delete, move, copy, and rename with collision-safe naming. * An inspector with Preview, Properties, and Links tabs; folder covers and icons are click-to-edit. * Virtualized lists keep large folders fast; breadcrumbs, grouping, and a Recently Deleted view keep them navigable. ## Files are objects too [Section titled “Files are objects too”](#files-are-objects-too) A file you add becomes an [object](/concepts/objects/) in your vault: it can be linked from a note with `@`, given properties, collected into sets, and surfaced in the [Graph](/apps/graph/). Your documents stop being loose attachments and become part of the connected workspace. ## Browsing and previewing [Section titled “Browsing and previewing”](#browsing-and-previewing) Files gives you a familiar browser for what’s in your vault, and the **Preview** app renders supported documents and media inline so you can read without leaving Brainstorm. ## On your disk [Section titled “On your disk”](#on-your-disk) Files you add are stored in your vault on your own disk and protected by your vault key. They sync with everything else when you [enable sync](/concepts/local-first-and-sync/), end-to-end encrypted. ## Related [Section titled “Related”](#related) * [Objects](/concepts/objects/) — how files relate to everything else * [Your data & security](/concepts/your-data-and-security/) — where files are stored and how they’re protected # Form Designer > Forms that create real objects. **Form Designer.** Build a property form over any entity type, save it as a reusable Layout object, and every fill creates a real object of that type — there is no submissions inbox to shovel data out of. It also renders invoices to PDF. ![Form Designer: The builder](/screenshots/apps/form-designer/01-builder.webp)![Form Designer: The builder](/screenshots/apps/form-designer/midnight/01-builder.webp) **The builder** — Pick a target type and compose its fields from the live property catalog. ![Form Designer: Fill mode](/screenshots/apps/form-designer/02-fill.webp)![Form Designer: Fill mode](/screenshots/apps/form-designer/midnight/02-fill.webp) **Fill mode** — Each fill validates required fields and creates a real object of the target type. ![Form Designer: Invoices](/screenshots/apps/form-designer/03-invoice.webp)![Form Designer: Invoices](/screenshots/apps/form-designer/midnight/03-invoice.webp) **Invoices** — Line items, totals, and a live paper preview, exportable to PDF. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Pick a target type and compose its fields from the live vault property catalog, with per-field label overrides. * Conditional visibility per field, using the same predicate language as Database filters. * Fill mode validates required fields and mints a new entity on create. * Forms are reusable vault objects, scoped to the type they create. * An Invoice document type with line items, tax, status, and totals, rendered to PDF. ## Related [Section titled “Related”](#related) * [Database](/apps/database/) — where the created objects show up # Graph > See how the objects in your vault link together as a navigable, interactive graph. **Graph** visualizes your vault as what it really is — a web of connected [objects](/concepts/objects/). Notes, tasks, files, and the links between them become a map you can explore. ![Graph: The whole vault](/screenshots/apps/graph/01-graph.webp)![Graph: The whole vault](/screenshots/apps/graph/midnight/01-graph.webp) **The whole vault** — Every object and typed link drawn live; mentions and relations become edges. ![Graph: Pattern filters](/screenshots/apps/graph/02-filters.webp)![Graph: Pattern filters](/screenshots/apps/graph/midnight/02-filters.webp) **Pattern filters** — Filter by type and condition; the match summary updates live as you refine. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Pattern filters describe subjects, typed edges, and per-subject conditions; the query compiles to SQL and stays live. * Local mode walks 1–10 hops from a root in either or both directions; path mode finds the shortest paths between two objects. * History animation replays the vault over time with a density histogram and a scrubber. * Force, radial, hierarchy, and circular layouts; drag nodes, or drag from a handle to create a real typed link. * An editable inspector changes a node’s properties inline without leaving the canvas. * Export as JSON, Graphviz DOT, GraphML, or SVG; embed a live graph inside a note. ## See the shape of your knowledge [Section titled “See the shape of your knowledge”](#see-the-shape-of-your-knowledge) Every `@`-mention, collection membership, and relationship becomes an edge. The graph reveals clusters, hubs, and orphans you’d never spot in a list — the note everything points to, the topic that’s drifted off on its own. ## Navigate by relationship [Section titled “Navigate by relationship”](#navigate-by-relationship) Click a node to open the object; follow edges to move between related objects. The graph is a way to *travel* your vault by meaning rather than by folder. ## Built for scale [Section titled “Built for scale”](#built-for-scale) The graph renders on a high-performance canvas so it stays smooth as your vault grows into thousands of objects and links. ## Related [Section titled “Related”](#related) * [Objects](/concepts/objects/) — what the nodes and edges represent * [Notes](/apps/notes/) — where most links are created # Journal > A daily writing habit, built in. **Journal.** Each day is an entry titled by its date, written in the same block editor as Notes. Moods, habits, streaks, and backlinks make it a journal that is part of the vault, not a silo. ![Journal: A day's entry](/screenshots/apps/journal/01-entry.webp)![Journal: A day's entry](/screenshots/apps/journal/midnight/01-entry.webp) **A day's entry** — Date-titled entries in the same block editor as Notes, with a mini-calendar for jumping days. ![Journal: Weekly rollup](/screenshots/apps/journal/02-weekly-rollup.webp)![Journal: Weekly rollup](/screenshots/apps/journal/midnight/02-weekly-rollup.webp) **Weekly rollup** — The This-week rollup gathers and links the days it covers. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Jump to any day, week, or month; weekly and monthly rollup entries auto-link their days. * A mood picker and habit check-ins color the mini-calendar; streaks and a writing heatmap track the habit. * Templates seed a Daily review, Gratitude, or Free write structure. * Backlinks and outgoing-links panels; @-mention anything from an entry. * Full-text search across days, filterable by mood and habit. * An opt-in daily reminder warns before a streak breaks; export any date range to Markdown or HTML. * Entries surface as all-day items in the Calendar. ## Related [Section titled “Related”](#related) * [Notes](/apps/notes/) — the same block editor, without the dates # Mailbox > Email that lives in your vault. **Mailbox.** A full mail client — folder rail, message list, reading pane, composer — where every message is a vault object you can search, link, and automate. Connect Gmail via OAuth or any IMAP/SMTP account; credentials are sealed shell-side and never touch the app. ![Mailbox: Connect an account](/screenshots/apps/mailbox/01-connect.webp)![Mailbox: Connect an account](/screenshots/apps/mailbox/midnight/01-connect.webp) **Connect an account** — Mail arrives once you connect an account; until then the app holds nothing at all. ![Mailbox: Bring any account](/screenshots/apps/mailbox/02-accounts.webp)![Mailbox: Bring any account](/screenshots/apps/mailbox/midnight/02-accounts.webp) **Bring any account** — Gmail via OAuth or plain IMAP/SMTP — either way the credentials are sealed shell-side and never touch the app. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Read, compose, reply, and forward; sending is idempotent, so a retry can never double-send. * HTML mail renders in a sandboxed frame that blocks remote images by default — tracking pixels don’t fire unless you opt in. * Choose a sync window from 30 days to everything, with server-authoritative flags and vault-local tags. * Threads, attachments as file objects, and per-message tags. * Other apps and the Agent can pre-seed a compose, reply, or forward through intents. * Senders resolve to existing Contacts people — linked, never auto-created. ## Related [Section titled “Related”](#related) * [Contacts](/apps/contacts/) — senders resolve to existing people # Notes > Rich-text writing in Brainstorm — headings, lists, code, links to any object, and a command menu. **Notes** is Brainstorm’s rich-text writing app. It’s where most freeform thinking starts. ![Notes: Notes that link out](/screenshots/apps/notes/01-editor.webp)![Notes: Notes that link out](/screenshots/apps/notes/midnight/01-editor.webp) **Notes that link out** — A reading note with a live embedded bookmark card — blocks, mentions, and embeds in one editor. ![Notes: Real documents](/screenshots/apps/notes/02-document.webp)![Notes: Real documents](/screenshots/apps/notes/midnight/02-document.webp) **Real documents** — Prose with @-mentions that link straight to people and projects; backlinks accrue on the other side. ![Notes: Typed properties on a page](/screenshots/apps/notes/03-properties.webp)![Notes: Typed properties on a page](/screenshots/apps/notes/midnight/03-properties.webp) **Typed properties on a page** — The shared properties panel: typed fields that live on the note object itself. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Slash commands, the block grip menu, and right-click all draw from one command registry — turn-into, insert, and block actions everywhere. * @-mention any vault object; backlinks and outgoing references show up in their own panel. * Transclude a block or a whole note inline and it stays live in both places. * Typed property blocks, sortable tables with fill-down, and syntax-highlighted code blocks. * Range-anchored comments and shared cursors over a local-first document. * Covers and icons, page-level and per-block read-only locks, find-and-replace, and export to Markdown, HTML, or PDF. ## Writing [Section titled “Writing”](#writing) Notes supports the formatting you’d expect — headings, bold and italic, lists, checkboxes, quotes, code blocks, and dividers. Text is structured under the hood (via Lexical), so it stays clean and portable rather than becoming a soup of markup. ## Linking your knowledge [Section titled “Linking your knowledge”](#linking-your-knowledge) * Type **`@`** to mention and link any [object](/concepts/objects/) in your vault — another note, a task, a contact. The link is real: the target knows it’s referenced. * Type **`/`** to open the command menu and insert blocks, headings, and embeds without leaving the keyboard. Because a note links to real objects, your writing becomes part of the connected graph of your vault rather than an island of text. ## Always saved, always yours [Section titled “Always saved, always yours”](#always-saved-always-yours) Every keystroke is saved to your vault on disk, offline and instantly. If you [sync](/concepts/local-first-and-sync/), edits merge cleanly across devices with no version conflicts. ## Related [Section titled “Related”](#related) * [Objects](/concepts/objects/) — what `@`-links point at * [Graph](/apps/graph/) — see your notes’ links visually # Preview > Quick previews for almost any file. **Preview.** A fast previewer that dispatches each file to a per-format renderer: images, RAW and HEIC photos, PDF, video, audio, text, Markdown, code, Office documents, and 3D models. Every renderer loads lazily, so opening stays quick. ![Preview: An image, previewed](/screenshots/apps/preview/01-image.webp)![Preview: An image, previewed](/screenshots/apps/preview/midnight/01-image.webp) **An image, previewed** — Pan and zoom without upscaling; arrow through neighboring files on the filmstrip. ![Preview: The inspector](/screenshots/apps/preview/02-inspector.webp)![Preview: The inspector](/screenshots/apps/preview/midnight/02-inspector.webp) **The inspector** — Edit the file's real vault properties and comments right next to the preview. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Images pan and zoom without upscaling, with rotate and flip; HEIC decodes in place and RAW shows the camera’s embedded JPEG. * PDF with page navigation, zoom, and safe external links; audio with ID3 tags, bitrate, and sample rate in the inspector. * DOCX, XLSX, and PPTX open as sanitized, read-only text and tables. * glTF, GLB, and OBJ models spin under orbit controls. * Arrow through neighboring files on a filmstrip, or browse the vault’s files from the built-in sidebar. * The inspector edits the file’s real vault properties and comments — the same object everywhere. ## Related [Section titled “Related”](#related) * [Files](/apps/files/) — browse everything Preview can open # Tasks > Inbox, Today, board and timeline. **Tasks.** Focused surfaces — Inbox, Today, Upcoming, per-project — over Task objects the Calendar, Database, and Graph read too. Structure lives on the object, so work moves between apps without moving the data. ![Tasks: Today](/screenshots/apps/tasks/01-today.webp)![Tasks: Today](/screenshots/apps/tasks/midnight/01-today.webp) **Today** — Inbox, Today, and Upcoming keep focus; counts update live as work moves. ![Tasks: Status board](/screenshots/apps/tasks/02-board.webp)![Tasks: Status board](/screenshots/apps/tasks/midnight/02-board.webp) **Status board** — Drag cards between status columns — the same Task objects Calendar and Graph read. ![Tasks: Timeline](/screenshots/apps/tasks/03-timeline.webp)![Tasks: Timeline](/screenshots/apps/tasks/midnight/03-timeline.webp) **Timeline** — Scheduled work laid out across the weeks, with today marked and unscheduled work counted. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Status kanban and tag filters next to the list surfaces, plus a timeline view with duration spans and dependency chains. * Subtasks roll progress up to the parent; blocking and blocked-by dependencies are explicit. * Priority, recurrence with a plain-language summary, and time estimates against logged time. * Reminders fire real notifications for due and scheduled work. * Per-task comments and an activity feed; assignees link to Person objects from Contacts. * An inline-task block embeds a checkable task in any note; two dashboard widgets track open tasks and stats. ## Related [Section titled “Related”](#related) * [Database](/apps/database/) — the same tasks as a table, board, or timeline * [Calendar](/apps/calendar/) — due dates on the month grid # Theme Editor > Design the OS you work in. **Theme Editor.** Compose a theme from four parts — a token set, an icon pack, typography, and an optional CSS style pack — and preview it live across the shell and every open app. Themes are vault objects like everything else. ![Theme Editor: The token set](/screenshots/apps/theme-editor/01-tokens.webp)![Theme Editor: The token set](/screenshots/apps/theme-editor/midnight/01-tokens.webp) **The token set** — Semantic tokens with live swatches and per-token reset, over a light or dark base. ![Theme Editor: Typography](/screenshots/apps/theme-editor/02-typography.webp)![Theme Editor: Typography](/screenshots/apps/theme-editor/midnight/02-typography.webp) **Typography** — Font stacks per role and a density scale, previewed live. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Edit the semantic token namespace with live swatches, a color picker, and per-token reset, against a light or dark base. * Pick an icon pack and set font stacks per role — UI, body, code, display — plus a density scale. * A raw-CSS style pack editor whose sanitizer rejects dangerous constructs and blocks save on errors. * One button previews the composition across the dashboard and every app window, then auto-reverts. * WCAG contrast lint flags unreadable token pairs. * Hand the style pack’s CSS to the Code Editor for a full editing surface. ## Related [Section titled “Related”](#related) * [Apps & permissions](/concepts/apps-and-permissions/) — themes are vault objects # Whiteboard > An infinite canvas next to your data. **Whiteboard.** Sticky notes, shapes, ink, images, frames, and connectors on a free canvas. Nodes can embed any vault object via the Block Protocol, so the board sits next to your structured data instead of off in another tool. ![Whiteboard: A working board](/screenshots/apps/whiteboard/01-board.webp)![Whiteboard: A working board](/screenshots/apps/whiteboard/midnight/01-board.webp) **A working board** — Sticky notes and connectors from a client review, on an infinite canvas. ![Whiteboard: Add to board](/screenshots/apps/whiteboard/02-insert-menu.webp)![Whiteboard: Add to board](/screenshots/apps/whiteboard/midnight/02-insert-menu.webp) **Add to board** — Shapes, stickies, text, frames, and connectors from one insert menu. ## What it can do [Section titled “What it can do”](#what-it-can-do) * Rectangles, ellipses, triangles, diamonds, lines and arrows, colored stickies, freehand ink, and rich text. * Connectors snap between node handles with bezier, step, or straight paths, arrowheads, and labels; step routing avoids obstacles. * Align, distribute, snap-to-grid, and smart guides; a layers panel manages stacking order. * Frames contain, groups gather; start from Blank, Kanban, Flowchart, or Mind-map templates. * Real-time presence with remote cursors, per-object and board-level locks, and undo/redo. * Export the board as JSON, SVG, or PNG. ## Related [Section titled “Related”](#related) * [Objects](/concepts/objects/) — boards can embed any vault object # Capabilities > Apps declare the narrow permissions they need; the shell grants, prompts, or denies. Nothing is ambient and checks fail closed. A Brainstorm app starts with almost no power. It can render its own window and read and write its own storage — that’s it. Everything else — reading other object types, reaching the network, posting a notification, signing a payload — is a named **capability** the app declares and the user grants. This is the same model described in [Apps & permissions](/concepts/apps-and-permissions/), seen from the builder’s side. Two invariants shape how you write apps: * **Nothing is ambient.** There’s no “let the app do anything.” Every sensitive action maps to a capability granted for a reason. * **It fails closed.** If a capability check can’t be satisfied — or anything goes wrong evaluating it — the action is denied, never silently allowed. ## The grammar [Section titled “The grammar”](#the-grammar) A capability is `.` with an optional `:`: ```plaintext storage.kv # own key/value store entities.read:io.brainstorm.notes/Note/v1 # read one entity type entities.write:io.brainstorm.notes/Note/v1 # write one entity type entities.read:* # read ALL entity types (heavily prompted) files.write # write file handles the user picks network.connect:wss://sync.example.com # connect to one host network.connect:* # broad network (heavily prompted) intents.dispatch:open # dispatch open intents notifications.post # post a notification ``` The scope is what keeps grants meaningful. Asking for `entities.read:io.brainstorm.tasks/Task/v1` is a request a user can reason about; asking for `entities.read:*` is asking to read their entire vault, and the prompt says so. **Request the narrowest scope that does the job** — broad scopes are heavily prompted and erode trust. ## Declaring them [Section titled “Declaring them”](#declaring-them) List the capabilities your app needs in the manifest. The user reviews them at install: ```json "capabilities": [ "storage.kv", "entities.read:io.brainstorm.tasks/Task/v1", "entities.write:io.brainstorm.tasks/Task/v1", "notifications.post" ] ``` The granted set is also available to the app at runtime: ```ts const granted = window.brainstorm.capabilities; // string[] if (granted.includes("notifications.post")) { // safe to call the notify path } ``` ## Requesting at runtime [Section titled “Requesting at runtime”](#requesting-at-runtime) Capabilities you don’t need up front are better requested when the feature is first used, with a reason the user sees in the prompt: ```ts await window.brainstorm.services.capabilities.request( "network.connect:wss://sync.example.com", "to sync your board with the team relay", ); ``` A clear, specific reason is the difference between a grant and a denial. Ask in context — at the moment the user clicks the thing that needs it — not on launch. ## The grant model [Section titled “The grant model”](#the-grant-model) Capabilities fall into three bands: * **Default-grant** — given without a prompt because they carry no cross-app or system risk: `storage.kv` (your own keyspace), dispatching `open` intents, and rendering your own window. You can rely on these existing. * **Prompt-grant** — the common case: the user is asked, at install or at first use, and can grant, deny, or scope the grant. Most `entities.*`, `files.*`, `network.*`, and `notifications.post` live here. * **Never-grant to sandboxed apps** — privileged, shell-internal capabilities a third-party app cannot hold at all. Grants are recorded **per vault**, so an app trusted in your work vault has no standing in your personal vault. The user can revoke any grant at any time; revocation takes effect on the next host-service call. ## Degrade gracefully when denied [Section titled “Degrade gracefully when denied”](#degrade-gracefully-when-denied) Because the user can deny or later revoke, **a denied capability is a normal runtime state, not a crash**. Service calls that hit a missing capability reject; catch and degrade: ```ts try { const hits = await window.brainstorm.services.search.query("budget"); render(hits); } catch (err) { if (err.name === "CapabilityDenied") { showInlineHint("Grant search access to find across your vault."); return; } throw err; } ``` Listen for changes so the UI tracks the live grant set: ```ts window.brainstorm.on("capability-changed", (caps) => { // re-enable or hide features as grants change }); ``` An app that hides or disables what it can’t currently do — rather than throwing — is one users trust enough to grant *more*. ## Next [Section titled “Next”](#next) * [SDK & runtime](/build/the-sdk/) — the services these capabilities gate. * [Working with data](/build/working-with-data/) — the `entities`, `files`, and `intents` calls in practice. # Build on Brainstorm > Brainstorm is built entirely out of sandboxed apps over a shared object layer. This is how you build one. Brainstorm is a desktop shell that hosts **apps** — and nothing else. Notes, Database, Graph, Calendar, the whole product is apps running over one shared [object layer](/concepts/objects/). The same model is open to you: an app you build is a peer of the built-in ones, with the same access to vault data and the same place in the launcher. This section is the developer hub for building those apps. It assumes you’ve read the [Concepts](/concepts/vaults/) — especially [Apps & permissions](/concepts/apps-and-permissions/) and [Objects](/concepts/objects/) — because the platform’s guarantees *are* its API. Note Brainstorm is in active development ahead of its public beta. App building today happens inside the shell source tree (see [Your first app](/build/your-first-app/)). A standalone published SDK and a third-party app-publishing pipeline are on the roadmap; these docs describe the app model and SDK as they exist now and will grow as that pipeline lands. ## What an app is [Section titled “What an app is”](#what-an-app-is) An app is a small web app — HTML, JavaScript, CSS — that runs in its own sandboxed renderer. It ships with a [manifest](/build/the-manifest/) that declares who it is, what data types it owns, and which [capabilities](/build/capabilities/) it needs. The shell installs it, gives it a window, and brokers every request it makes to the system. Three properties define the model: * **Sandboxed.** An app can’t reach the filesystem, the network, or another app on its own. It can only do what you’ve granted through the capability ledger. This is the security boundary — it’s what makes it safe to run third-party apps, and later autonomous agents, over your most important data. * **Capability-gated.** Every sensitive action maps to a named capability the app declared and you approved. Nothing is ambient; checks fail closed. See [Capabilities](/build/capabilities/). * **Over shared objects.** Apps don’t own private silos. They read and write typed [objects](/concepts/objects/) in the vault, so the note you write in one app is the same object another app can link to, show on a calendar, or place on a graph. ## What you build with [Section titled “What you build with”](#what-you-build-with) Every Brainstorm app is a **React app** built on one shared toolkit: * **`@brainstorm/sdk`** — the component and helper library: menus, popovers, icons, pickers, property UI, search, find-and-replace, formatting, and the app-chrome theme. Check the [SDK & runtime](/build/the-sdk/) before writing anything; if a primitive exists, you import it rather than rebuild it. * **`@brainstorm/react-yjs`** — the reactivity layer. Live entity lists and collaborative documents flow through hooks like `useVaultEntities` and `useYDoc`. You never hand-roll a change loop. * **`window.brainstorm`** — the runtime the shell injects into every app: your identity, your granted capabilities, your launch context, and the [service namespaces](/build/the-sdk/#the-runtime) (`entities`, `files`, `intents`, `storage`, `search`, …) you call to do work. ## The shape of the work [Section titled “The shape of the work”](#the-shape-of-the-work) A typical app is four things: 1. A **[manifest](/build/the-manifest/)** declaring the app, the object types it owns, and the capabilities it needs. 2. A **React UI** mounted into the app window, using the standard [header chrome](/build/the-sdk/#app-chrome) and SDK components. 3. **[Data access](/build/working-with-data/)** — reading and writing entities, syncing rich text through Yjs, storing app-private state. 4. **[Integration](/build/working-with-data/#talking-to-other-apps)** — registering as an opener for a type, dispatching intents, contributing widgets, so your app composes with the rest of the workspace instead of standing alone. ## Where to go next [Section titled “Where to go next”](#where-to-go-next) * **[Your first app](/build/your-first-app/)** — scaffold, run, and see an app in the shell. * **[The manifest](/build/the-manifest/)** — every field, with a real example. * **[Capabilities](/build/capabilities/)** — the permission grammar and how to ask for access. * **[SDK & runtime](/build/the-sdk/)** — the toolkit and the `window.brainstorm` surface. * **[Working with data](/build/working-with-data/)** — entities, documents, storage, and cross-app integration. * **[Recipes & anti-patterns](/build/recipes/)** — the patterns to copy and the mistakes to avoid. # Recipes & anti-patterns > The patterns that keep an app consistent with the platform, and the mistakes that get rejected in review. Brainstorm apps share a small set of conventions. Following them is what makes a third-party app feel native rather than bolted on — same keyboard model, same theming, same accessibility, same data discipline. These are the patterns to copy and the mistakes that get caught in review. ## Patterns to copy [Section titled “Patterns to copy”](#patterns-to-copy) ### Render lists from a live query [Section titled “Render lists from a live query”](#render-lists-from-a-live-query) Anything that shows a list of objects should re-render when those objects change — anywhere, on any device. Drive it from the live hook: ```tsx import { useVaultEntities } from "@brainstorm/react-yjs"; const { entities } = useVaultEntities(window.brainstorm.services.vaultEntities); const items = entities.filter((e) => e.type === MY_TYPE); ``` ### Ask for capabilities in context [Section titled “Ask for capabilities in context”](#ask-for-capabilities-in-context) Request a capability at the moment the feature is used, with a reason the user will see — not a wall of prompts on launch. ```ts await bs.services.capabilities.request( "network.connect:wss://relay.example.com", "to sync your board with the team", ); ``` ### Degrade when a grant is missing [Section titled “Degrade when a grant is missing”](#degrade-when-a-grant-is-missing) A denied or revoked capability is a normal state. Catch it and hide or disable the feature rather than throwing. ```ts try { render(await bs.services.search.query(q)); } catch (err) { if (err.name === "CapabilityDenied") return showHint("Grant search to use this."); throw err; } ``` ### Open the SDK before you build [Section titled “Open the SDK before you build”](#open-the-sdk-before-you-build) Need a menu, popover, picker, icon, date formatter, property cell, or empty state? It’s almost certainly in `@brainstorm/sdk`. Import it. See [SDK & runtime](/build/the-sdk/). ### Use the standard header [Section titled “Use the standard header”](#use-the-standard-header) Every app uses the shared `.app-header` chrome with `app-header__title` on the title and the overflow `⋯` menu last in `app-header__right`. Don’t restyle the header. ## Anti-patterns to avoid [Section titled “Anti-patterns to avoid”](#anti-patterns-to-avoid) ### Don’t hand-roll reactivity [Section titled “Don’t hand-roll reactivity”](#dont-hand-roll-reactivity) The single most common mistake. Reading the change signal yourself re-implements the reactivity layer per app and drifts. ```ts // ✗ rejected — per-app change loop service.onChange(() => setItems(service.list())); // ✓ the one reactivity stack const { entities } = useVaultEntities(service); ``` This is enforced in the shell repo. All live state flows through `@brainstorm/react-yjs`. ### Don’t build menus by hand [Section titled “Don’t build menus by hand”](#dont-build-menus-by-hand) A `
`, a native ``. A hand-built `
` standing in for a menu is rejected — it loses the shared keyboard model, anchoring, and accessibility. ## App chrome [Section titled “App chrome”](#app-chrome) The app theme stylesheet owns the header. Put this skeleton in every app and don’t re-declare its CSS: ```tsx

My App

{/* content actions and panel toggles first; the object ⋯ menu LAST */}
{/* your UI */}
``` The header is a fixed-height glass bar with platform-correct padding (macOS traffic lights, Windows controls) applied for you. Put `app-header__title` on your title element — don’t build your own title face. The overflow `⋯` menu, when you have one, is always the **last** element in `app-header__right`. ## Internationalization [Section titled “Internationalization”](#internationalization) Every user-visible string wraps in a translation call. Apps use the lightweight `createT` from `@brainstorm/sdk/i18n` (which does `{name}` interpolation only — no ICU). For plurals, use the shared `plural(t, count, "key.one", "key.other")` helper rather than a `count === 1 ?` branch in component code. Add new string ids to your app’s catalog; never put bare text in JSX. ## Next [Section titled “Next”](#next) * [Working with data](/build/working-with-data/) — the `entities`, `storage`, `intents`, and document APIs in practice. * [Recipes & anti-patterns](/build/recipes/) — the conventions that keep an app consistent with the platform. # Working with data > Read and write objects, sync collaborative documents, store app-private state, and integrate with other apps through intents. An app’s real work is data: reading and writing [objects](/concepts/objects/), syncing the documents behind them, keeping a little private state, and handing work to other apps. Brainstorm gives you four distinct stores, each for a different job — using the right one is most of getting data handling right. | Use | For | | ------------------- | ------------------------------------------------------------------------------- | | **Entities** | Shared, typed, synced objects — your app’s real content. | | **Documents (Yjs)** | The collaborative body of an object — rich text, structured fields edited live. | | **Storage** | App-private key/value state and uploaded files. | | **Settings** | Per-device UI state that should *not* sync (last-opened tab, panel widths). | ## Objects: the entities service [Section titled “Objects: the entities service”](#objects-the-entities-service) Objects are typed records in the vault. Create, read, update, delete, and query them through `services.entities`: ```ts const bs = window.brainstorm; // create — returns the new object const note = await bs.services.entities.create( "io.brainstorm.notes/Note/v1", { title: "Untitled", body: "", createdAt: Date.now(), updatedAt: Date.now() }, ); // read / update / delete by id const fetched = await bs.services.entities.get(note.id); await bs.services.entities.update(note.id, { title: "Renamed" }); await bs.services.entities.delete(note.id); // query — by type, predicate, text, with a limit const recent = await bs.services.entities.query({ type: "io.brainstorm.notes/Note/v1", limit: 50, }); ``` Each of these is gated by the matching [capability](/build/capabilities/): `entities.read:` to read, `entities.write:` to create, update, or delete. For anything that renders a list, prefer the **live** hook over one-shot `query` — it subscribes so the UI updates when objects change anywhere: ```tsx import { useVaultEntities } from "@brainstorm/react-yjs"; const { entities } = useVaultEntities(window.brainstorm.services.vaultEntities); const notes = entities.filter((e) => e.type === "io.brainstorm.notes/Note/v1"); ``` ## Documents: collaborative bodies [Section titled “Documents: collaborative bodies”](#documents-collaborative-bodies) An object’s *body* — rich text, or any field edited live and synced across devices and collaborators — lives in a Yjs document. Read and edit it through `@brainstorm/react-yjs` rather than the low-level sync calls: ```tsx import { useYDoc, useYMap, useYText } from "@brainstorm/react-yjs"; const doc = useYDoc(noteId); // the object's collaborative doc const props = useYMap(doc, "properties"); // structured fields const body = useYText(doc, "body"); // rich-text body ``` Edits made here merge cleanly with edits from other devices and users — that’s the CRDT layer doing its job. You mutate the shared types; the changes propagate. (The runtime exposes lower-level `entities.loadDoc` / `applyDoc` for advanced cases, but most apps never touch them.) ## App-private storage [Section titled “App-private storage”](#app-private-storage) For state that’s yours alone — caches, drafts, app preferences that *should* travel with the vault — use `services.storage`, gated by the default-granted `storage.kv`: ```ts await bs.services.storage.put("draft:" + id, text); const draft = await bs.services.storage.get("draft:" + id); const keys = await bs.services.storage.list("draft:"); await bs.services.storage.delete("draft:" + id); ``` To bring a file into the vault’s content-addressed store and get a URL back: ```ts const { url } = await bs.services.storage.uploadFile(name, bytes, mime); ``` ## Per-device settings [Section titled “Per-device settings”](#per-device-settings) State that should **not** sync — which tab was open, a panel’s width on this screen — goes in `services.settings`, not storage: ```ts await bs.services.settings.put("sidebar.width", 280); const width = await bs.services.settings.get("sidebar.width"); ``` The distinction matters: put device-local view state in `settings` and it won’t fight across machines; put real content there and it won’t follow the user. When unsure, ask “should this be the same on my laptop and my phone?” — yes means an entity or storage, no means settings. ## Files [Section titled “Files”](#files) Your app never sees filesystem paths. It asks the user to pick a file (or a save target), gets an opaque handle, and reads or writes through it: ```ts const handle = await bs.services.files.requestOpen({ mime: ["text/plain"] }); const bytes = await bs.services.files.read(handle); // … await bs.services.files.write(handle, newBytes); ``` Picking requires a user gesture; writing requires `files.write`. When your app is launched *as an opener* for a file (via a manifest [opener](/build/the-manifest/#registrations--plugging-into-the-shell)), the file arrives in your `launch` context. ## Talking to other apps [Section titled “Talking to other apps”](#talking-to-other-apps) Apps compose through **intents** — structured requests dispatched by verb, handled by whichever app registered for it. Your app dispatches without knowing or naming the handler: ```ts await bs.services.intents.dispatch({ verb: "open", payload: { entityId: someId }, source: bs.app.id, }); ``` Dispatching `open` is default-granted; other verbs are gated by `intents.dispatch:`. To *receive* intents, register a handler in your [manifest](/build/the-manifest/#registrations--plugging-into-the-shell) and listen: ```ts bs.on("intent", (intent) => { if (intent.verb === "open") openObject(intent.payload.entityId); }); ``` This is how the whole workspace stays connected: a note links to a task, clicking it dispatches `open`, and Tasks handles it — no app hard-codes another. ## Next [Section titled “Next”](#next) * [Recipes & anti-patterns](/build/recipes/) — patterns to copy and mistakes to avoid. * [SDK & runtime](/build/the-sdk/) — the full service surface and component library. # Your first app > Scaffold a Brainstorm app, run it in the shell, and see a live list of your own objects. This walkthrough scaffolds a working app, runs it in the shell, and shows it rendering a live list of objects from your vault. It takes about ten minutes. Note Apps are currently built inside the Brainstorm shell source tree — the same place the first-party apps live. A standalone SDK package and a third-party publishing flow are on the roadmap; until then, “building an app” means working in the shell repo. The app model and SDK shown here are stable and carry forward unchanged. ## Scaffold [Section titled “Scaffold”](#scaffold) From the shell repo, the scaffold generates a complete, compliant React app: ```sh bun run new-app field-notes "Field Notes" ``` The first argument is the app id (kebab-case); the second is the display name. You get: ```plaintext apps/field-notes/ ├── manifest.json # the app declaration ├── package.json # deps: @brainstorm/sdk, @brainstorm/react-yjs, react ├── tsconfig.json ├── vite.config.ts ├── icon.svg # generated from the app's initials └── src/ ├── index.html # entry document (ships a strict Content-Security-Policy) ├── main.tsx # React root mount ├── app.tsx # your root component — a live entity list ├── runtime.ts # type-safe accessor for window.brainstorm └── styles.css # app styles, themed from the SDK ``` The scaffold is deliberately not a blank page — it mounts a real `useVaultEntities` list and the standard header chrome, so you start from a compliant app rather than retrofitting the conventions later. ## What the scaffold gives you [Section titled “What the scaffold gives you”](#what-the-scaffold-gives-you) **`manifest.json`** declares the app and the one object type it owns: ```json { "id": "io.brainstorm.field-notes", "name": "Field Notes", "version": "0.1.0", "sdk": "1", "entry": "dist/index.html", "icon": "icon.svg", "capabilities": [ "storage.kv", "entities.read:*", "entities.write:io.brainstorm.field-notes/Item/v1" ], "registrations": { "entityTypes": [ { "id": "io.brainstorm.field-notes/Item/v1", "schema": { "type": "object", "required": ["id", "title", "createdAt", "updatedAt"] } } ] } } ``` See [The manifest](/build/the-manifest/) for every field and [Capabilities](/build/capabilities/) for what those capability strings mean. **`src/main.tsx`** mounts React. Two imports are mandatory and come first — the app-theme stylesheet (which carries the shared `.app-header` chrome and theme tokens) and the menu host: ```tsx import "@brainstorm/sdk/app-theme.css"; import { mountMenuHost } from "@brainstorm/sdk/menus"; import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { FieldNotesApp } from "./app"; import "./styles.css"; const root = document.getElementById("root"); if (!root) throw new Error("field-notes: #root not found"); mountMenuHost(); createRoot(root).render( , ); ``` **`src/app.tsx`** is your UI. The scaffold renders a live, reactive list of your own object type: ```tsx import { useVaultEntities } from "@brainstorm/react-yjs"; import { useMemo } from "react"; import { getBrainstorm } from "./runtime"; const APP_TYPE = "io.brainstorm.field-notes/Item/v1"; export function FieldNotesApp() { const service = getBrainstorm()?.services?.vaultEntities ?? null; const { entities } = useVaultEntities(service); const items = useMemo( () => entities.filter((e) => e.type === APP_TYPE), [entities], ); return (

Field Notes

{items.length === 0 ? (

Nothing here yet.

) : (
    {items.map((item) => (
  • {String(item.properties.title ?? item.id)}
  • ))}
)}
); } ``` The list is **live**: `useVaultEntities` subscribes to the vault, so when an object of this type is created or changed — by your app, another app, or another device — the list re-renders. You never write a manual `onChange → setState` loop; that’s [the reactivity rule](/build/recipes/#use-the-reactivity-layer). ## Register and run [Section titled “Register and run”](#register-and-run) A new app is registered with the shell so the dev seeder installs it on launch (add it to the first-party app list, per the repo’s contributor guide). Then: ```sh bun run dev ``` The shell rebuilds and reinstalls first-party apps on boot, so a **full shell restart** is what deploys your changes — reloading a window serves the previous build. You’ll see your app in the launcher; open it and it renders the (empty) list. Tip Each app logs `[app:] build ` in its own DevTools console and the shell logs `[shell] launch … build `. If you think a change didn’t take, check those shas match — a stale sha means the shell wasn’t restarted. ## Make it do something [Section titled “Make it do something”](#make-it-do-something) Create an object of your type from the app, and watch the list update itself: ```tsx const bs = getBrainstorm(); await bs.services.entities.create(APP_TYPE, { title: "First field note", createdAt: Date.now(), updatedAt: Date.now(), }); ``` No refresh, no refetch — the live query already subscribed to this type re-renders. From here: * [Working with data](/build/working-with-data/) — querying, editing, rich text, and app-private storage. * [SDK & runtime](/build/the-sdk/) — the components and services you build the rest of the UI from. * [Recipes & anti-patterns](/build/recipes/) — the conventions that keep an app consistent with the platform. # Apps & permissions > Every app runs sandboxed behind a capability ledger and can only touch what you explicitly allow. Brainstorm is built entirely out of **apps**, and every app runs **sandboxed**. An app can’t reach your data, your network, or another app on its own — it can only do what you’ve granted it through the **capability ledger**. ## The capability model [Section titled “The capability model”](#the-capability-model) A capability is a specific, narrow permission: *read notes*, *write files*, *reach this one network host*, *show a notification*. Apps declare the capabilities they need; you grant or deny them. Two principles make this trustworthy: * **Nothing is ambient.** There is no “just let the app do anything.” Every sensitive action maps to a capability that was granted for a reason. * **It fails closed.** If a permission check can’t be satisfied — or anything goes wrong evaluating it — the action is denied, never silently allowed. Because access is explicit and revocable, it’s safe to run third-party apps, and later autonomous AI agents, over even your most important data. ## Granting and revoking [Section titled “Granting and revoking”](#granting-and-revoking) When an app first needs a capability, Brainstorm asks. You can: * **Grant** it, optionally scoped (for example, to a single kind of object). * **Deny** it — the app keeps working, minus that ability. * **Revoke** it later from the vault’s permission settings. Grants are recorded per vault, so an app you trust in your work vault has no standing in your personal vault. ## Isolation between apps [Section titled “Isolation between apps”](#isolation-between-apps) Apps are isolated from each other as well as from the system. One app can’t read another app’s private state or reach into its window. When apps do share data, it’s through the common object layer you can see and control — not through back channels. See [Objects](/concepts/objects/). ## Agents are apps too [Section titled “Agents are apps too”](#agents-are-apps-too) AI agents in Brainstorm sit behind the same ledger. An agent operates under a ceiling of capabilities you set; it can never grant itself more access than you’ve allowed. The permission model that keeps apps honest is the same one that governs automation. ## Next steps [Section titled “Next steps”](#next-steps) * [Objects](/concepts/objects/) — the shared data apps read and write * [Your data & security](/concepts/your-data-and-security/) — the guarantees underneath # Local-first & sync > Brainstorm works fully offline on your own disk, and syncs across devices with end-to-end encryption through a relay that can't read your data. Brainstorm is **local-first**: your vault is on your disk, the app reads and writes it directly, and nothing about your own content requires a server. Sync is an option you turn on — not a dependency you depend on. ## Local-first, in practice [Section titled “Local-first, in practice”](#local-first-in-practice) * **Instant.** Opening a vault and editing objects is local disk speed — no round-trips. * **Offline by default.** Everything works with no network at all. You’re never blocked by a server being down or unreachable. * **Durable.** Your data is plain files you own. If you stopped using Brainstorm tomorrow, your vault is still right there on disk. ## Conflict-free editing with CRDTs [Section titled “Conflict-free editing with CRDTs”](#conflict-free-editing-with-crdts) Brainstorm stores editable content as **CRDTs** (via [Yjs](https://yjs.dev)). A CRDT lets two devices — or two people — edit the same object at the same time and merge the results automatically, with no “which version wins?” dialog. This is what makes offline edits and real-time collaboration both work without losing changes. ## Sync that can’t read your data [Section titled “Sync that can’t read your data”](#sync-that-cant-read-your-data) When you enable sync, Brainstorm connects your devices through a **relay** — but the relay is *blind*: * Your changes are **end-to-end encrypted** on your device before they’re sent. * The relay only stores and forwards encrypted CRDT traffic. It never holds your keys and cannot read your content. * The sync server is **self-hostable** if you’d rather run your own. So you get multi-device sync and collaboration without handing your knowledge to a third party. ## Restoring a device [Section titled “Restoring a device”](#restoring-a-device) Because the encrypted history lives on the relay (or your own server), setting up a new device restores your vault from sync — you authenticate, and your objects rebuild locally from the encrypted stream. ## Next steps [Section titled “Next steps”](#next-steps) * [Your data & security](/concepts/your-data-and-security/) — keys, identity, and the threat model * [Vaults](/concepts/vaults/) — the thing being synced # Objects > Everything in a vault is an object with typed properties, shared across every app rather than locked inside one. Everything you create in Brainstorm is an **object**: a note, a task, a contact, a file, a calendar event. Objects are the shared substance of a vault — apps are just different ways of looking at them. ## One object, many views [Section titled “One object, many views”](#one-object-many-views) An object isn’t trapped in the app that made it. A task you create in a database can show up on the calendar, appear as a node in the graph, and be linked from a note — because all of those apps read and write the **same** object layer. This is what makes Brainstorm feel connected rather than like a folder of disconnected tools: there’s one shared space of objects, and apps are lenses over it. ## Typed properties [Section titled “Typed properties”](#typed-properties) Objects carry **properties** — typed fields like text, number, date, checkbox, link, or a value drawn from a defined set. Properties are defined at the vault level, so the meaning of “Status” or “Due date” is consistent across every app that touches an object. Anything about an object that isn’t its main body is a property, edited through a real, shared property system rather than ad-hoc fields per app. ## Links and relationships [Section titled “Links and relationships”](#links-and-relationships) Objects relate to each other: * **Mentions** — type `@` in rich text to link to any object. The link is real and bidirectional, so you can see everything that references a given object. * **Collections** — group objects into typed sets (a reading list, a project’s tasks) without copying them. The [Graph](/apps/graph/) app visualizes these relationships directly. ## Built on Block Protocol [Section titled “Built on Block Protocol”](#built-on-block-protocol) Under the hood, objects follow the **Block Protocol** — an open standard for typed, interoperable data. That keeps your content structured and portable rather than locked to a proprietary format, and it’s why blocks and data can move cleanly between apps. ## Next steps [Section titled “Next steps”](#next-steps) * [Apps](/apps/) — the lenses you use to work with objects * [Local-first & sync](/concepts/local-first-and-sync/) — how objects stay consistent across devices # Vaults > A vault is the on-disk home for your knowledge — a folder of files you own, protected by a key only you hold. A **vault** is where your knowledge lives. It’s a folder on your own disk — not a row in someone else’s database — and it’s the unit Brainstorm opens, protects, and (optionally) syncs. ## What’s in a vault [Section titled “What’s in a vault”](#whats-in-a-vault) A vault holds everything for one body of work: * **Your objects** — notes, database rows, files, tasks, and anything else your apps create. * **The apps you’ve installed** into that vault and the **permissions** you’ve granted them. * **Your identity** for that vault — a cryptographic key that signs your changes, so collaborators can verify who wrote what. Different bodies of work can live in different vaults — for example, a personal vault and a work vault — each with its own apps, permissions, and sync settings. ## How a vault is protected [Section titled “How a vault is protected”](#how-a-vault-is-protected) When you create a vault you choose how its key is stored: * **System keychain** — the master key lives in your operating system’s secure keychain and the vault unlocks when you log in. * **Passphrase** — you supply a passphrase to derive the key. Without it, the vault can’t be opened. The master key never leaves your machine in plaintext and is held in memory only while the vault is open. See [Your data & security](/concepts/your-data-and-security/). ## Opening and closing [Section titled “Opening and closing”](#opening-and-closing) Only one vault is “active” at a time. Opening a vault loads its data and makes its apps available; closing it releases the key from memory. Switching vaults is instant and never mixes data between them — cross-vault isolation is a hard boundary. ## Next steps [Section titled “Next steps”](#next-steps) * [Apps & permissions](/concepts/apps-and-permissions/) — how apps get scoped access to a vault * [Local-first & sync](/concepts/local-first-and-sync/) — putting one vault on many devices # Your data & security > How Brainstorm protects your vault — encryption, a key only you hold, a signed identity, and a sandbox that fails closed. Brainstorm’s security model exists so you can run apps and agents over your most important knowledge without giving anything ambient access to it. ## A key only you hold [Section titled “A key only you hold”](#a-key-only-you-hold) Each vault is protected by a **master key** that never leaves your machine in plaintext. You choose where it’s stored: * in your **operating system keychain**, or * derived from a **passphrase** you supply. The key is held in memory only while the vault is open and is wiped when you close it. There’s no Brainstorm account that can unlock your vault for you — and equally, no one else can. ## Your identity [Section titled “Your identity”](#your-identity) Each vault carries a cryptographic **identity** — a keypair that signs the changes you make. Collaborators can verify that an edit genuinely came from you, and your private signing key never crosses an app boundary or leaves the device. ## The sandbox and the ledger [Section titled “The sandbox and the ledger”](#the-sandbox-and-the-ledger) Apps are sandboxed and isolated from each other and the system. Everything sensitive an app can do is mediated by the [capability ledger](/concepts/apps-and-permissions/), which **fails closed**: if a permission can’t be confirmed, the action is denied. There’s no path by which an app quietly gains access you didn’t grant. ## Encryption at rest and in transit [Section titled “Encryption at rest and in transit”](#encryption-at-rest-and-in-transit) * **In transit:** when you sync, content is end-to-end encrypted before leaving your device; the relay can’t read it. See [Local-first & sync](/concepts/local-first-and-sync/). * **At rest:** your vault is stored locally under your control, protected by your master key. ## What Brainstorm does *not* do [Section titled “What Brainstorm does not do”](#what-brainstorm-does-not-do) * It does not phone your content home. There is no server that holds your vault. * It does not give apps blanket access “to be convenient.” * It does not lock your data in a proprietary format — your knowledge is structured, portable, and yours. ## Next steps [Section titled “Next steps”](#next-steps) * [Apps & permissions](/concepts/apps-and-permissions/) — the capability model in detail * [Vaults](/concepts/vaults/) — how a vault is created and protected # Install > How to get Brainstorm running on macOS, Windows, and Linux. Brainstorm is a desktop application for **macOS, Windows, and Linux**. Private beta Brainstorm is in private beta ahead of its public release. Downloads are gated to waitlist members. [Join the waitlist at getbrainstorm.online](https://getbrainstorm.online) — you’ll get a download link and a short setup walkthrough when your invite lands. ## System requirements [Section titled “System requirements”](#system-requirements) * **macOS** 12 (Monterey) or later — Apple Silicon and Intel. * **Windows** 10 or later (64-bit). * **Linux** — a recent 64-bit distribution (AppImage / `.deb`). * \~400 MB of disk for the app, plus whatever your vaults hold. ## Installing [Section titled “Installing”](#installing) Once you have a download link: 1. **macOS** — open the `.dmg` and drag Brainstorm to Applications. On first launch, right-click → Open to clear Gatekeeper. 2. **Windows** — run the installer and follow the prompts. 3. **Linux** — mark the AppImage executable (`chmod +x`) and run it, or install the `.deb` with your package manager. ## First launch [Section titled “First launch”](#first-launch) On first launch Brainstorm asks you to **create a vault** — the on-disk home for your knowledge. Pick a folder, choose how to protect it (system keychain or a passphrase), and you’re in. The full walkthrough is in the [Quickstart](/start-here/quickstart/). ## Updating [Section titled “Updating”](#updating) Apps inside Brainstorm update independently of the shell. The shell itself checks for updates on launch and applies them in the background; your vaults are never touched by an update. ## Next steps [Section titled “Next steps”](#next-steps) * [Quickstart](/start-here/quickstart/) — your first vault and app * [Vaults](/concepts/vaults/) — what a vault is and how it’s protected # Quickstart > Create a vault, open your first app, and capture your first note in Brainstorm. This walkthrough takes about five minutes. It assumes Brainstorm is [installed](/start-here/install/). ## 1. Create a vault [Section titled “1. Create a vault”](#1-create-a-vault) On first launch, Brainstorm asks where your knowledge should live. 1. Click **Create vault**. 2. Choose an empty folder on your disk. 3. Choose how to protect it: * **System keychain** (recommended) — Brainstorm stores the key in your OS keychain; the vault unlocks automatically when you log in. * **Passphrase** — you type a passphrase to unlock. Nothing else can open the vault. 4. Give the vault a name and confirm. Your vault is now a folder of files you fully own. See [Vaults](/concepts/vaults/) for what’s inside. ## 2. Open an app [Section titled “2. Open an app”](#2-open-an-app) Brainstorm opens to a dashboard. Everything you do happens inside an **app**. 1. Open the launcher. 2. Pick **Notes**. 3. The app opens in its own window, sandboxed and scoped to only the data it’s allowed to touch. The first time an app needs a new capability (for example, reading a different kind of object), Brainstorm asks you to grant it. You can review and revoke these grants any time — see [Apps & permissions](/concepts/apps-and-permissions/). ## 3. Capture something [Section titled “3. Capture something”](#3-capture-something) In Notes: * Start typing to create a note. * Use rich text — headings, lists, checkboxes, code. * Type `@` to link to another object in your vault, or `/` for a command menu. Everything you write is saved to your vault on disk, immediately and offline. ## 4. Connect your knowledge [Section titled “4. Connect your knowledge”](#4-connect-your-knowledge) Brainstorm’s value comes from objects relating to each other: * Open **Database** to make a structured table — tasks, contacts, reading list — with typed properties. * Open **Graph** to see how your notes and objects link together. * Open **Files** to bring existing documents into the vault. The same object can appear in many apps; they’re all views over one shared data layer. See [Objects](/concepts/objects/). ## 5. (Optional) Sync across devices [Section titled “5. (Optional) Sync across devices”](#5-optional-sync-across-devices) If you want your vault on more than one machine, enable sync. Your data is end-to-end encrypted before it leaves your device, and the relay that forwards it can’t read it. See [Local-first & sync](/concepts/local-first-and-sync/). ## Where to go next [Section titled “Where to go next”](#where-to-go-next) * [Concepts](/concepts/vaults/) — the model behind everything you just did * [Apps](/apps/) — what each built-in app does # What is Brainstorm? > Brainstorm is a local-first, AI-native operating system for knowledge work — a desktop shell that hosts sandboxed apps over your own data. Brainstorm is a **local-first, AI-native operating system for knowledge work**. It looks and behaves like a desktop OS — a shell that hosts small, focused apps — except the “computer” is your knowledge, and everything runs on your own machine. Three ideas define it: ## Apps, not features [Section titled “Apps, not features”](#apps-not-features) The shell itself does almost nothing. It hosts **apps**: Notes, Database, Files, Graph, a calendar, a code editor, and more. You add the ones you want and ignore the rest. Each app is sandboxed and updates on its own, so the product grows without turning into a single sprawling monolith. ## Your data, your disk [Section titled “Your data, your disk”](#your-data-your-disk) Your knowledge lives in a **vault** — a folder of files on your own disk, not a row in someone else’s database. Brainstorm is local-first: it works fully offline, opens instantly, and never requires a server to read or write your own content. When you choose to sync across devices, traffic is end-to-end encrypted and the relay never sees your data. See [Local-first & sync](/concepts/local-first-and-sync/). ## Permissions you grant [Section titled “Permissions you grant”](#permissions-you-grant) Every app and every AI agent runs behind a **capability ledger**. An app can only touch the data and services you have explicitly allowed — reading a note, saving a file, reaching the network. Nothing is ambient. This is what makes it safe to run third-party apps and autonomous agents over your most important data. See [Apps & permissions](/concepts/apps-and-permissions/). ## Built on open foundations [Section titled “Built on open foundations”](#built-on-open-foundations) Brainstorm is built on open building blocks rather than a proprietary format: * **Block Protocol** for interoperable, typed data. * **Yjs** (CRDTs) for conflict-free, real-time collaboration and offline editing. * **Lexical** for rich text. That means your content is structured, portable, and not locked to one vendor. Note Brainstorm is in active development ahead of its public beta. Some features described in these docs are still rolling out. [Join the waitlist](https://getbrainstorm.online) to get early access. ## Next steps [Section titled “Next steps”](#next-steps) * [Install Brainstorm](/start-here/install/) * [Quickstart](/start-here/quickstart/) — create a vault and open your first app * [Concepts](/concepts/vaults/) — the model behind the product