org.nvim
Emacs Org mode, rebuilt for Neovim in pure Lua.
Outlines · TODOs · Agenda · Capture · Clocking · Spreadsheet tables · Babel · Export
Install · Tour · Features · Docs · Changelog · Contributing
Org mode is one of the most loved tools in Emacs. It works as a plain-text outliner, planner, time tracker, spreadsheet, literate-programming notebook and publishing system. org.nvim puts all of that in Neovim. It isn't a syntax file with a few keymaps on top. It reimplements Org's behaviour: the agenda, capture templates, repeaters, clock tables, table formulas, Babel and export.
- 🪶 No dependencies. It's about 170k lines of Lua and needs no tree-sitter parser, external binary or companion plugin.
- 🔁 Works with Emacs. It reads and writes the same plain-text format, so you can edit a file in Emacs today and in Neovim tomorrow.
- ⌨️ Keys that fit Vim. Context-aware keys fall back to normal Vim
behaviour when they don't apply (
>>still indents,<C-a>still increments). Pressg?in an org or agenda buffer to see what's available. - 💤 Ready for LazyVim. It comes with which-key groups, a blink.cmp source, pickers for snacks.nvim, fzf-lua, Telescope and mini.pick, and a lualine clock, and it works with any other setup too.
- ✅ Tested. The headless test suite runs 4,800+ tests from 240+ spec files.
🤔 Why another Org plugin?
There are already good ways to write Org files in Neovim, above all nvim-orgmode, which has been around for years and is used by many people. If it does what you need, keep using it. Neorg is another fine option, though it uses its own format rather than Org.
org.nvim exists because I wanted something those projects don't aim for:
- Full parity with Emacs Org. The goal is to behave like Org 9.8,
including the parts that are hard to port: Babel with sessions and
:var, a port of the export engine, clock tables,#+TBLFMformulas with a Calc-compatible evaluator, and image and LaTeX previews. Where org.nvim differs, it says so (Differences from Emacs Org mode and:h org-differences). - A different architecture. It's pure Lua with its own Org parser, where nvim-orgmode is built on a tree-sitter grammar. That's a foundational choice, not something a pull request could change.
- Speed. Adding everything above to an existing project would mean big design changes and a slow review cycle, so I built it separately.
- Keys that feel right in both worlds. The Emacs Org keys work as they do in Emacs, and the Vim-style keys fall back to normal Vim behaviour when they don't apply.
On AI: org.nvim is written with AI assistance
(Claude Code). To keep that honest, its
behaviour is checked against the Emacs Org source rather than guessed,
every feature comes with headless tests (make test, 4,800+ of them), and
I review and use every change myself. Bug reports are very welcome,
especially where it doesn't match Emacs.
⚡ Install in 30 seconds
With lazy.nvim / LazyVim:
-- ~/.config/nvim/lua/plugins/org.lua
return {
"xheisenbugx/org.nvim",
main = "org",
lazy = false, -- startup cost is small: heavy modules load on first use
opts = {
org_directory = "~/org",
agenda_files = { "~/org/**/*.org" },
default_notes_file = "~/org/refile.org",
},
}
Restart Neovim and run :checkhealth org. Then open
examples/tutorial.org, a hands-on tour with a
section and exercises for every feature. To try it without touching your
config or your notes, run it from a checkout with the bundled init file:
nvim -u examples/minimal_init.lua examples/tutorial.org
To go deeper into one feature, open
examples/00-index.org. It links to one file per
feature area (outlines, TODOs, the agenda, tables, spreadsheet formulas,
Babel, export and more), each with many examples, exercises and the result
you should expect.
🎬 A quick tour
Everything below was recorded in a plain Neovim with only org.nvim
installed. The tapes that produce these GIFs live in
docs/media/tapes, so they can be re-recorded after
every change. They use docs/media/demo/init.lua,
which changes a few defaults: it logs CLOSED: on DONE, opens the agenda
on the day, offers every top-level heading of the agenda files as a refile
target, and puts the clock in the statusline.
In the newer demos, the box in the bottom-right corner shows the key being
pressed.
Outlines that fold like Emacs
TAB cycles a subtree through folded, children and everything.
S-TAB does the same for the whole file. You can move a subtree with all
of its children (<leader>oK / <leader>oJ or M-k / M-j), promote and
demote it, or cut, paste and sort it.

Structure editing
M-RET adds a heading (or an item) at the right level,
and <leader>oit adds a TODO heading. M-h / M-l promote and demote.
<leader>ohs sorts the children (alphabetically, by TODO state, priority,
date and more), and <leader>ohn narrows to a subtree so you can edit it
on its own.

TODOs, checklists and priorities
Ticking a checkbox updates the [2/4] and [50%] cookies of its parents.
Marking a task DONE updates its parent's cookie and, with
log_done = "time" (or #+STARTUP: logdone), logs a CLOSED: timestamp.
Set the state with cit or with the fast-selection menu (<leader>oS), and the
priority with <leader>o,.

Plain lists
S-Right / S-Left on an item cycles the bullet style of its list: -,
+, * (in indented lists), 1. and 1). M-RET adds an item and
M-S-RET adds a checkbox item. TAB on a new empty item indents it.
M-Up / M-Down move an item with its children, and numbered lists are
renumbered as you go. <leader>o- turns plain lines into a list.

Tags and properties
<leader>ot opens fast tag selection: one key per tag, with mutually
exclusive groups like { @office @remote }. <leader>oxe sets the effort
from Effort_ALL, and <leader>op sets any property.

Dates with a real calendar
<leader>os (schedule) and <leader>od (deadline) open a floating
calendar with week numbers, today and weekends marked, and a preview of
the chosen date ("in 3 days"). Move around it with hjkl, or press i
and type a date the way you'd say it: fri 14:00, +2w, sep 15, w39.
Its colors are OrgCalendar* highlight groups (:h org-calendar).

You don't need the calendar to change a date. S-Right / S-Left move it
by a day, <C-a> / <C-x> (or S-Up / S-Down) change the part under
the cursor (year, month, day, hour or minutes, rounded to 5), and <CR>
on a date opens the agenda for that day.

A real agenda
<leader>oa → a opens the week, or the day with
agenda = { span = "day" }. The day view has a time grid, a current-time line, deadline
countdowns, overdue items and a habit consistency graph, the same as in
Emacs. From the agenda you can change states, reschedule, clock in,
refile, filter and run bulk actions. vd / vw switch between day and
week.

The week view

The dispatcher has the other Emacs views too: every TODO (t), a
tags/property match (m, here +oss) and a word search (s).

Capture from anywhere
Press <leader>oc in any buffer and pick a template. Templates can be
grouped under a prefix key (w → t here). Type the task and finish with
<C-c><C-c> or :w. It's filed where the template says: under a
headline, an outline path or a date tree.

Refile and archive
<leader>or moves a subtree under another heading: by default a
top-level heading of the current file, or any heading in your agenda files
with refile = { max_level = N } (here labelled with the file name,
use_outline_path = "file"). <leader>o$ archives a finished subtree to
<file>_archive and keeps its context in ARCHIVE_* properties.

Spreadsheet tables
Type a rough table, press <C-c><C-c> on its #+TBLFM line, and it
aligns itself and evaluates its formulas with a Calc-compatible evaluator.
Change a value, recalculate with <leader>oTf, and the totals follow.

Rows and columns are easy to edit. <leader>oTr / <leader>oTi insert a
row or a column, M-j / M-k and M-h / M-l move them, and
<leader>oTR / <leader>oTI delete them. Formulas in #+TBLFM are
rewritten to follow the moves.

<leader>oTs sorts the rows (alphabetically, numerically, by date or with
a function), and <leader>oTt transposes the table. Type := followed by
a formula in a field to add a field formula to #+TBLFM.

Code that runs in your notes
<C-c><C-c> on a source block runs it asynchronously and writes the
output back into the file:

Python, shell, Lua (in-process), Node, Ruby, R, Go, SQLite and more are
supported, along with :var, :noweb, :wrap, :cache, #+CALL,
inline src_lang{…} blocks and tangling. Nothing blocks the editor while
code runs (except Lua, which runs inside Neovim); :session keeps a live
REPL between blocks (C-c C-v C-z opens it so you can type into it), and
:session :async writes a placeholder result right away, as in Emacs.
<leader>o' opens a block in its own buffer with the language's filetype,
so it gets that language's highlighting, indentation and filetype plugins.
<C-c>' writes it back.

Clocking, clock tables and column view
<leader>oxi clocks in, and require("org").statusline()
shows the running total against the effort estimate. <leader>oxr inserts
a clock table that matches Emacs's output. <leader>oC opens column view,
drawn over the headlines like Emacs, which sums efforts and clocked time
up the tree.

Images and LaTeX, right in your notes
<leader>oxv (C-c C-x C-v) shows image links as images in place of the
link, like Emacs, and <leader>oxl (C-c C-x C-l) renders LaTeX
fragments. On Neovim 0.13+ they're drawn by the built-in vim.ui.img in
any terminal with the Kitty graphics protocol (kitty, Ghostty, WezTerm).
They follow scrolling, folds and splits, and the link text comes back on
the cursor line so you can edit it. On older Neovim, or inside tmux,
org.nvim uses snacks.nvim's image
module or image.nvim instead.
#+STARTUP: linkpreviews and latexpreview turn them on when a file
opens.

LaTeX is rendered in the background with latex + dvipng like Emacs, or
with tectonic / pdflatex, in your colorscheme's text color, and the
results are cached:

These two were recorded in a real kitty window
(docs/media/kitty); VHS can't show Kitty graphics.
Where do image previews work? (tmux, Neovim versions, terminals)
Previews depend on the Neovim version, the terminal, and what sits
between them. :checkhealth org shows what it found, and
:h org-images-troubleshooting has the details.
| Setup | What draws the images | Notes |
|---|---|---|
| Neovim 0.13+ in kitty or Ghostty | vim.ui.img (built in) | Everything works, including :align |
| Neovim 0.13+ in WezTerm | vim.ui.img | WezTerm's Kitty graphics support is partial |
| Neovim 0.11–0.12 | snacks.nvim or image.nvim | vim.ui.img needs 0.13 |
| Inside tmux | snacks.nvim | tmux drops vim.ui.img's images. Add set -g allow-passthrough on and install snacks.nvim, or run Neovim outside tmux |
| Inside zellij | nothing | zellij doesn't pass images through |
| Over SSH | vim.ui.img or snacks.nvim | Images and LaTeX tools must be on the machine running Neovim |
| Terminal.app, iTerm2, Alacritty, Windows Terminal, GNU screen | image.nvim at best | No Kitty graphics protocol |
With snacks.nvim or image.nvim, :align / org-image-align are ignored,
and when the link has text around it, snacks.nvim draws the image at the
start of the next line and puts an icon at the link.
Jump to any heading
<leader>o. (Emacs C-c C-j) jumps to a heading of the current file.
By default it opens Emacs's org-goto outline, a read-only copy of the
buffer you browse and jump from. With goto_interface = "outline-path-completion" (shown here) it's a picker instead, and a count
switches to the other interface for one jump. <leader>og jumps to any
heading of your agenda files. The pickers use vim.ui.select, so they get
your picker: snacks.nvim here, or Telescope / fzf-lua once they're set up
as the vim.ui.select provider. The pick_* actions talk to
those pickers directly, with a preview of each heading.


Timers
<C-c><C-x>0 starts a relative timer, and <C-c><C-x>- adds a list item
with the elapsed time, handy for meeting notes. <C-c><C-x>, pauses and
resumes it, and <C-c><C-x>_ stops it. The running time is part of the
statusline component.

<C-c><C-x>; starts a countdown for the current entry and notifies you
when it runs out:

Appointment reminders
With notifications.enabled (or :Org notifications_start), org.nvim
checks your agenda for timed entries and reminds you before they start,
by default 12, 9, 6, 3 and 0 minutes before, through vim.notify and the
system notifier (osascript, notify-send, or PowerShell on Windows).

Footnotes
<leader>oif (C-c C-x f) inserts a footnote reference and its
definition, in a Footnotes section or inline. <C-c><C-c> jumps between a
reference and its definition. A count sorts, renumbers or normalizes them.

Checking a file with org-lint
:Org lint runs the org-lint checks, such as misplaced planning lines,
broken property drawers, links to missing IDs or files and src blocks
without a language, and lists the problems in the location list.

Speed keys
With use_speed_commands = true, single letters typed at the very start
of a heading in Insert mode run commands, like Emacs's speed keys: n /
p to move, t for the TODO state, U / D to move the subtree, c to
cycle, and ? for the full list.

Links
<leader>ols stores a link to the current heading (or file, line or ID),
and <leader>oli inserts it with completion. Links show only their
description. <CR> follows them, and <leader>olt shows the raw text.

Sparse trees
<leader>o/ folds the file down to what matters: TODO entries, a regexp,
a tag or property match, or deadlines. The matches are highlighted, and
<C-c><C-c> clears the highlights.

Export
<leader>oe opens the export dispatcher. The HTML, LaTeX, Beamer, KOMA
letter, man page, Markdown, ASCII, Org, iCalendar, ODT and Texinfo
back-ends are ports of Emacs's, there's a GitHub-flavoured Markdown
back-end, and pandoc handles DOCX, EPUB and more. You can export to a
buffer to check the result:

Every key, one press away
Lost? Press g? in any org or agenda buffer to list every keymap
available there, grouped by topic (visibility, structure, dates, clock,
tables, Babel…), with each command's Vim and Emacs keys on one row. /
searches it, and { / } jump between sections:

✨ Features
| Area | Highlights | |
|---|---|---|
| 🌳 | Outline | Headline folding with Emacs-style TAB/S-TAB cycling, #+STARTUP and VISIBILITY visibility, archived subtrees that stay folded, motions (]] [[ g{), and text objects (ih ah ir ar) |
| ✂️ | Structure editing | A context-aware M-RET, promote and demote, move, cut/copy/paste/clone subtrees, sort, narrow, structure templates |
| 📋 | Plain lists | Every bullet style, checkboxes with a [-] partial state, [2/5] and [40%] statistics cookies, renumbering, TAB on a new item to indent it |
| ✅ | TODO | Multiple keyword sequences, fast selection, !/@ logging, LOGGING / LOG_INTO_DRAWER properties, repeaters (+1w, ++1d, .+2d, REPEAT_TO_STATE), ORDERED / NOBLOCKING dependencies, tag triggers, #+TYP_TODO type sequences, priorities |
| 🏷️ | Tags and properties | Fast tag selection with groups, tag changes over a selection, inheritance, #+FILETAGS, property drawers, Effort, _ALL values cycled with S-Left/S-Right |
| 📅 | Dates | A floating calendar that understands +2w, fri 14:00, sep 15 and w39; SCHEDULED/DEADLINE with warning and delay periods; <C-a>/<C-x> on any part of a timestamp, minutes rounded to 5; custom timestamp formats (C-c C-x C-t) in the buffer and in export; Emacs's org-duration units and formats |
| 🗓️ | Agenda | Day to year views, a time grid, habits, log, clock-report, entry-text and archive modes, the full Emacs match syntax, custom composite commands, tag/category/effort/regexp filters, bulk actions, follow mode, restriction lock, PDF/PostScript export, calendar conversions, moon phases, sunrise/sunset and holidays, the Emacs diary file and every diary sexp of Emacs's calendars |
| 📥 | Capture | Grouped templates; entry, item, checkitem and table-line types; file, headline, outline-path, date-tree, regexp, ID, clock and function targets; all the common %-escapes; :unnarrowed captures in the target file, org-extend-today-until for dates, Emacs Lisp %(sexp) escapes |
| 📦 | Refile and archive | Refile or copy subtrees or regions, with Emacs-style target specs, outline-path completion in steps and refile logging; archive to a file, heading, date tree or Archive sibling with the ARCHIVE_* context properties; refile cache; notes in the *Org Note* buffer |
| 🔗 | Links | file: with ::line, ::*heading, ::#id and ::/regex/; id:, <<targets>>, <<<radio targets>>>, coderefs, shell: (with an *Org Shell Output* buffer), elisp:, wildcard file:*.org listings, attachment:, abbreviations, custom types, concealed display, store/insert last/all links |
| ⏱️ | Clocking | Clock in/out/cancel/jump, clock history with default and interrupted tasks, Emacs's clock resolution (keep, subtract, got-back) for dangling clocks and idle time, auto clock-out, effort estimates with an overrun alert, a statusline component, clocktable blocks matching Emacs output (:step, :formula, :sort, :lang…), agenda clock check, relative and countdown timers |
| 🧮 | Tables | Automatic alignment, column shrinking, row/column/cell editing with formula fixing, copy-down, CSV/TSV import and export, #+TBLFM formulas with a Calc-compatible evaluator, a formula editor and debugger, radio tables, orgtbl-mode (including the unicode and table.el translators) and plots (including radar); Calc symbolic algebra (simplify, deriv, integ, solve), vectors and matrices, modulo forms, complex numbers, HMS forms, error forms, intervals and units; table.el grid tables (C-c ~, C-c ', export) |
| 🧪 | Babel | Asynchronous execution in many languages, :session as live REPL buffers (shells, Python, Node, Ruby, R, Lua) with :async, inline src_lang{…} blocks and call_name(), :results, :var references that evaluate blocks (name(x=1), slices, other files, IDs), :noweb, :wrap, :cache, :file, #+CALL, Library of Babel, tangling, optional evaluation on export, the C-c C-v commands, and editing a block in its own buffer with C-c '; emacs-lisp blocks run in a separate Emacs when one is installed |
| 📤 | Export | A port of Emacs's export engine (with #+BIND and (eval …) macros): HTML, LaTeX/PDF, Beamer, KOMA letters, man pages, Markdown, ASCII, Org, iCalendar, ODT and Texinfo/Info back-ends matching Emacs output, GitHub-flavoured Markdown, citations with the CSL processor, publishing projects, every #+OPTIONS key, plus DOCX, EPUB and more through pandoc |
| 🖼️ | Images and LaTeX | Image links and LaTeX fragments previewed in place of the link (org-link-preview, -region, -clear, -refresh, org-latex-preview) with Neovim 0.13's vim.ui.img, or snacks.nvim / image.nvim on older versions; org-image-actual-width, #+ATTR_ORG: :width / :align, images as link descriptions, previews on TAB, #+STARTUP: linkpreviews latexpreview, the Emacs LaTeX processes (dvipng, dvisvgm, xelatex, imagemagick) plus tectonic, images in ltximg/, preview functions for custom link types, remote http(s) images |
| 🧩 | Extensions | Optional, off until enabled: slideshows (org-present), queries and saved views (org-ql), linked notes (org-roam), grouped agendas (org-super-agenda), Todoist-style quick add, a guided weekly review, pomodoros (org-pomodoro), flashcards with spaced repetition (org-drill), an in-process language server (symbols, hover, cross-file rename), kanban board, timeline, clock heatmap and Today sidebar, code ↔ notes links and literate Neovim config, a structural git merge driver, iCalendar subscriptions, the org command line, mermaid/dot/plantuml diagrams, and live transclusion (org-transclusion) |
| 🎁 | And more | Column view, org-indent mode, speed keys, footnotes, sparse trees, org-lint, entry encryption (org-crypt), org-protocol, inline tasks, org-num, pretty entities, appointment notifications, attachments (with org-attach-git), RSS/Atom feeds (org-feed), MobileOrg, IDs, dynamic blocks, BibTeX links (ol-bibtex), org-ctags, the Org/table/agenda menus and org-mouse, completion, :checkhealth org |
The full reference is in :h org.nvim (doc/org.txt), and
on the documentation website
together with the examples, searchable.
📚 Contents
- Requirements
- Installation
- Quick start
- Keymaps
- Configuration
- Capture templates
- Custom agenda commands
- Completion
- Pickers
- Statusline
- Lua API
- Parity with Emacs Org
- Differences from Emacs Org mode
- Extensions
- Roadmap
- Contributing
Requirements
- Neovim 0.11+ on Linux, macOS or Windows. Nothing else is required
(Windows notes:
:h org-windows). - Optional:
pandocfor DOCX, EPUB and the other formats without a native back-end (HTML, LaTeX, ODT, Texinfo and the rest are built in).latexmk,pdflatex,xelatexorlualatexfor PDF, andmakeinfofor Info.- The language interpreters you want Babel to run.
- For image and LaTeX previews: Neovim 0.13+ in kitty, Ghostty or
WezTerm (or snacks.nvim / image.nvim), ImageMagick for non-PNG images,
and
latex+dvipngortectonicfor LaTeX.
Installation
LazyVim / lazy.nvim, with blink.cmp completion
-- ~/.config/nvim/lua/plugins/org.lua
return {
{
"xheisenbugx/org.nvim",
main = "org",
lazy = false,
opts = {
org_directory = "~/org",
agenda_files = { "~/org/**/*.org" },
default_notes_file = "~/org/refile.org",
},
},
-- completion in blink.cmp (LazyVim default)
{
"saghen/blink.cmp",
optional = true,
opts = {
sources = {
per_filetype = { org = { inherit_defaults = true, "org" } },
providers = { org = { name = "Org", module = "org.completion.blink" } },
},
},
},
}
Other plugin managers
Add the plugin to your 'runtimepath' and call:
require("org").setup({
org_directory = "~/org",
agenda_files = { "~/org/**/*.org" },
default_notes_file = "~/org/refile.org",
})
Local development checkout
Point lazy.nvim at the directory instead of a GitHub repo:
{
dir = "~/path/to/org.nvim",
name = "org.nvim",
main = "org",
lazy = false,
opts = { --[[ … ]] },
}
Restart Neovim (or run :Lazy reload org.nvim) and check the result with
:checkhealth org.
Tip
Keymap prefix. All org commands live under <leader>o by default. If
another plugin already uses it (obsidian.nvim, overseer), set
mappings = { prefix = "<leader>O" } or any other prefix.
Quick start
mkdir ~/organd open~/org/todo.org.- Type
* TODO Buy milk, press<Esc>, then<leader>osand<CR>to schedule it for today. <leader>oa→aopens the weekly agenda.tchanges the state of the entry under the cursor, and<CR>jumps to it.<leader>oc→tcaptures a new task from anywhere. Finish with<C-c><C-c>or:w.- Press
g?in any org or agenda buffer to list its keymaps.
Keymaps
<prefix> is mappings.prefix (default <leader>o). Every mapping can be
changed or disabled (false) under mappings.<section>.<action>. Keys
marked (ctx) depend on what's under the cursor. When they don't apply,
they fall back to the normal Vim behaviour (>> still indents plain text,
<C-a> still increments numbers).
Emacs keys
Coming from Emacs? The standard Org keys work out of the box, on top of
the Vim-style ones: C-c C-t, C-RET / C-S-RET, C-c C-s / C-c C-d,
C-c ., C-c C-q, C-c C-w, C-c C-x C-i / C-c C-x C-o, C-c C-l,
C-c C-e, C-c ', C-c C-v e, C-c =, C-c -, C-c ^ and about 150 more.
Context-sensitive keys behave as in Emacs (C-c - adds an hline in a table,
cycles a bullet on an item and toggles an item elsewhere). Use a count in
place of C-u: 4<C-c>. inserts a timestamp with the time.
The full list is in :h org-emacs-keys. Turn them off with
mappings = { emacs = false, emacs_insert = false, emacs_global = false }.
Global
| Key | Action |
|---|---|
<prefix>a | Agenda dispatcher |
<prefix>c | Capture |
<prefix>g | Go to any heading in the agenda files |
<prefix>ls | Store a link to the current location |
<prefix>xj / xo / xq | Go to clocked task / clock out / cancel clock |
Org buffers (click to expand)
| Key | Action |
|---|---|
<Tab> / <S-Tab> | Cycle subtree / global visibility (ctx: in insert mode, next table field or cycle the level of a new empty heading/item) |
<C-c><C-c>, <prefix><CR> | Context action: toggle checkbox, align/recalc table, run src block, update dblock/clock line/cookie, set tags on headline, property menu on a property line, clear sparse-tree highlights… |
<CR>, gx, <prefix>o | Open link / footnote / date at point (ctx) |
<M-CR> / <M-S-CR> | New heading, item or row / new TODO heading or checkbox item |
<prefix>ih it is | Insert heading / TODO heading / subheading |
<prefix>id ib if i@ | Insert drawer / block template / footnote (on a footnote: jump; count: sort/renumber/normalize/delete menu) / citation |
<< >> / <s >s | Promote/demote heading or item / subtree (ctx) |
<M-h> <M-l> (also <M-Left> <M-Right>) | Promote / demote heading or item (Visual: every headline); move table column (ctx) |
<M-k> <M-j> (also <M-Up> <M-Down>) | Move subtree, item or table row up / down (ctx) |
<M-H> <M-L> <M-K> <M-J> | Subtree promote/demote; table delete/insert column, delete/insert row; on a CLOCK timestamp move it and the touching clock; elsewhere drag the line up/down (ctx) |
<prefix>K / <prefix>J | Move subtree up / down |
<prefix>hy hd hp hc | Copy / cut / paste / clone subtree |
<prefix>hs hn hC hA hb | Sort / narrow / toggle COMMENT / toggle ARCHIVE tag / cycle bullet |
<prefix>* / <prefix>- | Toggle heading / list item |
cit / ciT / <prefix>S | Next / previous / select TODO state |
<S-Right> <S-Left> | Next/previous TODO; date ±1 day; next/previous allowed property value; cycle bullet (ctx) |
<S-Up> <S-Down> | Priority or timestamp part up/down; previous/next list item; move table field (ctx) |
<C-a> <C-x> | Timestamp part or priority cookie up/down; numbers elsewhere (ctx) |
<prefix>, t p P | Priority / tags (Visual: add/remove a tag on each headline; count: realign all) / set property / delete property |
<prefix>s d i. i! | Schedule / deadline / active / inactive timestamp |
<C-Space>, <prefix># | Toggle checkbox (Visual: every item; count 4: add/remove the box, 16: [-]) / update statistics cookies |
<prefix>xi xo xq xj | Clock in (count: pick from history) / out / cancel / goto |
<prefix>xe xE xm xz | Set effort / next allowed effort / change clocked effort / resolve open clocks |
<prefix>xr xd xu xU C | Insert clocktable / show clock sums / update dblock(s) / column view |
<prefix>li ls lt ln lp lI | Insert / store link, toggle link display, next/prev link, create ID |
<prefix>lL lA lg ly | Insert last / all stored links, go to ID, copy ID |
<prefix>r R $ A | Refile / copy to a refile target / archive subtree / attachments |
<prefix>/ e | Sparse tree / export dispatcher |
<prefix>E v nb ne | Emphasize / mark element / narrow to block / narrow to element |
<prefix>xv xV xl | Toggle image previews / refresh them / toggle LaTeX previews |
<prefix>Tc T- Tf Ts Tr TR Ti TI | Table: create/convert, hline, recalc, sort, insert/delete row, insert/delete column |
<prefix>Tt T#, <S-CR>, <S-arrows> | Table: transpose, rotate recalc mark, copy field down (with increment), swap field with neighbour |
<prefix>' | Edit src block or table formulas in a separate buffer |
<prefix>be bb bs bt bk bn bp | Babel: execute block/buffer/subtree, tangle, remove result, next/prev block |
<prefix>bv bd bg br bo bj bi | Babel: expand, split/wrap, go to named block/result, open result, insert header arg, ingest library |
<prefix>bz bZ bl bK | Babel sessions: show session, show session + edit block, load block into session, kill session |
]] [[ ][ [] g{ <prefix>. | Next/prev heading, next/prev sibling, parent, pick heading |
ih ah ir ar | Text objects: heading section / subtree |
g? | Show all keymaps |
Agenda buffer (click to expand)
| Key | Action | Key | Action |
|---|---|---|---|
f / b / . | later / earlier / today | vd vw vt vm vy | day / week / fortnight / month / year |
gd | go to date | r | redo |
<CR> / <Tab> / <Space> / L | switch to / go to / show / show and recenter | F | follow mode |
t, <C-S-Right/Left> | change TODO | , + - | set/raise/lower priority |
: / T | set / show tags | s / d | schedule / deadline |
<S-Right> / <S-Left> / > | date +1 / −1 / prompt | e / <C-c><C-x>p | effort / property |
I O X J | clock in / out / cancel / goto | R / $ / a | refile / archive / archive with confirmation |
<C-c><C-x>A / <C-c><C-x>a | archive sibling / ARCHIVE tag | <C-k> / <C-c><C-o> | delete entry / open link |
z | add note | K / c | capture (at the date at point) / jump to a date from the calendar |
l vL / C | log mode (all) / clock report | E / vG | entry text / time grid |
va / vA / v[ | archived trees / archive files / inactive timestamps | / \ < = _ ^ | | filter / filter tag / category / regexp / effort / top headline / clear |
[ ] { } | add +word / -word / +{re} / -{re} to the query | n / p, <C-c><C-n/p> | next / previous item, date line |
m u U B | mark / unmark / unmark all / bulk action | <M-m> * <M-*> % | toggle / mark all / toggle all / mark regexp |
<C-x><C-s> / <C-x><C-w> | save org buffers / export agenda | q / Q / x | quit / quit and wipe / exit (also closes files the agenda opened) |
More agenda keys (habits, diary, follow mode, clock check, block
navigation…): g? in the agenda or :h org-agenda-keys.
Capture and edit buffers (click to expand)
| Key | Capture | Edit src (C-c ') |
|---|---|---|
<C-c><C-c>, <prefix>w, :w | finalize | — (<C-c><C-c>, <prefix>e: send to the block's :session) |
<C-c>', <prefix>' | — | save and exit (:w writes back) |
<C-c><C-k>, <prefix>k | abort | abort |
<C-c><C-w>, <prefix>r | refile | — |
Configuration
Every option with its default is in lua/org/config/
and documented in :h org-config. The most common ones:
require("org").setup({
org_directory = "~/org",
agenda_files = { "~/org/**/*.org", "~/work/notes.org" },
default_notes_file = "~/org/refile.org",
todo_keywords = { "TODO(t) NEXT(n) WAITING(w@/!) | DONE(d!) CANCELLED(c@)" },
log_done = "time", -- false | "time" | "note"
log_into_drawer = "LOGBOOK",
tags = { "work(w)", "home(h)", "{", "@office(o)", "@remote(r)", "}" },
tags_column = -77,
startup_folded = "overview",
deadline_warning_days = 14,
agenda = { span = "week", start_on_weekday = 1, window = "current" },
capture = { templates = { --[[ see below ]] } },
refile = { max_level = 3 },
notifications = { enabled = true, reminder_time = { 10, 0 } },
ui = {
bullets = { "◉", "○", "✸", "✿" }, -- or false
checkboxes = { " ", "◐", "✓" }, -- or false
hide_emphasis_markers = false,
indent_mode = false, -- org-indent-mode
todo_keyword_faces = { WAITING = ":foreground #e0af68 :weight bold" },
},
mappings = {
prefix = "<leader>o",
org = { toggle_checkbox = "<C-Space>", open_at_point = { "<CR>", "gx" } },
agenda = { goto_date = "gd" },
},
})
Capture templates
capture = {
templates = {
t = { description = "Task", template = "* TODO %?\n %U\n %a", target = "~/org/refile.org" },
w = "Work", -- a group: w → wt, wm
wt = { description = "Work task", template = "* TODO %? :work:", target = "~/org/work.org", headline = "Inbox" },
wm = { description = "Meeting", template = "* %^{Who} %^g\n %T\n %?", target = "~/org/work.org", olp = { "Meetings" }, clock_in = true },
j = { description = "Journal", template = "* %<%H:%M> %?", target = "~/org/journal.org", datetree = true },
c = { description = "Checklist item", type = "checkitem", template = "[ ] %?", target = "~/org/todo.org", headline = "Shopping" },
l = { description = "Log line", type = "table-line", template = "| %U | %^{Amount} | %^{What} |", target = "~/org/log.org", headline = "Expenses", immediate_finish = true },
},
window = "split", -- "split" (like Emacs) | "float" | "vsplit" | "tab" | "current"
}
Target options:
target: the file to capture into (""or none:default_notes_file).headline: a headline in the target, created if it doesn't exist.olp: an outline path, as a list of headlines (they must exist).datetree:true, or{ tree_type = "week" | "month" | { "year", "quarter", ... } }.regexp: a Vim regexp; the text goes where the first match ends.func/location: functions choosing the position (file+function / function targets).id: insert under the entry with this ID.target = "clock": insert under the task being clocked.
Without any template, Emacs's "t" Task template is used (a TODO under
"Tasks" in default_notes_file). capture.templates_contexts limits
templates to some buffers (org-capture-templates-contexts).
Other options: type, prepend, empty_lines, table_line_pos,
properties, immediate_finish, jump_to_captured, kill_buffer,
refile_targets, clock_in, clock_keep, clock_resume,
time_prompt, no_save, and the prepare_finalize, before_finalize
and after_finalize hook functions.
Template expansions (click to expand)
| Escape | Inserts |
|---|---|
%? | cursor position |
%t %T %u %U | date / date+time, active / inactive |
%^t %^T %^u %^U | same, but prompts with the calendar |
%<%Y-%m-%d> | strftime format |
%a %A %l %L | annotation link: plain / with description prompt / without description / bare target |
%i | initial content (the visual selection), the text before it repeated on each line |
%x %c | clipboard / last yank |
%f %F | origin file name / full path |
%n | your full name |
%^{prompt|default|opt} | prompt with a default and options |
%\1 %\*1 | the answer to the first %^{...} prompt / to the first prompt of any kind |
%^g %^G | tags prompt |
%^{PROP}p | property prompt |
%k %K | the running clock's task / a link to it |
%(expr) | the value of an Emacs Lisp form, as in Emacs (a Lisp subset, else a separate Emacs); a Lua expression also works |
%[file] | the contents of a file |
\% | a literal % before an escape character (%% is not an escape, as in Emacs) |
Custom agenda commands
agenda = {
custom_commands = {
w = {
description = "Work overview",
types = {
{ type = "agenda", span = "day", header = "Today" },
{ type = "tags_todo", match = "+work-someday/!", header = "Open work tasks" },
{ type = "todo", match = "WAITING", header = "Waiting for" },
},
},
u = { description = "Urgent", type = "tags", match = 'PRIORITY="A"|+urgent' },
},
}
Block types: agenda, todo, tags, tags_todo, search, stuck.
Per-block options: match, header, span, start_day, files,
skip = function(headline) … end, and the todo_ignore_* flags.
Like Emacs' org-agenda-skip-entry-if, require("org.agenda").skip_entry_if("scheduled", "deadline")
and skip_subtree_if("regexp", ":someday:") build skip functions.
The match syntax is the same as in Emacs. Some examples:
+work-bosswork|homeLEVEL>1Effort<"1:00"SCHEDULED<="<+2d>"+proj/NEXT|TODO/!(only entries that aren't done)
Completion
- blink.cmp: add the provider shown in Installation.
- nvim-cmp:
require("cmp").register_source("org", require("org.completion.cmp").new())Then add
{ name = "org" }to your org sources. - Built in:
<C-x><C-o>(omnifunc).
It completes TODO keywords, tags, #+ keywords, #+STARTUP and
#+OPTIONS values, src block languages, property names, link types,
headings ([[*), custom IDs ([[#) and stored links.
Pickers
The pick_* actions open a fuzzy picker with a preview, using the first
one you have installed: snacks.nvim,
fzf-lua,
telescope.nvim or
mini.pick, else vim.ui.select.
Set picker = "snacks" | "fzf-lua" | "telescope" | "mini" | "select" to
choose. None of them is required, and none is loaded until a picker opens.
| Action | Picks |
|---|---|
pick_headline / pick_headline_all | a heading of this file / of the agenda files (TODO, priority and tags shown) |
pick_tag | a tag, then a heading with it |
pick_set_tags | tags to toggle on the heading (multi-select; typing a new one adds it) |
pick_agenda / pick_agenda_week / pick_todo | an entry of today's agenda / the next 7 days / the TODO list |
pick_agenda_file, pick_capture_template | an agenda file, a capture template |
They have no default keys; bind them like any action:
mappings = { global = { pick_headline_all = "<leader>fo", pick_todo = "<leader>ft" } }
Telescope users can also require("telescope").load_extension("org") and
run :Telescope org headlines. The roam extension's node finder uses the
same picker. See :h org-pickers.
Statusline
-- lualine (LazyVim)
{
"nvim-lualine/lualine.nvim",
optional = true,
opts = function(_, opts)
table.insert(opts.sections.lualine_x, 1, { function() return require("org").statusline() end })
end,
}
While a clock runs, it shows something like ⏱ [0:25/1:00] (Write report),
followed by the timer (⏲ 0:12:34) when one runs. It's empty otherwise.
Lua API
require("org.api") is a stable, versioned API for plugins and configs:
read files and headlines as plain data, query them, change them (TODO
state, tags, priority, properties, dates, clock, refile, archive, IDs),
run agenda queries without opening the agenda, capture without a window,
store and resolve links, and listen to events such as OrgTodoStateChange,
OrgTagsChanged or OrgRefile. Changes work whether or not the file is
open, and never prompt.
local api = require("org.api")
for _, h in ipairs(api.headlines({ match = "+work", todo = "WAITING" })) do
h:set_todo("TODO")
h:schedule("+1d")
end
api.capture({ template = "* TODO %^{Task}", target = "~/org/inbox.org", values = { Task = "Call the bank" } })
api.on("OrgClockOut", function(data) print(data.title, data.minutes) end)
See :h org-api for every function, field and event.
📊 Parity with Emacs Org
How much of Emacs Org 9.8 works the same way in org.nvim, measured against Org 9.8.10 (September 2026). Every interactive command and every user option of Org 9.8.10 (877 commands and 1,055 options, listed by Emacs itself) was checked against org.nvim:
| Lens | Parity | What it counts |
|---|---|---|
| Overall | ▰▰▰▰▰▰▰▰▰▰ 99.9% | The 1,805 commands and options (of 1,932) that can exist outside Emacs; Emacs internals are left out |
| Strict | ▰▰▰▰▰▰▰▰▰▰ 98.6% | Also counts the 24 that need Emacs itself (Gnus, BBDB, eww, TRAMP, CDLaTeX...) |
Before this round, the same measurement gave 76.6% overall and 74.3% strict. The earlier estimates in this README (~92–95%) weighted everyday features more heavily; this measurement gives every command and option the same weight.
By area:
| Area | Parity | Before | What's left |
|---|---|---|---|
| 🌳 Outline, structure, TODO, tags, properties, dates | ▰▰▰▰▰▰▰▰▰▰ 100% | 77% | Nothing that Neovim can do; CDLaTeX, RefTeX and speedbar need Emacs (98% strict) |
| 📋 Plain lists | ▰▰▰▰▰▰▰▰▰▰ 100% | 61% | — |
| 🗓️ Agenda and habits | ▰▰▰▰▰▰▰▰▰▰ 100% | 83% | — |
| 📥 Capture and date trees | ▰▰▰▰▰▰▰▰▰▰ 100% | 71% | — |
| 📦 Refile and archive | ▰▰▰▰▰▰▰▰▰▰ 100% | 91% | — |
| ⏱️ Clocking and timers | ▰▰▰▰▰▰▰▰▰▰ 100% | 91% | — |
| 🧮 Tables and plots | ▰▰▰▰▰▰▰▰▰▰ 99.6% | 88% | Calc's symbolic mode and date format can't be set in calc_default_modes |
| 🏛️ Column view | ▰▰▰▰▰▰▰▰▰▰ 100% | 100% | — |
| 🔗 Links | ▰▰▰▰▰▰▰▰▰▰ 100% | 59% | Links to Emacs applications (Gnus, BBDB, MH-E, eww, w3m) need Emacs (84% strict) |
| 📎 Attachments, IDs, footnotes, lint, protocol, crypt | ▰▰▰▰▰▰▰▰▰▰ 100% | 79% | — |
| 🧪 Babel and source editing | ▰▰▰▰▰▰▰▰▰▰ 99.7% | 58% | Common Lisp runs in sbcl, not SLIME/SLY; TRAMP and Clojure's CIDER need Emacs |
| 📤 Export and publishing | ▰▰▰▰▰▰▰▰▰▰ 100% | 78% | BBDB anniversaries in iCalendar need Emacs |
| 📚 Citations | ▰▰▰▰▰▰▰▰▰▰ 100% | 39% | — |
| 📰 Feeds and MobileOrg | ▰▰▰▰▰▰▰▰▰▰ 100% | 100% | — |
Note
How this is measured. docs/parity/inventory.el
makes Emacs list every command and option of Org 9.8.10, and
docs/parity/inventory.tsv records, for each
one, whether org.nvim does the same thing (with the code that does it), or
why not. A command or option counts as done only when org.nvim behaves
equivalently, with a spec that exercises it; results that Emacs produces
(buffer text, export output, agenda lines) are checked against Emacs run in
batch mode. Partial ones count half; Emacs internals with no user-visible
effect (byte compilation, caches, obsolete aliases) are left out. Run
docs/parity/score.sh to recompute the numbers.
A command or option that exists is not the same as every edge case of it
behaving identically, so this measures coverage, not bug-for-bug
equality. Where org.nvim differs on purpose (prefix arguments are counts,
the cursor sits on a character rather than between two), it says so in
Differences from Emacs Org mode,
:h org-differences and the parity review.
If something behaves differently from Emacs and isn't listed,
please open an issue.
Differences from Emacs Org mode
The goal is Emacs Org 9.8 parity: option defaults are Emacs's (so a fresh
setup behaves like a fresh Emacs: no agenda files, TODO | DONE, nothing
logged on DONE, files open expanded), and behaviour is checked against Emacs
run in batch mode. What can't work the same way is listed with the reason in
:h org-differences.
The Org 9.8 review follow-up records concrete regressions, implemented parity work, and remaining feature gaps. The main differences:
- Emacs Lisp runs outside the editor. Capture
%(sexp),(eval ...)macros, table'(...)formulas, diary sexps and Lisp in header arguments run on a built-in Lisp interpreter first; what it can't do runs in a separateemacs --batchwhen Emacs is installed (elisp:links and emacs-lisp Babel blocks always do). That Emacs can't see or change the editor's buffers and has none of your Emacs configuration unlessbabel.emacs_lisp.argsloads it.#+BINDsets the export variables that have an org.nvim option. Hooks and functions are Lua functions. - Emacs applications (Gnus, mu4e, BBDB, eww, w3m) and Emacs packages
(CDLaTeX, RefTeX, SLIME, CIDER, TRAMP) have no counterpart. The Emacs
diary file is read by the agenda, and
iadds entries to it. - Display: image and LaTeX previews replace the link, but a terminal line can't grow, so a tall image continues in virtual lines under it, and they need a terminal image backend. Multi-line fragments are drawn in place by hiding their other lines (with image.nvim they stay under the line). In indent mode, wrapped rows don't get the virtual indentation, and emphasis doesn't nest inside the same emphasis or inside verbatim.
- Point vs cursor: Emacs acts between characters, Normal mode on a character, so commands that insert "at point" act at the end of the line in Normal mode (at the cursor in Insert mode).
- Prefix arguments are counts (4 = C-u, 16 = C-u C-u, 64 = C-u C-u C-u).
- Babel sessions send each block to the REPL as one "run this file" line (the REPL shows that line, not the code), and Lua blocks run inside Neovim.
- Captures without
:unnarrowedare edited in a separate buffer and show up in the target file when they are finished (Neovim has no indirect buffers).
🧩 Extensions
Optional features modelled on popular third-party Emacs Org packages ship
with org.nvim but stay unloaded until you enable them in extensions:
require("org").setup({
extensions = {
present = true, -- enable with the defaults
roam = { directory = "~/roam" }, -- options are merged over its defaults
},
})
false or { enabled = false } keeps one off, and :checkhealth org lists
the enabled ones and checks what each needs. An extension adds its own
actions, :Org subcommands and default keys, but never replaces a key you
set. See :h org-extensions.
Each extension is marked ✅ stable (used daily, well covered by specs; changes to its options or keys are called out in the release notes) or 🧪 experimental (works and is tested, but has seen less real use, so its options may still change):
| ✅ Stable | 🧪 Experimental |
|---|---|
ql, super_agenda, present, roam, quickadd, ics, kanban, sidebar | review, pomodoro, drill, merge, cli, diagrams, code, literate, lsp, transclusion, timeline, heatmap |
Note
🧪 Experimental extensions are prone to change. Their options, commands,
keys and output (such as the org command line's JSON) can change in any
release, so read the release notes before you upgrade if a config or a
script relies on one.
✅
present(org-present)::Org presentshows the buffer as a slideshow, one top-level heading per slide, in its own tab (:h org-extensions-present).
✅
ql(org-ql): queries such as(and (todo "NEXT") (tags "work"))ortodo:NEXT tags:work !done,:Org ql_search, named and saved views,ql_find,ql_refile,ql_sparse_tree, recent items,org-qlagenda custom commands and#+BEGIN: org-qlblocks (:h org-extensions-ql).
✅
roam(org-roam): org-roam v2 notes in the same file format, so a directory can be shared with Emacs: find and insert nodes (typing a new title creates one), a backlinks, reflinks and unlinked references window, aliases, refs and tags, capture templates with org-roam's:targetforms, extracting and refiling subtrees, daily notes,roam-ref/roam-nodeorg-protocol handlers and a Graphviz node graph, over a JSON index that updates incrementally. Its keys live under<prefix>m(<prefix>mffinds a node,<prefix>miinserts one,<prefix>mltoggles the backlinks window,<prefix>mjcaptures to today's daily note and<prefix>md…goes to the dailies) (:h org-extensions-roam).
✅
super_agenda(org-super-agenda): group agenda days and lists (including org-ql results) by time grid, deadline, tag, priority, category and more, with auto groups.<Tab>on a group header folds the group, andgj/gkmove between headers (:h org-extensions-super-agenda).
✅
quickadd(Todoist-style quick add)::Org quickaddor<prefix>qturns one line such asCall Bob fri 3pm #work !A ~30m @Inbox due mon every weekinto an entry with SCHEDULED / DEADLINE, repeater, tags, priority and Effort, filed under the best-matching heading, with a live preview while you type. Capture templates can use the same syntax withquickadd = true(:h org-extensions-quickadd).
🧪
review(GTD weekly review)::Org review(<prefix>W) steps through a weekly review in a float: empty the inbox (refile, schedule, set a state, delete or skip each entry), stuck projects, waiting-for, overdue, the next two weeks, someday/maybe, last week's clocked time and reflection questions, with a progress line,n/pbetween steps and resumable progress. Finishing logs the review in a date tree. Steps can be reordered or replaced with your own (:h org-extensions-review).
🧪
pomodoro(org-pomodoro):<prefix>zsstarts a pomodoro on the heading at the cursor and clocks it in; when the 25 minutes are up the entry'sPOMODOROScount goes up, the clock stops and a 5-minute break starts (15 minutes after every fourth), with notifications and an optional sound. Pause, skip and stop, an optional overtime, a session that survives a restart, and a countdown inrequire("org").statusline()(:h org-extensions-pomodoro).
🧪
drill(org-drill): flashcards with spaced repetition. Headings tagged:drill:are cards (simple, two-sided, multi-sided and cloze deletions such as[Nile||river]);:Org drill(<prefix>D) reviews the due ones in a floating window, you grade each answer 0-5, and org-drill's SM-5 (or SM-2 / Simple8) schedules the next review in itsDRILL_*properties, so a deck can be shared with Emacs. Leeches, cram mode and org-drill's weighted cloze types included (:h org-extensions-drill).
🧪
merge: a structural git merge driver for Org files.:Org merge_installregisters it for the repository (*.org merge=org), and git then merges org files entry by entry: entries matched byIDor outline path, refiles followed, properties merged key by key, clocks and tags unioned, and a real conflict marked only around the one entry (or property) both sides changed. Also usable without org.nvim's setup viabin/org-merge(:h org-extensions-merge).
✅
ics: subscribe to Google, Outlook or any iCalendar (.ics) calendar, a secret URL fetched with curl into a cache or a local file, and see its events read-only in the agenda day and week views: times converted to your zone, repeating events, exceptions and cancellations.ics_importcopies an event into an org file andics_refreshfetches the calendars again (:h org-extensions-ics).
🧪
cli: anorgshell command (bin/org, a headless Neovim) that prints the agenda as text, CSV or JSON, captures with a template, clocks in and out, reports the running clock (for tmux, SketchyBar or Raycast), searches, queries and exports, and changes headings (TODO state, tags, priority, properties, dates, notes, refile, archive) without ever prompting, from a config file of its own. With--jsonevery command prints a versioned envelope with stable error codes, andorg schemadescribes the commands as JSON Schema, so scripts and AI agents can use it as a tool (:h org-extensions-cli,:h org-extensions-cli-json).
🧪
diagrams(ob-mermaid, ob-dot, ob-plantuml):mermaid(mmdc) anddot(Graphviz) source blocks, plus extras forplantuml:C-c C-cwrites the diagram and inserts afile:link (a name is generated when there's no:file), renders are cached by content hash, the image is previewed inline when an image backend is available, andrender_on_savere-renders changed diagrams on:w(:h org-extensions-diagrams).
🧪
code: a bridge between code and notes.code_captureturns a Visual selection into a#+begin_srcblock with a link back and the git branch;[[code:src/app.lua::M.setup]]links jump to a symbol through LSP (else treesitter or a text search); each repository gets an org file (.org/tasks.org) withproject_open,project_captureand aproject_agendathat lists the code'sTODO:/TODO(org:ID)comments; opt-in clocking by git branch. Keys under<prefix>j(:h org-extensions-code).
🧪
literate: a literate Neovim config. Savinginit.orgtangles it and runs only the Lua blocks you changed, so an option or keymap applies at once; errors are diagnostics on the org line. Plusliterate_reload,literate_run_block,literate_health, a jump from the tangled file back to the block, and:Org literate_bootstrapfor an init.lua that re-tangles a newer init.org on startup (:h org-extensions-literate).
🧪
lsp: a language server for org buffers that runs inside Neovim (nothing to install), so every LSP feature and plugin works in Org files: the outline as document symbols, headlines of all your files as workspace symbols, org-lint diagnostics as you type, hover on timestamps ("in 3 days, Friday", repeaters explained), links (a preview of the target), clocks and footnotes, go to definition, references, code actions (schedule, refile, archive, lint quick fixes) and a rename of a headline, CUSTOM_ID, ID or target that rewrites every link to it across files, something Emacs can't do (:h org-extensions-lsp).
🧪
transclusion(org-transclusion):#+transclude: [[file:notes.org::*Heading]] :level 2or[[file:main.py]] :lines 10-24 :src pythonshows that text live, as virtual lines under the keyword (the file isn't touched) or inserted into the buffer like Emacs and taken out again when it's written.<CR>edits the source in a float and:wwrites it back and updates every transclusion; sources are watched, nested transclusions expand, and#+transclude:is expanded on export (:h org-extensions-transclusion).
✅
kanban: a board with a column per TODO keyword (or group of keywords, with WIP limits) and a card per heading showing its priority, deadline countdown, effort and tags.h/lmove a card to the previous / next state through the regular TODO code, so logging, CLOSED and repeaters work;/filters by tags match or org-ql query,<CR>opens the heading. Cards come from the agenda files, a buffer, a subtree or a query (:Org kanban,<prefix>Vk,:h org-extensions-kanban).
🧪
timeline: a text-mode Gantt chart of the tasks with SCHEDULED, DEADLINE or Effort: bars from start to deadline, ◆ deadlines, today's column, overdue tasks in red, optional clocked days.+/-zoom (day, week, month),[/]pan,S/Dreschedule (:Org timeline,<prefix>Vt,:h org-extensions-timeline).
🧪
heatmap: a GitHub-style calendar of the time clocked each day, the tasks closed or the habits done, shaded from your colorscheme, with totals and streaks; the selected day shows its tasks and<CR>opens its agenda (:Org heatmap [clock|closed|habit] [tag],<prefix>Vh,:h org-extensions-heatmap).
✅
sidebar: a narrow "Today" window with the running clock against its effort, the next appointment with a countdown, today's items, habits due and the inbox count, kept up to date by a timer and on writes (sidebar_toggle,<prefix>Vs,:h org-extensions-sidebar).
🧭 Roadmap
The parity inventory leaves only two options
partial (calc_default_modes and Common Lisp's evaluator, which is sbcl
rather than SLIME/SLY). What's still missing is finer-grained than one
command or option:
- [ ] Calc's symbolic mode and date format in
calc_default_modes - [ ] Calc's rule-based
integ,factor, polynomial functions and numericsolve/fsolvefor degree 5 and up - [ ] table.el's cell commands (split, span, justify) and live realignment in
C-c ' - [ ] Babel sessions for more languages (Julia, SQL engines)
- [ ] Custom
diary-date-formsin the Emacs diary file - [ ] Column view headlines read-only against every kind of edit (Visual, Ex commands, the API)
- [ ]
#+BINDfor export variables that have no org.nvim option - [ ] More extensions
Done in the latest parity round (every command and option of Org 9.8.10
checked, see the
parity review):
citations you can insert, follow and highlight, and the CSL processor
(a port of citeproc-el); KOMA letters and man pages as native export
back-ends; highlighted source code in HTML and engraved LaTeX; Babel for
PlantUML, gnuplot, LaTeX, ditaa, LilyPond, Java, C#, Haskell, Clojure,
Common Lisp, Scheme, Fortran, Julia, OCaml, Groovy, Maxima, Processing and
screen; ol-bibtex; Org-aware = indentation and gq filling; the agenda's
remote undo, hour and minute date shifts and i diary entries;
alphabetical list bullets; the org-goto outline browser; the Org, table and
agenda menus and org-mouse; clipboard image paste; org-ctags. In all, 163
commands and 329 options that were missing, partial or thought to need
Emacs now work like Emacs.
Since then, the extensions present, ql, roam and
super_agenda have landed.
Sixteen more followed: lsp, kanban, timeline, heatmap,
sidebar, quickadd, review, pomodoro, drill, code, literate,
merge, ics, cli, diagrams and transclusion.
What needs Emacs itself (indirect buffers for narrowed captures, Emacs applications such as Gnus and mu4e, Lisp that must change the editor's state) isn't planned; see Differences from Emacs Org mode.
If there's something you'd like that isn't here, open an issue.
🤝 Contributing
Contributions of all sizes are welcome: bug reports, docs fixes, new link types, Babel languages, exporters, or anything on the roadmap. Each piece of Org lives in its own small module, and there's a fast headless test suite, so it's easy to get started:
git clone https://github.com/xheisenbugx/org.nvim && cd org.nvim
make test # run all specs headlessly
make test SPEC=tests/spec/agenda_spec.lua # one spec
make lint # stylua --check + source lint rules
CONTRIBUTING.md explains how the code is organised
and how to add a feature. CHANGELOG.md lists what changed
in each release.
License
org.nvim is released under the MIT License.
If org.nvim makes your notes, tasks or agenda better, give it a ⭐. It helps other Neovim users find it.
You can also buy me a coffee on Ko-fi ☕.