# SP Tasker Obsidian plugin: editing a note's frontmatter creates or updates a matching task in [Super Productivity](https://super-productivity.com), via its local REST API. One direction only — nothing syncs back from SP into Obsidian. ## What it does - `next` (frontmatter key name configurable) becomes the task title. Accepts a string, list, number, or boolean. - `waiting_on` (frontmatter key name configurable; string or list) prefixes the title ("Waiting on Alex: ...", or "Alex and Sam" / "Alex, Sam and Jo" for a deduped list) and adds the configured reminder tag — untagged if that tag doesn't exist yet in SP. - The SP project comes from a frontmatter property, a tag, or both: - **Property** (off by default): set "Project property name" (e.g. `Projects`) and the note's value picks the project. It can be a plain name (`Projects: Website`), a link to a note (`Projects: "[[Website]]"` — the linked file's name is used, ignoring any folder, `#heading` or `|alias`), or a list of either. A plain name is used exactly as written. - **Tag:** the note's `Project/` tag (frontmatter or inline body). The prefix (`Project/` by default) is configurable and can be a comma-separated list of prefixes; leave it empty to ignore tags entirely. Only the segment directly under the matched prefix is used, so `Project/Website` and `Project/Website/v2` collapse to the same project. - Names from both sources are combined: the same name in both is fine (handy while moving from tags to properties), but two *different* names abort the send rather than guessing. A note with no project at all is created in the project named by the "Default project" setting (`Inbox` by default; leave it empty to let SP decide), if that project exists in SP. - Project and reminder tag both have to already exist in Super Productivity — the API is read-only for both. If a note *names* a project but SP has no matching project, the send aborts (notice) rather than silently dropping it; a missing reminder tag just sends untagged. - `start` (frontmatter key name configurable; optional, `YYYY-MM-DD`) becomes the task's due date in SP. When a task is *created*, a `start` of today or later is used, and a valid `start` in the past becomes today (an overdue note starts out due now, including when a new task replaces one you completed in SP); a missing or unparseable `start` sends no due date. When an existing task is *updated*, a `start` strictly in the future is sent, and a `start` of today is sent only if the task has no date in SP yet (for example, you added `start` to the note after the task was created). This keeps a task you've pushed to a later day in SP from being snapped back to today by an unrelated edit or a manual send. A future `start` still overwrites a due date you set by hand in SP (Obsidian-first). A past or removed `start` never changes or clears an existing due date in SP. - Newly *created* tasks get no due date unless `start` supplies one (a past `start` counts as today). SP would otherwise stamp them as due today whenever its Today view is open; the "No due date on new tasks" setting (on by default) suppresses that. It only affects creation, never updates. - If a manual send is triggered on a note with no `next` value, a notice explains there's nothing to send (auto-triggered sends stay silent, since every keystroke touches frontmatter). - Optionally (on by default, toggleable), the task's notes field gets a clickable markdown link back to the note (`[label](obsidian://open?vault=...&file=...)`), since SP only auto-linkifies http/https, not the `obsidian:` scheme. - The plugin never overwrites notes you typed yourself in SP — only an empty field, a bare `obsidian://open?...` (old format), or its own current link format gets replaced. - `sp_task_id` and `sp_task_ref` are written back into the note's frontmatter by the plugin. `sp_task_ref` is the note's permanent display number: once assigned it's read from the note itself rather than internal state, so it can't drift or get reassigned if `data.json` is ever lost. It only changes if the task it spawned in SP gets checked and then next gets changed. Then, a new task is created with a new ref string, but same ID# (because it comes from the same note). - A successful send shows a brief confirmation notice. Runs automatically (debounced, 250ms floor) whenever a note's frontmatter changes or the note is renamed, or immediately via the **Send current note to Super Productivity** command — which also force-resyncs even when nothing changed, and re-checks the task's live status in SP. ## Requirements - Super Productivity desktop v14+, with the local REST API enabled (Settings → Misc, off by default) and its access token, listening on `http://127.0.0.1:3876`. - Obsidian desktop — the API is bound to `127.0.0.1`, so this only works with both apps running on the same machine. ## Install Download `main.js` and `manifest.json` from the latest [release](../../releases) and copy them into `/.obsidian/plugins/sp-tasker/`, then enable the plugin in Obsidian and set the API URL/token in its settings tab. If updating the plugin, just drop the new main.js and manifest.json into the plugin directory, data.json stays the same and you won't have to re-enter your SP API token. You can also install it through [BRAT](https://github.com/TfTHacker/obsidian42-brat) using this repository's URL. ## Network use and privacy - **Network:** the plugin's only network traffic is HTTP requests to the Super Productivity (SP) local REST API at the URL set in its settings (default `http://127.0.0.1:3876`, i.e. SP running on your own machine). It reads and writes tasks, projects and tags there. If you point the URL somewhere else, requests go to that address instead. Nothing is sent to any other server. - **Access token:** the SP access token you enter is sent as a `Bearer` token to that API URL, and is stored unencrypted in the plugin's `data.json` inside your vault (`/.obsidian/plugins/sp-tasker/`). Keep that in mind if you sync or share your vault. - **Account / payment:** none. Super Productivity is a separate, free app that must be installed and running on the same machine. - **Telemetry and ads:** none. - **Files:** the plugin only reads notes in your vault (frontmatter and tags) and writes `sp_task_id` / `sp_task_ref` into the frontmatter of notes it syncs. It does not access files outside your vault. Once at startup it also checks every note's cached frontmatter (not the note text) for the highest `sp_task_ref`, so the plugin's ref counter can never fall behind numbers already written into your notes. Nothing from that scan is stored or sent anywhere. - **Source and license:** open source under the [MIT license](LICENSE). ## Idempotency Every send computes two signatures for the note: `content` (title, resolved project name, resolved tag name, plus the due date when `start` supplies one) and `full` (content + the note's vault path), joined with a `\x01` separator and stored per SP task id. - Auto-triggered sends return early when the `full` signature is unchanged. The manual command never short-circuits this way — it always re-checks the task with SP. - If only the path changed (content signature still matches), the plugin refreshes the notes link and does nothing else — this is what stops a rename from reopening a completed task. - Otherwise it fetches the task from SP: if it's still open, that task is PATCHed in place and keeps its existing `sp_task_ref`. If it's done, archived, or gone (404), a brand-new task is created instead, with a new sequential `sp_task_ref`. If the plugin's `data.json` is lost, its ref counter can't restart at 1 and collide with numbers already written into the vault: on every startup (`layout-ready`) it automatically rescans all notes and raises the counter above the highest `sp_task_ref` found. It can't recover the old SP task ids though, so notes touched after data.json is lost will get a new task rather than update their old one. Errors and warnings surface only as an Obsidian `Notice` plus `console.error`. Log view may be added in future.