Here’s a minimal example that runs Mux in a GitHub Action:
- name: Mux Review env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: bunx mux run "Review this PR for critical issues. If any are found, exit with 1 to block merge."
mux run supports agent-controlled exit codes, so the workflow step can fail when issues are found.
This is the exact workflow used live in the Mux repo (see .github/workflows/auto-cleanup.yml). It runs periodically to identify low-risk cleanup opportunities and maintains a refactor PR with improvements.The prompt is stored in a separate file (.github/prompts/auto-cleanup.md) and piped via stdin, keeping the workflow file clean and the prompt easy to iterate on.Mux’s repo uses a workflow-specific repository secret (AUTO_CLEANUP_ANTHROPIC_API_KEY) for this job so auto-cleanup spend stays isolated from terminal-bench, while the runtime environment still uses the standard ANTHROPIC_API_KEY name.
# Periodically cleans up the codebase and maintains a refactor PR.# SETUP: Add AUTO_CLEANUP_ANTHROPIC_API_KEY, MUX_APP_PRIVATE_KEY, and MUX_APP_ID# to repository secrets so auto-cleanup spend stays isolated from terminal-bench.name: Auto-Cleanupon: schedule: - cron: "0 */4 * * *" # Every 4 hours workflow_dispatch:permissions: contents: write pull-requests: writejobs: cleanup: runs-on: ubuntu-latest steps: - name: Check required secrets id: precheck env: # Keep the runtime env name stable while routing spend to a dedicated key. ANTHROPIC_API_KEY: ${{ secrets.AUTO_CLEANUP_ANTHROPIC_API_KEY }} MUX_APP_ID: ${{ secrets.MUX_APP_ID }} MUX_APP_PRIVATE_KEY: ${{ secrets.MUX_APP_PRIVATE_KEY }} run: | missing=0 [ -z "$ANTHROPIC_API_KEY" ] && echo "Skipping (missing AUTO_CLEANUP_ANTHROPIC_API_KEY)." && missing=1 [ -z "$MUX_APP_ID" ] && echo "Skipping (missing MUX_APP_ID)." && missing=1 [ -z "$MUX_APP_PRIVATE_KEY" ] && echo "Skipping (missing MUX_APP_PRIVATE_KEY)." && missing=1 if [ "$missing" -eq 1 ]; then echo "enabled=false" >> "$GITHUB_OUTPUT" else echo "enabled=true" >> "$GITHUB_OUTPUT" fi - uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0 id: app-token if: ${{ steps.precheck.outputs.enabled == 'true' }} with: # Use a GitHub App token so PR events trigger CI. PRs opened via # GITHUB_TOKEN intentionally do not trigger other workflows. app-id: ${{ secrets.MUX_APP_ID }} private-key: ${{ secrets.MUX_APP_PRIVATE_KEY }} - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 if: ${{ steps.precheck.outputs.enabled == 'true' }} with: fetch-depth: 0 token: ${{ steps.app-token.outputs.token }} - uses: oven-sh/setup-bun@b7a1c7ccf290d58743029c4f6903da283811b979 # v2.1.0 if: ${{ steps.precheck.outputs.enabled == 'true' }} with: bun-version: 1.3.5 # Pin the git identity so the AI agent doesn't invent its own. # Without this, commits end up as "mux-auto-cleanup[bot]" while the # PR itself (created via the app token) is authored by "mux-bot[bot]". - name: Configure git identity if: ${{ steps.precheck.outputs.enabled == 'true' }} run: | git config user.name "mux-bot[bot]" git config user.email "264182336+mux-bot[bot]@users.noreply.github.com" - name: Cleanup with mux if: ${{ steps.precheck.outputs.enabled == 'true' }} env: ANTHROPIC_API_KEY: ${{ secrets.AUTO_CLEANUP_ANTHROPIC_API_KEY }} GH_TOKEN: ${{ steps.app-token.outputs.token }} run: | bunx mux@next run \ --model anthropic:claude-opus-4-7 \ --thinking xhigh \ < .github/prompts/auto-cleanup.md