diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index cd0e2ae7..d755da80 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -1378,8 +1378,9 @@ fn parse_args(args: &[String]) -> Result { // an empty prompt when credentials are present). let joined = rest.join(" "); if joined.trim().is_empty() { + // #798: add \n hint so split_error_hint extracts it (was empty_prompt + null) return Err( - "empty prompt: provide a subcommand (run `claw --help`) or a non-empty prompt string" + "empty prompt: provide a subcommand or a non-empty prompt string.\nUsage: claw or claw -p . Run `claw --help` for the full list." .to_string(), ); } diff --git a/rust/crates/rusty-claude-cli/tests/output_format_contract.rs b/rust/crates/rusty-claude-cli/tests/output_format_contract.rs index 21e821fd..b9354164 100644 --- a/rust/crates/rusty-claude-cli/tests/output_format_contract.rs +++ b/rust/crates/rusty-claude-cli/tests/output_format_contract.rs @@ -3418,3 +3418,36 @@ fn plugins_extra_args_have_non_null_hint_797() { "hint should reference plugins usage, got: {h:?}" ); } + +#[test] +fn empty_prompt_has_non_null_hint_798() { + // #798: `claw --output-format json ""` returned empty_prompt + hint:null. + // The error message "empty prompt: provide a subcommand..." had no \n delimiter. + let root = unique_temp_dir("empty-prompt-798"); + fs::create_dir_all(&root).expect("temp dir"); + std::process::Command::new("git") + .args(["init", "-q"]) + .current_dir(&root) + .output() + .ok(); + + let output = run_claw(&root, &["--output-format", "json", ""], &[]); + assert!( + !output.status.success(), + "empty prompt must exit non-zero (#798)" + ); + let stderr = String::from_utf8_lossy(&output.stderr); + let j: serde_json::Value = stderr + .lines() + .find(|l| l.trim_start().starts_with('{')) + .and_then(|l| serde_json::from_str(l).ok()) + .expect("empty prompt should emit JSON error envelope"); + assert_eq!(j["error_kind"], "empty_prompt"); + let h = j["hint"] + .as_str() + .expect("empty_prompt must have non-null hint (#798)"); + assert!( + h.contains("claw") || h.contains("Usage"), + "hint should reference usage, got: {h:?}" + ); +}