Skip to content

Support writing to stdout (-o - / /dev/stdout): currently hangs, and progress goes to stdout #223

Description

@samestep

Summary

Piping output to stdout doesn't work, for two independent reasons:

  1. -o /dev/stdout hangs forever. Confirmed: the command never produces output and has to be killed.
  2. Progress/status text is written to stdout, not stderr, so even if (1) were fixed, the content stream would be polluted with lines like Processing …, Loading … from cache, and Successfully converted ….

Together these block the natural workflow of claude-code-log … -o - | sed 's/^/> /' | <clipboard>, forcing a write-to-temp-file-then-cat detour.

Repro (v1.4.0)

# (1) hangs
claude-code-log session.jsonl -f markdown -o /dev/stdout   # never returns

# (2) status text on stdout
claude-code-log session.jsonl -f markdown -o out.md         # "Processing…"/"Successfully…" go to stdout

Cause

  1. Hang: before writing, the code runs a staleness check renderer.is_outdated(output_path) (converter.py:1728). For /dev/stdout the path "exists", so is_outdated opens it read-only to sniff the version marker (markdown/renderer.py:2174). When stdout is a pipe, /dev/stdout resolves to the pipe's write end; opening it O_RDONLY and calling readline() blocks waiting for bytes that never come → deadlock. (Fixing the "existing -o file skips regeneration" issue — bypassing the staleness skip for explicit -o — would also resolve this, since is_outdated would no longer be called.) A Path.is_file() guard in is_outdated would harden it regardless.
  2. stdout noise: status output uses bare print(...) (converter.py:252, :270, etc.) and click.echo(...) without err=True (cli.py:1128, the per-project summaries, etc.). Only warnings pass err=True.

Suggested fix

  • Treat -o - (and /dev/stdout) as "stream to stdout, always regenerate, don't consult or write cache, don't open a browser."
  • Route all progress/status/summary output to stderr (sweep click.echo(..., err=True) and replace the bare prints with logging/stderr), so stdout carries only the rendered document.

Investigation and write-up by Claude (Claude Code).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions