ref:af919907cb66143a9b28899af408f1376f17fe93

feat: add `anvil repo create` CLI command

Adds a `create` subcommand to `anvil repo` that POSTs to the new /:org/repos API endpoint. Supports --name, --org, --description, and --visibility flags. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SHA: af919907cb66143a9b28899af408f1376f17fe93
Author: Cole Christensen <cole.christensen@macmillan.com>
Date: 2026-03-14 18:20
Parents: 7d93289
1 files changed +65 -0
Type
src/commands/repo.rs +65 −0
@@ -17,6 +17,21 @@
/// Repository (org/repo), or detected from git remote
repo: Option<String>,
},
/// Create a new repository
Create {
/// Repository name
#[arg(long)]
name: String,
/// Organization slug (defaults to org from default repo)
#[arg(long)]
org: Option<String>,
/// Description
#[arg(long, default_value = "")]
description: String,
/// Visibility: private or public
#[arg(long, default_value = "private")]
visibility: String,
},
/// Clone a repository via SSH
Clone {
/// Repository (org/repo)
@@ -46,6 +61,12 @@
pub async fn run(args: RepoArgs) -> Result<(), Box<dyn std::error::Error>> {
match args.command {
RepoCommand::View { repo } => view(repo.as_deref()).await,
RepoCommand::Create {
name,
org,
description,
visibility,
} => create(&name, org.as_deref(), &description, &visibility).await,
RepoCommand::Clone { repo, dir } => clone(&repo, dir.as_deref()).await,
RepoCommand::SetDefault { repo } => set_default(&repo).await,
}
@@ -74,6 +95,50 @@
}
if let Some(ref ts) = repo.inserted_at {
output::detail("Created", &output::format_time(ts));
}
Ok(())
}
async fn create(
name: &str,
org: Option<&str>,
description: &str,
visibility: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_config()?;
// Resolve org: explicit flag, or first part of default repo
let org_slug = match org {
Some(o) => o.to_string(),
None => {
let (resolved_org, _) = config::resolve_repo(None)?;
resolved_org
}
};
let resp: serde_json::Value = client
.post(
&format!("/{org_slug}/repos"),
&serde_json::json!({
"name": name,
"description": description,
"visibility": visibility,
}),
)
.await?;
let slug = resp
.pointer("/slug")
.or_else(|| resp.pointer("/data/slug"))
.and_then(|v| v.as_str())
.unwrap_or(name);
output::success(&format!("Created repository {org_slug}/{slug}"));
let config = Config::load()?;
if let Some(ref url) = config.server_url {
println!("\n {url}/{org_slug}/{slug}");
}
Ok(())