Configuration reference
Complete config.yml reference for Jira and ClickUp providers, teams, metrics, QHS, and targets.
config.yml is the only file customers edit. Comments in the repo’s config.yml are the detailed inline reference.
Top-level keys
| Key | Required | Description |
|---|---|---|
provider | Yes | jira or clickup |
teams | Yes | Squad list (max 10) |
jira / clickup | Yes | API credentials |
customer_name | No | Label in logs and /health |
metrics | Yes | Workflow, bugs, FTPR, optional QHS/targets |
Teams
teams:
- name: Backend
jira:
project_key: BE
clickup:
folder_id: "16615923"
list_ids: ["198503460"]
routing:
squad_value: Backend
extra_tags: [backend_squad]
metrics: # optional per-squad override
jira:
workflow:
cycle_start_statuses: [Development]
exclusions:
title_keywords: ["WIP |"]
tags: [skip_metrics]
task_ids: ["abc123"]
Shorthand keys: jira_project, clickup_list_id, clickup_list_ids, clickup_folder_id, clickup_space_id
Each name becomes a team tab.
Jira credentials
jira:
url: https://acme.atlassian.net
email: pulse-bot@acme.com
token: ""
ClickUp credentials
clickup:
token: ""
workspace: "12345678"
workspace is the ClickUp Team ID. Pulse validates it with GET /team/{workspace} on the first API call.
Jira configuration
metrics.jira.workflow
| Key | Purpose |
|---|---|
cycle_start_statuses | When cycle time starts (default: In Progress) |
cycle_end_statuses | Optional explicit cycle end (default: use done) |
lead_start_statuses | Lead time start (default: ticket created) |
lead_end_statuses | Done statuses |
qa_in_progress_statuses | Exact statuses counted for Avg Time in QA |
qa_in_progress_contains | Substring match for QA/test columns |
qa_ready_statuses | Queue before QA, audit/info only, not avg QA time |
qa_ready_contains | Substring match for ready-QA columns |
bottleneck_exclude_statuses | Exact statuses omitted from Bottleneck Index |
bottleneck_exclude_prefixes | Prefix exclusions (done, closed, complete, …) |
status_order | Board column order for FTPR backward-move detection |
Status names are case-insensitive.
Cycle time vs lead time: These are independent. Lead time uses created (or lead_start_statuses, or ClickUp start/due dates) through done. Cycle time only starts when status history shows the ticket entered cycle_start_statuses (for example In Progress). A completed ticket can have lead time but a blank cycle time if it was closed without ever entering that status (common for bugs closed from backlog, or when status names in history do not match config). Blank cycle does not mean a sync error.
metrics.jira.ftpr
| Key | Purpose |
|---|---|
reopen_statuses | Moving to these after Done = FTPR fail |
fail_labels | Jira labels that force fail |
Default: backward move in status_order after first cycle_start_statuses, or reopen after Done.
metrics.jira.bugs
bugs:
task_types: [Bug] # Software projects
tags: [bug] # Jira labels, JSM, label-based bugs
title_keywords: ["[Bug]"] # title contains
title_prefix: "BUG |" # alias for title_keywords
A ticket is a bug if any rule matches.
metrics.jira.subtasks
subtasks:
include: false
issue_types: [Sub-task, Subtask]
Default: JQL adds parent is EMPTY.
metrics.jira.custom_fields
custom_fields:
ticket_size_field: Story Points
ticket_size_value_map: "0=XS, 1=S, 2=M, 3=L, 4=XL, 5=XXL"
ticket_size_order: [XS, S, M, L, XL, XXL]
urgency_field: Priority
urgency_value_map: ""
urgency_order: [Low, Normal, High, Critical]
Resolved by display name via /rest/api/3/field. Duplicate names → Config audit warning/error (never silent guess). Supports number, select, and ADF text fields.
Bugs by priority and bug lead by urgency (Jira and ClickUp): one source per workspace. If urgency_field is empty, charts use Jira native priority. If urgency_field is set, charts use only that field; issues with no value count as Unknown (native priority is not used as a fallback).
metrics.jira.flow
flow:
work_statuses: [In Progress, QA In Progress, In Review]
wait_statuses: [To Do, Ready for test, Blocked]
Powers flow efficiency and status distribution charts.
Jira fetch scope
- Tickets resolved or created in the date range
- Plus open bugs (created before range end, not resolved before range start)
- Does not use Jira’s
updatedfield (avoids stale tickets from comment-only edits) - Changelog fetched selectively when needed (
PULSE_JIRA_CHANGELOG_WORKERS, default 5)
ClickUp configuration
Squad source (at least one per team)
| Key | Purpose |
|---|---|
list_id | Single home list |
list_ids | Multiple lists |
folder_id | Expands to all lists in folder |
space_id | Expands folderless lists + all folder lists in space |
teams[].clickup.routing
| Key | Purpose |
|---|---|
squad_value | Dropdown option for this squad (only when use_squad_field: true) |
squad_field | Optional per-squad override of the custom dropdown field name |
extra_tags | Tag identity match |
locations | Location name match (case-insensitive) |
location_ids | Location ID match |
location_name | Substring in location name |
list_names | Exact list name match |
title_keywords | Title prefix match |
use_title_keywords | Apply title keywords (default false, last-resort fallback) |
product_support_list_ids | Shared support lists. still needs tag/title/location match |
Routing order (when multi_squad: false, strongest match wins):
- Tags, locations, list names (identity)
- Explicit
list_ids/folder_id/space_id - Squad dropdown, only when
use_squad_field: trueand multiple squads share the same list/folder - Title keywords (when
use_title_keywords: true)
metrics.clickup.routing
routing:
multi_squad: false
use_squad_field: false # default; set true when squads share a ClickUp folder/list
squad_field: Squad # default dropdown label (global fallback)
squad_field_by_space: # optional: different field name per ClickUp space_id
"12345678": Squad
cross_squad_value: Cross-squad # optional shared-pool dropdown value
squad_field is the display name of your custom dropdown in ClickUp (not a built-in field). Pulse resolves it in order: per-squad routing.squad_field, then squad_field_by_space[space_id], then global squad_field. Custom fields in ClickUp are created per Space, Folder, or List, so the label can differ per space.
Bad folder_id or space_id values surface as errors in the Config audit panel (not silent empty squads).
metrics.clickup.workflow
Same keys as Jira, plus:
| Key | Purpose |
|---|---|
cycle_start_fallback | When ticket never entered cycle start: none (default), flow_work, first_history, created |
metrics.clickup.ftpr
ftpr:
fail_tags: [ftpr-fail]
assume_pass_without_fail_tag: true # default
Grouped by completion month by default (same as throughput/cycle). Set metrics.clickup.ftpr.group_by: due_date to bucket by due-date month instead; tickets without a due date are then excluded from FTPR. Requires fail-tag automations.
Bug reopen rate uses status history (not fail tags): a bug counts as reopened when it leaves a done status after the first completion. Needs lead_end_statuses aligned with your done columns and status data from bulk_time_in_status.
metrics.clickup.bugs
bugs:
tags: [bug]
title_prefix: "BUG |"
title_keywords: [defect]
custom_item_types: [Bug]
metrics.clickup.custom_fields
custom_fields:
ticket_size_field: Story Points
urgency_field: "" # empty = native ClickUp priority for bug charts
urgency_order: [Low, Normal, High, Critical]
urgency_value_map: "" # optional aliases, e.g. 1=Low, 2=Normal
Bugs by priority and bug lead by urgency use one source for the whole workspace, never a mix per ticket:
urgency_fieldempty (default): bucket by ClickUp native priority (Urgent / High / Normal / Low).urgency_fieldset: bucket by that custom dropdown only. Tickets with the field empty count as Unknown. Native priority is ignored.
Both charts follow the same rule. Leave urgency_field empty unless your squad consistently fills the custom dropdown on bugs.
The name must match ClickUp exactly (emoji prefixes included). Pulse does not create or assume a custom urgency field for you.
ClickUp fetch architecture
- Global pool, one fetch for all squads’ list IDs (parallel, default 6 workers)
- Completed tasks via
date_done_gt+ open tasks for bug backlog bulk_time_in_statusbatched (100 IDs per call) for cycle/lead/QA/FTPR-adjacent timing- Per-squad routing filters the pool
Tune: PULSE_CLICKUP_PARALLEL (can only lower the plan worker cap), PULSE_CACHE_TTL_SECONDS (default 300)
Shared configuration
metrics.exclusions (global)
| Key | Purpose |
|---|---|
issue_types | Jira types to drop (default: [Epic, Spike], set [] to include) |
tags | Tag/label exclusion |
title_keywords | Title substring exclusion |
list_ids | ClickUp list IDs skipped before routing |
teams[].metrics.exclusions (squad-only)
Same as global, plus task_ids, drops specific tickets from this squad’s metrics only (routing unchanged).
metrics.qhs
qhs:
weights:
ftpr: 0.45
cycle: 0.35
bugs: 0.20
cycle_score:
days_multiplier: 4
min: 35
max: 95
bug_score:
per_bug_penalty: 1
min: 35
max: 95
Formula (shown live on Quality Insights):
- With FTPR:
round(w_ftpr×FTPR + w_cycle×cycle_score + w_bugs×bug_score) - Without FTPR: cycle + bug weights re-normalized
- Cycle score:
clamp(100 − median_cycle_days × days_multiplier, min, max) - Bug score:
clamp(100 − bugs_closed × per_bug_penalty, min, max)
metrics.targets
Optional good/warn thresholds for metric card colors and FTPR chart target line:
metrics:
targets:
ftpr:
good: 85
warn: 70
lower_is_better: false
median_cycle:
good: 5
warn: 10
lower_is_better: true
Supported keys: ftpr, qhs, median_cycle, average_cycle, median_lead, average_lead, avg_time_qa, bugs_closed, open_bugs, throughput, bug_density, bug_reopen_rate. Defaults apply when omitted.
Complete config.yml key index
Only the block for your active provider is required (metrics.jira or metrics.clickup). The other provider block can be omitted.
Top level
| Key | Required | Example | What it does |
|---|---|---|---|
provider | Yes | jira | Which API Pulse calls. jira or clickup. |
teams | Yes | see below | Squad list (max 10). Each name becomes a dashboard tab. |
jira | If provider: jira | url, email, token | Jira Cloud site and API credentials. |
clickup | If provider: clickup | token, workspace | ClickUp API token and Team ID. |
customer_name | No | Acme Corp | Shown in logs and /health. Not a UI logo. |
dashboard.theme | No | charcoal | Default UI theme: default, light, matrix, dutch, ember, charcoal. |
api.clickup_plan | No | business | Parallelism and rate limits for ClickUp. Default free. |
api.jira_plan | No | standard | Jira search page size and changelog workers. Default free. |
performance.* | No | see below | Cache and reuse toggles. All default on. |
teams[] (each squad)
| Key | Provider | Example | What it does |
|---|---|---|---|
name | Both | Platform | Tab label in the UI. Not the Jira project key. |
jira.project_key | Jira | PLAT | Jira project key used in JQL. |
clickup.list_id | ClickUp | "901234567890" | Single home list for this squad. |
clickup.list_ids | ClickUp | ["901…", "902…"] | Multiple lists. |
clickup.folder_id | ClickUp | "901…" | All lists under this folder. |
clickup.space_id | ClickUp | "901…" | Folderless lists plus all folder lists in the space. |
clickup.routing.* | ClickUp | squad_value: Platform | Per-squad routing rules when lists are shared. |
teams[].metrics | Both | nested block | Overrides global metrics for this squad only. |
teams[].metrics.exclusions | Both | tags, task_ids | Drop tickets from this squad's metrics (routing unchanged). |
Shorthand: jira_project, clickup_list_id, clickup_list_ids, clickup_folder_id, clickup_space_id (same meaning as nested keys).
metrics.jira.workflow
| Key | Default (if omitted) | Example | What it does |
|---|---|---|---|
cycle_start_statuses | [In Progress] | [In Progress] | Cycle time starts when the ticket first enters one of these statuses. |
cycle_end_statuses | [] (use done) | [Done] | Optional explicit cycle end. Empty means first lead_end_statuses transition. |
lead_start_statuses | [] (created) | [To Do] | Lead time start. Empty uses ticket created date. |
lead_end_statuses | [Done] | [Done, Live] | Statuses that count as done for lead/cycle end. |
qa_in_progress_statuses | [In QA] | [QA In Progress, In Review] | Exact statuses counted for Avg time in QA. |
qa_in_progress_contains | [] | [qa, test] | Substring match for QA-in-progress columns (combined with exact list). |
qa_ready_statuses | [Ready for QA] | [Ready for test] | Queue/wait before QA. Used in audit and flow charts, not avg QA time. |
qa_ready_contains | [] | [ready] | Substring match for ready-for-QA columns. |
bottleneck_exclude_statuses | long default list | [To Do, Done] | Statuses omitted from Bottleneck Index. |
bottleneck_exclude_prefixes | [done, closed, complete] | same | Prefix exclusions for bottleneck (case-insensitive). |
status_order | see defaults | board column order | FTPR backward-move detection after first cycle_start_statuses. |
Status names are matched case-insensitively.
metrics.jira.ftpr
| Key | Example | What it does |
|---|---|---|
reopen_statuses | [In Progress] | Moving to these after Done counts as FTPR fail. |
fail_labels | [ftpr-fail] | Jira labels that force FTPR fail regardless of history. |
metrics.jira.bugs
| Key | Example | What it does |
|---|---|---|
task_types | [Bug] | Issue types treated as bugs. |
tags | [bug] | Jira labels (useful for JSM incidents). |
title_keywords | ["[Bug]"] | Title contains any of these strings. |
title_prefix | BUG | | Alias for a single title prefix rule. |
A ticket is a bug if any rule matches.
metrics.jira.custom_fields
| Key | Example | What it does |
|---|---|---|
ticket_size_field | Story Points | Display name for size chart (resolved via /rest/api/3/field). |
ticket_size_value_map | 0=XS, 1=S | Map numeric/select values to labels. |
ticket_size_order | [XS, S, M, L] | Chart sort order. |
urgency_field | Priority | Bug priority charts. Empty = Jira native priority only. |
urgency_value_map | 1=Low, 2=High | Optional aliases for custom dropdown values. |
urgency_order | [Low, Normal, High] | Chart sort order. |
When urgency_field is set, only that field is used per ticket. Empty values count as Unknown. Native priority is not mixed in.
metrics.jira.flow
| Key | Example | What it does |
|---|---|---|
work_statuses | [In Progress, QA In Progress] | Active work time for flow efficiency. |
wait_statuses | [To Do, Ready for test] | Wait/queue time for flow efficiency. |
metrics.jira.subtasks
| Key | Default | What it does |
|---|---|---|
include | false | When false, sub-tasks are excluded from metrics (JQL parent is EMPTY). |
issue_types | [Sub-task, Subtask] | Extra issue types to treat as subtasks when include: false. |
metrics.clickup (when provider: clickup)
| Section | Key highlights | What it does |
|---|---|---|
routing | use_squad_field, squad_field, multi_squad | Shared-folder squad split via custom dropdown. |
workflow | same as Jira plus cycle_start_fallback | none, flow_work, first_history, created when cycle start missing. |
ftpr | fail_tags, assume_pass_without_fail_tag, group_by | Tag-based FTPR. group_by: due_date buckets by due month. |
bugs | tags, title_prefix, custom_item_types | Bug detection rules. |
custom_fields | ticket_size_field, urgency_field | Same urgency rules as Jira (one source per workspace). |
fetch_open_tasks | default true | false skips open tasks (faster, incomplete bug backlog). |
See ClickUp configuration for routing keys and examples.
metrics.exclusions (global)
| Key | Default | What it does |
|---|---|---|
issue_types | [Epic, Spike] | Jira types dropped from all squads. Set [] to include. |
tags | [] | Exclude tickets with these labels/tags. |
title_keywords | [] | Exclude when title contains keyword. |
list_ids | [] | ClickUp lists skipped before routing. |
metrics.qhs and metrics.targets
See sections above for formulas. metrics.targets sets good/warn bands on summary cards (keys in app/targets.py).
