Permissions
A called reusable workflow cannot hold more GITHUB_TOKEN permissions than the caller grants, and most repos default to a read-only token. So workflows that need to write must have the caller grant it on the calling job. The stubs in examples/ already include the right permissions: blocks; copy them as-is.
Per-workflow grants
-
check-ai-tells,check-bibliography-dois,check-code-similarity,check-equation-renders,check-extra,check-formatting,check-junk-files,check-new-line-breaks,check-news,check-non-standard-chars,check-one-function-per-file,check-phi,check-secrets,check-typos,cursor-code-review,lint-changed-files,lint-changed-lines,lint-markdown,lint-qmd,lint-workflows,lint-yaml,preview,r-cmd-check,spellcheck,test-coverage,version-checkneed onlycontents: read(the default), so nopermissions:block is needed. This list is checked against the workflows’ ownpermissions:blocks by.github/workflows/scripts/tests/run-permissions-docs-tests.py; keep the markers around it. check-linksopens an issue onmainfailures, so grantissues: write,pull-requests: read,contents: read.summarycomments on issues and calls the models API, so grantissues: write,models: read,contents: read.update-snapshotspushes the snapshot-update commit back to the branch, so grantcontents: write.quarto-publishdeploys to thegh-pagesbranch, so grantcontents: write, and set Settings -> Pages -> Source to “Deploy from a branch”, branchgh-pages/(root)once. Grantcontents: writeeven withdeploy: false: the deploy job is part of the workflow, so the caller must grant its permissions even when it is skipped.preview-deploy(deploy half) pushesgh-pagesand comments, so grantcontents: write,pull-requests: write,actions: read. Thepreviewbuild half is read-only, above.check-equation-rendersdownloads the build artifact. It is read-only, above, but a caller that narrows below the read-only default token still needsactions: readalongsidecontents: read.check-newsreads the PR’s labels live for its skip-label exemption. It is read-only, above, but a caller that narrows below the read-only default token still needsissues: readandpull-requests: readalongsidecontents: read.version-checkreads the PR’s labels live for itsno version incrementexemption. It is read-only, above, but a caller that narrows below the read-only default token still needspull-requests: readalongsidecontents: read. Notissues: read: that scope alone returned 403 on the same call (gha#724), since GitHub authorizes a label read on an issue object that is a pull request against the pull-requests permission.cleanup-pr-previewscommits deletions togh-pages, so grantcontents: write,pull-requests: read.bump-submodule,sync-shared-fragments,sync-upstreamopen a PR, so grantcontents: write,pull-requests: write, and enable Settings -> Actions -> General -> “Allow GitHub Actions to create and approve pull requests”.report-failurefiles or updates the issue tracking a failing workflow, so grantissues: writeon the reporting job – and nothing else. It performs no checkout, so it needs nocontentsgrant; the job it watches keeps its own permissions.claudepushes branches, opens PRs, and dispatches the review workflow, so grantcontents: write,pull-requests: write,issues: write,id-token: write,actions: write, and add either theCLAUDE_CODE_OAUTH_TOKENorANTHROPIC_API_KEYsecret.claude-code-review(read-only review) grantscontents: read,pull-requests: write,issues: write,actions: read,checks: read(grant it; required by the currently-tagged@v2), and either theCLAUDE_CODE_OAUTH_TOKENorANTHROPIC_API_KEYsecret. The model job’sGITHUB_TOKENhas no write scopes (contents/pull-requests/issues/actions: read); write is confined to jobs that never run the model (gather-contextandpost-review) (gha#580).actions: readis required on the caller: apermissions:block sets unspecified scopes to none, andpost-reviewneeds it to download the packed artifact (the model job also uses it for thegithub_ciMCP server). Grantchecks: read, but note what it does and does not buy.actions: readcovers workflow runs but notGET .../commits/{ref}/check-runs, so without that scope the reviewer’s check-status reads fail with HTTP 403 and a clean diff can be reported as blocked (ucdavis/bcs#964). As of 2026-09-06 the@v2tag still points at a commit that DOES request the scope, which is why a caller lacking it fails at startup. Oncev2is slid onto this change the model job stops requesting it, and the 403 returns for everyone until thev3reinstates it. Keep the grant through all three phases: it is what makes a caller work today, it is harmless while the slid@v2ignores it, and it is what makes thev3cost nothing later. The startup failure is the reason the callee gave the scope up: a called workflow cannot request a permission its caller lacks, so the run ends before any job starts. That is how thev2slide for that grant broke 17 of the 18 repositories pinning this workflow at@v2(gha#831 carries the derivation; how many still lack the grant falls as consumers add it, and is tracked in gha#833 as thev3precondition rather than restated here).cursor-code-reviewqueues a Cursor Bugbot review. It is read-only, above, but does need theCURSOR_API_KEYsecret (Enterprise,admin:*scope).opencode-code-reviewis a read-only review that posts its own comment, so grantcontents: read,pull-requests: write,issues: write, and set theOPENCODE_API_KEYsecret (OpenCode Zen).ai-code-reviewselects the first available AI reviewer and dispatches its review workflow, so grantcontents: read,pull-requests: read,issues: read,actions: write, and pass the secrets of whichever agent review workflows are installed (seeexamples/ai-code-review.yml).issues: readis required since the delivery classifier’s comment scan landed (gha#638); a caller missing it fails at parse time with no API-visible diagnostic (gha#685).geminipushes branches, opens PRs, and dispatches the review workflow, so grantcontents: write,pull-requests: write,issues: write,id-token: write,actions: write, and add theGEMINI_API_KEYsecret.gemini-code-reviewposts the Gemini review, so grantcontents: read,pull-requests: write,issues: write,id-token: write, and theGEMINI_API_KEYsecret.antigravity-code-reviewposts the Antigravity review, so grantcontents: read,pull-requests: write,issues: write,id-token: write, and theGEMINI_API_KEYsecret.small-model-agentposts the small-model agent’s PR comment, so grantcontents: read,pull-requests: write.claude-manage-projectfiles issues and updates the project board, so grantcontents: read,issues: write,repository-projects: write, and add theCLAUDE_CODE_OAUTH_TOKENsecret (required).altdoc-multiversion-docsdeploys togh-pages, comments PR previews, and rewrites rendered links, so grantcontents: write,pull-requests: write, andissues: write, and set Settings -> Pages -> Source to “Deploy from a branch”, branchgh-pages/(root)once.request-dependabot-reviewrequests a reviewer on the PR, so grantpull-requests: write.bump-dev-versionopens (or auto-merges) a PR, so grantcontents: write,pull-requests: write, enable the same “Allow GitHub Actions to create and approve pull requests” setting as above, and (for its defaultauto-merge: true) “Allow auto-merge” too. Itsversion-checkcounterpart is read-only, above.
Optional secrets
WORKFLOW_TOKEN(a PAT or GitHub App token withcontents:write+workflows:write). The integratedGITHUB_TOKENcannot push changes to files under.github/workflows/; GitHub rejects them without theworkflowsscope. Add this secret ifclaudewill edit workflow files, to push to a protected branch, or – forbump-dev-versionwith its defaultauto-mergein a repo with required status checks – to let the bump PR’s checks run so it can merge (aGITHUB_TOKEN-authored PR’spull_requestchecks never report, so the merge stays blocked; see its reference page). UnlikeGITHUB_TOKEN, a PAT or App-token push does trigger otherpush-based workflows, so enabling it can set off extra CI runs. When the secret is absent andclaudedoes edit a workflow file, the rejected push is reported as an error naming this secret, and the commits are posted to the thread as agit format-patchso they survive the run.SUBMODULES_TOKEN. Public submodules clone anonymously; private ones need this secret. Relevant toclaude,claude-code-review,r-cmd-check, andbump-submodulewhencheckout-submodules(or the submodule update) touches a private submodule.
Notes for private consumers
Reusable workflows in this public repo are callable from public repos automatically. A private consumer must allow access to this repo under Settings -> Actions -> General -> Access before it can call these workflows.