Skip to content
linoPublic

About

Implementation of some things org-mode in rust

Resources

Stars

3 stars

Watchers

0 watching

Forks

Repository files navigation

org-tools

Unified org-mode CLI: lint, format, query, clock, export. Runs without Emacs.

Why

For almost ten years I maintained a janky toolchain of Python scripts and Emacs Lisp hacks to keep my org files consistent. It worked — mostly — until it didn’t: scripts broke on edge cases, elisp ran only inside Emacs, and nothing could run in CI without pulling in a full Emacs installation.

org-tools replaces all of that with a single Rust binary. It is fast, correct (rules are validated against the org-mode specification and Emacs source), and designed to run anywhere — locally, in CI, or from any editor.

This project was built with the help of AI tooling (Claude Code). The rule set was designed by studying org-lint.el and the org-mode specification.

Features

Lint & Format (org fmt)

  • 9 format rules (auto-fixable): trailing whitespace, blank lines, heading spacing, table alignment, property drawer alignment, keyword spacing, tag alignment, list formatting, timestamp spacing
  • 38 lint rules (report-only): structural validation (including E003 include-validity for cross-file #+INCLUDE: directives), correctness checks, deprecation warnings, style suggestions — covering ~36 of Emacs org-lint’s ~58 checks
  • Protected regions: source, example, export, quote, verse, center, and comment blocks are never modified by format rules
  • Configurable via .org-tools.toml with sensible defaults matching Emacs

Query, Agenda & Columns (org query)

  • Query language with predicates: todo, done, tags, heading, body, property, priority, level, scheduled, deadline, closed, clocked, blocked, actionable, waiting
  • Boolean operators: and, or, not, parentheses, implicit AND
  • Agenda view (org query agenda): multi-day timeline (--from, --days, --warning-days, --composite) projecting + / ++ / .+ repeaters, org-habit (:STYLE: habit) consistency graphs, overdue items, deadline warnings, and active body timestamps in human, json (JSON schema via org schema agenda), locator, org, and md (-o)
  • Column view (org query columns): #+COLUMNS: specification parser and bottom-up property/clock/effort rollup evaluator ({+}, {min}, {max}, {mean}, {:}) in human, json, org, and md
  • Tag inheritance: child entries inherit parent tags in queries
  • Output formats: human, JSON (with JSON schema), locator, Org, Markdown

Org Item Locator

A unique identifier for any heading across a tree of org files:

PatternExampleStability
id:<uuid>id:550e8400-e29b-...Survives moves
<file>::#<custom-id>notes.org::#project-xFile-scoped
<file>::*/<path>todo.org::*/Work/MeetingFragile on rename
<file>::<line>inbox.org::42Fragile on edit

When an entry has an :ID: property, that is always preferred.

Clock Tracking (org clock)

  • Active clocking: org clock in, org clock out, and org clock cancel mutations managing :LOGBOOK: CLOCK: timestamps
  • Reports & Effort Variance: total clocked time grouped by entry, tag, or day with :EFFORT: vs. clocked duration variance deltas
  • Date filtering: --from and --to date range
  • Running clocks: detect entries with open clock lines
  • Output: human-readable tables and JSON

Entry Updates & Refiling (org update, org refile)

  • add-id: add :ID: properties to entries (UUIDv4, deterministic UUIDv5, template, or command)
  • set-state: change TODO keyword with automatic CLOSED timestamps, :LOGBOOK: state transition logging (#+STARTUP: logdone / :LOGGING:), :LAST_REPEAT: recording, repeater auto-advance (--no-repeat to close permanently), :TRIGGER: cascades, and --query filtering
  • set-scheduled / set-deadline: set, shift (today / ., +Nd, +Nw, +Nm, +Ny, -Nd), or --clear SCHEDULED and DEADLINE timestamps
  • add-todo: insert new entries with planning, priority, properties, and tags
  • set-property / delete-property / set-tags / dep: drawer, tag, and org-edna dependency mutations
  • add-cookie / calc: compute [/] / [%] statistic cookies and #+TBLFM: formulas
  • refile (org refile): move or copy subtrees across files or headings with automatic heading level adjustment and statistic cookie recalculation

Show & Export (org show, org export)

  • Scoped node extraction (org show): extract headings or level-0 org-roam file nodes as org, md, or json with optional --expand-includes
  • Markdown export (org export md): Zensical-ready GFM with Mermaid fences, cross-node [[id:...]] resolution, and --expand-includes (#+INCLUDE: with ::*Heading, :minlevel N, :lines "A-B", and :only-contents t)
  • Calendar export (org export ical, org export jscal): RFC 5545 iCalendar and RFC 8984 JSCalendar with date range and tag filtering

GTD Navigator & Action Inbox (org next, org roam gtd)

  • Action navigator (org next): find immediate unblocked next actions filtered by context, effort, energy, workmode, and project across vaults
  • GTD captures (org roam gtd inbox, org roam gtd project): capture raw inbox tasks and scaffold project outlines without Emacs
  • Agenda synchronization (org roam sync-agenda-tags): synchronize :agenda: filetags across vaults containing active TODO tasks

Zettelkasten & Fleeting Notes (org fleeting, org roam)

  • Luhmann fleeting queue (org fleeting): capture thoughts with source medium and location, list pending queues, reform into permanent concept notes, convert to tasks, discard, or interactively process
  • Atomic note capture (org roam capture): create permanent notes via templates with automatic Folgezettel parent links and slug naming
  • Backlinks & graphs (org roam node, backlinks, links, graph): query incoming links and export knowledge graph structures in Mermaid or JSON

MCP Server & Workspace Cache (org mcp, org cache)

  • Built-in zero-Emacs JSON-RPC 2.0 stdio server exposing 16 workspace-confined tools: org_roam_node, org_roam_backlinks, org_roam_search, org_roam_capture, org_fleeting_list, org_fleeting_transform, org_query_next, org_query_blocked, org_query_agenda, org_show, org_update_state, org_update_planning, org_clock_in, org_clock_out, org_refile, and org_fmt_file
  • Incremental SQLite WAL + FTS5 cache (.cache/org-cache.db) with warm telemetry

Language Server Protocol (org lsp)

  • Built-in zero-Emacs JSON-RPC 2.0 stdio server (org lsp [--workspace <DIR>] [--roam-dir <DIR>])
  • Editor capabilities: diagnostics, formatting, code actions, document symbols, document links, definition, backlink references, folding, completion, hover, workspace rename, and semantic tokens
  • Ready out of the box with Neovim, Helix, VS Code, Zed, and Emacs eglot

Archive (org archive)

  • Move done entries to an archive file with metadata properties
  • Configurable target via #+ARCHIVE: or --target
  • Preserves subtree structure and adds :ARCHIVE_TIME:, :ARCHIVE_FILE:, :ARCHIVE_OLPATH:

Quick Start

# Install via Homebrew (macOS / Linux), Cargo, or run directly via GHCR container
brew install --cask lino/tap/org-tools
cargo install org-tools
docker run --rm -v "$PWD:/workspace" ghcr.io/lino/org-tools:latest fmt check README.org

# Lint
org fmt check file.org

# Format in place
org fmt format file.org

# Query entries
org query search 'todo:TODO tags:work' ~/org/

# Find immediate next action
org next --context @office --max-effort 1:00 --pick

# Capture fleeting thought and create permanent concept note
org fleeting capture "Atomic concept notes link by ID" --medium "Smart Notes"
org roam capture "Knowledge Architecture" --parent "Slip-Box"

# Agenda view and Zensical Markdown export
org query agenda ~/org/
org query agenda --from 2026-04-06 --warning-days 7 --composite --format md -o agenda.md ~/org/

# Set or shift planning dates
org update set-scheduled '+3d' 'id:550e8400-e29b-41d4-a716-446655440000'
org update set-deadline --clear 'id:550e8400-e29b-41d4-a716-446655440000'

# JSON output for tooling
org query search 'deadline:past' --format json ~/org/

# Clock report grouped by tag
org clock report ~/org/ --group-by tag

# Export scheduled items to iCalendar
org export ical ~/org/ -o calendar.ics

# Add IDs to all entries
org update add-id ~/org/

# Mark entries as DONE via piping
org query search 'todo:TODO tags:done' --format locator | org update set-state DONE

# Pipe org content through set-state with query filter
cat todo.org | org update set-state DONE --query 'tags:shipped'

# Archive completed entries
org archive ~/org/

# Start Language Server Protocol server for editor integration
org lsp --workspace ~/org/

# Shell completions, Unix manpages, and embedded JSON schemas
eval "$(org --completions zsh)"
org --completions fish | source
eval "$(org --completions bash)"
org --completions bash > /etc/bash_completion.d/org
man 1 org
man 5 org-tools.toml
org schema --list
org schema columns --output build/org-columns-output.schema.json

Configuration

Copy .org-tools.toml.example to .org-tools.toml in your project root:

[format]
trailing_whitespace = true
blank_lines = false
heading_blank_lines = false
table_format = true
property_drawer_align = true

[lint]
disabled_rules = []

[agenda]
deadline_warning_days = 14

org-tools searches for .org-tools.toml starting from the current directory and walking up to the filesystem root.

See docs/user/usage.org for the full usage guide and rule reference.

Building from Source

Requires Rust 1.70+ or use mise to install the pinned version:

mise install           # install pinned Rust
mise run build         # cargo build
mise run install       # install org binary into ~/.cargo/bin
mise run test          # cargo test
mise run lint          # clippy + rustfmt + org fmt check
mise run hooks:install # install git pre-commit and pre-push hooks

Project Structure

org-tools is a Cargo workspace with two crates:

CratePurpose
org-tools-coreShared library: rules, runner, config, OrgDocument, OrgLocator
orgUmbrella binary: org fmt, org query, org clock, org update, org export, org archive

Documentation

Published via the Three-Manual Zensical site (zensical.toml, mise run docs:build) and native Unix roff manpages (man/org.1 and man/org-tools.toml.5):

License

GPL-3.0-or-later. See LICENSE.

org-tools’s rule set was designed by studying org-lint.el and the org-mode specification. We chose GPL to respect the ecosystem that made this possible.

About

Implementation of some things org-mode in rust

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages