Import Todoist tasks into Obsidian

This page describes how to get to-dos from Todoist into Obsidian in a super flexible way.

If you want to import Obsidian tasks into Todoist, see Make Obsidian and Todoist work better together.

If you want to try Taskbone you can request early access, if you didn't already.


To only get the tasks you want, standard Todoist filter conditions are supported. Use a custom liquid-template to format them in any way you need. This way, you can not only import tasks as Markdown, but also as TODO.txt or Taskpaper.

How to use it

Update the plugin

This feature is supported in plugin version "1.1.1" and higher. You can check for the version in the Obsidian Setting under Community Plugins.

To update the plugin, download the latest version from here and unzip it in the .obsidian/plugins/ directory of your vault, replacing the manifest.json and main.js files in the taskbone directory.

For Obsidian to pickup the changes, you need to restart it.

Create a command

Navigate to the Taskbone settings and click the add command button. A new flow Get open items from Todoist is now available.

Go ahead and create a new command.

Next, go to the command configuration page by clicking the cog-icon next to the newly created command.

As you can see, the command takes two inputs:

  • A Todoist filter for the tasks you want to import
  • A liquid template

In order for anything to happen with the tasks from Todoist you need to add an action and use these settings:

Action Type: Insert at cursor position
Datasource: A property from the output
Property: The formatted tasks

The filter

The filter is a standard Todoist filter expression, as explained here:

Another good explanation of what you can do with filters is here:

If you want to get all open tasks, select constant text and leave the input field empty.

The template

Everybody works a little bit different and has different ways of formatting their to-dos. You can use a liquid template to format the tasks accordig to your needs.

I suggest to put the template in a file in your vault and reference this file in the command configuration.

Here are some examples to get you started:


{%- for task in tasks %}{% capture line %}

{% for num in (1..task.level)%}    {% endfor %}

- [ ] {{ task.title }}

{% for label in task.labelNames %} #{{ label }}{% endfor %}

{% if task.dueDate %} #due::{{task.dueDate}}{% endif %}
 [todoist]({{ task.url }})

{% endcapture %}{{ line | strip_newlines}}
{% endfor %}


{%- assign projects = tasks | map: "projectName" | uniq -%}
{%- for project in projects -%}
{{ project }}:
{% assign filteredTasks = tasks | where: "projectName", project %}

{%- for task in filteredTasks %}{% capture line %}

{% for num in (1..task.level)%} {% endfor %}

- {{ task.title }}

{% for label in task.labelNames %} @{{ label }}{% endfor %}
 @priority({{ task.priority }})
{% if task.dueDate %} @due({{task.dueDate}}){% endif %}
 @todoist({{ task.url }})

{% endcapture %}{{ line | strip_newlines}}
{% endfor %}
{% endfor %}


{%- assign priorities = "0,A,B,C,D" | split: "," -%}

{%- for task in tasks %}{% capture line %}

({{ priorities[task.priority] }}) {{ task.creationDate | date: "%Y-%m-%d" }} {{ task.title }}

{% assign words = task.projectName | split: ' ' %}
{% capture titlecase %}{% for word in words %}{{ word | capitalize }}{% endfor %}{% endcapture %}
 +{{titlecase }}

{% for label in task.labelNames %} @{{ label }}{% endfor %}
{% if task.dueDate %} due::{{task.dueDate}}{% endif %}

{% endcapture %}{{ line | strip_newlines}}
{% endfor %}

Markdown Table

| status | title | created | due | labels | project | link |
| ----| ----- | ------- | --- | ------ | ------- | ---- |

{%- for task in tasks %}
{% capture line %}
{{ task.resolutionState }}
{{ task.title }}
{{ task.creationDate | date: "%Y-%m-%d" }}
{{ task.dueDate }}
{% for label in task.labelNames %} #{{ label }}{% endfor %}
{{ task.url }}
{% endcapture %}{{ line | strip_newlines}}{% endfor %}

Build your own

Right now, there is no really good way to write your own templates in Obsidian. It is possible, but you will not get proper error messages if there is something wrong with the liquid code. While this may be fine for minor changes (or if you really know what you are doing), I would suggest the following workaround:

Use this template to get a JSON representation of your tasks:

{{ tasks | json }}

You can use the result in the liquid playground as context data:

  "tasks": THE OUTPUT OF {{ tasks | json }} GOES HERE!

While this works, it's of course not a very good experience. There will be a better way, soon.

Example setup

I store all templates for formatting tasks in Obsidian in the folder taskbone/templates.

And then have the following commands:

Give me all tasks and prompt for the template

I bound this command to CTRL-T via the standard Obsidian Hotkeys-settings.

Now, when I hit CTRL-T, I get this dialogue to choose the template:

Get a table of tasks (over)due this week

While the first command is very flexible, you may also want to specify more specific parameters. This will get you a table of all tasks that are due this week or overdue: