feat(live): show tool call details in streaming output#253
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughUpdated live streaming in Changes
Sequence Diagram(s)sequenceDiagram
participant User as "User (CLI)"
participant Shell as "ralph_loop.sh"
participant Claude as "Claude streaming API"
participant JQ as "jq filter"
participant Stdout as "Terminal stdout"
User->>Shell: invoke with/without --show-tool-args
Shell->>Claude: start streaming request
Claude-->>Shell: stream events (content_block_start, assistant, task_started, ...)
Shell->>JQ: pipe streaming JSON + --argjson show_args
JQ-->>Shell: formatted lines (⚙ tool..., ⚡ [Tool] ..., task_started ...)
Shell->>Stdout: emit live lines to terminal
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ralph_loop.sh`:
- Around line 1563-1581: The tool-summary jq expression only strips newlines and
truncates for the "Bash" branch; update the other branches ("Read", "Write",
"Edit", "Glob", "Grep", "Agent") so their values are normalized the same way by
replacing raw emissions like (.input.file_path // ""), (.input.pattern // ""),
and (.input.description // "") with the same pipeline used for Bash (fallback to
"", split on "\n", take first line, truncate to 120 chars) in the jq string
construction around the tool summary generation.
- Around line 1576-1577: The current conditional only handles subagents named
"Agent" and drops descriptions from older versions that use "Task"; update the
condition that checks .name (the clause currently written as .name == "Agent")
to accept both "Agent" and "Task" (e.g., use a logical OR or an IN check so the
branch triggers for either name) and keep the existing extraction of
(.input.description // "") so the summary includes the description for both tool
names.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
7767280 to
90b904d
Compare
|
Both CodeRabbit findings addressed in the force-pushed commit:
Smoke-tested the filter directly with |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ralph_loop.sh`:
- Around line 1570-1584: The logging code that builds the tool-line (the
expression that checks .name == "Bash"/"Agent"/etc. and pulls
.input.command/.input.description) is emitting raw tool arguments into logs;
change it to redact or summarize sensitive content by default: replace direct
uses of (.input.command/.input.description/.input.file_path/.input.pattern) with
a sanitizer function (e.g., redact_sensitive()) that strips/obfuscates tokens,
secrets, long hex strings, URLs, emails, and common key=secret patterns and
returns a short safe summary (or "[REDACTED]" when unknown), and add an explicit
opt-in flag (e.g., ENABLE_VERBOSE_TOOL_ARGS) so full raw arguments are only
logged when explicitly enabled; update the branches for "Bash" and "Agent" to
call that sanitizer (or produce one-line summaries like "<command redacted>" /
first non-sensitive word) instead of writing raw input and keep the 120-char cut
as a secondary guard.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
frankbria
left a comment
There was a problem hiding this comment.
The enriched live feed is a nice improvement — seeing ⚡ [Bash] git status --short instead of a blank marker is much more useful. A few things to address before merging:
Blocking
Sensitive data in logs (security)
The jq filter emits raw tool arguments — Bash commands, file paths, grep patterns — directly into the live log. In practice these can contain secrets: aws configure set aws_secret_access_key ..., tokens passed as env vars, or credentials in file paths. Recommend either:
- Adding a sanitizer that redacts common secret patterns (e.g., long hex/base64 strings,
key=valuewhere key contains "secret"/"token"/"password"), or - Gating full argument output behind an opt-in flag like
ENABLE_VERBOSE_TOOL_ARGS=trueand emitting a safe summary by default (e.g. the command verb only for Bash)
This is particularly important since --live and --monitor output is often captured to a log file.
Non-blocking but please fix
Inconsistent normalization across tool branches
Only the Bash branch strips newlines and truncates to 120 chars. Read, Write, Edit, Glob, Grep, and Agent emit raw values that can contain newlines or be arbitrarily long. Apply the same normalization pipeline to all branches.
Missing Task tool name
The Agent branch only matches .name == "Agent". Older Claude CLI versions use "Task" as the tool name. Change the condition to match both:
elif .name == "Agent" or .name == "Task" thenAlso: please rebase
PR #256 (a 1-line crash fix in ralph_loop.sh) is being merged first. Please rebase this branch onto main after that lands, since both touch ralph_loop.sh.
Once the security concern is addressed and the other items fixed, happy to re-review.
90b904d to
57fe9c7
Compare
|
Tool argument details are now opt-in via Default behavior ( Opt-in ( Implementation: the flag is passed into the jq filter as |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ralph_loop.sh`:
- Line 77: The LIVE_SHOW_TOOL_ARGS variable is undocumented, defaults to false,
and is bypassing the _env_* capture/restore flow; update the script so this
feature is discoverable and precedence-safe: add LIVE_SHOW_TOOL_ARGS handling
into load_ralphrc() (respecting env > .ralphrc precedence and ensuring it
participates in the _env_* capture/restore flow), expose it in show_help()
and/or add an explicit --show-tool-args CLI flag that sets LIVE_SHOW_TOOL_ARGS,
and update any places that read LIVE_SHOW_TOOL_ARGS (e.g., where the ⚡ [Tool]
output is emitted) to follow the new precedence and documented behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
|
Looks like you still need to rebase. |
57fe9c7 to
391c076
Compare
sorry for taking a while to do so |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ralph_loop.sh`:
- Around line 1606-1607: The jq invocation using --argjson show_args
"${LIVE_SHOW_TOOL_ARGS:-false}" can abort on non-JSON values (e.g., "yes", "on",
"1 ", "True") and its stderr is currently thrown away; normalize
LIVE_SHOW_TOOL_ARGS into a strict JSON literal before invoking portable_timeout
and pipe jq stderr to $stderr_file (same as Claude) so failures are visible.
Implement normalization by trimming whitespace and lowercasing (use
POSIX-compatible tools like printf/tr and case mapping) to convert common truthy
values ("yes","on","true","1") to the JSON literal true and everything else to
false, then pass that normalized value to jq's --argjson show_args; also
redirect jq stderr (the pipeline segment with jq) to $stderr_file instead of
/dev/null.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
43f0189 to
3ca05d0
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
ralph_loop.sh (1)
1607-1609:⚠️ Potential issue | 🟡 Minor
--argjsonstill receives rawLIVE_SHOW_TOOL_ARGS; combined with2>/dev/nullit can silently blank the live pane.This was raised on the previous commit and is still unaddressed.
--argjson show_args "${LIVE_SHOW_TOOL_ARGS:-false}"requires a strict JSON literal, so any non-canonical value reaching this point —yes,on,True,1, a trailing space, or even an accidental quoted"true"from.ralphrc— makes jq abort withargjson takes JSON as argument. Because jq's stderr is sent to/dev/null, the live pane goes empty with no diagnostic whiletee "$output_file"keeps writing the raw stream, so the failure mode looks like "live mode broke" rather than "config typo".Two small fixes are worth applying together: normalize the value to a strict JSON boolean and route jq's stderr to
$stderr_fileso a future misconfiguration is at least visible.🛡️ Suggested normalization + stderr capture
+ # Normalize LIVE_SHOW_TOOL_ARGS to a strict JSON boolean for --argjson. + # jq aborts on non-JSON values (yes/on/1/True/quoted "true"); anything + # other than a recognized truthy token is treated as false. + local show_args_json="false" + case "$(printf '%s' "${LIVE_SHOW_TOOL_ARGS:-false}" | tr -d '[:space:]"' | tr '[:upper:]' '[:lower:]')" in + true|1|yes|on) show_args_json="true" ;; + esac + portable_timeout ${timeout_seconds}s "${LIVE_CMD_ARGS[@]}" \ - < /dev/null 2>"$stderr_file" | tee "$output_file" | jq --unbuffered -j --argjson show_args "${LIVE_SHOW_TOOL_ARGS:-false}" "$jq_filter" 2>/dev/null | tee "$LIVE_LOG_FILE" + < /dev/null 2>"$stderr_file" \ + | tee "$output_file" \ + | jq --unbuffered -j --argjson show_args "$show_args_json" "$jq_filter" 2>>"$stderr_file" \ + | tee "$LIVE_LOG_FILE"As per coding guidelines, "Use POSIX-compatible bash features (e.g., tr for case conversion instead of ${,,}) to support bash 3.x environments".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ralph_loop.sh` around lines 1607 - 1609, The jq invocation using --argjson show_args "${LIVE_SHOW_TOOL_ARGS:-false}" can fail on non-strict JSON values and its stderr is discarded; update the pipeline around the portable_timeout invocation so LIVE_SHOW_TOOL_ARGS is normalized to a strict JSON boolean (e.g., map common truthy strings like yes/on/true/1 to true and everything else to false using POSIX-safe tools such as tr and a case test) and pass that normalized literal to jq's --argjson, and also redirect jq's stderr to "$stderr_file" instead of /dev/null so failures from jq (invoked in the command that writes to "$output_file" and "$LIVE_LOG_FILE") are captured in stderr_file for diagnostics.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ralph_loop.sh`:
- Around line 2527-2530: The CLI flag handler for --show-tool-args sets
LIVE_SHOW_TOOL_ARGS but doesn't preserve/re-apply it after load_ralphrc; mimic
the existing --backup pattern by (1) when parsing the flag set a sentinel like
_cli_LIVE_SHOW_TOOL_ARGS=true in the same block that currently sets
LIVE_SHOW_TOOL_ARGS, (2) after load_ralphrc in main re-apply/override
LIVE_SHOW_TOOL_ARGS if _cli_LIVE_SHOW_TOOL_ARGS is set (same place and style as
the _cli_ENABLE_BACKUP re-application), and (3) ensure any existing
_env_LIVE_SHOW_TOOL_ARGS restore logic remains unchanged so exported env
variables still behave the same.
---
Duplicate comments:
In `@ralph_loop.sh`:
- Around line 1607-1609: The jq invocation using --argjson show_args
"${LIVE_SHOW_TOOL_ARGS:-false}" can fail on non-strict JSON values and its
stderr is discarded; update the pipeline around the portable_timeout invocation
so LIVE_SHOW_TOOL_ARGS is normalized to a strict JSON boolean (e.g., map common
truthy strings like yes/on/true/1 to true and everything else to false using
POSIX-safe tools such as tr and a case test) and pass that normalized literal to
jq's --argjson, and also redirect jq's stderr to "$stderr_file" instead of
/dev/null so failures from jq (invoked in the command that writes to
"$output_file" and "$LIVE_LOG_FILE") are captured in stderr_file for
diagnostics.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
The jq filter only showed tool names (⚡ [Bash]) with no arguments, making live mode appear empty when Claude does mostly tool calls. Now shows two levels of feedback: - ⚙ Bash... (immediate, from stream_event content_block_start) - ⚡ [Bash] actual command here (full args, from assistant message) Also removes stdbuf dependency check since stdbuf was removed in prior commit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3ca05d0 to
b40690b
Compare
Summary
Improves Ralph's
--live/--monitorstreaming output so the operator can actually see what Claude is doing during a loop iteration, not just that a tool was invoked.Before this change, the streaming
jqfilter only had access tostream_event content_block_startevents, which carry the tool name but no arguments (the input is delivered later as deltas). The result on screen was a blank⚡ [Bash]marker with no command, file path, or pattern — useful for confirming activity but not for following along.This PR keeps the immediate "tool starting" indicator and adds a richer second pass driven by full
assistantmessages, which arrive at the end of each turn with complete tool inputs.What changes in the live feed
⚙ Bash...— confirms a tool just started, with no args yet.⚡ [Bash] git status --short— the full first-line summary, truncated to 120 chars.Bash→ first line ofcommand, capped at 120 charsRead/Write/Edit→file_pathGlob/Grep→patternAgent→description🚀 Agent:and⚙markers for a less spread-out feed.Files
ralph_loop.sh— single-file change to thejqfilter inside the live streaming pipeline. +38 / -3.Why it's safe
emptyfor unknown tool types, so future tools won't break the filter.stream_eventbranch is preserved, so the immediate "tool started" indicator still fires even before the assistant message arrives.Test plan
ralph --monitoragainst a project that triggers a mix ofBash,Read,Edit, andGrepcalls — confirm each call shows a meaningful summary lineralph --live(without tmux) shows the same enriched feedBashcommand longer than 120 chars is truncated, not wrappedBashheredoc shows only the first line in the live feedAgent) invocations show the description stringnpm teststill passesSummary by CodeRabbit
New Features
Improvements