Skip to content

Syntax Reference

Complete syntax reference for YAML Toolkit for Obsidian rules.

Rule Structure

A rule has two parts entered in separate fields:

Condition field: What to match

<condition>

Action field: What to do

<operation> [arguments]

Important: The plugin automatically evaluates conditions and executes actions. Just enter the condition and action directly.

Action Syntax: Hybrid Grammar

Two syntax styles based on target type:

SCALAR operations (no FOR prefix):

SET field value               # Set/create field
DELETE field                  # Delete field
RENAME field TO newname       # Rename field
INCREMENT field number        # Add to number
DECREMENT field number        # Subtract from number

COLLECTION operations (FOR prefix required):

FOR array APPEND value        # Add to end
FOR array PREPEND value       # Add to start
FOR array INSERT value AT index  # Insert at position
FOR array WHERE condition SET field value  # Update matching items
FOR array SORT BY field       # Sort array
FOR object MERGE data         # Merge objects

Key principle: SCALARS operate on single fields directly. COLLECTIONS operate on arrays/objects and need FOR to specify the target.

Conditions

Comparison Operators

  • = - Equals
  • != - Not equals
  • > - Greater than
  • < - Less than
  • >= - Greater than or equal
  • <= - Less than or equal

Condition examples:

status = "active"
count > 10
date >= "2025-01-01"

Logical Operators

  • AND - Both conditions must be true
  • OR - Either condition can be true
  • NOT - Negates a condition

Examples:

tags contains "project" AND status != "archived"
priority = "high" OR deadline < "{{today}}"
NOT HAS completed_date

Special Operators

  • contains - Check if array contains value
  • HAS - Check if field exists
  • IN - Check if value is in list

Examples:

tags contains "important"
HAS custom_field
status IN ["draft", "review", "published"]

Advanced Operators

Powerful Features

These advanced condition operators provide precise querying and validation capabilities for your YAML frontmatter.

.length - Count Items or Characters

  • field.length - Get count of array items, string characters, or object keys
  • Works with: =, !=, >, <, >=, <=

Examples:

tags.length > 0              # Has tags
title.length < 50            # Short title
metadata.length >= 5         # Many metadata fields

Alternative: Use NOT HAS to check if a field doesn't exist:

NOT HAS tags                 # Alternative to: tags.length = 0
HAS tags                     # Alternative to: tags.length > 0

empty / !empty - Check for Empty Values

  • field empty - Field is empty array [], empty string "", or empty object {}
  • field !empty - Field has content

Examples:

tags empty                   # Empty array
content !empty               # Has content
tags exists AND tags !empty  # Has tags and they're populated

Note: Missing fields and null values return false for empty check.

NOT HAS - Alternative to Empty Check

Use NOT HAS field as an alternative to check if a field is not set:

  • NOT HAS field - Field doesn't exist or is missing
  • HAS field - Field exists

Examples:

NOT HAS tags                 # No tags field (alternative to tags empty)
HAS content AND content != "" # Field exists and is not empty
NOT HAS completed_date       # No completion date (for open tasks)

When to use which:

  • field empty - Check if a field exists but is empty (e.g., empty array or string)
  • NOT HAS field - Check if a field doesn't exist at all
  • field !empty - Check if a field has content

Type Checking

Validate field data types:

  • field :string - Field is a string
  • field :number - Field is a number
  • field :boolean - Field is boolean (true/false)
  • field :array - Field is an array
  • field :object - Field is an object
  • field :null - Field is null
  • field !:type - Field is NOT of type (negated)

Examples:

status :string               # Status is text
priority :number             # Priority is numeric
tags :array                  # Tags is an array
tags !:string                # Tags is NOT a string

Action Operations

SET - Create or Update Fields

Purpose: Set a field value (creates if missing, updates if exists)

Syntax:

SET <field> <value>

Examples:

SET status "active"
SET priority 1
SET tags ["project", "active"]
SET metadata {author: "John", version: 2}

Use when: You need to ensure a field has a specific value regardless of its current state.

FOR ... APPEND - Add to End of Array

Purpose: Add item to end of array (with de-duplication)

Syntax:

FOR <array> APPEND <value>

Examples:

FOR tags APPEND "reviewed"
FOR categories APPEND "work"

Use when: Building lists incrementally, adding to the end without duplicates.

FOR ... PREPEND - Add to Start of Array

Purpose: Add item to start of array (with de-duplication)

Syntax:

FOR <array> PREPEND <value>

Examples:

FOR tags PREPEND "urgent"
FOR categories PREPEND "important"

Use when: Adding priority items to the beginning of lists.

FOR ... REMOVE - Delete from Lists (Conditional)

Purpose: Remove specific items matching a condition

Syntax:

FOR <array> WHERE <condition> REMOVE

Examples:

FOR tags WHERE $ = "draft" REMOVE
FOR items WHERE priority < 3 REMOVE

Note: REMOVE requires a WHERE clause to specify what to remove.

FOR ... REMOVE_ALL - Delete All Occurrences

Purpose: Remove all instances of a specific value

Syntax:

FOR <array> REMOVE_ALL <value>

Examples:

FOR tags REMOVE_ALL "draft"
FOR categories REMOVE_ALL "archived"

Use when: Removing a specific value regardless of how many times it appears.

FOR ... REMOVE_ANY - Delete Multiple Values

Purpose: Remove all instances of any value in a list

Syntax:

FOR <array> REMOVE_ANY [<value1>, <value2>, ...]

Examples:

FOR tags REMOVE_ANY ["draft", "wip", "temp"]
FOR categories REMOVE_ANY ["old", "deprecated"]

Use when: Cleaning up multiple unwanted values at once.

DELETE - Remove Entire Field

Purpose: Remove field completely from front matter

Syntax:

DELETE <field>

Examples:

DELETE old_field
DELETE temp_status

Use when: Cleaning up obsolete or temporary fields.

RENAME - Rename Field

Purpose: Rename a field while preserving its value across all documents

Syntax:

RENAME <old_field> TO <new_field>

Examples:

RENAME author TO creator
RENAME due_date TO deadline
RENAME tags TO categories

Why it's atomic: Cannot be replicated with DELETE + SET because each document has unique values. RENAME preserves all values:

Before (different values in different docs):

yaml
# Doc 1: author: "Alice"
# Doc 2: author: "Bob"
# Doc 3: author: "Charlie"

After RENAME author TO creator:

yaml
# Doc 1: creator: "Alice"
# Doc 2: creator: "Bob"
# Doc 3: creator: "Charlie"

Use when: Standardizing field names across your vault while preserving all unique values.

INCREMENT - Add to Numeric Field

Purpose: Add to numeric field (positive or negative)

Syntax:

INCREMENT <field> <amount>

Examples:

INCREMENT view_count 1
INCREMENT priority -1
INCREMENT score 10

Use when: Tracking counters, scores, or numeric values that change over time.

DECREMENT - Subtract from Numeric Field

Purpose: Subtract from numeric field

Syntax:

DECREMENT <field> <amount>

Examples:

DECREMENT remaining_tasks 1
DECREMENT credits 5
DECREMENT attempts 1

Use when: Counting down values or tracking decreases.

REPLACE - Find and Replace Text (First Occurrence)

Purpose: Replace the first occurrence of text in a field

Syntax:

REPLACE <field> "<search>" "<replacement>"

Features:

  • Replaces only the first occurrence
  • Case-sensitive matching
  • Works with template variables: REPLACE content "" ""
  • Empty strings are valid: REPLACE field "suffix" "" removes suffix

Examples:

REPLACE url "http://" "https://"
REPLACE content "TODO" "DONE"
REPLACE title "Draft: " ""
REPLACE notes "author: John" "author: Jane"

Use when: Making targeted text substitutions in field values.

REPLACE_ALL - Find and Replace All Occurrences

Purpose: Replace all occurrences of text in a field

Syntax:

REPLACE_ALL <field> "<search>" "<replacement>"

Examples:

REPLACE_ALL content "old-url.com" "new-url.com"    # Replace all domain references
REPLACE_ALL text "---" "—"                          # Replace all em-dashes
REPLACE_ALL notes "TODO" "DONE"                     # Mark all TODOs as done

Use when: Making global replacements throughout a field value.

FOR ... INSERT - Insert at Position

Purpose: Insert value at specific position in arrays or strings

Syntax:

FOR <field> INSERT <value> AT <index>

Special indices:

  • 0 - Insert at start (beginning)
  • -1 - Insert at end
  • Positive numbers - Insert at that position
  • Negative numbers - Count from end

Examples:

# Arrays
FOR tags INSERT "urgent" AT 0        # Insert at start
FOR tags INSERT "archived" AT -1     # Insert at end
FOR history INSERT "checkpoint" AT 5 # Insert at position 5

# Strings (concatenation)
FOR title INSERT "DRAFT: " AT 0      # Prepend text
FOR notes INSERT "\n---\n" AT -1     # Append text

Use when: Adding items to arrays or concatenating strings at any position.

Array of Objects Operations

Special operations for structured arrays like task lists.

FOR ... WHERE ... SET - Update Items

Purpose: Update fields in objects matching a condition

Syntax:

FOR <array> WHERE <condition> SET <field> <value> [, <field> <value>]

Examples:

FOR tasks WHERE status = "pending" SET status "active", started "{{today}}"
FOR items WHERE priority < 3 SET priority 5
FOR entries WHERE type = "draft" SET type "review", reviewed true

Use when: Updating specific objects within arrays based on their properties.

FOR ... [index] ... SET - Update Specific Array Element

Purpose: Set fields on a specific array element by its index

Syntax:

FOR <array>[<index>] SET <field> <value> [, <field> <value>]

Index notation:

  • [0] - First element
  • [1], [2], etc. - By position
  • [-1] - Last element
  • [-2] - Second-to-last element
  • Works with nested paths: array[0].nested[-1]

Examples:

FOR history[0] SET reviewed true
FOR tasks[-1] SET status "completed", completed "{{today}}"
FOR teams[0].members[-1] SET role "lead"
FOR projects[-1].phases[-1].tasks[0] SET priority 10

Use when: Modifying a specific item by its position without needing conditions.

FOR ... WHERE ... MOVE - Reorder Items

Purpose: Move items matching condition within array

Syntax:

FOR <array> WHERE <condition> MOVE TO <position>

Positions: START, END, AFTER <condition>, BEFORE <condition>

Examples:

FOR tasks WHERE priority > 7 MOVE TO START
FOR items WHERE status = "done" MOVE TO END
FOR tasks WHERE urgent = true MOVE TO AFTER name = "Planning"

Use when: Prioritizing or organizing items without full sorting.

FOR ... SORT - Sort Arrays

Purpose: Sort array in ascending or descending order

Syntax:

FOR <array> SORT [<order>]
FOR <array> SORT BY <field> [<order>]

Orders: ASC (ascending), DESC (descending). Default is ASC.

Examples:

FOR tags SORT ASC
FOR priorities SORT DESC
FOR tasks SORT BY priority DESC
FOR entries SORT BY date ASC

Use when: Organizing simple arrays or object arrays by field values.

FOR ... MOVE - Move by Index

Purpose: Move item from one index to another

Syntax:

FOR <array> MOVE FROM <index> TO <index>

Examples:

FOR tags MOVE FROM 0 TO 5
FOR history MOVE FROM -1 TO 0

Use when: Manual reordering by position.

FOR ... DEDUPLICATE - Remove Duplicates

Purpose: Remove duplicate values from array

Syntax:

FOR <array> DEDUPLICATE

Examples:

FOR tags DEDUPLICATE
FOR categories DEDUPLICATE

Use when: Cleaning up arrays with duplicate values.

Object Operations

FOR ... MERGE - Deep Merge Objects

Purpose: Deep merge objects (preserves existing nested fields)

Syntax:

FOR <object> MERGE {<key>: <value>, ...}

Examples:

FOR metadata MERGE {author: "John", version: 2}
FOR config MERGE {theme: "dark", showIcons: true}

Use when: Adding or updating nested object fields while preserving others.

FOR ... MERGE_OVERWRITE - Shallow Merge Objects

Purpose: Shallow merge objects (overwrites all fields)

Syntax:

FOR <object> MERGE_OVERWRITE {<key>: <value>, ...}

Examples:

FOR metadata MERGE_OVERWRITE {author: "Jane", version: 3}
FOR settings MERGE_OVERWRITE {mode: "advanced"}

Use when: Replacing entire object contents.

Special Values

Template Variables

Template variables are evaluated at runtime and inserted into action values.

Built-in variables:

  • {{today}} - Today's date (YYYY-MM-DD)

Field mapping variables:

  • {{fm:field_name}} - Copy value from another field

Examples:

SET updated "{{today}}"
SET reviewed_on "{{today}}"

# Field mapping examples
SET author "{{fm:creator}}"              # Copy from creator field
FOR tags APPEND "{{fm:primary_tag}}"     # Use another field's value
SET backup_title "{{fm:title}}"          # Duplicate field value

Data Types

  • Strings: "text" (use quotes)
  • Numbers: 42, 3.14
  • Booleans: true, false
  • Arrays: ["item1", "item2"]
  • Objects: {key: "value", nested: {foo: "bar"}}
  • Dates: "2025-01-01"

Path Syntax & Array Access

Accessing Nested Data

Use dot notation and brackets to access nested structures:

field                    # Top-level field
object.property          # Object property
array[0]                 # Array by index
object.nested.deep       # Multi-level nesting
array[0].property        # Object within array

Deep nesting examples:

# Multi-level object paths
metadata.author.profile.name
config.server.database.connection.host

# Nested arrays within objects
projects[0].phases[1].tasks[2].status
teams[0].members[5].skills[0]

# Mixed nesting patterns
data.servers[0].endpoints[0].methods[1]
workflow.steps[0].substeps[2].validation.rules[0]

Real-world access patterns:

# Check nested status
Condition: projects[0].milestones[2].completed = true

# Update deep nested value
Action: SET config.api.endpoints[0].rateLimit 5000

# Access nested array property
Condition: teams[1].members[-1].role = "lead"

Negative Indexing

Access array items from the end using negative indices:

Syntax:

  • array[-1] - Last item
  • array[-2] - Second-to-last item
  • array[-n] - Nth item from end

Examples:

Check last task status:

Condition: tasks[-1].status = "done"

Update second-to-last entry:

Action: FOR history[-2] SET reviewed true

Insert before last item:

Action: FOR tags INSERT "archived" AT -2

Access nested array from end:

Condition: projects[0].tasks[-1].priority > 7
Action: SET projects[-1].status "completed"

Use cases:

  • Check most recent item in log/history arrays
  • Update last entry without knowing array length
  • Insert items relative to end of array
  • Access latest task, note, or record

Error Handling & Edge Cases

Understanding how the plugin handles different data states.

Missing Fields

Path doesn't exist:

Condition: nonexistent.field = "value"
Result: Condition evaluates to false, file skipped

Action on missing field:

Action: FOR tags APPEND "new-tag"
# If tags doesn't exist → Creates array: ["new-tag"]
# If tags exists → Appends to existing array

Null vs Empty vs Missing

Field doesn't exist:

yaml
# Field not present in frontmatter
  • field emptyfalse (can't be empty if doesn't exist)
  • field existsfalse
  • HAS fieldfalse
  • FOR field APPEND "x" → Creates new array: ["x"]

Null value:

yaml
field: null
  • field emptyfalse (null ≠ empty)
  • field :nulltrue
  • field existstrue
  • FOR field APPEND "x" → Replaces with array: ["x"]

Empty array:

yaml
field: []
  • field emptytrue
  • field.length = 0true
  • field existstrue
  • FOR field APPEND "x" → Result: ["x"]

Empty string:

yaml
field: ""
  • field emptytrue
  • field.length = 0true
  • field = ""true

Empty object:

yaml
field: {}
  • field emptytrue
  • field.length = 0true
  • field existstrue

Type Mismatches

Increment on non-number:

INCREMENT views 1     # views is string "5"
Result: Error logged, file skipped, operation aborted

Array operation on non-array:

FOR tags APPEND "new"  # tags is string "old"
Result: Replaces with array: ["old", "new"]

WHERE Finds No Matches

No matching items:

FOR tasks WHERE status = "archived" REMOVE
Result: No change (no items match), operation succeeds

Empty result set:

ANY tasks WHERE priority > 10    # No tasks have priority > 10
Result: Condition is false, file skipped

Out of Bounds Access

Array index out of range:

Condition: tags[100] = "test"    # tags only has 3 items
Result: Condition is false (index doesn't exist)

Negative index beyond array:

Action: FOR tags INSERT "x" AT -50   # tags has 5 items
Result: Inserts at start (index 0)

Safe Operations

Operations that won't fail:

  • HAS field - Always returns true/false
  • field exists - Always returns true/false
  • field empty - Returns false for missing/null, true for empty
  • FOR array WHERE ... - No error if no matches
  • SET field value - Creates field if missing

Operations that may fail:

  • INCREMENT/DECREMENT - Requires numeric field
  • REPLACE - Requires string field
  • Deep path access - Any missing intermediate path returns false

Complete Examples

Update Draft Notes

Condition:

status = "draft" AND HAS tags

Action:

SET status "ready-for-review"

Clean Up Archived Notes

Condition:

tags contains "archived"

Action:

SET status "archived"

Add Missing Metadata

Condition:

NOT HAS created_date

Action:

SET created_date "{{today}}"

Conditional Tagging

Condition:

priority > 5 AND NOT tags contains "urgent"

Action:

FOR tags APPEND "urgent"

See Also

Released under the MIT License.