vx-provider-creator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

VX Provider Creator

VX Provider Creator

This skill guides the creation of new runtime providers for the vx universal tool manager.
本技能指导你为vx通用工具管理器创建新的runtime provider。

When to Use

适用场景

  • Creating a new provider for a tool (e.g., "add support for ripgrep")
  • Implementing a new runtime in vx
  • Adding a new tool to the vx ecosystem
  • Adding project analyzer support for a language/ecosystem
  • Adding tools that require system package manager installation
  • 为某一工具创建新provider(例如:"添加对ripgrep的支持")
  • 在vx中实现新的runtime
  • 为vx生态系统添加新工具
  • 为某一语言/生态系统添加项目分析器支持
  • 添加需要通过系统包管理器安装的工具

Workflow Overview

工作流程概述

  1. Check license compatibility (MUST DO FIRST)
  2. Create a feature branch from remote main
  3. Determine installation type (direct download vs system package manager)
  4. Generate provider directory structure (including
    provider.toml
    )
  5. Implement core files (lib.rs, provider.rs, runtime.rs, config.rs)
  6. Add system package manager fallback if needed
  7. Register the provider in workspace and CLI
  8. (Optional) Add project analyzer integration for language-specific tools
  9. Update snapshot tests
  10. Verify and test
  1. 检查许可证兼容性(必须首先完成)
  2. 从远程main分支创建功能分支
  3. 确定安装类型(直接下载 vs 系统包管理器)
  4. 生成provider目录结构(包含
    provider.toml
  5. 实现核心文件(lib.rs、provider.rs、runtime.rs、config.rs)
  6. 按需添加系统包管理器回退
  7. 在工作区和CLI中注册provider
  8. (可选) 为特定语言工具添加项目分析器集成
  9. 更新快照测试
  10. 验证与测试

⚠️ License Compliance (MANDATORY - Step 0)

⚠️ 许可证合规性(强制要求 - 第0步)

Before creating ANY provider, you MUST check the upstream tool's license.
在创建任何provider之前,你必须检查上游工具的许可证。

Blocked Licenses (DO NOT integrate)

禁止集成的许可证

These licenses have "copyleft infection" that would require vx itself to change license:
LicenseRiskExample
AGPL-3.0Entire project must be AGPLx-cmd
SSPLServer-side copyleftMongoDB
CC BY-NCNo commercial use-
Proprietary (no redistribution)Cannot bundle/distribute-
这些许可证具有“左版感染”特性,会要求vx本身更改许可证:
许可证风险示例
AGPL-3.0整个项目必须采用AGPL许可证x-cmd
SSPL服务器端左版MongoDB
CC BY-NC禁止商业使用-
Proprietary (no redistribution)无法捆绑/分发-

Allowed Licenses (Safe to integrate)

允许集成的许可证

LicenseTypeNotes
MITPermissive✅ No restrictions
Apache-2.0Permissive✅ Patent grant included
BSD-2/BSD-3Permissive✅ Minimal restrictions
ISCPermissive✅ Similar to MIT
MPL-2.0Weak copyleft✅ File-level copyleft only
Unlicense/CC0Public domain✅ No restrictions
许可证类型说明
MIT宽松许可证✅ 无限制
Apache-2.0宽松许可证✅ 包含专利授权
BSD-2/BSD-3宽松许可证✅ 限制极少
ISC宽松许可证✅ 与MIT类似
MPL-2.0弱左版✅ 仅文件级左版
Unlicense/CC0公有领域✅ 无限制

Caution Licenses (Allowed with notes)

需谨慎使用的许可证(允许集成但有说明)

LicenseTypeNotes
GPL-2.0/GPL-3.0Strong copyleft⚠️ OK for vx since we only download and execute the tool (not link to it). Add
license_note
in provider.toml
LGPL-2.1/LGPL-3.0Weak copyleft⚠️ Same as GPL - OK for download/execute. Document in provider.toml
BSL-1.1Source-available⚠️ HashiCorp tools (terraform, vault). OK for version management. Document restriction
Proprietary (free to use)Proprietary⚠️ OK if tool is free to download/use (e.g., dotnet, msvc). Add note
许可证类型说明
GPL-2.0/GPL-3.0强左版⚠️ 对vx来说是可行的,因为我们仅下载并执行工具(而非链接到它)。需在provider.toml中添加
license_note
LGPL-2.1/LGPL-3.0弱左版⚠️ 与GPL相同 - 下载/执行是可行的。需在provider.toml中记录
BSL-1.1源码可用⚠️ HashiCorp工具(terraform、vault)。适用于版本管理。需记录限制
Proprietary (free to use)专有许可证⚠️ 若工具可免费下载/使用则可行(例如dotnet、msvc)。需添加说明

How to Check

检查方法

  1. Visit the tool's GitHub repository
  2. Check the LICENSE file or repository metadata
  3. Search for
    license
    in the repo's About section
  4. If no license found, treat as proprietary and document
  1. 访问工具的GitHub仓库
  2. 查看LICENSE文件或仓库元数据
  3. 在仓库的About部分搜索
    license
  4. 若未找到许可证,视为专有许可证并记录

provider.toml License Fields

provider.toml中的许可证字段

Every
provider.toml
MUST include:
toml
[provider]
name = "example"
license = "MIT"              # SPDX identifier of upstream tool's license
每个
provider.toml
必须包含:
toml
[provider]
name = "example"
license = "MIT"              # 上游工具许可证的SPDX标识符

license_note = "..." # Optional: any special notes about license implications

license_note = "..." # 可选:关于许可证影响的特殊说明


**If the license is in the "Blocked" category, DO NOT create the provider. Inform the user:**

> ⚠️ Cannot integrate {tool}: it uses {license} which has copyleft infection
> that would require the entire vx project to adopt the same license.
> Consider using it via system package manager instead.

**若许可证属于“禁止”类别,请勿创建provider,并告知用户:**

> ⚠️ 无法集成{tool}:它使用的{license}具有左版感染特性,会要求整个vx项目采用相同许可证。
> 建议通过系统包管理器使用该工具。

Installation Type Decision Tree

安装类型决策树

Before creating a provider, determine the installation method:
Does the tool provide portable binaries for all platforms?
├─ Yes → Standard Download Provider
│   └─ Examples: terraform, just, kubectl, helm, go, node
└─ No → Check platform availability
    ├─ Some platforms have binaries → Hybrid Provider (download + package manager)
    │   └─ Examples: imagemagick (Linux AppImage, macOS/Windows via brew/winget)
    │   └─ Examples: ffmpeg (Windows binary, macOS/Linux via brew/apt)
    └─ No portable binaries → System Package Manager Only
        └─ Examples: make, git (on non-Windows), curl, openssl
创建provider前,确定安装方式:
工具是否为所有平台提供可移植二进制文件?
├─ 是 → 标准下载Provider
│   └─ 示例:terraform、just、kubectl、helm、go、node
└─ 否 → 检查平台可用性
    ├─ 部分平台有二进制文件 → 混合Provider(下载 + 包管理器)
    │   └─ 示例:imagemagick(Linux用AppImage,macOS/Windows用brew/winget)
    │   └─ 示例:ffmpeg(Windows用二进制,macOS/Linux用brew/apt)
    └─ 无任何可移植二进制文件 → 仅系统包管理器
        └─ 示例:make、git(非Windows平台)、curl、openssl

Provider Types Summary

Provider类型总结

TypeDirect DownloadPackage Manager FallbackExamples
Standard✅ All platforms❌ Not neededterraform, just, go, node
Hybrid✅ Some platforms✅ For othersimagemagick, ffmpeg, docker
System-only❌ None✅ All platformsmake, curl, openssl
Detection-only❌ None❌ System-installedmsbuild, xcodebuild, systemctl
类型直接下载包管理器回退示例
标准✅ 所有平台❌ 无需terraform、just、go、node
混合✅ 部分平台✅ 其他平台使用imagemagick、ffmpeg、docker
仅系统❌ 无✅ 所有平台make、curl、openssl
仅检测❌ 无❌ 仅系统已安装msbuild、xcodebuild、systemctl

Step 1: Create Feature Branch

步骤1:创建功能分支

bash
git fetch origin main
git checkout -b feature/{name}-provider origin/main
Replace
{name}
with the tool name (lowercase, e.g.,
ripgrep
,
fd
).
bash
git fetch origin main
git checkout -b feature/{name}-provider origin/main
{name}
替换为工具名称(小写,例如
ripgrep
fd
)。

Step 2: Create Provider Directory Structure

步骤2:创建Provider目录结构

Create the following structure under
crates/vx-providers/{name}/
:
crates/vx-providers/{name}/
├── Cargo.toml
├── provider.toml       # Provider manifest (metadata, runtimes, constraints)
├── src/
│   ├── lib.rs          # Module exports + create_provider() factory
│   ├── provider.rs     # Provider trait implementation
│   ├── runtime.rs      # Runtime trait implementation
│   └── config.rs       # URL builder and platform configuration
└── tests/
    └── runtime_tests.rs  # Unit tests (using rstest)
crates/vx-providers/{name}/
下创建以下结构:
crates/vx-providers/{name}/
├── Cargo.toml
├── provider.toml       # Provider清单(元数据、运行时、约束)
├── src/
│   ├── lib.rs          # 模块导出 + create_provider()工厂函数
│   ├── provider.rs     # Provider trait实现
│   ├── runtime.rs      # Runtime trait实现
│   └── config.rs       # URL构建器和平台配置
└── tests/
    └── runtime_tests.rs  # 单元测试(使用rstest)

Step 2.1: Create provider.toml Manifest

步骤2.1:创建provider.toml清单

The
provider.toml
file is the declarative manifest for the provider. It defines:
  • Provider metadata (name, description, homepage, ecosystem)
  • Runtime definitions (executable, aliases, bundled tools)
  • Version source configuration
  • RFC 0019: Layout configuration (for binary/archive downloads)
  • Platform-specific settings
  • Dependency constraints
Ecosystems available:
nodejs
,
python
,
rust
,
go
,
devtools
,
system
,
zig
Version sources:
  • github-releases
    - GitHub Release API (most common)
  • github-tags
    - GitHub Tags API
  • nodejs-org
    - Node.js official releases
  • python-build-standalone
    - Python standalone builds
  • go-dev
    - Go official downloads
  • zig-download
    - Zig official downloads
RFC 0019 Layout Types:
  • binary
    - Single file download (needs renaming/placement)
  • archive
    - Compressed archive (tar.gz, zip, tar.xz)
See
references/templates.md
for complete provider.toml template. See
references/rfc-0019-layout.md
for RFC 0019 layout configuration guide.
provider.toml
文件是provider的声明式清单,它定义:
  • Provider元数据(名称、描述、主页、生态系统)
  • Runtime定义(可执行文件、别名、捆绑工具)
  • 版本源配置
  • RFC 0019:布局配置(用于二进制/归档文件下载)
  • 平台特定设置
  • 依赖约束
可用的生态系统:
nodejs
python
rust
go
devtools
system
zig
版本源:
  • github-releases
    - GitHub Release API(最常用)
  • github-tags
    - GitHub Tags API
  • nodejs-org
    - Node.js官方发布源
  • python-build-standalone
    - Python独立构建版本
  • go-dev
    - Go官方下载源
  • zig-download
    - Zig官方下载源
RFC 0019布局类型:
  • binary
    - 单文件下载(需要重命名/放置)
  • archive
    - 压缩归档(tar.gz、zip、tar.xz)
完整的provider.toml模板请参考
references/templates.md
。 RFC 0019布局配置指南请参考
references/rfc-0019-layout.md

Step 3: Implement Core Files

步骤3:实现核心文件

Refer to
references/templates.md
for complete code templates.
完整代码模板请参考
references/templates.md

Key Implementation Points

关键实现要点

Cargo.toml: Use workspace dependencies, package name
vx-provider-{name}
lib.rs: Export types and provide
create_provider()
factory function
provider.rs: Implement Provider trait with:
  • name()
    - Provider name (lowercase)
  • description()
    - Human-readable description
  • runtimes()
    - Return all Runtime instances
  • supports(name)
    - Check if runtime name is supported
  • get_runtime(name)
    - Get Runtime by name
runtime.rs: Implement Runtime trait with:
  • name()
    - Runtime name
  • description()
    - Description
  • aliases()
    - Alternative names (if any)
  • ecosystem()
    - One of: System, NodeJs, Python, Rust, Go
  • metadata()
    - Homepage, documentation, category
  • fetch_versions(ctx)
    - Fetch available versions
  • download_url(version, platform)
    - Build download URL
  • Executable Path Configuration (layered approach, most providers only need 1-2):
    • executable_name()
      - Base name of executable (default:
      name()
      )
    • executable_extensions()
      - Windows extensions (default:
      [".exe"]
      , use
      [".cmd", ".exe"]
      for npm/yarn)
    • executable_dir_path(version, platform)
      - Directory containing executable (default: install root)
    • executable_relative_path(version, platform)
      - Full path (auto-generated from above, rarely override)
  • verify_installation(version, install_path, platform)
    - Verify installation
config.rs: Implement URL builder with:
  • download_url(version, platform)
    - Full download URL
  • get_target_triple(platform)
    - Platform target triple
  • get_archive_extension(platform)
    - Archive extension (zip/tar.gz)
  • get_executable_name(platform)
    - Executable name with extension
Cargo.toml:使用工作区依赖,包名为
vx-provider-{name}
lib.rs:导出类型并提供
create_provider()
工厂函数
provider.rs:实现Provider trait,包含:
  • name()
    - Provider名称(小写)
  • description()
    - 人类可读的描述
  • runtimes()
    - 返回所有Runtime实例
  • supports(name)
    - 检查是否支持该runtime名称
  • get_runtime(name)
    - 通过名称获取Runtime
runtime.rs:实现Runtime trait,包含:
  • name()
    - Runtime名称
  • description()
    - 描述
  • aliases()
    - 替代名称(如有)
  • ecosystem()
    - 可选值:System、NodeJs、Python、Rust、Go
  • metadata()
    - 主页、文档、分类
  • fetch_versions(ctx)
    - 获取可用版本
  • download_url(version, platform)
    - 构建下载URL
  • 可执行文件路径配置(分层方法,大多数provider仅需1-2种配置):
    • executable_name()
      - 可执行文件的基础名称(默认:
      name()
    • executable_extensions()
      - Windows平台的扩展名(默认:
      [".exe"]
      ,npm/yarn使用
      [".cmd", ".exe"]
    • executable_dir_path(version, platform)
      - 包含可执行文件的目录(默认:安装根目录)
    • executable_relative_path(version, platform)
      - 完整路径(由上述配置自动生成,极少需要覆盖)
  • verify_installation(version, install_path, platform)
    - 验证安装
config.rs:实现URL构建器,包含:
  • download_url(version, platform)
    - 完整下载URL
  • get_target_triple(platform)
    - 平台目标三元组
  • get_archive_extension(platform)
    - 归档文件扩展名(zip/tar.gz)
  • get_executable_name(platform)
    - 带扩展名的可执行文件名称

Step 4: Register Provider

步骤4:注册Provider

4.1 Update Root Cargo.toml

4.1 更新根目录Cargo.toml

Add to
[workspace]
members:
toml
"crates/vx-providers/{name}",
Add to
[workspace.dependencies]
:
toml
vx-provider-{name} = { path = "crates/vx-providers/{name}" }
[workspace]
members中添加:
toml
"crates/vx-providers/{name}",
[workspace.dependencies]
中添加:
toml
vx-provider-{name} = { path = "crates/vx-providers/{name}" }

4.2 Update vx-cli/Cargo.toml

4.2 更新vx-cli/Cargo.toml

Add dependency:
toml
vx-provider-{name} = { workspace = true }
添加依赖:
toml
vx-provider-{name} = { workspace = true }

4.3 Update registry.rs

4.3 更新registry.rs

In
crates/vx-cli/src/registry.rs
, add:
rust
// Register {Name} provider
registry.register(vx_provider_{name}::create_provider());
crates/vx-cli/src/registry.rs
中添加:
rust
// 注册{Name} provider
registry.register(vx_provider_{name}::create_provider());

Step 5: Project Analyzer Integration (Optional)

步骤5:项目分析器集成(可选)

If the new tool corresponds to a language/ecosystem (e.g., Go, Java, PHP), add project analyzer support.
如果新工具对应某一语言/生态系统(例如Go、Java、PHP),可添加项目分析器支持。

5.1 Create Language Analyzer Directory

5.1 创建语言分析器目录

crates/vx-project-analyzer/src/languages/{lang}/
├── mod.rs          # Module exports
├── analyzer.rs     # {Lang}Analyzer implementation
├── dependencies.rs # Dependency parsing
├── rules.rs        # Script detection rules
└── scripts.rs      # Explicit script parsing
crates/vx-project-analyzer/src/languages/{lang}/
├── mod.rs          # 模块导出
├── analyzer.rs     # {Lang}Analyzer实现
├── dependencies.rs # 依赖解析
├── rules.rs        # 脚本检测规则
└── scripts.rs      # 显式脚本解析

5.2 Define Script Detection Rules

5.2 定义脚本检测规则

rust
// rules.rs
use crate::languages::rules::ScriptRule;

pub const {LANG}_RULES: &[ScriptRule] = &[
    ScriptRule::new("build", "{build_command}", "Build the project")
        .triggers(&["{config_file}"])
        .priority(50),
    ScriptRule::new("test", "{test_command}", "Run tests")
        .triggers(&["{test_config}", "tests"])
        .priority(50),
    ScriptRule::new("lint", "{lint_command}", "Run linter")
        .triggers(&["{lint_config}"])
        .excludes(&["{task_runner_config}"])
        .priority(50),
];
rust
// rules.rs
use crate::languages::rules::ScriptRule;

pub const {LANG}_RULES: &[ScriptRule] = &[
    ScriptRule::new("build", "{build_command}", "构建项目")
        .triggers(&["{config_file}"])
        .priority(50),
    ScriptRule::new("test", "{test_command}", "运行测试")
        .triggers(&["{test_config}", "tests"])
        .priority(50),
    ScriptRule::new("lint", "{lint_command}", "运行代码检查")
        .triggers(&["{lint_config}"])
        .excludes(&["{task_runner_config}"])
        .priority(50),
];

5.3 Implement LanguageAnalyzer

5.3 实现LanguageAnalyzer

rust
// analyzer.rs
use super::rules::{LANG}_RULES;
use crate::languages::rules::{apply_rules, merge_scripts};
use crate::languages::LanguageAnalyzer;

pub struct {Lang}Analyzer {
    script_parser: ScriptParser,
}

#[async_trait]
impl LanguageAnalyzer for {Lang}Analyzer {
    fn detect(&self, root: &Path) -> bool {
        root.join("{config_file}").exists()
    }

    fn name(&self) -> &'static str {
        "{Lang}"
    }

    async fn analyze_dependencies(&self, root: &Path) -> AnalyzerResult<Vec<Dependency>> {
        // Parse {config_file} for dependencies
    }

    async fn analyze_scripts(&self, root: &Path) -> AnalyzerResult<Vec<Script>> {
        // 1. Parse explicit scripts from config
        let explicit = parse_config_scripts(root, &self.script_parser).await?;
        
        // 2. Apply detection rules
        let detected = apply_rules(root, {LANG}_RULES, &self.script_parser);
        
        // 3. Merge (explicit takes priority)
        Ok(merge_scripts(explicit, detected))
    }

    fn required_tools(&self, _deps: &[Dependency], _scripts: &[Script]) -> Vec<RequiredTool> {
        vec![RequiredTool::new(
            "{tool}",
            Ecosystem::{Ecosystem},
            "{Tool} runtime",
            InstallMethod::vx("{tool}"),
        )]
    }

    fn install_command(&self, dep: &Dependency) -> Option<String> {
        Some(format!("{package_manager} add {}", dep.name))
    }
}
rust
// analyzer.rs
use super::rules::{LANG}_RULES;
use crate::languages::rules::{apply_rules, merge_scripts};
use crate::languages::LanguageAnalyzer;

pub struct {Lang}Analyzer {
    script_parser: ScriptParser,
}

#[async_trait]
impl LanguageAnalyzer for {Lang}Analyzer {
    fn detect(&self, root: &Path) -> bool {
        root.join("{config_file}").exists()
    }

    fn name(&self) -> &'static str {
        "{Lang}"
    }

    async fn analyze_dependencies(&self, root: &Path) -> AnalyzerResult<Vec<Dependency>> {
        // 解析{config_file}获取依赖
    }

    async fn analyze_scripts(&self, root: &Path) -> AnalyzerResult<Vec<Script>> {
        // 1. 从配置文件解析显式脚本
        let explicit = parse_config_scripts(root, &self.script_parser).await?;
        
        // 2. 应用检测规则
        let detected = apply_rules(root, {LANG}_RULES, &self.script_parser);
        
        // 3. 合并(显式脚本优先级更高)
        Ok(merge_scripts(explicit, detected))
    }

    fn required_tools(&self, _deps: &[Dependency], _scripts: &[Script]) -> Vec<RequiredTool> {
        vec![RequiredTool::new(
            "{tool}",
            Ecosystem::{Ecosystem},
            "{Tool} runtime",
            InstallMethod::vx("{tool}"),
        )]
    }

    fn install_command(&self, dep: &Dependency) -> Option<String> {
        Some(format!("{package_manager} add {}", dep.name))
    }
}

5.4 Register Analyzer

5.4 注册分析器

In
crates/vx-project-analyzer/src/languages/mod.rs
:
rust
mod {lang};
pub use {lang}::{Lang}Analyzer;

pub fn all_analyzers() -> Vec<Box<dyn LanguageAnalyzer>> {
    vec![
        // ... existing analyzers
        Box::new({Lang}Analyzer::new()),
    ]
}
crates/vx-project-analyzer/src/languages/mod.rs
中:
rust
mod {lang};
pub use {lang}::{Lang}Analyzer;

pub fn all_analyzers() -> Vec<Box<dyn LanguageAnalyzer>> {
    vec![
        // ... 现有分析器
        Box::new({Lang}Analyzer::new()),
    ]
}

5.5 Add Analyzer Tests

5.5 添加分析器测试

rust
// crates/vx-project-analyzer/tests/analyzer_tests.rs

#[tokio::test]
async fn test_{lang}_project_detection() {
    let temp = TempDir::new().unwrap();
    std::fs::write(temp.path().join("{config_file}"), "...").unwrap();
    
    let analyzer = {Lang}Analyzer::new();
    assert!(analyzer.detect(temp.path()));
}

#[tokio::test]
async fn test_{lang}_scripts() {
    let temp = TempDir::new().unwrap();
    std::fs::write(temp.path().join("{config_file}"), "...").unwrap();
    
    let analyzer = {Lang}Analyzer::new();
    let scripts = analyzer.analyze_scripts(temp.path()).await.unwrap();
    
    assert!(scripts.iter().any(|s| s.name == "test"));
}
rust
// crates/vx-project-analyzer/tests/analyzer_tests.rs

#[tokio::test]
async fn test_{lang}_project_detection() {
    let temp = TempDir::new().unwrap();
    std::fs::write(temp.path().join("{config_file}"), "...").unwrap();
    
    let analyzer = {Lang}Analyzer::new();
    assert!(analyzer.detect(temp.path()));
}

#[tokio::test]
async fn test_{lang}_scripts() {
    let temp = TempDir::new().unwrap();
    std::fs::write(temp.path().join("{config_file}"), "...").unwrap();
    
    let analyzer = {Lang}Analyzer::new();
    let scripts = analyzer.analyze_scripts(temp.path()).await.unwrap();
    
    assert!(scripts.iter().any(|s| s.name == "test"));
}

Step 6: Update Snapshot Tests

步骤6:更新快照测试

Update provider/runtime counts in:
  • tests/cmd/plugin/plugin-stats.md
    - Increment "Total providers" and "Total runtimes"
  • tests/cmd/search/search.md
    - Add the new runtime to the search results
在以下文件中更新provider/runtime计数:
  • tests/cmd/plugin/plugin-stats.md
    - 增加“Total providers”和“Total runtimes”的数值
  • tests/cmd/search/search.md
    - 在搜索结果中添加新的runtime

Step 7: Add Documentation

步骤7:添加文档

Add documentation for the new tool in the appropriate category:
在对应分类中添加新工具的文档:

English Documentation (
docs/tools/
)

英文文档(
docs/tools/

CategoryFileTools
DevOps
devops.md
terraform, docker, kubectl, helm, git
Cloud CLI
cloud.md
aws, az, gcloud
Build Tools
build-tools.md
just, task, cmake, ninja, protoc, vite
AI Tools
ai.md
ollama
Scientific/HPC
scientific.md
spack, rez
Code Quality
quality.md
pre-commit
Other
other.md
deno, zig, java, vscode, rcedit, choco
分类文件工具
DevOps
devops.md
terraform、docker、kubectl、helm、git
Cloud CLI
cloud.md
aws、az、gcloud
Build Tools
build-tools.md
just、task、cmake、ninja、protoc、vite
AI Tools
ai.md
ollama
Scientific/HPC
scientific.md
spack、rez
Code Quality
quality.md
pre-commit
Other
other.md
deno、zig、java、vscode、rcedit、choco

Chinese Documentation (
docs/zh/tools/
)

中文文档(
docs/zh/tools/

Create corresponding Chinese documentation with the same structure.
创建结构相同的对应中文文档。

Documentation Template

文档模板

markdown
undefined
markdown
undefined

{Tool Name}

{Tool Name}

{Brief description}
bash
vx install {name} latest

vx {name} --version
vx {name} {common-command-1}
vx {name} {common-command-2}
Key Features: (optional)
  • Feature 1
  • Feature 2
Platform Support: (if special)
  • Windows: {notes}
  • Linux/macOS: {notes}
undefined
{简要描述}
bash
vx install {name} latest

vx {name} --version
vx {name} {common-command-1}
vx {name} {common-command-2}
主要特性:(可选)
  • 特性1
  • 特性2
平台支持:(如有特殊说明)
  • Windows: {说明}
  • Linux/macOS: {说明}
undefined

Step 8: Version Fetching Strategies

步骤8:版本获取策略

GitHub Releases (Preferred)

GitHub Releases(首选)

rust
ctx.fetch_github_releases(
    "runtime-name",
    "owner",
    "repo",
    GitHubReleaseOptions::new()
        .strip_v_prefix(false)  // Set true if versions have 'v' prefix
        .skip_prereleases(true),
).await
rust
ctx.fetch_github_releases(
    "runtime-name",
    "owner",
    "repo",
    GitHubReleaseOptions::new()
        .strip_v_prefix(false)  // 若版本带有'v'前缀则设为true
        .skip_prereleases(true),
).await

Manual GitHub API

手动调用GitHub API

rust
let url = "https://api.github.com/repos/{owner}/{repo}/releases";
let response = ctx.http.get_json_value(url).await?;
// Parse response and build VersionInfo
rust
let url = "https://api.github.com/repos/{owner}/{repo}/releases";
let response = ctx.http.get_json_value(url).await?;
// 解析响应并构建VersionInfo

Step 9: Verification and Testing

步骤9:验证与测试

bash
undefined
bash
undefined

Check compilation

检查编译

cargo check -p vx-provider-{name}
cargo check -p vx-provider-{name}

Run tests

运行测试

cargo test -p vx-provider-{name}
cargo test -p vx-provider-{name}

If analyzer was added

若添加了分析器

cargo test -p vx-project-analyzer
cargo test -p vx-project-analyzer

Verify full workspace

验证整个工作区

cargo check
cargo check

Run snapshot tests

运行快照测试

cargo test --test cli_tests
undefined
cargo test --test cli_tests
undefined

Common Patterns

常见模式

VersionInfo Construction

VersionInfo构建

rust
VersionInfo::new(version)
    .with_lts(false)
    .with_prerelease(false)
    .with_release_date(date_string)
rust
VersionInfo::new(version)
    .with_lts(false)
    .with_prerelease(false)
    .with_release_date(date_string)

VerificationResult

VerificationResult

rust
// Success
VerificationResult::success(exe_path)

// Failure
VerificationResult::failure(
    vec!["Error message".to_string()],
    vec!["Suggested fix".to_string()],
)
rust
// 成功
VerificationResult::success(exe_path)

// 失败
VerificationResult::failure(
    vec!["错误信息".to_string()],
    vec!["建议修复方案".to_string()],
)

Platform Matching

平台匹配

rust
match (&platform.os, &platform.arch) {
    (Os::Windows, Arch::X86_64) => Some("x86_64-pc-windows-msvc"),
    (Os::Windows, Arch::Aarch64) => Some("aarch64-pc-windows-msvc"),
    (Os::MacOS, Arch::X86_64) => Some("x86_64-apple-darwin"),
    (Os::MacOS, Arch::Aarch64) => Some("aarch64-apple-darwin"),
    (Os::Linux, Arch::X86_64) => Some("x86_64-unknown-linux-musl"),
    (Os::Linux, Arch::Aarch64) => Some("aarch64-unknown-linux-musl"),
    _ => None,
}
rust
match (&platform.os, &platform.arch) {
    (Os::Windows, Arch::X86_64) => Some("x86_64-pc-windows-msvc"),
    (Os::Windows, Arch::Aarch64) => Some("aarch64-pc-windows-msvc"),
    (Os::MacOS, Arch::X86_64) => Some("x86_64-apple-darwin"),
    (Os::MacOS, Arch::Aarch64) => Some("aarch64-apple-darwin"),
    (Os::Linux, Arch::X86_64) => Some("x86_64-unknown-linux-musl"),
    (Os::Linux, Arch::Aarch64) => Some("aarch64-unknown-linux-musl"),
    _ => None,
}

Executable Path Configuration (Layered API)

可执行文件路径配置(分层API)

The framework provides a layered approach - most providers only need 1-2 overrides:
rust
// 1. Simple case: executable in root with standard .exe
// No overrides needed, defaults work

// 2. Tool uses .cmd on Windows (npm, yarn, npx)
fn executable_extensions(&self) -> &[&str] {
    &[".cmd", ".exe"]
}

// 3. Executable in subdirectory
fn executable_dir_path(&self, version: &str, _platform: &Platform) -> Option<String> {
    Some(format!("myapp-{}", version))
}

// 4. Different executable name than runtime name
fn executable_name(&self) -> &str {
    "python3"  // Runtime name is "python"
}

// 5. Complex platform-specific paths (Node.js style)
fn executable_dir_path(&self, version: &str, platform: &Platform) -> Option<String> {
    let dir = format!("node-v{}-{}", version, platform.as_str());
    if platform.is_windows() {
        Some(dir)  // Windows: no bin subdir
    } else {
        Some(format!("{}/bin", dir))  // Unix: has bin subdir
    }
}
框架提供分层方法 - 大多数provider仅需1-2种覆盖配置:
rust
// 1. 简单情况:可执行文件在根目录,使用标准.exe扩展名
// 无需覆盖,默认配置即可

// 2. 工具在Windows上使用.cmd扩展名(npm、yarn、npx)
fn executable_extensions(&self) -> &[&str] {
    &[".cmd", ".exe"]
}

// 3. 可执行文件在子目录中
fn executable_dir_path(&self, version: &str, _platform: &Platform) -> Option<String> {
    Some(format!("myapp-{}", version))
}

// 4. 可执行文件名称与runtime名称不同
fn executable_name(&self) -> &str {
    "python3"  // Runtime名称是"python"
}

// 5. 复杂的平台特定路径(Node.js风格)
fn executable_dir_path(&self, version: &str, platform: &Platform) -> Option<String> {
    let dir = format!("node-v{}-{}", version, platform.as_str());
    if platform.is_windows() {
        Some(dir)  // Windows:无bin子目录
    } else {
        Some(format!("{}/bin", dir))  // Unix:有bin子目录
    }
}

ScriptRule Priority Guidelines

ScriptRule优先级指南

PriorityUse Case
100Task runners (nox, tox, just, make)
90Secondary task runners
50Default tools (pytest, ruff, cargo)
优先级使用场景
100任务运行器(nox、tox、just、make)
90次要任务运行器
50默认工具(pytest、ruff、cargo)

System Package Manager Integration

系统包管理器集成

For tools without portable binaries on all platforms, implement system package manager fallback.
对于并非所有平台都有可移植二进制文件的工具,实现系统包管理器回退。

When to Use System Package Manager

何时使用系统包管理器

PlatformNo Direct DownloadPackage Manager Options
macOSNo portable binarybrew (priority 90)
WindowsNo portable binarywinget (95), choco (80), scoop (60)
LinuxNo portable binaryapt (90), dnf (85), pacman (80)
平台无直接下载包包管理器选项
macOS无可移植二进制文件brew(优先级90)
Windows无可移植二进制文件winget(95)、choco(80)、scoop(60)
Linux无可移植二进制文件apt(90)、dnf(85)、pacman(80)

Step 1: Add system_deps.pre_depends in provider.toml

步骤1:在provider.toml中添加system_deps.pre_depends

Declare which package managers are required as dependencies:
toml
undefined
声明所需的包管理器依赖:
toml
undefined

macOS requires Homebrew

macOS需要Homebrew

[[runtimes.system_deps.pre_depends]] type = "runtime" id = "brew" platforms = ["macos"] reason = "Required to install {tool} on macOS (no portable binary available)" optional = false # brew is required
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "brew" platforms = ["macos"] reason = "在macOS上安装{tool}需要依赖Homebrew(无可移植二进制文件)" optional = false # brew是必需的

Windows: winget (preferred), choco, or scoop (any one is sufficient)

Windows:winget(首选)、choco或scoop(任意一个即可)

[[runtimes.system_deps.pre_depends]] type = "runtime" id = "winget" platforms = ["windows"] reason = "Preferred package manager for Windows (built-in on Windows 11)" optional = true # any one of winget/choco/scoop is sufficient
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "choco" platforms = ["windows"] reason = "Alternative to winget for Windows installation" optional = true
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "scoop" platforms = ["windows"] reason = "Alternative to winget for Windows installation" optional = true
undefined
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "winget" platforms = ["windows"] reason = "Windows首选包管理器(Windows 11内置)" optional = true # winget/choco/scoop任意一个即可
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "choco" platforms = ["windows"] reason = "Windows安装的替代包管理器" optional = true
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "scoop" platforms = ["windows"] reason = "Windows安装的替代包管理器" optional = true
undefined

Step 2: Add system_install.strategies in provider.toml

步骤2:在provider.toml中添加system_install.strategies

Define how to install via each package manager:
toml
undefined
定义通过各包管理器安装的方式:
toml
undefined

System installation strategies for platforms without direct download

无直接下载包的平台使用系统安装策略

[[runtimes.system_install.strategies]] type = "package_manager" manager = "brew" package = "mytool" # Homebrew package name platforms = ["macos"] priority = 90
[[runtimes.system_install.strategies]] type = "package_manager" manager = "winget" package = "Publisher.Package" # winget uses Publisher.Package format platforms = ["windows"] priority = 95 # Highest priority on Windows (built-in on Win11)
[[runtimes.system_install.strategies]] type = "package_manager" manager = "choco" package = "mytool" platforms = ["windows"] priority = 80
[[runtimes.system_install.strategies]] type = "package_manager" manager = "scoop" package = "mytool" platforms = ["windows"] priority = 60
undefined
[[runtimes.system_install.strategies]] type = "package_manager" manager = "brew" package = "mytool" # Homebrew中的包名 platforms = ["macos"] priority = 90
[[runtimes.system_install.strategies]] type = "package_manager" manager = "winget" package = "Publisher.Package" # winget使用Publisher.Package格式 platforms = ["windows"] priority = 95 # Windows上优先级最高(Win11内置)
[[runtimes.system_install.strategies]] type = "package_manager" manager = "choco" package = "mytool" platforms = ["windows"] priority = 80
[[runtimes.system_install.strategies]] type = "package_manager" manager = "scoop" package = "mytool" platforms = ["windows"] priority = 60
undefined

Step 3: Implement install() Method with Fallback

步骤3:实现带有回退的install()方法

For hybrid providers, override
install()
to try direct download first, then fall back to package manager:
rust
use vx_system_pm::{PackageInstallSpec, PackageManagerRegistry};
use vx_runtime::{InstallResult, Runtime, RuntimeContext};

impl MyRuntime {
    /// Get package name for specific package manager
    fn get_package_name_for_manager(manager: &str) -> &'static str {
        match manager {
            "winget" => "Publisher.MyTool",  // winget uses Publisher.Package format
            "brew" | "choco" | "scoop" | "apt" => "mytool",
            "dnf" | "yum" => "MyTool",  // Some use different casing
            _ => "mytool",
        }
    }

    /// Install via system package manager
    async fn install_via_package_manager(
        &self,
        version: &str,
        _ctx: &RuntimeContext,
    ) -> Result<InstallResult> {
        let registry = PackageManagerRegistry::new();
        let available_managers = registry.get_available().await;

        if available_managers.is_empty() {
            return Err(anyhow::anyhow!(
                "No package manager available. Please install brew (macOS) or winget/choco/scoop (Windows)"
            ));
        }

        // Try each available package manager (sorted by priority)
        for pm in &available_managers {
            let package_name = Self::get_package_name_for_manager(pm.name());
            let spec = PackageInstallSpec {
                package: package_name.to_string(),
                ..Default::default()
            };

            match pm.install_package(&spec).await {
                Ok(_) => {
                    // Return system-installed result with actual executable path
                    let exe_path = which::which("mytool").ok();
                    return Ok(InstallResult::system_installed(
                        format!("{} (via {})", version, pm.name()),
                        exe_path,
                    ));
                }
                Err(e) => {
                    tracing::warn!("Failed to install via {}: {}", pm.name(), e);
                    continue;
                }
            }
        }

        Err(anyhow::anyhow!("All package managers failed"))
    }
}

#[async_trait]
impl Runtime for MyRuntime {
    async fn install(&self, version: &str, ctx: &RuntimeContext) -> Result<InstallResult> {
        let platform = Platform::current();

        // Try direct download first (if available for this platform)
        if let Some(url) = self.download_url(version, &platform).await? {
            return self.install_via_download(version, &url, ctx).await;
        }

        // Fall back to system package manager
        self.install_via_package_manager(version, ctx).await
    }
}
对于混合provider,覆盖
install()
方法,先尝试直接下载,失败则回退到包管理器:
rust
use vx_system_pm::{PackageInstallSpec, PackageManagerRegistry};
use vx_runtime::{InstallResult, Runtime, RuntimeContext};

impl MyRuntime {
    /// 获取特定包管理器对应的包名
    fn get_package_name_for_manager(manager: &str) -> &'static str {
        match manager {
            "winget" => "Publisher.MyTool",  // winget使用Publisher.Package格式
            "brew" | "choco" | "scoop" | "apt" => "mytool",
            "dnf" | "yum" => "MyTool",  // 部分包管理器使用不同大小写
            _ => "mytool",
        }
    }

    /// 通过系统包管理器安装
    async fn install_via_package_manager(
        &self,
        version: &str,
        _ctx: &RuntimeContext,
    ) -> Result<InstallResult> {
        let registry = PackageManagerRegistry::new();
        let available_managers = registry.get_available().await;

        if available_managers.is_empty() {
            return Err(anyhow::anyhow!(
                "无可用包管理器。请安装brew(macOS)或winget/choco/scoop(Windows)"
            ));
        }

        // 按优先级尝试每个可用的包管理器
        for pm in &available_managers {
            let package_name = Self::get_package_name_for_manager(pm.name());
            let spec = PackageInstallSpec {
                package: package_name.to_string(),
                ..Default::default()
            };

            match pm.install_package(&spec).await {
                Ok(_) => {
                    // 返回系统安装结果及实际可执行文件路径
                    let exe_path = which::which("mytool").ok();
                    return Ok(InstallResult::system_installed(
                        format!("{} (via {})", version, pm.name()),
                        exe_path,
                    ));
                }
                Err(e) => {
                    tracing::warn!("通过{}安装失败: {}", pm.name(), e);
                    continue;
                }
            }
        }

        Err(anyhow::anyhow!("所有包管理器安装均失败"))
    }
}

#[async_trait]
impl Runtime for MyRuntime {
    async fn install(&self, version: &str, ctx: &RuntimeContext) -> Result<InstallResult> {
        let platform = Platform::current();

        // 首先尝试直接下载(若该平台支持)
        if let Some(url) = self.download_url(version, &platform).await? {
            return self.install_via_download(version, &url, ctx).await;
        }

        // 回退到系统包管理器
        self.install_via_package_manager(version, ctx).await
    }
}

Step 4: Handle InstallResult Correctly

步骤4:正确处理InstallResult

Important: System-installed tools have different paths than store-installed tools:
rust
// Store-installed: executable in ~/.vx/store/{tool}/{version}/bin/
InstallResult::success(install_path, exe_path, version)

// System-installed: executable in system PATH (e.g., /opt/homebrew/bin/)
InstallResult::system_installed(version, Some(exe_path))
The test handler and other code must check
executable_path
from
InstallResult
rather than computing store paths.
重要提示:系统安装的工具路径与存储安装的工具路径不同:
rust
// 存储安装:可执行文件在~/.vx/store/{tool}/{version}/bin/
InstallResult::success(install_path, exe_path, version)

// 系统安装:可执行文件在系统PATH中(例如/opt/homebrew/bin/)
InstallResult::system_installed(version, Some(exe_path))
测试处理程序及其他代码必须从
InstallResult
中获取
executable_path
,而非计算存储路径。

Package Manager Priority Reference

包管理器优先级参考

ManagerPlatformPriorityNotes
wingetWindows95Built-in on Win11, App Installer on Win10
brewmacOS90De-facto standard for macOS
aptLinux (Debian)90Debian/Ubuntu default
dnfLinux (Fedora)85Fedora/RHEL default
chocoWindows80Popular third-party
pacmanLinux (Arch)80Arch Linux default
scoopWindows60Developer-focused
管理器平台优先级说明
wingetWindows95Windows 11内置,Windows 10需安装App Installer
brewmacOS90macOS事实上的标准包管理器
aptLinux (Debian)90Debian/Ubuntu默认包管理器
dnfLinux (Fedora)85Fedora/RHEL默认包管理器
chocoWindows80流行的第三方包管理器
pacmanLinux (Arch)80Arch Linux默认包管理器
scoopWindows60面向开发者的包管理器

Common Package Names

常见包名对应表

Toolbrewwingetchocoscoopapt
ImageMagickimagemagickImageMagick.ImageMagickimagemagickimagemagickimagemagick
FFmpegffmpegGyan.FFmpegffmpegffmpegffmpeg
GitgitGit.Gitgitgitgit
AWS CLIawscliAmazon.AWSCLIawscliawsawscli
Azure CLIazure-cliMicrosoft.AzureCLIazure-cli-azure-cli
DockerdockerDocker.DockerDesktopdocker-desktop-docker.io
工具brewwingetchocoscoopapt
ImageMagickimagemagickImageMagick.ImageMagickimagemagickimagemagickimagemagick
FFmpegffmpegGyan.FFmpegffmpegffmpegffmpeg
GitgitGit.Gitgitgitgit
AWS CLIawscliAmazon.AWSCLIawscliawsawscli
Azure CLIazure-cliMicrosoft.AzureCLIazure-cli-azure-cli
DockerdockerDocker.DockerDesktopdocker-desktop-docker.io

provider.toml Quick Reference

provider.toml快速参考

Minimal Example (GitHub Releases with Layout)

最小示例(GitHub Releases + 布局配置)

toml
[provider]
name = "mytool"
description = "My awesome tool"
homepage = "https://github.com/owner/repo"
repository = "https://github.com/owner/repo"
ecosystem = "devtools"

[[runtimes]]
name = "mytool"
description = "My tool CLI"
executable = "mytool"

[runtimes.versions]
source = "github-releases"
owner = "owner"
repo = "repo"
strip_v_prefix = true
toml
[provider]
name = "mytool"
description = "My awesome tool"
homepage = "https://github.com/owner/repo"
repository = "https://github.com/owner/repo"
ecosystem = "devtools"

[[runtimes]]
name = "mytool"
description = "My tool CLI"
executable = "mytool"

[runtimes.versions]
source = "github-releases"
owner = "owner"
repo = "repo"
strip_v_prefix = true

RFC 0019: Executable Layout Configuration

RFC 0019:可执行文件布局配置

[runtimes.layout] download_type = "archive" # or "binary"
[runtimes.layout.archive] strip_prefix = "mytool-{version}" executable_paths = [ "bin/mytool.exe", # Windows "bin/mytool" # Unix ]
[runtimes.platforms.windows] executable_extensions = [".exe"]
[runtimes.platforms.unix] executable_extensions = []
undefined
[runtimes.layout] download_type = "archive" # 或"binary"
[runtimes.layout.archive] strip_prefix = "mytool-{version}" executable_paths = [ "bin/mytool.exe", # Windows "bin/mytool" # Unix ]
[runtimes.platforms.windows] executable_extensions = [".exe"]
[runtimes.platforms.unix] executable_extensions = []
undefined

Binary Download Example

二进制下载示例

toml
[runtimes.layout]
download_type = "binary"

[runtimes.layout.binary."windows-x86_64"]
source_name = "mytool-{version}-win64.exe"
target_name = "mytool.exe"
target_dir = "bin"

[runtimes.layout.binary."linux-x86_64"]
source_name = "mytool-{version}-linux"
target_name = "mytool"
target_dir = "bin"
target_permissions = "755"
toml
[runtimes.layout]
download_type = "binary"

[runtimes.layout.binary."windows-x86_64"]
source_name = "mytool-{version}-win64.exe"
target_name = "mytool.exe"
target_dir = "bin"

[runtimes.layout.binary."linux-x86_64"]
source_name = "mytool-{version}-linux"
target_name = "mytool"
target_dir = "bin"
target_permissions = "755"

Hybrid Provider Example (Direct Download + Package Manager Fallback)

混合Provider示例(直接下载 + 包管理器回退)

For tools like ImageMagick that have direct download on some platforms but need package managers on others:
toml
[provider]
name = "mytool"
description = "My awesome tool"
homepage = "https://example.com"
ecosystem = "devtools"

[[runtimes]]
name = "mytool"
description = "My tool CLI"
executable = "mytool"

[runtimes.versions]
source = "github-releases"
owner = "owner"
repo = "repo"
适用于像ImageMagick这样部分平台有直接下载包、其他平台需要包管理器的工具:
toml
[provider]
name = "mytool"
description = "My awesome tool"
homepage = "https://example.com"
ecosystem = "devtools"

[[runtimes]]
name = "mytool"
description = "My tool CLI"
executable = "mytool"

[runtimes.versions]
source = "github-releases"
owner = "owner"
repo = "repo"

Linux: Direct download available (AppImage, binary, etc.)

Linux:支持直接下载(AppImage、二进制文件等)

[runtimes.layout] download_type = "binary"
[runtimes.layout.binary."linux-x86_64"] source_name = "mytool-{version}-linux-x64" target_name = "mytool" target_dir = "bin" target_permissions = "755"
[runtimes.layout] download_type = "binary"
[runtimes.layout.binary."linux-x86_64"] source_name = "mytool-{version}-linux-x64" target_name = "mytool" target_dir = "bin" target_permissions = "755"

Note: No Windows/macOS binary configs = download_url returns None

注意:未配置Windows/macOS二进制文件 = download_url返回None

Triggers package manager fallback

触发包管理器回退

macOS requires Homebrew

macOS需要Homebrew

[[runtimes.system_deps.pre_depends]] type = "runtime" id = "brew" platforms = ["macos"] reason = "Required to install mytool on macOS (no portable binary available)" optional = false
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "brew" platforms = ["macos"] reason = "在macOS上安装mytool需要依赖Homebrew(无可移植二进制文件)" optional = false

Windows: winget (preferred) or choco/scoop

Windows:winget(首选)或choco/scoop

[[runtimes.system_deps.pre_depends]] type = "runtime" id = "winget" platforms = ["windows"] reason = "Preferred package manager for Windows (built-in on Windows 11)" optional = true
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "choco" platforms = ["windows"] reason = "Alternative to winget for Windows installation" optional = true
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "winget" platforms = ["windows"] reason = "Windows首选包管理器(Windows 11内置)" optional = true
[[runtimes.system_deps.pre_depends]] type = "runtime" id = "choco" platforms = ["windows"] reason = "Windows安装的替代包管理器" optional = true

System installation strategies

系统安装策略

[[runtimes.system_install.strategies]] type = "package_manager" manager = "brew" package = "mytool" platforms = ["macos"] priority = 90
[[runtimes.system_install.strategies]] type = "package_manager" manager = "winget" package = "Publisher.MyTool" platforms = ["windows"] priority = 95
[[runtimes.system_install.strategies]] type = "package_manager" manager = "choco" package = "mytool" platforms = ["windows"] priority = 80
undefined
[[runtimes.system_install.strategies]] type = "package_manager" manager = "brew" package = "mytool" platforms = ["macos"] priority = 90
[[runtimes.system_install.strategies]] type = "package_manager" manager = "winget" package = "Publisher.MyTool" platforms = ["windows"] priority = 95
[[runtimes.system_install.strategies]] type = "package_manager" manager = "choco" package = "mytool" platforms = ["windows"] priority = 80
undefined

provider.toml Fields Reference

provider.toml字段参考

SectionFieldDescription
[provider]
name
Provider name (required)
description
Human-readable description
homepage
Project homepage URL
repository
Source repository URL
ecosystem
nodejs
,
python
,
rust
,
go
,
devtools
,
system
,
zig
[provider.platforms]
os
Restrict to platforms:
["windows"]
,
["macos"]
,
["linux"]
[[runtimes]]
name
Runtime name (required)
description
Runtime description
executable
Executable file name (required)
aliases
Alternative names list
bundled_with
If bundled with another runtime
[runtimes.versions]
source
Version source type
owner
GitHub owner (for github-releases/tags)
repo
GitHub repo name
strip_v_prefix
Remove 'v' from version tags
[runtimes.layout]
download_type
"binary"
or
"archive"
(RFC 0019)
[runtimes.layout.binary."{platform}"]
source_name
Downloaded file name (supports
{version}
)
target_name
Final executable name
target_dir
Target directory (e.g.,
"bin"
)
target_permissions
Unix permissions (e.g.,
"755"
)
[runtimes.layout.archive]
strip_prefix
Directory prefix to remove (supports
{version}
,
{os}
,
{arch}
)
executable_paths
Paths to executables after stripping
[runtimes.executable_config]
dir_pattern
Directory pattern (e.g.,
{name}-{version}
)
extensions
Executable extensions list
[[runtimes.system_deps.pre_depends]]
type
"runtime"
(dependency type)
id
Package manager runtime id (brew, winget, choco, scoop)
platforms
Array of platforms:
["macos"]
,
["windows"]
,
["linux"]
reason
Human-readable reason for dependency
optional
true
if any one of multiple options is sufficient
[[runtimes.system_install.strategies]]
type
"package_manager"
or
"manual"
manager
Package manager name (brew, winget, choco, scoop, apt, dnf)
package
Package name in that manager
platforms
Array of platforms this strategy applies to
priority
Priority (higher = preferred). winget=95, brew=90, choco=80, scoop=60
[[runtimes.constraints]]
when
Version condition (e.g.,
*
,
^1
,
>=2
)
requires
Required dependencies list
recommends
Recommended dependencies list
章节字段描述
[provider]
name
Provider名称(必填)
description
人类可读的描述
homepage
项目主页URL
repository
源码仓库URL
ecosystem
nodejs
python
rust
go
devtools
system
zig
[provider.platforms]
os
限制支持的平台:
["windows"]
["macos"]
["linux"]
[[runtimes]]
name
Runtime名称(必填)
description
Runtime描述
executable
可执行文件名(必填)
aliases
替代名称列表
bundled_with
若该runtime与其他runtime捆绑
[runtimes.versions]
source
版本源类型
owner
GitHub所有者(适用于github-releases/tags)
repo
GitHub仓库名
strip_v_prefix
移除版本标签中的'v'前缀
[runtimes.layout]
download_type
"binary"
"archive"
(RFC 0019)
[runtimes.layout.binary."{platform}"]
source_name
下载文件名(支持
{version}
变量)
target_name
最终可执行文件名
target_dir
目标目录(例如
"bin"
target_permissions
Unix权限(例如
"755"
[runtimes.layout.archive]
strip_prefix
要移除的目录前缀(支持
{version}
{os}
{arch}
变量)
executable_paths
解压后可执行文件的路径
[runtimes.executable_config]
dir_pattern
目录模式(例如
{name}-{version}
extensions
可执行文件扩展名列表
[[runtimes.system_deps.pre_depends]]
type
"runtime"
(依赖类型)
id
包管理器runtime id(brew、winget、choco、scoop)
platforms
适用平台数组:
["macos"]
["windows"]
["linux"]
reason
依赖该包管理器的原因(人类可读)
optional
true
表示多个选项中任意一个即可
[[runtimes.system_install.strategies]]
type
"package_manager"
"manual"
manager
包管理器名称(brew、winget、choco、scoop、apt、dnf)
package
该包管理器中的包名
platforms
该策略适用的平台数组
priority
优先级(数值越高越优先)。winget=95、brew=90、choco=80、scoop=60
[[runtimes.constraints]]
when
版本条件(例如
*
^1
>=2
requires
必填依赖列表
recommends
推荐依赖列表

Reference Files

参考文件

For complete code templates, see
references/templates.md
.
完整代码模板请参考
references/templates.md