Synchronization plugin for super-productivity that allows to sync many markdown files to the same number of projects
  • TypeScript 66%
  • HTML 32.4%
  • JavaScript 1.6%
Find a file
Fernando Pindado 7e9332c1b3 /close: session-log row for Taskdown kickoff prep + docs housekeeping
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 17:07:47 +02:00
.claude/commands Remove erroneous executable bit from source/doc/config files 2026-06-24 12:45:25 +02:00
scripts Remove erroneous executable bit from source/doc/config files 2026-06-24 12:45:25 +02:00
src Release v0.2.1 docs + bump to 0.2.2 2026-07-08 16:57:12 +02:00
taskdown-bootstrap taskdown-bootstrap: note to adapt (not copy) the plugin's @done handling 2026-07-08 17:06:18 +02:00
Tech_Docs Release v0.2.1 docs + bump to 0.2.2 2026-07-08 16:57:12 +02:00
.gitignore Doc regoranization and v0.0.7 2026-05-29 15:31:00 +02:00
CLAUDE.md /close: session-log row for Taskdown kickoff prep + docs housekeeping 2026-07-08 17:07:47 +02:00
eslint.config.js Remove erroneous executable bit from source/doc/config files 2026-06-24 12:45:25 +02:00
jest.config.cjs Remove erroneous executable bit from source/doc/config files 2026-06-24 12:45:25 +02:00
LICENSE Initial commit 2026-05-22 17:52:28 +02:00
package-lock.json Release v0.2.1 docs + bump to 0.2.2 2026-07-08 16:57:12 +02:00
package.json Release v0.2.1 docs + bump to 0.2.2 2026-07-08 16:57:12 +02:00
README.md Release v0.2.1 docs + bump to 0.2.2 2026-07-08 16:57:12 +02:00
README_es.md Release v0.2.1 docs + bump to 0.2.2 2026-07-08 16:57:12 +02:00
tsconfig.json Remove erroneous executable bit from source/doc/config files 2026-06-24 12:45:25 +02:00

sync.md Multi Plugin for Super Productivity

sync.md Multi is an enhanced version of the original sync.md plugin that lets you synchronize multiple Super Productivity projects with their own independent Markdown files simultaneously.

What does sync.md Multi do?

  • Multiple project bindings: Link any number of Super Productivity projects to their own .md files, each managed independently.
  • Bidirectional synchronization: Changes made in Super Productivity are written to the Markdown file; changes made to the Markdown file are imported back into Super Productivity.
  • Task IDs preserved in Markdown: Each task is identified by a unique ID embedded as an HTML comment (<!--task-id-->), enabling reliable round-trip sync without data loss.
  • Notes support: Task notes are synced alongside task titles and completion status.
  • Header preservation: Any YAML front matter or free-text content at the top of your .md file (before the first task line) is preserved when the plugin rewrites it.
  • Oscillation prevention: After a Markdown→SP sync, the plugin suppresses redundant SP→Markdown write-backs for 2 seconds, preventing sync loops (fix for issue #6021).
  • Window focus awareness: Sync triggered by file changes runs immediately when Super Productivity is focused; it is deferred until the window regains focus otherwise.
  • Parentchild task conversion: Change a subtask's indentation in the Markdown file to promote it to a parent task, or indent a parent under another task to make it a subtask. The change is picked up on the next sync.
  • Coexistence: sync.md Multi has a different plugin ID (sync-md-multi) and can be installed alongside the original sync.md plugin without conflicts.

Markdown file format

The plugin uses a specific Markdown format. Tasks are represented as checkboxes with an embedded HTML comment containing the SP task ID:

- [ ] <!--task-id-abc123--> Parent Task Title
  - [x] <!--task-id-def456--> Completed Subtask
    A note line belonging to the subtask
  - [ ] <!--task-id-ghi789--> Pending Subtask
  A note line belonging to the parent task

Key conventions:

  • Parent tasks use no indentation; subtasks are indented with 2 spaces.
  • The <!--id--> comment is placed after the checkbox and before the title.
  • Notes appear as plain lines below their task, indented by 4 spaces (subtask notes) or 2 spaces (parent notes).
  • Blank lines within the task area are ignored (not treated as notes).
  • New tasks added manually without an ID comment will be assigned one on the next sync.
  • The plugin preserves any content above the first task line (headers, YAML front matter, etc.).

Section headers and other non-task content within the task area

Lines like ## Completed Tasks that appear between task lines are treated as section dividers during the Markdown→SP import: they are not imported into SP as tasks and they are not attached to any task's notes. During the SP→Markdown write-back, spToMd performs an in-place update — only checkbox lines are modified, and every other line (section headers, blank lines, notes, free-form text) is preserved exactly as-is.

Completion timestamps (@done)

When you complete a task in Super Productivity, the plugin appends a @done tag with your local completion time to that task's line in the Markdown file:

- [x] <!--task-id-def456--> Completed Subtask @done(2026-07-07 14:30)
  • The format is @done(YYYY-MM-DD HH:mm) in your local time.
  • Reopening the task (un-completing it) removes the @done tag. Active tasks stay untagged.
  • The write is idempotent: re-syncing an already-completed task does not rewrite the timestamp.
  • When reading a file, the plugin keeps the SP task title clean — it recognises a trailing @done, @done(2026-07-07) (date only) or @done(2026-07-07 14:30) and strips it from the imported title.
  • A date you typed into the file yourself is preserved across round-trips (the plugin does not overwrite an existing timestamp).

Note

: @todo and @doing tags are not written by the plugin (Super Productivity only tracks done vs. not-done). If they already appear in a file they are tolerated (kept out of the SP title) but not managed by the plugin.

This aligns the Markdown file format with the companion Taskdown app.

How synchronization works

Markdown → SP (triggered by file change):

  1. The file watcher detects a modification to the .md file.
  2. The watcher is temporarily stopped to prevent feedback loops.
  3. mdToSp parses the file, computes the diff against the current SP state, and applies create, update, delete, and reorder operations via batchUpdateForProject.
  4. A write-back (spToMd) is always performed after the import to stamp the newly assigned task IDs back into the Markdown file.
  5. The file watcher is restarted.

SP → Markdown (triggered by SP task or project update):

  1. The taskUpdate hook fires (normal edits and project moves) or projectListUpdate (project structure changes). The legacy anyTaskUpdate hook is kept as a fallback for older SP versions.
  2. A 500 ms debounce timer starts (batches rapid consecutive updates).
  3. If the timer fires within 2 seconds of a recent Markdown→SP sync, the write-back is suppressed to avoid oscillation.
  4. Otherwise, spToMd reads the existing file and performs an in-place merge: each task's checkbox and title are updated in the file while every other line (section headers, blank lines, notes, free-form text) is left exactly as written. Tasks that were deleted in SP are removed; tasks new in SP are appended at the end. If the file does not exist, the full content is generated from scratch.

Manual sync (Sync Now button in the SP header):

  1. SP→MD runs first, writing the current SP state to every Markdown file.
  2. MD→SP runs immediately after, importing any remaining differences from the files back into SP.

Initial sync (when a binding is created or the plugin starts):

  • If the .md file does not exist: SP tasks are written to the file (creating it).
  • If the .md file exists: tasks are imported from Markdown into SP, then a write-back stamps task IDs into the file immediately — no restart required.

When a file or project goes missing

A binding must never keep running in a broken state. If a sync finds that a resource it depends on is gone, the plugin stops and shows a dialog asking you how to proceed. There are two cases.

The Markdown file is missing (deleted, moved, or on a folder/volume that is not currently available):

  • Recreate from SP — regenerate the .md file from the current tasks in the bound project.
  • Delete binding — remove the binding.
  • Ignore — dismiss the dialog. If you restore the file yourself, the next sync continues normally. If it is still missing, the dialog reappears on the next sync.

Note

: Creating a brand-new binding that points at a file which does not exist yet still creates that file silently, with no dialog. The dialog only appears for a file that existed before and then went missing.

The bound Super Productivity project was deleted (your .md file is left untouched):

  • Recreate project in SP — create a new project under its previous name, re-point the binding to it, and re-import the tasks from the .md file.
  • Delete binding — remove the binding (the .md file stays where it is).
  • Ignore — dismiss the dialog. Use this if you plan to create a project and re-point the binding yourself in the config panel. The dialog reappears on the next sync if the project is still missing.

If both the project and the .md file are gone, only Delete binding and Ignore are offered.

Deleting a project never wipes your .md file. Your Markdown content is always preserved.

Installation

  1. Build the plugin (or download a pre-built ZIP):

    npm install
    npm run build
    

    This produces dist/plugin.js and a sync-md-multi-v<version>.zip in the project root.

  2. Open Super Productivity and go to Settings → Plugins.

  3. Install from ZIP: Click Install Plugin from ZIP, select the generated zip, and confirm.

  4. sync.md Multi will appear in your plugin list, ready to configure.

Desktop only: File read/write operations require the desktop version of Super Productivity. The plugin will not function in the web or mobile versions.

⚠️ SP version compatibility: Fully working on Super Productivity ≤ 18.9.1 and ≥ 18.13.1. SP 18.10.018.12.x block nodeExecution for externally-loaded plugins ("Node.js execution is currently only available to built-in desktop plugins") — a security hardening (SP PR #8205, advisory GHSA-78rv-m663-4fph), confirmed on 18.10, 18.11 and 18.12, so the plugin cannot sync on those versions. SP 18.13.1 re-opens nodeExecution for uploaded/external plugins behind a one-time native consent dialog (click Allow; consent persists per plugin — PRs #8576 / #8600 / #8708). Verified working on macOS (Apple Silicon) with 18.13.1. Avoid the 18.10.018.12.x range.

Configuration

  1. Open the plugin configuration via the sync.md Multi entry in SP's left-hand menu (or the gear icon in the plugin list).
  2. Under Add New Binding:
    • Select the Super Productivity project from the dropdown.
    • Enter the absolute path to the .md file (e.g., /home/user/projects/work-tasks.md), or click Browse… to navigate the filesystem. The file will be created if it does not exist.
    • Click Add Binding.
  3. The binding appears under Active Bindings and sync starts immediately — no restart needed.

You can add as many bindings as you have projects. Each binding is independent — a crash or error in one does not affect the others. Each entry under Active Bindings also shows when it last synced.

Note: Each .md file path must be unique across all bindings. The UI will reject a duplicate path to prevent two watchers from fighting over the same file.

To modify a binding, click Edit. To remove it, click Delete — a confirmation dialog then offers three choices:

  • Delete binding — remove the binding and leave the .md file untouched (its hidden <!--…--> sync markers stay in place).
  • Delete + clean file — remove the binding and strip the hidden <!--…--> sync markers from the file, leaving it neutral (unbound). Use this if you want to hand the file to another tool or re-bind it cleanly later.
  • Cancel — keep the binding.

Neither delete option removes the .md file itself — only the binding (and, for Delete + clean file, the sync markers inside it).

A Sync Now button in the SP header bar (labelled "sync.md Multi: Sync Now") forces an immediate bidirectional sync for all active bindings: Markdown→SP first (picks up any manual file edits), then SP→Markdown (writes the current SP state back to the file with IDs).

Updating the plugin

You have two options:

  • Quick update: install the new ZIP directly from Settings → Plugins → Install Plugin from ZIP without uninstalling first. SP will overwrite the existing plugin files in place.
  • Clean update: uninstall the current version first, then install the new ZIP.

Either way, your binding configuration is stored in SP's synced data store and is preserved across updates.

Important considerations

  • Desktop only: File operations are not available in the web or mobile versions of Super Productivity.
  • Simultaneous editing is safe: The oscillation prevention mechanism handles the case where you edit the Markdown file while Super Productivity is open. You do not need to pause SP before editing your .md files.
  • Moving tasks between projects: Task moves are detected automatically. When a task is moved, both the origin file (task removed) and the destination file (task added) are updated within the normal sync debounce window.
  • Unique IDs in comments: Do not remove or alter the <!--id--> comments in your Markdown file. They are the link between a line and its SP task. A line without an ID comment will be treated as a new task on the next sync.
  • Section headers and non-task lines are preserved: Markdown headings (##, ###, etc.) and all other non-task lines within the task area are kept exactly as-is during a SP→Markdown write-back. They are not imported into SP (no section concept in SP), but they survive write-backs intact.
  • Notes in the file are the source of truth: Task notes in the Markdown file are preserved verbatim during SP→Markdown write-back. If you edit a task's notes inside Super Productivity, those changes will NOT be written back to the Markdown file — the file's note lines are kept as-is. Notes written in the Markdown file are, however, imported into SP on the next Markdown→SP sync.
  • Config migration: If you were using the original sync.md plugin, its single-project configuration (filePath + projectId) is automatically migrated to a V2 binding on first load.

What happens to existing SP tasks when you create a binding

The behaviour on the first sync depends on whether the .md file already exists:

Situation What happens
File does not exist SP tasks are written to the new file. SP is unchanged.
File exists but has no task lines Treated the same as a non-existent file: SP tasks are written to it. SP is unchanged.
File exists and has tasks The file is the source of truth. Tasks in the file are imported into SP (created or matched by title). Tasks that exist in SP but are absent from the file are deleted from SP.

⚠️ Warning: If you link a file that does not contain your existing SP tasks, those tasks will be deleted from the project. To keep existing SP tasks, either link a file that does not exist yet (SP writes them to the file) or make sure the file already contains those tasks before creating the binding.

Troubleshooting

Plugin can't sync on SP 18.10.018.12.x Those versions block the nodeExecution permission for externally-loaded plugins. Upgrade to SP ≥ 18.13.1 — it re-opens nodeExecution behind a one-time consent dialog (click Allow) — or stay on ≤ 18.9.1.

"Sync Now" button does not appear in the SP toolbar (macOS) Fixed in v0.1.0. Earlier builds had a registration-timing issue that prevented the header button from rendering on macOS; the button is now registered before SP builds its toolbar. If you don't see it, make sure you are on v0.1.0 or later and reinstall from the ZIP.

Plugin does not appear or does not work Ensure you are using the desktop version of Super Productivity and that it supports the plugin API version this plugin targets. Try reinstalling from the ZIP.

The project dropdown shows only "Inbox" or is missing a newly created project The plugin loads the project list directly from Super Productivity on every panel open, with automatic retries every 2 seconds. If only "Inbox" appears, SP may not have finished loading the project state into the iframe yet — wait a moment and the dropdown will refresh itself. You can also click the button next to the dropdown to force an immediate refresh. A newly created project should appear within a few seconds; if not, click ↺.

Sync does not trigger after editing the file Verify the file path in the binding is correct and that the app has filesystem read/write permissions for that location. The file watcher polls mtime; some editors write to a temp file and rename — this should still be detected, but the Sync Now button in the SP header can force a refresh.

Tasks appear duplicated after a sync This usually means the <!--id--> comments were removed or corrupted. Restore them from a backup or delete the affected tasks in SP and let the next SP→Markdown sync regenerate the file cleanly.

Errors in the console Open the developer console (Ctrl+Shift+I / Cmd+Option+I) and look for [sync-md] prefixed messages. Errors include the binding's file path to help identify which binding is affected.

SP→Markdown sync fires but produces no visible change The 2-second cooldown after a Markdown→SP sync may be suppressing the write-back. This is intentional — wait a few seconds and trigger a task update in SP to force a fresh SP→Markdown sync.

For developers

npm install          # Install dependencies
npm run build        # Bundle plugin.js via esbuild + create dist ZIP
npm test             # Run Jest test suite (328 tests across 34 suites)
npx tsc --noEmit     # TypeScript type check (skipLibCheck: true)

The plugin is bundled with esbuild. TypeScript type checking is separate from the build. The @super-productivity/plugin-api package is mocked in tests via jest.config.cjs module name mapping — the published npm package does not include internal hooks like anyTaskUpdate. All imports from this package in source files use import type to avoid a runtime require() call inside the IIFE bundle.

Contributing

If you find a bug or want to propose a feature, please open an issue. Pull requests are welcome.

Acknowledgements

sync.md Multi is based on the original sync.md plugin, created by Johannes Millan (@johannesjo), the author of Super Productivity. Many thanks for the excellent foundation that made this extension possible.

The multi-project evolution was developed by Fernando Pindado together with Claude (Anthropic).


Based on sync.md by @johannesjo · Multi-project extension by Fernando Pindado with Claude (Anthropic)