Explanation
Template runtime contract
The `linkar_template.yaml` contract, `run.command` versus `run.sh`, and what render and run do.
Linkar templates are small runtime contracts, not mini workflow languages.
The canonical template file is linkar_template.yaml. Linkar still accepts template.yaml for
backward compatibility, but new templates should use the canonical name.
Template shape
The smallest useful template is usually:
id: simple_echo
version: 0.1.0
description: Write one greeting file.
params:
name:
type: str
required: true
outputs:
greeting_file:
path: greeting.txt
run:
mode: direct
command: >-
printf 'hello %s\n' "${param:name}" > "${LINKAR_RESULTS_DIR}/greeting.txt"
Top-level fields:
idversiondescriptionparamsoutputstoolsrun
Parameter types
Linkar supports:
strintfloatboolpathlist[path]
Use explicit defaults in the schema whenever possible. That keeps wrapper logic small and makes the CLI help clearer.
Declared outputs
Outputs are how Linkar records what a template produced.
Common patterns:
outputs:
results_dir: {}
report_html:
path: reports/report.html
fastq_files:
glob: output/**/*.fastq.gz
Rules:
results_dir: {}means the wholeresults/directorypathis resolved relative toresults/globis also resolved relative toresults/- only existing outputs are recorded
Tool requirements
Templates can declare external commands that must exist before execution:
tools:
required:
- pixi
required_any:
- [bcl-convert, bcl_convert]
This is a preflight check. It is not an environment manager.
run.command versus run.sh
Use run.command for a thin wrapper around one real command.
Use run.sh only when the template needs real local logic:
- branching
- temp files
- generated configs
- multi-step local orchestration
- traps and cleanup
run.py is also a good option once shell stops being clearer.
Explicit parameter placeholders
The preferred form in run.command is:
"${param:bcl_dir}"
"${param:samplesheet}"
${param:run_name:+--run-name "${param:run_name}"}
This is clearer than relying on the older implicit shell convention where bcl_dir became
BCL_DIR.
Linkar still supports the older form because existing templates use it, but new templates should
prefer ${param:...}.
What linkar render does
linkar render ... stages a standalone runnable artifact and stops there.
Bare template names such as export or nfcore_methylseq resolve through configured packs first.
If you want to execute a template from the current filesystem path explicitly, pass ./template_dir
or an absolute path instead of a bare name.
Render behavior:
- writes one final
run.sh - for
run.entry: run.sh, renders that script in place as the runnable artifact - resolves parameters into the rendered script
- localizes bound file parameters into the rendered directory when needed
- writes metadata under
.linkar/ - does not execute the template
- when inside a project, records the rendered bundle in
project.yamlwithstate: rendered
In a project, render defaults to the visible project path such as ./demultiplex, not to
.linkar/runs/....
What linkar run does
linkar run ... always executes.
Run behavior:
- for
run.mode: direct, stages the run under.linkar/runs/<instance_id>/ - for
run.mode: renderinside a project, executes directly in the visible project directory such as./export - executes the template
- collects declared outputs
- writes
.linkar/meta.jsonand.linkar/runtime.json - appends a run record to
project.yamlwithstate: completedorstate: failed - updates the stable project alias such as
./fastqcwhen a separate history run directory exists
For render-mode templates in a project:
linkar render TEMPLATErefreshes the visible bundlelinkar run TEMPLATEruns the current visible bundle if it already existslinkar run TEMPLATE --refreshrerenders first, then runs- if no visible bundle exists yet,
linkar run TEMPLATEmaterializes it once and then executes it
That split is intentional:
rendercreates a handoff artifact and records that current draft asrenderedruncreates immutable executed history for direct-run templates and records execution state for both direct and render-mode templates
Manual execution after render
If you manually execute a rendered run.sh, Linkar is not involved in the execution itself.
You can collect outputs afterward with:
linkar collect /path/to/rendered_dir
That updates .linkar/meta.json and, when the rendered artifact belongs to a project, also updates
its recorded outputs in project.yaml.