askill
vx-provider-creator

vx-provider-creatorSafety 95Repository

This skill should be used when creating a new runtime provider for the vx tool manager. It provides complete templates, code generation, and step-by-step guidance for implementing Provider and Runtime traits, including URL builders, platform configuration, test files, provider.toml manifest, system package manager fallback, and optionally project analyzer integration for language-specific tools. Use this skill when the user asks to add support for a new tool/runtime in vx.

18 stars
1.2k downloads
Updated 3/5/2026

Package Files

Loading files...
SKILL.md

VX Provider Creator

This skill guides the creation of new runtime providers for the vx universal tool manager.

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

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

⚠️ License Compliance (MANDATORY - Step 0)

Before creating ANY provider, you MUST check the upstream tool's license.

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-

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

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

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

provider.toml License Fields

Every provider.toml MUST include:

[provider]
name = "example"
license = "MIT"              # SPDX identifier of upstream tool's license
# license_note = "..."       # Optional: any special notes about license implications

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.

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 Types Summary

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

Step 1: Create Feature Branch

git fetch origin main
git checkout -b feature/{name}-provider origin/main

Replace {name} with the tool name (lowercase, e.g., ripgrep, fd).

Step 2: Create Provider Directory Structure

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)

Step 2.1: Create provider.toml Manifest

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.

Step 3: Implement Core Files

Refer to references/templates.md for complete code templates.

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

Step 4: Register Provider

4.1 Update Root Cargo.toml

Add to [workspace] members:

"crates/vx-providers/{name}",

Add to [workspace.dependencies]:

vx-provider-{name} = { path = "crates/vx-providers/{name}" }

4.2 Update vx-cli/Cargo.toml

Add dependency:

vx-provider-{name} = { workspace = true }

4.3 Update registry.rs

In crates/vx-cli/src/registry.rs, add:

// Register {Name} provider
registry.register(vx_provider_{name}::create_provider());

Step 5: Project Analyzer Integration (Optional)

If the new tool corresponds to a language/ecosystem (e.g., Go, Java, PHP), add project analyzer support.

5.1 Create Language Analyzer Directory

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

5.2 Define Script Detection Rules

// 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),
];

5.3 Implement LanguageAnalyzer

// 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))
    }
}

5.4 Register Analyzer

In crates/vx-project-analyzer/src/languages/mod.rs:

mod {lang};
pub use {lang}::{Lang}Analyzer;

pub fn all_analyzers() -> Vec<Box<dyn LanguageAnalyzer>> {
    vec![
        // ... existing analyzers
        Box::new({Lang}Analyzer::new()),
    ]
}

5.5 Add Analyzer Tests

// 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

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

Step 7: Add Documentation

Add documentation for the new tool in the appropriate category:

English Documentation (docs/tools/)

CategoryFileTools
DevOpsdevops.mdterraform, docker, kubectl, helm, git
Cloud CLIcloud.mdaws, az, gcloud
Build Toolsbuild-tools.mdjust, task, cmake, ninja, protoc, vite
AI Toolsai.mdollama
Scientific/HPCscientific.mdspack, rez
Code Qualityquality.mdpre-commit
Otherother.mddeno, zig, java, vscode, rcedit, choco

Chinese Documentation (docs/zh/tools/)

Create corresponding Chinese documentation with the same structure.

Documentation Template

## {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}

## Step 8: Version Fetching Strategies

### GitHub Releases (Preferred)

```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

Manual GitHub API

let url = "https://api.github.com/repos/{owner}/{repo}/releases";
let response = ctx.http.get_json_value(url).await?;
// Parse response and build VersionInfo

Step 9: Verification and Testing

# Check compilation
cargo check -p vx-provider-{name}

# Run tests
cargo test -p vx-provider-{name}

# If analyzer was added
cargo test -p vx-project-analyzer

# Verify full workspace
cargo check

# Run snapshot tests
cargo test --test cli_tests

Common Patterns

VersionInfo Construction

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

VerificationResult

// Success
VerificationResult::success(exe_path)

// Failure
VerificationResult::failure(
    vec!["Error message".to_string()],
    vec!["Suggested fix".to_string()],
)

Platform Matching

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)

The framework provides a layered approach - most providers only need 1-2 overrides:

// 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
    }
}

ScriptRule Priority Guidelines

PriorityUse Case
100Task runners (nox, tox, just, make)
90Secondary task runners
50Default tools (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)

Step 1: Add system_deps.pre_depends in provider.toml

Declare which package managers are required as dependencies:

# macOS requires 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

# Windows: winget (preferred), choco, or scoop (any one is sufficient)
[[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

Step 2: Add system_install.strategies in provider.toml

Define how to install via each package manager:

# 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

Step 3: Implement install() Method with Fallback

For hybrid providers, override install() to try direct download first, then fall back to package manager:

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
    }
}

Step 4: Handle InstallResult Correctly

Important: System-installed tools have different paths than store-installed tools:

// 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.

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

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

provider.toml Quick Reference

Minimal Example (GitHub Releases with Layout)

[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
[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 = []

Binary Download Example

[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)

For tools like ImageMagick that have direct download on some platforms but need package managers on others:

[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.)
[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
# Triggers package manager fallback

# macOS requires 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

# Windows: winget (preferred) or 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

# 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

provider.toml Fields Reference

SectionFieldDescription
[provider]nameProvider name (required)
descriptionHuman-readable description
homepageProject homepage URL
repositorySource repository URL
ecosystemnodejs, python, rust, go, devtools, system, zig
[provider.platforms]osRestrict to platforms: ["windows"], ["macos"], ["linux"]
[[runtimes]]nameRuntime name (required)
descriptionRuntime description
executableExecutable file name (required)
aliasesAlternative names list
bundled_withIf bundled with another runtime
[runtimes.versions]sourceVersion source type
ownerGitHub owner (for github-releases/tags)
repoGitHub repo name
strip_v_prefixRemove 'v' from version tags
[runtimes.layout]download_type"binary" or "archive" (RFC 0019)
[runtimes.layout.binary."{platform}"]source_nameDownloaded file name (supports {version})
target_nameFinal executable name
target_dirTarget directory (e.g., "bin")
target_permissionsUnix permissions (e.g., "755")
[runtimes.layout.archive]strip_prefixDirectory prefix to remove (supports {version}, {os}, {arch})
executable_pathsPaths to executables after stripping
[runtimes.executable_config]dir_patternDirectory pattern (e.g., {name}-{version})
extensionsExecutable extensions list
[[runtimes.system_deps.pre_depends]]type"runtime" (dependency type)
idPackage manager runtime id (brew, winget, choco, scoop)
platformsArray of platforms: ["macos"], ["windows"], ["linux"]
reasonHuman-readable reason for dependency
optionaltrue if any one of multiple options is sufficient
[[runtimes.system_install.strategies]]type"package_manager" or "manual"
managerPackage manager name (brew, winget, choco, scoop, apt, dnf)
packagePackage name in that manager
platformsArray of platforms this strategy applies to
priorityPriority (higher = preferred). winget=95, brew=90, choco=80, scoop=60
[[runtimes.constraints]]whenVersion condition (e.g., *, ^1, >=2)
requiresRequired dependencies list
recommendsRecommended dependencies list

Reference Files

For complete code templates, see references/templates.md.

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

80/100Analyzed 2/18/2026

High-quality technical reference skill with comprehensive provider creation guidance. Excellent license compliance section, clear decision trees, and detailed code templates. Strong actionability with step-by-step instructions. Penalized for internal-only path (.codebuddy) suggesting project-specific agent config.

95
90
85
95
90

Metadata

Licenseunknown
Version-
Updated3/5/2026
Publisherloonghao

Tags

apici-cdgithubgithub-actionslintingobservabilitytesting