Bidirectional Markdown Sync
Bidirectional Markdown Sync keeps your JSON data and individual Markdown task files in lockstep. Every change you make in the plugin UI is written to a .md file, and every edit you make to a .md file is picked up by the plugin automatically.
How It Works
Automatic JSON → Markdown Sync
Whenever you add, update, or delete a task through the plugin UI, the corresponding Markdown file is created, updated, or removed automatically. Files are stored at:
{ProjectName}/Tasks/{TaskTitle}.md
If a task is renamed, the old file is deleted and a new one is created with the updated title.
Automatic Markdown → JSON Sync
When you modify, create, or delete a Markdown task file directly (for example, in the Obsidian editor or through an external tool), the plugin detects the change via Obsidian's metadata cache and updates data.json to match.
Initial Sync
On plugin startup (when Sync on Startup is enabled), a full reconciliation runs: existing Markdown files are compared against the JSON data and any discrepancies are resolved.
If you use Obsidian Sync across multiple devices, enable Sync on Startup with caution. Simultaneous edits on different devices can cause last-write-wins conflicts. Consider disabling Sync on Startup and using the manual Sync All Tasks Now button after confirming your vault is fully synced.
Task Markdown Format
Each synced task file follows this structure:
---
id: f8e7d6c5-b4a3-2190-fedc-ba0987654321
title: Design landing page
status: In Progress
completed: false
priority: high
parentId: null
bucketId: bucket-uuid-2
startDate: 2025-02-01
dueDate: 2025-02-14
tags:
- design
- frontend
collapsed: false
dependencies:
- blockedBy:other-task-uuid
---
Create the initial wireframes and high-fidelity mockups.
## Subtasks
- [x] Wireframe
- [ ] Hi-fi mockup
## Dependencies
- Blocked by: [[other-task-title]]
## Links
- [Figma file](https://figma.com/...)
---
*Managed by Project Planner — do not remove the frontmatter.*
YAML Frontmatter Fields
Required Fields
- id — UUID v4 unique identifier
- title — task display name
- status — current status label (must match a bucket name)
- completed —
trueorfalse
Optional Fields
- parentId — UUID of the parent task, or
null - priority —
high,medium,low, or omit - bucketId — UUID of the Board bucket
- startDate / dueDate —
YYYY-MM-DDformat - tags — YAML list of tag name strings
- collapsed — whether child tasks are collapsed in List view
- dependencies — YAML list using the format
TYPE:TASK_ID(e.g.,blockedBy:uuidorblocking:uuid)
Settings
-
Enable Markdown Sync
Toggle on Settings → Markdown Sync → Enable Markdown Sync. This activates bidirectional sync for all existing and new tasks.
-
Auto-Create Task Notes
When enabled, a Markdown file is automatically created for every new task added through the UI. Disable this if you prefer to create notes selectively.
-
Sync on Startup
Runs a full reconciliation when the plugin loads. Recommended for single-device workflows.
WarningIf you use Obsidian Sync, disable this setting to avoid conflicts from unsettled remote changes.
-
Sync All Tasks Now
A manual button that triggers an immediate full sync. Use this after resolving conflicts or receiving remote vault changes.
Creating Tasks from Markdown
You can create a new task entirely from a Markdown file:
- Create a new
.mdfile inside the{ProjectName}/Tasks/folder. - Add valid YAML frontmatter with at least the required fields.
- Save the file. The plugin will detect it and add the task to
data.json.
Minimal Example
---
id: 550e8400-e29b-41d4-a716-446655440000
title: Review pull request
status: To Do
completed: false
---
Check the latest PR for the auth module.
Generate a valid UUID quickly by running crypto.randomUUID() in the Obsidian developer console (Ctrl+Shift+I → Console), or use any online UUID generator.
Conflict Resolution
To prevent recursive write loops, Project Planner uses a syncInProgress guard set. When a sync operation starts, the affected task ID is added to the set. A 200 ms timeout clears each entry, ensuring the complementary watcher (JSON or Markdown) ignores the echoed change.
If both sources are modified simultaneously, the last write wins. In practice this means:
- UI changes overwrite file changes made within the same 200 ms window.
- File changes overwrite UI changes if the file is saved after the UI write completes.
Use Cases
- Manual editing: Tweak task details in your favorite text editor while the plugin keeps everything in sync.
- Bulk operations: Use find-and-replace across Markdown files to rename tags, update statuses, or reassign priorities in bulk.
- Version control: Commit individual task files to Git for granular change history.
- Templates: Create task template files with preset frontmatter and duplicate them for recurring workflows.
- Plugin integration: Other Obsidian plugins (Dataview, Templater, etc.) can read and write to the Markdown files.
Limitations
- Last save wins: There is no merge strategy—the most recent write always takes precedence.
- Subtask and link IDs are regenerated: When syncing from Markdown to JSON, subtask and link IDs are regenerated because Markdown does not store them.
- New file detection delay: Newly created Markdown files may take up to 1 second to be detected by the metadata cache watcher.
- Board view leaf-only: In Board view, only leaf-level tasks (tasks without children) are displayed. Parent tasks created from Markdown will appear in List or Timeline views.
Troubleshooting
Tasks Not Syncing
- Verify Enable Markdown Sync is toggled on in settings.
- Ensure the Markdown file is inside the correct
{ProjectName}/Tasks/folder. - Check that the YAML frontmatter contains all required fields (
id,title,status,completed). - Reload the plugin (Ctrl+P → "Reload without saving").
Duplicate Tasks Appearing
- Duplicates can occur if the same
idexists in more than one Markdown file. Remove or correct the duplicate file. - If you manually copy a task file, change the
idin the frontmatter to a new UUID.
Resolving Conflicts
- Disable Markdown Sync temporarily.
- Decide which source (JSON or Markdown) is authoritative.
- Delete the non-authoritative version.
- Re-enable sync and trigger Sync All Tasks Now.
Debugging
Open the Obsidian developer console (Ctrl+Shift+I) and look for sync-related messages:
[ProjectPlanner] Markdown→JSON sync: updated task "Design landing page"
[ProjectPlanner] JSON→Markdown sync: wrote file "My Project/Tasks/Design landing page.md"
[ProjectPlanner] Sync conflict detected for task id f8e7d6c5 — last write wins