Open a pull request and Claude Code decides whether it needs a watchable
walkthrough. The ones that do get one, linked in a comment a few minutes
later; a typo fix or a dependency bump gets a one-line note saying why it was
skipped. Mention @bisque-cloud on any pull request to get one on request,
and publish a release to have its notes gain one too.
It runs in your repository's GitHub Actions on your Claude Code subscription,
so writing an explainer is part of the plan you already pay for, with no API
bill. It signs in with GitHub: the workflow run's own GitHub identity
publishes to your repository's channel, bisque.today/p/{owner}/{repo}, so
there is no Bisque account and no Bisque key.
Hand it to your agent
Set up the Bisque pull request and release explainers on this repository by following https://bisque.today/docs/github.md
Your agent does the steps below. Making the token is yours, because only you can sign in to your Claude account.
On your Claude plan
One secret, CLAUDE_CODE_OAUTH_TOKEN, runs every explainer.
Claude Code decides which pull requests get one
-
Make a Claude Code token and store it as a repository secret. In a terminal where
claudeis installed:claude setup-token gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo OWNER/REPOThe first command opens a browser to sign in and prints a token. Paste it when the second asks. An agent should ask the person to run both and wait, and never read the token itself.
-
Add the workflow as
.github/workflows/explain-pull-requests.yml:name: Pull request explainer on: pull_request: types: [opened, ready_for_review, reopened] permissions: contents: read pull-requests: write # post the watch link, or why it was skipped id-token: write # sign in with GitHub to publish concurrency: group: explain-pull-request-${{ github.event.pull_request.number }} jobs: explain: if: >- !github.event.pull_request.draft && github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' runs-on: ubuntu-latest steps: - uses: bisque-cloud/presenter@v1 with: source: pull-request when: judged claude-code-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}when: judgedis the part that decides. Claude Code reads the pull request first and explains it when someone who did not write it would want the reasoning: a design decision, a new command or surface, a migration, a change across packages. It skips a dependency bump, formatting, a lockfile, a typo, a one-line fix, or a change only its author will read, and posts one comment saying why in a sentence. A skipped run passes, and nothing is published.It runs when a pull request opens, reopens, or leaves draft, and not on every push, so each pull request costs one Claude Code run. Pull requests from forks and from Dependabot are left out: GitHub gives those runs no secrets and a read-only token. Mention
@bisque-cloudon one to explain it, as set up below. -
Open a pull request that adds it. A
pull_requestworkflow runs from the pull request's own branch, so the pull request that adds this file is the first one judged, most likely as a skip.
On request, with a mention
Mention @bisque-cloud in a comment on a pull request and it is explained,
whatever Claude Code would have decided. This covers pull requests from forks,
and one that was skipped. It uses the same CLAUDE_CODE_OAUTH_TOKEN secret,
so set that up first. On its own, this is also the setup for a repository
that wants explainers only when someone asks.
-
Add the workflow as
.github/workflows/explain-on-mention.yml:name: Pull request explainer on mention on: issue_comment: types: [created] permissions: contents: read pull-requests: write # post the watch link as a comment issues: write # react to the comment that mentions @bisque-cloud id-token: write # sign in with GitHub to publish jobs: explain: if: >- github.event.issue.pull_request && contains(github.event.comment.body, '@bisque-cloud') runs-on: ubuntu-latest steps: - name: Check the mention and write access, and react so the commenter knows id: mention env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} ACTOR: ${{ github.actor }} COMMENT_ID: ${{ github.event.comment.id }} BODY: ${{ github.event.comment.body }} run: | if ! grep -Eiq '(^|[[:space:]])@bisque-cloud([[:space:].,!?;:]|$)' <<<"$BODY"; then echo "No @bisque-cloud mention."; exit 0 fi perm="$(gh api "repos/$REPO/collaborators/$ACTOR/permission" --jq .permission)" case "$perm" in write|maintain|admin) echo "$ACTOR: $perm" ;; *) echo "::error::$ACTOR has '$perm' permission; @bisque-cloud needs write."; exit 1 ;; esac gh api --silent -X POST \ "repos/$REPO/issues/comments/$COMMENT_ID/reactions" -f content=eyes echo "explain=true" >> "$GITHUB_OUTPUT" - if: steps.mention.outputs.explain == 'true' uses: bisque-cloud/presenter@v1 with: source: pull-request claude-code-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}If the repository takes pull requests from people you do not know, add
network: denyunderwith:. The agent then has no shell and no internet while it reads their text, and the explainer uses system fonts. -
Commit it to the default branch. GitHub runs comment-triggered workflows from the default branch only, so a workflow on a feature branch does nothing yet.
-
Try it. On an open pull request, comment
@bisque-cloud explain this. The mention is what starts it; the rest of the comment is not read. An π reaction appears within a minute, and the reply with the watch link follows several minutes later. Only people with write access can start one.
Release explainers
It uses the same CLAUDE_CODE_OAUTH_TOKEN secret as the pull request
explainers.
-
Add the workflow as
.github/workflows/explain-releases.yml:name: Release explainer on: release: types: [published] permissions: contents: write # append the watch link to the release notes id-token: write # sign in with GitHub to publish jobs: explain: runs-on: ubuntu-latest steps: - uses: bisque-cloud/presenter@v1 with: claude-code-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} -
Publish a release. The agent reads its notes and the diff since the previous tag, and a few minutes later the watch link is appended to the notes. To explain a release you already published, add
workflow_dispatch:underon:and pass its tag astag:underwith:.
Change the voice
Every explainer speaks in kokoro:af_heart. To use another voice, add it
under with:, engine first:
with:
source: pull-request
claude-code-oauth-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
voice: kokoro:am_michael
The Kokoro voices start with the accent and gender, then a name:
af_ and am_ are American, bf_ and bm_ British, for example
kokoro:bf_emma or kokoro:bm_george. The voice is downloaded on the first
run and cached.
With another model
The pull request and release explainers run on a Claude Code subscription by default. Without one, give them an API key from Google, OpenAI, xAI or Anthropic instead. Everything else is the same: they still sign in with GitHub to publish, so there is still no Bisque account and no Bisque key.
Swap the token for a key
Store the key as a repository secret, then pass it in place of
claude-code-oauth-token in either workflow:
gh secret set GOOGLE_API_KEY --repo OWNER/REPO
- uses: bisque-cloud/presenter@v1
with:
google-api-key: ${{ secrets.GOOGLE_API_KEY }}
The key names the provider, and the provider picks the model:
| Input | What writes the explainer |
|---|---|
claude-code-oauth-token | Claude Code on your Claude plan, its own default |
google-api-key | gemini-3.1-pro-preview |
openai-api-key | gpt-5.6-sol, medium effort |
xai-api-key | grok-4.6 |
anthropic-api-key | claude-opus-5, medium effort |
Set one. An API key is billed by its provider for each explainer, where a Claude plan token counts against the plan you already pay for.
Pick a different model
Add model: with any provider/model id from models.dev,
from the provider whose key you set, for example
model: anthropic/claude-sonnet-4-6 with an Anthropic key to spend less. variant: sets reasoning
effort where the provider has one.
How the key is kept from the agent
The agent never holds the key. Its model calls go through a local proxy that holds it and rewrites the auth header, so it is in no environment the agent or its tools can read. The means to mint the run's GitHub identity is removed from the agent's step too, and the publishing step refuses to run a skill whose hash changed while the agent ran.
Where explainers live
A public repository's explainers are public on bisque.today/p/{owner}/{repo},
next to the GitHub path you already know: release v1.2.0 of acme/widgets
is at bisque.today/p/acme/widgets/v1-2-0. Mentioning @bisque-cloud again
on the same pull request, or re-running a release's workflow, replaces that
explainer rather than adding a second one. A pull request keeps one comment
from the explainer: a later explainer replaces a skip note, and a later skip
leaves an existing explainer in place.
A private repository's explainers are private. Anyone who can open the repository on GitHub watches them after choosing Sign in with GitHub. Their access is checked against GitHub again at least every 12 hours, so someone removed from the repository loses its explainers too.
Manage the channel
Open bisque.today/p/{owner}/{repo} and choose Sign in with GitHub, as an
admin of the repository. The channel then carries your GitHub name, and you
can delete an explainer or open its analytics. Signing in is optional;
explainers publish either way.
What it costs
Writing an explainer is one Claude Code run, counted like any other use of
your plan. With when: judged, a skipped pull request is a shorter run that
stops after reading it. Narration runs on the GitHub runner, which is free on
a public repository and a few minutes of Actions time on a private one.
Publishing and hosting are free.
If something looks wrong
- A pull request got no comment at all. It was a draft, came from a fork
or Dependabot, or was opened before the workflow reached the default
branch. Mention
@bisque-cloudon it, or mark it ready for review. - It skipped one you wanted. Mention
@bisque-cloudon it; a mention always explains. - No π reaction. The workflow is not on the default branch, or the comment
does not mention
@bisque-cloudas a whole word:@bisque-cloudyor@bisque-cloud/presenterdoes not count. - The run fails at "Narrate on this runner and publish" about
id-token. The workflow'spermissions:block is missingid-token: write. - The run fails while authoring. The job log shows what the agent did, and
the run's artifacts hold its working files. An expired or revoked
CLAUDE_CODE_OAUTH_TOKENfails here; make a new one withclaude setup-token. - The release notes have no link. The release workflow needs
contents: writeto edit them.
Every input is described in
action.yml.