Tools

act: run GitHub Actions locally and stop the fix-ci commit loop

TL;DR

act reads .github/workflows and runs jobs in Docker containers on your machine. act -l lists, act -j runs one job, -s or --secret-file passes secrets. It is not identical to GitHub, so guard deploy steps with the ACT variable.

The familiar way to fix GitHub Actions: edit the YAML, commit "fix ci", push, wait a few minutes, see it fail, repeat. Your history fills with "fix ci 2", "fix ci 3", and each loop costs minutes. act runs GitHub Actions workflows on your own machine: it reads .github/workflows/, spins up Docker containers matching the runners, and executes the steps as GitHub would. The feedback loop drops from minutes to seconds.

GitHub page of nektos/act
GitHub page of nektos/act (screenshot, November 2026)

GitHub: https://github.com/nektos/act · about 73k stars · Go · MIT

Installation

brew install act                         # macOS/Linux
gh extension install nektos/gh-act       # use it as "gh act"

act needs Docker running. On first run, act asks you to pick a default runner image: Micro (small, missing many tools), Medium (balanced, enough for most) or Large (closest to GitHub's runners but tens of GB). The choice is saved in an .actrc file.

Basic usage

act -l                     # list every job and its trigger events
act                        # run workflows triggered by push
act pull_request           # simulate a pull_request event
act -j test                # run only the job named "test"
act -W .github/workflows/ci.yml   # run only one workflow file
act -n                     # dry run: show what would happen

Secrets, variables and events

NeedHow
Pass one secretact -s GITHUB_TOKEN="$(gh auth token)"
Many secrets from a fileact --secret-file .secrets (.env format; add it to .gitignore)
vars.* variablesact --var ENV=staging or --var-file
A specific event payloadact pull_request -e event.json with JSON mimicking a PR
Different image for a runneract -P ubuntu-latest=catthehacker/ubuntu:act-latest
Apple Silicon Macsact --container-architecture linux/amd64 if you hit architecture errors

An example workflow

# 1. See which jobs exist
act -l
# 2. Run just the lint job while editing it
act -j lint
# 3. Run the full PR CI with a real token
act pull_request -s GITHUB_TOKEN="$(gh auth token)"
# 4. Push only once it's green locally

Limits to know

  • Containers aren't identical to GitHub runners: preinstalled tools, permissions and OS differ. macOS and Windows runners aren't emulated as fully as Linux.
  • Features tied to GitHub's infrastructure (OIDC, cache, artifacts, some GitHub-only actions) may not work or need extra setup.
  • A real deploy step really deploys if you pass real secrets. Use a condition like if: ${{ !env.ACT }} to skip dangerous steps under act (act sets the ACT environment variable).
  • The Large image is huge; start with Medium and switch only if tools are missing.

How to apply it

  • Dev: When editing a workflow, run act -j <job> before pushing. Fewer "fix ci" commits, fewer CI minutes burned.
  • Tech Lead: Add act instructions to CONTRIBUTING and guard deploy steps with the ACT condition so local runs are safe.
  • PM: A shorter CI feedback loop means pipelines get fixed faster, with less waiting and fewer billed GitHub Actions minutes.

Sources & references

  1. nektos/act — nektos (GitHub)