Chrome extension that injects contextual action buttons for CI/bot slash commands on GitHub PR pages.
One-click buttons for /lgtm, /approve, /hold, /retest, and more — injected above the GitHub comment box:
All buttons with keyboard shortcuts, color-coded by action type:
Click Override... or Test... to open a searchable picker showing all CI jobs from the PR — select multiple, then fire them at once:
Override picker (failing checks, multi-select):
Test picker (available presubmit jobs to retest):
Extension scrapes the Checks section to populate the job pickers, and injects
Test/Override/Rehearse buttons directly on each check row:
A pj-rehearse rehearsal check (ci/rehearse/<org>/<repo>/<branch>/<job>) isn't
/test-able, and its context can't be reliably reverse-engineered into the
real job name Prow needs (Prow builds the two independently). The extension
resolves the real name instead by fetching the target repo's own presubmit
config and matching Prow's own shortname algorithm — never guessing:
Not every check belongs to Prow — a repo can run plain GitHub Actions checks
(e.g. a workflow matrix job) that Prow has no knowledge of at all. Posting
/test <name> for one of those gets bounced ("target(s) not found"), no
matter how the name is spelled. The extension detects this per check and
adjusts what it offers:
- Prow-owned check —
/testand/overridebuttons, as before. - GitHub Actions-native check — no
/testbutton (it can't work). Instead: a "Rerun?" link to the check's own Actions run page by default (GitHub's own "Re-run jobs" needs repo write access, so it may be greyed out there), or a real one-click Rerun button if a GitHub token is configured./overrideis still offered — Prow's override plugin accepts any failed check run, not just ones it owns, so it remains the right way to unblock a Tide-blocked merge either way.
Previously overridden checks stay actionable. An /override makes Prow
rewrite the failed context to a green "Overridden by <login>" status, so the
job looks passed even though it never ran green. That's usually intentional for
the moment ("known CI issue, fix landing elsewhere"), but those are exactly the
jobs you want to re-run once the base branch carries the fix. The extension
detects the override marker and:
- keeps the row in the checks section (despite the failed-only filter) and offers a Retest button instead of a second Override;
- highlights and badges overridden jobs in the Test picker, ranking them above genuinely passing ones so they're easy to find and select.
Full profile management — enable/disable profiles, configure commands, set keyboard shortcuts:
Bot profile detail view with all commands, styles, and shortcuts:
- Clone or download this repository
- Open
chrome://extensions/in Chrome - Enable Developer mode (top right)
- Click Load unpacked and select the
github-bot-command-palettedirectory - Navigate to any GitHub PR page — command buttons appear above the comment box
Side-loaded installs don't auto-update, so the extension checks manifest.json on main
(on browser start, and when you open the popup or Settings) and tells you when a newer
version exists: an ↑ badge on the toolbar icon, plus an Update available card in
Settings with a Reload extension button. Web Store installs update themselves and
skip the check.
- Desktop (git checkout):
git pull, then Reload extension in Settings (or the reload icon onchrome://extensions). - Desktop (zip): download
github-bot-command-palette-vX.Y.Z.zipfrom the latest release, unzip it over the folder you loaded, then Reload extension. - Android (Titanium, one-tap with Tasker): see below.
Why not just unzip on Android? Reload extension re-reads the folder you originally picked for Load unpacked. Most Android unzip tools extract into a new folder named after the zip, so the loaded folder stays on the old version. Picking the new folder creates a different extension (the ID comes from the folder path), and its settings start empty. The update has to land in the same folder, which is what the recipe below does.
Every release also attaches an unversioned github-bot-command-palette.zip, so this URL always serves the newest build: https://github.com/kaovilai/github-bot-command-palette/releases/latest/download/github-bot-command-palette.zip.
One-time setup: extract that zip into Download/ghbcp (or any folder), then in Titanium use Load unpacked and pick that folder.
Tasker task Update GHBCP (grant Tasker "All files access" first; option labels may differ slightly between Tasker versions, and the unzip must target the loaded folder):
- Net → HTTP Request — Method
GET, URL above, File To Save With Output:Download/ghbcp-update.zip, Timeout 60. - File → Unzip File — Path:
Download/ghbcp-update.zip, Destination:Download/ghbcp(the folder you picked, not a new one), Delete Zip After: on. - Alert → Flash —
Extension files updated. Tap Reload extension.
Add it as a home-screen shortcut or widget. To finish, tap Reload extension in Settings (or the reload icon on chrome://extensions). Settings are kept because the folder, and therefore the extension ID, never changes. Files deleted in a newer release stay behind in the folder; they're unused and harmless.
Releases are cut automatically when the version in manifest.json changes on main, so bump it in any PR you want users to be notified about.
- Slash command buttons — one-click
/lgtm,/approve,/retest,/hold, etc. - Profile system — configure commands per bot system (Prow, Mergify, Changesets, etc.)
- Repo pattern matching — glob patterns like
openshift/*to scope profiles - Inline check buttons — retest buttons next to failed CI checks
- Failure log view — the log icon on a failed Prow check opens a scrollable, grep-filtered list of error lines from the job's actual failing step (falling back to image build logs / the ci-operator log), plus the Claude failure-analysis report when the job's
analyze-e2e-failurepost-step produced one; "Full log" opens everything in a modal - GitHub Actions rerun (optional) — one-click rerun for checks Prow doesn't own, via a self-supplied token — see below
- Dynamic commands — auto-generate buttons from failed check names (e.g.,
/pj-rehearse <job-name>) - Keyboard shortcuts — Alt+L for LGTM, Alt+A for Approve, Alt+R for Retest, Alt+T for Test picker, Alt+O for Override picker
- GitHub theme support — matches light/dark mode automatically
- SPA-aware — works with GitHub's Turbo/PJAX navigation
- Accessible — ARIA labels on all injected buttons and dialogs; screen-reader-friendly
| Profile | Match Pattern | Commands |
|---|---|---|
| Tide/Prow — Universal | * (all repos) |
/lgtm, /lgtm cancel, /approve, /approve cancel, /hold, /hold cancel, /retest, /retest-required, /test … (job picker), /override … (job picker), /cherry-pick … (branch picker; Chain picks toggle: parallel picks or a single sequential chain command, with drag/↑↓ reordering of the chain order), /cc @user, /uncc @user, /ok-to-test, /verified by/later/bypass/remove, /jira refresh/backport/cherrypick |
| Prow — OpenShift Release | openshift/release |
/pj-rehearse ack, /pj-rehearse <tests>… (job picker), /pj-rehearse (all) |
| OpenShift Payload Testing | openshift/* |
/payload, /payload-job, /payload-aggregate, /payload-with-prs, /payload-job-with-prs, /payload-aggregate-with-prs, /payload-abort |
| OpenShift Labels | openshift/*, openshift-priv/* |
/label shortcuts: cherry-pick-approved, backport-risk-assessed, qe-approved, docs-approved, px-approved, staff-eng-approved, tide/merge-method-*, jira/skip-dependent-bug-check |
| OpenShift Private (embargoed CVE) | openshift-priv/* |
/publicize |
| OpenShift Specialized | openshift/* |
/testwith, /testwith abort, /validate-backports, /pipeline required |
| Mergify | * (disabled by default) |
/mergify requeue, /mergify refresh |
| Changesets Bot | * (disabled by default) |
/changeset <type> |
| Dependabot | * (disabled by default) |
@dependabot rebase, @dependabot recreate, @dependabot merge, @dependabot squash and merge, @dependabot cancel merge, @dependabot reopen, @dependabot close, @dependabot ignore this major/minor version, @dependabot ignore this dependency |
| Claude | * (disabled by default) |
@claude <instruction> (free-form input), @claude review this PR, @claude fix this, @claude implement … |
| CodeRabbit AI | * (disabled by default) |
@coderabbitai full review, @coderabbitai review, @coderabbitai summary, @coderabbitai generate docstrings, @coderabbitai resolve, @coderabbitai pause, @coderabbitai resume, @coderabbitai help |
- Click the extension icon → Open Settings
- Scroll to Bot Profiles → click + Add Profile
- Fill in:
- Name — display name
- Repo Patterns — one glob pattern per line (e.g.,
myorg/*) - Commands — add global commands (always visible) and check commands (next to failed CI)
- Click Save
In Settings → Repo Overrides, you can:
- Add extra profiles for a specific repo
- Disable profiles for a specific repo
- Add one-off commands for a specific repo
Checks that are plain GitHub Actions jobs — not Prow ProwJobs — can't be
retriggered with /test (Prow doesn't own them, see Failing CI
Checks). Without any setup, the extension links to the
check's own Actions run page instead. To turn that into a real one-click
Rerun button:
- Click the extension icon → Open Settings
- Under Global Settings, paste a token into GitHub Personal Access
Token — use a fine-grained token scoped to just the repos you need,
with Actions: read and write permission only. A classic all-repo
repo-scope token also works but is broader than necessary. - Click Verify Token to confirm it's valid before relying on it.
The token is stored in chrome.storage.local — device-scoped, never synced
across Chrome profiles, and not included in Export/Import. It's read by the
background service worker only when you click Rerun, to call GitHub's
documented POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun API;
/override (which works with or without a token — see above) remains the way
to unblock a Tide-blocked merge on a check you can't rerun.
Settings → Global Settings → Live updates. github.tig.pw is an optional
host permission: the extension only requests it when you flip this toggle, and the
setting stays off if you decline. When enabled, the extension polls https://github.tig.pw/github-bot-command-palette/logic.json (at most
once a minute, ETag-revalidated) and applies data-only logic changes
without reloading the extension or the page:
- the checks-section and legacy check-row selectors (so a GitHub DOM change
can be fixed by pushing
live/logic.json, no release needed), - the failure-log grep patterns and error-line cap,
- a
versionnumber — bump it and the page re-renders with a toast.
live/logic.json in this repo is the source; every push to main touching
live/** is validated and deployed to GitHub Pages by
.github/workflows/deploy-live-logic.yml.
Only whitelisted JSON fields are read — the extension never fetches or
executes remote code (Manifest V3 forbids it). Real code changes in
content.js/background.js still require reloading the unpacked extension.
Prerequisite: this repo's Pages source must be GitHub Actions, with the
site reachable under the github.tig.pw Pages domain
(https://github.tig.pw/github-bot-command-palette/ for project pages).
- Export: Settings → Export Config (JSON) — downloads
ghbcp-config.json - Import: Settings → Import Config — upload a previously exported JSON file
- Reset: Settings → Reset to Defaults — restores built-in profiles
manifest.json — Chrome Manifest V3 config
background.js — Service worker: config fetch, plugin YAML parsing, presubmit job caching
config-manager.js — Configuration CRUD, storage, glob matching
prow-plugin-map.js — Static map of known Prow plugin commands
content.js — Main injection: DOM manipulation, button rendering, SPA listeners
styles.css — GitHub-themed styles (light/dark, responsive)
settings.html/js — Full settings page (profiles, commands, import/export)
popup.html/js — Toolbar popup (current repo, matched profiles)
icons/ — Extension icons (16/48/128px)
config-export.json — Sample config with all default profiles
vendor/ — Vendored third-party libraries (js-yaml)
tests/ — Unit and integration tests
See config-export.json for the full schema. Key types:
- BotProfile — name, repo patterns, global/check/dynamic commands
- BotCommand — label, command text, style, input support, keyboard shortcut
- DynamicCommandRule — JS expression evaluated with check context (testName, checkName)
The optional GitHub token is not part of
this schema — it lives in its own chrome.storage.local key, separate from
the synced config blob, and is therefore excluded from Export/Import.
- No
eval()— dynamic commands usenew Function()with scoped variables only - All user input sanitized before DOM insertion
- No network requests from the content script — it only talks to the background
service worker (
chrome.runtime.sendMessage), which makes all outbound calls - All config lives in
chrome.storage.sync, except the optional GitHub token, which lives inchrome.storage.local(device-scoped) precisely so it doesn't propagate to every Chrome profile signed into the same account - The background service worker calls
api.github.comwith that token only when you click Rerun / Verify Token — never automatically, and never with any other origin - Runs only on
https://github.com/*







