Todoist Bridge

by Rodrigo Farinha
5
4
3
2
1
Score: 51/100

Description

Sync Todoist tasks with Obsidian Markdown task lines using #todoist bridge markers.

Reviews

No reviews yet.

Stats

0
stars
261
downloads
0
forks
114
days
15
days
15
days
2
total PRs
0
open PRs
0
closed PRs
2
merged PRs
0
total issues
0
open issues
0
closed issues
14
commits

Latest Version

15 days ago

Changelog

Todoist Bridge 3.0.1

Todoist Bridge 3.0.1 is a correctness release focused on one class of problem: the bridge could detach a task that Todoist had not actually deleted. It also repairs description drift, fixes Obsidian link encoding for vault and file names containing reserved characters, and stops reconciliation work from accumulating without end.

No state schema change. Runtime-state schema v2 from 3.0.0 is unchanged, so upgrading and rolling back between 3.0.0 and 3.0.1 is safe.

Deletion is now proven, not assumed

Previous releases treated several different signals as evidence that a Todoist task had been deleted. Two of them were unreliable:

  • A deleted entry in the Todoist activity log survives an undo. Deleting a task and immediately restoring it leaves the event in place permanently.
  • A failed task lookup — a timeout, a transient server error, a dropped connection — was handled the same way as a confirmed deletion. The audit text the bridge wrote said as much: "deleted or unavailable".

Either could cause the bridge to rewrite the Markdown task line as #todoist_detached and strip the bridge label from a task that was still open in Todoist, leaving the task present on both sides but no longer synchronized.

From 3.0.1, every deletion signal is treated as a claim that must be confirmed against the current state of the task before anything is modified:

  • A confirmed deletion — an explicit deletion flag, or a definitive not-found response — detaches exactly as before.
  • A task that is still open is repaired instead: the bridge label and the Obsidian link description are restored and the task stays synchronized.
  • A task that turns out to be completed rather than deleted is left alone for the completion path to handle.
  • A lookup that fails for any other reason changes nothing and is retried on a later run.

This cannot prevent a real deletion from being applied. It only prevents an unverified one.

If you were affected

Tasks detached by an earlier release keep the audit line naming their original Todoist ID. They are not repaired automatically, because a detached line can also be the correct result of deliberately deleting a task or removing its bridge label. To check whether a detached task still exists, look up the recorded ID in Todoist. Re-attaching is a manual edit: remove the #todoist_detached tag and the audit line, and restore the #todoist tag.

Reconciliation no longer accumulates

  • A tombstone recording an uncertain deletion is now retired once the question it recorded has been answered, including when the deletion is confirmed and no bridged line remains. Previously such a tombstone was kept forever and re-examined on every run.
  • Only a recently created uncertain-deletion tombstone bypasses the periodic reconciliation delay. Previously a single unresolved tombstone disabled that delay entirely, so every synchronization performed a full reconciliation pass regardless of how little had changed.

Other fixes

  • Obsidian links survive reserved characters. Vault and file names containing &, #, ?, ' or similar are now percent-encoded per component. Previously such links could be truncated or point at the wrong note.
  • Description drift is repaired. When a bridged task's remote description is empty or contains only a bridge link, the bridge restores the current Obsidian link instead of leaving it stale. Descriptions you have edited yourself are not overwritten.
  • Comments reach moved tasks. Incoming Todoist comments are matched by task ID across the vault rather than only at the last known path, so a note that has been moved or renamed still receives them.
  • Open tasks are repaired rather than detached. During reconciliation, a task that is open in Todoist but missing its bridge label has the label restored instead of having its local marker detached.
  • Deletions awaiting confirmation are prioritized. Uncertain deletions are checked ahead of the rolling reconciliation cursor rather than waiting for their turn.
  • Task metadata is read more conservatively. A task response carrying real content and no deletion evidence is treated as open rather than ambiguous.

Network behavior

Requests to the Todoist API now send Accept: application/json and a generic browser User-Agent header. No additional data about your vault, tasks, or device is included, and no new endpoint is contacted.

Known limits

  • Tasks detached by an earlier release are not restored automatically; see above.
  • Confirming a deletion costs one extra API request per deletion event. On a run with a large backlog of deletions this makes the run longer.
  • If the Todoist API is unreachable, deletions are deferred rather than applied, and the affected tasks stay bridged until a later run can confirm their state.

README file from

Github

Todoist Bridge

Todoist Bridge connects selected Markdown tasks in Obsidian with Todoist. Add #todoist to a task to create the matching Todoist task, then complete, reopen, or rename it from either app.

- [ ] Call Ana tomorrow #todoist

The plugin deliberately avoids destructive deletion. If either side of a bridge disappears or loses its bridge marker, the surviving task is detached and annotated instead of being silently completed or deleted.

Requirements

  • Obsidian 1.12.7 or later.
  • A Todoist account and Todoist API token.
  • Network access to Todoist while synchronizing.
  • The plugin configured separately on every Obsidian device you use.

Todoist Bridge is an independent community plugin and is not affiliated with or endorsed by Todoist.

Install and connect

  1. Back up your vault before installing a major version.
  2. In Obsidian, open Settings → Community plugins → Browse, find Todoist Bridge, install it, and enable it.
  3. In the Todoist web app, follow Find your API token: open Settings → Integrations → Developer and copy the token. Treat it like a password.
  4. In Obsidian, open Settings → Todoist Bridge.
  5. In Todoist API token, create or select an Obsidian SecretStorage entry and put the Todoist token in that secret. The token value is not written to the plugin's data.json.
  6. Select that secret, then click the send/connect button beside the token field. A successful connection loads your Todoist projects.
  7. Choose the Default project for new Obsidian tasks.
  8. Add #todoist to an unchecked Markdown task.
  9. Open the command palette and run Todoist Bridge: Sync now (Todoist ⇄ Obsidian).
  10. Confirm that the task appears in the selected Todoist project.

Obsidian SecretStorage entries are device-local. Repeat the token selection, connection, and default-project setup on every desktop or mobile device. Do not put the token in a note, issue, diagnostic report, or screenshot.

Everyday use

Only Markdown checkbox tasks marked with #todoist are bridged:

- [ ] Prepare the agenda #todoist
Change Result
Add #todoist to an unchecked Obsidian task Creates a Todoist task
Complete or reopen the task in either app Updates the other app
Rename the task in either app Updates the other app
Move or rename the Obsidian note Updates the Todoist link back to the note
Remove #todoist or delete the local line/note Keeps the Todoist task open and detaches it
Remove the bridge label or delete the task in Todoist Keeps the Obsidian task and detaches it

Automatic sync runs while Obsidian is open. Mobile operating systems may suspend background timers, so use Sync now when you need immediate confirmation.

Active and detached tasks

An active Obsidian task contains #todoist and its Todoist counterpart carries the bridge labels.

- [ ] Prepare the agenda #todoist

When a bridge ends, the local task is marked #todoist_detached and/or the Todoist task receives the obsidian_detached label, depending on which side still exists.

- [ ] Prepare the agenda #todoist_detached

Detached tasks no longer synchronize. The detached marker is an audit trail; it does not create a new Todoist task or reconnect the old one.

What is and is not synchronized

Todoist Bridge synchronizes the task's text, open/completed state, reopen state, and ordinary task hashtags as Todoist labels. When creating a Todoist task, it also maps an !!1!!4 marker to Todoist priority, selects a project, and preserves Markdown nesting when the parent task is already bridged. The bridge adds its control labels and an Obsidian link to the Todoist description; the link contains the vault name and note path.

Due dates are not synchronized in either direction. Adding a date to a Markdown task does not set a Todoist due date, and changing a Todoist due date does not edit the note.

The plugin does not continuously run when Obsidian is closed, and mobile background sync is best-effort. Ordinary vault-sync conflicts can still occur when the same note or plugin state is edited concurrently on multiple devices.

Network and data disclosure

Todoist Bridge communicates with Todoist's APIs over the network. It reads Todoist tasks, projects, labels, comments/notes, and lifecycle activity needed to reconcile bridged tasks. It sends the following data to Todoist when required by a sync:

  • task content, completion/reopen state, and ordinary task hashtags as Todoist labels;
  • for newly created tasks, the parsed !!1!!4 priority and any bridged parent-task relationship;
  • Todoist project identifiers and bridge/detached-label changes;
  • an obsidian:// link containing the Obsidian vault name and note path;
  • an ISO completion timestamp in the Todoist description and a completion comment when a task is completed from Obsidian;
  • explanatory comments when a task is detached.

The plugin does not send unrelated note bodies to Todoist. It scans Markdown files locally to find bridge markers and task IDs. Todoist processes data received through its API under Todoist's privacy policy.

Data stored locally

The following files can contain sensitive task metadata. Protect them as you protect the vault itself, and review them before sharing:

  • .obsidian/plugins/todoist-bridge/data.json — plugin preferences and the name of the selected SecretStorage entry; it does not intentionally contain the token value.
  • .obsidian/plugins/todoist-bridge/todoist-bridge-state.json and .bak — runtime state, task IDs and cached task metadata, note paths, projects, labels, the durable work queue, device sync cursors, tombstones, and health information.
  • .obsidian/plugins/todoist-bridge/events/*.jsonl and .bak — retained Todoist lifecycle events. Retention has no count limit, so this archive can grow over time.
  • .obsidian/plugins/todoist-bridge/todoist-completions.log — task IDs, task names, note paths, Todoist URLs, timestamps, and lifecycle status.
  • Markdown reports in the vault root, including todoist_bridge_*.md and todoist_bridgedatabase_check_*.md — user-requested audits, repairs, cache rebuilds, database checks, and diagnostics. Diagnostics redact the API token but can still reveal paths, counts, identifiers, and settings.
  • todoist-backup-*.json in the vault root — a user-requested Todoist account backup containing Todoist resources. This is the most sensitive export.

These runtime, archive, report, and backup files are not encrypted by the plugin. If your .obsidian directory or vault is synchronized to another service, those files may be synchronized by that service too. Delete or retain user-created reports and backups according to your own data policy.

Upgrade and rollback warning

Version 3.0.0 introduces runtime-state schema v2. On first launch it can migrate legacy cached state from data.json and a legacy token into SecretStorage when the host supports it.

Before upgrading, make a full backup that includes the hidden .obsidian/plugins/todoist-bridge directory. Do not downgrade to 2.0.2 while reusing state written by 3.0.0: the older release does not understand the new durable state, outbox, cursors, or tombstones and can produce duplicate or stale synchronization decisions.

To roll back safely, disable the plugin and restore both the older plugin files and the complete pre-upgrade Todoist Bridge data/state from the same backup. If no matching backup exists, do not delete state manually; export diagnostics and request support first.

Recovery tools

The plugin settings include:

  • Bridge health — last-run state and pending outbound work.
  • Audit Todoist Bridge — a dry run that writes a report without changing notes or Todoist.
  • Repair Todoist Bridge — applies Todoist-confirmed completions and rebuilds verified open-task state.
  • Export Todoist Bridge diagnostics — writes a sanitized support report without the API token.
  • Rebuild Todoist Bridge cache — reconstructs local bridge state after verification.
  • Back up Todoist data — writes a Todoist resource export to the vault root.

Run an audit before repair or cache rebuilding. Keep a vault backup before any recovery operation that can change notes or state.

Support and security

  • For reproducible bugs and feature requests, open a GitHub issue.
  • Check existing issues before filing a duplicate.
  • For a suspected security vulnerability, follow the private-reporting instructions in SECURITY.md. Do not include API tokens, private task content, raw state, backups, or unredacted vault paths in a public issue.

When requesting support, include the plugin and Obsidian versions, platform, relevant steps, and the sanitized diagnostics report only after reviewing it.

Maintainer documentation

License

MIT