Skip to content
31 changes: 30 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,32 @@ fn codegen_registry() {
.collect::<Vec<_>>()
})
.unwrap_or_default();
// Parse options - can be a table with key=value pairs
let options = info
.get("options")
.map(|opts| {
if let Some(table) = opts.as_table() {
table
.iter()
.map(|(k, v)| {
let value = match v {
toml::Value::String(s) => s.clone(),
toml::Value::Table(t) => {
// Serialize nested tables back to TOML string
toml::to_string(t).unwrap_or_default()
}
_ => v.to_string(),
};
(k.clone(), value)
})
.collect::<Vec<_>>()
} else {
vec![]
}
})
.unwrap_or_default();
let rt = format!(
r#"RegistryTool{{short: "{short}", description: {description}, backends: &[{backends}], aliases: &[{aliases}], test: &{test}, os: &[{os}], depends: &[{depends}], idiomatic_files: &[{idiomatic_files}]}}"#,
r#"RegistryTool{{short: "{short}", description: {description}, backends: &[{backends}], aliases: &[{aliases}], test: &{test}, os: &[{os}], depends: &[{depends}], idiomatic_files: &[{idiomatic_files}], options: &[{options}]}}"#,
description = description
.map(|d| format!("Some(r###\"{d}\"###)"))
.unwrap_or("None".to_string()),
Expand Down Expand Up @@ -150,6 +174,11 @@ fn codegen_registry() {
.map(|f| format!("\"{f}\""))
.collect::<Vec<_>>()
.join(", "),
options = options
.iter()
.map(|(k, v)| format!("(r###\"{k}\"###, r###\"{v}\"###)"))
.collect::<Vec<_>>()
.join(", "),
);
lines.push(format!(r#" ("{short}", {rt}),"#));
for alias in aliases {
Expand Down
19 changes: 18 additions & 1 deletion registry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -795,10 +795,27 @@ test = ["clarinet --version", "clarinet {{version}}"]

[tools.claude]
aliases = ["claude-code"]
backends = ["npm:@anthropic-ai/claude-code"]
backends = ["http:claude", "npm:@anthropic-ai/claude-code"]
description = "Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows -- all through natural language commands"
os = ["linux", "macos"]
test = ["claude --version", "{{version}} (Claude Code)"]

[tools.claude.options]
bin = "claude"
version_list_url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/stable"

[tools.claude.options.platforms.macos-arm64]
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/{version}/darwin-arm64/claude"

[tools.claude.options.platforms.macos-x64]
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/{version}/darwin-x64/claude"

[tools.claude.options.platforms.linux-arm64]
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/{version}/linux-arm64/claude"

[tools.claude.options.platforms.linux-x64]
url = "https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/{version}/linux-x64/claude"

[tools.claude-squad]
backends = ["aqua:smtg-ai/claude-squad", "ubi:smtg-ai/claude-squad"]
description = "Manage multiple AI agents like Claude Code, Aider, Codex, and Amp. 10x your productivity"
Expand Down
20 changes: 20 additions & 0 deletions schema/mise-registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,26 @@
"type": "string"
},
"description": "Files that indicate this tool should be used in a project"
},
"options": {
"type": "object",
"description": "Backend-specific options for the tool (e.g., version_list_url, bin, platforms)",
"properties": {
"platforms": {
"type": "object",
"description": "Platform-specific options (e.g., macos-arm64, linux-x64)",
"additionalProperties": {
"type": "object",
"description": "Platform-specific configuration",
"additionalProperties": {
"type": "string"
}
}
}
},
"additionalProperties": {
"type": "string"
}
}
},
"required": ["backends"],
Expand Down
23 changes: 21 additions & 2 deletions src/backend/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::backend::static_helpers::{
clean_binary_name, get_filename_from_url, list_available_platforms_with_key,
lookup_platform_key, template_string, verify_artifact,
};
use crate::backend::version_list;
use crate::cli::args::BackendArg;
use crate::config::Config;
use crate::config::Settings;
Expand Down Expand Up @@ -378,6 +379,24 @@ impl HttpBackend {
}
Ok(())
}

/// Fetch and parse versions from a version list URL
async fn fetch_versions_from_url(&self) -> Result<Vec<String>> {
let opts = self.ba.opts();

// Get version_list_url from options
let version_list_url = match opts.get("version_list_url") {
Some(url) => url.clone(),
None => return Ok(vec![]),
};

// Get optional version regex pattern or JSON path
Comment on lines +387 to +393
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] These two lines extract options that are already being extracted from opts. Consider extracting all three options (version_list_url, version_regex, version_json_path) consistently at the same location for better code organization.

Suggested change
// Get version_list_url from options
let version_list_url = match opts.get("version_list_url") {
Some(url) => url.clone(),
None => return Ok(vec![]),
};
// Get optional version regex pattern or JSON path
// Get version_list_url and related options from options
let version_list_url = match opts.get("version_list_url") {
Some(url) => url.clone(),
None => return Ok(vec![]),
};

Copilot uses AI. Check for mistakes.
let version_regex = opts.get("version_regex").map(|s| s.as_str());
let version_json_path = opts.get("version_json_path").map(|s| s.as_str());

// Use the version_list module to fetch and parse versions
version_list::fetch_versions(&version_list_url, version_regex, version_json_path).await
Comment on lines +388 to +398
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clone() is unnecessary here. Since opts.get() returns Option<&String>, you can use as_str() to get &str and pass it directly to fetch_versions without cloning.

Suggested change
let version_list_url = match opts.get("version_list_url") {
Some(url) => url.clone(),
None => return Ok(vec![]),
};
// Get optional version regex pattern or JSON path
let version_regex = opts.get("version_regex").map(|s| s.as_str());
let version_json_path = opts.get("version_json_path").map(|s| s.as_str());
// Use the version_list module to fetch and parse versions
version_list::fetch_versions(&version_list_url, version_regex, version_json_path).await
let version_list_url = opts.get("version_list_url").map(|s| s.as_str());
if version_list_url.is_none() {
return Ok(vec![]);
}
// Get optional version regex pattern or JSON path
let version_regex = opts.get("version_regex").map(|s| s.as_str());
let version_json_path = opts.get("version_json_path").map(|s| s.as_str());
// Use the version_list module to fetch and parse versions
version_list::fetch_versions(version_list_url.unwrap(), version_regex, version_json_path).await

Copilot uses AI. Check for mistakes.
}
}

#[async_trait]
Expand All @@ -391,8 +410,8 @@ impl Backend for HttpBackend {
}

async fn _list_remote_versions(&self, _config: &Arc<Config>) -> Result<Vec<String>> {
// Http backend doesn't support remote version listing
Ok(vec![])
// Fetch versions from version_list_url if configured
self.fetch_versions_from_url().await
}

async fn install_version_(
Expand Down
Loading
Loading