Contributing
Thank you for your interest in contributing to vx!
Getting Started
Prerequisites
- Rust 1.80+
- Git
Clone and Build
git clone https://github.com/loonghao/vx.git
cd vx
cargo buildCross-Platform Build Notes
vx uses rustls (pure Rust TLS implementation) instead of OpenSSL, which enables:
- No system dependencies: Cross-compilation to musl targets works out of the box
- Smaller binaries: No need to bundle OpenSSL
- Consistent behavior: Same TLS implementation across all platforms
The HTTP client (reqwest) is configured with:
rustls-tls: Pure Rust TLS backendrustls-tls-native-roots: Uses system certificate store for trust roots
This means you can build static musl binaries without installing OpenSSL:
# Build for Linux musl (static binary)
cross build --release --target x86_64-unknown-linux-musl
# Build for ARM64 musl
cross build --release --target aarch64-unknown-linux-muslRun Tests
cargo testRun Clippy
cargo clippy --workspace --all-targets --all-features -- -D warningsFormat Code
cargo fmtDevelopment Workflow
1. Create a Branch
git checkout -b feature/my-feature2. Set Up Pre-commit Hooks
vx uses prek for pre-commit hooks. Install them once after cloning:
vx prek installThis installs hooks that automatically check your code before every commit. See Pre-commit Hooks for the full list of checks.
3. Make Changes
- Write code
- Add tests
- Update documentation
4. Test Locally
# Run all tests
cargo test
# Run specific test
cargo test test_name
# Run with output
cargo test -- --nocapture5. Check Code Quality
# Format
cargo fmt
# Lint
cargo clippy --workspace --all-targets --all-features -- -D warnings
# Check documentation
cargo doc --all-features --no-deps
# Run all pre-commit hooks manually
vx prek run --all-files6. Keep workspace-hack in Sync
After adding or updating dependencies in any Cargo.toml, regenerate the workspace-hack:
just hakari-generate
# or manually:
cargo hakari generate
cargo hakari manage-depsThe pre-commit hook will catch this automatically if you forget.
7. Submit PR
- Push your branch
- Create a pull request
- Fill out the PR template
Code Guidelines
Rust Style
- Follow Rust conventions
- Use
rustfmtfor formatting - Address all Clippy warnings
- Document public APIs
Testing
- Place tests in
tests/directories - Use
rstestfor parameterized tests - Aim for good coverage
Documentation
- Document public functions and types
- Include examples in doc comments
- Update user documentation as needed
Project Structure
vx/
├── crates/
│ ├── vx-cli/ # CLI application (entry point)
│ ├── vx-core/ # Core types and traits
│ ├── vx-paths/ # Path management
│ ├── vx-resolver/ # Version resolution and execution
│ ├── vx-runtime/ # Runtime management and registry
│ ├── vx-starlark/ # Starlark DSL engine
│ │ └── stdlib/ # 14 Starlark standard library modules
│ ├── vx-installer/ # Download and install
│ ├── vx-config/ # Configuration management
│ ├── vx-console/ # Unified output and progress
│ ├── vx-project-analyzer/ # Project detection
│ └── vx-providers/ # 105 tool providers (provider.star)
├── skills/ # AI agent skill files (5 SKILL.md)
├── docs/ # Documentation (English + Chinese)
├── tests/ # Integration tests
└── justfile # Development task runnerAdding a New Provider
- Create
crates/vx-providers/<name>/provider.starusing a template (covers 90% of cases) - Define metadata:
name,description,ecosystem,runtimes,permissions - Add tests:
vx <runtime> --version - Update documentation if needed
# Example: crates/vx-providers/mytool/provider.star
load("@vx//stdlib:provider.star", "runtime_def", "github_permissions")
load("@vx//stdlib:provider_templates.star", "github_rust_provider")
name = "mytool"
description = "My awesome tool"
ecosystem = "custom"
runtimes = [runtime_def("mytool")]
permissions = github_permissions()
_p = github_rust_provider("owner", "repo",
asset = "mytool-{vversion}-{triple}.{ext}")
fetch_versions = _p["fetch_versions"]
download_url = _p["download_url"]
install_layout = _p["install_layout"]
store_root = _p["store_root"]
get_execute_path = _p["get_execute_path"]
environment = _p["environment"]See Creating a Provider and provider.star Reference for the complete guide.
Commit Messages
Use conventional commits:
feat: add support for new tool
fix: resolve version parsing issue
docs: update installation guide
test: add provider tests
refactor: simplify version resolutionPull Request Process
- Ensure CI passes
- Update documentation
- Add tests for new features
- Request review
- Address feedback
CI Pipeline
The CI pipeline is optimized with crate-level change detection to minimize build times:
How It Works
- Change Detection: The CI automatically detects which crates have changed
- Dependency Analysis: It understands the dependency graph between crates
- Targeted Testing: Only affected crates are tested
Crate Dependency Layers
┌─────────────────────────────────────────────────────────────┐
│ vx-cli (Application) │
├─────────────────────────────────────────────────────────────┤
│ vx-resolver │ vx-extension │ vx-project-analyzer │ ... │
├─────────────────────────────────────────────────────────────┤
│ vx-runtime (Infrastructure) │
├─────────────────────────────────────────────────────────────┤
│ vx-core │ vx-paths (Foundation) │
└─────────────────────────────────────────────────────────────┘Impact Rules
| Changed Crate | Affected Crates |
|---|---|
vx-core | All crates that depend on it (runtime, resolver, extension, etc.) |
vx-paths | runtime, resolver, env, setup, migration, args, extension, cli |
vx-runtime | resolver, extension, cli, all providers |
vx-config | project-analyzer, cli |
| Provider crates | Only the changed provider and cli |
vx-cli | Only cli itself |
CI Jobs
| Job | Condition | Description |
|---|---|---|
test-targeted | Specific crates changed | Tests only affected crates |
test-full | Core crates changed or CI config changed | Full workspace test |
code-quality | Any Rust code changed | Format and Clippy checks |
dogfood | Any Rust code changed | Integration tests with real tools |
cross-build | Main branch only | Cross-compilation for ARM/musl |
coverage | Main branch only | Code coverage report |
Force Full CI
To run all tests regardless of changes:
- Go to Actions tab
- Select "CI" workflow
- Click "Run workflow"
- Check "Force full CI run"
Dependency Constraints
Some dependencies have version constraints that cannot be automatically upgraded:
bincode (v1.3 → v3.x blocked)
The bincode crate is pinned to v1.3 because:
- msvc-kit (used for MSVC Build Tools installation on Windows) depends on
bincode ^1.3 bincode v3has a completely different API (the crate was restructured)- Until
msvc-kitreleases a version supportingbincode v3, we cannot upgrade
Workaround: Renovate is configured to skip major bincode updates. See PR #378 for details.
Resolution: Monitor msvc-kit releases for bincode v3 support. Once available:
- Update
msvc-kitto the new version - Remove the Renovate rule for
bincode - Migrate code to
bincode v3API
Reporting Issues
When reporting bugs:
- Check existing issues
- Include vx version (
vx --version) - Include OS and shell
- Provide reproduction steps
- Include error messages
Feature Requests
- Check existing issues/discussions
- Describe the use case
- Propose a solution if possible
Community
License
By contributing, you agree that your contributions will be licensed under the MIT License.