Tooling reference
This page covers the practical Org2 tooling surface today. For the product framing around compiler-style corpus checks, see Maintenance and health workflows.
The CLI is the shared backend for editor integrations and automation. You can use it directly or through VS Code commands.
Core command families
Run npm run org2 -- --help for current top-level usage. AI architecture, job design, draft artifacts, and provider boundaries are documented separately in AI processing architecture, AI job manifests, AI draft artifacts, and AI adapter interface so the deterministic CLI surface stays clear.
Main workflows:
agendatodoplancapturearchive,refilefmtsearch,id,query,backlinksrender-chartroam ...crypt ...export htmlpublishlintai validate-joblsp
Command conventions and stability
Audit summary for CLI consistency: most commands already use --dir for corpus roots, --recursive for traversal, --format for alternate output, and --apply for mutating writes. The lowest-risk cleanup is to make JSON output easier and consistent across commands.
Conventions:
Prefer
--format jsonfor stable machine-readable output;--jsonis a shorthand alias where JSON output is supported.Preview is the default for mutating commands. Pass
--applyto write files.Use
--dir DIRwith--recursivefor corpus-wide scans, or--file FILE/--files FILE ...for bounded scans.Text/report output is human-facing and may evolve; JSON output is the integration surface.
Examples:
npm run org2 -- agenda --dir ~/notes --recursive --json
npm run org2 -- lint --dir ~/notes --recursive --format json
npm run org2 -- roam node new --dir ~/notes --title "Acme Corp" --apply --json
Agenda
Purpose: query scheduled/deadline items across Org files.
npm run org2 -- agenda --dir ~/notes --recursive --from 2026-03-01 --to 2026-03-31
Important behavior:
Includes both
SCHEDULED:andDEADLINE:rows in-range.Supports broad filter/sort/group dimensions in CLI + VS Code integration.
Normalizes common TODO aliases into stable status buckets (including wait/hold/pause-style states).
TODO + planning edits
npm run org2 -- todo toggle --file notes.org2 --line 42 --apply
npm run org2 -- todo set --file notes.org2 --line 42 --status in_progress --apply
npm run org2 -- plan set --file notes.org2 --line 42 --kind scheduled --date 2026-03-25 --apply
Capture / archive / refile
npm run org2 -- capture --file inbox.org2 --title "Quick note" --template note --apply
npm run org2 -- archive --file notes.org2 --pos 120:0 --apply
npm run org2 -- refile --file notes.org2 --pos 120:0 --to-file projects.org2 --to-pos 40:0 --apply
Archiving moves the selected subtree to a companion archive file (by default FILE_archive for .org and .org2 files, otherwise FILE.archive). Archived subtrees receive a property drawer with ARCHIVED_AT, ARCHIVE_SOURCE, ARCHIVE_SOURCE_LINE, ARCHIVE_HEADING_PATH, and ARCHIVE_ORIGINAL_ID when the original subtree had an ID. Use --format diff to preview the exact removal/append operation, or --format json for editor/agent integrations.
Formatter
Canonical formatting for Org2 files.
npm run org2 -- fmt --dir ~/notes --recursive --check
npm run org2 -- fmt --dir ~/notes --recursive --apply
Chart rendering
org2 render-chart renders an SVG artifact from #+chart: / #+plot: metadata or an adjacent fenced ```chart block attached to an org2 table. This gives editor clients a shared backend instead of making each extension reimplement table parsing and chart semantics.
npm run org2 -- render-chart --file report.org2 --block-id quarterly_revenue --out /tmp/quarterly-revenue.svg
npm run org2 -- render-chart --file report.org2 --line 42 --format json
The first renderer supports deterministic bar, line, and bucketed histogram charts with x and y column mappings. New hand-written examples should prefer fenced chart blocks when they are easier to scan:
| bucket | fetches |
|--------+---------|
| 0-10 | 14 |
| 11-50 | 32 |
```chart histogram
x: bucket
y: fetches
sort: y-desc
source: previous-table
```
For data-backed reports, a chart block can also point at a named materialized result table in the same note:
#+name: package_fetches_result
#+results: query-fetches-by-company
| day | fetches |
|------------+---------|
| 2026-06-10 | 84 |
#+name: package_fetches_chart
```chart line
x: day
y: fetches
source: package_fetches_result
```
Add sort: x-asc, sort: x-desc, sort: y-asc, or sort: y-desc when a chart preview should be ordered independently of the table rows. JSON output includes ok, format, artifact, source, diagnostics, and svg so VS Code, Vim, or agent tooling can show useful errors for missing columns, unsupported chart types, missing chart sorts, missing named source tables, or missing chart blocks.
Local data queries
org2 query-data is the first DuckDB-backed bridge for local/ad hoc datasets described in org2 notes. It scans fenced ```dataset blocks, creates DuckDB views for explicit csv, parquet, or json paths/URLs or named org2 tables, optionally creates reusable SQL views from ```sql view=NAME blocks, then runs a fenced ```sql results=NAME block and materializes the returned rows.
```dataset fetches
type: csv
path: ./data/package-fetches.csv
engine: duckdb
```
```sql results=fetches_by_state artifact=views/fetches_by_state.org freshness=24h
SELECT state, count(*) AS fetches
FROM fetches
GROUP BY state
ORDER BY fetches DESC
```
Reusable SQL views can sit between datasets and the final materialized result:
```sql view=california_fetches
SELECT state, fetches
FROM fetches
WHERE state = 'CA'
```
```sql results=fetches_by_state
SELECT state, sum(fetches) AS fetches
FROM california_fetches
GROUP BY state
```
Read-only HTTP(S) or file: URLs can be recorded with url: when DuckDB can read the source directly:
```dataset remote_fetches
type: csv
url: https://data.example.test/package-fetches.csv
engine: duckdb
credential: env:SCARF_API_TOKEN
config: profile:product-analytics
```
```sql results=remote_fetches_by_state
SELECT state, count(*) AS fetches
FROM remote_fetches
GROUP BY state
```
Named org2 tables can also become local DuckDB views without an intermediate CSV export:
#+name: raw_fetches
| state | fetches |
|-------+---------|
| CA | 42 |
| NY | 24 |
```dataset fetches
type: table
source: raw_fetches
engine: duckdb
```
```sql results=fetches_total
SELECT sum(fetches) AS fetches
FROM fetches
```
npm run org2 -- query-data --file report.org2 --results fetches_by_state
npm run org2 -- query-data --file report.org2 --line 42 --format json
npm run org2 -- query-data --file report.org2 --inspect --include-script
npm run org2 -- query-data --file report.org2 --results fetches_by_state --out views/fetches_by_state.org
cat report.org2 | npm run org2 -- query-data --stdin --results fetches_by_state
The default output is a named org table with #+name: fetches_by_state so it can be pasted or written into the note and consumed by render-chart via source: fetches_by_state. Materialized tables also include a compact #+query-data: provenance line with the result id, row count, optional artifact reference, optional freshness token, selected SQL hash, full DuckDB script hash, and ran_at timestamp so refreshed results can be compared without embedding the full script in the note. Add artifact=PATH to a SQL result block to record the intended materialized output; when --out FILE is used, the actual written artifact path is stamped instead. Add freshness=24h, ttl=24h, or max-age=24h to a SQL result block when editor, agent, or dashboard clients should know how long a materialized result can be treated as fresh. SQL result ids must be unique within the note; duplicate result ids are reported as diagnostics instead of selecting an arbitrary block. Dataset ids and SQL view ids also share DuckDB's relation namespace, so a SQL view cannot reuse a dataset name. URL and table datasets may also include metadata-only credential: or auth: references and config: or profile: references such as env:SCARF_API_TOKEN or profile:product-analytics; inline bearer tokens and passwords are rejected, and these references are not injected into the generated DuckDB SQL. JSON output includes diagnostics, dataset metadata, SQL view metadata, available SQL result block metadata, provenance hashes/artifact/freshness/run timestamp, rows, and the generated org table; --include-script also includes the DuckDB setup SQL for debugging. Use --inspect to emit parsed JSON metadata, structural diagnostics, and selected-query provenance without running DuckDB; add --include-script to preview the generated DuckDB SQL for the selected result in the same dry run. Editor and agent clients can pass an unsaved buffer with --stdin and select the SQL result block containing or after the cursor with --line N; file-backed dataset paths are then resolved relative to the current working directory, while URL datasets are passed through as declared. The command expects a local DuckDB CLI on PATH for execution, or a custom path via --duckdb.
Corpus lint
Lint is the first compiler-style health pass for artifact metadata and corpus structure. It belongs to the broader maintenance and health workflow alongside formatter checks, graph queries, publish previews, and ID/index repair passes.
npm run org2 -- lint --dir ~/notes --recursive
Current checks include:
invalid or missing
ORG2_ARTIFACT_ROLEon generated outputsmissing/invalid provenance, generator, and generated-at metadata
duplicate IDs and unresolved provenance references
stale generated artifacts when provenance file mtimes or
ORG2_SOURCE_HASHESno longer matchunresolved
id:links, unresolved wiki links, and ambiguous wiki links/aliases using the same graph index as roam workflowsconventional corpus-flow checks when you organize notes as
raw/->notes/->compiled/->views/->publish/
See Corpus flow for the canonical zone model, artifact roles, and generated-output trust boundaries.
AI job manifest validation
org2 ai validate-job validates repeatable AI workflow manifests without calling a provider or loading secrets.
npm run org2 -- ai validate-job --job examples/jobs/weekly-summary.org2-ai.json
npm run org2 -- ai validate-job --job examples/jobs/weekly-summary.org2-ai.json --format json
Use this in CI or editor workflows before a future AI runner consumes a job. The validator checks corpus input selection, task type, symbolic adapter names, generated output targets, provenance/review requirements, and common accidental secret leaks. See AI job manifests for the schema and examples.
org2 ai run writes a reviewable generated draft artifact from a validated job. The current implementation is provider-free and uses manifest input.files as deterministic source material, including simple glob patterns. It stamps ORG2_PROVENANCE, ORG2_SOURCE_HASHES, prompt/template, adapter/model, generated-at, and ORG2_REVIEW_STATUS metadata. Without --apply it previews the draft.
npm run org2 -- ai run --job examples/jobs/weekly-summary.org2-ai.json --out views/weekly-summary.org2
npm run org2 -- ai run --job examples/jobs/weekly-summary.org2-ai.json --out views/weekly-summary.org2 --apply
org2 ai suggest-links ranks compiler-provided roam/linkify candidates with the deterministic mock adapter. It scans the graph, aliases, exact linkify matches, represented-node semantic suggestions, and title-case entity mentions, then emits review-only suggestions with confidence, reasons, source context, and citations. It never edits canonical notes directly; --apply only writes the suggestion report when --out is provided.
npm run org2 -- ai suggest-links --dir ~/notes --recursive --format json
npm run org2 -- ai suggest-links --dir ~/notes --recursive --out views/link-suggestions.org2 --apply
org2 ai promote is the safe acceptance path. It refuses drafts until ORG2_REVIEW_STATUS is reviewed, then appends the reviewed body to a canonical note only when --apply is present and marks the draft promoted.
npm run org2 -- ai promote --file views/weekly-summary.org2 --to-file notes/weekly-summary.org2 --apply
See AI draft artifacts for the full format, review checklist, and VS Code command-palette entry points.
Compiled corpus artifacts
org2 compile corpus emits a stable, schema-versioned knowledge artifact that LLM tools, search indexes, and other automation can consume. Org2 only compiles local plain-text notes into structured data; it does not call an LLM or require any hosted AI service.
npm run org2 -- compile corpus --dir ~/notes --recursive --out compiled/corpus.json
npm run org2 -- compile corpus --dir ~/notes --recursive --format jsonl --out compiled/corpus.jsonl
The JSON form includes:
standardized
artifactmetadata: role, generator, generated-at timestamp, source provenance, source hashes, and review statusfiles with relative paths, absolute paths, SHA-256 hashes, line counts, titles, and IDs
file and heading nodes with source ranges for citations
heading TODO state, priority cookies, tags, planning timestamps, explicit
properties, inheritedinheritedProperties, overlaideffectiveProperties, IDs, and aliaseslinks and resolved backlinks for explicit
id:links and unambiguous wiki linkstext snippets suitable for previews or retrieval pipelines
Use JSONL for larger corpora when downstream tools prefer one record per line; the first JSONL record carries the same artifact metadata header as the JSON form. If you wrap compiled artifacts in Org files, stamp the wrapper with the same ORG2_ARTIFACT_*, ORG2_SOURCE_HASHES, and ORG2_REVIEW_STATUS fields and keep using org2 lint for generated-output health checks.
Search + cited query
Use search for literal, case-insensitive full-text lookup over .org and .org2 files, and query when you want cited context suitable for answering factual questions from notes. Directory scans are non-recursive unless --recursive is set. The External LLM consumer pattern page shows how provider-agnostic agents can turn this JSON into cited model context without adding LLM calls to Org2 core.
npm run org2 -- search "Chris Martin" --dir ~/notes --recursive --context 3 --sort date-desc
npm run org2 -- query "Chris Martin" --dir ~/notes --recursive --subtree --sort date-desc --format json
npm run org2 -- query "Sentra" --dir ~/notes --recursive --format json
Useful flags:
--context Nincludes surrounding source lines.--limit Ncaps returned matches.--sort date-descis useful for “when did I last...” style questions over date-named daily files and heading timestamps.--subtreededuplicates matches to cited heading/subtree sections withsourceRange,headingAncestry,matchedLines, and full subtree context.--answer-contextadds a plain subtree text block for downstream local LLM prompts.--date-from/--date-toand--file-zonenarrow results by local corpus zones and source dates.--format jsonreturns machine-readable file, line, heading, snippet, source range, and context fields.
Roam workflows
npm run org2 -- roam db-sync --dir ~/notes --recursive --apply
npm run org2 -- roam node new --dir ~/notes --title "Acme Corp" --apply
npm run org2 -- roam backlinks --id 123e4567-e89b-12d3-a456-426614174000 --dir ~/notes --recursive --format json
npm run org2 -- roam linkify --dir ~/notes --recursive
npm run org2 -- roam graph --dir ~/notes --recursive --format report
npm run org2 -- roam graph --dir ~/notes --recursive --format json
Org2 supports both title-based wiki links and explicit id: links, with backlinks across both forms. Linkify and graph reports are intended as compiler-style maintenance passes: preview references, strengthen links deliberately, and inspect corpus connectivity without leaving plain files. org2 roam linkify --format json reports exact title/alias replacements plus review-only represented-node suggestions with confidence, evidence tokens, and source ranges for headings or multi-line paragraphs; --apply only writes exact safe replacements, never semantic suggestions. org2 roam graph --format report emits a human-readable maintenance view with graph summary, orphan/high-degree nodes, alias/title collisions, unresolved or ambiguous links with file/line citations, and linkify suggestions; --format json includes the same maintenance payload for scripts and CI.
Org-crypt
Org2 keeps the existing Org-style :crypt: convention and encrypts at the subtree boundary. A subtree can be encrypted symmetrically with a passphrase, or to multiple public-key recipients so the same private note can be opened by your user key, another device key, and an agent key without sharing one password around.
# Passphrase/symmetric mode
npm run org2 -- crypt decrypt --file secrets.org2 --line 42 --passphrase 'your-passphrase' --apply
npm run org2 -- crypt encrypt --file secrets.org2 --line 42 --passphrase 'your-passphrase' --apply
# Multi-recipient public-key mode
npm run org2 -- crypt encrypt --file secrets.org2 --line 42 \
--recipient user@example.com \
--recipient agent@example.com \
--apply
# Public-key recipient files are useful for keys that are not in your keyring
npm run org2 -- crypt encrypt --file secrets.org2 --line 42 \
--recipient-file keys/agent-public.asc \
--apply
# Or make sharing per-entry with an Org property drawer
# Relative recipient-file paths resolve from the current note's directory.
* Private note shared with an agent :crypt:
:PROPERTIES:
:CRYPT_RECIPIENT_FILE: keys/agent-public.asc
:END:
Only the entries with this property are encrypted to that agent.
# Migration: decrypt an existing block, then re-encrypt it for the new recipients
npm run org2 -- crypt reencrypt --file secrets.org2 --line 42 \
--passphrase 'old-passphrase-if-needed' \
--recipient user@example.com \
--recipient agent@example.com \
--apply
Per-entry recipient properties let one corpus mix private-only and shared-with-agent notes without a global editor setting. :CRYPT_RECIPIENT: / :CRYPT_RECIPIENTS: add GPG recipient identifiers, while :CRYPT_RECIPIENT_FILE: / :CRYPT_RECIPIENT_FILES: add armored public key files. Multiple values can be separated with commas. Relative recipient-file paths are resolved relative to the Org2 file that contains the subtree, so they work across machines when the key file lives in the synced project.
Export + publish
npm run org2 -- export html --file README.org --out README.html --apply
npm run org2 -- export html --dir docs/site --recursive --out-dir site --apply
npm run org2 -- publish docs-site --config org2.json
Useful export options include TOC, heading numbering, stylesheet injection, and Org-file-link rewrite to HTML targets.
LSP
Start language server:
npm run org2 -- lsp
Current implemented capabilities include:
definitions/references/hover/completion/signature help
rename + linked editing for IDs/file links
file-rename link updates
formatting (document/range/on-type)
semantic tokens, inlay hints, code lens, call hierarchy
For full details, see:
LSP_README.md