Run GitHub Actions workflows locally with the same fidelity as GitHub's servers. Completely offline, zero configuration, minimal complexity.
./ci # Run .github/workflows/ci.yml
./ci .github/workflows/test.yml # Run specific workflowThat's it. No installation, no setup, no configuration files.
- Reads your GitHub Actions workflow file
- Extracts all
- run:commands from the workflow - Executes them in Ubuntu Jammy (same as GitHub's
ubuntu-latest) - Sets the same environment variables GitHub Actions uses
- Mounts your project at
/github/workspace(GitHub's exact path) - Cleans up automatically - no artifacts left behind
Your workflow .github/workflows/ci.yml:
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm test
- run: npm run buildRun locally:
./ciExecutes: npm ci; npm test; npm run build in the same Ubuntu environment GitHub uses.
- Same Ubuntu version - Uses
ubuntu:jammy(GitHub's currentubuntu-latest) - Same paths - Your code lives at
/github/workspace - Same environment -
CI=true,GITHUB_ACTIONS=true, etc. - Same package versions - Fresh Ubuntu container each time
- 12 lines of bash - No VMs, no act installation, no configuration
- Uses Docker - Leverages existing container technology
- Offline capable - Works without internet after initial image pull
- No cleanup needed - Container is removed automatically
- Runs
- run:commands - The core of most CI workflows - Ignores complex actions - Focuses on the 80% use case
- Stable base - Won't break when GitHub changes
ubuntu-latest
This tool focuses on the essential complexity. It doesn't:
- Handle
uses:actions (checkout, setup-node, etc.) - Support multiple jobs or complex workflows
- Provide perfect GitHub compatibility
- Install additional tools beyond basic Ubuntu packages
For these cases, your workflow should be robust enough to install what it needs, or use tools like act for full GitHub Actions compatibility.
- Node.js projects -
npm ci && npm test && npm run build - Python projects -
pip install -r requirements.txt && pytest - Go projects -
go mod download && go test ./... - Static sites - Jekyll, Hugo, simple build processes
- Quick validation - Test workflow changes before pushing
- Complex multi-job workflows
- Workflows heavily dependent on GitHub-specific actions
- Matrix builds across multiple environments
- Workflows requiring specific GitHub context/secrets
# .github/workflows/ci.yml
name: CI
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
- run: apt-get install -y nodejs
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build# .github/workflows/ci.yml
name: CI
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: apt-get update && apt-get install -y python3-pip
- run: pip install -r requirements.txt
- run: python -m pytest
- run: python -m flake8 .# .github/workflows/pages.yml
name: Build and Deploy
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: apt-get update && apt-get install -y ruby-full build-essential zlib1g-dev
- run: gem install jekyll bundler
- run: bundle install
- run: bundle exec jekyll build./ci .github/workflows/your-workflow.ymlAdd installation commands to your workflow:
- run: apt-get update && apt-get install -y your-packageThe container runs as root, so file permissions should work automatically.
Docker needs to pull the Ubuntu image (~200MB). Subsequent runs are fast.
This tool embodies Dijkstra's concept of focusing on essential complexity:
- Essential: Run CI commands in isolated, reproducible environment
- Accidental: Perfect GitHub compatibility, complex workflow parsing, VM management
By focusing only on what's essential, we get:
- Simplicity: 12 lines vs 500+ in other solutions
- Reliability: Fewer moving parts, fewer failure modes
- Maintainability: Easy to understand and modify
- Longevity: Won't break when GitHub changes their infrastructure
The result catches 80% of CI issues with 5% of the complexity.