Skip to content

Background <task-notification> entries are rendered as User messages #99

Description

@willirath

When Claude Code runs an agent or shell command in the background (run_in_background=true), the eventual completion arrives in the JSONL as a type: user entry whose message.content is a string beginning with <task-notification> — not the usual list of tool_result content blocks. The transcript renderer treats these as ordinary user prompts (blue "User" panel), which makes long sessions look like the human kept typing system-generated XML at random intervals.

In a recent session of mine this affected 7 entries: 1 background Agent completion, 3 Monitor events, and 3 background Bash completions.

Minimal repro JSONL (4 lines — last entry is the bug):

{"type":"assistant","timestamp":"2026-01-01T10:00:00.000Z","message":{"role":"assistant","content":[{"type":"tool_use","id":"toolu_AAA","name":"Bash","input":{"command":"sleep 30","run_in_background":true,"description":"Long task"}}]}}
{"type":"user","timestamp":"2026-01-01T10:00:00.500Z","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_AAA","content":"Async bash launched. id=bash_AAA"}]}}
{"type":"assistant","timestamp":"2026-01-01T10:00:01.000Z","message":{"role":"assistant","content":[{"type":"text","text":"Started; continuing while it runs."}]}}
{"type":"user","timestamp":"2026-01-01T10:00:31.000Z","message":{"role":"user","content":"<task-notification>\n<task-id>bash_AAA</task-id>\n<tool-use-id>toolu_AAA</tool-use-id>\n<status>completed</status>\n<summary>Background command \"Long task\" completed (exit code 0)</summary>\n</task-notification>"}}

Save as repro.jsonl and run:

claude-code-transcripts json repro.jsonl -o /tmp/out

Observed: the 4th entry renders as

<div class="message user" id="msg-..."><span class="role-label">User</span> ...
  <p><task-notification> ... </task-notification></p>

i.e. a normal blue user-prompt bubble.

Expected: classified as a system / tool-reply panel (e.g. orange tool-reply), since the human did not author it. Ideally the renderer would parse out <status> and <summary> (and <result> when present) for a compact display.

Suggested detection: any type: "user" entry where message.content is a string starting with <task-notification>. (These are also distinguishable by the absence of a tool_result content block and the presence of an <output-file> or <task-id> element inside.)

Environment: claude-code-transcripts (current uvx install), Claude Code generating the JSONL.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions