Variables and data flow
When a choice runs, QuickAdd keeps one scratchpad of named values for that run.
Prompts, scripts, and AI Assistant commands write values onto it; placeholders
like {{VALUE:project}} read them back. In a Macro, every step shares the same
scratchpad in order, so an answer you give in one step is available to every
step after it.
This page is about those run variables - the temporary values that exist only while a Template, Capture, or Macro run is executing. For saved, reusable snippets that persist across runs, see Global Variables instead. The exact placeholder grammar lives in Format Syntax; this page is about how values move between steps.
At a glance, here is what writes a run variable and what reads it back:
| Written by | Read by |
|---|---|
A prompt, such as {{VALUE:project}} or {{VDATE:due,YYYY-MM-DD}} | {{VALUE:project}} in a later field or step |
A user script (params.variables.slug = "...") | {{VALUE:slug}}, or params.variables.slug in another script |
| An AI Assistant command’s Output variable name | {{VALUE:output}} |
| A script, the CLI, or the API supplying a value up front | any placeholder that would otherwise prompt |
Write once, use everywhere
Section titled “Write once, use everywhere”Give a value a name when the same answer should appear in more than one place. QuickAdd asks for it once and reuses your answer everywhere the name appears:
File name format: Projects/{{VALUE:project}}Template body: # {{VALUE:project}}Capture format: Logged work for {{VALUE:project}}If project isn’t set yet, QuickAdd asks once and stores your answer under
project. Every later {{VALUE:project}} in the same run reads that stored
answer instead of asking again. This works across a Template file name, the
Template body, Capture formats, and later Macro steps.
If a script, the CLI, or the QuickAdd API supplies project before the
placeholder is formatted, the placeholder uses that value and never asks. A key
that is absent or set to undefined counts as missing; an empty string counts
as a deliberate empty answer.
When the prompt should be a picker, define the options once with a name, then reuse the name on its own:
{{VALUE:work,home,urgent|name:category}}{{VALUE:category}}See {{VALUE:<options>|name:<name>}} for
option lists, display labels, first-definition behavior, and reserved names.
The unnamed answer: {{VALUE}}
Section titled “The unnamed answer: {{VALUE}}”The unnamed {{VALUE}} reads a special variable called value. It’s meant for
one-off input, or for a trigger that already supplied some content:
{{VALUE}}This is not the same as {{VALUE:project}}. If an answer needs to survive
across several Macro steps, copy it into a named key and read that instead:
module.exports = async (params) => { if (params.variables.value !== undefined) { params.variables.project = params.variables.value; }};Later steps can then use:
{{VALUE:project}}Sharing values with a script
Section titled “Sharing values with a script”A user script in a Macro receives params.variables - the same scratchpad the
placeholders read from. Write to it, and later steps see your values:
module.exports = async (params) => { const title = await params.quickAddApi.inputPrompt("Title");
params.variables.title = title; params.variables.slug = title.toLowerCase().replace(/\s+/g, "-");};Later Macro steps can read them:
# {{VALUE:title}}Slug: {{VALUE:slug}}Two things trip people up here:
- A plain JavaScript variable isn’t enough. Only values written onto
params.variablesare visible to later steps. Aconst title = "Inbox"stays private to that one script;params.variables.title = titleis what makes it available. - Order matters. A script must run before the Template, Capture, or script step that reads its variables.
Inline scripts run first
Section titled “Inline scripts run first”Inline scripts run before the ordinary placeholders around them, so an inline script can’t read a value the surrounding output is still about to prompt for. This does not do what it looks like:
const value = "{{VALUE:project}}";While the inline script runs, that’s just literal text - the placeholder hasn’t been filled in yet. If the script needs input-aware logic, prompt inside the script, or read a variable an earlier step already set:
const project = this.variables.project;return project ? `Project: ${project}` : "";Reading an AI Assistant’s output
Section titled “Reading an AI Assistant’s output”An AI Assistant Macro command writes its response to the variable named in its
Output variable name setting. The default name is output, so later steps
can read:
{{VALUE:output}}or, in a script:
module.exports = async (params) => { console.log(params.variables.output);};QuickAdd also writes a quote-block version under <name>-quoted. With the
default output name that’s:
{{VALUE:output-quoted}}If you renamed the output variable to description, read {{VALUE:description}}
and {{VALUE:description-quoted}} instead. Both are available to later steps in
the same Macro run.
executeChoice is a trigger, not a function call
Section titled “executeChoice is a trigger, not a function call”The Macro Builder’s Choice command and the API method
quickAddApi.executeChoice look similar but behave differently.
A Choice command added inside a Macro runs as part of that Macro’s sequence and shares the Macro’s scratchpad with the steps after it.
quickAddApi.executeChoice(choiceName, variables) is a one-way trigger. It
passes the variables you give it into the target choice, waits for that choice
to finish, and resolves with undefined - it does not hand the target
choice’s output back to the caller. After the target finishes, QuickAdd clears
the temporary variables that execution used. So if you call it from a Macro
script, don’t expect your current params.variables to still be around
afterward unless you saved and restored them yourself.
Use it to trigger another choice with input:
module.exports = async (params) => { await params.quickAddApi.executeChoice("Create project note", { project: params.variables.project, });};Don’t expect a return value back from it:
module.exports = async (params) => { const result = await params.quickAddApi.executeChoice("Pick project"); params.variables.project = result; // result is undefined};When later steps need a value, keep the workflow inside one Macro sequence, set
params.variables directly, or call a shared JavaScript helper that returns the
value to your script.
Troubleshooting
Section titled “Troubleshooting”The same prompt appears more than once. Use the same named placeholder
everywhere, such as {{VALUE:project}}. A bare {{VALUE}} and a named
{{VALUE:project}} are different inputs.
A script value is missing in a later Template or Capture. Set it on
params.variables, not only in a local JavaScript variable, and make sure the
script step runs before the step that reads it.
A placeholder stayed as literal text. The syntax is {{VALUE:name}}. A bare
{{name}} is not a QuickAdd placeholder.
An AI result is missing. Check the AI Assistant command’s Output variable name, then read that exact variable in a later Macro step.
executeChoice returned undefined. That’s expected. Use executeChoice
to trigger another choice with input variables, not to fetch a return value from
it.