Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>Org (org-lsp)New to Visual Studio Code? Get it now.
Org (org-lsp)

Org (org-lsp)

Preview

Kristijan Husak

| (0) | Free
Org mode support through the org-lsp language server: highlighting, folding, outline, TODO states and the agenda.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Org in VS Code

The VS Code extension (editors/vscode) runs Org through the server. It is a thin client: it starts the server and tells it where the cursor is when a command runs. Its commands, keys and token colors are written into package.json from the server's own description of itself, so nothing about Org is listed there by hand. It works in VS Code's relatives too (VSCodium, Cursor).

Installing

curl -fsSL https://github.com/kristijanhusak/org-lsp/releases/download/nightly/install.sh | bash -s -- vscode

or, in a checkout of this repository:

scripts/install.sh vscode                    # the nightly build for this machine
scripts/install.sh --release v0.2.0 vscode   # a release
scripts/install.sh --source vscode           # built from this checkout (cargo, npm)

The script downloads the package for your platform from the nightly release (or the release named), or builds it, and installs it with code --install-extension. Run it again to update, then reload the window. CODE=codium (or code-insiders, cursor) installs into another editor. On Windows without a shell, download org-lsp-win32-x64.vsix from the release and run Extensions: Install from VSIX….

The package has the server inside. The extension looks for the server in this order: the org-lsp.server.path setting, the one inside the extension, org-lsp on PATH.

Setting it up

The settings go in settings.json (Preferences: Open User Settings (JSON)). The server's options go in org-lsp.settings, where they are completed, described on hover and checked; the extension's own settings beside it:

{
  "org-lsp.settings": {
    "org_agenda_files": ["~/org"],
    "org_todo_keywords": ["TODO(t)", "NEXT(n)", "|", "DONE(d!)"],
    "org_log_done": "time",
    "org_capture_templates": [
      { "key": "t", "description": "Task", "target": ["file+headline", "~/org/inbox.org", "Tasks"], "template": "* TODO %?\n  %U" }
    ],
    "org_agenda_custom_commands": [
      {
        "key": "d",
        "description": "Today, then what is waiting",
        "blocks": [
          { "type": "agenda", "settings": { "org_agenda_span": "day" } },
          { "type": "todo", "match": "WAIT", "header": "Waiting for" }
        ]
      }
    ]
  },
  "org-lsp.keys": "vim",
  "org-lsp.winSplitMode": "vsplit"
}

Without org_agenda_files, the agenda is built from the Org files in the workspace folders. When org-lsp.settings changes, the extension restarts the server, so the change applies at once. A folder's .vscode/settings.json may set them too, but only once VS Code trusts the folder: in restricted mode, org-lsp.settings and org-lsp.server.path come from the user's settings alone, as they name programs the server runs.

The server also reads the shared configuration file, ~/.config/org-lsp/config.toml, which every editor shares; org-lsp.settings goes on top of it. configuration.org has everything else: the extension's settings and every option of the server with its default.

Headline levels in colors

Color themes give every heading the same color, so by default each level of headlines looks alike. With "org-lsp.headlineLevelColors": true each level takes a color of its own from the theme, as Emacs's org-level-N faces take theirs from outline-1 to outline-8: the colors of function names, variables, keywords, comments, types, constants, built-ins and strings, the stars with the title. The text past a done keyword (org_fontify_done_headline) or a TODO one (org_fontify_todo_headline), archived headlines and inline tasks keep their own look. The change shows at once in the open files.

The headlines then have the token type outline with the modifiers level1 to level8, so editor.semanticTokenColorCustomizations picks other colors, for every theme or for one:

{
  "org-lsp.headlineLevelColors": true,
  "editor.semanticTokenColorCustomizations": {
    "rules": {
      "outline.level1:org": { "foreground": "#4f97d7", "bold": true },
      "outline.level2:org": "#2d9574"
    },
    "[Default Light Modern]": {
      "rules": { "outline.level1:org": "#3a81c3" }
    }
  }
}

Using it

The commands are in the Command Palette under Org, and the changes that apply at the cursor under Quick Fix… (Ctrl+.). Org: Show the keys lists the keys of the editor at hand; picking one runs it.

Emacs's keys are bound in Org files (Ctrl+C Ctrl+T, Ctrl+C Ctrl+S, Shift and the arrows, Tab and Shift+Tab to cycle folds …), in capture buffers (Ctrl+C Ctrl+C) and in the date prompt. In Org files Ctrl+C waits for a second key instead of copying (Ctrl+Insert still copies). The agenda has the keys it has in every editor: Emacs's agenda keys (f, b, t, +, Enter, Ctrl+C Ctrl+S …), with Shift+J for a date and the views under v (v d, v w), so that VSCodeVim keeps its motions; q closes it. org-lsp.keys picks other keys: "vim" binds the Neovim plugin's keys for VSCodeVim, "custom" none. keys/vscode.org lists every key and command, and how to add, change and remove keys.

A date is typed as at Org's prompt: fri 10:00, +2d, 2/15, ++1w, 10:00-11:30. Under the input box the extension shows the timestamp the answer makes, as you type. As in Emacs, a date command shows a calendar first, beside the file, with the answer and what it means on its last line. Emacs's keys work there: Shift and the arrows by day and week, Alt+Shift+Left and Alt+Shift+Right by month, Alt+Shift+Up and Alt+Shift+Down by year, < and > for other months, . for today, Enter to take the day under the cursor, i to type the answer, q or Ctrl+G to give up.

A change made from the agenda edits the entry's file and saves it (auto_save; off, it is left unsaved, as in Emacs). As in Emacs, the entry's lines stay where they are, showing the new state, priority or date, with the cursor on them, until the agenda is built again with r.

What works

Feature Parity VS Code What does not work, and why
Highlighting 100% ✅
Folding and visibility 91% ❓ A closed fold ends in VS Code's own ⋯: an extension cannot change it (org_ellipsis).
Headings and structure 96% ❓ VS Code does not tell an extension which folds are closed: C-k on a folded headline is VS Code's own (org-ctrl-k-protect-subtree), and a subtree cut or copied folded is not folded again when it is pasted.
Lists and checkboxes 93% ✅
TODO keywords 100% ✅
Priorities 100% ✅
Tags 88% ✅
Properties and column view 100% ❓ Column view's header is in the status bar, with the column picked in brackets. Custom properties are not hidden (org.custom.properties.toggle): VS Code hides lines only in a fold of the folding ranges, which keeps its first line showing, and a decoration cannot hide a line.
Dates and times 100% ✅
Agenda 97% ❓ Tags are at column 80, not at the window's edge (org_agenda_tags_column "auto"): VS Code does not tell an extension how many columns an editor shows.
Clocking 100% ✅
Capture 100% ✅
org-protocol 86% ✅
Notes (org-roam) 94% ✅
A journal (org-journal) 93% ✅
Refile and archive 100% ✅
Links 96% ✅
Footnotes 100% ✅
Tables 100% ✅
Table formulas 100% ✅
Code blocks (Babel) 100% ✅
Export and publishing 100% ❓ VS Code does not tell an extension which folds are closed: with C-v everything is exported.
Citations 82% ✅
Diagnostics (org-lint) 100% ✅
Indentation and formatting 100% ❓ The lines a long line wraps into are not indented as Org does: VS Code indents them by the line's own leading whitespace (editor.wrappingIndent), the same way for every line, without the prefix of virtual indentation, a decoration it does not count.
Notes and logging 100% ✅
Completion and editing helpers 100% ✅
Timers 100% ✅
Attachments 100% ✅
Encryption 100% ✅
Inline images and LaTeX previews 100% ❓ VS Code cannot leave lines free for an image: an image takes the place of its link only as high as a line, and shows whole on hover (at the width Org gives it, at most 600 pixels). Counts through a key's args.
All of Org 97%

✅ all that org-lsp does works there, ❓ some does not (the last column says what and why), ❌ none does, — nothing to support yet. Parity is the share of what Emacs Org does in that area that org-lsp does; parity.org lists both.

TESTING.org lists what to try by hand.

Developing

scripts/install.sh --source vscode (in the repository root) builds the extension and installs it. By hand, in editors/vscode:

cargo build --release -p org-lsp   # in the repository root
npm install
npm run generate                   # package.json from the server's manifest
npm run bundle-server              # copies the binary into server/
npm run package                    # writes org-lsp-<version>.vsix

Packaging writes README.md, which VS Code shows on the extension's page and reads only as Markdown, from this page (scripts/readme.mjs, run by vsce as vscode:prepublish); it is not kept in the repository.

npm test runs the extension inside VS Code against the server (xvfb-run -a npm test on a machine without a display; VSCODE_EXECUTABLE names a VS Code or VSCodium to use instead of downloading one).

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft