org.nvim

Quick add (Todoist-style)

Stability: stable (org-extensions-stability)

quickadd adds an entry from one line, the way Todoist's quick add does:

require("org").setup({ extensions = { quickadd = true } })

:Org quickadd [text] (action quickadd, key <prefix>q, available anywhere) adds text, or asks for a line in a small float that previews the parsed entry as you type (with vim.ui.input() when there is no UI). <CR> adds it, <Esc> in Normal mode or <C-c> cancel. The entry goes under its @target, else into file (under headline), and the file is saved. For example

Call Bob fri 3pm #work #phone !A ~30m @Inbox due mon every week

becomes, under the best-matching "Inbox" heading,

* TODO [#A] Call Bob                                      :work:phone:
DEADLINE: <2026-10-05 Mon> SCHEDULED: <2026-10-02 Fri 15:00 +1w>
:PROPERTIES:
:Effort:   0:30
:END:

What the line may contain

  dates        Anything the date prompt reads (org-dates): today,
               tomorrow (tmr), fri, fri 3pm, at 14:30,
               9am-10:30am, +2w, dec 24, 24 dec, 12/24,
               2026-12-24, w45, plus next week, next fri,
               in 3 days and noon. Dates go to SCHEDULED (see
               date_kind); after due (or by) to DEADLINE. A month
               name only counts next to a day number, so "May call Bob"
               stays a title. A weekday, now, noon, midnight or
               tonight on its own is a date only at the end of the
               title (tags and the like may follow) or after at, on
               or due: "Watch Friday Night Lights" stays a title,
               "Meeting on fri with Bob" and "Standup mon 9am with the
               team" get a date. When the line holds several dates, the
               last one counts (the last due one for the deadline), as
               in Todoist; the others stay in the title.
  repeaters    every day|week|month|year, every 2w, every 3 days,
               every other week, every mon (the next Monday, today on a
               Monday). every! repeats from the day it is done (.+).
               Without a date the repeater starts today. It goes on the
               SCHEDULED date, or on the deadline when there is only one.
               every weekday, every weekend and several days
               (every mon and thu, every mon,wed,fri) have no Org
               repeater and are written as a diary sexp,
               <%%(memq (calendar-day-of-week date) '(1 2 3 4 5))>.
  #tag       a tag; #42 (digits only) stays in the title
  !A !1    priority; also p1, p2, p3 (p1 is the highest)
  ~30m       Effort: ~30m, ~1h, ~1h30, ~1:30, ~90, ~1.5h
  @Heading   target: the best match among the headings of the targets
               files (exact, then prefix, substring and fuzzy match);
               @Parent/Child matches outline paths, @file/Heading
               looks in one file (its name without .org), @file/ adds
               at the top level of that file. A heading that doesn't
               exist in a named file is created. When nothing matches the
               entry goes to file and the message says so.
               @"Two words" for spaces.
  *NEXT      keyword instead of keyword; *- for none

Quote words to keep them in the title ("Friday Night Lights", 'due fri'), or escape one character with a backslash (\#1, \fri). :Org quickadd reads the text as typed and completes @ headings (a heading with spaces as @"Big Project"), # tags and * keywords. The preview keeps an index of the headings of the targets files and reads a file again only when it (or its buffer) changed.

Capture templates

A capture template with quickadd = true reads its headline the same way when the capture is stored, so %^{Task} answers or text typed in the capture buffer can hold dates, tags, priorities and efforts. The template's own keyword, tags, planning and properties are kept and completed. An @target sends the entry to that heading instead of the template's target (whose date tree or heading, when the capture made one, is removed again); when it matches nothing, the template's target is used and a warning says so.

capture = { templates = {
  q = { description = "Quick task", template = "* TODO %^{Task}",
        target = "inbox.org", immediate_finish = true, quickadd = true },
} }

Options

  file       file for entries without a target, relative to
             org_directory (nil: default_notes_file)
  headline   headline of file entries go under, created when missing
             (nil: the top level)
  keyword    keyword of new entries ("TODO"); false for none
  date_kind  where dates without due go: "scheduled" or "deadline"
  targets    files @target looks in: "agenda" (the agenda files and
             file) or a list of files and globs
  preview    preview the parsed entry while typing (true)
  created    add a :CREATED: inactive timestamp property (false)
  jump       go to the new entry after adding it (false)

The parser is require("org.extensions.quickadd").parse(text, now), which returns the title, keyword, priority, tags, effort (minutes), dates, the planning timestamps and the target without touching any file.