Claude Code workflow (storybookjs/storybook)
The Claude Code workflow from storybookjs/storybook, explained and optimized by Latchkey.
A
CI health: A - excellent
Point runs-on at Latchkey and get job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Claude Code workflow from the storybookjs/storybook repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
workflow (.yml)
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
# Only org OWNERs and MEMBERs may trigger Claude. author_association is set by
# GitHub on the comment/review/issue payload; everything else (COLLABORATOR,
# CONTRIBUTOR, FIRST_TIME_CONTRIBUTOR, NONE) is rejected.
if: |
(github.event_name == 'issue_comment' &&
contains(github.event.comment.body, '@claude') &&
contains(fromJSON('["OWNER", "MEMBER"]'), github.event.comment.author_association)) ||
(github.event_name == 'pull_request_review_comment' &&
contains(github.event.comment.body, '@claude') &&
contains(fromJSON('["OWNER", "MEMBER"]'), github.event.comment.author_association)) ||
(github.event_name == 'pull_request_review' &&
contains(github.event.review.body, '@claude') &&
contains(fromJSON('["OWNER", "MEMBER"]'), github.event.review.author_association)) ||
(github.event_name == 'issues' && (
(github.event.action == 'opened' &&
contains(fromJSON('["OWNER", "MEMBER"]'), github.event.issue.author_association) &&
(contains(github.event.issue.body, '`@claude`') || contains(github.event.issue.title, '`@claude`'))) ||
(github.event.action == 'assigned' && github.event.assignee.login == 'claude')
))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1
persist-credentials: false
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@a92e7c70a4da9793dc164451d829089dc057a464 # v1.0.159
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
assignee_trigger: 'claude'
base_branch: 'next'
prompt: 'Respect the PR description template and repository guidelines in AGENTS.md.'
# Allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Tool permissions Claude needs to follow AGENTS.md (install, compile,
# typecheck, lint, format, test). Bash is NOT allowed by default, so
# without this Claude cannot run any of the repo's build/test commands.
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
claude_args: |
--allowed-tools "Bash(yarn:*),Bash(cd:*),Bash(node:*),Bash(git status:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*)"
--disallowed-tools "Bash(yarn start),Bash(yarn task dev)"
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Claude Code on: issue_comment: types: [created] pull_request_review_comment: types: [created] issues: types: [opened, assigned] pull_request_review: types: [submitted] jobs: claude: timeout-minutes: 30 # Only org OWNERs and MEMBERs may trigger Claude. author_association is set by # GitHub on the comment/review/issue payload; everything else (COLLABORATOR, # CONTRIBUTOR, FIRST_TIME_CONTRIBUTOR, NONE) is rejected. if: | (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') && contains(fromJSON('["OWNER", "MEMBER"]'), github.event.comment.author_association)) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && contains(fromJSON('["OWNER", "MEMBER"]'), github.event.comment.author_association)) || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && contains(fromJSON('["OWNER", "MEMBER"]'), github.event.review.author_association)) || (github.event_name == 'issues' && ( (github.event.action == 'opened' && contains(fromJSON('["OWNER", "MEMBER"]'), github.event.issue.author_association) && (contains(github.event.issue.body, '`@claude`') || contains(github.event.issue.title, '`@claude`'))) || (github.event.action == 'assigned' && github.event.assignee.login == 'claude') )) runs-on: latchkey-small permissions: contents: read pull-requests: read issues: read id-token: write actions: read # Required for Claude to read CI results on PRs steps: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 1 persist-credentials: false - name: Run Claude Code id: claude uses: anthropics/claude-code-action@a92e7c70a4da9793dc164451d829089dc057a464 # v1.0.159 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} assignee_trigger: 'claude' base_branch: 'next' prompt: 'Respect the PR description template and repository guidelines in AGENTS.md.' # Allows Claude to read CI results on PRs additional_permissions: | actions: read # Tool permissions Claude needs to follow AGENTS.md (install, compile, # typecheck, lint, format, test). Bash is NOT allowed by default, so # without this Claude cannot run any of the repo's build/test commands. # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md # or https://code.claude.com/docs/en/cli-reference for available options claude_args: | --allowed-tools "Bash(yarn:*),Bash(cd:*),Bash(node:*),Bash(git status:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*)" --disallowed-tools "Bash(yarn start),Bash(yarn task dev)"
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Add a job timeout so a hung step cannot burn hours of runner time.
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.