GitHub Actions

Mention @bisque-cloud on a pull request, or publish a release; the explainer lands on bisque.today/p/{owner}/{repo}.

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

  1. Make a Claude Code token and store it as a repository secret. In a terminal where claude is installed:

    claude setup-token
    gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo OWNER/REPO
    

    The 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.

  2. 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: judged is 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-cloud on one to explain it, as set up below.

  3. Open a pull request that adds it. A pull_request workflow 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.

  1. 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: deny under with:. The agent then has no shell and no internet while it reads their text, and the explainer uses system fonts.

  2. 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.

  3. 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.

  1. 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 }}
    
  2. 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: under on: and pass its tag as tag: under with:.

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:

InputWhat writes the explainer
claude-code-oauth-tokenClaude Code on your Claude plan, its own default
google-api-keygemini-3.1-pro-preview
openai-api-keygpt-5.6-sol, medium effort
xai-api-keygrok-4.6
anthropic-api-keyclaude-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-cloud on it, or mark it ready for review.
  • It skipped one you wanted. Mention @bisque-cloud on it; a mention always explains.
  • No πŸ‘€ reaction. The workflow is not on the default branch, or the comment does not mention @bisque-cloud as a whole word: @bisque-cloudy or @bisque-cloud/presenter does not count.
  • The run fails at "Narrate on this runner and publish" about id-token. The workflow's permissions: block is missing id-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_TOKEN fails here; make a new one with claude setup-token.
  • The release notes have no link. The release workflow needs contents: write to edit them.

Every input is described in action.yml.