GitHub Actions Stale Issues/PRs Workflow Builder

Auto-label and close stale issues and pull requests

Generate a GitHub Actions stale.yml using actions/stale@v9 with configurable days-before-stale, days-before-close, exempt labels, and custom stale and close messages. Runs entirely in your browser. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What does days-before-close count from?

It counts from the moment the item is marked stale, not from the last activity. So a 60-day stale plus 7-day close means an item can sit untouched for 67 days before it is automatically closed.

A GitHub Actions stale workflow builder that generates a ready-to-commit stale.yml using the official actions/stale@v9 action. It marks inactive issues and pull requests as stale, then closes them after a grace period — unless they carry a label you have marked as exempt. The result is a self-maintaining issue tracker that does not drown in abandoned tickets.

How it works

The generated workflow runs on a schedule (a cron expression in UTC) and can also be triggered manually via workflow_dispatch. On each run, actions/stale scans open issues and PRs and compares each item’s last-activity time against days-before-stale. Items past that threshold get the stale label and a comment. A second timer, days-before-close, counts forward from when the item became stale; once it elapses, the item is closed with a closing comment.

Exempt labels short-circuit the whole process: an item with pinned, security, or any label you list is never touched. The job declares issues: write and pull-requests: write permissions so it can apply labels, comment, and close — operations a read-only token cannot perform.

Generated workflow structure

name: Stale

on:
  schedule:
    - cron: "0 1 * * *"  # daily at 01:00 UTC
  workflow_dispatch:      # allow manual runs to preview behavior

permissions:
  issues: write
  pull-requests: write

jobs:
  stale:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/stale@v9
        with:
          stale-issue-message: >
            This issue has been inactive for 60 days and is marked stale.
            Add a comment to keep it open.
          close-issue-message: >
            This issue has been closed due to inactivity.
            Reopen it if the problem persists.
          stale-pr-message: >
            This PR has been inactive for 60 days and is marked stale.
          close-pr-message: >
            This PR has been closed due to inactivity.
          days-before-stale: 60
          days-before-close: 7
          exempt-issue-labels: "pinned,security,roadmap"
          exempt-pr-labels: "pinned,do-not-close"
          operations-per-run: 100

Understanding the timeline

The two timer settings combine, not overlap:

  • An item untouched for 60 days gets the stale label and a comment.
  • If no activity happens for another 7 days after that, the item is closed.
  • So the total time from last activity to closure is 67 days.

Reopening a closed issue or adding a comment to a stale one resets the clock — the stale label is removed and the countdown starts over.

Choosing exempt labels wisely

Exempt labels protect items from the stale cycle entirely. Common candidates:

LabelReason to exempt
pinnedKnown issue deliberately kept open for visibility
securitySecurity vulnerabilities should never auto-close
roadmapIntentional long-term tracking issues
help wantedActively seeking contribution — premature to close
blockedWaiting on an upstream dependency or external factor

Add these labels to issues that would be confusing or damaging to auto-close, and leave everyday bugs and feature requests to the stale cycle.

Tips and notes

  • Keep operations-per-run modest on large repositories. The action burns API quota for every comment and label change, and a huge backlog can otherwise exhaust your hourly limit.
  • Set days-before-close to -1 if you only want a stale label and a nudge, leaving the close decision to a human.
  • Run the workflow on workflow_dispatch first to preview behaviour before trusting the schedule — the action logs exactly which items it would mark or close.
  • Schedule it during off-peak UTC hours (for example 0 1 * * *) so the notification burst does not land in the middle of your team’s workday.