BIBLIOGRAPHY

History

  • [2025-03-26 Wed 15:14]

매뉴얼

[2025-03-26 Wed 15:15] 그대로 가져왔다. 검토 필요. 동작이 잘 된다.

Org Todoist: What is it?

An Emacs package for bidirectional incremental sync of Org Mode elements with Todoist using org exactly how you normally would in Emacs Org Mode.

![[https://media.githubusercontent.com/media/Lillenne/org-todoist/refs/heads/main/readme-images/demo.png|640]] >

Key features

  • CRUD1 tasks
    • Complete by changing TODO state
    • Cancel by changing TODO state
    • Scheduling
    • Deadlines
    • Effort/Duration
    • Priority
    • Descriptions
    • Tags/Labels
    • Notes/Comments + send notifications to other users
    • Repeating tasks2
    • Assignee3
    • Retains LOGBOOK information (e.g., clocking)
  • CRUD1 new sections
  • CRUD1 new projects
  • Refile tasks and sections to other sections and projects

Org Todoist also supports collaboration with other users via assigning tasks and notifications.

How it works

Commands are automatically detected and batched by diffing the current org-todoist-file with the abstract syntax tree from a snapshot of the previous sync and nodes are updated in place using a single asynchronous request, meaning metadata (such as time tracking information and additional properties) is retained.

Syncing is done using the Todoist sync API, which sends a single request for both pulling and pushing. Local changes will overwrite remote changes!

Installation

Doom Emacs

(package! org-todoist
  :recipe (:host github
           :repo "lillenne/org-todoist"
           :branch "main"
           :files ("org-todoist.el")))

Usage

Bidirectional sync

;; Unless ARG, go to the Todoist buffer.
(org-todoist-sync &optional ARG)

Local changes will overwrite remote changes!

To automatically sync at a given interval, unless the org-todoist-file is visited by the active buffer:

(run-at-time nil 180 #'org-todoist-background-sync)

Mapping org headlines to Todoist objects

OrgTodoist
HeadlineProject, Section, or Task
Plain-text under headlineDescription
ScheduledDue
DeadlineDeadline
EffortDuration
PriorityPriority
Todo-state + Todo-keywordChecked, Deleted
Tags (+inherited)Labels
org-archive-tagArchive projects + sections
Responsible UID propertyAssignee

See the next section to learn the mapping rules for projects, sections, and tasks.

Creating projects, subprojects, sections, tasks, and subtasks

Simply create org headlines! The corresponding Todoist types (projects, subprojects, sections, tasks, and subtasks) will be inferred from the org structure. Sections will be preferred over subprojects unless the TODOIST_TYPE property is set to PROJECT. A new subproject can be created quickly using the interactive function org-todoist-add-subproject. If a TODO item does not fall under a project, it will be assigned to the default section of the Inbox project.

LevelTodoist Type
1Project
2+Section or Subproject
TODOTask

Updating projects, sections, and tasks

Updating items happens automatically when updating any headline, description, todo-state, todo-keyword4, priority, effort, tag, scheduled time, deadline time, or assignee OR when any project, section, or task is moved under another headline. This works with standard org commands (e.g., org-refile).

Deleting items

When the org-todoist-delete-remote-items variable is non-nil, removing items from the org-todoist-file (via deletion or refiling) will cause them to be deleted from Todoist. Additionally, items can be deleted by changing their todo-keyword to the org-todoist-deleted-keyword.

Tags, labels, and archiving

Org tags are mapped directly to Todoist labels and support inherited tags. Note, inherited tags will also be applied directly to the child tasks on next sync.

Projects and sections can be archived in Todoist by applying the org-archive-tag to the headline. Note, you cannot archive the default section and if you do locally on your org document it will not be synced.

Comments and notifications

Comments are done via org-add-note and currently ([2025-01-12 Sun]) do not support editing or deletion from org mode. Within comments, other users can be notified via the org-todoist-tag-user command, which will prompt for completion of the desired user, send a request to notify them in the comment’s note_add command, and input a special markdown syntax into the comment which will property display as @<User> in the Todoist app. If you prefer to use the org link syntax and have it look funny in the Todoist app, set org-todoist-comment-tag-user-pretty to non-nil.

;; Inserts the special tag from the todoist app that formats to @User
;; & adds the user id to uids_to_notify in the request
(org-todoist-tag-user)
 
;; non-nil to format in org link syntax instead of markdown for better viewing in org but worse in the Todoist app
(setq org-todoist-comment-tag-user-pretty nil)

Assigning Tasks

(org-todoist-assign-task) ;; Prompts for user selection and changes the responsible uid property to the user's id
(org-todoist-unassign-task) ;; Removes the responsibile uid property

![[https://media.githubusercontent.com/media/Lillenne/org-todoist/refs/heads/main/readme-images/assign.png|640]] >

Ignoring subtrees

If you’d like to keep other notes or TODOs alongside your projects and not have them synced to Todoist, you can mark a subtree as ignored by setting the TODOIST_TYPE property to IGNORED using M-x org-todoist-ignore-subtree. Any org element descendent from an ignored node will not have its changes pushed to Todoist.

Org capture to a Todoist project section

Captures will automatically sync by default via the org-capture-finalize-hook. If you would like to change this behavior, run (remove-hook 'org-capture-after-finalize-hook #'org-todoist--sync-after-capture).

Sample capture templates:

(setq org-capture-templates `(
        ;; Capture a TODO directly to the inbox
         ("i" "Inbox" entry
         (file+olp ,(org-todoist-file) "Inbox" ,org-todoist--default-section-name)
         "* TODO %?")
         ;; Capture to a specific project, section, and parent task, creating them if needed.
         ;; Also prompts for tags, effort, task assignment, scheduled, and deadline times
         ;; Projects are determined by projectile if possible, otherwise via an interactive prompt
        ("p" "Select project, section, and parent task" entry (function org-todoist--find-project-and-section)
         "* TODO %^{What is the task} %^G %^{EFFORT}p %(org-todoist-assign-task) %(progn (org-schedule nil) nil) %(progn (org-deadline nil) nil)\n%?")
        ;; Capture a note to an ignored subtree
        ("n" "Project Notes" entry (function org-todoist-project-notes) "* %?")))

(Currently) unsupported features

[X] = Implemented

[-] = WIP or implemented with caveats

[ ] = Not currently supported

  • [-] Essential task items
    • [-] Recurring tasks2
    • Quick add
  • [-] Comments
    • [-] Item comments
      • Add and pull (plain-text only)
      • Sort by time added
      • Update
      • Delete
      • [-] Notify other users
    • Project comments
      • Add
      • Update
      • Delete
      • Notify other users

Quirks

  • Once a task has been permanently deleted in Todoist, changing the TODO state in org will be reset back to org-todoist-deleted-keyword on next sync. Todoist does not support reviving permanently deleted tasks.
  • Comments on subtasks are added to both the root task and the subtask on Todoist, which is reflected here.
  • The org element API does not properly parse property drawers if anything besides is put above them (e.g. adding your description above the property drawer), so don’t do that!

Configuration

NOTE: To match Todoist’s 4 priority structure, this package sets the user’s org-priority-highest org-priority-lowest and org-priority-default values.

Required

Org Todoist requires a Todoist API token to function.

(setq org-todoist-api-token "<your-token>")

Additionally, Todoist markdown lists use 4 spaces vs the default 2 spaces for org plain lists. This is compenated for by using a file-local variable in the org-todoist-file header to set org-list-indent-offset to 2 (2 base + 2 offset = Todoist’s 4). However, this means that when accessing the file for the first time, you will be prompted to allow “potentially unsafe” file-local variables. You must accept this or manually set the value otherwise this may cause sync errors.

Optional

  • org-todoist-delete-remote-items - If non-nil, delete items no longer present in the org todoist buffer after the last sync. This will also delete tasks refiled or archived to a separate file from Todoist.
  • org-todoist-file - The file to use for Todoist tasks.
  • org-todoist-use-auto-reminder - If newly created tasks should use Todoist’s default reminder. Default t.
  • org-todoist-show-n-levels - The fold level of the org buffer after sync, with caveats. See docstring. Default show all.
  • org-todoist-todo-keyword - New tasks are given this keyword.
  • org-todoist-done-keyword - Completed tasks are given this keyword.
  • org-todoist-deleted-keyword - Tasks with this keyword are deleted remotely.
  • org-todoist-storage-dir - Directory for storing Todoist sync_tokens and the previous org file for detecting changes to push. If using multiple computers and a synced file solution, this directory must be accessible on all PCs.
  • org-todoist-my-id - (Currently unused) Your todoist ID. This will be inferred if your name is Todoist matches user-full-name. Otherwise, you can set this property to the value of “tid” in the property drawer under “Todoist Metadata” > “Collaborators” > “<your-name>“.

Troubleshooting

For troubleshooting errors, you can use the following variables and methods:

  • org-todoist-log-last-request - Set to non-nil to log the last outgoing request to the org-todoist--last-request variable
  • org-todoist-log-last-response - Set to non-nil to log the last response json to the org-todoist-sync-dir and alist to org-todoist--last-response. Any
  • org-todoist--push-test - Returns the detected diff commands.

Why?

Org mode is an excellent planning and note-taking tool, but struggles in a few areas:

  • Collaboration with others
  • Mobile app features / availability (shoutout to Orgzly for their great android app)
  • Sync between devices (I personally use Syncthing which works well, but will often have conflicts when adding from the widget)

Todoist fills these gaps and, more importantly, my wife uses it.

There is currently another great integration for org-mode and todoist, but it takes a fundamentally different approach (stateless on-demand regeneration using many requests with the REST API vs stateful syncing with a single request to the sync API that can be queried by Orgzly on mobile and buffer creation with org.el vs org-element-api).

Contributing, Issues, and Feature Request

Feel free to submit an issue or feature request! When submitting issues please see the troubleshooting section and attach the response json (or at least the error information). I’ll do my best to address issues timely and evaluate feature additions. I work full time and have two very young (0-3) boys, so if there is a feature you want to add please feel free to submit a PR yourself!

Todoist API Data

My personal test API call data is included in the repo to show the API return format and help my own development but is protected with sops. If you need data for any reason, please use your own.

To test interacting with the Todoist API using curl with your own data, you can use the following commands. Note, Todoist has many great examples using curl in their API documentation.

curl https://api.todoist.com/sync/v9/sync \
    -H "Authorization: Bearer <token> " \
    -d sync_token='sSK9OCkrXyWsUjMU0g6iuS05TwAKhmceWSiL7FCho_p2SRb23dpApCsv9u_P2jyidIDJqjE94dzOeB-1JnipI5wJRl01N8ZdaeTBdMUbxvWZavpF' \
    -d resource_types='["all"]'
curl https://api.todoist.com/sync/v9/sync \
    -H "Authorization: Bearer <token>" \
    -d commands='[
    {
        "type": "item_complete",
        "uuid": "a74bfb5c-5f1d-4d14-baea-b7415446a871",
        "args": {
            "id": "<task-id>"
        }
    }]'

Not on Roadmap

Things that I am not currently planning to implement (myself! you are welcome to!) due to time restrictions or it not being important to my workflow:

  • File attachments
  • Filters (use org agenda for this)
  • Location notifications
  • Updating or deleting comments
  • Markdown support
  • Activity log
  • View options
  • Templates (use org capture templates for this)

Footnotes

  1. CRUD: create, read, update, delete. 2 3

  2. Recurring tasks only support a subset of Todoist scheduling features. e.g. Todoists “every mon, fri” is not easily recreatable using org mode. These tasks should still be pulled down correctly from Todoist on next sync. 2

  3. Assignee is a Todoist-only idea, but is supported via the [BROKEN LINK: Collaboration] commands.

  4. Changing todo-keywords only triggers an update if the todo-state changes or the keyword is the org-todoist-deleted-keyword.