This guide walks you through creating and running checklists with ChecklistFabrik, from your very first template to advanced features like conditional pages and reusable includes.
A checklist is a YAML file with a title and one or more pages, where each page contains tasks. Here is a minimal example:
title: 'Server Maintenance'
pages:
- title: 'Pre-Maintenance'
tasks:
- linuxfabrik.clf.checkbox_input:
label: 'Notify users about the upcoming maintenance window'
required: true
- linuxfabrik.clf.checkbox_input:
label: 'Create a full backup'
required: trueSave this as server-maintenance.yml and run it:
clf-play --template server-maintenance.ymlA browser window opens with your checklist. Fill it out and click Finish on the last page. ChecklistFabrik saves a report file with your answers and shuts the local server down. Your progress is also written to the report file on every page submit, so closing the tab mid-run does not lose what you already entered — re-open the report file later to continue, or click Continue Later to stop the server explicitly.
- A template is the YAML file you write—it defines the structure and tasks of your checklist.
- A report is the YAML file that ChecklistFabrik generates when you run a template. It contains your answers.
You run a template to create a new report:
clf-play --template my-template.yml my-report.ymlYou re-open an existing report to continue or review it:
clf-play my-report.ymlIf you omit the report filename, ChecklistFabrik auto-generates one (see Automatic Report Names below).
Use the optional description field to describe what your checklist is about. This is especially useful when using the dashboard:
title: 'Server Maintenance'
description: 'Monthly maintenance procedure for production servers.'
pages:
...Each task delegates its rendering to a module. ChecklistFabrik ships with these built-in modules:
| Module | Purpose |
|---|---|
linuxfabrik.clf.checkbox_input |
Single checkbox or checkbox group |
linuxfabrik.clf.html |
Static HTML content |
linuxfabrik.clf.markdown |
Markdown-formatted content |
linuxfabrik.clf.radio_input |
Radio button group (single selection) |
linuxfabrik.clf.run_template |
Embedded card with a "Run" button that launches another checklist template in a new tab |
linuxfabrik.clf.select_input |
Dropdown (single or multi-select) |
linuxfabrik.clf.text_input |
Single-line text input |
Use linuxfabrik.clf.text_input to collect freeform text. Add required: true to enforce non-empty input:
- linuxfabrik.clf.text_input:
label: 'Ticket number'
required: true
fact_name: 'ticket_number'The fact_name stores the user's input so it can be referenced later (for example in Jinja expressions or on other pages).
A single checkbox:
- linuxfabrik.clf.checkbox_input:
label: 'I have read the runbook'
required: trueA group of checkboxes:
- linuxfabrik.clf.checkbox_input:
label: 'Services to restart'
values:
- label: 'Apache'
value: 'apache'
- label: 'PostgreSQL'
value: 'postgres'
- label: 'Redis'
value: 'redis'
fact_name: 'services'A group where exactly one option can be selected:
- linuxfabrik.clf.radio_input:
label: 'Environment'
values:
- label: 'Staging'
value: 'staging'
- label: 'Production'
value: 'production'
required: true
fact_name: 'environment'A single-select dropdown:
- linuxfabrik.clf.select_input:
label: 'Datacenter'
values:
- 'Zurich'
- 'Frankfurt'
- 'Vienna'
required: true
fact_name: 'datacenter'A multi-select dropdown (hold Ctrl to select multiple):
- linuxfabrik.clf.select_input:
label: 'Affected components'
values:
- 'Database'
- 'Load Balancer'
- 'Web Server'
multiple: true
fact_name: 'components'Use linuxfabrik.clf.markdown to show formatted instructions:
- linuxfabrik.clf.markdown:
content: |
## Important
Before proceeding, make sure you have:
- SSH access to the target server
- The latest backup available
- The runbook open in another tabUse linuxfabrik.clf.run_template to embed a card that launches another checklist template in a new browser tab. Useful for breaking large procedures into independent, reusable sub-checklists that each produce their own report:
- linuxfabrik.clf.run_template:
path: 'shared/db-maintenance.yml'The card shows the target template's title and description fields plus a Run button. The path is resolved relative to the checklist file that defines the task (same as linuxfabrik.clf.import).
Both labels are optional overrides and support Jinja and Markdown:
- linuxfabrik.clf.run_template:
path: 'shared/db-maintenance.yml'
label: 'Run database maintenance for **{{ host }}**'
description: 'Restarts services after the maintenance window.'Clicking Run starts a new server in the background and opens it in a new tab. The launched checklist is fully independent — its facts and report file are separate from the calling checklist.
For raw HTML, use linuxfabrik.clf.html:
- linuxfabrik.clf.html:
content: |
This is <b>raw HTML</b>.Split your checklist into pages for better structure. Each page gets its own screen with navigation buttons:
title: 'Deployment Checklist'
pages:
- title: 'Preparation'
tasks:
- linuxfabrik.clf.text_input:
label: 'Version to deploy'
required: true
fact_name: 'deploy_version'
- title: 'Deployment'
tasks:
- linuxfabrik.clf.checkbox_input:
label: 'Run database migrations'
required: true
- title: 'Verification'
tasks:
- linuxfabrik.clf.checkbox_input:
label: 'Smoke tests passed'
required: trueAll labels and Markdown content support Jinja expressions. Once a user fills in a fact_name, that value becomes available as a Jinja variable on subsequent pages:
pages:
- title: 'Setup'
tasks:
- linuxfabrik.clf.text_input:
label: 'Server hostname'
required: true
fact_name: 'hostname'
- title: 'Deployment'
tasks:
- linuxfabrik.clf.markdown:
content: |
Connect to **{{ hostname }}** via SSH and run the deployment script.Use when to show or hide pages and tasks based on user input:
pages:
- title: 'Setup'
tasks:
- linuxfabrik.clf.radio_input:
label: 'Installation type'
values:
- label: 'Fresh install'
value: 'fresh'
- label: 'Upgrade'
value: 'upgrade'
required: true
fact_name: 'install_type'
- title: 'Fresh Install Steps'
when: 'install_type == "fresh"'
tasks:
- linuxfabrik.clf.checkbox_input:
label: 'Partition disks'
required: true
- title: 'Upgrade Steps'
when: 'install_type == "upgrade"'
tasks:
- linuxfabrik.clf.checkbox_input:
label: 'Create pre-upgrade snapshot'
required: truePages where when evaluates to false are automatically skipped. The same when field works on individual tasks, too.
You can combine multiple conditions (logical AND):
- title: 'Production Fresh Install'
when:
- 'install_type == "fresh"'
- 'environment == "production"'Templates can define a report_path to auto-generate meaningful filenames when creating reports:
title: 'Server Maintenance'
report_path: 'reports/maintenance-{{ hostname }}-{{ now().strftime("%Y%m%d") }}.yml'
pages:
...When running clf-play --template server-maintenance.yml (without specifying a report file), ChecklistFabrik generates the filename from this pattern. Environment variables are also supported:
report_path: '$HOME/reports/maintenance-{{ now().strftime("%Y%m%d") }}.yml'Large checklists can be split into separate files using the linuxfabrik.clf.import directive.
Import pages from another file:
title: 'Full Deployment'
pages:
- title: 'Preparation'
tasks:
- linuxfabrik.clf.markdown:
content: 'This page is defined inline.'
- linuxfabrik.clf.import: 'shared/database-pages.yml'Import tasks into a page:
pages:
- title: 'Security Checks'
tasks:
- linuxfabrik.clf.import: 'shared/security-tasks.yml'
- linuxfabrik.clf.checkbox_input:
label: 'Additional check specific to this checklist'Paths are relative to the importing file.
Use the optional version field to track which iteration of a template created a report:
title: 'Server Maintenance'
version: '2025031901'
pages:
...The version is displayed on the checklist page and carried over to reports.
Run clf-play without any arguments to open the dashboard:
clf-playThe dashboard opens in your browser and shows two sections:
- Templates — click "Run" to start a new checklist from a template (opens in a new tab).
- Reports — click "View" to re-open a previous checklist.
The dashboard scans for *.yml files and displays their title and description fields:
- If
templates/and/orreports/subdirectories exist in the current working directory, they are used automatically. - If only one of them exists, the other falls back to the current directory.
- If both point to the same directory, all files are shown in both sections — use "Run" to start a new checklist or "View" to re-open an existing one.
You can override this with explicit paths:
clf-play --templates-dir ./my-templates --reports-dir ./my-reportsTo explore the bundled examples in a dashboard:
cd examples/
clf-playHere is a complete, real-world-style template that uses most features:
title: 'Application Deployment'
description: 'Standard deployment procedure for the web application.'
version: '2025031901'
report_path: 'reports/deploy-{{ app_version }}-{{ now().strftime("%Y%m%d-%H%M") }}.yml'
pages:
- title: 'General Information'
tasks:
- linuxfabrik.clf.text_input:
label: 'Application version to deploy'
required: true
fact_name: 'app_version'
- linuxfabrik.clf.radio_input:
label: 'Target environment'
values:
- label: 'Staging'
value: 'staging'
- label: 'Production'
value: 'production'
required: true
fact_name: 'target_env'
- title: 'Pre-Deployment Checks for v{{ app_version }} ({{ target_env }})'
tasks:
- linuxfabrik.clf.checkbox_input:
values:
- label: 'All tests passing on CI'
- label: 'Release notes prepared'
required: true
- linuxfabrik.clf.checkbox_input:
label: 'Stakeholders notified'
required: true
when: 'target_env == "production"'
- title: 'Production Approval for v{{ app_version }}'
when: 'target_env == "production"'
tasks:
- linuxfabrik.clf.markdown:
content: |
A production deployment requires explicit approval before proceeding.
- linuxfabrik.clf.text_input:
label: 'Approved by (name)'
required: true
fact_name: 'approved_by'
- title: 'Deploy v{{ app_version }} to {{ target_env }}'
tasks:
- linuxfabrik.clf.checkbox_input:
values:
- label: 'Database migrations executed'
- label: 'Application deployed'
- label: 'Health checks passing'
required: true
- linuxfabrik.clf.checkbox_input:
label: 'Notify stakeholders about the deployment'
required: true
when: 'target_env == "production"'
- title: 'Post-Deployment'
tasks:
- linuxfabrik.clf.checkbox_input:
values:
- label: 'Smoke tests completed'
- label: 'Monitoring dashboards checked'
- label: 'Deployment logged in change management system'
required: trueSave it as deploy-template.yml, then:
# Start from the dashboard:
clf-play
# Or run it directly:
clf-play --template deploy-template.yml| Field | Type | Required | Description |
|---|---|---|---|
description |
string | no | Freeform text shown in the dashboard. |
pages |
sequence | yes | One or more pages. See Page Fields. |
report_path |
string (Jinja) | no | Auto-generate report file paths. Supports env vars ($HOME). Invalid filename characters are removed automatically. |
title |
string | yes | Checklist title, used for browser tab and page heading. |
version |
string | no | Freeform identifier displayed on the checklist page. Carried over from template to report. |
| Field | Type | Required | Description |
|---|---|---|---|
linuxfabrik.clf.import |
string | — | Import pages from a separate file. Must be the only field in the mapping. Paths are relative to the importing file. |
tasks |
sequence | yes | Tasks to render on this page. See Task Fields. |
title |
string (Jinja) | yes | Page heading. May not be empty. |
when |
string or sequence | no | Jinja condition(s). Page is skipped if false. Multiple values are combined with AND. |
Each task mapping starts with a module key, followed by optional metadata:
| Field | Type | Required | Description |
|---|---|---|---|
<module> |
mapping | yes | First key in the mapping. Specifies the rendering module. See Task Modules. |
fact_name |
string | no | Name under which user input is stored. Available as a Jinja variable on subsequent pages. Auto-generated if omitted. |
value |
any (Jinja) | no | Saved value from a previous run (managed by clf-play). Can be set in templates as a default. When set in a template, string values are rendered through Jinja once at load time, so expressions like {{ now().strftime("%Y%m%d") }} or references to earlier facts are resolved before the default is shown to the user. |
when |
string or sequence | no | Jinja condition(s). Task is hidden if false. Multiple values are combined with AND. |
The special module linuxfabrik.clf.import takes a file path string instead of a mapping and imports tasks from that file.
Single checkbox or checkbox group.
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | no | Label for the checkbox or group. Supports Jinja and Markdown. |
required |
boolean | no | If true, all checkboxes must be checked to proceed. |
values |
sequence | no | Checkbox group items (see below). Omit for a single checkbox. |
Each item in values:
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | no | Checkbox label. Falls back to value. Supports Jinja and Markdown. |
required |
boolean | no | Require this specific checkbox. Overridden by task-level required. |
value |
string | no | Value stored when checked. Auto-generated if omitted. |
Renders Jinja-templated HTML directly. For most cases, prefer linuxfabrik.clf.markdown.
| Field | Type | Required | Description |
|---|---|---|---|
content |
string | yes | HTML to render. Supports Jinja. |
Renders Markdown content as HTML.
| Field | Type | Required | Description |
|---|---|---|---|
content |
string | yes | Markdown text to render. Supports Jinja. |
Radio button group (single selection).
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | no | Group label. Supports Jinja and Markdown. |
required |
boolean | no | If true, one option must be selected to proceed. |
values |
sequence | yes | Radio button options (see below). |
Each item in values:
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | no | Radio button label. Falls back to value. Supports Jinja and Markdown. |
value |
string | no | Value stored when selected. Auto-generated if omitted. |
Embeds a card that displays the target checklist template's metadata and a Run button. Clicking the button starts the referenced template in a new browser tab.
| Field | Type | Required | Description |
|---|---|---|---|
description |
string | no | Override the description shown on the card. Supports Jinja and Markdown. Falls back to the target template's description field. |
label |
string | no | Override the title shown on the card. Supports Jinja and Markdown. Falls back to the target template's title field. |
path |
string (Jinja) | yes | Path to a YAML template file. Relative paths are resolved against the checklist file that defines the task. |
The launched checklist runs as an independent server and produces its own report file. Closing the tab does not affect the calling checklist.
Dropdown (single or multi-select). Single-selects always include a --- Please Select --- placeholder.
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | no | Label. Supports Jinja and Markdown. |
multiple |
boolean | no | Allow selecting multiple options. |
required |
boolean | no | Single: must pick a real option. Multi: at least one must be selected. |
values |
sequence | yes | Options to display. Each item is a plain string. |
Single-line text input.
| Field | Type | Required | Description |
|---|---|---|---|
label |
string | no | Label. Supports Jinja and Markdown. |
required |
boolean | no | If true, the input must be non-empty to proceed. |
Import tasks from a separate file.
| Field | Type | Required | Description |
|---|---|---|---|
| (value) | string | yes | Path to a YAML file containing a task list. Relative to the importing file. |
In addition to Jinja's built-in features, these globals are available in all Jinja-enabled fields:
| Variable | Description |
|---|---|
now() |
Current date and time (datetime.datetime.now()). Example: {{ now().strftime("%Y%m%d") }} |
The examples/ directory contains runnable showcases, organized into templates/ and reports/ subdirectories. Open them in a dashboard:
cd examples/
clf-play| Template | Description |
|---|---|
builtin-modules-showcase.yml |
Demonstrates all built-in task modules and their options. |
demo-deploy-keycloak.yml |
Real-world deployment checklist based on Red Hat documentation. |
demo-takeoff-checklist.yml |
Before-takeoff checklist for pilots, based on AOPA guidelines. |
feature-showcase.yml |
Conditional pages, Jinja templating, report_path. |
import-showcase.yml |
Importing pages and tasks from external files. |