| name | obsidian-frontmatter-sync |
| description | Manage Obsidian vault frontmatter via the rematter CLI to validate schemas, sync to external destinations (Astro, etc.), rename fields, and manage filenames. Use for bulk frontmatter operations across an Obsidian vault or any collection of markdown with frontmatter. |
Obsidian Frontmatter Sync with rematter
rematter is a CLI tool for transforming and syncing Obsidian vault frontmatter.
Quick Start
uv tool install rematter
brew install g15r/tap/rematter
uv tool upgrade rematter
brew upgrade rematter
uv tool install rematter --reinstall
rematter validate ~/vault/sky
rematter sync ~/vault/sky --dest ~/site/src/content/sky
rematter sync -n ~/vault/sky
Config File (.rematter.yaml)
Lives in the vault subdirectory being operated on. Combines sync config and frontmatter schema in one file.
link_path_prefix: /sky
dest: ~/dev/my-site/src/content/sky/
ignore:
- draft-*
- private/*
media:
source: _media
dest: src/assets
link_prefix: /assets
properties:
status:
type: string
required: false
enum: [not_started, in_progress, on_hold, done, cancelled]
default: not_started
creators:
type: list
required: false
own:
type: bool
required: false
default: false
sync: false
hero:
type: string
required: false
requires: [heroAlt]
heroAlt:
type: string
required: false
requires: [hero]
created:
type: timestamp
required: true
default: "%Y-%m-%d %H:%M"
sync: false
modified:
type: timestamp
required: true
default: "%Y-%m-%d %H:%M"
synced:
type: timestamp
required: true
default: null
publish:
type: bool
required: true
default: false
sync: false
Property Spec Fields
| Field | Purpose |
|---|
type | timestamp, bool, string, list, int, float |
required | Key must exist (null is valid — e.g. synced: null before first sync) |
default | Value set by --fix when missing. strftime string for timestamps, literal for others, null for explicit null |
enum | Allowed values (string fields) |
requires | Companion fields that must also have values (co-dependency) |
sync | true (default) or false — when false, field is recognized but stripped from dest output |
Commands
validate — Check frontmatter against schema
rematter validate <directory> [--schema PATH] [--fix] [--recursive] [--dry-run]
- Report-only by default, exits 1 on failures
--fix sets defaults for missing properties and reorders keys to match schema order
--fix + --dry-run previews what would change
- All properties must be declared in schema — unrecognized keys always error
sync — Sync vault markdown to an external destination
rematter sync <source> [--dest PATH] [--link-path-prefix PREFIX] [--dry-run]
Pipeline per file:
- Skip files where
publish is not true
- Slugify filename for dest (
Publishable Book.md → publishable-book.md)
- Skip if dest has same
modified value (no changes)
- Extract type from capitalized Obsidian tags (
#Book → type: book)
- Validate against schema
- Resolve creator wikilinks to
{name, slug} objects
- Resolve body wikilinks to markdown links (broken links → plain text)
- Resolve media references (wikilink and markdown image syntax)
- Rewrite hero image path if media config present
- Stamp
synced timestamp, set title from source filename
- Strip
sync: false fields from dest
- Write dest file, copy referenced media, stamp
synced back on source
Config keys (dest, link_path_prefix) can come from .rematter.yaml or CLI flags. CLI always wins. Config is required for sync.
filename — Prepend date to filenames
rematter filename <directory> [--field DATE_FIELD] [--recursive] [--dry-run]
Reads a date field (default: Date), prepends YYYY-MM-DD - to the filename, and removes the field from frontmatter. Already-prefixed files are skipped.
transform — Rename a frontmatter field
rematter transform <directory> --field OLD --to NEW [--recursive] [--dry-run]
Renames a field across all markdown files. Key order preserved. Skips files where the target name already exists.
Key Behaviors
- Wikilink resolution:
[[Target]] and [[Target|Label]] resolve to markdown links for known files (source + dest corpus). Broken links become plain text. Image refs (![[img.png]]) are handled separately and never mangled.
- Media sync: When
media config is present, ![[img.png]] and  refs are rewritten with the dest link prefix. Only referenced files are copied, not the entire media directory.
- Ignore patterns:
ignore list in config uses glob patterns matched against both filename and relative path.
- Timestamp format: Always
YYYY-MM-DD HH:MM (space separator, no seconds) to match Obsidian's native format.
- Type tags: Capitalized Obsidian tags (
#Book, #Film) are extracted as the type field. Multiple capitalized tags → skip with warning. Lowercase tags are content, not types.