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
-
annotation-gate,check-ai-tells,check-code-messages,check-bibliography-dois,check-code-similarity,check-dependency-graph,check-duplicate-roxygen,check-equation-renders,check-extra,check-formatting,check-informal-definitions,check-junk-files,check-literal-math-letters,check-wikipedia-further-reading,check-redundant-citations,check-self-credits,check-one-div-per-subfile,check-heading-levels,check-heading-titles,check-self-reference,check-page-length,check-heading-siblings,check-figure-placement,check-div-ids,check-multipart-exercises,check-rubric-checklists,check-single-ask-parts,check-split-solutions,check-restated-results,check-extracted-lemmas,check-definition-equations,check-hybrid-sentences,check-format-output-files,check-def-title-synonyms,check-bare-yes-no,check-serial-comma,check-exercise-background,check-exercise-question-paragraph,check-key-equations-displayed,check-definite-antecedents,check-pr-concerns,check-pr-size,check-caller-permissions,check-exm-figures,check-contour-3d,check-axis-titles,check-visualization-figures,check-tree-lists,check-search-shortcut,check-self-contained-captions,check-def-commentary,check-unexplained-contrasts,check-unexplained-choices,check-solution-citations,check-exercise-before-result,check-term-links,check-paired-file-change,check-local-macros,check-fform-paren,check-macro-expansions,check-write-idiom,check-avoided-words,check-proof-statements,check-math-definitions,check-merge-drops,check-note-sheet-rows,check-new-line-breaks,check-news,check-non-standard-chars,check-one-function-per-file,check-orphaned-images,check-phi,check-python-package,check-quarto-book,check-quarto-links,check-quarto-manuscript,check-quarto-prose,check-quarto-website,check-r-package,check-repo-hygiene,check-secrets,check-source-overlap,check-typed-output,check-typos,cursor-code-review,lint-changed-files,lint-changed-lines,lint-markdown,lint-qmd,lint-workflows,lint-yaml,preview,r-cmd-check,spellcheck,student-qmd,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, so grantissues: write,contents: read.cancel-supersededcancels other runs of the pull request, so grantactions: write,pull-requests: 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-pagesand queries workflow runs to verify deployment before pruning merged PR previews, so grantcontents: write,pull-requests: read,actions: read.bump-submodule,sync-shared-fragments,sync-upstream,update-quarto-extensionsopen 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; optional under@v2, which no longer requests it per gha#832, but required by the model job as of@v3), and either theCLAUDE_CODE_OAUTH_TOKENorANTHROPIC_API_KEYsecret. The model job’sGITHUB_TOKENhas no write scopes (contents/pull-requests/issues/actions/checks: 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: readregardless of which tag you pin, but note what it does and does not buy.actions: readcovers workflow runs but notGET .../commits/{ref}/check-runs, so withoutchecks: readthe reviewer’s check-status reads fail with HTTP 403 and a clean diff can be reported as blocked (ucdavis/bcs#964). The model job briefly lost this scope on@v2: a called workflow cannot request a permission its caller lacks, so the run ends instartup_failurebefore any job begins, and@v2’s original grant ofchecks: readon the model job broke startup for 17 of the 18 repositories pinning this workflow at@v2that had not yet added the caller-side grant above (gha#831). Dropping the scope from the model job un-broke those callers but reopened the 403 for everyone – which is whatv3fixes by reinstating it there, now that the caller-side grant above is established practice. Keep grantingchecks: readregardless: it is optional under the currently-tagged@v2(which no longer requests it, per gha#832) but required by the model job once you adopt@v3. A Dependabot bump from@v2to@v3is where a missing grant shows up, and it shows up as an absence: the bumped run ends instartup_failure, so the PR carries no review check at all rather than a red one. Addchecks: readto the caller job in that same PR before merging it (gha#1006; measured on Morrison-Lab/mds#78).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).opposition-researchmines competitor feature demand and files opportunity issues, so grantcontents: read,issues: write, and pass eitherCLAUDE_CODE_OAUTH_TOKENorANTHROPIC_API_KEY.check-dependency-updatesaudits dependencies and files update issues, so grantcontents: read,issues: write, and pass eitherCLAUDE_CODE_OAUTH_TOKENorANTHROPIC_API_KEY.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.