Run your tests on a warm sandbox before you push
Sync your uncommitted working tree to a warm Linux sandbox with Crabbox and run your test suite there, so your laptop and your coding agent stay free.
Guzman Pintos
9 min read
You have a change half done and you want to know whether the tests still pass. Running the suite locally takes over your laptop for a few minutes. Running it in CI means committing work you don't consider finished, pushing it, waiting for a runner, and watching it reinstall every dependency before a single test runs. By the time the result arrives you have moved on to something else.
Coding agents make this worse. An agent runs the test suite far more often than you do, and it runs it on whatever machine it is sitting on: your laptop, maybe alongside other agents doing the same thing in other worktrees. The alternative, letting the agent push work-in-progress commits to get a CI signal, is how agents end up multiplying your CI bill.
There is a middle option: a remote Linux box that stays warm, receives the files you have right now, uncommitted edits included, and runs your tests there. That is what Crabbox does, and with Tenki as its provider the box is a Tenki Sandbox session.
What Crabbox does
Crabbox is an open-source, MIT-licensed CLI from OpenClaw. You run crabbox run in a Git checkout, and it ships your working tree to a remote machine, runs the command you gave it, streams the output back, and exits with the remote command's exit code. It supports many providers. With provider: tenki, Crabbox asks the tenki CLI to create, resume and terminate sandbox sessions, and reaches them over SSH through Tenki's proxy with a per-session certificate. You don't manage SSH keys or guest IPs.
Crabbox doesn't know how your project installs dependencies or runs tests. Whatever you type after -- is what runs, so it works for any stack that runs on Linux.
Why a warm box beats a cold runner for the inner loop
CI is built to start from nothing. Every job gets a fresh machine, checks out a commit, restores or reinstalls dependencies, and then runs your tests. That is exactly what you want from the check that gates a merge, because it proves the committed code works on a clean machine. It is a poor fit for the twentieth run of the afternoon, where the only thing that changed is one file.
A warm box inverts the trade-off. You lease it once, install dependencies once, and every run after that reuses the installed node_modules, the module cache and the build output already on the box. Only the files you changed travel over the wire. Nothing has to be committed, so you can test a change before you have decided what the commit is.
The trade-off is that a warm box drifts. It accumulates state from earlier runs, and a test can pass because of something left over from last Tuesday. Keep CI as the merge gate and treat the warm box as the fast signal you get before it.
How the sync decides what goes up
Crabbox builds its file list from Git: it runs git ls-files --cached --others --exclude-standard and hands that manifest to rsync. In practice that means tracked files plus untracked files Git would not ignore. It seeds the remote tree at your local HEAD, so only your diff is transferred, and it skips the sync entirely when a fingerprint of your changes matches what the box already has.
That has a few consequences for the first run:
- Your uncommitted edits go up. Your
.envdoes not, as long as Git ignores it and has never tracked it. A file that was committed before it was added to.gitignoreis still tracked, and still syncs. - Ignored inputs your tests need, such as generated code, don't sync. Copy them up once with
crabbox cp. - Environment variables stay on your laptop unless you allow them. Out of the box only
CIandNODE_OPTIONSare forwarded, so a test that readsDATABASE_URLpasses locally and fails on the box until you add it to the allowlist. Keep tokens off that list: a forwarded value sits in the environment of every command on a box that stays up all day.
The shortest setup
Sign in to the tenki CLI and install Crabbox:
tenki login
brew install openclaw/tap/crabbox
Crabbox uses the CLI's saved credentials and workspace, so there is no separate token to configure. Add a .crabbox.yaml at the repository root:
provider: tenki
target: linux
tenki:
cpus: 4
memoryMB: 8192
diskGB: 20
Set diskGB. The default root disk is 5 GiB, which fills up quickly once dependencies are installed, and it can't be resized on an existing sandbox. Check the setup with crabbox doctor, then lease a box, give it a name, and aim runs at it:
crabbox warmup --slug ci
crabbox run --id ci -- pnpm install --frozen-lockfile
crabbox run --id ci -- pnpm test
The first run installs dependencies on the box. Later runs sync only what changed. To rerun the tests on every save, use watch mode:
crabbox watch --id ci -- pnpm test
watch debounces filesystem events and never overlaps two runs; a change that lands mid-run queues one rerun from the newest tree. Exiting the loop leaves the box running because you passed --id.
Keep it warm, or pause it overnight
crabbox warmup marks the session sticky, so Tenki won't stop it at a maximum duration. It runs, and bills, until you stop it.
Sandbox compute is billed per second from the rate card: $0.000014 per vCPU-second and $0.0000045 per GiB-second of memory, with disk above 5 GiB adding a fraction of a cent per hour. For the 4 vCPU, 8 GiB box above, that works out to about $0.33 an hour before your plan's monthly credits, or about $8 if it runs for 24 hours. The default 2 vCPU, 4 GiB size is about $0.17 an hour. For scale, the Starter plan's $10 of monthly credits covers roughly 30 hours of the 4 vCPU box. Starter caps sandboxes at 4 cores and 8 GB of RAM; bigger warm boxes need the Team plan.
If you want to keep the installed state but stop paying for compute overnight, pause the session from the Tenki side:
crabbox list --provider tenki
tenki sandbox pause --session <session-id>
crabbox list shows the Tenki session ID next to the slug. Pausing stops the compute meter and keeps disk and memory. The next crabbox run --id ci sees the paused session, resumes it and carries on. A paused session doesn't count against your concurrent session limit, but its saved state counts toward your workspace storage quota. /tmp is cleared across a pause; everything under /home/tenki, including the synced workspace and its dependencies, survives.
When you are done with the box for good, crabbox stop ci terminates the session.
Gate your pushes on it
Once the command settles, write it down as a job in the same .crabbox.yaml so nobody has to remember the flags:
jobs:
test:
shell: true
command: pnpm install --frozen-lockfile && pnpm test
stop: auto
stop: auto terminates a sandbox the job created and leaves alone one you passed with --id. Because Crabbox exits with the remote command's exit code, a pre-push hook is two lines:
#!/bin/sh
exec crabbox job run --id ci test
Save it as .git/hooks/pre-push and make it executable with chmod +x. A failing suite now blocks the push, the warm box stays up afterwards, and git push --no-verify skips the hook when you need to push anyway. With the hook in place, most pushes that reach CI have already passed once.
Tell your coding agents to use it
An agent won't use the warm box unless the repository tells it to. A short section in AGENTS.md or CLAUDE.md does it (see our guide to shared instruction files for how each tool reads them):
## Running checks
Checks run on a Tenki sandbox through Crabbox, not locally.
- Warm box: `crabbox warmup --slug ci`. Skip it if `crabbox status --id ci` prints `state=ready`.
- Run a command there: `crabbox run --id ci -- <command>`. The full suite is `crabbox job run --id ci test`.
- Only tracked and non-ignored files sync. Ignored inputs the checks need go up once with `crabbox cp --id ci <local-path> SANDBOX:<remote-path>`.
- Leave the box running. Do not `crabbox stop ci`.
The last line matters because agents like to clean up after themselves, and an agent that stops the box throws away the installed dependencies you were keeping it warm for. crabbox init also writes a generic Crabbox skill file to .agents/skills/crabbox/SKILL.md; keep it and add the repository-specific section above.
If you run several agents in parallel, give each worktree its own slug so each box holds one working tree. Each warm box is a running session, and Starter allows 5 at a time.
The agent's test runs now happen on the sandbox, so the machine it runs on stays responsive. If you are also worried about what the agent's code does when it runs, the same isolation helps; see Where to run code your AI agent wrote.
When not to use it
- Don't use it as a replacement for CI. The warm box runs whatever is in your working tree on a machine with history. CI runs a commit on a clean machine and is what your branch rules should require. When you suspect leftover state, a plain
crabbox runwithout--idgets a fresh sandbox and terminates it afterwards. - Platform-specific tests don't fit. The Tenki provider targets Linux, so tests that need macOS or Windows stay local or in CI.
- Tests that depend on your laptop need extra work. Anything they connect to, such as a database, has to run on the box or be reachable from it. Secrets have to be fetched inside the command or baked into a template; forwarding them from your shell leaves them on a long-lived machine.
Next step
The Crabbox guide has the full setup: environment variable allowlists, JUnit output, per-run sizing, starting new boxes from a snapshot with a warm package store, and troubleshooting. The Tenki provider page on crabbox.sh covers the provider from Crabbox's side.


