A GitHub CLI extension for effortlessly adding self-hosted runners to your repositories, organizations, or enterprises.
- What is gh-runner?
- Features
- Prerequisites
- Installation
- Usage
- Examples
- How It Works
- Managing Runners
- Troubleshooting
- Contributing
- Development
- Roadmap
- License
gh-runner is a command-line tool that simplifies the process of setting up GitHub Actions self-hosted runners. Instead of manually downloading runner binaries, configuring tokens, and managing deployments, this extension automates the entire process with a single command.
Why use self-hosted runners?
- Run workflows on your own hardware with specific configurations
- Access to GPUs, specialized software, or network resources
- Better control over the execution environment
- Cost savings for high-volume CI/CD pipelines
- Compliance with security and privacy requirements
- ✅ Simple CLI - Add runners with a single command
- ✅ Multiple Scopes - Support for repositories, organizations, and enterprises
- ✅ Docker Integration - Automatically deploy runners in Docker containers
- ✅ Windows Support - Deploy Windows runners with
--windowsflag - ✅ Custom Configuration - Set custom names and labels
- ✅ Secure - Uses GitHub CLI authentication and token management
- ✅ Cross-Platform - Works on Linux, macOS, and Windows
- ✅ Official Runner Binaries - Uses official GitHub Actions runner directly
- ⏳ Kubernetes Support - Coming soon for k8s/minikube deployments
- GitHub CLI (
gh) - Installation guide - Git - For version control
- Go 1.21+ - For building from source
- Docker - Required for
--dockerflag (Installation guide) - Minikube - Required for
--k8sflag (coming soon)
You need admin access to the repository, organization, or enterprise where you want to add runners.
gh extension install madkoo/gh-runner# Clone the repository
git clone https://github.com/madkoo/gh-runner.git
cd gh-runner
# Install the extension
gh extension install .# Clone and build
git clone https://github.com/madkoo/gh-runner.git
cd gh-runner
make build
# Install
gh extension install .gh runner --helpgh runner add OWNER/REPO --dockerExample:
gh runner add mycompany/my-private-repo --dockergh runner add org/ORG-NAME --dockerExample:
gh runner add org/my-company --dockergh runner add enterprise/ENTERPRISE-NAME --dockerExample:
gh runner add enterprise/my-enterprise --dockergh runner add owner/repo --docker --name production-runner-01gh runner add owner/repo --docker --labels linux,x64,gpu,cuda,large-diskLabels help you target specific runners in your workflows:
jobs:
build:
runs-on: [self-hosted, linux, gpu, cuda]gh runner add org/myorg --docker \
--name gpu-runner-01 \
--labels linux,x64,gpu,nvidia-rtx-4090,128gb-ramgh runner add myorg/myrepo --docker --windowsNote: Windows containers require:
- Docker Desktop with Windows containers enabled
- Running on a Windows host
- Switch to Windows containers via Docker Desktop settings
gh runner add owner/repoThis displays manual installation instructions with the registration token.
gh runner add mycompany/private-api --dockerOutput:
✓ Registration token obtained
✓ Runner scope: Repository
✓ Target: mycompany/private-api
🐳 Setting up Docker runner...
🐧 Using Linux runner configuration (slim Ubuntu image)
✓ Docker container started: gh-runner-MacBook-Pro
✓ Runner name: MacBook-Pro
✓ Platform: Linux
To view logs: docker logs -f gh-runner-MacBook-Pro
To stop: docker stop gh-runner-MacBook-Pro
To remove: docker rm -f gh-runner-MacBook-Pro
gh runner add org/myorg --docker \
--name build-server-01 \
--labels linux,x64,build,productiongh runner add myuser/test-project --docker \
--name dev-runner \
--labels linux,x64,developmentgh runner add mycompany/windows-app --docker --windows \
--name windows-runner \
--labels windows,x64,dotnetAfter adding your runner, use it in .github/workflows/ci.yml:
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: [self-hosted, linux, x64]
steps:
- uses: actions/checkout@v6
- name: Build
run: make build
- name: Test
run: make test- Authentication - Uses your existing GitHub CLI credentials
- Token Generation - Requests a registration token from GitHub API
- Deployment - Either:
- Starts a Docker container with the runner pre-configured (with
--docker) - Provides manual setup instructions with the token
- Starts a Docker container with the runner pre-configured (with
- Registration - The runner automatically registers with GitHub
- Ready - Runner appears online in your Settings → Actions → Runners
┌─────────────┐
│ gh CLI │
│ (User) │
└──────┬──────┘
│
│ gh runner add owner/repo --docker
│
┌──────▼──────────┐
│ gh-runner │
│ Extension │
└──────┬──────────┘
│
│ 1. Get Registration Token
├─────────────────────────────┐
│ │
┌──────▼──────────┐ ┌────────▼────────┐
│ GitHub API │ │ Docker │
│ (REST) │ │ │
│ │ │ ┌───────────┐ │
│ Returns Token │────────▶│ │ Runner │ │
└─────────────────┘ │ │ Container │ │
│ │ (Ubuntu │ │
│ │ or Win) │ │
│ └───────────┘ │
└─────────────────┘
│
│ Registers & Listens
│
┌───────▼─────────┐
│ GitHub Actions │
│ Job Queue │
└─────────────────┘
docker logs -f gh-runner-<runner-name>docker stop gh-runner-<runner-name># Stop and remove container
docker rm -f gh-runner-<runner-name>
# Then remove from GitHub UI
# Go to Settings → Actions → Runners → Click runner → Removedocker ps --filter "name=gh-runner-"docker restart gh-runner-<runner-name>Problem: Docker is not installed or not running.
Solution:
# Install Docker Desktop (macOS/Windows)
# or Docker Engine (Linux)
# Then start Docker and try again
docker versionProblem: Authentication or permission issues.
Solutions:
-
Authenticate with GitHub CLI:
gh auth login
-
Verify you have admin access to the repo/org/enterprise
-
Check your token has the correct scopes:
gh auth status
Problem: A runner with the same name is already running.
Solution:
# Remove the existing container
docker rm -f gh-runner-<name>
# Or use a different name
gh runner add owner/repo --docker --name runner-02Problem: Runner container stopped or crashed.
Solution:
# Check container status
docker ps -a --filter "name=gh-runner-"
# View logs to see what happened
docker logs gh-runner-<name>
# Restart the container
docker restart gh-runner-<name>Problem: Need sudo for Docker commands.
Solution:
# Add your user to docker group (Linux)
sudo usermod -aG docker $USER
# Then log out and back inWe welcome contributions! Here's how you can help:
- Check if the issue already exists in Issues
- If not, create a new issue with:
- Clear description of the problem
- Steps to reproduce
- Expected vs actual behavior
- Your environment (OS, Go version, Docker version)
- Open an issue with the
enhancementlabel - Describe the feature and use case
- Explain how it would benefit users
-
Fork the repository
gh repo fork madkoo/gh-runner --clone cd gh-runner -
Create a feature branch
git checkout -b feature/my-awesome-feature
-
Make your changes
- Follow Go best practices
- Keep code simple and readable
- Add comments for complex logic
-
Test your changes
make build ./gh-runner add --help
-
Commit with clear messages
git commit -m "feat: add support for runner groups" -
Push and create PR
git push origin feature/my-awesome-feature gh pr create
- Follow standard Go formatting (
gofmt) - Use meaningful variable names
- Keep functions focused and small
- Add error handling for all operations
- Write descriptive commit messages
# Clone the repo
git clone https://github.com/madkoo/gh-runner.git
cd gh-runner
# Install dependencies
go mod download
# Build
make build
# Run locally (without installing as extension)
./gh-runner add owner/repo --docker# Build the extension
make build
# Install locally
gh extension install .
# Test with a real repository (use a test repo!)
gh runner add your-test-org/test-repo --docker --name test-runner
# Verify in GitHub UI
# Settings → Actions → Runners
# Clean up
docker rm -f gh-runner-test-runnergh-runner/
├── main.go # Main application code
├── go.mod # Go module dependencies
├── go.sum # Dependency checksums
├── Makefile # Build automation
├── runners/ # Runner Docker configurations
│ ├── linux/ # Linux runner files
│ │ ├── Dockerfile # Ubuntu-based runner image
│ │ └── entrypoint.sh
│ └── windows/ # Windows runner files
│ ├── Dockerfile # Windows Server Core runner image
│ └── entrypoint.ps1
├── README.md # This file
├── QUICKSTART.md # Quick start guide
├── LICENSE # MIT license
├── examples.sh # Usage examples
└── .gitignore # Git ignore rules
# Using make
make build
# Or manually
CGO_ENABLED=0 go build -trimpath -o gh-runner# Install the extension
gh extension install .
# Or upgrade if already installed
gh extension upgrade runnergh extension remove runner- ✅ Add runners to repositories
- ✅ Add runners to organizations
- ✅ Add runners to enterprises
- ✅ Docker deployment (Linux)
- ✅ Docker deployment (Windows)
- ✅ Custom runner names
- ✅ Custom labels
- ✅ Manual setup instructions
- ✅ Official GitHub Actions runner binaries
- ⏳ Deploy runners to minikube
- ⏳ Deploy runners to existing k8s clusters
- ⏳ Helm chart support
- ⏳ Auto-scaling configuration
- ⏳ List existing runners (
gh runner list) - ⏳ Remove runners (
gh runner remove) - ⏳ Update runner configuration
- ⏳ Show runner status and health
- ⏳ Runner groups support
- ⏳ Multiple runners deployment
- ⏳ Configuration file support
- ⏳ Runner templates
- ⏳ Automatic updates
- ⏳ Runner monitoring and alerts
Have an idea? Open an issue or submit a PR!
A: No, but it's recommended. Without Docker, the tool provides manual setup instructions with the registration token.
A: Yes! Use different --name values for each runner:
gh runner add owner/repo --docker --name runner-01
gh runner add owner/repo --docker --name runner-02A: Currently, remove the old container and create a new one:
docker rm -f gh-runner-old-name
gh runner add owner/repo --docker --name new-nameA: Yes! The Docker runner uses official GitHub Actions runner binaries with minimal Ubuntu 24.04 (Linux) or Windows Server Core LTSC2022 base images. For production, consider:
- Using specific labels for different environments
- Setting up monitoring
- Using
--restart unless-stopped(automatic with this tool)
A: Runners use ephemeral registration tokens from GitHub. The Docker container runs with minimal privileges. Always review the GitHub security best practices.
A: Currently supports GitHub.com and GitHub Enterprise Cloud. GHES support is planned.
- actions/runner - Official GitHub Actions runner (used by this extension)
- actions-runner-controller - Kubernetes controller for runners
- github/gh - GitHub CLI
- 📖 Quick Start Guide
- 💬 GitHub Discussions
- 🐛 Report Issues
- 📧 Contact the maintainer
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2026 Madis Koosaar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- GitHub CLI team for the excellent
ghtool and go-gh library - GitHub Actions team for the official runner binaries
- Cobra for the CLI framework
- The Go and GitHub Actions communities
If you find this project useful, please consider giving it a ⭐!
Made with ❤️ by Madis Koosaar