Templates¶
Templates define which checklist items appear when an issue is opened. They are plain Markdown files stored in your repositories.
File location¶
When an issue is opened, the app searches for a template in this priority order, stopping at the first file found:
| Priority | Location | Use case |
|---|---|---|
| 1 | {issue-repo}/.github/CHECKLIST/{type}.md |
Repo-specific overrides (can be restricted — see below) |
| 2 | {org}/.github-private/.github/CHECKLIST/{type}.md |
Org-wide private defaults |
| 3 | {org}/.github/.github/CHECKLIST/{type}.md |
Org-wide public defaults |
{type} is the slugified value of the issue's native type name:
| Issue type name | File name |
|---|---|
Bug |
bug.md |
Feature |
feature.md |
Bug Report |
bug-report.md |
If no template is found in any location, a built-in default is used. For the common issue types — Bug, Task, Feature, Incident, Security — the built-in default is tailored to that type (for example, Incident includes items like "Root cause identified" and "Postmortem shared"). Any other issue type falls back to a short, generic checklist.
If a repo + issue type combination is still on the built-in default, the app may occasionally post a comment suggesting you add a template of your own — each eligible issue has roughly a 1-in-10 chance, capped at 5 nudges per repo + issue type per rolling 30 days. Turn this off entirely with suppressCustomizationNudge in checklist-app.json.
Restricting repo-level overrides¶
By default any repo can place its own template at priority 1. You can restrict this per-repo using the repoOverrides setting in .github/checklist-app.json. When a repo is restricted, its .github/CHECKLIST/ files are skipped and resolution starts at priority 2.
See Configuration reference → repoOverrides for details.
Caching¶
Resolved templates are cached in Cloudflare KV to avoid repeated GitHub API calls. By default templates are cached for 5 minutes (300 seconds). You can adjust this per-org in .github/checklist-app.json:
| Value | When to use |
|---|---|
60 |
Actively developing templates — changes appear quickly |
300 |
Default — good balance for most teams |
1800 |
High-volume orgs — maximizes cache hits (hard ceiling) |
Bulk imports: Each cache miss makes up to 3 GitHub API calls. If you're migrating issues in bulk (bug bash, tracker migration, scripts), a warm cache after the first issue means subsequent issues are free. Stagger scripts to allow the first event to populate the cache before the rest follow.
Enforcement level¶
Templates can declare per-checklist behaviour using a YAML frontmatter block at the top of the file:
---
enforcementLevel: Block
exceptionApproversTeam: security-leads
requireExceptionRequestorComments: true
requireExceptionApprovalComments: true
---
## Security
- [ ] Security review completed
All fields are optional and independent — use any combination, or none.
Field names are matched regardless of case or hyphenation, so enforcementLevel, enforcement-level, and ENFORCEMENTLEVEL are all equivalent — same for the other three fields below. Values for enforcementLevel and the two require...Comments flags are also matched case-insensitively (Block/block/BLOCK, true/TRUE). This is meant to be forgiving of how you happen to write it, since a typo'd field name otherwise fails silently — there's no validation step that would flag it.
enforcementLevel¶
Controls what happens when the issue is closed while items are still incomplete.
| Value | Behavior |
|---|---|
Advise |
Does nothing — the checklist is informational only |
Warn |
Posts a comment listing incomplete items but lets the close proceed |
Block |
Reopens the issue and posts a comment listing incomplete items |
Defaults to Warn when omitted. Use Block for compliance-critical templates (security audits, legal sign-offs). Use Advise for optional checklists where the team should see the items but not be gated.
exceptionApproversTeam¶
The GitHub team slug whose members are permitted to approve exception items on this checklist. When omitted, falls back to the exceptionApproversTeam value in checklist-app.json.
This lets different checklists route exceptions to different teams — a security template to security-leads, a legal template to legal-approvers — while keeping a sensible org-wide default in config.
requireExceptionRequestorComments¶
When true, a collaborator must add requestor notes explaining the exception before the item can be saved as Need Exception. Defaults to false — notes stay optional.
requireExceptionApprovalComments¶
When true, an approver must add approver notes before they can approve the exception. Defaults to false.
See the Exception approvals guide for how requestor and approver notes work in the editor.
Template format¶
Templates are standard Markdown with GFM task-list items. Sections are ## headings; items are - [ ] lines.
## Security
- [ ] [Security review completed](https://wiki.example.com/security-review)
- [ ] PII audit done
## Release
- [ ] Changelog entry added
- [ ] Linked to milestone
Items with doc links¶
Wrap the label in a Markdown link to attach a documentation URL:
The link is informational only — clicking it opens the URL in a new tab. It is never required to save an item's state.
Items without doc links¶
Sections¶
Group related items under ## headings. Each heading becomes a collapsible section in the checklist UI.
## Pre-merge
- [ ] Tests passing
- [ ] Code review approved
## Post-merge
- [ ] Deployed to staging
- [ ] QA sign-off
Sections are optional. Items at the top of the file before any heading are placed in an implicit "General" section.
Notes and cautions¶
Add > [!NOTE], > [!TIP], > [!IMPORTANT], > [!WARNING], or > [!CAUTION] blocks to a section — GitHub's own Alert syntax. These render natively wherever the template file itself is viewed on GitHub, and as a labeled, icon-prefixed note in the checklist editor.
## Security
- [ ] PII audit done
> [!CAUTION]
> Do not skip this section for repos handling customer data.
A note's body can span multiple lines — keep each line prefixed with >. A blank line inside the block doesn't end the note; start a new > [!TYPE] block to begin a separate one.
Notes belong to whichever section they appear under, same as items — one before any ## heading lands in the implicit "General" section. The editor's note icons are fixed, not configurable: GitHub already renders its own icon for each alert type when the template file is viewed on GitHub itself, so both surfaces stay visually consistent.
When the issue type changes¶
If the issue type is changed after the checklist has been posted, the app:
- Re-resolves the template for the new type
- Runs the merge algorithm:
- Items whose label text matches an existing item carry forward their status and approver
- New items (not in the old template) are added as
pending - Removed items (not in the new template) are dropped
- Updates the managed comment
- Posts a bot reply: "Checklist updated — N items added, M items removed, K items carried over."
When an issue is transferred¶
Same merge behavior as a type change, but the template is resolved from the destination repo's context. The app must be installed on the destination org/repo to receive the transfer event.