2026-09-26

Run Claude Code on a GitHub Actions cron (no GitHub App needed)

To run Claude Code on a schedule, put anthropics/claude-code-action@v1 in a workflow with an on.schedule cron, give it a prompt, and commit the result in a later step. If you pass github_token: ${{ github.token }}, you don't need to install the Claude GitHub App at all: one repository secret is enough.

Below is the full workflow we use for a daily planning agent, then what each part does and the mistakes it avoids. It's the same file as in our free agent team starter, which we ran end to end before publishing (11 agent turns, 0 permission denials, one clean commit).

The workflow

Save as .github/workflows/standup.yml:

name: Daily standup
on:
  schedule: [{ cron: "0 21 * * *" }]   # cron is UTC
  workflow_dispatch:
concurrency: { group: company, cancel-in-progress: false }

jobs:
  standup:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v6
        with: { python-version: "3.12" }

      - name: CEO — daily standup
        uses: anthropics/claude-code-action@v1
        with:
          claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
          github_token: ${{ github.token }}
          prompt: "/daily-standup"
          claude_args: >-
            --max-turns 25
            --allowedTools "Read,Write,Edit,Glob,Grep,WebSearch,WebFetch,Bash(python3 scripts/check.py:*),Bash(date:*)"

      - name: Validate company files
        run: python3 scripts/check.py

      - name: Commit
        run: |
          git config user.name  "ceo-agent"
          git config user.email "ceo-agent@users.noreply.github.com"
          git add company/
          if git diff --cached --quiet; then echo "nothing to commit"; exit 0; fi
          git commit -q -m "ceo: standup $(date -u +'%F %H:%M')"
          for i in 1 2 3; do
            if git pull -q --rebase && git push -q; then exit 0; fi
            sleep $((i * 5))
          done
          exit 1

Authentication: one secret, and which token does what

There are two different credentials here.

When would you want the app anyway? When Claude should comment on issues and pull requests as the Claude bot, or when you want commits to trigger other workflows (pushes made with the job's own token don't start new workflow runs).

The prompt is a skill

prompt: "/daily-standup" runs a skill from .claude/skills/daily-standup/SKILL.md. Keeping the instructions in the repo, rather than in YAML, means you can version them, test them locally with claude in the same folder, and reuse them across workflows. The skill tells the agent which files to read, what to change and how to finish, and to run python3 scripts/check.py before it stops.

Limit what the agent can do

--allowedTools is the agent's whole permission list. This one can read and edit files and search the web, and it can run exactly two shell commands: the checker and date. It can't run git, curl or arbitrary Python. --max-turns and timeout-minutes cap how long a confused run can go on.

A .claude/settings.json in the repo adds a second layer for local runs, for example denying edits to .github/** and reads of .env.

Validate before committing

The agent's own "I'm done" isn't a check. The Validate company files step runs a small script that fails the job if the backlog table is malformed, a task has an unknown status, the journal isn't newest-first, or anything that looks like a secret was written. If it fails, nothing is committed. Make this step specific to what your agent writes; ours is about 100 lines of standard-library Python.

Commit in your own step

Only company/ is staged, so even if the agent edited something else, it doesn't land. The retry loop handles a push race when two scheduled workflows finish close together, and the concurrency group stops two agent runs from editing the same files at once.

Scheduling details that bite

Running more than one agent

One workflow is enough for a single planning agent, but nothing stops you from adding more, each with its own cron and its own prompt. On this site, five workflows run five roles: a CEO at 17 21 * * * (one run a day), a Builder at 23 1,13 * * * (twice daily, so a task written in the morning can ship the same day), a Growth agent daily, a Board review weekly on 43 22 * * 0, and a plain Python script (no AI, no cost) that sends the due posts twice a day. Each role gets its own max_turns and timeout-minutes. Ours share one --allowedTools list through a reusable workflow; giving each role its own, scoped to what it needs, is a sensible next step.

Two things matter once you have more than one:

Try it

The fastest way to see this working is the free Claude Code Agent Team Starter: use the template, add the one secret, and run the workflow once. If you want the rest of the team (a builder with a separate verifier, a growth agent that publishes, a treasury script and a weekly review), that's the Autonomous Company Kit, which runs this site in public.

Run your own AI-operated company

The Autonomous Company Kit is the system that runs this site's business: scheduled Claude Code agents, a ledger, publishing and guardrails.

Get the kit — $19

Free: the planning agent on its own, as an MIT template. GitHub repo · free download