System: Org Mode

Table of Contents

Get the raw elisp file

Use n and p to navigate this webpage, and i for a table of contents. Press ? for a full list of commands available.


This is the first official article for my system series, however I already wrote a little bit about my Org mode workflow here. This is a more complete look at my configuration for Org mode.

Org is a plaintext note-taking syntax which excels at hierarchical structures and agenda building. This blog was written in Org syntax, as are all of my notes and dates, recipes, and habits. My entire life, basically, exists in three Org files.

Org mode is an Emacs major mode for editing Org files. It is highly configurable and useful for queries, viewing the agenda, outlines, and navigation.

Getting Org mode

Org mode is included in Emacs. All (a normal person) has to do is require it:

(require 'org)

I am a contributor to org (a single commit so far), so I installed the latest version from git:

# Clone the Org mode project into the ~/code/org-mode folder (or wherever)
git clone git://git.svannah.gnu.org/emacs/org-mode.git ~/code/org-mode
(add-to-list 'load-path "~/code/org-mode/lisp")
(require 'org-loaddefs)

My org directory

This variable is used for building the agenda and capturing items. It is the path to the parent directory of all of my Org files.

(setq my-org-directory "~/org/")

Startup hook

A number of things need to happen when entering Org mode.

(defun my/org-mode-setup ()
  (setq truncate-lines nil)
  (org-autolist-mode 1))

(add-hook 'org-mode-hook #'my/org-mode-setup)


This will wrap text automatically while typing. If a paragraph becomes out of wack for any reason, use M-q (org-fill-paragraph) with point in the paragraph in order to align it.

(setq truncate-lines nil)

For long lines in an Org file, I like them to be wrapped to the next line instead of having to scroll horizontally.


This requires that org-autolist is loaded, available from MELPA.

org-autolist makes org-mode lists behave more like lists from Google Docs. Within a list, pressing return will create a new list item.

It can be installed by first setting up use-package, then installing org-autolist.

(use-package org-autolist)

General Settings

Show an overview of an Org file by default

Repeatedly pressing S-TAB will cycle between an overview and showing all content.

(setq org-startup-folded t)

Align to heading text

This is a personal preference (and not a very strong one), but I prefer the text to line up beneath the heading rather than always aligned to the first column.

(setq org-adapt-indentation t)

Return follows link

When point is within a link, C-c C-o (org-open-at-point) will launch the appropriate application for the link, usually a web browser or another Org file. In addition, to follow a link by pressing return, add this to your config.

(setq org-return-follows-link t)

Show inline images

Inline images are represented as Org links without a description. They can be toggled on and off with C-c C-x C-c.

(setq org-startup-with-inline-images t
      org-image-actual-width nil)

The size of images can be controlled by setting an:

#+ATTR_ORG: :width 300

(or whatever value) directly above the link.

When inserting a new link as an image, it will show as a link at first. You can toggle inline images off and on again to display it. This toggling step is also necessary for resizing images.

Use internal unique id generation

Org mode has a short id creation method which I find aesthetically pleasing. Ids can be used for linking to headings from other places in an Org file or another file.

Use M-x org-id-get-create to create an id at the current heading.

(setq org-id-method 'org)

Log notes into drawer

C-c C-z will log a note to the current heading. I find it nice to separate these notes from the rest of the heading content by placing them in a collapsible drawer.

(setq org-log-into-drawer t)

Log a note when rescheduling

Log a note when setting a deadline (C-c C-d) or a schedule (C-c C-s) on a heading which already has a deadline or scheduled cookie.

(setq org-log-reschedule 'note
      org-log-redeadline 'note)


A task is any heading with a keyword, such as TODO or DONE attached to it. Tasks are essential for building an agenda.


Keywords denote a status of a task. Statuses can be split into two general categories: TODO and DONE. In the configuration, the TODO keywords are listed first, then the pipe character |, then the DONE keywords.

(setq org-todo-keywords
         "TODO(t!)" ;; Default keyword. Log timestamp
                    ;; automatically. Used for tasks that are not
                    ;; immediate or that have a specific date, like an
                    ;; appointment. Can be scheduled or deadlined.

         "NEXT(n!)" ;; The very next thing to do for a specific
                    ;; project. Log timestamp automatically. Should
                    ;; only be one per project.

         "WAITING(w@)" ;; Waiting on an external event, like a package
                       ;; to arrive or work to be done by another
                       ;; person. Log a note when entering this state
                       ;; describing who or what you are waiting on.

         "SOMEDAY(s)" ;; A task without a schedule or deadline.
         "DONE(d!)" ;; Completed task. Log timestamp automatically.

         "CANCELLED(c@)"))) ;; Cancelled task. Log a note for why this
                            ;; task was cancelled.

In order to mark a heading with a keyword, use C-c C-t (org-todo). Some keywords are configured to log a note, in which case a popup buffer will show. Once the note is completed, use C-c C-c to store it into the drawer.

Enforce todo dependencies

If a child task has a keyword that is not in the DONE category, the parent task can not be marked complete. Parent tasks with unfinished children will be dimmed in the agenda view.

(setq org-enforce-todo-dependencies t
      org-enforce-todo-checkbox-dependencies t
      org-agenda-dim-blocked-tasks t)


Tags denote the type of the work required to complete a task split into two groups: context and energy. Context is used to define the physical requirements of a task, like needing to be online, in the city, or on your phone. Energy is the mental state needed to excell at a task like 'mindful', or 'social'. From each group, a heading may have at most one tag.

You can set tags for a heading using C-c C-q

(setq org-tag-alist '((:startgroup)
                      ("web" . ?w)
                      ("phone" . ?p)
                      ("outdoors" . ?o)
                      ("city" . ?c)
                      ("dev" . ?d)
                      ("mindful" . ?m)
                      ("tedious" . ?t)
                      ("social" . ?s)
                      ("physical" . ?P)


The approximate amount of time it will take to complete a task. This can be set for a heading using C-c C-x e.

(add-to-list 'org-global-properties '("Effort_ALL" . "0:05 0:15 2:00 4:00"))


Which files show up in agenda and refile, and how to interact with them.


Configure which files are used when building the agenda.

You can either list individual files here, use the contents of a directory, or recursively include all org files in a certain directory.

;; List files individually
(setq org-agenda-files (list (concat my-org-directory "projects.org")
                             (concat my-org-directory "IN.org")))

;; Include all files in `my-org-directory', but not recursively
;; (setq org-agenda-files (list my-org-directory))

;; Include all files in `my-org-directory' recursively
;; (setq org-agenda-files my-org-directory)


Configure which files are displayed as refile targets when refiling a headings with C-c C-w (org-refile).

;; Set refile targets to all headings in the current buffer and all
;; headings in the agenda files.  If
;; `org-outline-path-complete-in-steps' is non-nil, you may want to
;; lower the ':maxlevel' setting to limit the amount of refile
;; targets.
(setq org-refile-targets '((nil :maxlevel . 9)
                           (org-agenda-files :maxlevel . 9)))

;; Allow refile as top level heading to other files
(setq org-refile-use-outline-path 'file)

;; Show all refile targets (at all depths) immediately
;; (setq org-outline-path-complete-in-steps nil)

;; Refile in steps, choosing the file first, then parent
;; headline and so on
(setq org-outline-path-complete-in-steps t)

;; Ability to create new parent node while refiling
(setq org-refile-allow-creating-parent-nodes 'confirm)


Where to create archive files for archived headings when using C-c $ (org-archive-subtree).

;; Archive subtrees in a subfolder called 'archive' in a file named
;; %s_archive where %s is the name of the file.
(setq org-archive-location "archive/%s_archive::")


Org-habit is a module included with Org mode which allows you to keep track of daily habits.

(add-to-list 'org-modules 'org-habit)
(require 'org-habit)


Persist clock between sessions

(setq org-clock-persist t)

All clock commands can be found by using C-h a org-clock RET.


When creating a code block (C-c C-, s), placing the cursor in it and pressing C-c C-c will execute the script using an executor. Add any languages here which have an executor you would like to use.

(org-babel-do-load-languages 'org-babel-load-languages
                             '((shell . t)))


M-x org-agenda will show you a menu of different task views. The two most important are a and t. a, agenda view, will show scheduled and deadlined tasks that are coming up soon or overdue. t will show all TODO entries and has instructions for limiting it to a particular TODO status.

The keymap for org-agenda-mode is very convenient and can be viewed with C-h m (describe-mode).

;; Don't warn about deadlines if item is already scheduled
(setq org-agenda-skip-deadline-prewarning-if-scheduled 'pre-scheduled)

;; Use current window to display agenda.
(setq org-agenda-window-setup 'current-window)

;; Don't rebuild agenda each time. Press 'g' to rebuild manually.
;; (setq org-agenda-sticky t)

;; Exclude DONE and CANCELLED items from agenda
(setq org-agenda-skip-deadline-if-done t
      org-agenda-skip-scheduled-if-done t)


Org crypt allows you to symmetrically encrypt headings on save using gpg. Any heading with a :crypt: tag will be encrypted on save, like this:

* Encrypted entry                                                     :crypt:


(require 'org-crypt)
(setq org-tags-exclude-from-inheritance '("crypt"))

;; Use symmetric encryption
(setq org-crypt-key nil)

You can decrypt headings with org-decrypt-entry, then entering the same passphrase used to encrypt it.


Capturing information into Org files is very simple, regardless where the information comes from. I've already written about my capture templates in the workflow article.


Org yaap

Org yaap (yet another alert package) is a package I wrote to send notifications for Org mode alerts. It works on desktop and Termux on Android.

(use-package org-yaap
  :straight (org-yaap :type git :host gitlab :repo "tygrdev/org-yaap")
  (org-yaap-mode 1))

Org real

Org real allows you to create links which point to real objects.

(use-package org-real)

Boxy headings

View an org file as a boxy diagram.

(use-package boxy-headings)

Org ssr

Org ssr (server-side renderer) automatically exports Org files in the requested format in the browser (html, pdf, txt, or org). You can start an Org ssr server in the current directory by using M-x org-ssr. To serve files recursively, use C-u M-x org-ssr.

The variable org-export-async-init-file should be set to an elisp file which loads the bare minimum config to export Org files correctly.

Download the latest release (org-ssr-x.y.z.el) then M-x package-install-file RET org-ssr-x.y.z.el RET


;; Access org-agenda from anywhere in emacs with C-c a
(global-set-key (kbd "C-c a") 'org-agenda)

;; Store a link to the current heading.  Uses the id property if it
;; exists, otherwise a relative location.  This can be used when
;; capturing a link.
(define-key org-mode-map (kbd "C-c l") #'org-store-link)

;; Store a link to a file in dired.
(require 'dired)
(define-key dired-mode-map (kbd "C-c l") #'org-store-link)

;; Set an id on the current heading if it does not exist
(define-key org-mode-map (kbd "C-c i") #'org-id-get-create)

;; Decrypt the entry at point
(define-key org-mode-map (kbd "C-c d") #'org-decrypt-entry)

;; View a generated image of all Org-real links in a buffer
(define-key org-mode-map (kbd "C-c r") #'org-real-world)

;; View the current Org file as a boxy diagram
(define-key org-mode-map (kbd ("C-c o") #'boxy-headings)

Speed commands

Speed commands allow you to navigate an Org file faster, without any modifier keys like control or meta.

Speed commands interfere with normal typing so they are only activated when the cursor is at or near the beginning of a heading.

(setq org-use-speed-commands
      (lambda ()
        (and (looking-at org-outline-regexp)
             (looking-back "^\\**"))))

In order to see all speed commands, type ? at the beginning of any heading.


That is the extent of my Org mode configuration. There's a lot to it, but I think it's worth it.