Skip to main content

Frontmatter transformation tool for Obsidian vaults

Project description

rematter

Frontmatter management CLI for Obsidian vaults. Validate metadata against a schema, auto-fix missing fields, sync markdown to external destinations like Astro content collections, rename fields, and prepend dates to filenames -- all async with parallel threads for great performance on large vaults. Every command comes with dry-run support to preview the operations, your notes are precious, and we value that! We're Obsidian weirdos too.

The tool is still very early, there is much more to come.

Install

The easiest way to install if you're a Python user is via uv, but there's also a compiled binary (via PyInstaller) available on Homebrew for macOS and Linux:

# uv (recommended)
uv tool install rematter

# Homebrew
brew install g15r/tap/rematter

Quick start

# Validate frontmatter against a schema
rematter validate ~/vault/notes

# Auto-fix missing fields with defaults
rematter validate ~/vault/notes --fix

# Sync to an Astro content collection
rematter sync ~/vault/notes --dest ~/site/src/content/notes

# Preview any command without writing
rematter sync ~/vault/notes -n

Commands

validate -- Check frontmatter against a schema

rematter validate <directory> [--schema PATH] [--fix] [--recursive] [--dry-run]

Validates every markdown file against the .rematter.yaml schema in the target directory. Report-only by default -- exits 1 on failures. Unrecognized fields always error.

--fix sets defaults for missing properties and reorders keys to match schema order. Combine with --dry-run (-n) to preview what would change.

sync -- Sync vault markdown to an external destination

rematter sync [source] [--dest PATH] [--link-path-prefix PREFIX] [--recursive] [--dry-run]

Syncs publishable markdown files to an external directory. The pipeline per file:

  1. Skip files where publish is not true
  2. Slugify the filename for the destination
  3. Skip if dest has the same modified value (no changes)
  4. Extract type from capitalized Obsidian tags (#Book -> type: book)
  5. Validate against schema
  6. Resolve creator wikilinks to {name, slug} objects
  7. Resolve body wikilinks to markdown links (broken links -> plain text)
  8. Resolve media references and rewrite hero image paths
  9. Stamp synced timestamp, set title from source filename
  10. Strip sync: false fields from destination output
  11. Write dest file, copy referenced media, stamp synced back on source

Requires a .rematter.yaml config with at least dest (or pass --dest). CLI flags override config values.

transform -- Rename a frontmatter field

rematter transform <directory> --field OLD --to NEW [--recursive] [--dry-run]

Renames a field across all markdown files. Key order is preserved. Files where the target name already exists are skipped with an error.

date-extract -- Prepend dates to filenames

rematter date-extract <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. Useful for systems like Notion that export a date field, when you want to pull that out into the filename for Obsidian's filesystem-centric approach.

Configuration

Each directory can be given a .rematter.yaml that combines sync config and frontmatter schema:

# Sync config
link_path_prefix: /notes
dest: ~/site/src/content/notes/
ignore:
  - draft-*
  - private/*
media:
  source: _media
  dest: src/assets
  link_prefix: /assets

# Frontmatter schema
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          # validated but stripped from dest
  hero:
    type: string
    required: false
    requires: [heroAlt]  # co-dependency: both or neither
  heroAlt:
    type: string
    required: false
    requires: [hero]
  created:
    type: timestamp
    required: true
    default: "%Y-%m-%d %H:%M"   # strftime format, stamps current time on --fix
    sync: false
  modified:
    type: timestamp
    required: true
    default: "%Y-%m-%d %H:%M"
  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 values are valid)
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 -- field is validated but stripped from dest during sync

Sync config fields

Field Purpose
dest Destination directory (overridable via --dest)
link_path_prefix URL prefix for resolved wikilinks (overridable via --link-path-prefix)
ignore Glob patterns for files to skip
media.source Source media directory name (relative to vault dir)
media.dest Destination media directory (relative to dest root)
media.link_prefix URL prefix for media links in dest output

Development

uv sync --dev          # install deps
uv run pytest -v       # run tests
uv run rematter --help # run locally

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rematter-0.1.0.tar.gz (73.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rematter-0.1.0-py3-none-any.whl (19.1 kB view details)

Uploaded Python 3

File details

Details for the file rematter-0.1.0.tar.gz.

File metadata

  • Download URL: rematter-0.1.0.tar.gz
  • Upload date:
  • Size: 73.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for rematter-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7afb29b45f219b00f0cdc7292dfcbd5fd8649fc7de47ee47c2c965d30a70548d
MD5 d0bb9cf98fabf21fd626a8f9db246311
BLAKE2b-256 9c93e47fe441c54b17ab5c8b4800590820734b9675434613c2440a495636bf17

See more details on using hashes here.

File details

Details for the file rematter-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: rematter-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for rematter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ab16fe8e56b334e84050ccc3942dfc0ead4c85ee62009abf368ba91e8157bd2d
MD5 e1b7ecfea2aa37132d54adc176347185
BLAKE2b-256 90113f79a59076026791bf3bb99d129f9f2270e4adda818a3e18c4f11534bb09

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page