Note: Before I dive into the how, I want to tell you a story about why I needed checklists, and how, for a long time, I wasn’t aware that org-mode capture templates can be called from individual files, complete with their headers, tags, checklists… everything. You might find this useful if you’re starting out with Emacs, or if you are a veteran Emacs user who wants to understand some of the hurdles non-programmer Emacs “newbs” might go through.

If you want to jump ahead to the good stuff, it’s under the “How this works” header below.

First, I want to answer why use a whole file as an org-mode capture template. To understand that, I need to explain some of the work I do as a help desk person in a large organization.

Among other things, my work includes prepping desktop and laptop computers. For the most part, this is done from an image, and all software not included is installed remotely via our SMA. However, there are still many cases where the automation fails or does not apply and hands-on deployment is needed. Some scenarios include:

  • BYOD devices, which need to be evaluated and prepared for our environment.
  • MacBooks, which we can’t automate yet.
  • Replacements of existing computers, which should also come with a snort checklist, reminding me to change the inventory, and re-add the hostname to AD down the line, because it is taken (by the existing computer) when I start the process.

These scenarios are complex but similar in one area: they beg me to use checklists. We’re a big company, and often I find that a good checklist is half the job.

Communication with clients, managers, purchasing staff, as well as documenting everything, is also a part of the checklist. The difference between a job that was done with a checklist and one that was done without is so obvious that my checklists have been adopted throughout the team, and I was asked several times to guide others (especially newcomers) because of my “methods”. I find this humorous because if you know me, you’d know I’ve always been far from organized. It’s all org-mode, to which I’m very thankful (note from future me, about six years later: I owe this organization my promotions at work. Little did I know back then that these checklists would go so far!).

As you can imagine, these checklists get quite long and complex, containing parent items and their children.

In the past, I’ve had a long checklist “template” in a header in the setups.org file, which I used to copy-paste into new projects. The idea of using a file as a template for org-mode capture occurred to me in the past, but because I’ve never seen an example in the wild and didn’t find a clear reference to it in the manual, I dismissed it as wishful thinking.

When I asked about using org files as templates on Reddit I didn’t get answers. I believe that’s because I didn’t understand exactly what to ask, since I didn’t know what I was looking for. After all, if I had a more concrete idea, I’d probably read this in the Org manual for what it was:

template

The template for creating the capture item. If you leave this empty, an appropriate default template will be used. Otherwise this is a string with escape codes, which will be replaced depending on time and context of the capture call. The string with escapes may be loaded from a template file, using the special syntax ‘(file “template filename”)’. See below for more details.

This little paragraph of text can be found about half a page down in the manual. I read the capture part of the manual probably 20 times or more at this point, and I still feel I wouldn’t know I can use a file as a template just from reading it. But why?

There’s no clear statement that says you can load a capture from a file; rather, it says “the string with escapes may be loaded from a file…”. To me, this meant I could include my template’s syntax in a separate file instead of specifying it in my init file. I had the following template:

      ("j" "Journal" entry (file+datetree "~/Documents/Work/Setups.org")
    "**** %<%H:%M> about %a \n%?" :tree-type week)

** And I thought this bit of lisp could go into a file. OK, but what’s the point of that?

So, if for some reason I wouldn’t want the above code in my init file, I could copy-paste it into a dedicated file. This didn’t seem useful for me, after all, I wanted all my code in one place where I can break it down with explanations in org-mode, so I didn’t bother with it.

Further, the manual says “see below for more details,” and there aren’t any. There are only details about what is referred to as “string with escapes.” Nothing really tells me I can have my whole template, a huge checklist with headers and tags, in another file.

So I just struggled for a while, trying to figure out how to fit my a checklist in a single string, as shown above, such as [ ] checklist item one /n [ ] checklist item two /n and so forth, which of course didn’t work well (how would I tell org-capture to indent items so create children items under a parent item this way?)

At some point, I saw an example of someone using a checklist that was inside a different file. stumbled me: for the first time, I realized what I should look for. I managed to find a couple of questions related to org-mode in emacs.stackexchange.com that were not directly related to my issue, but had the following lines in the code (I cut out the paths as they do not matter here)

("j" "Journal" entry (file+datetree "...")
(file "..."))

And then, I found a presentation by Jonathan E. Magen. Of particular interest was slide 6. Right there, in front of me, the title was “Template stored in file,” and below it, a very simple example of org-capture lips that tells org-mode to read the template’s content from a file. It was as it is in the manual, but this time, the slide was very specific, telling me “this is how you tell org mode to go to a file and grab the capture template from there.” Someone finally pointed a finger at it for me. So, this was true. Org-mode can read templates from other org files.

I wrote the code as I understood it from the examples I found and added (file "~/Documents/Personal/journal-tmpl.org") to the code above instead of that “string with escapes”, and got an error: org-capture: Capture template ‘j’: Template is not a valid Org entry or tree.

I saw this error in the past. I got this far before. Now, through the eyes of someone who knows this should work, this error looked different. Org-mode, I knew, (or Emacs for that matter) should open any file if I tell it to, even if an MP4 or a JPEG file. I would see gibberish on my screen, yes, but it would open. That made me realize that if I see this error, it means the capture template should work, and what I wrote does indeed tell it to open the template from a file, but something in the template file was specifically wrong.

Suddenly, this error became an encouragement that I am headed in the right direction. The error was now telling me, “Hey, I want to do this for you, but your file is messed up, sorry.” Knowing this, I turned back to the community, this time asking the right question: What is wrong with my org file?

How this works

As it turns out, my regular org file started with certain options like #+TITLE: and #+TODO: with several headers already nested inside of it: org-mode capture was looking for the capture syntax, and instead found options it didn’t know what to do with. If I simplified the file and removed all the additional options, it worked.

Here’s a complete example of one of my org-mode capture template files (for example, mac-checklist.org). Notice how the very first thing is the header itself. It must be the first thing in org-capture syntax. Then the second line specifies what the template does, just like it did in my init. Finally, the checklist itself:

    * Setup Proccess [0%] 
    %^{Ticket}p %^{ID}p %^{Computer}p
    - [ ] Rename (SLS-ID-MAC)
    - [ ] Check OS Updates
    - [ ] Encryption
    - [ ] A/V
      - [ ] Install
      - [ ] Manage (overwrite XML file)
    - [ ] SMA
    - [ ] Restart 
    - [ ] WiFi
    - [ ] VPN 
    - [ ] Another App
      - [ ] Install
      - [ ] Test
      - [ ] Test w/ VPN
    - [ ] Asset Registration

The header has a percentage that changes as I fill in the checklist items. This allows me to see how close I am to being done straight from the agenda view. The second line tells org-capture to prompt me for properties for the ticket number, ID number of the person, and the computer name. Then I have a blank list ahead of me, which I can fill up according to whatever is already done.

This particular list is summoned by a very similar line to the one I have above regarding my journal. I just have a different file specified (say mac-checklist.org instead of journal-tmpl.org).

I am now working with four checklists, which I’m tweaking to perfection, summoned directly from org-capture.

Because I was encouraged to work with different checklists from one menu (org-capture), it meant I needed to look for a way to have “submenus” inside org-capture. In other words, if I want to capture a checklist, I should choose something like c in org-mode capture, and it would then take me to another menu asking me which of the four checklists I have to use.

Once again, I learned this is possible, and I went down a different rabit whole understanding org-mode capture menus to the point of re-inventing my workflow. This is too much to include in one post, so I hope to specify on that soon (note from the future: I did). For now, the big lesson I learned is this:

If you think something is possible, it probably is. One way or another, it is. And for those of you who used org-mode for years, especially from a programming background, I hope this post serves to show that some of us struggle not with the code, but with a lack of good, clear examples. We need a story, a scenario, a reason to explore. (another note from the future, after using Emacs for almost 8 years: this is probably our job - the bloggers. To tell a story and not just explain how we do something, but why.)