From 414526c1bdbfb150cb8d02287351914788819e72 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 9 Apr 2026 14:36:00 +0900 Subject: [PATCH] =?UTF-8?q?fix(cli):=20exclude=20stub=20slash=20commands?= =?UTF-8?q?=20from=20help=20output=20=E2=80=94=20ROADMAP=20#39?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The --help slash-command section was listing ~35 unimplemented commands alongside working ones. Combined with the completions fix (c55c510), the discovery surface now consistently shows only implemented commands. Changes: - commands crate: add render_slash_command_help_filtered(exclude: &[&str]) - move STUB_COMMANDS to module-level const in main.rs (reused by both completions and help rendering) - replace render_slash_command_help() with filtered variant at all help-rendering call sites 156 CLI tests pass, fmt clean. --- rust/crates/commands/src/lib.rs | 36 +++++++++ rust/crates/rusty-claude-cli/src/main.rs | 98 ++++++++++++------------ 2 files changed, 85 insertions(+), 49 deletions(-) diff --git a/rust/crates/commands/src/lib.rs b/rust/crates/commands/src/lib.rs index 556ff96..82c544e 100644 --- a/rust/crates/commands/src/lib.rs +++ b/rust/crates/commands/src/lib.rs @@ -1938,6 +1938,42 @@ pub fn suggest_slash_commands(input: &str, limit: usize) -> Vec { } #[must_use] +/// Render the slash-command help section, optionally excluding stub commands +/// (commands that are registered in the spec list but not yet implemented). +/// Pass an empty slice to include all commands. +pub fn render_slash_command_help_filtered(exclude: &[&str]) -> String { + let mut lines = vec![ + "Slash commands".to_string(), + " Start here /status, /diff, /agents, /skills, /commit".to_string(), + " [resume] also works with --resume SESSION.jsonl".to_string(), + String::new(), + ]; + + let categories = ["Session", "Tools", "Config", "Debug"]; + + for category in categories { + lines.push(category.to_string()); + for spec in slash_command_specs() + .iter() + .filter(|spec| slash_command_category(spec.name) == category) + .filter(|spec| !exclude.contains(&spec.name)) + { + lines.push(format_slash_command_help_line(spec)); + } + lines.push(String::new()); + } + + lines + .into_iter() + .rev() + .skip_while(String::is_empty) + .collect::>() + .into_iter() + .rev() + .collect::>() + .join("\n") +} + pub fn render_slash_command_help() -> String { let mut lines = vec![ "Slash commands".to_string(), diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index e34bf99..e75ee86 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -35,8 +35,8 @@ use commands::{ classify_skills_slash_command, handle_agents_slash_command, handle_agents_slash_command_json, handle_mcp_slash_command, handle_mcp_slash_command_json, handle_plugins_slash_command, handle_skills_slash_command, handle_skills_slash_command_json, render_slash_command_help, - resume_supported_slash_commands, slash_command_specs, validate_slash_command_input, - SkillSlashDispatch, SlashCommand, + render_slash_command_help_filtered, resume_supported_slash_commands, slash_command_specs, + validate_slash_command_input, SkillSlashDispatch, SlashCommand, }; use compat_harness::{extract_manifest, UpstreamPaths}; use init::initialize_repo; @@ -4711,7 +4711,7 @@ fn render_repl_help() -> String { " Browse sessions /session list".to_string(), " Show prompt history /history [count]".to_string(), String::new(), - render_slash_command_help(), + render_slash_command_help_filtered(STUB_COMMANDS), ] .join( " @@ -6925,6 +6925,51 @@ fn collect_prompt_cache_events(summary: &runtime::TurnSummary) -> Vec, @@ -6932,51 +6977,6 @@ fn slash_command_completion_candidates_with_sessions( ) -> Vec { let mut completions = BTreeSet::new(); - // Commands that are registered in the spec list but not yet implemented - // in this build. Exclude them from completions so the discovery surface - // matches what actually works (ROADMAP #39). - const STUB_COMMANDS: &[&str] = &[ - "login", - "logout", - "vim", - "upgrade", - "stats", - "share", - "feedback", - "files", - "fast", - "exit", - "summary", - "desktop", - "brief", - "advisor", - "stickers", - "insights", - "thinkback", - "release-notes", - "security-review", - "keybindings", - "privacy-settings", - "plan", - "review", - "tasks", - "theme", - "voice", - "usage", - "rename", - "copy", - "hooks", - "context", - "color", - "effort", - "branch", - "rewind", - "ide", - "tag", - "output-style", - "add-dir", - ]; - for spec in slash_command_specs() { if STUB_COMMANDS.contains(&spec.name) { continue; @@ -7874,7 +7874,7 @@ fn print_help_to(out: &mut impl Write) -> io::Result<()> { )?; writeln!(out)?; writeln!(out, "Interactive slash commands:")?; - writeln!(out, "{}", render_slash_command_help())?; + writeln!(out, "{}", render_slash_command_help_filtered(STUB_COMMANDS))?; writeln!(out)?; let resume_commands = resume_supported_slash_commands() .into_iter()