Using vx in GitHub Actions
vx provides an official GitHub Action that makes it easy to use vx in your CI/CD workflows. This allows you to have consistent development tool versions across local development and CI environments.
Quick Start
Add the following to your GitHub Actions workflow:
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}Note: You can use
@mainfor the latest version, or pin to a specific release tag (e.g.,@vx-v0.6.4). Check releases for available versions.
Then use vx to run any supported tool:
- run: vx node --version
- run: vx npm install
- run: vx uv pip install -r requirements.txt
- run: vx go build ./...Full Example
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
# Setup vx with caching
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
tools: 'node uv' # Pre-install these tools
cache: 'true'
# Use vx to run tools
- name: Install dependencies
run: vx npm ci
- name: Run tests
run: vx npm test
- name: Build
run: vx npm run buildInputs
| Input | Description | Default |
|---|---|---|
version | vx version to install (e.g., "0.5.7", "latest") | latest |
github-token | GitHub token for API requests (avoids rate limiting) | github.token |
tools | Space-separated list of tools to pre-install (e.g., "node go uv") | '' |
cache | Enable caching of vx tools directory | true |
cache-key-prefix | Custom prefix for cache key | vx-tools |
Outputs
| Output | Description |
|---|---|
version | The installed vx version |
cache-hit | Whether the cache was hit |
Use Cases
Automatic Dependency Installation
vx automatically detects and installs missing dependencies before running commands. This is especially useful in CI environments where you don't want to manually add install steps.
| Tool | Trigger Command | Auto-runs | Detection |
|---|---|---|---|
| uv | vx uv run | uv sync | pyproject.toml exists, .venv missing |
| npm | vx npm run | npm install | package.json exists, node_modules missing |
| pnpm | vx pnpm run | pnpm install | package.json exists, node_modules missing |
| yarn | vx yarn run | yarn install | package.json exists, node_modules missing |
| bun | vx bun run | bun install | package.json exists, node_modules missing |
| go | vx go run | go mod download | go.mod exists, vendor missing |
This means your CI workflow can be as simple as:
- run: vx uv run pytest # Auto-syncs dependencies first
- run: vx npm run build # Auto-installs node_modules first
- run: vx go run main.go # Auto-downloads modules firstNode.js Project
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
tools: 'node'
- run: vx npm ci
- run: vx npm test
- run: vx npm run buildNote: vx automatically installs dependencies before running scripts. When running
vx npm run,vx pnpm run,vx yarn run, orvx bun run, it will automatically execute the corresponding install command first ifpackage.jsonexists butnode_modulesdoesn't.
Python Project with UV
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
tools: 'uv'
# vx automatically runs 'uv sync' before 'uv run' if .venv doesn't exist
- run: vx uv run pytest
- run: vx uvx ruff check .Note: vx automatically detects if dependencies need to be installed. When running
vx uv run, it will automatically executeuv syncfirst ifpyproject.tomlexists but.venvdoesn't.
Go Project
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
tools: 'go'
- run: vx go build ./...
- run: vx go test ./...Note: vx automatically downloads Go modules before running. When running
vx go run, it will automatically executego mod downloadfirst ifgo.modexists butvendordirectory doesn't.
Multi-Language Project
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
tools: 'node uv go'
# Frontend
- run: vx npm ci
- run: vx npm run build
# Backend (Python)
- run: vx uv sync
- run: vx uv run pytest
# Services (Go)
- run: vx go build ./cmd/...Cross-Platform CI
jobs:
build:
runs-on: ${{matrix.os}}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v6
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
# Same commands work on all platforms!
- run: vx node --version
- run: vx npm ci
- run: vx npm testUsing with Version Pinning
If your project has a vx.toml configuration file, vx will automatically use the versions specified there:
# vx.toml
[tools]
node = "20.10.0"
uv = "0.4.0"
go = "1.22.0"jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
# vx will use versions from vx.toml
- run: vx node --version # Uses 20.10.0
- run: vx uv self version # Uses 0.4.0One-Click Setup with vx setup
The most powerful way to use vx in CI is with vx setup. This command reads your vx.toml and automatically:
- Installs all required tools with pinned versions
- Sets up Python virtual environment (if configured)
- Installs Python dependencies
- Verifies environment variables
Example vx.toml:
[project]
name = "my-fullstack-app"
description = "A full-stack application"
[tools]
node = "20"
uv = "latest"
go = "1.22"
[python]
version = "3.11"
venv = ".venv"
[python.dependencies]
requirements = ["requirements.txt", "requirements-dev.txt"]
packages = ["pytest", "black", "ruff"]
[env]
NODE_ENV = "production"
[scripts]
test = "pytest"
build = "npm run build"
lint = "ruff check ."GitHub Actions workflow:
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
# One command to setup everything!
- name: Setup development environment
run: vx setup
# Now run your scripts
- run: vx run lint
- run: vx run test
- run: vx run buildThis approach ensures:
- Consistency: Local and CI environments use identical tool versions
- Simplicity: One command replaces multiple setup actions
- Reproducibility: Just copy
vx.tomlto any project for the same setup
Share Your Configuration
Commit vx.toml to your repository. New team members can run vx setup to get the exact same development environment in seconds.
Environment Export for Subsequent Steps
When you need tools to be available in subsequent workflow steps without the vx prefix, use vx env export:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}
- name: Setup development environment
run: vx setup
# Export tool paths to GITHUB_PATH
- name: Setup vx environment
run: |
if [ -f "vx.toml" ]; then
vx env export --format github >> $GITHUB_PATH
fi
# Now tools are available directly!
- run: node --version # No 'vx' prefix needed
- run: uv --version
- run: npm ciThis is particularly useful when:
- Using tools that don't work well with the
vxprefix - Running scripts that expect tools to be directly in PATH
- Integrating with other actions that invoke tools directly
How it works
vx env export --format github outputs tool paths (one per line) that GitHub Actions appends to $GITHUB_PATH. These paths become available in all subsequent steps.
Caching
The action automatically caches the vx tools directory (~/.vx) to speed up subsequent runs. You can customize the cache behavior:
- uses: loonghao/vx@main
with:
cache: 'true'
cache-key-prefix: 'my-project-vx'To disable caching:
- uses: loonghao/vx@main
with:
cache: 'false'Troubleshooting
Rate Limiting
If you encounter GitHub API rate limiting, make sure to provide a GitHub token:
- uses: loonghao/vx@main
with:
github-token: ${{secrets.GITHUB_TOKEN}}The vx action automatically exports the GITHUB_TOKEN environment variable to all subsequent steps, so you don't need to set it manually in each step. However, if you're running vx commands in a separate job or workflow, make sure to pass the token:
- name: Run vx command
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: vx uv run pytestTool Installation Failures
If a tool fails to install, check:
- The tool is supported by vx (
vx listto see all supported tools) - Network connectivity to the tool's download source
- Sufficient disk space
Cache Issues
If you're experiencing cache-related issues, try:
- Using a different cache key prefix
- Disabling caching temporarily
- Clearing the cache in GitHub Actions settings
Supported Tools
vx supports many popular development tools:
- JavaScript/TypeScript: Node.js, npm, npx, Bun, Deno, pnpm, Yarn, Vite
- Python: UV, uvx
- Go: Go
- Rust: Cargo, rustc, rustup
- Java: Java, javac
- DevOps: Terraform, kubectl, Helm
- Others: Just, Zig, and more
Run vx list to see all available tools.
Migration from Other Actions
From actions/setup-node
Before:
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ciAfter:
- uses: loonghao/vx@main
- run: vx npm ciFrom actions/setup-python + pip
Before:
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install -r requirements.txtAfter:
- uses: loonghao/vx@main
- run: vx uv pip install -r requirements.txtFrom actions/setup-go
Before:
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- run: go build ./...After:
- uses: loonghao/vx@main
- run: vx go build ./...Benefits of Using vx
- Unified Tool Management: One action to manage all development tools
- Version Consistency: Same tool versions in CI as local development
- Cross-Platform: Works on Linux, macOS, and Windows
- Caching: Automatic caching for faster CI runs
- Simplicity: No need to configure multiple setup actions
Using Docker Images
vx provides official Docker images that can be used directly in your CI/CD workflows. These images are available on both Docker Hub and GitHub Container Registry.
Available Images
| Image Tag | Description | Base |
|---|---|---|
vx:latest | Minimal image with just vx | Ubuntu 24.04 (Noble) |
vx:tools-latest | Image with pre-installed tools (uv, ruff, node) | Ubuntu 24.04 (Noble) |
Why Ubuntu 24.04?
We use Ubuntu 24.04 (glibc 2.39) because:
- vx is compiled on Ubuntu 24.04 runners, requiring glibc 2.39
- Most development tools provide glibc-compiled binaries
- Alpine (musl) causes "No such file or directory" errors
- Older Debian/Ubuntu versions have outdated glibc
Using the Tools Image in Container Jobs
The vx:tools-latest image comes with commonly used tools pre-installed, making it perfect for CI/CD workflows where you need fast startup times:
Pre-installed tools:
- uv - Fast Python package manager
- ruff (via uvx) - Python linter and formatter
- Node.js - JavaScript runtime (LTS version)
jobs:
lint:
runs-on: ubuntu-latest
container:
image: ghcr.io/loonghao/vx:tools-latest
steps:
- uses: actions/checkout@v6
# Tools are already available - no installation needed!
- name: Lint Python
run: vx uvx ruff check .
- name: Run tests
run: |
vx uv sync
vx uv run pytest
- name: Build frontend
run: |
vx npm ci
vx npm run buildPulling the Images
# From GitHub Container Registry (recommended)
docker pull ghcr.io/loonghao/vx:latest
docker pull ghcr.io/loonghao/vx:tools-latest
# From Docker Hub
docker pull longhal/vx:latest
docker pull longhal/vx:tools-latestUsing in Docker Compose
# docker-compose.yml
version: '3.8'
services:
dev:
image: ghcr.io/loonghao/vx:tools-latest
working_dir: /app
volumes:
- .:/app
command: bash -c "vx uv sync && vx uv run pytest"Building Custom Images
You can extend the vx images with your own tools:
FROM ghcr.io/loonghao/vx:tools-latest
# Pre-install additional tools
RUN vx go version
# Add your project files
COPY . /app
WORKDIR /app
# Run your application
CMD ["vx", "uv", "run", "main.py"]Image Tags
Both Docker Hub and GHCR provide the following tags:
latest- Latest stable base imagetools-latest- Latest stable tools image{version}- Specific version (e.g.,0.6.5)tools-{version}- Specific version with tools
When to use the tools image
Use vx:tools-latest when:
- Your workflow needs Python (uv/ruff) or Node.js
- You want faster CI startup times
- You're running multiple jobs that all need the same tools
Use vx:latest when:
- You only need specific tools not in the tools image
- You want the smallest possible image size
- You're building a custom image on top of vx