Fetch Claude Code Docs #1346
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Fetch Claude Code Docs | |
| on: | |
| schedule: | |
| # Four times daily: 01:00, 06:00, 11:00, 16:00 UTC (aligned with hn-digest) | |
| - cron: "0 1,6,11,16 * * *" | |
| workflow_dispatch: # Allow manual trigger | |
| jobs: | |
| fetch-docs: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| actions: read | |
| id-token: write | |
| env: | |
| AWS_REGION: us-west-2 | |
| steps: | |
| - name: Generate GitHub App token | |
| id: app-token | |
| uses: actions/create-github-app-token@v2 | |
| with: | |
| app-id: ${{ secrets.APP_ID }} | |
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | |
| # Make the writable token the default for all later steps in this job | |
| - name: Export token for subsequent steps | |
| run: echo "GITHUB_TOKEN=${{ steps.app-token.outputs.token }}" >> "$GITHUB_ENV" | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ steps.app-token.outputs.token }} | |
| - name: Install uv and Python 3.14t | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: "3.14t" | |
| enable-cache: "true" | |
| cache-python: "true" | |
| - name: Fetch all Anthropic docs | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | |
| run: uv run scripts/fetcher.py | |
| - name: Setup GitHub CLI and Git | |
| run: | | |
| gh --version | |
| git --version | |
| git config --global user.name "claude-yolo[bot]" | |
| git config --global user.email "claude-yolo@lroole.com" | |
| - name: Claude handles everything | |
| # Pinned: @main changed claude_args parsing in June 2026 and silently | |
| # broke 'Bash(gh pr:*)' (split on the space into two invalid rules) | |
| # -> 3 weeks of pushed branches with no PRs. Tool permissions now live | |
| # in .claude/settings.json, which survives arg-parsing changes. | |
| uses: anthropics/claude-code-action@v1.0.168 | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | |
| with: | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| github_token: ${{ steps.app-token.outputs.token }} | |
| allowed_bots: "claude-yolo[bot]" | |
| claude_args: | | |
| --model claude-sonnet-4-6 | |
| --mcp-config '{ | |
| "mcpServers": { | |
| "barkme": { | |
| "command": "npx", | |
| "args": ["@vibeworks/barkme-mcp-server"], | |
| "env": { | |
| "LOG_LEVEL": "error", | |
| "BARK_DEVICES": "${{ secrets.BARK_DEVICES }}", | |
| "BARK_SERVER": "${{ secrets.BARK_SERVER }}", | |
| "BARK_GROUP": "Claude YOLO", | |
| "BARK_ICON": "https://avatars.githubusercontent.com/in/1452392", | |
| "BARK_RETRY": "3", | |
| "BARK_ASYNC": "false" | |
| } | |
| } | |
| } | |
| }' | |
| prompt: | | |
| You're an AI agent responsible for fetching and evaluating Anthropic documentation updates. Think like a news editor - you decide what's worth publishing. | |
| ## YOUR ROLE | |
| You're the overnight docs fetcher (night shift claude-yolo) who runs at 23:45 Pacific Time. | |
| You run after Anthropic engineers push their updates and go home for the day. | |
| Your day shift colleague (also you) will review your PRs in the morning. | |
| You decide if humans need to wake up for this or not. | |
| ## WHY YOU EXIST | |
| Docs change constantly. Most changes are noise. Your job: filter signal from noise. | |
| ## CONTENT SOURCES | |
| The fetcher archives from multiple sources: | |
| - `content/en/docs/claude-code/` - Claude Code + Agent SDK docs | |
| - `content/en/api/` - API reference (1500+ docs) | |
| - `content/en/build-with-claude/` - Platform features | |
| - `content/mcp/` - MCP protocol spec | |
| - `content/blog/` - FROZEN archive (anthropic.com is HTML-only; no longer fetched) | |
| - `content/github/` - GitHub repos (cookbooks, skills, plugins, courses) | |
| - `content/support/` - Support articles (sitemap + .md) | |
| ## YOUR WORKFLOW | |
| 1. **Check what changed** (`git status`) | |
| WHY: No changes = go back to sleep | |
| 2. **Understand the changes** (`git diff`) | |
| WHY: Context determines importance | |
| 3. **Decide importance** | |
| WHY: Different changes need different handling | |
| ## DECISION CRITERIA (based on WHY it matters) | |
| This repo is an archive: EVERY fetched change gets committed. | |
| main is push-protected (branch ruleset, no bypass), so all | |
| changes travel through a PR - even minor ones. What varies is | |
| whether humans hear about it: | |
| **PR + leave open for day shift** (WHY: humans need to know): | |
| - Version updates in content/claude-code-manifest.json | |
| - New features documented in claude-code or agent-sdk docs | |
| - CHANGELOG additions | |
| - API changes or new API endpoints | |
| - Breaking changes | |
| - Security-related updates | |
| - New MCP spec versions | |
| **PR + self-merge immediately** (WHY: archive freshness, zero human value): | |
| - Only github/ mirror or support/ content changed | |
| - Only .metadata.json / timestamps changed | |
| - Typo fixes, formatting tweaks, dead links, minor wording | |
| If `git status` is completely clean: nothing to do, exit 0. | |
| ## HOW TO HANDLE | |
| IMPORTANT - invoke the PR script as ONE single line: no | |
| backslash line-continuations, no $( ) command-substitution | |
| wrapper. The permission allowlist matches command prefixes, | |
| and a multi-line command is silently DENIED (this exact | |
| failure stalled the pipeline in July 2026). | |
| **For meaningful changes (PR for day shift)**: | |
| ```bash | |
| ./scripts/create-docs-pr.sh "{key feature}" "{why it matters}" "{version}" | |
| ``` | |
| The script prints the PR URL on its last line. Then barkme. | |
| **For minor changes (PR + immediate self-merge)**: | |
| ```bash | |
| ./scripts/create-docs-pr.sh "{what} (minor)" "{one-line why}" "{version}" | |
| gh pr merge {pr-url} --rebase | |
| ``` | |
| No barkme for minor self-merges. | |
| ## OUTPUT STYLE | |
| - Focus on WHY changes matter, not WHAT changed | |
| - Lead with the most interesting bit | |
| - Skip the obvious ("files were updated" duh) | |
| - One-line summaries when possible | |
| ## HANDOFF PROTOCOL | |
| When creating PRs, remember your day-shift self will: | |
| 1. Review your work (don't worry, they trust you) | |
| 2. Enhance descriptions if needed | |
| 3. Create tracking issues for version updates | |
| 4. Merge if everything looks good | |
| So make their job easy: | |
| - Clear PR titles with version numbers | |
| - Focus on WHY in descriptions | |
| - Highlight the interesting bits | |
| ## BARKME PROTOCOL (nightshift notifications) | |
| Bark AFTER the PR exists, never before: | |
| - Only notify once gh pr create / create-docs-pr.sh returned a real PR URL | |
| - Title: "📦 Claude Code v{version}" | |
| - Body: "{key feature}" | |
| - URL: the actual PR link (verify it is non-empty before barking) | |
| If push or PR creation fails: bark a failure alert instead | |
| ("🚨 docs pipeline: {step} failed - needs human") and exit non-zero. | |
| A notification without a PR behind it is worse than no notification. | |
| Keep it SHORT - day shift will do detailed analysis later. | |
| Remember: You're not a changelog generator. You're a smart filter that understands WHY changes matter to humans using Claude Code. | |
| [>be me >11:45pm Pacific docs checker >Anthropic devs are asleep >catching their fresh updates >day shift will handle the rest] | |
| # Tripwire: a pushed branch without a PR, or changes left uncommitted, | |
| # means the agent step silently failed. Fail loudly instead of lying green. | |
| # (June 2026 incident: 31 orphan branches, zero PRs, all runs green.) | |
| - name: Verify outcome | |
| env: | |
| GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} | |
| run: | | |
| BRANCH=$(git branch --show-current) | |
| if [ -n "$(git status --porcelain)" ]; then | |
| echo "::error::Workspace has uncommitted changes after agent step" | |
| git status --short | head -20 | |
| exit 1 | |
| fi | |
| if [ "$BRANCH" != "main" ] && [ -n "$BRANCH" ]; then | |
| # --state all: minor PRs are self-merged (and their branch | |
| # auto-deleted) before this step runs - that is success, not failure | |
| PRS=$(gh pr list --head "$BRANCH" --state all --json number --jq 'length') | |
| if [ "$PRS" = "0" ]; then | |
| echo "::error::Branch $BRANCH pushed but no PR exists - PR creation silently failed" | |
| exit 1 | |
| fi | |
| fi |