This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
anvs is a Rust-based automatic Node.js version switcher that activates on cd, designed to be 2-3x faster than its predecessor (avn).
Key Characteristics:
- Language: Rust (for performance, safety, zero runtime dependencies)
- Distribution: npm with pre-compiled binaries + Homebrew tap
- Platforms: Linux (x64/arm64), macOS (x64/arm64)
- Architecture: Modular plugin system for version managers (nvm, fnm)
- Version: 2.0.0 (Project renamed from xvn to anvs)
Current Phase: Production (v2.0.0)
- Project renamed from xvn to anvs (Automatic Node Version Switcher)
- MVP complete and published to npm (anvs)
- Homebrew tap available (olvrcc/anvs)
- CI/CD with GitHub Actions for releases
- Active user base with ongoing enhancements
- README.md - User-facing documentation, installation, and usage
- docs/ARCHITECTURE.md - System design and architectural decisions
- docs/MIGRATION.md - Migration guide for upgrading from older versions (including xvn to anvs)
- CONTRIBUTING.md - Contribution guidelines
- spec/ - Historical planning documents and milestone specifications (reference)
✅ Implemented:
- Core CLI with
activate,status,setup,uninstall,setcommands - Configuration via
~/.anvsrcand./.anvs.yaml - Version file detection:
.nvmrc,.node-version,package.json - Plugin system with nvm and fnm support
- Shell integration (bash/zsh via chpwd hooks)
- FD:3 protocol for parent shell communication
- Auto-install prompts for missing versions
- Automatic return to default version when leaving projects
- Semver range support in
package.jsonengines.node - npm distribution with pre-compiled binaries
- Homebrew tap (olvrcc/anvs)
- CI/CD with GitHub Actions
- Comprehensive test suite (>85% coverage)
⏳ Potential Future Enhancements:
- Additional version managers (n, asdf, volta)
- Daemon mode for <10ms activation
- Windows/PowerShell support
- Additional shells (fish, nushell)
- Advanced commands (doctor, which, list, exec)
- VersionManagerPlugin trait - Interface for version manager plugins
- Built-in plugins compiled into binary (nvm, fnm)
- Dynamic plugin loading from
~/.anvs/plugins/ - Plugin priority ordering via configuration
- File descriptor #3 protocol for parent shell environment modification
- chpwd_functions hook integration (bash/zsh)
- Version file discovery (walk up directory tree)
- Idempotency checks to prevent re-activation
- Activation time: <100ms (P50), <150ms (P95) for v1.0
- Activation time: <8ms (P50), <15ms (P95) for v2.0 (daemon mode)
- Binary size: <5MB compressed
- Memory footprint: <5MB resident
~/.anvsrc- User-level configuration (YAML).anvs.yaml- Project-level configuration overrides.nvmrc/.node-version- Node.js version specification files
# Development
cargo build # Build debug binary
cargo build --release # Build optimized binary
cargo test # Run unit tests
cargo install --path . # Install locally for testing
# Code Quality
cargo clippy -- -D warnings # Rust linter (strict)
cargo fmt # Format code
npm run check # Run fmt, clippy, and tests together
npm run lint # Run clippy only
# Testing
cargo test # Run all tests
cargo test --test integration # Run integration tests only
cargo test <test_name> # Run specific test
./scripts/coverage.sh # Generate code coverage report
# Local Installation for Development
npm run dev # Build and install locally (cargo install --path .)
npm run setup # Build, install locally, and run anvs setup
# Version Management
./scripts/bump-version.sh <major|minor|patch> # Bump version in all files
./scripts/version.sh # Display current version
# Release Process
npm run release:download # Download release artifacts from GitHub Actions
npm run release:extract # Extract binaries from archives
npm run release:pack # Create npm package tarball
npm run release:verify # Verify package contents
npm publish # Publish to npm (requires auth)
# Homebrew Tap
./scripts/setup-homebrew-tap.sh # Create/update Homebrew formula
# User Commands
anvs setup # Configure shell integration
anvs activate [path] # Manually activate version
anvs status # Show config and last activation time
anvs set <key> # Interactive config setting
anvs uninstall # Remove anvs completely
anvs --version # Check version- Rust over Node.js - 2-3x performance gain, memory safety, zero runtime dependencies
- npm distribution - Leverages existing Node.js ecosystem, binary downloads via postinstall
- File descriptor #3 protocol - Inherited from avn, allows child process to modify parent shell
- Plugin-first design - Even built-in version managers are plugins
- Auto-install with prompts - UX improvement over avn (prompts to install missing versions)
- Modular shell integration - Future-ready for additional shell support
src/
├── main.rs # CLI entry point (minimal)
├── lib.rs # Library exports
├── cli.rs # Command-line interface using clap
├── error.rs # Error types and AnvsError
├── output.rs # Terminal output formatting
│
├── activation/ # Version activation orchestration
│ ├── mod.rs # Main activation logic
│ ├── orchestrator.rs # Coordinates plugins and shell
│ ├── errors.rs # Activation-specific errors
│ └── user_prompt.rs # Interactive prompts for auto-install
│
├── commands/ # CLI subcommands
│ ├── mod.rs # Command dispatching
│ ├── set.rs # Interactive config setting
│ └── uninstall.rs # Clean removal
│
├── config/ # Configuration management
│ ├── mod.rs # Config API
│ ├── schema.rs # Config struct and defaults
│ └── loader.rs # YAML parsing and merging
│
├── init/ # Setup wizard
│ ├── mod.rs # Setup command
│ ├── wizard.rs # Interactive setup flow
│ ├── detection.rs # Detect shell, version managers
│ ├── validation.rs # Validate installation
│ └── prompts.rs # User prompts
│
├── plugins/ # Version manager plugins
│ ├── mod.rs # Plugin exports
│ ├── trait_def.rs # VersionManagerPlugin trait
│ ├── registry.rs # Plugin loading and priority
│ ├── nvm.rs # nvm implementation
│ ├── fnm.rs # fnm implementation
│ └── mock.rs # Test mock plugin
│
├── setup/ # Shell profile modification
│ ├── mod.rs # Setup logic
│ ├── installer.rs # Binary installation
│ ├── shell_detection.rs # Detect shell type
│ └── profile_modification.rs # Modify .bashrc/.zshrc
│
├── shell/ # Shell communication
│ ├── mod.rs # Shell abstraction
│ ├── fd3.rs # File descriptor 3 protocol
│ └── json_writer.rs # JSON output for --json flag
│
└── version_file/ # Version file detection
├── mod.rs # Main finder logic
├── finder.rs # Walk directory tree
├── package_json.rs # Parse package.json engines
└── semver.rs # Semver range resolution
tests/ # Integration tests
├── integration.rs # End-to-end tests
├── config_test.rs # Config loading tests
├── plugin_test.rs # Plugin system tests
├── version_file_test.rs # Version file detection tests
├── shell_integration.rs # Shell hook tests
└── security_test.rs # Security validations
shell/
└── anvs.sh # Shell hook script (bash/zsh)
scripts/ # Release and dev scripts
├── bump-version.sh # Bump version across files
├── version.sh # Display current version
├── download-artifacts.sh # Download CI build artifacts
├── extract-binaries.sh # Extract release binaries
└── setup-homebrew-tap.sh # Create Homebrew formula
Activation Flow:
cli.rsparses command (activate,status, etc.)activation/orchestrator.rscoordinates the activation:version_file/finder.rswalks up directory tree to find.nvmrc, etc.version_file/package_json.rsparsesengines.nodeif neededplugins/registry.rsloads plugins in priority order- Each plugin attempts to resolve the version
- If missing,
activation/user_prompt.rsprompts to install
shell/fd3.rswrites activation command to file descriptor 3- Parent shell executes the command
Shell Integration:
shell/anvs.shhooks intochpwd(bash/zsh)- Triggers
anvs activateon directory change - Uses FD:3 protocol to modify parent shell environment
- Handles idempotency (doesn't re-activate same version)
Plugin System:
plugins/trait_def.rsdefinesVersionManagerPlugintrait- Built-in plugins:
nvm.rs,fnm.rs(compiled into binary) - Registry loads plugins in priority order from config
- Each plugin checks if the version manager is installed
- Plugins generate shell commands for activation
Configuration:
config/loader.rsreads~/.anvsrcand./.anvs.yaml- Project config overrides global config
- YAML format with validation
- Interactive editing via
anvs setcommand
- Central installation: anvs installs to
~/.anvs/binto remain available across Node.js version changes - Not a version manager: anvs requires nvm/fnm to be installed; it's a switcher, not a manager
- Platform support: Linux and macOS only (x64/arm64); Windows not supported
- Shell support: bash and zsh only (via chpwd hooks)
- File descriptor 3 protocol: Child process communicates shell commands to parent via FD:3
- Conventional commits: Always use conventional commit format (feat:, fix:, chore:, etc.)
- No
anytypes: Never useanyin TypeScript; always provide correct types (comment if impossible) - Commit after changes: Always commit after every change with file list in message
- Add before commit: Always
git addall files before committing
- Version bump: Use
./scripts/bump-version.sh <major|minor|patch>to update version in all files - Git tag: Create annotated git tag matching version (e.g.,
v2.0.0) - Push tag:
git push --tagstriggers GitHub Actions CI/CD - CI builds: GitHub Actions builds binaries for all platforms
- Download artifacts:
npm run release:downloadto get binaries - Extract binaries:
npm run release:extractto prepare for packaging - npm publish:
npm publishto release to npm registry - Homebrew:
./scripts/setup-homebrew-tap.shto update Homebrew formula
- Located in
tests/directory - Run with
cargo test - Use
tempfilefor filesystem tests - Mock plugins available in
src/plugins/mock.rs
tests/integration.rsfor end-to-end scenarios- Test shell hook integration
- Validate version file detection across directory trees
- Target: >85% line coverage
- Generate reports:
./scripts/coverage.sh - Uses
cargo tarpaulin
Core:
clap- CLI argument parsing with derive macrosserde+serde_yaml- Config serializationanyhow+thiserror- Error handlingsemver- Semantic version parsingdirs- Cross-platform directory locations
User Interaction:
inquire- Interactive promptsowo-colors- Terminal colorslog+env_logger- Debugging
Dev:
tempfile- Temporary files in testsassert_cmd- CLI testingpredicates- Test assertions