rtk curl breaks downstream parsers by returning compressed schema instead of raw payload when stdout is pipedrtk curl always returns a token-compressed, schema-like representation of the response body, regardless of whether stdout is a TTY or a pipe. This silently breaks any command that pipes rtk curl into a parser expecting the raw payload (python -c "json.load(sys.stdin)", jq, node -e, awk, sed, etc.).
Because the Claude Code hook (rtk-rewrite.sh) auto-rewrites curl → rtk curl, this affects every such pipeline the LLM constructs — even though the LLM never sees the rtk-compressed output, only the downstream parser error.
# Expected: prints "Hello World"
curl -s "https://api.mymemory.translated.net/get?q=Bonjour%20monde&langpair=fr%7Cen" \
| python3 -c "import json,sys; d=json.load(sys.stdin); print(d['responseData']['translatedText'])"
Under the Claude Code hook (or when the user explicitly writes rtk curl), this pipeline fails:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 3 (char 4)
Because rtk curl returns:
{
exception_code: null,
matches:
[{
create-date: string,
created-by: string,
...
instead of the raw JSON body that json.load expects.
curl | <parser> breaks silently.curl ... | jq from the assistant never typed rtk, yet get hit by it.rtk aws, rtk psql, rtk json, rtk cat) likely have the same class of bug.rtk curl is not a passthrough — it post-processes the response body for LLM consumption. This is correct behavior when an LLM is the consumer. It is incorrect when a parser is the consumer.
The tool currently has no way to distinguish those two cases.
Detect isatty(stdout) at startup. If stdout is not a TTY (i.e., it is piped, redirected to a file, or captured), skip the compression layer and passthrough the raw response bytes from the underlying curl.
This matches the long-standing Unix convention followed by ls, grep, diff, etc., which disable colors and column formatting when piped.
// pseudo-code inside rtk curl
if !io::stdout().is_terminal() {
return run_native_curl_passthrough(args);
}
// else: existing compression path
The same fix should apply to every rtk subcommand that transforms output (cat, read, json, aws, psql, git, gh, etc.).
rtk proxy <cmd> to bypass rewriting. But the Claude Code hook rewrites curl unconditionally, so the LLM has to remember to write rtk proxy curl every time it pipes, which does not scale.[hooks] exclude_commands = ["curl"] in ~/.config/rtk/config.toml, but this disables all rtk curl savings globally, even when the LLM IS the consumer.Neither replaces a proper TTY-aware passthrough inside rtk itself.
hooks/rtk-rewrite.sh (rtk-hook-version: 3)rtk curl passes through raw bytes when stdout is not a TTYrtk cat, rtk read, rtk json, rtk aws, rtk psql, rtk git, rtk ghjq, python -c "json.load", file redirect, /dev/null