diff --git a/ROADMAP.md b/ROADMAP.md index b57d7d1..835ec36 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -508,3 +508,5 @@ Model name prefix now wins unconditionally over env-var presence. Regression tes 40. **Surface broken installed plugins before they become support ghosts** — community-support lane. Clawhip commit `ff6d3b7` on worktree `claw-code-community-support-plugin-list-load-failures` / branch `community-support/plugin-list-load-failures`. When an installed plugin has a broken manifest (missing hook scripts, parse errors, bad json), the plugin silently fails to load and the user sees nothing — no warning, no list entry, no hint. Related to ROADMAP #27 (host plugin path leaking into tests) but at the user-facing surface: the test gap and the UX gap are siblings of the same root. Landing on `main` will close the silent-ghost class of support issues where users report "my plugin does nothing" with no error to share. Track until merged to `main`. 41. **Stop ambient plugin state from skewing CLI regression checks** — community-support lane. Clawhip commit `7d493a7` on worktree `claw-code-community-support-plugin-test-sealing` / branch `community-support/plugin-test-sealing`. Companion to #40: the test sealing gap is the CI/developer side of the same root — host `~/.claude/plugins/installed/` bleeds into CLI test runs, making regression checks non-deterministic on any machine with a non-pristine plugin install. Closely related to ROADMAP #27 (dev/rust `cargo test` reads host plugin state). Track until merged to `main`. + +42. **`--output-format json` errors emitted as prose, not JSON** — dogfooded 2026-04-09. When `claw --output-format json prompt` hits an API error, the error was printed as plain text (`error: api returned 401 ...`) to stderr instead of a JSON object. Any tool or CI step parsing claw's JSON output gets nothing parseable on failure — the error is invisible to the consumer. **Fix (`a...`):** detect `--output-format json` in `main()` at process exit and emit `{"type":"error","error":""}` to stderr instead of the prose format. Non-JSON path unchanged. **Done** in this nudge cycle. diff --git a/rust/crates/rusty-claude-cli/src/main.rs b/rust/crates/rusty-claude-cli/src/main.rs index ee974e4..9803532 100644 --- a/rust/crates/rusty-claude-cli/src/main.rs +++ b/rust/crates/rusty-claude-cli/src/main.rs @@ -110,7 +110,22 @@ type RuntimePluginStateBuildOutput = ( fn main() { if let Err(error) = run() { let message = error.to_string(); - if message.contains("`claw --help`") { + // When --output-format json is active, emit errors as JSON so downstream + // tools can parse failures the same way they parse successes (ROADMAP #42). + let argv: Vec = std::env::args().collect(); + let json_output = argv + .windows(2) + .any(|w| w[0] == "--output-format" && w[1] == "json") + || argv.iter().any(|a| a == "--output-format=json"); + if json_output { + eprintln!( + "{}", + serde_json::json!({ + "type": "error", + "error": message, + }) + ); + } else if message.contains("`claw --help`") { eprintln!("error: {message}"); } else { eprintln!(