Install
openclaw skills install vx-best-practicesBest practices for using vx effectively. Use when following recommended patterns for tool management, project setup, and team workflows with vx.
openclaw skills install vx-best-practicesGolden rule: Always prefix tool commands with
vxin vx-managed projects. Usevx.tomlfor project-level tool versions, commitvx.lockfor reproducibility, prefer templates over custom code when creating providers, and prefer structured or compact output before reading large logs.
vx PrefixIn vx-managed projects, always prefix tool commands with vx:
# ✅ Correct
vx npm install
vx cargo build
vx just test
# ❌ Wrong (might use system tools)
npm install
cargo build
just test
Use vx.toml to ensure consistency across team members:
# ✅ Correct - defined in vx.toml
vx sync
# ❌ Wrong - manual installation
vx install node@22
Always commit vx.lock to ensure reproducible builds:
vx git add vx.lock
vx git commit -m "chore: update dependencies"
When an AI agent uses vx, optimize for correctness, speed, judgment, and token efficiency:
For large or unknown output, scope first and filter through vx-managed tools:
vx rg -n -m 20 "SearchTerm" src
vx git diff --stat
vx git diff --name-only origin/main...HEAD
vx gh pr view 123 --json title,state,files
vx gh run view 456 --json status,conclusion,jobs --jq '.jobs[] | {name,conclusion}'
vx gh run view 456 --log | vx rg -n -m 50 "error|failed|panic|Traceback|FAILED"
vx --compact gh run view 456 --log
Use this priority order for token-heavy surfaces:
--json, selected fields, --jq, --fields, --toon.vx rg -n -m 80 ..., vx jq, vx yq.vx --compact <tool> ... for broad subprocess output that still needs context.The compact filter follows RTK-style principles: preserve high-signal lines,
strip presentation noise, collapse repetition, cap volume, and measure savings
with vx metrics tokens --json when comparing approaches. Do not make
transparent forwarding commands (vx git, vx gh, vx cargo, vx npm) compact
by default; agents should opt in explicitly with --compact so scripts and
humans keep the native tool contract.
# 1. Initialize project
vx init
# 2. Add required tools
vx add node@22
vx add go
vx add just
# 3. Generate lock file
vx lock
# 4. Commit configuration
vx git add vx.toml vx.lock
New team members only need to run:
# Clone repository
git clone <repo>
cd <repo>
# One command setup
vx setup
Use the vx GitHub Action:
# .github/workflows/ci.yml
- uses: loonghao/vx@main
with:
setup: 'true'
cache: 'true'
| Scenario | Constraint | Example |
|---|---|---|
| Development | Major version | node = "22" |
| CI/CD | Exact version | node = "22.0.0" |
| Library | Range | node = ">=18 <23" |
| Latest features | "latest" | uv = "latest" |
# ✅ Good - flexible for patch updates
[tools]
node = "22"
go = "1.22"
# ❌ Bad - too rigid for development
[tools]
node = "22.0.0" # Blocks security patches
go = "1.22.0" # Requires update for each patch
# Use LTS versions for stability
[tools]
node = "lts" # Auto-updates to latest LTS
[scripts]
# Standard scripts (run with: vx run <name>)
dev = "npm run dev"
test = "npm run test"
build = "npm run build"
lint = "npm run lint"
# Colon-separated variants (run with: vx run test:watch)
test:watch = "npm run test -- --watch"
test:coverage = "npm run test -- --coverage"
build:prod = "npm run build -- --mode production"
# CI-specific scripts
ci = "just ci"
ci:test = "cargo test --all-features"
# Scripts can depend on specific tools
[scripts]
lint = "eslint . && cargo clippy" # Uses node and rust
build = "go build ./..." # Uses go
[env]
NODE_ENV = "development"
DEBUG = "app:*"
# Required variables (vx will warn if missing)
API_KEY = { env = "API_KEY", required = true }
# Default values
PORT = { default = "3000" }
Never commit secrets. Use environment variables:
# .env (add to .gitignore)
DATABASE_URL=postgresql://...
API_KEY=secret123
# Reference in vx.toml
[env]
DATABASE_URL = { env = "DATABASE_URL" }
[cache]
# Enable aggressive caching
enabled = true
ttl = 86400 # 24 hours
# Cache location
dir = "~/.vx/cache"
# In project setup, pre-install tools
vx sync --parallel
# When network is unreliable
vx sync --offline
[tools]
# Cross-platform tools first
node = "22"
uv = "latest"
# Platform-specific
[tools.msvc]
version = "14.42"
os = ["windows"]
[tools.brew]
version = "latest"
os = ["macos", "linux"]
# Use tools that work everywhere
[scripts]
build = "just build" # just is cross-platform
test = "cargo test" # cargo is cross-platform
# Avoid platform-specific commands
# ❌ build = "make build" # Unix only
vx automatically verifies checksums. For additional security:
# Verify installation
vx install node@22 --verify
# Install as regular user, not root
# ❌ sudo vx install node
# vx manages user-level installations
vx install node
# Audit installed tools
vx audit
# Check for vulnerabilities
vx npm audit
# 1. Add to vx.toml
vx add python@3.12
# 2. Update lock file
vx lock
# 3. Commit changes
git add vx.toml vx.lock
git commit -m "feat: add python 3.12"
# 1. Check for updates
vx outdated
# 2. Update specific tool
vx update node
# 3. Update all tools
vx update --all
# 4. Commit lock file changes
git add vx.lock
# 1. Remove from vx.toml
vx remove tool-name
# 2. Clean up installation
vx sync --clean
# 3. Commit changes
git add vx.toml vx.lock
# Weekly: Check for updates
vx outdated
# Monthly: Clean cache
vx cache clean
# After issues: Run diagnostics
vx doctor
[scripts]
doctor = "vx doctor"
check = "vx check"
audit = "vx npm audit && cargo audit"
# ❌ Don't manually install tools in vx projects
npm install -g node # Conflicts with vx
# ✅ Let vx manage tools
vx npm install
# ❌ Don't ignore vx.lock
git rm --cached vx.lock
# ✅ Always commit lock files
git add vx.lock
# ❌ Don't rely on global configuration
~/.vx/vx.toml
# ✅ Use project-level configuration
./vx.toml
# ❌ Don't hardcode absolute paths
[env]
TOOL_PATH = "/Users/alice/.vx/tools/node"
# ✅ Use vx variables
[env]
TOOL_PATH = "${VX_ROOT}/tools/node"
# 1. Export current versions
node --version > .nvmrc
# 2. Create vx.toml
vx init
# 3. Add node version
vx add node@$(cat .nvmrc | tr -d 'v')
# 4. Remove nvm
rm -rf ~/.nvm
# 1. Check current Python version
python --version
# 2. Create vx.toml
vx init
# 3. Add uv (recommended Python manager)
vx add uv
# 4. Remove pyenv
rm -rf ~/.pyenv
Decision tree for new providers:
github_rust_provider (most common)github_go_providergithub_binary_providersystem_providerdownload_url functionFor most tools, use a template instead of writing custom functions:
# ✅ Good — Use template (10 lines)
_p = github_rust_provider("owner", "tool",
asset = "tool-{vversion}-{triple}.{ext}")
# ❌ Avoid — Custom download_url when template works
def download_url(ctx, version):
# 30+ lines of custom code...
All provider.star functions receive a ctx object:
| Field | Example value | Description |
|---|---|---|
ctx.platform.os | "windows", "macos", "linux" | Current OS |
ctx.platform.arch | "x64", "arm64" | CPU architecture |
ctx.install_dir | ~/.vx/store/node/22.0.0 | Install path |
ctx.store_dir | ~/.vx/store | Global store root |
ctx.cache_dir | ~/.vx/cache | Cache directory |
# ✅ Correct terminology
name = "ripgrep" # Provider name
runtimes = [runtime_def("rg")] # Runtime name (what user types)
# Common pattern: provider name = project name, runtime name = binary name
# ripgrep provider → rg runtime
# rust provider → cargo, rustc, rustup runtimes
Return None from download_url for unsupported platforms:
def download_url(ctx, version):
platform = platform_map(ctx, _PLATFORMS)
if not platform:
return None # Not supported on this platform
return "https://example.com/v{}/tool-{}.tar.gz".format(version, platform)
Use bundled_runtime_def for tools shipped inside another:
runtimes = [
runtime_def("node"), # Primary runtime
bundled_runtime_def("npm", "node"), # npm comes with node
bundled_runtime_def("npx", "node"), # npx comes with node
]
vx just quick # format → lint → test → build
vx cargo check -p vx-cli # Fast type-checking for one crate
vx cargo test -p vx-starlark # Test one crate
tests/ directories — Never inline #[cfg(test)]rstest for parameterized teststracing for logging, never println! or eprintln!vx maintains a comprehensive set of AI agent configuration files for 15+ agents:
| File | Purpose | Audience |
|---|---|---|
AGENTS.md | Primary AI agent entry point — rules, architecture, quick reference | All AI coding agents (official standard) |
CLAUDE.md | Claude Code specific instructions with @-import support | Claude Code |
llms.txt | Concise LLM-friendly project index (llmstxt.org protocol) | LLMs discovering the project |
llms-full.txt | Detailed LLM documentation with full examples | LLMs needing deep context |
.github/copilot-instructions.md | GitHub Copilot-specific instructions | GitHub Copilot |
.cursor/rules/*.mdc | Modern Cursor IDE rules with YAML frontmatter (4 files) | Cursor AI (new format) |
.cursorrules | Cursor IDE agent rules (legacy format, still supported) | Cursor AI (legacy) |
.clinerules | Cline/Roo agent rules | Cline |
.windsurfrules | Windsurf AI IDE rules | Windsurf |
.kiro/steering/*.md | Kiro AI IDE steering documents | Kiro |
.trae/rules/*.md | Trae AI IDE project rules | Trae |
skills/ | Distributable skill files for 15+ AI agents | ClawHub, vx ai setup |
Best practice: When making changes that affect AI agent behavior (terminology, architecture, commands), update AGENTS.md first — it is the single source of truth. Other files derive from it.