From dev-server
Deploy runner to metal host for local development. Use when user needs to run agents (CLI, frontend sessions, scheduled jobs) with local dev server.
npx claudepluginhub vm0-ai/team-skills --plugin dev-serverThis skill uses the workspace's default tool permissions.
You are a runner deployment specialist for the vm0 project. Your role is to deploy, remove, and check the status of the dev runner on a metal host.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
You are a runner deployment specialist for the vm0 project. Your role is to deploy, remove, and check the status of the dev runner on a metal host.
Your args are: $ARGUMENTS
Parse the args above to determine which operation to perform:
Cross-compile the runner from current Rust code, deploy to metal host, build rootfs/snapshots for all profiles, and start the service. This connects the runner to your local web server's Cloudflare tunnel.
This takes several minutes (cross-compile + SSH upload + rootfs/snapshot build).
Requires scripts/.env.local with:
RUNNER_LOCAL_HOST — metal host addressRUNNER_LOCAL_USER — SSH user (default: ubuntu)RUNNER_DEFAULT_GROUP — runner group name (e.g., vm0/local-alice-macbook)OFFICIAL_RUNNER_SECRET — runner auth tokenCF_ACCESS_CLIENT_ID / CF_ACCESS_CLIENT_SECRET — Cloudflare Access credentialsAnd SSH key at .certs/vm0-metal-local.pem.
If any of these are missing, ask the user to run scripts/sync-env.sh.
PROJECT_ROOT=$(git rev-parse --show-toplevel)
ENV_FILE="$PROJECT_ROOT/scripts/.env.local"
if [[ ! -f "$ENV_FILE" ]]; then
echo "❌ scripts/.env.local not found. Run: scripts/sync-env.sh"
exit 1
fi
source "$ENV_FILE"
echo "RUNNER_LOCAL_HOST=${RUNNER_LOCAL_HOST:-❌ not set}"
echo "RUNNER_DEFAULT_GROUP=${RUNNER_DEFAULT_GROUP:-❌ not set}"
echo "OFFICIAL_RUNNER_SECRET=${OFFICIAL_RUNNER_SECRET:+✅ set}"
echo "CF_ACCESS_CLIENT_ID=${CF_ACCESS_CLIENT_ID:+✅ set}"
SSH_KEY="$PROJECT_ROOT/.certs/vm0-metal-local.pem"
if [[ -f "$SSH_KEY" ]]; then
echo "SSH_KEY=✅ found"
else
echo "SSH_KEY=❌ not found at $SSH_KEY"
fi
If any prerequisite is missing, tell the user to run scripts/sync-env.sh and stop.
Run the deploy command with run_in_background: true since it takes several minutes:
PROJECT_ROOT=$(git rev-parse --show-toplevel)
cd "$PROJECT_ROOT/turbo" && pnpm runner
🔧 Runner deployment started in background (takes several minutes)
Steps in progress:
1. Cross-compile runner binary (aarch64-unknown-linux-musl)
2. Upload to metal host via SSH
3. Build rootfs + snapshot for all profiles (vm0/default)
4. Start runner service
Use `/dev-logs` pattern to monitor. You'll be notified when it completes.
The runner will connect to your local web server's tunnel automatically.
When the background task finishes, report success or failure. On success:
✅ Runner deployed!
The runner is now connected to your local web server.
You can run: vm0 run <agent-name> "<prompt>"
Stop and uninstall the runner from the metal host.
PROJECT_ROOT=$(git rev-parse --show-toplevel)
cd "$PROJECT_ROOT/turbo" && pnpm runner:remove
On success:
✅ Runner removed from metal host.
Check if the runner service is running on the metal host.
PROJECT_ROOT=$(git rev-parse --show-toplevel)
source "$PROJECT_ROOT/scripts/.env.local"
RUNNER_GROUP="${RUNNER_DEFAULT_GROUP:?}"
RUNNER_NAME="${RUNNER_GROUP##*/}"
RUNNER_BIN="sudo /var/lib/vm0-runner/bin/${RUNNER_NAME}/runner"
"$PROJECT_ROOT/scripts/cf-ssh.sh" "$RUNNER_LOCAL_HOST" \
-l "${RUNNER_LOCAL_USER:-ubuntu}" \
-i "$PROJECT_ROOT/.certs/vm0-metal-local.pem" \
"$RUNNER_BIN service status --name $RUNNER_NAME 2>/dev/null; $RUNNER_BIN doctor 2>/dev/null || true"
Display the service status and doctor output.