RunsOn CLI
Command line tool to manage and troubleshoot your RunsOn installation
RunsOn CLI (roc) is a command line tool to manage and troubleshoot your RunsOn ↗ installation.
It works with modern RunsOn installations, including current v3 stacks. The CLI assumes you run it with AWS credentials that can read the RunsOn stack resources, CloudWatch logs, SSM sessions, EC2 instance metadata, and any service used by the selected command.
Usage
Flex
Most troubleshooting starts with the GitHub Actions job URL:
JOB_URL="https://github.com/acme/app/actions/runs/123456789/job/987654321"
AWS_PROFILE=runs-on-admin roc logs "$JOB_URL" --include=console --watchAWS_PROFILE=runs-on-admin roc connect "$JOB_URL"AWS_PROFILE=runs-on-admin roc interrupt "$JOB_URL" --waitUse logs first, connect when you need a live SSM shell, and interrupt to test Spot interruption handling.
Fleet
For Fleet, start with roc logs when you need CloudWatch logs for a specific job URL. roc connect and roc interrupt are primarily Flex troubleshooting tools today; use Fleet troubleshooting for Fleet-specific runtime checks.
Installation
Download Binary
You can download the binaries for your platform (Linux, macOS) from the Releases ↗ page.
Example (macOS ARM64):
VERSION=v3.1.0curl -Lo ./roc https://github.com/runs-on/cli/releases/download/${VERSION}/roc_${VERSION#v}_darwin_arm64chmod a+x ./roc./roc --helpExample (Linux AMD64):
VERSION=v3.1.0curl -Lo ./roc https://github.com/runs-on/cli/releases/download/${VERSION}/roc_${VERSION#v}_linux_amd64chmod a+x ./roc./roc --helpGitHub Action
You can use the RunsOn CLI in your GitHub Actions workflows by including it as a step:
- uses: runs-on/cli@main with: version: 'latest' # Optional: defaults to 'latest'Example workflow:
name: Lint RunsOn Config
on: pull_request: paths: - '.github/runs-on.yml'
jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6
- uses: runs-on/cli@main
- name: Lint runs-on.yml run: roc lint .github/runs-on.ymlCore Commands
roc connect
Connect to the instance running a specific job via SSM by passing the GitHub Actions job URL.
This feature requires the AWS Session Manager plugin ↗ to be installed on your local machine.
Usage: roc connect JOB_URL [flags]
Flags: --debug Enable debug output -h, --help help for connect --watch Wait for instance ID if not found
Global Flags: --stack string CloudFormation stack name (default "runs-on")Example:
AWS_PROFILE=runs-on-admin roc connect https://github.com/runs-on/runs-on/actions/runs/12415485296/job/34661958899roc logs
Fetch RunsOn server and instance logs for a specific job URL. Use the --include flag to specify additional log types.
Usage: roc logs JOB_URL [flags]
Flags: -d, --debug Enable debug output -f, --format string Output format: long (default) or short (default "long") --full Export full diagnostic archive (ZIP) for the job -h, --help help for logs --include strings Include additional log types: 'run' (all logs from entire run), 'console' (EC2 instance console logs) --no-color Disable color output -w, --watch string[="5s"] Watch for new logs with optional interval (e.g. --watch 2s)
Global Flags: --stack string CloudFormation stack name (default "runs-on")The lookback window for roc logs is fixed at the last 2 hours. The --full flag exports a full diagnostic archive (ZIP) for the job instead of streaming; it cannot be combined with --watch.
Examples:
# Fetch logs for a specific job (default behavior)AWS_PROFILE=runs-on-admin roc logs https://github.com/runs-on/runs-on/actions/runs/12415485296/job/34661958899 --watch
# Fetch all application logs for a run (all jobs in the run)AWS_PROFILE=runs-on-admin roc logs https://github.com/runs-on/runs-on/actions/runs/12415485296/job/34661958899 --include=run --watch
# Fetch EC2 instance console logsAWS_PROFILE=runs-on-admin roc logs https://github.com/runs-on/runs-on/actions/runs/12415485296/job/34661958899 --include=console
# Fetch both run logs and console logsAWS_PROFILE=runs-on-admin roc logs https://github.com/runs-on/runs-on/actions/runs/12415485296/job/34661958899 --include=run,console --watchroc interrupt
Trigger a spot interruption on the instance running a specific job, simulating a spot instance interruption for testing purposes.
This command uses AWS Fault Injection Simulator (FIS) to send a spot interruption notification to the running instance.
Usage: roc interrupt JOB_URL [flags]
Flags: --debug Enable debug output --delay duration Delay before interruption (e.g., 2m, 30s) (default 5s) -h, --help help for interrupt -w, --wait Wait for instance ID if not found
Global Flags: --stack string CloudFormation stack name (default "runs-on")Requirements:
- The target instance must be a running spot instance
- AWS FIS service must be available in your region
How it works:
- Validates the instance is a running spot instance
- Creates an IAM role for FIS if it doesn’t exist
- Creates and starts a FIS experiment to send the interruption
- Monitors the experiment progress
- Automatically cleans up the experiment template when complete
Example:
AWS_PROFILE=runs-on-admin roc interrupt https://github.com/runs-on/runs-on/actions/runs/12415485296/job/34661958899# Wait for instance if job hasn't started yetAWS_PROFILE=runs-on-admin roc interrupt https://github.com/runs-on/runs-on/actions/runs/12415485296/job/34661958899 --wait
# Custom delay before interruption (default is 5 seconds)AWS_PROFILE=runs-on-admin roc interrupt https://github.com/runs-on/runs-on/actions/runs/12415485296/job/34661958899 --delay 30sroc lint
Validate and lint runs-on.yml configuration files. This command validates your configuration files against the RunsOn schema, checking for syntax errors, invalid values, missing required fields, and schema violations.
When no file path is provided, the command recursively searches for all runs-on.yml files in the current directory and subdirectories.
Usage: roc lint [flags] [file]
Flags: --format string Output format: text, json, or sarif (default "text") --stdin Read configuration from stdin -h, --help help for lint
Global Flags: --stack string CloudFormation stack name (default "runs-on")What it validates:
- YAML syntax errors
- Schema validation for all top-level fields (
_extends,runners,images,pools,admins) - Required fields and valid value types
- Pool configuration (name pattern, schedule values, runner references)
- Runner specifications (CPU, RAM, family, spot values, etc.)
- Image specifications (AMI IDs, platform, architecture, etc.)
- Custom fields are allowed (e.g.,
x-defaultsfor YAML anchors)
Output formats:
text(default): Human-readable output with file status and diagnosticsjson: Structured JSON output for CI/CD integrationsarif: SARIF format for GitHub Code Scanning and other tools
Examples:
# Lint a specific configuration fileroc lint .github/runs-on.yml
# Lint all runs-on.yml files recursively (no arguments)roc lint
# Lint from stdincat runs-on.yml | roc lint --stdin
# Lint with JSON output for CI/CD pipelinesroc lint config/runs-on.yml --format json
# Lint with SARIF output for GitHub Code Scanningroc lint .github/runs-on.yml --format sarifIntegration with CI/CD:
The command exits with a non-zero status code when validation errors are found:
# Exit code 0 for valid config, 1 for invalidif roc lint runs-on.yml --format json > validation-report.json; then echo "Configuration is valid!"else echo "Configuration validation failed. See validation-report.json for details." exit 1fiPre-commit hook:
You can use roc lint as a pre-commit hook to automatically validate runs-on.yml files before committing. First, install pre-commit ↗:
pip install pre-commitThen add the hook to your .pre-commit-config.yaml:
repos: - repo: https://github.com/runs-on/cli rev: v0.1.13 # Use the latest release tag hooks: - id: roc-lintFinally, install the git hook scripts:
pre-commit installNow roc lint will automatically run on staged runs-on.yml files before each commit. The commit will be blocked if validation errors are found.
roc version
Display the version of the roc CLI.
roc versionStack Management
roc stack doctor
Diagnose RunsOn stack health and export troubleshooting information.
This command performs health checks on your RunsOn stack:
- Checks ECS service health (running vs desired tasks)
- Tests endpoint accessibility (Flex stacks only)
- Validates service readiness via
/readyz, incl. GitHub App configuration (Flex stacks only) - Fetches application logs
Fleet stacks skip the endpoint and readiness checks (no public endpoint).
Results are exported as a timestamped ZIP file containing checks.json and logs.
Usage: roc stack doctor [flags]
Flags: -h, --help help for doctor --since string Fetch logs since duration (e.g. 30m, 2h, 24h) (default "24h")
Global Flags: --stack string CloudFormation stack name (default "runs-on")Example:
AWS_PROFILE=runs-on-admin roc stack doctor --since 2hOutput:
Checking service (https://us-east-1.console.aws.amazon.com/ecs/v2/clusters/.../services/.../configuration/overview)... ✅ (status: RUNNING (1/1 tasks))Checking service endpoint (https://example.execute-api.us-east-1.amazonaws.com/prod)... ✅Checking service readiness... ✅ (app_tag: v3.1.0)Fetching application logs (since 24h0m0s)... ✅ (5419 lines)
Full results exported to: /Users/crohr/dev/runs-on/cli/roc-doctor-2025-06-20-12-40-29.ziproc stack logs
Stream all RunsOn application logs from CloudWatch log streams.
This command streams all application logs from the RunsOn service, not filtered by specific jobs. Use this to monitor overall service activity and troubleshoot system-wide issues.
Usage: roc stack logs [flags]
Flags: -d, --debug Enable debug output -f, --format string Output format: long (default) or short (default "long") -h, --help help for logs --no-color Disable color output -s, --since string Show logs since duration (e.g. 30m, 2h) (default "2h") -w, --watch string[="5s"] Watch for new logs with optional interval (e.g. --watch 2s)
Global Flags: --stack string CloudFormation stack name (default "runs-on")Examples:
# Stream last 2 hours of application logs (default)AWS_PROFILE=runs-on-admin roc stack logs
# Stream last 24 hours of logsAWS_PROFILE=runs-on-admin roc stack logs --since 24h
# Stream logs with watch mode (refreshes every 5 seconds)AWS_PROFILE=runs-on-admin roc stack logs --watch
# Stream logs with custom watch intervalAWS_PROFILE=runs-on-admin roc stack logs --watch 10s
# Stream logs in short format without colorAWS_PROFILE=runs-on-admin roc stack logs --format short --no-colorUse Cases
Debugging Job Failures
When a GitHub Actions job fails on your RunsOn infrastructure:
- Get logs: Use
roc logs JOB_URLto fetch detailed logs - Connect to instance: Use
roc connect JOB_URLto SSH into the runner - Check stack health: Run
roc stack doctorto ensure infrastructure is healthy - Test interruption handling: Use
roc interrupt JOB_URLto simulate spot interruptions
Real-time Monitoring
# Monitor logs in real-time for active jobsroc logs JOB_URL --watch
# Monitor all application logsroc stack logs --watchHealth Checks
# Regular stack health verificationroc stack doctor
# Stream application logs for monitoringroc stack logs --since 1hTroubleshooting
Connection Issues
If roc connect fails:
- Ensure AWS Session Manager plugin is installed
- Verify your AWS credentials have appropriate permissions to access the RunsOn stack
- Check that you are targeting the correct stack (
--stackflag) and region (AWS profile orAWS_REGIONenvironment variable) - Use
--debugflag for detailed error information
Log Access Issues
If roc logs returns no results:
- Verify the job URL is correct
- Check your AWS credentials and permissions
- Check that you are targeting the correct stack (
--stackflag) and region (AWS profile orAWS_REGIONenvironment variable) - Try adjusting the
--sincetimeframe
Interruption Testing Issues
If roc interrupt fails:
- Ensure the target instance is a running spot instance
- Verify AWS FIS service is available in your region
- Check that your AWS credentials have appropriate FIS permissions
- Use
--debugflag for detailed error information
Support
For issues with the RunsOn CLI:
- Open an issue on GitHub ↗
- Contact support at ops@runs-on.com
- Include output from
roc stack doctorwhen reporting problems
License
This project is licensed under the MIT License - see the LICENSE file for details.