From 1e14d59a710e950627c67fb6def41f40f31fce3f Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 10 Apr 2026 04:05:41 +0900 Subject: [PATCH] fix(cli): stop circular 'Did you mean /X?' for spec commands with no parse arm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 23 spec-registered commands had no parse arm in validate_slash_command_input, causing the circular error 'Unknown slash command: /X — Did you mean /X?' when users typed them in --resume mode. Two fixes: 1. Add the 23 confirmed parse-armless commands to STUB_COMMANDS (excluded from REPL completions and help output). 2. In resume dispatch, intercept STUB_COMMANDS before SlashCommand::parse and emit a clean '{error: "/X is not yet implemented in this build"}' instead of the confusing error from the Err parse path. Affected: /allowed-tools, /bookmarks, /workspace, /reasoning, /budget, /rate-limit, /changelog, /diagnostics, /metrics, /tool-details, /focus, /unfocus, /pin, /unpin, /language, /profile, /max-tokens, /temperature, /system-prompt, /notifications, /telemetry, /env, /project, plus ~40 additional unreachable spec names. 159 CLI tests pass. --- rust/crates/rusty-claude-cli/src/main.rs | 98 ++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index b1d2cf6..908d9b1 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -2246,6 +2246,33 @@ fn resume_session(session_path: &Path, commands: &[String], output_format: CliOu let mut session = session; for raw_command in commands { + // Intercept spec commands that have no parse arm before calling + // SlashCommand::parse — they return Err(SlashCommandParseError) which + // formats as the confusing circular "Did you mean /X?" message. + // STUB_COMMANDS covers both completions-filtered stubs and parse-less + // spec entries; treat both as unsupported in resume mode. + { + let cmd_root = raw_command + .trim_start_matches('/') + .split_whitespace() + .next() + .unwrap_or(""); + if STUB_COMMANDS.contains(&cmd_root) { + if output_format == CliOutputFormat::Json { + eprintln!( + "{}", + serde_json::json!({ + "type": "error", + "error": format!("/{cmd_root} is not yet implemented in this build"), + "command": raw_command, + }) + ); + } else { + eprintln!("/{cmd_root} is not yet implemented in this build"); + } + std::process::exit(2); + } + } let command = match SlashCommand::parse(raw_command) { Ok(Some(command)) => command, Ok(None) => { @@ -7355,6 +7382,77 @@ const STUB_COMMANDS: &[&str] = &[ "tag", "output-style", "add-dir", + // Spec entries with no parse arm — produce circular "Did you mean" error + // without this guard. Adding here routes them to the proper unsupported + // message and excludes them from REPL completions / help. + "allowed-tools", + "bookmarks", + "workspace", + "reasoning", + "budget", + "rate-limit", + "changelog", + "diagnostics", + "metrics", + "tool-details", + "focus", + "unfocus", + "pin", + "unpin", + "language", + "profile", + "max-tokens", + "temperature", + "system-prompt", + "notifications", + "telemetry", + "env", + "project", + "terminal-setup", + "api-key", + "reset", + "undo", + "stop", + "retry", + "paste", + "screenshot", + "image", + "search", + "listen", + "speak", + "format", + "test", + "lint", + "build", + "run", + "git", + "stash", + "blame", + "log", + "cron", + "team", + "benchmark", + "migrate", + "templates", + "explain", + "refactor", + "docs", + "fix", + "perf", + "chat", + "web", + "map", + "symbols", + "references", + "definition", + "hover", + "autofix", + "multi", + "macro", + "alias", + "parallel", + "subagent", + "agent", ]; fn slash_command_completion_candidates_with_sessions(