A from-scratch successor to Org Mode, built to be editor-agnostic and platform-agnostic.
As originally described in https://avi.press/posts/2024-01-15-standalone-org.html.
Current development is workflow-driven: small, user-facing slices (especially CLI + VS Code integration) are implemented incrementally and validated in real daily use.
- A comprehensive org mode successor, decoupled from Emacs.
- Build and support full featured org mode experiences in any text editor or any platform.
- Work towards a formal specification of the Org format.
- Support a thriving plug-in ecosystem that leverages more popular development environments.
- v0 (draft): ./spec/v0/SPEC.org
Org2 is active, but still early alpha. It is not yet a drop-in replacement for full GNU Org Mode.
Current reality:
- The parser/spec/tooling are evolving quickly.
- CLI + VS Code workflows are the most actively developed and validated surfaces.
- APIs/flags/behavior can still change between iterations.
- Headlines / hierarchy: Available now
- Drawers + PROPERTIES: Available now
- Planning lines (SCHEDULED/DEADLINE/CLOSED): Available now
- TODO keywords + state transitions: Available now
- Lists + checkboxes: Available now (basic)
- Timestamps: Available now (basic)
- Tables: Available now (basic)
- Links (including ID links): Available now
- Agenda (CLI + VS Code panel): Available now
- Agenda status filtering (CLI + VS Code): Available now (MVP)
- Agenda status exclusion filtering (CLI + VS Code): Available now (MVP)
- Agenda planning-kind filtering (CLI + VS Code): Available now (MVP)
- Agenda planning-kind exclusion filter (CLI + VS Code): Available now (MVP)
- Agenda time-bucket filtering (CLI + VS Code): Available now (MVP)
- Agenda text matching filter (CLI + VS Code): Available now (MVP)
- Agenda tag filter (CLI + VS Code): Available now (MVP)
- Agenda TODO keyword filter (CLI + VS Code): Available now (MVP)
- Agenda priority filter (CLI + VS Code): Available now (MVP)
- Agenda exclusion filters (CLI + VS Code): Available now (MVP)
- Agenda source-file filtering (CLI + VS Code): Available now (MVP)
- Agenda sort-order filtering (CLI + VS Code): Available now (MVP)
- Agenda row-limit filtering (CLI + VS Code): Available now (MVP)
- Agenda explicit date-range bounds (CLI + VS Code): Available now (MVP)
- TODO set/toggle from CLI/editor: Available now
- Set SCHEDULED/DEADLINE (including “today” fast paths): Available now
- Archive subtree: Available now (MVP)
- Roam node creation (CLI + VS Code command): Available now (MVP)
- Roam ID open command (VS Code prompt/selection + id-link parsing): Available now (MVP)
- Roam ID link copy commands (VS Code current heading/file + prompt/link target flows): Available now (MVP)
- Roam backlink insert/show commands (VS Code current heading/file + prompt/link target flows): Available now (MVP)
- Roam backlink source picker (VS Code quick pick + prompt/link target input): Available now (MVP)
- Roam-ish ID/backlink workflows: In progress
- Formatter drift detection (
org2 fmt --check): Available now (MVP) - Formatter directory scans (
org2 fmt --dir ... --recursive): Available now (MVP) - Formatter file-path filters (
org2 fmt --file-match/--exclude-file): Available now (MVP) - Formatter structured check output (
org2 fmt --check --format json): Available now (MVP) - Formatter single-file JSON preview (
org2 fmt --file ... --format json): Available now (MVP) - Formatter apply JSON summary (
org2 fmt --apply --format json): Available now (MVP) - Formatter config-driven target discovery (
org2 fmt --config PATH): Available now (MVP) - Formatter workspace apply command (VS Code): Available now (MVP)
- Formatter current-file check/apply commands (VS Code): Available now (MVP)
- Formatter current-file diff preview command (VS Code): Available now (MVP)
- Formatter (
org2 fmt): In progress - HTML export (
org2 export html): Available now (MVP, single-file + directory batch standalone export + optional index page + configurable stylesheet injection + optional table of contents + optional Org file-link rewrite + automatic heading anchors for TOC/rewrite targets and in-document[[* Heading]]/=#custom-id= links [including:CUSTOM_ID:targets] + keyword-driven metadata/head controls) - LSP go-to-definition for file/id links (including file
::searchsuffix targets) (org2 lsp): Available now (MVP) - LSP go-to-declaration for file/id links (including file
::searchsuffix targets) (textDocument/declarationviaorg2 lsp): Available now (MVP) - LSP go-to-type-definition + go-to-implementation for file/id links (including file
::searchsuffix targets) (textDocument/typeDefinition+textDocument/implementationviaorg2 lsp): Available now (MVP) - LSP find-references for file/id links (
org2 lsp): Available now (MVP) - LSP workspace symbol search for headings (
org2 lsp): Available now (MVP) - LSP document links for file/id/URL links (
org2 lsp): Available now (MVP) - LSP completion for TODO/planning keywords, timestamps, and ID/file link targets (
org2 lsp): Available now (MVP) - LSP signature help for planning timestamps (
textDocument/signatureHelpviaorg2 lsp): Available now (MVP) - LSP hover tooltips for links/TODO/planning keywords (
org2 lsp): Available now (MVP) - LSP document highlights for ID/file references (
org2 lsp): Available now (MVP) - LSP rename for
[[id:...]]links +:ID:properties and matching file-link targets (org2 lsp): Available now (MVP) - LSP workspace file-rename edits for Org file links (
workspace/willRenameFilesviaorg2 lsp): Available now (MVP) - LSP quick-fix code actions for CRLF/tab parser issues (
org2 lsp): Available now (MVP) - LSP document formatting (
textDocument/formattingviaorg2 lsp): Available now (MVP) - LSP range formatting (
textDocument/rangeFormattingviaorg2 lsp): Available now (MVP) - LSP on-type formatting for Org tables (
textDocument/onTypeFormattingviaorg2 lsp): Available now (MVP) - LSP selection ranges (
textDocument/selectionRangeviaorg2 lsp): Available now (MVP) - LSP semantic tokens for TODO/planning/properties/links (
textDocument/semanticTokens/fullviaorg2 lsp): Available now (MVP) - LSP backlink code lenses for
:ID:properties (textDocument/codeLensviaorg2 lsp): Available now (MVP) - LSP linked editing ranges for ID links/properties plus matching file links (
textDocument/linkedEditingRangeviaorg2 lsp): Available now (MVP) - LSP document colors for hex literals (
textDocument/documentColor+textDocument/colorPresentationviaorg2 lsp): Available now (MVP) - LSP inlay hints for unlabeled ID/file links (
textDocument/inlayHintviaorg2 lsp): Available now (MVP) - LSP call hierarchy for Org ID/file links (
textDocument/prepareCallHierarchy+callHierarchy/incomingCalls+callHierarchy/outgoingCallsviaorg2 lsp): Available now (MVP) - LSP entrypoint (
org2 lsp): In progress - Formal Org2 spec (v0 draft): In progress
- Export/publishing pipeline parity: In progress (MVP single-file + directory-batch HTML export + index generation + configurable stylesheet injection + optional table of contents + optional Org file-link rewrite + automatic heading anchors [including
:CUSTOM_ID:targets during file-link rewrite] + keyword-driven HTML metadata tags/lang/head snippets available via CLI + VS Code) - Org crypt (encrypted sections/workflows): Planned
- Recurring tasks / repeaters: In progress (agenda repeater expansion MVP available)
- Habits: Planned
- Clocking + effort/properties for time tracking: Planned
- Capture templates / quick capture flow: Available now (CLI MVP: note/task quick-capture templates)
- Refile workflows parity: Available now (CLI + VS Code MVP)
- Advanced agenda customization parity: Planned
- Mature extensibility/plugin ecosystem: Planned
- VS Code: In progress (primary integration target)
- Vim/Neovim: In progress (minimal plugin)
- Other editors: Planned
If you need full, stable, mature Org Mode parity today, treat Org2 as experimental for now.
Current editor status:
- VS Code (
editors/vscode-org2/): primary integration target right now.- Provides language support + folding + agenda + TODO/planning/archive + roam commands via CLI-backed actions.
- Usable for daily workflows, but still evolving quickly.
- Vim/Neovim (
editors/vim-org2/): minimal support.- Filetype + syntax + heading fold toggles.
- Not feature-parity with VS Code integration.
- Other editors: no first-class integration yet.
Contributions are welcome.
Fastest way to help:
- start from active issues/PRs,
- pick a small workflow slice,
- keep changes focused and test-backed.
For local development:
- build + run CLI tests,
- verify the workflow end-to-end (especially for editor-facing changes),
- include clear behavior notes in PRs because the surface is still evolving.
Org2 ships a small CLI that you can run from a local checkout.
Right now the CLI is primarily focused on reading/planning workflows (like agenda) plus a handful of experimental editing commands used by the VSCode extension. The exact set of commands changes quickly, so treat it as unstable and prefer org2 --help for the authoritative list.
cd /path/to/org2
npm install
npm run buildYou can invoke the CLI in a few equivalent ways:
npm run org2 -- <command> [...args](recommended for local development)node dist/cli.js <command> [...args]npm link(optional) to get a globalorg2command
The agenda command scans one or more .org files for scheduled items and prints either human-readable text or JSON.
# Run against a directory of .org files
npm run org2 -- agenda --dir /path/to/org/files --recursive
# Run against explicit files
npm run org2 -- agenda --files /path/to/a.org /path/to/b.org
# Control the date range
npm run org2 -- agenda --dir /path/to/org --today 2026-01-25 --days 7
# Explicitly bound the date range (start/end)
npm run org2 -- agenda --dir /path/to/org --from 2026-01-25 --to 2026-02-01
# JSON output (useful for tests/automation)
npm run org2 -- agenda --dir /path/to/org --format json
# Exclude overdue items from output
npm run org2 -- agenda --dir /path/to/org --no-overdue
# Filter by TODO status buckets (advanced agenda customization)
npm run org2 -- agenda --dir /path/to/org --status active
# Exclude TODO status buckets (advanced agenda customization)
npm run org2 -- agenda --dir /path/to/org --exclude-status done,canceled
# Filter by planning kind (SCHEDULED vs DEADLINE)
npm run org2 -- agenda --dir /path/to/org --kind deadline
# Exclude a planning kind (hide SCHEDULED or DEADLINE rows)
npm run org2 -- agenda --dir /path/to/org --exclude-kind scheduled
# Filter by time bucket (overdue, today, upcoming)
npm run org2 -- agenda --dir /path/to/org --when today
# Filter by headline text (case-insensitive, comma-separated OR terms)
npm run org2 -- agenda --dir /path/to/org --match "release,retro"
# Exclude rows by headline text (case-insensitive, comma-separated OR terms)
npm run org2 -- agenda --dir /path/to/org --exclude-match "retro,parking lot"
# Filter by headline tags (case-insensitive exact tag match, comma-separated OR terms)
npm run org2 -- agenda --dir /path/to/org --tag "work,urgent"
# Filter by exact TODO keywords (case-insensitive, comma-separated OR terms)
npm run org2 -- agenda --dir /path/to/org --todo "waiting,done"
# Filter by headline priority markers (case-insensitive; accepts A,B or [#A],[#B])
npm run org2 -- agenda --dir /path/to/org --priority "a,[#b]"
# Exclude rows with tags (case-insensitive exact tag match, comma-separated OR terms)
npm run org2 -- agenda --dir /path/to/org --exclude-tag "someday,maybe"
# Exclude rows with exact TODO keywords (case-insensitive, comma-separated OR terms)
npm run org2 -- agenda --dir /path/to/org --exclude-todo "done,canceled"
# Exclude rows with headline priority markers (case-insensitive; accepts A,B or [#A],[#B])
npm run org2 -- agenda --dir /path/to/org --exclude-priority "c"
# Keep only rows whose source file path contains any term (case-insensitive)
npm run org2 -- agenda --dir /path/to/org --file-match "projects,work"
# Hide rows whose source file path contains any term (case-insensitive)
npm run org2 -- agenda --dir /path/to/org --exclude-file "archive,personal"
# Sort rows within each day (comma-separated sort keys: file, headline, todo, kind, line)
npm run org2 -- agenda --dir /path/to/org --sort "file,headline"
# Limit total rows after sorting (across overdue + upcoming sections)
npm run org2 -- agenda --dir /path/to/org --limit 25
# Show parse errors instead of silently skipping broken files
npm run org2 -- agenda --dir /path/to/org --verbose-errorsNotes:
- If a file fails to parse, the CLI will skip it (use
--verbose-errorsto see why). - By default, overdue items are included; use
--no-overdueto hide them. --whenfilters by schedule bucket relative to--today:overdue,today,upcoming.--exclude-statushides rows with matching TODO state buckets (active,closed, etc.; same allowed values as--status).--exclude-kindhides rows with matching planning kinds (scheduledand/ordeadline).--matchchecks agenda headline text only, case-insensitively.--exclude-matchhides rows whose headline text matches any provided term.--tagchecks agenda headline tags only, case-insensitively (exact tag match).--todochecks exact TODO keywords only, case-insensitively.--prioritychecks Org headline priority markers (for exampleA,B, or[#A]tokens).--exclude-taghides rows with matching headline tags.--exclude-todohides rows with matching TODO keywords.--exclude-priorityhides rows with matching Org priority markers.--file-matchkeeps rows whose source file path contains any term.--exclude-filehides rows whose source file path contains any term.--sortreorders rows within each date bucket (always date-first overall sorting).--limitcaps total rendered rows after sorting (across overdue + upcoming).--fromoverrides agenda start date (default:--today/ current date).--tooverrides agenda end date (default: start +--days - 1).- Repeater timestamps like
<2026-01-08 Thu +1w>are expanded into recurring agenda rows (MVP:/++/.with d/w/m/y units).
If you don’t pass --dir or --files, the CLI will look for an org2.json config file in the current directory (or up to 10 parents).
- Create an
org2.jsonin the root of your notes repo (or anywhere you plan to run the command from):
{
"agendaFiles": ["*.org", "notes/**/*.org"],
"recursive": true,
"ignorePatterns": [".git/**", "node_modules/**", ".#*"]
}- Run agenda with no paths:
If you want to run org2 from your notes repo without typing a long path, you can do:
# in the org2 checkout
cd /path/to/org2
npm link
# in your notes repo
cd /path/to/your/notes
org2 agenda --format jsonOr, without npm link, call the CLI via an absolute path:
cd /path/to/your/notes
# org2.json will be discovered automatically
/path/to/org2-repo/node_modules/.bin/org2 agenda --format json
# or from the org2 checkout:
cd /path/to/org2
npm run org2 -- agenda --format jsonTip: for a reproducible “fixture” when testing agenda output, create a small folder with a couple .org files (for example ./tmp/agenda-fixture/) and run:
npm run org2 -- agenda --dir ./tmp/agenda-fixture --today 2026-01-25 --days 14 --format json# Preview a note capture append (prints full resulting file text)
npm run org2 -- capture --file /path/to/inbox.org2 --template note --title "Call with design team"
# Preview a task capture append with explicit TODO keyword
npm run org2 -- capture --file /path/to/inbox.org2 --template task --todo IN_PROGRESS --title "Ship onboarding copy" --format json
# Write the capture result to disk
npm run org2 -- capture --file /path/to/inbox.org2 --template task --title "Plan Q2 roadmap" --apply
# Emit a unified diff preview instead of full text/json
npm run org2 -- capture --file /path/to/inbox.org2 --template note --title "Draft launch notes" --format diffNotes:
captureappends a new heading to the end of the target file.--template notewrites* Title+CAPTURED: <...>.--template taskwrites* TODO Titleby default (override keyword with--todo).- Use
--now ISOfor deterministic tests.
# Preview moving the subtree at/above --pos into another file (append to file end)
npm run org2 -- refile --file /path/to/inbox.org2 --pos 42 --to-file /path/to/projects.org2 --format json
# Preview as diff
npm run org2 -- refile --file /path/to/inbox.org2 --pos 42 --to-file /path/to/projects.org2 --format diff
# Refile under a destination heading (line or cursor-like LINE[:COL])
npm run org2 -- refile --file /path/to/inbox.org2 --pos 42 --to-file /path/to/projects.org2 --to-pos 10 --applyNotes:
refilemoves the headline subtree at/above--posout of the source file and into--to-file.- Without
--to-pos, the moved subtree is appended at end-of-file. - With
--to-pos, the moved subtree is inserted at the end of the destination heading subtree and headline levels are adjusted so the moved root becomes a child of that heading. - Use
--format diffto preview the exact source+destination edits before applying.
# Preview standalone HTML for a single file (prints HTML to stdout)
npm run org2 -- export html --file /path/to/notes.org2
# Preview as machine-readable JSON (includes title, outputPath, changed, html)
npm run org2 -- export html --file /path/to/notes.org2 --format json
# Write HTML to the default output path (same path with .html extension)
npm run org2 -- export html --file /path/to/notes.org2 --apply
# Write HTML to an explicit output path
npm run org2 -- export html --file /path/to/notes.org2 --out /path/to/site/index.html --apply
# Preview a whole directory tree as machine-readable JSON (includes per-file output paths)
npm run org2 -- export html --dir /path/to/org --recursive --out-dir /path/to/site --format json
# Export a whole directory tree to HTML (preserves subdirectory structure)
npm run org2 -- export html --dir /path/to/org --recursive --out-dir /path/to/site --apply
# Preview a generated index page for batch exports (links to exported files)
npm run org2 -- export html --dir /path/to/org --recursive --out-dir /path/to/site --index index.html --index-title "Site Index" --format json
# Export with custom stylesheet links and no built-in inline style
npm run org2 -- export html --file /path/to/notes.org2 --css /assets/site.css,https://cdn.example.com/theme.css --no-default-style --apply
# Export with an auto-generated table of contents + heading anchors
npm run org2 -- export html --file /path/to/notes.org2 --toc --apply
# Rewrite Org file links (file:*.org / *.org2) to .html hrefs in exported output
npm run org2 -- export html --file /path/to/notes.org2 --rewrite-file-links --applyNotes:
export html --filerenders one file and supports--title/--outoverrides.export html --dirbatch-renders all.org/=*.org2files in the target directory (recursive when--recursiveis set).- Directory exports preserve relative source paths under
--out-dir(or under--dirwhen--out-diris omitted), swapping source extensions to.html. --index FILE(directory mode only) emits an HTML index file with links to every exported page; relative index paths are resolved under--out-dir.--index-title TITLEoverrides the index page title.--css HREFinjects an external stylesheet link (repeat flag or pass comma-separated values).--no-default-styleomits Org2’s built-in inline stylesheet (useful when styling entirely via external CSS).--tocprepends an auto-generated table of contents and heading anchor IDs to each exported HTML page.--rewrite-file-linksrewrites Org file links (for examplefile:notes.org2or../notes.org) to.htmlhrefs during export and emits heading anchor IDs so rewritten::* Heading/::#custom-idtargets resolve in published output.- In-document heading links (
[[* Heading]]and[[#custom-id]]) are exported as hash anchors and trigger heading anchor IDs automatically (no--tocrequired). - Exported HTML maps
#+AUTHOR,#+DATE,#+DESCRIPTION, and#+KEYWORDSinto corresponding HTML<meta>tags. #+LANGUAGEsets the exported<html lang“…”>= attribute (defaults toenwhen omitted/invalid).#+HTML_HEADand#+HTML_HEAD_EXTRAinject raw snippets into the HTML<head>(in file order).- Single-file JSON export includes a
metadataobject when keyword metadata/head snippets are present. - Without
--apply, output is preview-only (single-file emits HTML text by default; batch mode emits summary text or JSON).
# Print formatted output for one file
npm run org2 -- fmt --file /path/to/file.org
# Apply formatting in place (supports multiple files)
npm run org2 -- fmt --file /path/to/file.org --apply
npm run org2 -- fmt --files /path/to/a.org /path/to/b.org --apply
# Check formatting drift (exit 1 + print changed files)
npm run org2 -- fmt --files /path/to/a.org /path/to/b.org --check
# Check formatting drift across a directory tree
npm run org2 -- fmt --dir /path/to/org --recursive --check
# Check formatting drift as machine-readable JSON
npm run org2 -- fmt --dir /path/to/org --recursive --check --format json
# Preview single-file formatter output as JSON (safe-edit style)
npm run org2 -- fmt --file /path/to/file.org --format json
# Format stdin and emit JSON (changed + formattedText)
cat /path/to/file.org | npm run org2 -- fmt --stdin --format json
# Check formatting drift using org2.json agendaFiles/ignorePatterns
npm run org2 -- fmt --check --config /path/to/org2.json
# Apply formatting across a directory tree
npm run org2 -- fmt --dir /path/to/org --recursive --apply
# Apply formatting and emit machine-readable JSON summary
npm run org2 -- fmt --dir /path/to/org --recursive --apply --format json
# Filter directory checks/applies by file path substring
npm run org2 -- fmt --dir /path/to/org --recursive --check --file-match projects,work
npm run org2 -- fmt --dir /path/to/org --recursive --apply --exclude-file archive,tmpNotes:
fmt --checkis intended for CI/pre-commit-style drift detection.fmt --check --format jsonemitschangedpluscheckedFiles=/=changedFilesarrays while preserving exit code semantics (0 clean, 1 drift).fmt --file ... --format jsonemits a single-file preview payload withformattedTextandchanged(without mutating files).fmt --checkdoes not support--stdin.fmt --stdin --format jsonemitschangedplusformattedText.fmt --apply --format jsonemitschangedplusprocessedFiles=/=changedFilesarrays.fmt --config PATHresolves files fromorg2.json(agendaFiles+ignorePatterns) before formatter path filters.fmt --dirscans top-level files by default; add--recursiveto include subdirectories.--file-matchand--exclude-fileuse case-insensitive path substring matching and support comma-separated terms.
# Start the LSP server over stdio
npm run org2 -- lspCurrent LSP features include parser diagnostics, document symbols, folding ranges, go-to-definition + go-to-declaration + go-to-type-definition + go-to-implementation (including file-link ::search suffix targets like ::*Heading, ::#custom-id, and ::42), find-references for both [[file:...]] and [[id:...]] links, document links for file/id/URL targets, document highlights for ID/file references, hover tooltips for links/TODO/planning keywords, rename support for [[id:...]] links plus :ID: property values and matching file-link targets, workspace file-rename edits for file links (workspace/willRenameFiles), linked editing ranges for synchronized ID edits across links/properties plus matching file links (textDocument/linkedEditingRange), completion for TODO/planning keywords, Org timestamps, and ID/file link targets, planning timestamp signature help (textDocument/signatureHelp), quick-fix code actions for CRLF/tab parser issues, document formatting (textDocument/formatting), range formatting (textDocument/rangeFormatting), table-aware on-type formatting (textDocument/onTypeFormatting), selection ranges (textDocument/selectionRange), semantic tokens for TODO/planning/properties/link targets (textDocument/semanticTokens/full), backlink code lenses for :ID: properties (textDocument/codeLens), document color extraction + hex presentations (textDocument/documentColor / textDocument/colorPresentation), inlay hints for unlabeled ID/file links (textDocument/inlayHint), call hierarchy for Org ID/file links (textDocument/prepareCallHierarchy + callHierarchy/incomingCalls + callHierarchy/outgoingCalls), and workspace symbol search over org/org2 headings.
Org2 also includes additional commands that are mostly used internally by editor integrations (for example, marking TODO states, setting SCHEDULED/DEADLINE dates, formatting, and the LSP server).
Rather than documenting them here (they change often), run:
npm run org2 -- --help
# or
node dist/cli.js --helpSee ./tools/README.md for the fixture runner and reference parser.