Documentation
Commands
Comment on a pull request. You need write access on GitHub, or Contribute on Azure DevOps — a comment from anyone else is refused, including help and status.
On GitHub, install the App on the account that owns the repository first. A comment is ignored until it is installed there.
| Command | Effect |
|---|---|
| /schedule friday 18:00 | Merge at that time, in your timezone |
| /schedule 2026-10-05 18:00 Europe/Berlin | Explicit date and zone |
| /schedule 2026-10-05 18:00 UTC+2 | A fixed offset from UTC |
| /schedule 2026-10-05T16:00Z | An absolute instant |
| /schedule in 3 hours | Relative to now |
| /schedule friday 18:00 squash | Choose the merge method |
| /reschedule tomorrow 09:00 | Move an existing schedule |
| /unschedule | Cancel it |
| /schedule status | Show the current schedule |
| /schedule help | This table, on the pull request |
A bare time is read in your own timezone, learned from the dashboard or from any command where you named one. Failing that, the repository’s configured zone. Commands inside code fences are ignored, so you can write about them without triggering them.
Labels
On GitHub, a label that starts with schedule: is the same as a /schedule comment. The rest of the name is the time. Removing the label cancels the schedule. You still need write access — a label from anyone else is ignored.
Useful when a bot or workflow already applies labels. The label has to be added to that pull request; a repository label that is not on the PR does nothing.
Azure DevOps
There is no Entra app. Scheduled-PR never creates a personal access token for you — you make one in Azure DevOps and paste it into the extension.
- Install the Scheduled-PR extension on the organization from the Visual Studio Marketplace.
- In Azure DevOps, open User settings → Personal access tokens and create a token. Scope it to this organization. Grant Code: Read & write. Copy the token when Azure shows it — it is not shown again.
- Open Repos → Scheduled-PR, paste the token, and click Connect. That stores the token and creates the service hooks.
- Comment the same commands on a pull request, or use Schedule merge… on the pull request menu.
When the token expires or you rotate it, open the hub and Reconnect with a new one. Reconnect also replaces the service hooks. Nothing is pasted into scheduled-pr.dev itself.
Repository configuration
.scheduled-pr.ymlOptional. Commit it to the root of your repository, on the default branch. Every key has a default, so a file with one line is valid. An invalid file does not disable scheduling — the defaults apply and the pull request comment says what was wrong.
version: 1
timezone: Europe/Berlin
default_merge_method: squash # merge | squash | rebase
on_failure: retry # retry | fail | wait-for-checks
retry:
max_attempts: 10
backoff: exponential # exponential | fixed
give_up_after: 2h
on_new_commits: keep # keep | cancel
# Merges happen only inside these. Declare none and any time is allowed.
allowed:
- { days: [mon, tue, wed, thu], from: "18:00", to: "22:00" }
# Applied on top. Blocked always beats allowed.
blackout:
- { days: [fri], after: "15:00" }
- { days: [sat, sun] }
require:
checks_green: true
approvals: 1
no_changes_requested: true
max_lead_time: 90d| Key | Default | What it does | Examples |
|---|---|---|---|
| timezone | UTC | Zone for bare times, when the person has none of their own. An IANA name, or a fixed offset |
|
| default_merge_method | merge | Used when a command names no method. Must be one the repository allows |
|
| on_failure | retry | retry backs off; fail gives up at once; wait-for-checks waits for a check suite to finish |
|
| retry.max_attempts | 10 | Attempts before giving up and saying why |
|
| retry.give_up_after | 2h | Wall-clock limit, whichever comes first |
|
| on_new_commits | keep | keep follows the new head; cancel drops the schedule when commits land |
|
| allowed | any time | Merges happen only inside these windows. Both bounds required; a window may run past midnight |
|
| blackout | none | Applied on top of allowed. Blocked always beats allowed |
|
| require.checks_green | true | Refuse to merge while checks are red or running |
|
| require.approvals | 0 | Minimum approving reviews |
|
| require.no_changes_requested | true | Refuse while a reviewer has requested changes |
|
| max_lead_time | 90d | How far ahead a merge may be scheduled |
|
The file is re-read every few minutes, so a change takes effect without reinstalling anything.
What happens at the scheduled time
- The pull request is read again from GitHub or Azure DevOps. Nothing cached is trusted.
- It must be open, not a draft, free of conflicts, passing whatever you require, and outside any blackout window.
- The merge is pinned to the current commit, so a push landing mid-merge is rejected rather than merged unseen.
- If it cannot merge, the comment is edited with the reason in GitHub’s own words, the next attempt time, and when it will stop trying.
A closed or already-merged pull request cancels the schedule quietly. Conflicts, red required checks, and a merge method the repository forbids all stop it immediately — retrying those would never succeed.
What counts against your plan
One unique pull request scheduled within a calendar month. Rescheduling the same pull request as often as you like still counts once. Cancelling does not give the unit back — otherwise the free plan would be unlimited to anyone willing to schedule and cancel.