Skip to content

Schema Reference

The schema file defines your vault’s type system: what kinds of notes exist, what fields they have, and how they relate to each other.

For conceptual overview, see Schema and Types and Inheritance.

The schema lives at .bwrb/schema.json in your vault root:

my-vault/
├── .bwrb/
│ └── schema.json # Your schema definition
├── Ideas/
├── Objectives/
└── ...
{
"$schema": "https://bwrb.dev/schema.schema.json",
"version": 2,
"schemaVersion": "1.0.0",
"types": { ... },
"config": { ... },
"audit": { ... }
}
PropertyTypeRequiredDescription
$schemastringNoJSON Schema URI for editor validation
versionintegerNoSchema format version (default: 2)
schemaVersionstringNoUser-controlled version for migrations (semver)
typesobjectYesType definitions
configobjectNoVault-wide settings
auditobjectNoAudit command configuration

Types define categories of notes. Each type has a name (the object key) and a definition.

{
"types": {
"idea": {
"fields": {
"status": { "prompt": "select", "options": ["raw", "developing", "mature"] }
}
}
}
}
PropertyTypeDefaultDescription
extendsstring"meta"Parent type name
fieldsobject{}Field definitions
field_orderarrayOrder of fields in frontmatter
body_sectionsarrayBody structure after frontmatter
recursivebooleanfalseWhether type can contain instances of itself
pluralstringautoCustom plural for folder naming (e.g., "research" instead of "researchs")

All types inherit from meta (implicitly created if not defined). Types form a single-inheritance tree:

{
"types": {
"meta": {
"fields": {
"status": { "prompt": "select", "options": ["raw", "active", "done"] },
"created": { "value": "$NOW" }
}
},
"objective": {
"extends": "meta",
"fields": {
"deadline": { "prompt": "date" }
}
},
"task": {
"extends": "objective",
"fields": {
"status": { "default": "inbox" },
"assignee": { "prompt": "relation", "source": "person" }
}
}
}
}

A task inherits:

  • status and created from meta
  • deadline from objective
  • Adds assignee, overrides status default to "inbox"

Inheritance rules:

  • Type names must be unique across the entire schema
  • No cycles allowed (a type cannot extend its own descendant)
  • Child types can only override default values, not field structure

Types with recursive: true can have a parent field pointing to the same type:

{
"task": {
"extends": "objective",
"recursive": true,
"fields": {
"parent": {
"prompt": "relation",
"source": "task"
}
}
}
}

This enables subtasks, nested chapters, etc. Cycles are prevented—a note cannot be its own ancestor.


Fields define the frontmatter properties of a note. Each field has a name (the object key) and a definition specifying how values are collected and stored.

TypePromptStored AsUse Case
Staticas definedFixed values, computed dates
textSingle-line inputstringNames, descriptions
numberNumeric inputnumberPriority, counts
booleanY/n confirmtrue/falseFlags, toggles
dateDate inputstring (YYYY-MM-DD)Deadlines, dates
selectPicker from optionsstring or string[]Status, category
relationPicker from vaultstring (wikilink)Links to other notes
listComma-separated inputstring[]Tags, aliases

Fields with value are not prompted—they’re computed automatically:

{
"type": { "value": "task" },
"created": { "value": "$NOW" },
"date": { "value": "$TODAY" }
}

Special values:

  • $NOW — Current datetime: 2025-01-07 14:30
  • $TODAY — Current date: 2025-01-07

Free-form single-line input.

{
"description": {
"prompt": "text",
"label": "Brief description",
"required": false
}
}

Numeric input with validation.

{
"priority": {
"prompt": "number",
"default": "3"
}
}

Yes/no confirmation prompt.

{
"archived": {
"prompt": "boolean",
"default": "false"
}
}

Stored as true or false (YAML booleans).

Date input with YYYY-MM-DD format.

{
"deadline": {
"prompt": "date",
"required": false
}
}

Choose from predefined options.

{
"status": {
"prompt": "select",
"options": ["raw", "inbox", "in-flight", "done", "dropped"],
"default": "raw",
"required": true
}
}

For multi-select (array output):

{
"tags": {
"prompt": "select",
"options": ["urgent", "blocked", "waiting", "review"],
"multiple": true
}
}

Link to other notes in the vault. Shows a picker filtered by type.

{
"milestone": {
"prompt": "relation",
"source": "milestone",
"required": false
}
}

Source options:

  • Specific type: "source": "milestone" — only milestones
  • Type branch: "source": "objective" — objectives and all descendants (task, milestone, project, etc.)
  • Any note: "source": "any" — entire vault

Filtering results:

{
"milestone": {
"prompt": "relation",
"source": "milestone",
"filter": {
"status": { "not_in": ["done", "dropped"] }
}
}
}

Filter conditions:

  • equals: Field must equal value
  • not_equals: Field must not equal value
  • in: Field must be one of values
  • not_in: Field must not be one of values

Multiple relations:

{
"related": {
"prompt": "relation",
"source": "any",
"multiple": true
}
}

Owned relations:

When owned: true, referenced notes are private to the parent and colocate in the parent’s folder:

{
"chapters": {
"prompt": "relation",
"source": "chapter",
"multiple": true,
"owned": true
}
}

Owned notes:

  • Live in the owner’s subfolder (e.g., drafts/My Novel/chapters/)
  • Cannot be referenced by other notes’ frontmatter fields
  • Are still discoverable via bwrb list and bwrb search

Comma-separated input stored as an array.

{
"aliases": {
"prompt": "list",
"label": "Aliases (comma-separated)"
}
}

Output format controlled by list_format:

  • yaml-array (default): ["one", "two", "three"]
  • comma-separated: "one, two, three"

Complete list of field properties:

PropertyTypeApplies ToDescription
valuestringstaticFixed value (mutually exclusive with prompt)
promptstringpromptedPrompt type: text, number, boolean, date, select, relation, list
labelstringpromptedCustom label shown during prompting
requiredbooleanpromptedWhether field must have a value (default: false)
defaultstringpromptedDefault value if user skips prompt
optionsarrayselectAllowed values for selection
multiplebooleanselect, relationAllow multiple values (default: false)
sourcestringrelationType name to filter picker, or "any"
filterobjectrelationFilter conditions for source query
ownedbooleanrelationWhether referenced notes are owned/colocated (default: false)
list_formatstringlistOutput format: yaml-array or comma-separated

Define document structure after frontmatter:

{
"body_sections": [
{
"title": "Description",
"level": 2,
"content_type": "paragraphs"
},
{
"title": "Steps",
"level": 2,
"content_type": "checkboxes",
"prompt": "list",
"prompt_label": "Steps (comma-separated)"
},
{
"title": "Notes",
"level": 2,
"content_type": "bullets",
"children": [
{ "title": "Blockers", "level": 3 }
]
}
]
}
PropertyTypeRequiredDescription
titlestringYesSection heading text
levelintegerNoHeading level 2-6 (default: 2)
content_typestringNoPlaceholder type: none, paragraphs, bullets, checkboxes
promptstringNoIf "list", prompts for initial content during creation
prompt_labelstringNoLabel for the content prompt
childrenarrayNoNested subsections

Vault-wide settings:

{
"config": {
"link_format": "wikilink",
"open_with": "obsidian",
"editor": "nvim",
"visual": "code",
"obsidian_vault": "My Vault"
}
}
PropertyTypeDefaultDescription
link_formatstring"wikilink"Link format for relations: wikilink ([[Note]]) or markdown ([Note](Note.md))
open_withstring"visual"Default for --open: editor, visual, or obsidian
editorstring$EDITORTerminal editor command
visualstring$VISUALGUI editor command
obsidian_vaultstringautoObsidian vault name for URI scheme

Configure the bwrb audit command:

{
"audit": {
"ignored_directories": ["Archive", ".obsidian", "Templates"],
"allowed_extra_fields": ["aliases", "cssclass", "publish"]
}
}
PropertyTypeDescription
ignored_directoriesarrayDirectories to skip during audit
allowed_extra_fieldsarrayExtra frontmatter fields that won’t trigger warnings

Add $schema to your schema file for editor autocomplete and validation:

{
"$schema": "https://bwrb.dev/schema.schema.json",
"types": { ... }
}

If the URL isn’t reachable, configure the schema manually in .vscode/settings.json:

{
"json.schemas": [
{
"fileMatch": ["**/.bwrb/schema.json"],
"url": "./node_modules/bwrb/schema.schema.json"
}
]
}

Or reference a local copy of schema.schema.json from the bwrb repository.

With nvim-lspconfig and jsonls:

require('lspconfig').jsonls.setup({
settings = {
json = {
schemas = {
{
fileMatch = { "*/.bwrb/schema.json" },
url = "https://bwrb.dev/schema.schema.json"
}
}
}
}
})

A full schema demonstrating inheritance, relations, body sections, and config:

{
"$schema": "https://bwrb.dev/schema.schema.json",
"version": 2,
"schemaVersion": "1.0.0",
"config": {
"link_format": "wikilink",
"open_with": "obsidian"
},
"audit": {
"ignored_directories": [".obsidian", "Templates"],
"allowed_extra_fields": ["aliases", "cssclass"]
},
"types": {
"meta": {
"fields": {
"status": {
"prompt": "select",
"options": ["raw", "active", "settled", "dropped"],
"default": "raw"
},
"created": { "value": "$NOW" }
}
},
"idea": {
"fields": {
"tags": {
"prompt": "select",
"options": ["shower-thought", "research", "project-idea"],
"multiple": true
}
},
"body_sections": [
{ "title": "Description", "level": 2, "content_type": "paragraphs" }
]
},
"objective": {
"fields": {
"deadline": { "prompt": "date" }
}
},
"task": {
"extends": "objective",
"recursive": true,
"fields": {
"status": { "default": "inbox" },
"priority": {
"prompt": "select",
"options": ["low", "medium", "high"],
"default": "medium"
},
"milestone": {
"prompt": "relation",
"source": "milestone",
"filter": {
"status": { "not_in": ["settled", "dropped"] }
}
},
"parent": {
"prompt": "relation",
"source": "task"
}
},
"body_sections": [
{
"title": "Steps",
"level": 2,
"content_type": "checkboxes",
"prompt": "list",
"prompt_label": "Steps (comma-separated)"
},
{ "title": "Notes", "level": 2, "content_type": "bullets" }
]
},
"milestone": {
"extends": "objective",
"fields": {
"project": {
"prompt": "relation",
"source": "project"
}
}
},
"project": {
"extends": "objective"
},
"draft": {
"fields": {
"draft-status": {
"prompt": "select",
"options": ["idea", "outlining", "drafting", "revising", "done"],
"default": "idea"
},
"chapters": {
"prompt": "relation",
"source": "chapter",
"multiple": true,
"owned": true
}
}
},
"chapter": {
"extends": "draft",
"recursive": true,
"fields": {
"word-count": { "prompt": "number" }
}
},
"person": {
"fields": {
"email": { "prompt": "text" },
"company": { "prompt": "text" }
}
}
}
}