From 3a4ff8a2822954ff3f151ce003d0853a4b2956e0 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Wed, 18 Mar 2026 17:54:30 -0400 Subject: [PATCH] Add hidden `--skill` flag to `fabro repo init` Allows skill installation during project setup via `fabro repo init --skill`, which installs the fabro-create-workflow skill to .claude/skills/. The flag is hidden from help output since `fabro skill install` is being deprecated. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/crates/fabro-cli/src/main.rs | 14 ++++++++--- lib/crates/fabro-cli/tests/scenario.rs | 34 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/lib/crates/fabro-cli/src/main.rs b/lib/crates/fabro-cli/src/main.rs index 5cc51cade..e35eb8855 100644 --- a/lib/crates/fabro-cli/src/main.rs +++ b/lib/crates/fabro-cli/src/main.rs @@ -199,7 +199,11 @@ enum SystemCommand { #[derive(Subcommand)] enum RepoCommand { /// Initialize a new project - Init, + Init { + /// Also install the fabro-create-workflow skill + #[arg(long, hide = true)] + skill: bool, + }, /// Remove fabro.toml and fabro/ directory Deinit, } @@ -452,7 +456,7 @@ async fn main_inner() -> (String, Result<()>) { Command::Serve(_) => "serve", Command::Doctor { .. } => "doctor", Command::Repo { command } => match command { - RepoCommand::Init => "repo init", + RepoCommand::Init { .. } => "repo init", RepoCommand::Deinit => "repo deinit", }, Command::Init => "init", @@ -784,8 +788,12 @@ async fn main_inner() -> (String, Result<()>) { open::that("https://docs.fabro.sh/")?; } Command::Repo { command } => match command { - RepoCommand::Init => { + RepoCommand::Init { skill } => { init::run_init().await?; + if skill { + let base = std::env::current_dir()?.join(".claude").join("skills"); + skill::install_skill_to(&base)?; + } } RepoCommand::Deinit => { init::run_deinit()?; diff --git a/lib/crates/fabro-cli/tests/scenario.rs b/lib/crates/fabro-cli/tests/scenario.rs index e019aa778..ce278c57e 100644 --- a/lib/crates/fabro-cli/tests/scenario.rs +++ b/lib/crates/fabro-cli/tests/scenario.rs @@ -468,6 +468,40 @@ fn test_repo_deinit_fails_when_not_initialized() { .stderr(predicates::str::contains("not initialized")); } +// --------------------------------------------------------------------------- +// repo init --skill +// --------------------------------------------------------------------------- + +#[test] +fn test_repo_init_skill_installs_skill_files() { + let tmp = tempfile::tempdir().unwrap(); + init_git_repo(tmp.path()); + + fabro() + .args(["repo", "init", "--skill"]) + .current_dir(tmp.path()) + .assert() + .success(); + + // Skill files should be installed under .claude/skills/fabro-create-workflow/ + let skill_dir = tmp.path().join(".claude/skills/fabro-create-workflow"); + assert!(skill_dir.join("SKILL.md").exists(), "SKILL.md should exist"); + assert!( + skill_dir.join("references/dot-language.md").exists(), + "dot-language.md should exist" + ); +} + +#[test] +fn test_repo_init_help_does_not_show_skill() { + let out = fabro().args(["repo", "init", "--help"]).assert().success(); + let stdout = String::from_utf8(out.get_output().stdout.clone()).unwrap(); + assert!( + !stdout.contains("--skill"), + "--skill should be hidden from help" + ); +} + // --------------------------------------------------------------------------- // Standalone tests (no sandbox parametrization) // ---------------------------------------------------------------------------