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-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-check need only contents: read (the default), so no permissions: block is needed. This list is checked against the workflows’ own permissions: blocks by .github/workflows/scripts/tests/run-permissions-docs-tests.py; keep the markers around it.
  • check-links opens an issue on main failures, so grant issues: write, pull-requests: read, contents: read.
  • summary comments on issues and calls the models API, so grant issues: write, models: read, contents: read.
  • update-snapshots pushes the snapshot-update commit back to the branch, so grant contents: write.
  • quarto-publish deploys to the gh-pages branch, so grant contents: write, and set Settings -> Pages -> Source to “Deploy from a branch”, branch gh-pages / (root) once. Grant contents: write even with deploy: 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) pushes gh-pages and comments, so grant contents: write, pull-requests: write, actions: read. The preview build half is read-only, above.
  • check-equation-renders downloads the build artifact. It is read-only, above, but a caller that narrows below the read-only default token still needs actions: read alongside contents: read.
  • check-news reads 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 needs issues: read and pull-requests: read alongside contents: read.
  • version-check reads the PR’s labels live for its no version increment exemption. It is read-only, above, but a caller that narrows below the read-only default token still needs pull-requests: read alongside contents: read. Not issues: 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-previews commits deletions to gh-pages, so grant contents: write, pull-requests: read.
  • bump-submodule, sync-shared-fragments, sync-upstream open a PR, so grant contents: write, pull-requests: write, and enable Settings -> Actions -> General -> “Allow GitHub Actions to create and approve pull requests”.
  • report-failure files or updates the issue tracking a failing workflow, so grant issues: write on the reporting job – and nothing else. It performs no checkout, so it needs no contents grant; the job it watches keeps its own permissions.
  • claude pushes branches, opens PRs, and dispatches the review workflow, so grant contents: write, pull-requests: write, issues: write, id-token: write, actions: write, and add either the CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY secret.
  • claude-code-review (read-only review) grants contents: read, pull-requests: write, issues: write, actions: read, and either the CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY secret. The model job’s GITHUB_TOKEN has no write scopes (contents / pull-requests / issues / actions: read); write is confined to jobs that never run the model (gather-context and post-review) (gha#580). actions: read is required on the caller: a permissions: block sets unspecified scopes to none, and post-review needs it to download the packed artifact (the model job also uses it for the github_ci MCP server).
  • cursor-code-review queues a Cursor Bugbot review. It is read-only, above, but does need the CURSOR_API_KEY secret (Enterprise, admin:* scope).
  • opencode-code-review is a read-only review that posts its own comment, so grant contents: read, pull-requests: write, issues: write, and set the OPENCODE_API_KEY secret (OpenCode Zen).
  • ai-code-review selects the first available AI reviewer and dispatches its review workflow, so grant contents: read, pull-requests: read, issues: read, actions: write, and pass the secrets of whichever agent review workflows are installed (see examples/ai-code-review.yml). issues: read is 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).
  • gemini pushes branches, opens PRs, and dispatches the review workflow, so grant contents: write, pull-requests: write, issues: write, id-token: write, actions: write, and add the GEMINI_API_KEY secret.
  • gemini-code-review posts the Gemini review, so grant contents: read, pull-requests: write, issues: write, id-token: write, and the GEMINI_API_KEY secret.
  • antigravity-code-review posts the Antigravity review, so grant contents: read, pull-requests: write, issues: write, id-token: write, and the GEMINI_API_KEY secret.
  • small-model-agent posts the small-model agent’s PR comment, so grant contents: read, pull-requests: write.
  • claude-manage-project files issues and updates the project board, so grant contents: read, issues: write, repository-projects: write, and add the CLAUDE_CODE_OAUTH_TOKEN secret (required).
  • altdoc-multiversion-docs deploys to gh-pages, comments PR previews, and rewrites rendered links, so grant contents: write, pull-requests: write, and issues: write, and set Settings -> Pages -> Source to “Deploy from a branch”, branch gh-pages / (root) once.
  • request-dependabot-review requests a reviewer on the PR, so grant pull-requests: write.
  • bump-dev-version opens (or auto-merges) a PR, so grant contents: write, pull-requests: write, enable the same “Allow GitHub Actions to create and approve pull requests” setting as above, and (for its default auto-merge: true) “Allow auto-merge” too. Its version-check counterpart is read-only, above.

Optional secrets

  • WORKFLOW_TOKEN (a PAT or GitHub App token with contents:write + workflows:write). The integrated GITHUB_TOKEN cannot push changes to files under .github/workflows/; GitHub rejects them without the workflows scope. Add this secret if claude will edit workflow files, to push to a protected branch, or – for bump-dev-version with its default auto-merge in a repo with required status checks – to let the bump PR’s checks run so it can merge (a GITHUB_TOKEN-authored PR’s pull_request checks never report, so the merge stays blocked; see its reference page). Unlike GITHUB_TOKEN, a PAT or App-token push does trigger other push-based workflows, so enabling it can set off extra CI runs. When the secret is absent and claude does edit a workflow file, the rejected push is reported as an error naming this secret, and the commits are posted to the thread as a git format-patch so they survive the run.
  • SUBMODULES_TOKEN. Public submodules clone anonymously; private ones need this secret. Relevant to claude, claude-code-review, r-cmd-check, and bump-submodule when checkout-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.