crabbox actions prepares a leased box from your repository's own GitHub
Actions workflow, so repo-owned setup (toolchains, dependencies, caches,
services) runs the same way CI does before crabbox run attaches.
Hydration has two modes:
- Local hydration (default) runs the hydrate workflow over SSH on the leased
box. Crabbox reads the workflow file from
.github/workflows/, syncs the current checkout, executes supported setup steps in the persistent workspace, and waits for the ready marker. This path needs no GitHub repository write access. - GitHub runner hydration (
--github-runner) registers the box as a self-hosted runner, dispatches the configured workflow with the canonical lease label, and waits for the workflow to write the marker. Use it when the workflow needs full GitHub Actions semantics — repository secrets, OIDC, service containers, or unsupported actions.
The companion commands actions register and actions dispatch expose the
runner-registration and workflow-dispatch steps directly.
hydrate --id <lease-id-or-slug> [--provider <provider>] [--target linux|macos|windows]
[--windows-mode normal|wsl2] [--repo owner/name] [--workflow <file|name|id>]
[--job <name>] [--ref <ref>] [--github-runner] [--wait-timeout 20m]
[--keep-alive-minutes 90] [--reclaim] [--timing-json] [-f key=value] [--field key=value]
register --id <lease-id-or-slug> [--provider <provider>] [--target linux|macos|windows]
[--windows-mode normal|wsl2] [--repo owner/name] [--name <runner-name>]
[--labels <csv>] [--version latest] [--ephemeral=true] [--reclaim]
dispatch [--repo owner/name] [--workflow <file|name|id>] [--ref <ref>] [-f key=value] [--field key=value]
hydrate and register validate the current repo's lease claim before touching
the box. Pass --reclaim to intentionally move a lease to the current repo.
When local defaults point at another backend, repeat the same provider/target
routing flags used to create the lease.
Populates a lease's workspace from the configured workflow. Requires --id and
either --workflow or actions.workflow.
crabbox warmup
crabbox actions hydrate --id blue-lobster
crabbox run --id blue-lobster -- pnpm test:changedLocal hydration supports Linux and Windows WSL2 targets. With
--github-runner, native Windows is also supported. Static macOS hosts can run
commands through provider=ssh, but Actions hydration still requires Linux,
Windows WSL2, or native Windows with --github-runner.
Blacksmith Testbox IDs (tbx_...) and --provider blacksmith-testbox are
skipped, because Blacksmith owns Testbox hydration. Run commands against those
boxes directly with crabbox run --provider blacksmith-testbox --id <tbx_id> -- ....
On success, hydrate prints a workspace summary and a total-duration line. Add
--timing-json to emit a final JSON timing record (stderr) with provider, lease
ID, slug, total duration, exit code, and — for the GitHub fallback — the Actions
run URL when the marker reports a run ID.
Registers an existing box as a GitHub Actions self-hosted runner. Crabbox
obtains a repository registration token through gh api, installs the official
actions/runner package, and starts it under systemd on Linux/WSL2 or a
detached PowerShell process on native Windows. Supports Linux and Windows
targets only. Registration metadata and the short-lived token travel over SSH
stdin rather than the remote process command line.
crabbox actions register --id blue-lobsterEach runner gets the labels crabbox, the canonical lease label
crabbox-<lease-id>, profile/class labels, the slug label when available, and
any labels from actions.runnerLabels or --labels. Runner names use the
friendly slug when available; workflow inputs and state-file paths keep using the
canonical cbx_... ID.
Dispatches the configured workflow via gh workflow run. Requires --workflow
or actions.workflow.
crabbox actions dispatch -f testbox_id=cbx_abcdef123456Every -f / --field value must be key=value. During actions hydrate, CLI
values override matching actions.fields entries. Automatic hydration also uses
actions.fields.
Standalone actions dispatch sends only inputs explicitly supplied with -f /
--field; it still uses configured repository, workflow, and ref defaults.
For GitHub runner hydration, Crabbox inspects the selected workflow's
workflow_dispatch.inputs (when the workflow path is available under
.github/workflows/). It sends only declared inputs and requires crabbox_id,
crabbox_runner_label, and crabbox_keep_alive_minutes; crabbox_job is optional.
If that hydration dispatch rejects crabbox_job as an unexpected input, Crabbox
retries once without it so older workflow refs stay usable.
A hydrate workflow must accept these inputs:
on:
workflow_dispatch:
inputs:
crabbox_id:
required: true
type: string
crabbox_runner_label:
required: true
type: string
crabbox_job:
required: false
default: "hydrate"
type: string
crabbox_keep_alive_minutes:
required: false
default: "90"
type: stringFor local hydration, Crabbox runs the YAML job named hydrate when present, or
the only job in a single-job workflow. actions.job is the marker-input value,
not the YAML job selector; older workflows can omit both. When actions.job is
set and the workflow declares crabbox_job, Crabbox sends it and verifies the
ready marker came from that job. For --github-runner, the job should target the
dynamic lease label:
runs-on: [self-hosted, "${{ inputs.crabbox_runner_label }}"]actions:
repo: example-org/my-app
workflow: .github/workflows/crabbox.yml
job: hydrate
ref: main
fields:
- crabbox_docker_cache=true
runnerLabels:
- crabbox
runnerVersion: latest
ephemeral: trueUse actions.fields for repository-specific workflow inputs that should be sent
on every hydration.
Use hydration when CI already knows how to prepare the repository and you want a fast local-style loop:
crabbox warmup
crabbox actions hydrate --id blue-lobster
crabbox run --id blue-lobster -- pnpm test:changedThe workflow owns repository-specific setup: checkout, dependency install,
caches, and project tools. Local hydration supports run steps plus common
setup actions: actions/checkout, actions/setup-node, pnpm/action-setup,
actions/setup-go, actions/setup-python, and actions/cache/restore|save
(cache restore reports a miss; save is skipped). pnpm/action-setup requires an
explicit exact version (major.minor.patch) and installs into the managed tool
cache without lifecycle scripts; it bootstraps Node 24 if Node or npm is absent,
so pnpm setup may precede setup-node. A later setup-node selects the project Node
version without displacing the managed pnpm. Other pnpm inputs and version
inference/ranges require --github-runner; install project dependencies in a
separate run step. Setup-node accepts cache: pnpm as an explicitly uncached
local run. Repo-local composite actions (./path) are supported.
Job containers and service containers are not; actions/checkout options that
change the repository, path, submodules, or LFS fail locally so you can rerun
with --github-runner when you need full GitHub Actions semantics.
Local hydration resolves simple expressions in env, run steps, working
directories, and supported action inputs: ${{ inputs.name }},
${{ env.NAME }}, ${{ github.workspace }}, ${{ hashFiles(...) }}, and
runner temp/toolcache references. Unsupported or complex expressions fail with a
suggestion to use --github-runner.
After checkout and setup, the workflow writes the ready marker under
$HOME/.crabbox/actions/. Map workflow inputs into step environment variables
such as CRABBOX_ID and CRABBOX_JOB; do not interpolate them directly into
shell source:
case "$CRABBOX_ID" in
""|*[!A-Za-z0-9_-]*)
echo "::error::crabbox_id must match [A-Za-z0-9_-]+"
exit 2
;;
esac
case "$CRABBOX_JOB" in
*$'\n'*|*$'\r'*)
echo "::error::crabbox_job must not contain line breaks"
exit 2
;;
esac
job="$CRABBOX_JOB"
[ -n "$job" ] || job=hydrate
mkdir -p "$HOME/.crabbox/actions"
state="$HOME/.crabbox/actions/${CRABBOX_ID}.env"
env_file="$HOME/.crabbox/actions/${CRABBOX_ID}.env.sh"
services_file="$HOME/.crabbox/actions/${CRABBOX_ID}.services"
{
echo "WORKSPACE=${GITHUB_WORKSPACE}"
echo "RUN_ID=${GITHUB_RUN_ID}"
echo "JOB=${job}"
echo "ENV_FILE=${env_file}"
echo "SERVICES_FILE=${services_file}"
echo "READY_AT=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
} > "${state}.tmp"
mv "${state}.tmp" "$state"crabbox run --id <lease-id-or-slug> reads that marker, syncs into the hydrated
$GITHUB_WORKSPACE, and sources the non-secret env file when present. If no
marker exists and actions.workflow is configured, run performs local
hydration automatically after sync unless --no-hydrate or --no-sync is set.
The env file should hold stable GitHub/runner context such as
GITHUB_WORKSPACE, GITHUB_RUN_ID, GITHUB_JOB, RUNNER_TEMP, and
RUNNER_TOOL_CACHE — never secrets or OIDC request tokens. Keep the workflow job
alive (via --keep-alive-minutes) only when using --github-runner and service
containers or job-scoped setup must stay running for the remote command loop.
crabbox stop <lease-id-or-slug> writes the .stop marker before releasing the
box.
crabbox warmup --actions-runner leases a box and registers it as an ephemeral
runner in one step:
crabbox warmup --actions-runner
crabbox warmup --provider aws --target windows --windows-mode wsl2
crabbox actions hydrate --provider aws --target windows --windows-mode wsl2 --id blue-lobster
crabbox run --id blue-lobster -- pnpm test