Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions claude_code_log/html/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
format_askuserquestion_input,
format_bash_input,
format_edit_input,
format_grep_input,
format_exitplanmode_input,
format_multiedit_input,
format_read_input,
Expand Down Expand Up @@ -105,6 +106,7 @@
"format_askuserquestion_input",
"format_bash_input",
"format_edit_input",
"format_grep_input",
"format_exitplanmode_input",
"format_multiedit_input",
"format_read_input",
Expand Down
10 changes: 10 additions & 0 deletions claude_code_log/html/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
EditInput,
ExitPlanModeInput,
GlobInput,
GrepInput,
MultiEditInput,
ReadInput,
TaskInput,
Expand Down Expand Up @@ -92,6 +93,7 @@
format_edit_input,
format_edit_output,
format_exitplanmode_input,
format_grep_input,
format_exitplanmode_output,
format_multiedit_input,
format_read_input,
Expand Down Expand Up @@ -310,6 +312,10 @@ def format_ExitPlanModeInput(
"""Format → empty string (no content)."""
return format_exitplanmode_input(input)

def format_GrepInput(self, input: GrepInput, _: TemplateMessage) -> str:
"""Format → pattern + params (path, glob, type, mode)."""
return format_grep_input(input)

def format_WebSearchInput(self, input: WebSearchInput, _: TemplateMessage) -> str:
"""Format → search query display."""
return format_websearch_input(input)
Expand Down Expand Up @@ -445,6 +451,10 @@ def title_GlobInput(self, input: GlobInput, message: TemplateMessage) -> str:
summary = f"{summary} in {input.path}"
return self._tool_title(message, "🔍", summary)

def title_GrepInput(self, input: GrepInput, message: TemplateMessage) -> str:
"""Title → '🔎 Grep `pattern`'."""
return self._tool_title(message, "🔎", input.pattern)

def title_BashInput(self, input: BashInput, message: TemplateMessage) -> str:
"""Title → '💻 Bash <description>'."""
return self._tool_title(message, "💻", input.description)
Expand Down
29 changes: 29 additions & 0 deletions claude_code_log/html/tool_formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
EditOutput,
ExitPlanModeInput,
ExitPlanModeOutput,
GrepInput,
MultiEditInput,
ReadInput,
ReadOutput,
Expand Down Expand Up @@ -268,6 +269,33 @@ def format_websearch_output(output: WebSearchOutput) -> str:
return render_markdown_collapsible(markdown_content, "websearch-results")


# -- Grep Tool ----------------------------------------------------------------


def format_grep_input(grep_input: GrepInput) -> str:
"""Format Grep tool use content showing search parameters.

Args:
grep_input: Typed GrepInput with pattern, path, glob, type, etc.

Each field is shown on its own line with a consistent label: value format.
"""
html_parts = ["<div class='grep-tool-content'>"]
html_parts.append(f"<div class='grep-tool-field'><span class='grep-tool-label'>pattern:</span> <code>{escape_html(grep_input.pattern)}</code></div>")
if grep_input.path:
html_parts.append(f"<div class='grep-tool-field'><span class='grep-tool-label'>path:</span> <code>{escape_html(grep_input.path)}</code></div>")
if grep_input.glob:
html_parts.append(f"<div class='grep-tool-field'><span class='grep-tool-label'>glob:</span> <code>{escape_html(grep_input.glob)}</code></div>")
if grep_input.type:
html_parts.append(f"<div class='grep-tool-field'><span class='grep-tool-label'>type:</span> <code>{escape_html(grep_input.type)}</code></div>")
if grep_input.output_mode:
html_parts.append(f"<div class='grep-tool-field'><span class='grep-tool-label'>mode:</span> <code>{escape_html(grep_input.output_mode)}</code></div>")
if grep_input.multiline:
html_parts.append(f"<div class='grep-tool-field'><span class='grep-tool-label'>multiline:</span> <code>true</code></div>")
Comment on lines +283 to +294
Copy link
Copy Markdown

@coderabbitai coderabbitai bot Mar 12, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Render the full GrepInput, not just this hand-picked subset.

GrepInput in claude_code_log/models.py (Lines 782-797) also carries head_limit, offset, and extra allowed grep flags, but this formatter drops all of them. Because HtmlRenderer.format_GrepInput() now routes Grep rendering here, those inputs disappear from the transcript entirely, and the if grep_input.multiline: check also hides an explicit False. Please derive the rendered rows from the actual provided fields so the HTML stays faithful to the tool invocation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@claude_code_log/html/tool_formatters.py` around lines 283 - 294, The current
formatter in tool_formatters.py (inside format_GrepInput / the Grep HTML
rendering) only prints a hand-picked subset of GrepInput fields and hides
explicit False values; update the formatter to render all actual GrepInput
attributes (including head_limit, offset and any extra grep flags defined on
GrepInput in claude_code_log/models.py) by iterating the model's fields (e.g.,
dataclasses.fields or vars(grep_input)/asdict(grep_input)) and emitting a row
for each key/value where None is omitted but booleans are rendered as true/false
explicitly; ensure values are run through escape_html and preserve the existing
label/value HTML structure so the HTML accurately reflects the real tool
invocation.

Copy link
Copy Markdown
Owner

@daaain daaain Mar 18, 2026

Choose a reason for hiding this comment

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

Hey @zhouxuan009, thanks a lot for this PR! Can you please check if this comment from Coderabbit is true? Also, please make sure that linting and tests pass.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for pointing it out. I will take a look.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

html_parts.append("</div>")
return "".join(html_parts)


# -- TodoWrite Tool -----------------------------------------------------------


Expand Down Expand Up @@ -832,6 +860,7 @@ def format_tool_result_content_raw(tool_result: ToolResultContent) -> str:
"format_edit_input",
"format_multiedit_input",
"format_bash_input",
"format_grep_input",
"format_task_input",
"format_websearch_input",
"format_webfetch_input",
Expand Down
Loading