krz/orgstar

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

docs/manual/guide/08-capture.org

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

332 lines · 27757 bytes

  1#+TITLE: Capture
  2#+DESCRIPTION: Capture templates, the capture window, date trees, org-protocol, Shortcuts and the iOS share sheet.
  3#+LEDE: Capture files a note, task or link into the right place in your org files without leaving what you are doing.
  4
  5* Starting a capture
  6
  7Capture mirrors =org-capture=. Start it from anywhere in the app:
  8
  9| Preset | Key                                    |
 10|--------+----------------------------------------|
 11| Mac    | =⇧⌘N= (File ▸ Capture…)                |
 12| Emacs  | =C-c c= or =⇧⌘N=                       |
 13| Doom   | =SPC X= (normal state), =C-c c= or =⇧⌘N= |
 14
 15=⌃⌥Space= opens the capture window from any app, with Orgstar in the background. Turn it off in Settings ▸ Capture, or in =config.toml=:
 16
 17#+BEGIN_SRC toml
 18[orgstar]
 19global-capture-hotkey = false
 20#+END_SRC
 21
 22The shortcut is registered as a system hot key and needs no accessibility permission.
 23
 24Captures can also arrive from a browser through org-protocol, from Shortcuts, and on iOS from the share sheet; see the sections below.
 25
 26* The capture window
 27
 28A capture goes through up to three steps.
 29
 301. *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.
 312. *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.
 323. *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.
 33
 34Press Esc (Cancel) at any step to close the window without filing anything, as =org-capture-kill= does.
 35
 36Filing, 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.
 37
 38If 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.
 39
 40Limits compared with Emacs:
 41
 42- 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.
 43- 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.
 44- The target is not shown while you edit (the capture buffer in Emacs is narrowed to the new entry in the target file).
 45
 46* Capture templates
 47
 48Templates live in =capture.toml= in the configuration folder (=~/.config/orgstar/capture.toml= by default; see [[file:13-configuration.org][Configuration]]). Settings ▸ Capture shows its path. Each template is a =[[template]]= table:
 49
 50#+BEGIN_SRC toml
 51[[template]]
 52key = "t"
 53name = "Personal todo"
 54type = "entry"
 55file = "todo.org"
 56headline = "Inbox"
 57template = "* TODO %?\n%i\n%a"
 58prepend = false
 59#+END_SRC
 60
 61The 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:
 62
 63| Key | Name           | Target                      | Template              |
 64|-----+----------------+-----------------------------+-----------------------|
 65| =t= | Personal todo  | =todo.org=, heading =Inbox= | =* TODO %?\n%i\n%a=   |
 66| =n= | Personal notes | =notes.org=, heading =Inbox= | =* %u %?\n%i\n%a=   |
 67
 68A 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.
 69
 70Templates 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.
 71
 72** Keys
 73
 74| Key                  | Value             | Meaning                                                                                       | Org property            |
 75|----------------------+-------------------+-----------------------------------------------------------------------------------------------+-------------------------|
 76| =key=                | string, required  | What you press to choose the template                                                         | key                     |
 77| =name=               | string            | The name in the list; the key when omitted                                                    | description             |
 78| =type=               | string            | =entry= (the default), =item=, =checkitem=, =plain= or =table-line=                           | type                    |
 79| =template=           | string, required  | The text to fill; see [[*Template escapes][Template escapes]]                                 | template                |
 80| =file=               | string            | The target file; required except with =id= or =clock=                                         | target                  |
 81| =headline=           | string            | A heading in =file=                                                                           | =file+headline=         |
 82| =olp=                | string            | An outline path in =file=, titles separated by =/=                                            | =file+olp=              |
 83| =datetree=           | boolean           | Today's entry in a date tree in =file=, under =olp= if given                                  | =file+olp+datetree=     |
 84| =tree-type=          | string            | =day= (the default), =week= or =month=, for =datetree=                                        | =:tree-type=            |
 85| =id=                 | string            | The heading with this =ID= property, in any file                                              | =id=                    |
 86| =clock=              | boolean           | The entry the clock is running in                                                             | =clock=                 |
 87| =prepend=            | boolean           | Put the text first rather than last                                                           | =:prepend=              |
 88| =immediate-finish=   | boolean           | File without showing the editor                                                               | =:immediate-finish=     |
 89| =empty-lines=        | integer           | Blank lines before and after the captured text                                                | =:empty-lines=          |
 90| =empty-lines-before= | integer           | Blank lines before; overrides =empty-lines=                                                   | =:empty-lines-before=   |
 91| =empty-lines-after=  | integer           | Blank lines after; overrides =empty-lines=                                                    | =:empty-lines-after=    |
 92| =jump-to-captured=   | boolean           | Show the new entry in the editor after filing                                                 | =:jump-to-captured=     |
 93| =clock-in=           | boolean           | Clock in to the captured entry                                                                | =:clock-in=             |
 94| =clock-keep=         | boolean           | With =clock-in=, keep the clock running after filing                                          | =:clock-keep=           |
 95| =clock-resume=       | boolean           | With =clock-in=, restart the clock that was running before                                    | =:clock-resume=         |
 96| =table-line-pos=     | string            | Where a =table-line= goes, such as ="II-3"=                                                   | =:table-line-pos=       |
 97
 98=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=.
 99
100#+BEGIN_SRC toml
101[[template]]
102key = "m"
103name = "Meeting"
104file = "work.org"
105olp = "Meetings"
106template = "* %^{Topic} :meeting:\n%U\n- Attendees: %^{Attendees}\n- Topic again: %\\1\n%?"
107#+END_SRC
108
109** Targets
110
111The target keys are checked in this order: =id=, =clock=, =datetree=, =headline=, =olp=; with none of them the target is =file= itself.
112
113| Target                    | Where the text goes                                                                                             |
114|---------------------------+-----------------------------------------------------------------------------------------------------------------|
115| =file= alone              | The file's top level: an =entry= becomes a top-level heading at the end (or start, with =prepend=)              |
116| =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 |
117| =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= |
118| =datetree = true=         | Under today's heading in a date tree; see [[*Date trees][Date trees]]                                           |
119| =id = "…"=                | Under the heading with that =ID=, found through the workspace index. Fails with =Cannot find target ID= if no heading has it |
120| =clock = true=            | Under the heading the running clock is in. Fails with =No running clock= when no clock runs                    |
121
122=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.
123
124Emacs's =file+regexp=, =file+function= and =function= targets, and templates read from a file (=(file "…")=), are not supported.
125
126** Template types
127
128| Type         | What is inserted                                                                                                                                         |
129|--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------|
130| =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= |
131| =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 |
132| =checkitem=  | As =item=, with a =[ ]= checkbox added if there is none                                                                                                   |
133| =plain=      | The text as it is, at the end of the entry's body (with =prepend=, right after the heading line)                                                          |
134| =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 |
135
136For =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 [[file:10-tables.org][Tables]]).
137
138Placement 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.
139
140** Clocking while capturing
141
142With =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 [[file:06-dates-and-clocking.org][Dates, scheduling and clocking]].
143
144* Template escapes
145
146These follow =org-capture-fill-template=. Escapes that need no answer are filled first; prompts are then asked in order.
147
148** Inserted values
149
150| Escape     | Inserts                                                                                                         |
151|------------+-----------------------------------------------------------------------------------------------------------------|
152| =%?=       | Nothing; the cursor goes here                                                                                   |
153| =%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 |
154| =%a=       | A link to where capture started, =[[target][description]]=                                                      |
155| =%A=       | The same link, asking for its description                                                                       |
156| =%l=       | The link as =[[target]]=, without description                                                                   |
157| =%L=       | The link target alone                                                                                           |
158| =%c=, =%x= | The clipboard's text                                                                                            |
159| =%f=       | The name of the file capture started from                                                                       |
160| =%F=       | The full path of that file                                                                                      |
161| =%n=       | Your full name from macOS                                                                                       |
162| =%k=       | The title of the entry the clock is running in                                                                  |
163| =%K=       | A link to that entry                                                                                            |
164| =%t=       | Today's date as an active timestamp, =<2026-10-07 Wed>=                                                         |
165| =%T=       | Active timestamp with the current time                                                                          |
166| =%u=       | Inactive timestamp, =[2026-10-07 Wed]=                                                                          |
167| =%U=       | Inactive timestamp with the current time                                                                        |
168| =%<…>=     | The current time formatted with a =format-time-string= pattern, such as =%<%Y-%m-%d %H:%M>=                     |
169| =%:name=   | A link property; see below                                                                                      |
170
171From 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.
172
173=%<…>= 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.
174
175=%: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.
176
177** Prompts
178
179| Escape                         | Asks for                                                                                   |
180|--------------------------------+--------------------------------------------------------------------------------------------|
181| =%^{Prompt}=                   | A line of text                                                                             |
182| =%^g=                          | Tags, offering the tags used in the target file                                            |
183| =%^G=                          | Tags, offering every tag in your folders                                                   |
184| =%^t=, =%^T=                   | A date, inserted as an active timestamp; =%^T= always includes a time                      |
185| =%^u=, =%^U=                   | The same as an inactive timestamp                                                          |
186| =%^C=                          | Text, offering the initial text and the clipboard                                          |
187| =%^L=                          | As =%^C=, inserted as a link                                                               |
188| =%^{NAME}p=                    | A value for the property =NAME=, set in the entry's property drawer                        |
189
190=%^{Prompt|default|a|b}= asks for text with a default and suggested choices, separated by vertical bars.
191
192A 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 [[file:06-dates-and-clocking.org][Dates, scheduling and clocking]]); an empty answer is today, or now for =%^T= and =%^U=. A time in the answer makes =%^t= include it.
193
194After 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.
195
196** Escaping and unsupported escapes
197
198Put 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.
199
200=%(…)= 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.
201
202* Date trees
203
204With =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.
205
206| =tree-type= | Levels                                                    |
207|-------------+-----------------------------------------------------------|
208| =day=       | =* 2026=, =** 2026-10 October=, =*** 2026-10-07 Wednesday= |
209| =week=      | =* 2026=, =** 2026-W41=, =*** 2026-10-07 Wednesday= (ISO week and its year) |
210| =month=     | =* 2026=, =** 2026-10 October=                            |
211
212#+BEGIN_SRC toml
213[[template]]
214key = "j"
215name = "Journal"
216file = "journal.org"
217datetree = true
218template = "* %<%H:%M> %?\n%i"
219#+END_SRC
220
221With =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.
222
223* org-protocol
224
225Orgstar 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.
226
227** capture
228
229#+BEGIN_SRC text
230org-protocol://capture?template=w&url=https%3A%2F%2Fexample.com&title=Example&body=Selected%20text
231#+END_SRC
232
233This opens the capture window with:
234
235- =template= chosen. Without =template=, the template list shows. A key with no template reports =No capture template "w"=.
236- =%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).
237- =%i= and =%:initial= set to =body=.
238- =%:link= set to the URL, =%:description= to the title, and =%:type= to the URL's scheme.
239
240In the query form, =+= stands for a space, as in Org; encode a literal =+= as =%2B=.
241
242** store-link
243
244#+BEGIN_SRC text
245org-protocol://store-link?url=https%3A%2F%2Fexample.com&title=Example
246#+END_SRC
247
248This stores the link, so =C-c C-l= in the editor offers it (see [[file:09-links.org][Links]]), and puts the URL on the clipboard.
249
250Other handlers, such as =open-source=, report that Orgstar handles only capture and store-link. On iOS only =capture= links are handled.
251
252** Bookmarklets
253
254Bookmarklets written for Emacs's org-protocol work unchanged. Add a bookmark with one of these as its address:
255
256#+BEGIN_SRC js
257javascript:location.href='org-protocol://capture?template=w&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)+'&body='+encodeURIComponent(window.getSelection())
258#+END_SRC
259
260#+BEGIN_SRC js
261javascript:location.href='org-protocol://store-link?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)
262#+END_SRC
263
264A matching web capture template:
265
266#+BEGIN_SRC toml
267[[template]]
268key = "w"
269name = "Web page"
270file = "inbox.org"
271headline = "Web"
272template = "* %:description\n:PROPERTIES:\n:URL: %:link\n:END:\n%U\n%i\n%?"
273#+END_SRC
274
275* Shortcuts
276
277The Shortcuts action Capture to Orgstar files text with a template, without the capture window. It has two parameters:
278
279| Parameter    | Meaning                                                                 |
280|--------------+-------------------------------------------------------------------------|
281| Text         | The text, inserted as =%i=                                              |
282| Template Key | A template's =key= in =capture.toml=; the first template when empty     |
283
284Every 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.
285
286On the Mac, the action opens Orgstar if it isn't running and waits up to five seconds for it to be ready.
287
288* Capture on iOS
289
290The Capture button (a square with a pencil) at the top of the Agenda and Folders tabs opens the capture sheet. The templates come from the =capture.toml= in your synced configuration folder (see [[file:14-ios.org][iOS]]).
291
292The sheet works as on the Mac, in a form:
293
294- The Template picker chooses the template; it starts on the first one.
295- Prompts appear as fields. Date prompts have a date picker; choices and tags appear as buttons, and tapping a tag adds it.
296- Continue fills the template and shows the text to edit; File files it; Cancel discards it.
297
298Differences 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.
299
300** The share sheet
301
302In another app, share a web page or text and choose Orgstar. The share form has:
303
304- a Template picker, with the templates the app read the last time it ran;
305- for a link, its title (editable) and address;
306- a Text field, filled with shared text.
307
308Capture 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.
309
310The share form lists no templates until Orgstar has run once with your configuration folder; the capture sheet then starts on the first template.
311
312* Importing templates from Emacs
313
314Import from Emacs (see [[file:13-configuration.org][Configuration]] and [[file:15-alongside-emacs.org][Alongside Emacs]]) reads =org-capture-templates= and appends a =[[template]]= table to =capture.toml= for each template whose key isn't there already.
315
316| Emacs                                        | Imported as                              |
317|----------------------------------------------+------------------------------------------|
318| types =entry=, =item=, =checkitem=, =plain=, =table-line= | =type=                      |
319| =(file "f")=                                 | =file=                                   |
320| =(file+headline "f" "H")=                    | =file=, =headline=                       |
321| =(file+olp "f" "A" "B")=                     | =file=, =olp = "A/B"=                    |
322| =(file+olp+datetree "f" …)=                  | =file=, =datetree=, =olp= if a path is given |
323| =(file+datetree "f")=                        | =file=, =datetree=                       |
324| =(file+weektree "f")=                        | =file=, =datetree=, =tree-type = "week"= |
325| =(id "…")=                                   | =id=                                     |
326| =(clock)=                                    | =clock=                                  |
327| =:prepend=, =:immediate-finish=, =:jump-to-captured=, =:clock-in=, =:clock-keep=, =:clock-resume= | the boolean of the same name |
328| =:empty-lines=, =:empty-lines-before=, =:empty-lines-after=, =:table-line-pos=, =:tree-type= | the key of the same name |
329
330A 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.
331
332Emacs 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.