krz/orgstar

A native macOS editor for org-mode files. editor org-mode swift

docs/manual/guide/08-capture.org

b98a6509c5ae75e5172dd333d1b6105fd6ceee0e
orgstar/docs/manual/guide/08-capture.org rendered · source · history · blame · raw

349 lines · 29017 bytes

21 symbols in this file

Capture

Starting a capture

Capture mirrors org-capture. Start it from anywhere in the app:

Preset Key
Mac ⇧⌘N (File ▸ Capture…)
Emacs C-c c or ⇧⌘N
Doom SPC X (normal state), C-c c or ⇧⌘N

⌃⌥Space opens the capture window from any app, with Orgstar in the background. Turn it off in Settings ▸ Capture, or in config.toml:

[orgstar]
global-capture-hotkey = false

The shortcut is registered as a system hot key and needs no accessibility permission.

Captures can also arrive from a browser through org-protocol, from Shortcuts, and on iOS from the share sheet; see the sections below.

The capture window

A capture goes through up to three steps.

  1. Choose a template. The window lists your templates with their keys and targets. Type a template's key, or click it. For a key of several characters, such as wb, each character you type narrows the list to the templates whose keys start with what you typed, and the header shows the keys so far (Capture: w). Delete removes the last key typed. The template is chosen as soon as the keys match one.
  2. Answer its questions. If the template has prompts (%^{…}, %^g, %^t and the others below), they appear as a form. Leave a field empty for its default. Press Return (Continue) to go on.
  3. Edit and file. The filled template appears in an editor, headed with the template's name and target, with the cursor where %? was. Press ⌘Return (File It) to file it.

Press Esc (Cancel) at any step to close the window without filing anything, as org-capture-kill does.

Filing, the equivalent of org-capture-finalize, places the text in its target and saves it through the open buffer if the file is open, or into the file otherwise. A target file that doesn't exist is created, with its folders. The status line in the main window then says where the entry went.

If filing fails, for example because a heading on an olp path is missing, the window stays open with your text and shows the error in red below it, so you can try again after fixing the file or cancel.

Limits compared with Emacs:

  • The editor is a plain text editor. Org editing commands and keys such as C-c C-c and C-c C-k don't work in it; use ⌘Return and Esc.
  • There is no refile from the capture window (C-c C-w in an Emacs capture buffer). Capture to an inbox heading and refile from the agenda or the editor.
  • The target is not shown while you edit (the capture buffer in Emacs is narrowed to the new entry in the target file).

Capturing onto an agenda day

The + at the right of a day's header in the agenda, or k in the Mac agenda (org-agenda-capture), starts a capture for that day; see The agenda. Choose a template as usual. The day then stands in for today, as org-overriding-default-time makes it do in Org:

  • %t, %T, %u and %U give that day. The escapes with a time use the current time of day.
  • An empty answer to a date prompt (%^t and the others) is that day.
  • With datetree = true, the entry goes under that day in the date tree.

When the filled template is a heading without an active timestamp, Orgstar adds SCHEDULED: with that day on the line after the heading, or at the end of the planning line when the template has one:

* TODO Call the bank
SCHEDULED: <2026-10-09 Fri>

The line is part of the text you edit, so you can change or remove it before filing. A template with an active timestamp of its own, such as %t or %^t, gets no SCHEDULED line. On the Mac, the window's header names the day, as Capture, scheduled Fri 9 Oct.

Capture templates

Templates live in capture.toml in the configuration folder (~/.config/orgstar/capture.toml by default; see Configuration). Settings ▸ Capture shows its path. Each template is a [[template]] table:

[[template]]
key = "t"
name = "Personal todo"
type = "entry"
file = "todo.org"
headline = "Inbox"
template = "* TODO %?\n%i\n%a"
prepend = false

The file is read each time the capture window opens. If it doesn't exist, or none of its templates is valid, these two built-in templates are used:

Key Name Target Template
t Personal todo todo.org, heading Inbox * TODO %?\n%i\n%a
n Personal notes notes.org, heading Inbox * %u %?\n%i\n%a

A problem in the file, such as a table without a key, shows in red at the bottom of the window; the other templates still load.

Templates are a flat list. Keys of several characters are typed one character at a time, as in Emacs, but Emacs's template groups (an entry with only a key and a description) have no equivalent: the list shows every template whose key starts with what you typed.

Keys

Key Value Meaning Org property
key string, required What you press to choose the template key
name string The name in the list; the key when omitted description
type string entry (the default), item, checkitem, plain or table-line type
template string, required The text to fill; see Template escapes template
file string The target file; required except with id or clock target
headline string A heading in file file+headline
olp string An outline path in file, titles separated by / file+olp
datetree boolean Today's entry in a date tree in file, under olp if given file+olp+datetree
tree-type string day (the default), week or month, for datetree :tree-type
id string The heading with this ID property, in any file id
clock boolean The entry the clock is running in clock
prepend boolean Put the text first rather than last :prepend
immediate-finish boolean File without showing the editor :immediate-finish
empty-lines integer Blank lines before and after the captured text :empty-lines
empty-lines-before integer Blank lines before; overrides empty-lines :empty-lines-before
empty-lines-after integer Blank lines after; overrides empty-lines :empty-lines-after
jump-to-captured boolean Show the new entry in the editor after filing :jump-to-captured
clock-in boolean Clock in to the captured entry :clock-in
clock-keep boolean With clock-in, keep the clock running after filing :clock-keep
clock-resume boolean With clock-in, restart the clock that was running before :clock-resume
table-line-pos string Where a table-line goes, such as "II-3" :table-line-pos

capture.toml uses a subset of TOML: basic strings in double quotes, literal strings in single quotes, booleans and integers. Multi-line strings ("""…""") are not supported, so write a newline in a template as \n inside a double-quoted string. A double-quoted string accepts only the escapes \", \\, \n, \t, \uXXXX and \UXXXXXXXX; any other backslash is an error. A template backslash, as in %\1 or \%, is therefore written %\\1 or \\% in double quotes, or as it is in a single-quoted string, which has no escapes and no \n.

[[template]]
key = "m"
name = "Meeting"
file = "work.org"
olp = "Meetings"
template = "* %^{Topic} :meeting:\n%U\n- Attendees: %^{Attendees}\n- Topic again: %\\1\n%?"

Targets

The target keys are checked in this order: id, clock, datetree, headline, olp; with none of them the target is file itself.

Target Where the text goes
file alone The file's top level: an entry becomes a top-level heading at the end (or start, with prepend)
headline = "Inbox" Under the first heading with that exact title, at any level. If there is none, * Inbox is added at the end of the file
olp = "Projects/Work" Under Work, a child of Projects. Every heading on the path must exist; otherwise filing fails with Heading not found on outline path
datetree = true Under today's heading in a date tree; see Date trees
id = "…" Under the heading with that ID, found through the workspace index. Fails with Cannot find target ID if no heading has it
clock = true Under the heading the running clock is in. Fails with No running clock when no clock runs

file may be absolute (/Users/me/org/todo.org), start with ~/, or be relative. A relative path is relative to the first folder in the sidebar (your home folder if you have none). Heading titles match the title text without its TODO keyword, priority or tags. Because olp uses / as its separator, a heading whose title contains / can't be on an outline path; use headline or id for it.

Emacs's file+regexp, file+function and function targets, and templates read from a file ((file "…")), are not supported.

Template types

Type What is inserted
entry An Org entry. If the text has no heading, * = is added. Its level is adjusted to be one below the target heading, or 1 at the top level. Placed as the last child (first with =prepend). Text whose first heading isn't its highest is refused: Template is not a valid Org entry or tree
item A list item. A =- = bullet is added if the text has none. Goes after the last item of the first list in the target entry (or the file), with that list's indentation; if there is no list, at the end of the entry's text
checkitem As item, with a [ ] checkbox added if there is none
plain The text as it is, at the end of the entry's body (with prepend, right after the heading line)
table-line A table row, in the first table in the target entry (or the file); a new table is made if there is none

For table-line, a text that doesn't start with a vertical bar gets one. The row goes at the end of the table. With prepend it goes before the first data row after the first rule. With table-line-pos, II-3 means three lines above the second horizontal rule and I+1 the first line below the first rule; an impossible position fails with Invalid table line specification. After the row is placed, the table is aligned and its formulas recomputed; a table whose formulas need Emacs makes the capture fail with a message that says so (see Tables).

Placement follows org-capture-place-entry and its siblings, including how blank lines are kept: without empty-lines options, a new heading gets a blank line before it when its neighbors have one (org-blank-before-new-entry (heading . auto)). Within an existing list, at most one blank line goes between items.

Clocking while capturing

With clock-in = true, the captured entry gets a clock entry from when the template was filled to when you filed it, as Emacs clocks in while the capture buffer is open and out on finalize. With clock-keep = true as well, the clock keeps running in the new entry. With clock-resume = true, the clock that was running before the capture starts again after filing. With no clock running, clocking in to the entry first asks about open clocks, as Clock In does, as of when the capture began; on the Mac the questions are in the main window's echo area. See Dates, scheduling and clocking.

Template escapes

These follow org-capture-fill-template. Escapes that need no answer are filled first; prompts are then asked in order.

Inserted values

Escape Inserts
%? Nothing; the cursor goes here
%i The initial text: the selection in the editor, or the body from org-protocol, Shortcuts or the share sheet. Later lines get the indentation of the line %i is on
%a A link to where capture started, [[target][description]]
%A The same link, asking for its description
%l The link as [[target]], without description
%L The link target alone
%c, %x The clipboard's text
%f The name of the file capture started from
%F The full path of that file
%n Your full name from macOS
%k The title of the entry the clock is running in
%K A link to that entry
%t Today's date as an active timestamp, <2026-10-07 Wed>
%T Active timestamp with the current time
%u Inactive timestamp, [2026-10-07 Wed]
%U Inactive timestamp with the current time
%<…> The current time formatted with a format-time-string pattern, such as %<%Y-%m-%d %H:%M>
%:name A link property; see below

From the Mac capture window, %a links to the heading at the cursor in the open file, as [[file:~/org/work.org::*Heading][Heading]], or to the file itself before the first heading. It is empty with no file open.

%<…> understands %Y, %m, %d, %e, %H, %M, %S, %a, %A, %b, %B, %F, %R and %%, with English day and month names. Other format-time-string codes are left in the text as they are.

%:name inserts a property of the link being captured. From org-protocol these are %:link, %:description (the page title), %:type (the link's scheme, such as https), %:annotation (the same as %a) and %:initial (the same as %i). Without org-protocol, %:annotation and %:initial still work and other names insert nothing.

Prompts

Escape Asks for
%^{Prompt} A line of text
%^g Tags, offering the tags used in the target file
%^G Tags, offering every tag in your folders
%^t, %^T A date, inserted as an active timestamp; %^T always includes a time
%^u, %^U The same as an inactive timestamp
%^C Text, offering the initial text and the clipboard
%^L As %^C, inserted as a link
%^{NAME}p A value for the property NAME, set in the entry's property drawer

%^{Prompt|default|a|b} asks for text with a default and suggested choices, separated by vertical bars.

A name in braces before any of the keyed forms becomes its prompt: %^{Start}T, %^{Context}g. Leave a text answer empty for the default. Tags are typed separated by colons (work:urgent); on a heading line they are aligned to org-tags-column. A date takes the same input as the editor's date prompt, such as +2d, fri or fri 14:00 (see Dates, scheduling and clocking); an empty answer is today, or now for %^T and %^U. A time in the answer makes %^t include it.

After the prompts are answered, %\1, %\2 and so on insert the answer to the first, second, … text prompt (%^{…} only), and %\*1, %\*2 the answer to the first, second, … prompt of any kind.

Escaping and unsupported escapes

Put a backslash before % to keep it literally: \%t inserts %t (in a double-quoted TOML string, write \\%t). Two backslashes insert one backslash followed by the escape's value.

%(…) runs Emacs Lisp in Org and is not supported; a template that contains it fails with a message saying so. %[file] (insert a file's contents) is not supported either. Any other % sequence is left as it is.

Date trees

With datetree = true, the entry goes under today's date in a tree of headings, as org-datetree-find-create-entry builds it. Missing levels are created in date order among their siblings.

tree-type Levels
day * 2026, ** 2026-10 October, *** 2026-10-07 Wednesday
week * 2026, ** 2026-W41, *** 2026-10-07 Wednesday (ISO week and its year)
month * 2026, ** 2026-10 October
[[template]]
key = "j"
name = "Journal"
file = "journal.org"
datetree = true
template = "* %<%H:%M> %?\n%i"

With olp, the tree goes under that outline path, one level down, instead of at the top of the file. The date is the day you file the capture. There is no :time-prompt to choose another day.

org-protocol

Orgstar registers the org-protocol: URL scheme and handles the two handlers browser bookmarklets use, as org-protocol.el does in Org 9.8.7. Both the ?key=value form and the older :/a/b/c form work.

capture

org-protocol://capture?template=w&url=https%3A%2F%2Fexample.com&title=Example&body=Selected%20text

This opens the capture window with:

  • template chosen. Without template, the template list shows. A key with no template reports No capture template "w".
  • %a and %:annotation set to [[url][title]] (the URL as its own description when the title is blank; the title alone when there is no URL).
  • %i and %:initial set to body.
  • %:link set to the URL, %:description to the title, and %:type to the URL's scheme.

In the query form, + stands for a space, as in Org; encode a literal + as %2B.

store-link

org-protocol://store-link?url=https%3A%2F%2Fexample.com&title=Example

This stores the link, so C-c C-l in the editor offers it (see Links), and puts the URL on the clipboard.

Other handlers, such as open-source, report that Orgstar handles only capture and store-link.

Bookmarklets

Bookmarklets written for Emacs's org-protocol work unchanged. Add a bookmark with one of these as its address:

javascript:location.href='org-protocol://capture?template=w&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)+'&body='+encodeURIComponent(window.getSelection())
javascript:location.href='org-protocol://store-link?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)

A matching web capture template:

[[template]]
key = "w"
name = "Web page"
file = "inbox.org"
headline = "Web"
template = "* %:description\n:PROPERTIES:\n:URL: %:link\n:END:\n%U\n%i\n%?"

Shortcuts

The Shortcuts action Capture to Orgstar files text with a template, without the capture window. It has two parameters:

Parameter Meaning
Text The text, inserted as %i
Template Key A template's key in capture.toml; the first template when empty

Every prompt in the template takes its default (an empty answer: today for dates, no tags), and %? is ignored. %a is empty. On the Mac, %c is the clipboard and %n your name; on iOS both are empty, because reading the pasteboard would ask for permission on every run. The action returns a message, Captured to … with the target on the Mac and Captured with … with the template name on iOS, or fails with the same messages as the capture window. You can also say "Capture to Orgstar" to Siri.

On the Mac, the action opens Orgstar if it isn't running and waits up to five seconds for it to be ready.

Capture on iOS

The Capture button (a square with a pencil) at the top of the Agenda and Folders tabs opens the capture sheet. The + on a day's header in the Agenda tab opens it for that day, as described in Capturing onto an agenda day; date prompts then show that day as their default. The templates come from the capture.toml in your synced configuration folder (see iOS).

The sheet works as on the Mac, in a form:

  • The Template picker chooses the template; it starts on the first one.
  • Prompts appear as fields. Date prompts have a date picker; choices and tags appear as buttons, and tapping a tag adds it.
  • Continue fills the template and shows the text to edit; File files it; Cancel discards it.

Differences from the Mac: there is no selection, clipboard, current file, user name or clock link to insert, so %i and %a are empty unless the capture came from a link or the share sheet, and %c, %x, %f, %F, %n, %k and %K are empty. An org-protocol link naming a template key that doesn't exist opens the sheet on the first template and shows No capture template "x" with the key.

The share sheet

In another app, share a web page or text and choose Orgstar. The share form has:

  • a Template picker, with the templates the app read the last time it ran;
  • for a link, its title (editable) and address;
  • a Text field, filled with shared text.

Capture saves the item in the app group's capture inbox. The next time you open Orgstar, it opens the capture sheet with the item as an org-protocol capture: the link becomes %a and %:link, the title %:description, and the text %i. Several waiting items open one after another, oldest first. If the extension says Orgstar's shared folder isn't available, the app group is missing from the build and nothing can be saved.

The share form lists no templates until Orgstar has run once with your configuration folder; the capture sheet then starts on the first template.

Importing templates from Emacs

Import from Emacs (see Configuration and Alongside Emacs) reads org-capture-templates and appends a [[template]] table to capture.toml for each template whose key isn't there already.

Emacs Imported as
types entry, item, checkitem, plain, table-line type
(file "f") file
(file+headline "f" "H") file, headline
(file+olp "f" "A" "B") file, olp = "A/B"
(file+olp+datetree "f" …) file, datetree, olp if a path is given
(file+datetree "f") file, datetree
(file+weektree "f") file, datetree, tree-type = "week"
(id "…") id
(clock) clock
:prepend, :immediate-finish, :jump-to-captured, :clock-in, :clock-keep, :clock-resume the boolean of the same name
:empty-lines, :empty-lines-before, :empty-lines-after, :table-line-pos, :tree-type the key of the same name

A file name given as a variable or a simple form is evaluated where the importer can. The import report lists what it left out: other targets, templates that aren't strings, unknown :tree-type values, and other properties such as :time-prompt, :kill-buffer or :unnarrowed. Template groups are skipped.

Emacs resolves relative target files against org-directory; Orgstar resolves them against the first folder in the sidebar. If org-directory isn't your first folder, edit the imported file values or make them absolute.