I built Skipbox, a runner that runs your GitHub Actions jobs on a dedicated VM, blazing fast and dirt cheap.
Using it is dead simple: just change runs-on in your job definition.
jobs: test: - runs-on: ubuntu-latest + runs-on: skipbox steps: - uses: actions/checkout@v4 - run: make test - 1/12 the cost of GitHub at full use
- A flat price, so you can run it all day
- 7× GitHub's cache space
🚀
Here is what you save at 20,000 minutes a month (a typical startup), comparing 4 vCPU with 4 vCPU, from the cost calculator on skipbox.dev:
| Today | Per month | Skipbox S × 1 | You save |
|---|---|---|---|
| GitHub 4-core runner | about $222 | $39 flat | $183 a month ($2,196 a year) |
| Blacksmith (4 vCPU) | about $148 | $39 flat | $109 a month ($1,308 a year) |
Way cheaper than Blacksmith, too!
What I built
Skipbox is a GitHub Actions runner that works as a GitHub App.
Install the app on your GitHub organization or personal account, and each plan gives you one VM dedicated to your account.
Because that VM belongs to your account alone, the Docker images and the npm cache the previous job pulled down are already on disk when the next job starts.
| Kept between jobs | Wiped after every job |
|---|---|
| Docker images, layers, and build cache | The runner's credentials |
| Package caches for npm, pip, Go, Gradle, Cargo, and more | The work directory with your checkout |
| The tool cache that setup-* actions fill | The runner user's processes and every container |
Credential files such as ~/.npmrc and ~/.git-credentials |
The caches that make jobs fast stay; the credentials don't.
A health check also runs after every job, so if a machine ever gets into a bad state, it is automatically rebuilt from a clean image.
VMs come in three sizes. You pick one with the runs-on label, depending on the plan you subscribe to.
| Plan | CPU / Memory | Disk | runs-on |
|---|---|---|---|
| S | 4 vCPU / 8 GB | 80 GB | skipbox |
| M | 8 vCPU / 16 GB | 160 GB | skipbox-8x16 |
| L | 16 vCPU / 32 GB | 320 GB | skipbox-16x32 |
How it started: heavy jobs on a powerful PC at home, development on a laptop
For Convika, another product I'm building, I ran CI on a self-hosted runner on my desktop at home.
The machine never got reset, so Playwright's browsers and the pnpm store simply stayed on disk. No re-downloading them on every run, and no worrying about cache size limits.
By the way, GitHub doesn't charge for minutes on self-hosted runners, so quite a few people turn a powerful home PC into a self-hosted runner and keep it busy around the clock (if they don't mind the power bill and the roar of fans that never stop). In December 2025, GitHub did announce that it would start charging for self-hosted runners too, but in the end that plan was put on hold.
So I realized that the shortest path to cheap, fast CI is a dedicated machine that isn't reset every time, used for every job.
Skipbox gives you that setup without keeping a PC running at home.
Provisioning the VM, registering a runner for each job, cleaning up after each job, rebuilding when something breaks: Skipbox takes care of all the tedious parts for you.
Have you mastered GitHub Actions' complex caching?
To get caching working in GitHub Actions, you usually write something like this. Could you explain what each line does?
- uses: actions/cache@v4 with: path: ~/.npm key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }} restore-keys: | npm-${{ runner.os }}- And GitHub's cache comes with these rules (GitHub Docs):
- Not shared across branches. A job can only use caches made on its own branch and on the default branch (plus the base branch, for a pull request).
- A pull request's first run misses. If the default branch has no cache, it builds from scratch.
- No overwriting a key. A cache can't be changed once it's created, so you have to design your keys and
restore-keys. - Deleted after 7 days unused. Once the repository goes past 10 GB in total, the caches used least recently are deleted first (LRU).
With Skipbox, none of this matters: no cache keys, no restore steps.
The cache simply stays on the VM's disk, and every job your account runs on that machine uses the same disk.
And there's plenty of room. The S plan's disk is 80 GB, and 70 GB of it (everything but the OS and tools) is yours for caches. That's 7× the 10 GB GitHub gives a repository by default (15× on M, 31× on L). Docker cleans up unused data only once the disk is more than 85% full.
Docker builds reuse the previous job's layers too. docker build and docker compose build work unchanged, and if you use docker/setup-buildx-action, set driver: docker and the machine's cache kicks in.
- uses: docker/setup-buildx-action@v3 with: driver: docker How it works
- GitHub → Skipbox (Cloudflare Workers): a job is queued (the
workflow_jobwebhook). - Skipbox → GitHub: registers a just-in-time (JIT) runner for that job.
- Your account's VM → Skipbox: "Is there a next job?" (every second)
- Skipbox → VM: hands over the JIT config.
- VM → GitHub: runs the job.
- VM: wipes the credentials and the work directory, then runs a health check.
- VM → Skipbox: reports the result and waits for the next job.
The backend runs on Cloudflare Workers. As a GitHub App, it receives job webhooks, registers a fresh runner for each job, and hands it to your account's VM. The VM takes your account's jobs one at a time, and after each one it cleans up and checks itself before waiting for the next. This flow is why every job starts with the cache already in place.
Pricing
| S | M | L | |
|---|---|---|---|
| Monthly | $39 | $79 | $149 |
| CPU / Memory | 4 vCPU / 8 GB | 8 vCPU / 16 GB | 16 vCPU / 32 GB |
| Disk | 80 GB | 160 GB | 320 GB |
| Minutes | Unlimited | Unlimited | Unlimited |
There's no usage-based billing at all.
Running S all day, 43,200 minutes a month, costs 1/12 of GitHub's 4-core runner.
Plans differ in how many jobs can run at once and how big they are, but no plan limits your minutes.
If you want to run more jobs at once, just add a plan. You can subscribe to several plans (say, three S, two M, and one L), so it scales as far as you need.
In the AI era, I keep hearing about teams that use GitHub Actions so heavily they hit their budget cap and CI stops at the end of the month. With Skipbox, there's simply nothing usage-based to hit.
There's a free trial for 7 days (it ends earlier if you use up its 3,000 minutes).
Summary
- Skipbox is a dedicated VM for GitHub Actions, blazing fast and dirt cheap
- Huge cache space (7× GitHub's)
- A flat monthly price with unlimited minutes, so you can run E2E tests 24 hours a day
Try it out: move one job to Skipbox and see how it runs ↓
Questions or feedback? Leave a comment or email hello@skipbox.dev.


