Templates
Templates are reusable test configurations that define what to test, how long to test, and what results to collect. Instead of repeating the same parameters on every job, define them once in a template and reference it by name.
Template Sources
Runhuman supports three template sources, checked in this order:
| Source | Where it lives | How to create |
|---|---|---|
| Repo templates | .runhuman/templates/*.md in your GitHub repo | Commit markdown files |
| Project templates | Stored in the Runhuman database | Create via dashboard, API, or CLI |
| Built-in templates | Bundled with Runhuman | Available automatically |
When you reference a template by name, Runhuman checks repo first, then project, then built-in. The first match wins.
Repo Templates
Repo templates live in your GitHub repository at .runhuman/templates/. They’re version-controlled alongside your code, making them easy to review, update, and share with your team.
File Structure
your-repo/
.runhuman/
templates/
smoke-test.md
checkout-flow.md
accessibility-check.md
Each .md file is a template. The filename (without .md) becomes the template name used to reference it.
Template Format
Templates are markdown files with YAML frontmatter:
---
name: Smoke Test
duration: 5
device_class: desktop
url: https://staging.example.com
---
Verify the app loads and core features work:
1. Load the homepage and confirm it renders without errors
2. Navigate to the login page and verify the form appears
3. Check that the main navigation links work
4. Verify the footer loads with correct content
## Results
Page loads without errors: [ ]
Login form is accessible: [ ]
Navigation works: [ ]
Issues found: ___
Frontmatter Fields
| Field | Type | Description |
|---|---|---|
name | string | Display name for the template. Falls back to the filename if omitted. |
duration | number | Target test duration in minutes (1-60) |
device_class | string | Device class: desktop, mobile, or both (default: both) |
url | string | Default URL for the tester to visit |
max_extension_minutes | number | Total extension time in minutes (default: 15) |
extension_count | number | Number of extensions (default: 3). Set to 0 to disable extensions |
github_repos | string[] | GitHub repos as a YAML list of owner/repo strings (overrides project default) |
All frontmatter fields are optional. The template name is inferred from the filename if not specified.
Body Content
Everything after the frontmatter becomes the test description — the instructions your tester sees. Write clear, step-by-step instructions in markdown.
Results Section
Use a ## Results heading to define a free-form results template. Testers fill in the blanks and checkboxes:
## Results
Login works: [ ]
Page load time: ___ seconds
Errors found:
item[
- Description: ___
- Severity: ___
]
The syntax uses MDForm conventions:
[ ]— Checkbox (tester checks or leaves unchecked)___— Free text field (tester fills in)item[...]— Repeatable item group
Results Schema Section
For structured JSON output, use a ## Results Schema heading with a JSON code block:
## Results Schema
```json
{
"loginWorks": {
"type": "boolean",
"description": "Whether the login flow completes successfully"
},
"pageLoadTime": {
"type": "number",
"description": "Page load time in seconds"
},
"issues": {
"type": "array",
"description": "List of issues found",
"items": { "type": "string" }
}
}
```
You can include both ## Results and ## Results Schema in the same template. They serve different purposes:
- Results — A human-friendly form the tester fills out
- Results Schema — A structured JSON schema for machine-readable output
Complete Example
Here’s a full template with all features:
---
name: Checkout Flow
duration: 10
device_class: desktop
url: https://staging.myshop.com
max_extension_minutes: 5
extension_count: 1
---
Test the complete checkout flow:
1. Add an item to the cart
2. Go to checkout
3. Fill in shipping details (use test data)
4. Select a payment method
5. Complete the purchase
6. Verify the order confirmation page
## Results
Cart adds item: [ ]
Checkout page loads: [ ]
Shipping form works: [ ]
Payment selection works: [ ]
Order completes: [ ]
Confirmation page shows: [ ]
Order number: ___
Notes: ___
## Results Schema
```json
{
"checkoutCompletes": {
"type": "boolean",
"description": "Whether the full checkout flow completes"
},
"orderNumber": {
"type": "string",
"description": "The order confirmation number"
},
"issues": {
"type": "array",
"description": "Any issues encountered",
"items": { "type": "string" }
}
}
```
Using Templates
In the CLI
# By name (resolved from repo → project → built-in)
runhuman job create https://example.com --template "Find Bugs"
# By local file path
runhuman job create --template-file .runhuman/templates/smoke-test.md
--template vs --template-file:
--template <name>— A name resolved server-side through the fallback chain (repo → project → builtin)--template-file <path>— A local.mdfile read by the CLI and sent as raw content
When using a template, URL and description are optional — they can come from the template itself. See the CLI docs for the full list of options.
In GitHub Actions
Reference a repo template by name or file path:
# By name (resolved from .runhuman/templates/smoke-test.md)
- uses: volter-ai/runhuman-action@v1
with:
api-key: ${{ secrets.RUNHUMAN_API_KEY }}
url: 'https://staging.example.com'
template: smoke-test
# By file path (read directly from the repo)
- uses: volter-ai/runhuman-action@v1
with:
api-key: ${{ secrets.RUNHUMAN_API_KEY }}
url: 'https://staging.example.com'
template-file: .runhuman/templates/smoke-test.md
template vs template-file:
template— A name resolved server-side through the fallback chain (repo → project → builtin)template-file— A local file path read by the action and sent as raw content
For the full list of action inputs, outputs, and workflow examples, see GitHub Actions.
In the REST API
// By template name (resolved server-side)
const response = await fetch('https://runhuman.com/api/jobs', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
projectId: 'your-project-id',
template: 'smoke-test'
})
});
// With raw template content
const response = await fetch('https://runhuman.com/api/jobs', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
projectId: 'your-project-id',
templateContent: '---\nname: Quick Test\nduration: 5\n---\nCheck the homepage loads.'
})
});
In the Web Dashboard
The Templates page shows all your templates — project templates and repo templates side by side. Repo templates are read-only (marked with a GitHub icon) and must be edited in your repository. Project templates can be edited in the Playground via the Edit button on each card.
To run a template, click its Edit button to open it in the Playground, then click Run.
In the MCP Server
Run a test using the "smoke-test" template on my project
The MCP server’s run_template tool accepts a template name and resolves it through the same fallback chain.
Merge Precedence
When you use a template and provide additional fields in your request, explicit request values always take precedence:
Request fields > Template values > Project defaults
For example, if your template defines duration: 5 but your API request includes targetDurationMinutes: 15, the job uses 15 minutes. This applies to every field: url, description, outputSchema, deviceClass, targetDurationMinutes, and more.
This means you can use a template as a base and override specific fields per-request without creating a new template.
Built-in Templates
Every new project comes with three built-in templates that cover common QA scenarios. You can use them as-is or as starting points for your own templates.
| Template | What it does |
|---|---|
| Find Bugs | Test the app and report bugs with severity, steps to reproduce, and expected behavior |
| Assess UX | Evaluate usability, visual design, mobile-friendliness, and give an overall rating (1-10) |
| Give Product Feedback | Provide honest product feedback: first impressions, strengths, weaknesses, and suggestions |
Use them by name with any client:
runhuman job create https://example.com --template "Find Bugs"
Built-in templates are the last fallback in the resolution chain. If you create a repo or project template with the same name, it takes precedence.
Project Templates
Project templates are stored in the Runhuman database and managed through the dashboard, API, or CLI. Unlike repo templates, they’re editable in the Playground.
Managing Templates in the Dashboard
The Templates page is a browsing and management interface. Each template card shows metadata at a glance — duration, device class, output schema, and active schedules. Hover over a card to reveal quick-action buttons:
- Edit (pencil icon) — Opens the template in the Playground for editing
- Schedule (calendar icon) — Create or manage a schedule for this template (project templates only)
- Delete (trash icon) — Delete the template (project templates only)
Click a card to open a read-only detail modal showing the full template configuration.
Editing Templates in the Playground
The Playground is the primary template editor. When you open a template in the Playground (via the Edit button on its card or the detail modal), you get two save options:
- Save (solid floppy disk icon) — Updates the existing template in place (PATCH). Only visible when a project template is loaded.
- Save as New (outline floppy disk icon) — Creates a new template from the current Playground configuration. Always available. Prompts for a name.
This lets you iterate on a template directly in the Playground, test it with live jobs, and save changes back without leaving the editor.
Create via Dashboard
- Navigate to your project’s Playground
- Configure your test (URL, description, schema, device class, etc.)
- Click Save as New and enter a template name
Create via API
const response = await fetch(
`https://runhuman.com/api/projects/${projectId}/templates`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Smoke Test',
testDescription: 'Check if homepage loads and key features work',
outputSchema: {
pageLoads: { type: 'boolean', description: 'Homepage loads?' },
loginWorks: { type: 'boolean', description: 'Can user login?' }
},
targetDurationMinutes: 5
})
}
);
Create via CLI
# Create a new template
runhuman templates create "Smoke Test" \
--description "Check if homepage loads and key features work" \
--duration 5 \
--schema '{"pageLoads": {"type": "boolean"}, "loginWorks": {"type": "boolean"}}'
# Overwrite an existing template with the same name
runhuman templates create "Smoke Test" \
--description "Updated instructions" \
--force
If a template with the same name already exists, the CLI prompts to confirm the overwrite (or use --force to skip the prompt). See the CLI docs for the full list of options.
Repo Templates vs Project Templates
| Repo Templates | Project Templates | |
|---|---|---|
| Stored in | Your GitHub repo | Runhuman database |
| Version controlled | Yes (git) | No |
| Editable in UI | No (read-only, edit in your repo) | Yes (edit in Playground) |
| Format | Markdown with frontmatter | JSON via API/Playground/CLI |
| Requires GitHub connection | Yes | No |
| Best for | Teams using git workflows | Quick one-off templates |
Recommendation: Use repo templates for your standard test configurations. They’re version-controlled, reviewable in PRs, and stay in sync with your codebase. Use project templates for quick experiments or templates that don’t belong in a specific repo.