Skip to content

Template variables

Prompts, system prompts, subagent prompts, shell commands, approval messages, Run only if conditions and branch-name templates are all rendered with Jimothy’s small template engine. For a guided introduction see Templates; this page is the complete list.

{{ issue.title }} value lookup (dot path; spaces optional)
{{ issue.key | slug }} filter
{{ steps.test.output | truncate:4000 }} filter with an argument
{{ issue.priority | default:"none" | upper }} filters chain left to right
{{ "literal text" | upper }} quoted literal
{{#if steps.review.output}}…{{else}}…{{/if}} conditional (nestable, else optional)
  • Unknown paths render as an empty string. They never raise an error.
  • Strings render as-is; numbers and booleans as text; arrays of plain values as a comma-separated list (api, security); objects and arrays of objects as pretty-printed JSON.
  • {{else}} must be written exactly like that. {{#if}} blocks can be nested.
Place Notes
Agent step Prompt and System prompt
Subagent prompts Rendered with the same context before being passed to the harness.
Shell step Command Every interpolated value is shell-quoted automatically (see below).
Approval step Message shown to the approver Default Approve to continue.
Run only if (runIf) The step is skipped when the result is falsy (see Truthiness).
Workspace Branch name template Default jimothy/{{issue.key | slug}}. Rendered before any step runs, so only issue, run.number, run.id, pipeline, project and vars are useful here.
Harness Arguments / Model arguments / … A separate, smaller context. See Harness argument placeholders.

The issue that started the run. For manual runs, it’s built from the Start a run dialog; for schedule triggers, from the trigger’s title and description.

Variable Description
issue.key Human key: ENG-123 (Linear), WEB-45 (Jira), web-app#42 (GitHub), SCHED-202609280300 (schedule), the webhook key or HOOK-…, the manual Issue key or TASK-<n>
issue.title Title / summary
issue.description Body as plain text or Markdown (Jira Cloud’s ADF is converted)
issue.url Link to the issue, if any
issue.labels Labels, comma separated (api, security)
issue.priority Priority name (Linear priority label, Jira priority, webhook priority)
issue.status Current status (Linear state, Jira status, GitHub open)
issue.assignee Assignee name (GitHub: login)
issue.reporter Creator / reporter name (GitHub: author login)
issue.updatedAt Last-updated timestamp from the tracker
issue.source jira, linear, github, manual, webhook or schedule
issue.id Provider id (Linear UUID, Jira id, GitHub issue number, webhook key)
issue.raw.* Provider-specific extras (below)

issue.raw contents:

Source Fields
Linear raw.teamId, raw.teamKey
Jira raw.issueType
GitHub raw.number, raw.repo (owner/repo)
Schedule raw.firedAt (UTC, YYYY-MM-DD HH:MM)
Webhook the entire JSON body, e.g. raw.environment

If a run somehow has no issue, issue.key is RUN-<number> and issue.title is the pipeline name.

Variable Description
run.id Run id, e.g. run_0mfz2k1a9c3e5d7
run.number Run number (increments across all pipelines)
run.branch Git branch created for this run (empty until the workspace is ready)
run.workspace Absolute path of the run’s workspace
run.baseBranch The workspace’s Base branch (default main)
Variable Description
pipeline.id Pipeline id
pipeline.name Pipeline name
project.id Project id (empty if the pipeline has no project)
project.name Project name (empty if the pipeline has no project)

vars.<NAME> is a variable from, in increasing precedence:

  1. the project’s Commands, as vars.setupCommand, vars.startCommand, vars.testCommand, vars.buildCommand, vars.lintCommand (only the ones that are set);
  2. the project’s Variables;
  3. the pipeline’s Variables;
  4. per-run overrides from the Start a run dialog.

In shell steps, use | raw for commands stored in variables: {{vars.testCommand | raw}}. Otherwise the whole command is quoted as one word.

For every step in the pipeline, by step id:

Variable Description
steps.<id>.output The step’s output: the agent’s final answer, the shell step’s combined stdout+stderr, or the approval comment (with choices: the picked options’ text, then Approver notes: …). Capped at the last 20,000 characters. Empty if the step hasn’t run.
steps.<id>.status pending, running, awaiting_approval, succeeded, failed, skipped or cancelled
steps.<id>.error The step’s error message, if any
steps.<id>.approvedBy Approval steps: who decided
steps.<id>.comment Approval steps: the approver’s comment
steps.<id>.selected Approval steps with choices: the full Markdown of each picked option, separated by a blank line
steps.<id>.selectedIds Approval steps with choices: the picked option numbers, e.g. 1, 3
steps.<id>.selectedTitles Approval steps with choices: the picked option titles, separated by ;

Values are captured when a step starts. In a feedback loop, a re-run implement step sees the reviewer’s latest output in {{steps.review.output}}.

Variable Description
loop.iteration How many times this step has been re-entered through a feedback loop: 0 on the first pass, 1 on the first loop, …
Filter Argument Result
default text The argument if the value is missing or an empty string; otherwise the value. {{issue.priority | default:"none"}}
slug max length (default 48) Lowercase, accents removed, non-alphanumerics collapsed to -, trimmed. ENG-123 Fix login! → eng-123-fix-login
lower — Lowercase
upper — Uppercase
trim — Strip surrounding whitespace
first_line — Only the first line
truncate length (default 2000) First N characters, plus … if cut
json — JSON-encode the value ("a \"quoted\" string", arrays as JSON arrays)
shell — Shell-quote the value (single quotes on macOS/Linux)
raw — No change; in shell steps, disables automatic quoting for this value

Unknown filter names are ignored. Arguments may be quoted (default:"n/a") or bare (truncate:4000).

In a shell step’s Command, every {{…}} value is shell-quoted after filters run, so issue text can’t inject commands:

Terminal window
git commit -m {{issue.title}}
# renders as: git commit -m 'Fix "login" on Safari; rm -rf /'
  • Values are wrapped in single quotes ('it'\''s').
  • Don’t add your own quotes around a template value, or you’ll get nested quotes. Write echo {{issue.key}}, not echo "{{issue.key}}".
  • Add | raw as the last filter to insert a value unquoted: {{vars.testCommand | raw}}.
  • Environment variables are an alternative that needs no quoting: "$FACTORY_ISSUE_TITLE". See Environment variables.

Quoting applies only to shell step commands. Prompts, approval messages and conditions are rendered as plain text.

{{#if …}} and Run only if treat these as false: a missing value, an empty string, a string that is false, 0 or no (case-insensitive, ignoring surrounding whitespace), an empty array, false and 0. Everything else is true.

{{#if steps.review.output}}Reviewer feedback: {{steps.review.output}}{{else}}First pass.{{/if}}
{{#if issue.url}}Link: {{issue.url}}{{/if}}

Run only if examples: {{vars.deploy}} (run when the variable is set to something other than false/0/no), {{#if issue.labels}}yes{{/if}}.

Harness argument templates are rendered with a different context — only these values, plus filters:

Placeholder Value
{{prompt}} The rendered prompt
{{promptFile}} Path to a temporary file containing the prompt
{{model}} The step’s model (or the harness default)
{{systemPrompt}} The rendered system prompt
{{subagents}} Attached subagents as a JSON object keyed by name
{{cwd}} The run’s workspace
{{options}} Marker line where model / system prompt / subagent arguments are inserted

See Custom harnesses.

The prompt editor suggests: issue.key, issue.title, issue.description, issue.url, issue.labels, issue.priority, issue.source, run.id, run.number, run.branch, run.workspace, run.baseBranch, pipeline.name, project.name, loop.iteration, the pipeline’s and project’s vars.*, and steps.<id>.output for the other steps. Everything else on this page works too; it just isn’t suggested.