Configuration#

All metric commands require a .gh-velocity.yml file. Run gh velocity config preflight --write to generate one. This page covers first-time setup; for the full schema, see Configuration Reference.

Generate a config with preflight#

The fastest way to get started is to let preflight inspect your repo and generate a tailored config:

cd your-repo
gh velocity config preflight --write

Preflight examines your repo's labels, project boards, and recent activity, then generates a .gh-velocity.yml with appropriate matchers (patterns like label:bug that classify issues), lifecycle labels, and project board settings.

The generated config includes match evidence — comments showing how many issues each matcher would catch:

# Match evidence (last 30 days of issues + PRs):
#   bug / label:bug — 33 matches, e.g. #12893 error parsing "input[title]"...
#   feature / label:enhancement — 37 matches, e.g. #12862 Remove a book...
#   chore / label:tech-debt — 0 matches (review this matcher)

Check these evidence comments before you commit your config. Matchers with 20+ matches are solid. Zero-match matchers may need a different label name — check your repo's actual labels with gh label list.

You can also preview what preflight would generate without writing the file (dry run):

gh velocity config preflight

Discover project board settings#

If you use a GitHub Projects v2 board, the config discover command finds your project URL, status field name, and available status values:

gh velocity config discover -R owner/repo

Use this output to fill in the project and lifecycle sections of your config.

Validate your config#

After writing or editing your config, validate it:

gh velocity config validate

This checks all fields for correct types, valid ranges, and proper formats. It does not make API calls.

To see the resolved configuration with all defaults applied:

gh velocity config show
gh velocity config show -f json

Minimal config#

If your repo uses standard bug and enhancement labels, this is all you need:

quality:
  categories:
    - name: bug
      match:
        - "label:bug"
    - name: feature
      match:
        - "label:enhancement"

This is equivalent to what preflight generates for repos with standard labels.

What each section does#

Each config section represents a decision about how gh-velocity should measure your project. Most have sensible defaults — you only need to configure what matters for your workflow. See Configuration Reference for the full schema.

workflow#

How your team works. pr (default) means PRs close issues. local means direct commits to main (solo projects, scripts).

scope#

Which issues and PRs to analyze, using GitHub search query syntax:

scope:
  query: "repo:myorg/myrepo"

quality.categories#

Ordered list of classification categories. The first matching category wins; unmatched issues are classified as "other." Matcher types:

  • label:<name> — exact label match
  • type:<name> — GitHub Issue Type
  • title:/<regex>/i — title regex, case-insensitive
  • field:<Name>/<Value> — GitHub Projects v2 SingleSelect field value (e.g., field:Size/M). See Labels vs. Board
quality:
  categories:
    - name: bug
      match:
        - "label:bug"
        - "label:defect"
    - name: feature
      match:
        - "label:enhancement"
    - name: chore
      match:
        - "label:tech-debt"
        - "title:/^chore[\\(: ]/i"

The report's defect rate counts issues classified as "bug". If you name your bug category differently (e.g., "defect"), use bug as the name in the config.

quality.hotfix_window_hours#

A release is flagged as a hotfix if published within this many hours of the previous release. Default: 72 (3 days). Maximum: 8760 (1 year).

cycle_time#

Which strategy to use: issue (label-based) or pr (PR creation to merge). See How It Works for guidance on choosing, and Cycle Time Setup for step-by-step configuration.

cycle_time:
  strategy: pr

project#

GitHub Projects v2 settings. Enables the wip command and backlog detection:

project:
  url: "https://github.com/users/yourname/projects/1"
  status_field: "Status"

lifecycle#

Maps labels and project board columns to workflow stages. Labels (match) provide reliable cycle time timestamps. Board columns (project_status) power WIP and backlog detection. See Labels vs. Project Board for why labels are preferred:

lifecycle:
  backlog:
    project_status: ["Backlog", "Triage"]
  in-progress:
    project_status: ["In progress"]
    match: ["label:in-progress", "label:wip"]

velocity#

How to measure effort per iteration. Three effort strategies: count (just count items), attribute (labels like size:M with point values), or numeric (a project board number field). See Velocity Setup for a walkthrough.

velocity:
  effort:
    strategy: attribute
    attribute:
      - query: "label:size/S"
        value: 1
      - query: "label:size/M"
        value: 3
      - query: "label:size/L"
        value: 5

commit_ref#

Controls how the commit-ref linking strategy scans commit messages:

commit_ref:
  patterns: ["closes"]           # default: only closing keywords
  # patterns: ["closes", "refs"] # also match bare #N references

exclude_users#

Exclude bot accounts from metrics:

exclude_users:
  - "dependabot[bot]"
  - "renovate[bot]"

discussions#

GitHub Discussions integration for --post on bulk commands:

discussions:
  category: General

Token permissions#

The default gh auth login token works for all local usage. In CI, different tokens cover different capabilities.

CapabilityDefault GITHUB_TOKEN+ GH_VELOCITY_TOKEN (PAT with project scope)
Lead time, throughput, release qualityYesYes
Bus factor, reviewsYesYes
--post to issues/PRs/DiscussionsYesYes
Cycle time (issue strategy with project board)NoYes
WIP commandNoYes

If your config has no project: section, you do not need GH_VELOCITY_TOKEN.

If your config has a project: section, commands that need the board will warn and skip that data unless GH_VELOCITY_TOKEN is set. The rest of the report still works.

For CI token setup details, see CI Setup.

Next steps#