Skip to content

feat(cloud): add xh command support#1235

Open
arvindcr4 wants to merge 1 commit intortk-ai:developfrom
arvindcr4:feat/xh-cmd
Open

feat(cloud): add xh command support#1235
arvindcr4 wants to merge 1 commit intortk-ai:developfrom
arvindcr4:feat/xh-cmd

Conversation

@arvindcr4
Copy link
Copy Markdown

Summary

  • Adds rtk xh subcommand — a filter wrapping xh (modern curl replacement at https://github.com/ducaale/xh).
  • Mirrors curl_cmd: prepends --pretty=none --body so the JSON schema filter sees raw payload; early-exits on non-2xx to avoid mangling HTML error pages.
  • Registers an RtkRule so the PreToolUse hook auto-rewrites bare xh ...rtk xh ... (Network category, ~70% est savings).

Why

Many users (myself + global CLAUDE.md rules from others) already prefer xh over curl. Today those invocations bypass RTK entirely — rtk discover flags them as top "unhandled commands" on sessions where I counted 22 xh calls in one session alone.

Implementation

  • src/cmds/cloud/xh_cmd.rs — new, 5 unit tests (JSON schema compression, small-JSON passthrough Broken curl usage #297, plain text, line truncation, array)
  • src/main.rs — import, Commands::Xh variant, dispatch, read-only matcher entry
  • src/discover/rules.rs — new RtkRule right after the curl rule

Test plan

  • cargo build — clean (0 errors)
  • cargo fmt — clean
  • cargo test1355 passed, 0 failed (5 new)
  • End-to-end: rtk xh https://r.jina.ai/.../users — 5729 B → 686 B (88% reduction)
  • Error path: non-2xx responses bail to FAILED: xh … on stderr, no filter corruption

Notes

  • Flag ordering lets users override: since RTK prepends --pretty=none --body and xh honors later flags, rtk xh --headers <url> still works.
  • No change to existing curl_cmd behavior.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings April 11, 2026 19:00
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@arvindcr4 arvindcr4 changed the base branch from master to develop April 11, 2026 19:03
Add rtk xh as a filter for the xh HTTP client (a modern curl replacement).
Mirrors curl_cmd: prepends --pretty=none --body so the JSON schema filter
sees raw payload, early-exits on non-2xx to avoid mangling HTML error pages.

Also registers an RtkRule so the PreToolUse hook auto-rewrites bare
'xh ...' invocations to 'rtk xh ...' (Network category, ~70% savings).

5 unit tests added; full suite: 1355 passed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class support for xh (HTTP client) to RTK’s CLI routing and auto-rewrite/discovery system, mirroring the existing curl filtering approach for JSON-aware compression.

Changes:

  • Adds rtk xh subcommand wiring in the CLI (new Commands::Xh variant + dispatch + operational categorization).
  • Introduces src/cmds/cloud/xh_cmd.rs to run xh with default flags and filter/truncate output (including the “schema only if shorter” guard related to #297).
  • Registers an xh rewrite/discover rule so bare xh ... can be rewritten to rtk xh ....

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.

File Description
src/main.rs Adds the Xh subcommand to Clap routing and operational command classification.
src/discover/rules.rs Adds an RtkRule so xh invocations can be detected and rewritten to rtk xh.
src/cmds/cloud/xh_cmd.rs Implements xh execution + JSON autodetection/schema filtering + truncation + unit tests.

Comment on lines +32 to +41
// Early exit: don't feed HTTP error bodies (HTML 404 etc.) through JSON schema filter
if !output.status.success() {
let msg = if stderr.trim().is_empty() {
stdout.trim().to_string()
} else {
stderr.trim().to_string()
};
eprintln!("FAILED: xh {}", msg);
return Ok(exit_code_from_output(&output, "xh"));
}
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “early exit” is keyed off the xh process exit status (output.status.success()), not the HTTP status code. As written, this won’t guarantee skipping filtering for non-2xx responses (as described), and can still run HTML error bodies through the JSON/schema path if xh exits 0 for HTTP 4xx/5xx. Consider either adding an xh flag that makes non-2xx exit non-zero (e.g., check-status) or capturing status/headers so you can decide based on the HTTP status explicitly.

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +93
fn filter_xh_output(output: &str) -> String {
let trimmed = output.trim();

// Try JSON detection: starts with { or [
if (trimmed.starts_with('{') || trimmed.starts_with('['))
&& (trimmed.ends_with('}') || trimmed.ends_with(']'))
{
if let Ok(schema) = json_cmd::filter_json_string(trimmed, 5) {
// Only use schema if it's actually shorter than the original (#297)
if schema.len() <= trimmed.len() {
return schema;
}
}
}

// Not JSON: truncate long output
let lines: Vec<&str> = trimmed.lines().collect();
if lines.len() > 30 {
let mut result: Vec<&str> = lines[..30].to_vec();
result.push("");
let msg = format!(
"... ({} more lines, {} bytes total)",
lines.len() - 30,
trimmed.len()
);
return format!("{}\n{}", result.join("\n"), msg);
}

// Short output: return as-is but truncate long lines
lines
.iter()
.map(|l| truncate(l, 200))
.collect::<Vec<_>>()
.join("\n")
}
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter_xh_output is effectively identical to filter_curl_output (same JSON detection, schema-shorter guard for #297, and truncation logic). This duplication makes it easy for curl/xh behavior to drift over time; consider extracting the shared filtering into a common helper (e.g., a cloud/http response filter function) used by both commands.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants