orgwarrior
A porcelain for Org's agenda. Your tasks from the command line, with
the Emacs you already run doing all the Org work: a
taskwarrior-style CLI where every task gets a
short ID, and orgwarrior ID VERB acts on it.
- Org does the work. orgwarrior never parses your files: it asks your
running Emacs (
org-agenda,org-todo,org-schedule,org-read-date). Your agenda files, TODO keywords, custom agenda commands, logging, habits and refile targets all apply as in Emacs. - Nothing to set up in Emacs. It loads its own elisp into the daemon
when it needs to; your
init.elstays as it is. - IDs that stay put. A task's ID comes from its file and title, so it's the same in every view and from one day to the next.
Want it on your phone too? orgwarrior-web is a web page over the same engine, and orgwarrior-mcp gives it to Claude.
Quick start
You need Emacs 29 or later running as a daemon (emacs --daemon, or
your system's Emacs service). Then one of:
brew install aleksozolins/tap/orgwarrior # macOS or Linux, with Homebrew
yay -S orgwarrior # Arch, from the AUR (any AUR helper)
pipx install orgwarrior # anywhere with Python 3.11+ (or: uv tool install orgwarrior)
Want the web page or Claude too? Install orgwarrior-web or orgwarrior-mcp instead: each brings this command along, sharing one copy of the engine.
orgwarrior # today's agenda
orgwarrior help # everything on one screen
It shows what Emacs's agenda shows, from your org-agenda-files: if every
view is empty, Emacs has none set. Then act on a task by the ID beside it:
orgwarrior c1 done -m "booked for the 20th"
orgwarrior 32 sched fri
orgwarrior add NEXT call the dentist :@phone: s:fri
Update as you installed it (brew upgrade, your AUR helper, pipx upgrade orgwarrior). An alias saves typing: alias ow=orgwarrior. Homebrew and
the AUR install the man page; with pipx or uv, put it where man looks
(again after an upgrade):
mkdir -p ~/.local/share/man/man1
orgwarrior help --man > ~/.local/share/man/man1/orgwarrior.1
Everyday use
orgwarrior |
the default view (today) |
orgwarrior week, orgwarrior fri, orgwarrior all |
this week, one day, every open TODO |
orgwarrior +@phone, orgwarrior next +@phone |
a tag search, a TODO state with one |
orgwarrior flu shot |
a text search; --archive searches the archives too |
orgwarrior projects.org |
an agenda file's outline |
orgwarrior c1 |
show a task: its path, body, notes and children |
orgwarrior c1 done, orgwarrior c1 wait |
any of your TODO keywords (asks for a note where org would) |
orgwarrior c1 sched fri 14:00, orgwarrior c1 due +2w |
dates, as org-read-date reads them |
orgwarrior c1 +@home -someday, orgwarrior c1 pri A |
tags, priority |
orgwarrior c1 refile projects |
refile under a heading (alone, it lists the targets) |
orgwarrior c1 clock in, orgwarrior clock out |
clocking; orgwarrior clocked week totals it |
orgwarrior c1 clocks add yesterday 14:00-15:30 |
time already spent, a running clock left alone |
orgwarrior closed week |
what was done, day by day, archived tasks too |
orgwarrior c1 edit |
the task in Emacs, in this terminal |
orgwarrior add event Dentist @fri 10:30 |
an event: a plain timestamp, no keyword |
orgwarrior help TOPIC covers each part in full, with examples (help dates, help refile, help clock…), and so does --help after any
command. Several IDs at once work too: orgwarrior c1 32 done.
How it works
orgwarrior isn't a task manager: Org is. In Git's terms Org is the plumbing, and orgwarrior a porcelain: friendlier commands over machinery that already works.
porcelain orgwarrior orgwarrior-web orgwarrior-mcp
a terminal a browser Claude, any MCP client
\ | /
engine orgwarrior.el, loaded into your running Emacs
|
plumbing Org mode ──▶ your .org files
A small Python program sends each command to your Emacs daemon with
emacsclient, where its elisp drives Org: building the agenda, changing a
heading, reading a date. Org writes the file, as it would from the agenda
buffer, so logging, repeaters, [1/3] cookies and hooks behave as in
Emacs.
- IDs are short hashes of the file and the heading's title, git-style.
Changing a task's keyword, tags or dates keeps its ID; renaming or
refiling it changes it, and the new one is printed (
6a → 91). A task that's gone simply stops matching, and its ID stays its own for a day while Emacs runs (a new task that would share it gets a longer one), so a stale ID can't act on the wrong task. - Notes: where Emacs would ask for one (
@inorg-todo-keywords, aLOGGINGproperty), orgwarrior asks on the terminal.-manswers up front. - Safety: if a file has unsaved changes in Emacs, orgwarrior refuses
rather than save someone's half-finished edit.
killasks first.
Configuration
All optional: ~/.config/orgwarrior/config.toml (or $XDG_CONFIG_HOME,
or ORGWARRIOR_CONFIG). config.toml.example has
every key, commented.
| key | what it does |
|---|---|
default_view |
the view for bare orgwarrior (default today) |
socket |
the Emacs server socket, if not the default (also -s or ORGWARRIOR_SOCKET) |
prefix_format |
org-agenda-prefix-format, for orgwarrior only |
tags |
inline (after the title, the default) or right |
time_grid |
true to keep Org's time grid |
color |
auto (on a terminal, unless NO_COLOR), always, never |
[views] |
name = "key": an org-agenda-custom-commands entry as a view; a week here replaces the built-in one |
[add] |
where add writes: file (else Emacs's org-default-notes-file), a heading to file under, captured = true for a :CAPTURED: time |
[add.event] |
the same for add event |
[refile] |
new_in and new_suffix for refile --new; usual, a front end's first choice |
[colors] |
a role or TODO keyword → bold cyan, #ff8f88, on-green… (orgwarrior help colors) |
[web] |
orgwarrior-web's settings; orgwarrior itself ignores them |
If something's wrong
- "no Emacs daemon running on socket 'server'": start Emacs as a
daemon (
emacs --daemon). If yours runs under another name (emacs --daemon=work), setsocket = "work"in the config. - An empty agenda: Emacs has no
org-agenda-files. Set them in your init ((setq org-agenda-files '("~/org")), a directory works), or withC-c [in a file, as for Org's agenda. - "File to add to not found":
addwrites toorg-default-notes-fileunless[add] filesays otherwise; point it at your inbox. - "… is encrypted and not open in Emacs": an agenda file is
.gpg, and orgwarrior can't type its passphrase. Open it in Emacs once (it stays decrypted while Emacs runs), or leave it out oforg-agenda-files. - "Emacs tried to prompt": something in your Emacs wanted to ask a question (a hook, an unsaved-file prompt). orgwarrior can't answer prompts, so it stops; the message says which one.
- Odd colors:
color = "never", orNO_COLOR=1, turns them off;[colors]changes any of them.
From Python
orgwarrior.api is the same engine for other programs (orgwarrior-web is
built on it): views, tasks and actions as plain data.
from orgwarrior.api import Orgwarrior
ow = Orgwarrior() # your config.toml and daemon
ow.view("wait +@phone") # [{"text", "id", "spans"}, ...]
ow.show("c1") # {"id", "file", "path", "lines", "children"}
ow.show("c1", html=True) # ... plus "html": its text as org exports it
ow.act(["c1"], "done", note="booked")
With Claude
Claude Code, or any AI agent with a shell on the machine with your Emacs, can run orgwarrior for you. A skill teaches it how: reading views and IDs, the verbs, adding, asking before it deletes anything.
mkdir -p ~/.claude/skills/orgwarrior
orgwarrior help --skill > ~/.claude/skills/orgwarrior/SKILL.md
Then ask "what's due this week?" or "what did I get done yesterday?".
Write it again after an upgrade, for what's new. Your own habits (your
inbox's tags, keywords you'd rather it left alone) go in your
~/.claude/CLAUDE.md, which a rewrite leaves alone.
Where Claude can't run commands on that machine (claude.ai, the phone
apps), orgwarrior-mcp
gives it the same agenda as MCP tools.
Development
git clone https://github.com/aleksozolins/orgwarrior
cd orgwarrior
uv tool install --editable . # the orgwarrior command runs this checkout
uv run pytest # everything, the ERT suite included
scripts/dev-daemon # a throwaway emacs -Q daemon on test fixtures
scripts/dev-orgwarrior today # orgwarrior against it
scripts/dev-daemon stop
The dev daemon never touches your real Emacs, config or Org files: it writes Org files only in its own copy, whatever config talks to it. The scripts run on Linux and macOS. Tested on Emacs 29.4 (its Org 9.6) and 31.1 (Org 9.8).
Claude (Anthropic's AI) was used in developing orgwarrior. All code is reviewed by me, and every behavior is covered by real tests.
Contributing
I read every issue and fix what I can, bugs first. Pull requests are
welcome; for anything big, open an issue first so we can talk it through.
uv run pytest runs every test (Development).
License
GPL-3.0-or-later, as Emacs and Org are.
Metadata
Release files for orgwarrior 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| orgwarrior-0.1.0.tar.gz | 755.6 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| orgwarrior-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 855.1 kB
Release files / orgwarrior-0.1.0.tar.gz
| Download URL | orgwarrior-0.1.0.tar.gz |
|---|---|
| Size | 755.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
49c2dbed048617382f58cb387f77d0f3383c694dca6a4194c778ea3fcb7abca2
|
|
BLAKE2b-256 checksum How to use checksums |
3fe84750472fc84a6cbd957b154ff55337814132f0911c8fa5fb98b0e4f1717e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / orgwarrior-0.1.0-py3-none-any.whl
| Download URL | orgwarrior-0.1.0-py3-none-any.whl |
|---|---|
| Size | 99.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
65834ca0a900c1e943514df19a638f42edf2a9f7ef1f44345194f82312d9d387
|
|
BLAKE2b-256 checksum How to use checksums |
628e1f554d458c8dc3463bfb2a37ab92c0fb425989e256629fd9fe8285f766ea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for orgwarrior 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for orgwarrior-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.